summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes14
-rw-r--r--.gitignore46
-rw-r--r--.nuget/NuGet.Config6
-rw-r--r--.nuget/NuGet.exebin0 -> 692736 bytes
-rw-r--r--.nuget/NuGet.targets133
-rw-r--r--.nuget/packages.config4
-rw-r--r--.nuspec/Xamarin.Forms.Debug.targets80
-rw-r--r--.nuspec/Xamarin.Forms.Maps.nuspec135
-rw-r--r--.nuspec/Xamarin.Forms.Maps.props11
-rw-r--r--.nuspec/Xamarin.Forms.Maps.targets22
-rw-r--r--.nuspec/Xamarin.Forms.nuspec240
-rw-r--r--.nuspec/Xamarin.Forms.targets69
-rw-r--r--AndroidNative/FormsViewGroup/.classpath9
-rw-r--r--AndroidNative/FormsViewGroup/.project33
-rw-r--r--AndroidNative/FormsViewGroup/.settings/org.eclipse.jdt.core.prefs4
-rw-r--r--AndroidNative/FormsViewGroup/AndroidManifest.xml17
-rw-r--r--AndroidNative/FormsViewGroup/libs/android-support-v4.jarbin0 -> 758727 bytes
-rw-r--r--AndroidNative/FormsViewGroup/proguard-project.txt20
-rw-r--r--AndroidNative/FormsViewGroup/project.properties15
-rw-r--r--AndroidNative/FormsViewGroup/res/drawable-hdpi/ic_launcher.pngbin0 -> 9397 bytes
-rw-r--r--AndroidNative/FormsViewGroup/res/drawable-mdpi/ic_launcher.pngbin0 -> 5237 bytes
-rw-r--r--AndroidNative/FormsViewGroup/res/drawable-xhdpi/ic_launcher.pngbin0 -> 14383 bytes
-rw-r--r--AndroidNative/FormsViewGroup/res/values-v11/styles.xml11
-rw-r--r--AndroidNative/FormsViewGroup/res/values-v14/styles.xml12
-rw-r--r--AndroidNative/FormsViewGroup/res/values/strings.xml5
-rw-r--r--AndroidNative/FormsViewGroup/res/values/styles.xml20
-rw-r--r--AndroidNative/FormsViewGroup/src/com/xamarin/forms/platform/android/FormsViewGroup.java96
-rw-r--r--ICSharpCode.Decompiler/Ast/Annotations.cs52
-rw-r--r--ICSharpCode.Decompiler/Ast/AstBuilder.cs1690
-rw-r--r--ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs1220
-rw-r--r--ICSharpCode.Decompiler/Ast/CommentStatement.cs69
-rw-r--r--ICSharpCode.Decompiler/Ast/DecompilerContext.cs71
-rw-r--r--ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs86
-rw-r--r--ICSharpCode.Decompiler/Ast/NameVariables.cs347
-rw-r--r--ICSharpCode.Decompiler/Ast/TextTokenWriter.cs369
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/AddCheckedBlocks.cs368
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/CombineQueryExpressions.cs179
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs111
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs183
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/CustomPatterns.cs109
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs58
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs368
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs502
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs875
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/FlattenSwitchBlocks.cs27
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/IntroduceExtensionMethods.cs66
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/IntroduceQueryExpressions.cs295
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs106
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs359
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs1123
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs164
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs356
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs65
-rw-r--r--ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs528
-rw-r--r--ICSharpCode.Decompiler/CecilExtensions.cs374
-rw-r--r--ICSharpCode.Decompiler/CodeMappings.cs57
-rw-r--r--ICSharpCode.Decompiler/DecompilerException.cs42
-rw-r--r--ICSharpCode.Decompiler/DecompilerSettings.cs356
-rw-r--r--ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs447
-rw-r--r--ICSharpCode.Decompiler/Disassembler/ILStructure.cs228
-rw-r--r--ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs239
-rw-r--r--ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs1168
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/ControlFlowEdge.cs78
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraph.cs191
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraphBuilder.cs439
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs305
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs241
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/OpCodeInfo.cs312
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/SimplifyByRefCalls.cs174
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/SsaBlock.cs60
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/SsaForm.cs162
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs257
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/SsaInstruction.cs191
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/SsaOptimization.cs138
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/SsaVariable.cs91
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/TransformToSsa.cs254
-rw-r--r--ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj159
-rw-r--r--ICSharpCode.Decompiler/ICSharpCode.Decompiler.sln17
-rw-r--r--ICSharpCode.Decompiler/ILAst/AsyncDecompiler.cs704
-rw-r--r--ICSharpCode.Decompiler/ILAst/DefaultDictionary.cs128
-rw-r--r--ICSharpCode.Decompiler/ILAst/GotoRemoval.cs319
-rw-r--r--ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs839
-rw-r--r--ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs988
-rw-r--r--ICSharpCode.Decompiler/ILAst/ILAstTypes.cs601
-rw-r--r--ICSharpCode.Decompiler/ILAst/ILCodes.cs490
-rw-r--r--ICSharpCode.Decompiler/ILAst/ILInlining.cs524
-rw-r--r--ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs543
-rw-r--r--ICSharpCode.Decompiler/ILAst/LiftedOperators.cs528
-rw-r--r--ICSharpCode.Decompiler/ILAst/LoopsAndConditions.cs443
-rw-r--r--ICSharpCode.Decompiler/ILAst/PatternMatching.cs177
-rw-r--r--ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs1103
-rw-r--r--ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs376
-rw-r--r--ICSharpCode.Decompiler/ILAst/StateRange.cs312
-rw-r--r--ICSharpCode.Decompiler/ILAst/SymbolicExecution.cs157
-rw-r--r--ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs1294
-rw-r--r--ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs635
-rw-r--r--ICSharpCode.Decompiler/ITextOutput.cs62
-rw-r--r--ICSharpCode.Decompiler/PlainTextOutput.cs122
-rw-r--r--ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs27
-rw-r--r--ICSharpCode.Decompiler/ReferenceResolvingException.cs68
-rw-r--r--ICSharpCode.Decompiler/Tests/Async.cs155
-rw-r--r--ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il59
-rw-r--r--ICSharpCode.Decompiler/Tests/CallOverloadedMethod.cs52
-rw-r--r--ICSharpCode.Decompiler/Tests/CheckedUnchecked.cs117
-rw-r--r--ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs133
-rw-r--r--ICSharpCode.Decompiler/Tests/ControlFlow.cs97
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs41
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs30
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomAttributes/S_AssemblyCustomAttribute.cs21
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs508
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs79
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs88
-rw-r--r--ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs89
-rw-r--r--ICSharpCode.Decompiler/Tests/DelegateConstruction.cs205
-rw-r--r--ICSharpCode.Decompiler/Tests/DoubleConstants.cs28
-rw-r--r--ICSharpCode.Decompiler/Tests/ExceptionHandling.cs128
-rw-r--r--ICSharpCode.Decompiler/Tests/ExpressionTrees.cs370
-rw-r--r--ICSharpCode.Decompiler/Tests/Generics.cs165
-rw-r--r--ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs110
-rw-r--r--ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs38
-rw-r--r--ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj137
-rw-r--r--ICSharpCode.Decompiler/Tests/IL/ILTests.cs51
-rw-r--r--ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.Output.cs53
-rw-r--r--ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.il140
-rw-r--r--ICSharpCode.Decompiler/Tests/IL/StackTests.il132
-rw-r--r--ICSharpCode.Decompiler/Tests/IncrementDecrement.cs254
-rw-r--r--ICSharpCode.Decompiler/Tests/InitializerTests.cs885
-rw-r--r--ICSharpCode.Decompiler/Tests/LiftedOperators.cs830
-rw-r--r--ICSharpCode.Decompiler/Tests/Lock.cs38
-rw-r--r--ICSharpCode.Decompiler/Tests/Loops.cs74
-rw-r--r--ICSharpCode.Decompiler/Tests/MultidimensionalArray.cs58
-rw-r--r--ICSharpCode.Decompiler/Tests/PInvoke.cs96
-rw-r--r--ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs80
-rw-r--r--ICSharpCode.Decompiler/Tests/QueryExpressions.cs188
-rw-r--r--ICSharpCode.Decompiler/Tests/Switch.cs89
-rw-r--r--ICSharpCode.Decompiler/Tests/TestRunner.cs198
-rw-r--r--ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs153
-rw-r--r--ICSharpCode.Decompiler/Tests/Types/EnumTests.cs18
-rw-r--r--ICSharpCode.Decompiler/Tests/Types/S_EnumSamples.cs129
-rw-r--r--ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs17
-rw-r--r--ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs1138
-rw-r--r--ICSharpCode.Decompiler/Tests/Types/TypeTests.cs18
-rw-r--r--ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs41
-rw-r--r--ICSharpCode.Decompiler/Tests/UnsafeCode.cs145
-rw-r--r--ICSharpCode.Decompiler/Tests/ValueTypes.cs188
-rw-r--r--ICSharpCode.Decompiler/Tests/YieldReturn.cs148
-rw-r--r--ICSharpCode.Decompiler/Tests/packages.config6
-rw-r--r--ICSharpCode.Decompiler/TextOutputWriter.cs55
-rw-r--r--ICSharpCode.Decompiler/packages.config5
-rw-r--r--Makefile40
-rw-r--r--README.md1
-rw-r--r--Stubs/Xamarin.Forms.Platform.Android/Properties/AssemblyInfo.cs31
-rw-r--r--Stubs/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android (Forwarders).csproj94
-rw-r--r--Stubs/Xamarin.Forms.Platform.Android/packages.config5
-rw-r--r--Stubs/Xamarin.Forms.Platform.WP8/Properties/AssemblyInfo.cs30
-rw-r--r--Stubs/Xamarin.Forms.Platform.WP8/Xamarin.Forms.Platform.WP8 (Forwarders).csproj119
-rw-r--r--Stubs/Xamarin.Forms.Platform.cs141
-rw-r--r--Stubs/Xamarin.Forms.Platform.iOS.Classic/Properties/AssemblyInfo.cs37
-rw-r--r--Stubs/Xamarin.Forms.Platform.iOS.Classic/Xamarin.Forms.Platform.iOS.Classic (Forwarders).csproj60
-rw-r--r--Stubs/Xamarin.Forms.Platform.iOS/Properties/AssemblyInfo.cs37
-rw-r--r--Stubs/Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS (Forwarders).csproj60
-rw-r--r--Xamarin.Forms.Android.UITests/BaseTestFixture.cs108
-rw-r--r--Xamarin.Forms.Android.UITests/Makefile15
-rw-r--r--Xamarin.Forms.Android.UITests/PlatformHelpers.cs132
-rw-r--r--Xamarin.Forms.Android.UITests/PlatformQueries.cs111
-rw-r--r--Xamarin.Forms.Android.UITests/Properties/AssemblyInfo.cs36
-rw-r--r--Xamarin.Forms.Android.UITests/Xamarin.Forms.Android.UITests.csproj85
-rw-r--r--Xamarin.Forms.Android.UITests/packages.config5
-rw-r--r--Xamarin.Forms.Android.UITests/testcloudupload.bat1
-rw-r--r--Xamarin.Forms.Build.Tasks/CreateObjectVisitor.cs544
-rw-r--r--Xamarin.Forms.Build.Tasks/DebugXamlCTask.cs152
-rw-r--r--Xamarin.Forms.Build.Tasks/ExpandMarkupsVisitor.cs207
-rw-r--r--Xamarin.Forms.Build.Tasks/FieldReferenceExtensions.cs22
-rw-r--r--Xamarin.Forms.Build.Tasks/FixedCreateCSharpManifestResourceName.cs27
-rw-r--r--Xamarin.Forms.Build.Tasks/ILContext.cs37
-rw-r--r--Xamarin.Forms.Build.Tasks/ILProcessorExtensions.cs14
-rw-r--r--Xamarin.Forms.Build.Tasks/ILRootNode.cs15
-rw-r--r--Xamarin.Forms.Build.Tasks/MethodDefinitionExtensions.cs38
-rw-r--r--Xamarin.Forms.Build.Tasks/MethodReferenceExtensions.cs63
-rw-r--r--Xamarin.Forms.Build.Tasks/NodeILExtensions.cs480
-rw-r--r--Xamarin.Forms.Build.Tasks/Properties/AssemblyInfo.cs30
-rw-r--r--Xamarin.Forms.Build.Tasks/PropertyDefinitionExtensions.cs33
-rw-r--r--Xamarin.Forms.Build.Tasks/SetFieldVisitor.cs72
-rw-r--r--Xamarin.Forms.Build.Tasks/SetNamescopesAndRegisterNamesVisitor.cs142
-rw-r--r--Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs681
-rw-r--r--Xamarin.Forms.Build.Tasks/SetResourcesVisitor.cs141
-rw-r--r--Xamarin.Forms.Build.Tasks/TypeDefinitionExtensions.cs66
-rw-r--r--Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs222
-rw-r--r--Xamarin.Forms.Build.Tasks/Xamarin.Forms.Build.Tasks.csproj120
-rw-r--r--Xamarin.Forms.Build.Tasks/XamlCAssemblyResolver.cs15
-rw-r--r--Xamarin.Forms.Build.Tasks/XamlCTask.cs417
-rw-r--r--Xamarin.Forms.Build.Tasks/XamlGTask.cs261
-rw-r--r--Xamarin.Forms.Build.Tasks/XmlTypeExtensions.cs96
-rw-r--r--Xamarin.Forms.Build.Tasks/packages.config4
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Activity1.cs412
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Assets/WebImages/XamarinLogo.pngbin0 -> 6990 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Assets/default.css2
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Assets/local.html10
-rw-r--r--Xamarin.Forms.ControlGallery.Android/BrokenNativeControl.cs60
-rw-r--r--Xamarin.Forms.ControlGallery.Android/CustomRenderers.cs344
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Properties/AndroidManifest.xml22
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Properties/AssemblyInfo.cs37
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/AboutResources.txt44
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/CustomSelector.xml18
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/CustomSelector2.xml18
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/FlowerBuds.jpgbin0 -> 5008 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/Fruits.jpgbin0 -> 10315 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/Icon.pngbin0 -> 2574 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/Legumes.jpgbin0 -> 6210 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/Vegetables.jpgbin0 -> 5349 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/bank.pngbin0 -> 1444 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/calculator.pngbin0 -> 1558 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/coffee.pngbin0 -> 490 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/cover1.jpgbin0 -> 40625 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/cover1small.jpgbin0 -> 24277 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/crimson.jpgbin0 -> 79109 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/crimsonsmall.jpgbin0 -> 5028 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/menuIcon.pngbin0 -> 129 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/oasis.jpgbin0 -> 27478 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/oasissmall.jpgbin0 -> 3084 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/photo.jpgbin0 -> 114121 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/seth.pngbin0 -> 4696 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/drawable/toolbar_close.pngbin0 -> 463 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/layout/NativeAndroidCell.axml35
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/layout/NativeAndroidListViewCell.axml35
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/layout/Tabbar.axml11
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/layout/Toolbar.axml8
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/values/Colors.xml5
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Resources/values/styles.xml38
-rw-r--r--Xamarin.Forms.ControlGallery.Android/Xamarin.Forms.ControlGallery.Android.csproj260
-rw-r--r--Xamarin.Forms.ControlGallery.Android/app.config11
-rw-r--r--Xamarin.Forms.ControlGallery.Android/packages.config14
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/App.xaml20
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/App.xaml.cs234
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/Assets/AlignmentGrid.pngbin0 -> 9042 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/Assets/ApplicationIcon.pngbin0 -> 3392 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/FlipCycleTileLarge.pngbin0 -> 9930 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/FlipCycleTileMedium.pngbin0 -> 9070 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/FlipCycleTileSmall.pngbin0 -> 3674 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/IconicTileMediumLarge.pngbin0 -> 4937 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/IconicTileSmall.pngbin0 -> 3724 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/BrokenNativeControl.cs56
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/LocalizedStrings.cs14
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/MainPage.xaml63
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/MainPage.xaml.cs143
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/Properties/AppManifest.xml6
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/Properties/AssemblyInfo.cs37
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/Properties/WMAppManifest.xml46
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/Resources/AppResources.Designer.cs127
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/Resources/AppResources.resx137
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/WebImages/XamarinLogo.pngbin0 -> 6990 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/Xamarin.Forms.ControlGallery.WP8.csproj258
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/app.config11
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/bank.pngbin0 -> 1444 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/cover1.jpgbin0 -> 40625 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/cover1small.jpgbin0 -> 24277 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/crimson.jpgbin0 -> 79109 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/crimsonsmall.jpgbin0 -> 5028 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/default.css2
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/local.html10
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/menuIcon.pngbin0 -> 129 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/oasis.jpgbin0 -> 27246 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/oasissmall.jpgbin0 -> 3084 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/packages.config4
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/photo.jpgbin0 -> 114121 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/seth.pngbin0 -> 4696 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/toolbar_close.pngbin0 -> 463 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/App.xaml7
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/App.xaml.cs67
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/Assets/Logo.scale-100.pngbin0 -> 801 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/Assets/SmallLogo.scale-100.pngbin0 -> 329 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/Assets/SplashScreen.scale-100.pngbin0 -> 2146 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/Assets/StoreLogo.scale-100.pngbin0 -> 429 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/BrokenNativeControl.cs64
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/MainPage.xaml11
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/MainPage.xaml.cs100
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/Package.appxmanifest29
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/Properties/AssemblyInfo.cs29
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/StringProvider.cs15
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows.csproj207
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows_TemporaryKey.pfxbin0 -> 2450 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/toolbar_close.pngbin0 -> 463 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/App.xaml7
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/App.xaml.cs134
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/Assets/Logo.scale-240.pngbin0 -> 2516 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/Assets/SmallLogo.scale-240.pngbin0 -> 753 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/Assets/SplashScreen.scale-240.pngbin0 -> 14715 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/Assets/Square71x71Logo.scale-240.pngbin0 -> 1122 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/Assets/StoreLogo.scale-240.pngbin0 -> 2200 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/Assets/WideLogo.scale-240.pngbin0 -> 4530 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/BrokenNativeControl.cs65
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/MainPage.xaml11
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/MainPage.xaml.cs108
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/Package.appxmanifest34
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/Properties/AssemblyInfo.cs29
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/StringProvider.cs15
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/Xamarin.Forms.ControlGallery.WindowsPhone.csproj187
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/app.config11
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/toolbar_close.pngbin0 -> 463 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/App.xaml8
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/App.xaml.cs107
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/Logo.scale-100.pngbin0 -> 801 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/SmallLogo.scale-100.pngbin0 -> 222 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/SplashScreen.scale-100.pngbin0 -> 2146 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/StoreLogo.scale-100.pngbin0 -> 429 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/WideLogo.scale-100.pngbin0 -> 2150 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/BrokenNativeControl.cs67
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/MainPage.xaml10
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/MainPage.xaml.cs109
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/Package.appxmanifest27
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/Properties/AssemblyInfo.cs29
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/Properties/default.rd.xml8
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj192
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal_TemporaryKey.pfxbin0 -> 2454 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/project.json16
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/toolbar_close.pngbin0 -> 463 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs276
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/BrokenNativeControl.cs34
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/CustomRenderers.cs415
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Default-568h@2x.pngbin0 -> 750043 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Default-667h@2x.pngbin0 -> 1089613 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Default@2x.pngbin0 -> 4600 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Entitlements.plist5
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Goobuntu-icon.pngbin0 -> 29591 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Images/FlowerBuds.jpgbin0 -> 2073 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Images/FlowerBuds@2x.jpgbin0 -> 5008 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Images/Fruits.jpgbin0 -> 6484 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Images/Fruits@2x.jpgbin0 -> 10315 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Images/Legumes.jpgbin0 -> 2422 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Images/Legumes@2x.jpgbin0 -> 6210 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Images/Vegetables.jpgbin0 -> 2161 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Images/Vegetables@2x.jpgbin0 -> 5349 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Info.plist106
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Intranet-icon.pngbin0 -> 210884 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Main.cs30
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Properties/AssemblyInfo.cs36
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/WebImages/XamarinLogo.pngbin0 -> 6990 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Xamarin.Forms.ControlGallery.iOS.Classic.csproj218
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/Xamarin.Forms.ControlGallery.iOS.csproj246
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/app.config11
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/bank.pngbin0 -> 1444 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/bank@2x.pngbin0 -> 1746 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/calculator.pngbin0 -> 1558 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/calculator@2x.pngbin0 -> 2134 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/coffee@2x.pngbin0 -> 490 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/cover1.jpgbin0 -> 40625 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/cover1small.jpgbin0 -> 24277 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/crimson.jpgbin0 -> 79109 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/crimsonsmall.jpgbin0 -> 5028 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/default.css2
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/local.html10
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/menuIcon.pngbin0 -> 3036 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/menuIcon@2x.pngbin0 -> 129 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/move_slider_one_right_ios6_iphone.base64345
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/move_slider_three_right_ios6_iphone.base64284
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/move_slider_two_right_ios6_iphone.base6444
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/oasis.jpgbin0 -> 27478 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/oasissmall.jpgbin0 -> 3084 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/packages.config5
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/photo.jpgbin0 -> 114121 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/seth.pngbin0 -> 4130 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/seth@2x.pngbin0 -> 4696 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/settings@2x.pngbin0 -> 837 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.iOS/toolbar_close.pngbin0 -> 463 bytes
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/AddingMultipleItemsListView.cs443
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/AppBarIconColors.cs52
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla21368.cs90
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla21501.cs47
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla21780.cs19
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla22229.xaml11
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla22229.xaml.cs51
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla22401.cs114
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla24574.cs50
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla24769.cs80
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla25662.cs35
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla25979.cs133
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26032.xaml51
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26032.xaml.cs75
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26171.cs98
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26233.cs56
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26501.cs150
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26868.cs105
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26993.cs105
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27085.cs36
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27318.xaml23
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27318.xaml.cs22
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27350.cs151
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27378.cs33
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27581.cs29
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27642.cs178
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27698.cs53
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27779.cs83
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28001.cs60
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28240.cs38
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28498.cs78
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28570.cs118
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28575.cs53
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28709.cs94
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28796.cs35
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28939.cs21
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29017.cs82
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29107.xaml249
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29107.xaml.cs22
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29128.cs36
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29158.cs24
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29229.cs29
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29247.cs67
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29257.cs100
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29363.cs48
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29453.cs72
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30317.cs260
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30324.cs97
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30353.cs113
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30651.cs101
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30835.cs207
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30935.cs44
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31029.cs126
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31114.cs421
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31145.cs67
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31255.cs88
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31330.cs163
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31333.cs256
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31366.cs85
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31395.cs54
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31602.cs130
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31964.cs116
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31967.xaml18
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31967.xaml.cs47
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32034.cs31
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32040.cs59
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32148.cs240
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32230.cs59
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32447.xaml160
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32447.xaml.cs28
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32462.cs57
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32487.cs50
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32615.cs70
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32691.cs60
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32776.cs20
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32801.cs92
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32842.xaml42
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32842.xaml.cs46
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32847.cs119
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32898.cs74
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32902.cs131
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33268.cs143
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33450.cs47
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33578.cs99
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33612.cs159
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33714.cs86
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33870.cs71
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33890.cs38
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34007.cs91
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34061.cs76
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34072.cs54
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34561.cs89
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34632.cs79
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34720.cs352
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34727.cs30
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34912.cs106
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35078.cs34
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35127.cs22
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35157.cs58
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35294.cs45
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35472.cs88
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35477.cs49
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35490.cs39
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35733.cs58
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35738.cs41
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36009.cs56
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36014.cs16
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36171.cs107
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36393.cs43
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36479.cs43
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36559.cs54
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36649.cs29
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36681.cs88
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36788.cs122
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37462.cs88
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37601.cs50
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37625.cs36
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37841.cs153
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37863.cs26
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38105.cs59
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38112.cs98
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38416.xaml27
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38416.xaml.cs48
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38658.cs74
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38827.xaml24
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38827.xaml.cs20
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38978.cs90
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39331.cs71
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39395.cs30
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39461.cs36
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39463.xaml18
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39463.xaml.cs33
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39483.xaml24
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39483.xaml.cs50
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39499.cs134
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39530.cs85
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39624.cs40
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39668.cs51
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/CarouselAsync.cs114
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ComplexListView.cs111
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/DataTemplateGridImageTest.cs55
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/DefaultColorToggleTest.cs146
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/DisposedSharedPages.cs70
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/InputTransparentIssue.cs37
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/IsPasswordToggleTest.cs38
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/IsShowingUserIssue.cs35
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1025.cs24
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1026.cs91
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1028.cs31
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1075.cs85
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1097.cs60
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1146.cs48
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1219.cs19
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1228.cs67
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1236.cs26
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1259.cs112
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1267.cs65
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1305.cs50
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1329.cs46
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1384.cs40
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1400.cs153
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1461.cs286
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1497.xaml27
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1497.xaml.cs20
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1538.cs28
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1545.xaml16
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1545.xaml.cs129
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1546.cs21
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1549.xaml34
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1549.xaml.cs74
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1554.xaml20
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1554.xaml.cs25
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1557.cs34
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1566.cs91
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1567.cs37
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1568.xaml53
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1568.xaml.cs22
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1583.cs20
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1590.cs123
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1593.cs169
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1598.cs80
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1613.cs64
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1618.cs37
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1641.xaml17
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1641.xaml.cs17
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1644.cs74
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653.xaml22
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653.xaml.cs25
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653v2.xaml20
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653v2.xaml.cs23
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1664.cs46
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1680.cs106
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1682.cs30
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1685.cs77
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1691.cs77
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1698.cs29
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1700.cs30
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1703.cs63
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1705.cs38
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1712.xaml6
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1712.xaml.cs20
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1722.cs26
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1723.cs53
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1741.xaml6
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1741.xaml.cs27
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1742.cs55
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1747.xaml9
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1747.xaml.cs65
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1755.cs36
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1758.cs68
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1762.cs273
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1763.cs104
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1766.xaml22
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1766.xaml.cs65
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1769.cs81
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1777.cs66
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue181.cs41
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1851.cs92
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1875.cs105
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1888.cs36
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1891.cs81
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1895.cs80
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1898.xaml20
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1898.xaml.cs47
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1905.cs31
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1914.cs27
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue194.cs72
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue198.cs78
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue206.cs143
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue214.cs36
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2143.cs55
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2191.cs51
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2222.cs49
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue22246_BZ.cs49
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2241.cs58
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2248.cs74
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2259.cs156
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2266.cs162
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2270.cs77
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2272.cs54
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2282.xaml32
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2282.xaml.cs42
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2288.xaml10
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2288.xaml.cs40
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2289.xaml36
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2289.xaml.cs119
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue229.cs29
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2291.cs36
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2292.cs39
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2294.cs60
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2333.cs39
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2339.cs66
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2354.cs116
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2357.xaml21
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2357.xaml.cs418
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2411.cs276
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2414.cs97
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2470.xaml29
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2470.xaml.cs155
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2563.cs41
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2594.cs33
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2597.cs61
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue260.cs41
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2615.cs80
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2628.cs31
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2634.cs333
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue264.cs75
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2659.xaml34
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2659.xaml.cs64
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2775.cs116
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2777.xaml23
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2777.xaml.cs132
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2783.cs36
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2794.cs48
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2809.cs50
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2883.cs125
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2923.cs83
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2927.cs105
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2948.cs232
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2951.xaml48
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2951.xaml.cs140
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2953.cs89
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2954.cs58
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2961.cs290
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2963.cs53
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2964.cs101
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2965.cs152
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2976.cs441
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2981.cs37
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2983.cs30
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2987.cs39
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3086.xaml28
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3086.xaml.cs31
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3276.cs91
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3292.cs83
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3319.xaml42
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3319.xaml.cs264
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue342.cs85
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue416.cs41
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue417.cs110
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue465.cs61
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue488.cs45
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue530.cs66
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue764.cs55
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue773.cs174
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue774.cs77
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue852.cs154
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue886.cs71
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue889.cs140
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue892.cs224
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue935.cs83
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue968.cs52
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue973.cs164
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ListViewViewCellBinding.cs168
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ModalActivityIndicatorTest.cs150
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ModelContentPage.cs24
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/NavPage.cs25
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/NavigationStackTests.cs84
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ScrollViewOutOfBounds.cs59
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/StackLayoutIssue.cs132
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/SwipeBackNavCrash.cs88
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TabbedPageTests.cs64
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TabbedPageWithList.cs71
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TestPages/TestPages.cs223
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems485
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.shproj12
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/_Template.cs35
-rw-r--r--Xamarin.Forms.Controls/App.cs321
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/AppearingGalleryPage.cs129
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/AutomationIDGallery.cs104
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/BehaviorsAndTriggers.xaml37
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/BehaviorsAndTriggers.xaml.cs75
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/CellForceUpdateSizeGalleryPage.cs193
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/LayoutAddPerformance.xaml15
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/LayoutAddPerformance.xaml.cs36
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/ListRefresh.cs115
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/ListScrollTo.cs93
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/ListViewSelectionColor.cs150
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/NavBarTitleTestPage.cs91
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/NestedNativeControlGalleryPage.cs27
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/PanGestureGalleryPage.cs96
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/PinchGestureTestPage.cs91
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/ToolbarItems.cs55
-rw-r--r--Xamarin.Forms.Controls/Controls/Issue3076Button.cs14
-rw-r--r--Xamarin.Forms.Controls/CoreGallery.cs419
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/ActivityIndicatorCoreGalleryPage.cs39
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/ButtonCoreGalleryPage.cs106
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/CoreBoxViewGalleryPage.cs37
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/CoreGalleryPage.cs185
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/DatePickerCoreGalleryPage.cs34
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/EditorCoreGalleryPage.cs51
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/EntryCoreGalleryPage.cs92
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/FrameCoreGalleryPage.cs36
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/ImageCoreGalleryPage.cs56
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/KeyboardCoreGalleryPage.cs49
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/LabelCoreGalleryPage.cs158
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/ListViewCoreGalleryPage.cs268
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/OpenGLViewCoreGalleryPage.cs16
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/PickerCoreGalleryPage.cs35
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/ProgressBarCoreGalleryPage.cs27
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/SearchBarCoreGalleryPage.cs89
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/SliderCoreGalleryPage.cs29
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/StepperCoreGalleryPage.cs29
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/SwitchCoreGalleryPage.cs25
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/TableViewCoreGalleryPage.cs16
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/TimePickerCoreGalleryPage.cs24
-rw-r--r--Xamarin.Forms.Controls/CoreGalleryPages/WebViewCoreGalleryPage.cs62
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/AbsoluteLayoutGallery.cs151
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/ActionSheetGallery.cs64
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/AlertGallery.cs28
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/BackgroundImageGallery.cs109
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/BoundContentPage.cs79
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/ButtonGallery.cs115
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/CarouselPageGallery.cs76
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/CarouselViewGallery.cs292
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/CellTypeList.cs63
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/CellsGalleries/EntryCellListPage.cs54
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/CellsGalleries/EntryCellTablePage.cs85
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ImageCellListPage.cs121
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ImageCellTablePage.cs68
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ProductViewCell.cs33
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/CellsGalleries/SwitchCellListPage.cs47
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/CellsGalleries/SwitchCellTablePage.cs65
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/CellsGalleries/TextCellListPage.cs48
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/CellsGalleries/TextCellTablePage.cs58
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/CellsGalleries/UnEvenViewCellGallery.cs34
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ViewCellGallery.cs115
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/ClipToBoundsGallery.cs31
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/ControlTemplatePage.cs48
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/ControlTemplateXamlPage.xaml24
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/ControlTemplateXamlPage.xaml.cs31
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/DisposeGallery.cs58
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/EditableList.cs116
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/EditorGallery.cs132
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/EntryGallery.cs104
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/FrameGallery.cs32
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/GridGallery.cs174
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/GroupedListActionsGallery.cs282
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/GroupedListContactsGallery.cs244
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/ImageGallery.cs71
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/ImageLoadingGallery.cs43
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/InputIntentGallery.cs101
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/LabelGallery.cs116
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/LayoutOptionsGallery.cs108
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/LayoutPerformanceGallery.cs116
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/LineBreakModeGallery.cs41
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/ListPage.cs117
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/ListViewDemoPage.cs231
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/MapGallery.cs153
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/MasterDetailPageTabletPage.cs40
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/MinimumSizeGallery.cs50
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/MultiGallery.cs58
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/NavigationBarGallery.cs62
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/NavigationMenuGallery.cs38
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/NavigationPropertiesGallery.cs64
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/OpenGLGallery.cs70
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/PickerGallery.cs45
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/ProgressBarGallery.cs26
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/RelativeLayoutGallery.cs47
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/ScaleRotate.cs157
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/ScrollGallery.cs158
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/SearchBarGallery.cs128
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/SettingsPage.cs57
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/SliderGallery.cs33
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/StackLayoutGallery.cs47
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/StepperGallery.cs49
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/StyleGallery.cs41
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/StyleXamlGallery.xaml17
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/StyleXamlGallery.xaml.cs15
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/SwitchGallery.cs53
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/TableViewGallery.cs24
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/TemplatedCarouselGallery.cs114
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/TemplatedTabbedGallery.cs169
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/ToolbarGallery.cs40
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/UnevenListGallery.cs112
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/WebViewGallery.cs50
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/XamlPage.xaml4
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/XamlPage.xaml.cs13
-rw-r--r--Xamarin.Forms.Controls/GalleryPages/crimson.jpgbin0 -> 79109 bytes
-rw-r--r--Xamarin.Forms.Controls/Helpers/ITestCloudService.cs12
-rw-r--r--Xamarin.Forms.Controls/LegacyRepro/Page1.xaml13
-rw-r--r--Xamarin.Forms.Controls/LegacyRepro/Page1.xaml.cs193
-rw-r--r--Xamarin.Forms.Controls/LegacyRepro/SampleViewCell.xaml34
-rw-r--r--Xamarin.Forms.Controls/LegacyRepro/SampleViewCell.xaml.cs149
-rw-r--r--Xamarin.Forms.Controls/Properties/AssemblyInfo.cs33
-rw-r--r--Xamarin.Forms.Controls/RootPages/CaseTenPage.cs27
-rw-r--r--Xamarin.Forms.Controls/RootPages/Issue465Page.cs28
-rw-r--r--Xamarin.Forms.Controls/RootPages/RootContentPage.cs19
-rw-r--r--Xamarin.Forms.Controls/RootPages/RootMDPNavigationContentPage.cs40
-rw-r--r--Xamarin.Forms.Controls/RootPages/RootMDPNavigationTabbedContentPage.cs49
-rw-r--r--Xamarin.Forms.Controls/RootPages/RootNavigationContentPage.cs26
-rw-r--r--Xamarin.Forms.Controls/RootPages/RootNavigationManyTabbedPage.cs63
-rw-r--r--Xamarin.Forms.Controls/RootPages/RootNavigationTabbedContentPage.cs45
-rw-r--r--Xamarin.Forms.Controls/RootPages/RootTabbedContentPage.cs43
-rw-r--r--Xamarin.Forms.Controls/RootPages/RootTabbedMDPNavigationContentPage.cs57
-rw-r--r--Xamarin.Forms.Controls/RootPages/RootTabbedManyNavigationContentPage.cs77
-rw-r--r--Xamarin.Forms.Controls/RootPages/RootTabbedNavigationContentPage.cs46
-rw-r--r--Xamarin.Forms.Controls/RootPages/SwapHierachyStackLayout.cs69
-rw-r--r--Xamarin.Forms.Controls/RootPages/TabbedNavPage.cs33
-rw-r--r--Xamarin.Forms.Controls/TestCases.cs213
-rw-r--r--Xamarin.Forms.Controls/ViewContainers/EventViewContainer.cs32
-rw-r--r--Xamarin.Forms.Controls/ViewContainers/LayeredViewContainer.cs38
-rw-r--r--Xamarin.Forms.Controls/ViewContainers/MultiBindingHack.cs47
-rw-r--r--Xamarin.Forms.Controls/ViewContainers/StateViewContainer.cs48
-rw-r--r--Xamarin.Forms.Controls/ViewContainers/ValueViewContainer.cs16
-rw-r--r--Xamarin.Forms.Controls/ViewContainers/ViewContainer.cs44
-rw-r--r--Xamarin.Forms.Controls/Xamarin.Forms.Controls.csproj285
-rw-r--r--Xamarin.Forms.Controls/app.config11
-rw-r--r--Xamarin.Forms.Controls/packages.config4
-rw-r--r--Xamarin.Forms.Core.Android.UITests/App.cs22
-rw-r--r--Xamarin.Forms.Core.Android.UITests/Makefile2
-rw-r--r--Xamarin.Forms.Core.Android.UITests/PlatformQueries.cs133
-rw-r--r--Xamarin.Forms.Core.Android.UITests/PlatformTests/DisplayAlertUITestsAndroid.cs27
-rw-r--r--Xamarin.Forms.Core.Android.UITests/Properties/AssemblyInfo.cs40
-rw-r--r--Xamarin.Forms.Core.Android.UITests/Xamarin.Forms.Core.Android.UITests.csproj313
-rw-r--r--Xamarin.Forms.Core.Android.UITests/packages.config5
-rw-r--r--Xamarin.Forms.Core.Design/AttributeTableBuilder.cs74
-rw-r--r--Xamarin.Forms.Core.Design/EnumConverter.cs14
-rw-r--r--Xamarin.Forms.Core.Design/Properties/AssemblyInfo.cs7
-rw-r--r--Xamarin.Forms.Core.Design/RegisterMetadata.cs9
-rw-r--r--Xamarin.Forms.Core.Design/Xamarin.Forms.Core.Design.csproj76
-rw-r--r--Xamarin.Forms.Core.Design/packages.config4
-rw-r--r--Xamarin.Forms.Core.UnitTests/AbsoluteLayoutTests.cs265
-rw-r--r--Xamarin.Forms.Core.UnitTests/AnimatableKeyTests.cs72
-rw-r--r--Xamarin.Forms.Core.UnitTests/BaseTestFixture.cs32
-rw-r--r--Xamarin.Forms.Core.UnitTests/BehaviorTest.cs110
-rw-r--r--Xamarin.Forms.Core.UnitTests/BindableObjectExtensionTests.cs72
-rw-r--r--Xamarin.Forms.Core.UnitTests/BindableObjectUnitTests.cs1326
-rw-r--r--Xamarin.Forms.Core.UnitTests/BindablePropertyUnitTests.cs135
-rw-r--r--Xamarin.Forms.Core.UnitTests/BindingBaseUnitTests.cs227
-rw-r--r--Xamarin.Forms.Core.UnitTests/BindingExpressionTests.cs83
-rw-r--r--Xamarin.Forms.Core.UnitTests/BindingTests.cs75
-rw-r--r--Xamarin.Forms.Core.UnitTests/BindingTypeConverterTests.cs27
-rw-r--r--Xamarin.Forms.Core.UnitTests/BindingUnitTests.cs2649
-rw-r--r--Xamarin.Forms.Core.UnitTests/BoxViewUnitTests.cs42
-rw-r--r--Xamarin.Forms.Core.UnitTests/ButtonUnitTest.cs181
-rw-r--r--Xamarin.Forms.Core.UnitTests/CarouselPageTests.cs29
-rw-r--r--Xamarin.Forms.Core.UnitTests/CellTests.cs190
-rw-r--r--Xamarin.Forms.Core.UnitTests/ColorUnitTests.cs268
-rw-r--r--Xamarin.Forms.Core.UnitTests/CommandSourceTests.cs184
-rw-r--r--Xamarin.Forms.Core.UnitTests/CommandTests.cs155
-rw-r--r--Xamarin.Forms.Core.UnitTests/ContentFormUnitTests.cs68
-rw-r--r--Xamarin.Forms.Core.UnitTests/ContentViewUnitTest.cs393
-rw-r--r--Xamarin.Forms.Core.UnitTests/ContraintTypeConverterTests.cs16
-rw-r--r--Xamarin.Forms.Core.UnitTests/ControlTemplateTests.cs181
-rw-r--r--Xamarin.Forms.Core.UnitTests/DataTemplateSelectorTests.cs79
-rw-r--r--Xamarin.Forms.Core.UnitTests/DataTemplateTests.cs119
-rw-r--r--Xamarin.Forms.Core.UnitTests/DataTriggerTests.cs146
-rw-r--r--Xamarin.Forms.Core.UnitTests/DatePickerUnitTest.cs178
-rw-r--r--Xamarin.Forms.Core.UnitTests/DependencyServiceTests.cs128
-rw-r--r--Xamarin.Forms.Core.UnitTests/DistanceTests.cs197
-rw-r--r--Xamarin.Forms.Core.UnitTests/DynamicBindingContextTests.cs314
-rw-r--r--Xamarin.Forms.Core.UnitTests/DynamicResourceTests.cs153
-rw-r--r--Xamarin.Forms.Core.UnitTests/EasingTests.cs32
-rw-r--r--Xamarin.Forms.Core.UnitTests/EditorTests.cs34
-rw-r--r--Xamarin.Forms.Core.UnitTests/EffectTests.cs121
-rw-r--r--Xamarin.Forms.Core.UnitTests/ElementTests.cs176
-rw-r--r--Xamarin.Forms.Core.UnitTests/EntryCellTests.cs82
-rw-r--r--Xamarin.Forms.Core.UnitTests/EntryUnitTests.cs55
-rw-r--r--Xamarin.Forms.Core.UnitTests/EventTriggerTest.cs73
-rw-r--r--Xamarin.Forms.Core.UnitTests/FluentTests.cs8
-rw-r--r--Xamarin.Forms.Core.UnitTests/FontUnitTests.cs129
-rw-r--r--Xamarin.Forms.Core.UnitTests/FormattedStringTests.cs114
-rw-r--r--Xamarin.Forms.Core.UnitTests/FrameUnitTests.cs291
-rw-r--r--Xamarin.Forms.Core.UnitTests/GeocoderUnitTests.cs42
-rw-r--r--Xamarin.Forms.Core.UnitTests/GridLengthTypeConverterTests.cs53
-rw-r--r--Xamarin.Forms.Core.UnitTests/GridTests.cs1569
-rw-r--r--Xamarin.Forms.Core.UnitTests/GroupViewUnitTests.cs292
-rw-r--r--Xamarin.Forms.Core.UnitTests/ImageSourceTests.cs151
-rw-r--r--Xamarin.Forms.Core.UnitTests/ImageTests.cs261
-rw-r--r--Xamarin.Forms.Core.UnitTests/Images/crimson.jpgbin0 -> 79109 bytes
-rw-r--r--Xamarin.Forms.Core.UnitTests/KeyboardTests.cs52
-rw-r--r--Xamarin.Forms.Core.UnitTests/LabelTests.cs296
-rw-r--r--Xamarin.Forms.Core.UnitTests/LayoutOptionsUnitTests.cs22
-rw-r--r--Xamarin.Forms.Core.UnitTests/ListProxyTests.cs426
-rw-r--r--Xamarin.Forms.Core.UnitTests/ListViewTests.cs1490
-rw-r--r--Xamarin.Forms.Core.UnitTests/MapSpanTests.cs44
-rw-r--r--Xamarin.Forms.Core.UnitTests/MapTests.cs147
-rw-r--r--Xamarin.Forms.Core.UnitTests/MarginTests.cs134
-rw-r--r--Xamarin.Forms.Core.UnitTests/MasterDetailFormUnitTests.cs415
-rw-r--r--Xamarin.Forms.Core.UnitTests/MenuItemTests.cs75
-rw-r--r--Xamarin.Forms.Core.UnitTests/MessagingCenterTests.cs191
-rw-r--r--Xamarin.Forms.Core.UnitTests/MockPlatformServices.cs270
-rw-r--r--Xamarin.Forms.Core.UnitTests/MockViewModel.cs30
-rw-r--r--Xamarin.Forms.Core.UnitTests/MotionTests.cs118
-rw-r--r--Xamarin.Forms.Core.UnitTests/MultiPageTests.cs805
-rw-r--r--Xamarin.Forms.Core.UnitTests/MultiTriggerTests.cs134
-rw-r--r--Xamarin.Forms.Core.UnitTests/NavigationMenuUnitTests.cs191
-rw-r--r--Xamarin.Forms.Core.UnitTests/NavigationModelTests.cs304
-rw-r--r--Xamarin.Forms.Core.UnitTests/NavigationProxyTests.cs188
-rw-r--r--Xamarin.Forms.Core.UnitTests/NavigationUnitTest.cs393
-rw-r--r--Xamarin.Forms.Core.UnitTests/NotifiedPropertiesTests.cs214
-rw-r--r--Xamarin.Forms.Core.UnitTests/NotifyCollectionChangedEventArgsExtensionsTests.cs73
-rw-r--r--Xamarin.Forms.Core.UnitTests/ObservableWrapperTests.cs402
-rw-r--r--Xamarin.Forms.Core.UnitTests/OpenGLViewUnitTests.cs20
-rw-r--r--Xamarin.Forms.Core.UnitTests/PageTests.cs498
-rw-r--r--Xamarin.Forms.Core.UnitTests/PanGestureRecognizerUnitTests.cs99
-rw-r--r--Xamarin.Forms.Core.UnitTests/PickerTests.cs59
-rw-r--r--Xamarin.Forms.Core.UnitTests/PinTests.cs105
-rw-r--r--Xamarin.Forms.Core.UnitTests/PinchGestureRecognizerTests.cs75
-rw-r--r--Xamarin.Forms.Core.UnitTests/PointTests.cs121
-rw-r--r--Xamarin.Forms.Core.UnitTests/PositionTests.cs89
-rw-r--r--Xamarin.Forms.Core.UnitTests/ProgressBarTests.cs50
-rw-r--r--Xamarin.Forms.Core.UnitTests/Properties/AssemblyInfo.cs27
-rw-r--r--Xamarin.Forms.Core.UnitTests/RectangleUnitTests.cs208
-rw-r--r--Xamarin.Forms.Core.UnitTests/RegistrarUnitTests.cs149
-rw-r--r--Xamarin.Forms.Core.UnitTests/RelativeLayoutTests.cs516
-rw-r--r--Xamarin.Forms.Core.UnitTests/ResourceDictionaryTests.cs256
-rw-r--r--Xamarin.Forms.Core.UnitTests/ScrollViewUnitTests.cs403
-rw-r--r--Xamarin.Forms.Core.UnitTests/SearchBarUnitTests.cs112
-rw-r--r--Xamarin.Forms.Core.UnitTests/SizeTests.cs93
-rw-r--r--Xamarin.Forms.Core.UnitTests/SliderUnitTests.cs112
-rw-r--r--Xamarin.Forms.Core.UnitTests/StackLayoutUnitTests.cs619
-rw-r--r--Xamarin.Forms.Core.UnitTests/StepperUnitTests.cs176
-rw-r--r--Xamarin.Forms.Core.UnitTests/StyleTests.cs670
-rw-r--r--Xamarin.Forms.Core.UnitTests/SwitchCellTests.cs62
-rw-r--r--Xamarin.Forms.Core.UnitTests/SwitchUnitTests.cs48
-rw-r--r--Xamarin.Forms.Core.UnitTests/TabbedFormUnitTests.cs32
-rw-r--r--Xamarin.Forms.Core.UnitTests/TableModelTests.cs87
-rw-r--r--Xamarin.Forms.Core.UnitTests/TableRootUnitTests.cs103
-rw-r--r--Xamarin.Forms.Core.UnitTests/TableSectionTests.cs225
-rw-r--r--Xamarin.Forms.Core.UnitTests/TableViewUnitTests.cs84
-rw-r--r--Xamarin.Forms.Core.UnitTests/TapGestureRecognizerTests.cs33
-rw-r--r--Xamarin.Forms.Core.UnitTests/TemplatedItemsListTests.cs1073
-rw-r--r--Xamarin.Forms.Core.UnitTests/TextCellTests.cs129
-rw-r--r--Xamarin.Forms.Core.UnitTests/ThicknessTests.cs132
-rw-r--r--Xamarin.Forms.Core.UnitTests/TimePickerUnitTest.cs43
-rw-r--r--Xamarin.Forms.Core.UnitTests/ToolbarItemTests.cs11
-rw-r--r--Xamarin.Forms.Core.UnitTests/ToolbarTrackerTests.cs194
-rw-r--r--Xamarin.Forms.Core.UnitTests/ToolbarUnitTests.cs144
-rw-r--r--Xamarin.Forms.Core.UnitTests/TriggerTests.cs116
-rw-r--r--Xamarin.Forms.Core.UnitTests/TypeUnitTests.cs23
-rw-r--r--Xamarin.Forms.Core.UnitTests/UnitPlatform.cs40
-rw-r--r--Xamarin.Forms.Core.UnitTests/UriImageSourceTests.cs145
-rw-r--r--Xamarin.Forms.Core.UnitTests/ViewCellTests.cs65
-rw-r--r--Xamarin.Forms.Core.UnitTests/ViewUnitTests.cs868
-rw-r--r--Xamarin.Forms.Core.UnitTests/WebViewUnitTests.cs93
-rw-r--r--Xamarin.Forms.Core.UnitTests/Xamarin.Forms.Core.UnitTests.csproj206
-rw-r--r--Xamarin.Forms.Core.UnitTests/packages.config4
-rw-r--r--Xamarin.Forms.Core.Windows.UITests/App.cs24
-rw-r--r--Xamarin.Forms.Core.Windows.UITests/PlatformQueries.cs129
-rw-r--r--Xamarin.Forms.Core.Windows.UITests/Properties/AssemblyInfo.cs36
-rw-r--r--Xamarin.Forms.Core.Windows.UITests/Xamarin.Forms.Core.Windows.UITests.csproj292
-rw-r--r--Xamarin.Forms.Core.Windows.UITests/packages.config5
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/App.cs27
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/BaseTestFixture.cs76
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Makefile2
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/PlatformQueries.cs136
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Properties/AssemblyInfo.cs40
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Queries.cs165
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Remotes/BaseViewContainerRemote.cs315
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Remotes/EventViewContainerRemote.cs20
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Remotes/LayeredViewContainerRemote.cs25
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Remotes/RemoteFactory.cs56
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Remotes/StateViewContainerRemote.cs35
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Remotes/ViewContainerRemote.cs13
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/ActionSheetUITests.cs171
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/ActivityIndicatorUITests.cs76
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/AppearingUITests.cs64
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/AutomationIDUITests.cs73
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/BoxViewUITests.cs57
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/ButtonUITests.cs178
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/ContextActionsUITests.cs129
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/DatePickerUITests.cs55
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/DisplayAlertUITests.cs85
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/EditorUITests.cs55
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/EntryUITests.cs73
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/FrameUITests.cs57
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/ImageUITests.cs63
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/LabelUITests.cs57
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-AbsoluteLayoutGalleryTest.cs229
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-BoundViewUITest.cs96
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ButtonUITests.cs98
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-CarouselPageUITests.cs63
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-CellsUITests.cs318
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ClipToBoundsUITests.cs73
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-EditorUITests.cs269
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-EntryUITests.cs301
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-GridGalleryUITests.cs132
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-GroupedListActionsUITests.cs277
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-InputIntentUITests.cs190
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ListUITests.cs92
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-MapUITests.cs110
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-MinimumSizeUITest.cs48
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-NavigationBarUITests.cs57
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-RelativeLayoutUITest.cs49
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-SearchBarUITests.cs163
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-SliderUITests.cs94
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-StackLayoutUITest.cs76
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-StepperUITests.cs93
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-SwitchUITests.cs104
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-TableViewUITests.cs76
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-TemplatedCarouselPageUITests.cs407
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-TemplatedTabPageUITests.cs346
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ToolbarGalleryUITests.cs51
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-UnevenListTests.cs38
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-UnevenViewCellUITests.cs94
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ViewCellUITests.cs66
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/PickerUITests.cs54
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/ProgressBarUITests.cs56
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/RootGalleryUITests.cs88
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/ScrollViewUITests.cs68
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/SearchBarUITests.cs54
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/SliderUITests.cs54
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/StepperUITests.cs54
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/SwitchUITests.cs54
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/TimePickerUITests.cs56
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/ToolbarItemTests.cs102
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/ViewUITests.cs257
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Tests/WebViewUITests.cs93
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Utilities/AppExtensions.cs116
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Utilities/Drag.cs173
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Utilities/Gestures.cs114
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Utilities/Logger.cs71
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Utilities/NumericExtensions.cs126
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Utilities/ParsingUtils.cs89
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Utilities/UITestCustomExceptions.cs101
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Utilities/ViewInspector.cs342
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/Xamarin.Forms.Core.iOS.UITests.csproj175
-rw-r--r--Xamarin.Forms.Core.iOS.UITests/packages.config5
-rw-r--r--Xamarin.Forms.Core/AbsoluteLayout.cs313
-rw-r--r--Xamarin.Forms.Core/AbsoluteLayoutFlags.cs17
-rw-r--r--Xamarin.Forms.Core/ActionSheetArguments.cs45
-rw-r--r--Xamarin.Forms.Core/ActivityIndicator.cs24
-rw-r--r--Xamarin.Forms.Core/AlertArguments.cs43
-rw-r--r--Xamarin.Forms.Core/AnimatableKey.cs82
-rw-r--r--Xamarin.Forms.Core/Animation.cs138
-rw-r--r--Xamarin.Forms.Core/AnimationExtensions.cs259
-rw-r--r--Xamarin.Forms.Core/Application.cs308
-rw-r--r--Xamarin.Forms.Core/Aspect.cs9
-rw-r--r--Xamarin.Forms.Core/BackButtonPressedEventArgs.cs9
-rw-r--r--Xamarin.Forms.Core/BaseMenuItem.cs6
-rw-r--r--Xamarin.Forms.Core/BindableObject.cs647
-rw-r--r--Xamarin.Forms.Core/BindableObjectExtensions.cs34
-rw-r--r--Xamarin.Forms.Core/BindableProperty.cs331
-rw-r--r--Xamarin.Forms.Core/BindablePropertyConverter.cs105
-rw-r--r--Xamarin.Forms.Core/BindablePropertyKey.cs17
-rw-r--r--Xamarin.Forms.Core/Binding.cs233
-rw-r--r--Xamarin.Forms.Core/BindingBase.cs111
-rw-r--r--Xamarin.Forms.Core/BindingBaseExtensions.cs17
-rw-r--r--Xamarin.Forms.Core/BindingExpression.cs506
-rw-r--r--Xamarin.Forms.Core/BindingMode.cs10
-rw-r--r--Xamarin.Forms.Core/BindingTypeConverter.cs10
-rw-r--r--Xamarin.Forms.Core/BoundsConstraint.cs34
-rw-r--r--Xamarin.Forms.Core/BoundsTypeConverter.cs42
-rw-r--r--Xamarin.Forms.Core/BoxView.cs23
-rw-r--r--Xamarin.Forms.Core/Button.cs251
-rw-r--r--Xamarin.Forms.Core/CarouselPage.cs17
-rw-r--r--Xamarin.Forms.Core/CarouselView.cs86
-rw-r--r--Xamarin.Forms.Core/CastingEnumerator.cs46
-rw-r--r--Xamarin.Forms.Core/Cells/Cell.cs209
-rw-r--r--Xamarin.Forms.Core/Cells/EntryCell.cs80
-rw-r--r--Xamarin.Forms.Core/Cells/INativeElementView.cs7
-rw-r--r--Xamarin.Forms.Core/Cells/ImageCell.cs56
-rw-r--r--Xamarin.Forms.Core/Cells/SwitchCell.cs31
-rw-r--r--Xamarin.Forms.Core/Cells/TextCell.cs94
-rw-r--r--Xamarin.Forms.Core/Cells/ViewCell.cs48
-rw-r--r--Xamarin.Forms.Core/ChatKeyboard.cs6
-rw-r--r--Xamarin.Forms.Core/ChildCollectionChangedEventArgs.cs15
-rw-r--r--Xamarin.Forms.Core/CollectionSynchronizationCallback.cs7
-rw-r--r--Xamarin.Forms.Core/CollectionSynchronizationContext.cs22
-rw-r--r--Xamarin.Forms.Core/Color.cs375
-rw-r--r--Xamarin.Forms.Core/ColorTypeConverter.cs72
-rw-r--r--Xamarin.Forms.Core/ColumnDefinition.cs34
-rw-r--r--Xamarin.Forms.Core/ColumnDefinitionCollection.cs6
-rw-r--r--Xamarin.Forms.Core/Command.cs80
-rw-r--r--Xamarin.Forms.Core/ConcurrentDictionary.cs426
-rw-r--r--Xamarin.Forms.Core/Constraint.cs56
-rw-r--r--Xamarin.Forms.Core/ConstraintExpression.cs53
-rw-r--r--Xamarin.Forms.Core/ConstraintType.cs9
-rw-r--r--Xamarin.Forms.Core/ConstraintTypeConverter.cs17
-rw-r--r--Xamarin.Forms.Core/ContentPage.cs26
-rw-r--r--Xamarin.Forms.Core/ContentPresenter.cs91
-rw-r--r--Xamarin.Forms.Core/ContentPropertyAttribute.cs26
-rw-r--r--Xamarin.Forms.Core/ContentView.cs26
-rw-r--r--Xamarin.Forms.Core/ControlTemplate.cs15
-rw-r--r--Xamarin.Forms.Core/CustomKeyboard.cs12
-rw-r--r--Xamarin.Forms.Core/DataTemplate.cs80
-rw-r--r--Xamarin.Forms.Core/DataTemplateExtensions.cs15
-rw-r--r--Xamarin.Forms.Core/DataTemplateSelector.cs17
-rw-r--r--Xamarin.Forms.Core/DateChangedEventArgs.cs17
-rw-r--r--Xamarin.Forms.Core/DatePicker.cs99
-rw-r--r--Xamarin.Forms.Core/DefinitionCollection.cs109
-rw-r--r--Xamarin.Forms.Core/DelegateLogListener.cs22
-rw-r--r--Xamarin.Forms.Core/DependencyAttribute.cs15
-rw-r--r--Xamarin.Forms.Core/DependencyFetchTarget.cs8
-rw-r--r--Xamarin.Forms.Core/DependencyService.cs102
-rw-r--r--Xamarin.Forms.Core/Device.cs159
-rw-r--r--Xamarin.Forms.Core/DeviceInfo.cs51
-rw-r--r--Xamarin.Forms.Core/DeviceOrientation.cs13
-rw-r--r--Xamarin.Forms.Core/DeviceOrientationExtensions.cs15
-rw-r--r--Xamarin.Forms.Core/Easing.cs98
-rw-r--r--Xamarin.Forms.Core/Editor.cs67
-rw-r--r--Xamarin.Forms.Core/Effect.cs70
-rw-r--r--Xamarin.Forms.Core/Element.cs584
-rw-r--r--Xamarin.Forms.Core/ElementCollection.cs11
-rw-r--r--Xamarin.Forms.Core/ElementEventArgs.cs17
-rw-r--r--Xamarin.Forms.Core/ElementTemplate.cs96
-rw-r--r--Xamarin.Forms.Core/EmailKeyboard.cs6
-rw-r--r--Xamarin.Forms.Core/Entry.cs99
-rw-r--r--Xamarin.Forms.Core/EnumerableExtensions.cs81
-rw-r--r--Xamarin.Forms.Core/EventArg.cs18
-rw-r--r--Xamarin.Forms.Core/ExportEffectAttribute.cs20
-rw-r--r--Xamarin.Forms.Core/ExpressionSearch.cs7
-rw-r--r--Xamarin.Forms.Core/FileAccess.cs9
-rw-r--r--Xamarin.Forms.Core/FileImageSource.cs38
-rw-r--r--Xamarin.Forms.Core/FileImageSourceConverter.cs15
-rw-r--r--Xamarin.Forms.Core/FileMode.cs12
-rw-r--r--Xamarin.Forms.Core/FileShare.cs15
-rw-r--r--Xamarin.Forms.Core/FocusEventArgs.cs20
-rw-r--r--Xamarin.Forms.Core/Font.cs145
-rw-r--r--Xamarin.Forms.Core/FontAttributes.cs12
-rw-r--r--Xamarin.Forms.Core/FontSizeConverter.cs48
-rw-r--r--Xamarin.Forms.Core/FontTypeConverter.cs88
-rw-r--r--Xamarin.Forms.Core/FormattedString.cs99
-rw-r--r--Xamarin.Forms.Core/Frame.cs30
-rw-r--r--Xamarin.Forms.Core/GestureRecognizer.cs9
-rw-r--r--Xamarin.Forms.Core/GestureState.cs12
-rw-r--r--Xamarin.Forms.Core/GestureStatus.cs10
-rw-r--r--Xamarin.Forms.Core/Grid.cs359
-rw-r--r--Xamarin.Forms.Core/GridCalc.cs698
-rw-r--r--Xamarin.Forms.Core/GridLength.cs74
-rw-r--r--Xamarin.Forms.Core/GridLengthTypeConverter.cs27
-rw-r--r--Xamarin.Forms.Core/GridUnitType.cs9
-rw-r--r--Xamarin.Forms.Core/HandlerAttribute.cs23
-rw-r--r--Xamarin.Forms.Core/HtmlWebViewSource.cs28
-rw-r--r--Xamarin.Forms.Core/IAnimatable.cs34
-rw-r--r--Xamarin.Forms.Core/IApplicationController.cs6
-rw-r--r--Xamarin.Forms.Core/IButtonController.cs7
-rw-r--r--Xamarin.Forms.Core/ICarouselViewController.cs10
-rw-r--r--Xamarin.Forms.Core/IControlTemplated.cs11
-rw-r--r--Xamarin.Forms.Core/IDefinition.cs9
-rw-r--r--Xamarin.Forms.Core/IDeserializer.cs11
-rw-r--r--Xamarin.Forms.Core/IEffectControlProvider.cs7
-rw-r--r--Xamarin.Forms.Core/IElement.cs13
-rw-r--r--Xamarin.Forms.Core/IElementController.cs10
-rw-r--r--Xamarin.Forms.Core/IExpressionSearch.cs10
-rw-r--r--Xamarin.Forms.Core/IExtendedTypeConverter.cs13
-rw-r--r--Xamarin.Forms.Core/IFontElement.cs11
-rw-r--r--Xamarin.Forms.Core/IGestureRecognizer.cs8
-rw-r--r--Xamarin.Forms.Core/IIsolatedStorageFile.cs18
-rw-r--r--Xamarin.Forms.Core/IItemViewController.cs10
-rw-r--r--Xamarin.Forms.Core/IItemsView.cs9
-rw-r--r--Xamarin.Forms.Core/ILayout.cs9
-rw-r--r--Xamarin.Forms.Core/ILayoutController.cs9
-rw-r--r--Xamarin.Forms.Core/IListViewController.cs15
-rw-r--r--Xamarin.Forms.Core/IMarkupExtension.cs14
-rw-r--r--Xamarin.Forms.Core/INavigation.cs28
-rw-r--r--Xamarin.Forms.Core/IOpenGlViewController.cs9
-rw-r--r--Xamarin.Forms.Core/IPageContainer.cs7
-rw-r--r--Xamarin.Forms.Core/IPanGestureController.cs13
-rw-r--r--Xamarin.Forms.Core/IPinchGestureController.cs15
-rw-r--r--Xamarin.Forms.Core/IPlatform.cs7
-rw-r--r--Xamarin.Forms.Core/IPlatformServices.cs36
-rw-r--r--Xamarin.Forms.Core/IProvideParentValues.cs9
-rw-r--r--Xamarin.Forms.Core/IProvideValueTarget.cs9
-rw-r--r--Xamarin.Forms.Core/IRegisterable.cs6
-rw-r--r--Xamarin.Forms.Core/IResourceDictionary.cs12
-rw-r--r--Xamarin.Forms.Core/IResourcesProvider.cs7
-rw-r--r--Xamarin.Forms.Core/IRootObjectProvider.cs7
-rw-r--r--Xamarin.Forms.Core/IScrollViewController.cs15
-rw-r--r--Xamarin.Forms.Core/IStyle.cs12
-rw-r--r--Xamarin.Forms.Core/ISystemResourcesProvider.cs7
-rw-r--r--Xamarin.Forms.Core/ITimer.cs13
-rw-r--r--Xamarin.Forms.Core/IValueConverter.cs11
-rw-r--r--Xamarin.Forms.Core/IValueConverterProvider.cs10
-rw-r--r--Xamarin.Forms.Core/IValueProvider.cs9
-rw-r--r--Xamarin.Forms.Core/IViewContainer.cs9
-rw-r--r--Xamarin.Forms.Core/IViewController.cs6
-rw-r--r--Xamarin.Forms.Core/IVisualElementController.cs7
-rw-r--r--Xamarin.Forms.Core/IWebViewRenderer.cs8
-rw-r--r--Xamarin.Forms.Core/IXamlTypeResolver.cs10
-rw-r--r--Xamarin.Forms.Core/IXmlLineInfoProvider.cs9
-rw-r--r--Xamarin.Forms.Core/Image.cs145
-rw-r--r--Xamarin.Forms.Core/ImageSource.cs142
-rw-r--r--Xamarin.Forms.Core/ImageSourceConverter.cs18
-rw-r--r--Xamarin.Forms.Core/InputView.cs18
-rw-r--r--Xamarin.Forms.Core/Interactivity/AttachedCollection.cs127
-rw-r--r--Xamarin.Forms.Core/Interactivity/Behavior.cs65
-rw-r--r--Xamarin.Forms.Core/Interactivity/BindingCondition.cs100
-rw-r--r--Xamarin.Forms.Core/Interactivity/Condition.cs51
-rw-r--r--Xamarin.Forms.Core/Interactivity/DataTrigger.cs57
-rw-r--r--Xamarin.Forms.Core/Interactivity/EventTrigger.cs91
-rw-r--r--Xamarin.Forms.Core/Interactivity/IAttachedObject.cs8
-rw-r--r--Xamarin.Forms.Core/Interactivity/MultiCondition.cs66
-rw-r--r--Xamarin.Forms.Core/Interactivity/MultiTrigger.cs23
-rw-r--r--Xamarin.Forms.Core/Interactivity/PropertyCondition.cs100
-rw-r--r--Xamarin.Forms.Core/Interactivity/Trigger.cs60
-rw-r--r--Xamarin.Forms.Core/Interactivity/TriggerAction.cs37
-rw-r--r--Xamarin.Forms.Core/Interactivity/TriggerBase.cs212
-rw-r--r--Xamarin.Forms.Core/Internals/DynamicResource.cs12
-rw-r--r--Xamarin.Forms.Core/Internals/IDataTemplate.cs10
-rw-r--r--Xamarin.Forms.Core/Internals/IDynamicResourceHandler.cs7
-rw-r--r--Xamarin.Forms.Core/Internals/INameScope.cs12
-rw-r--r--Xamarin.Forms.Core/Internals/NameScope.cs56
-rw-r--r--Xamarin.Forms.Core/InvalidNavigationException.cs11
-rw-r--r--Xamarin.Forms.Core/InvalidationEventArgs.cs14
-rw-r--r--Xamarin.Forms.Core/InvalidationTrigger.cs16
-rw-r--r--Xamarin.Forms.Core/ItemTappedEventArgs.cs17
-rw-r--r--Xamarin.Forms.Core/ItemVisibilityEventArgs.cs14
-rw-r--r--Xamarin.Forms.Core/ItemsView.cs92
-rw-r--r--Xamarin.Forms.Core/ItemsViewSimple.cs335
-rw-r--r--Xamarin.Forms.Core/Keyboard.cs64
-rw-r--r--Xamarin.Forms.Core/KeyboardFlags.cs13
-rw-r--r--Xamarin.Forms.Core/KeyboardTypeConverter.cs29
-rw-r--r--Xamarin.Forms.Core/Label.cs270
-rw-r--r--Xamarin.Forms.Core/Layout.cs433
-rw-r--r--Xamarin.Forms.Core/LayoutAlignment.cs13
-rw-r--r--Xamarin.Forms.Core/LayoutAlignmentExtensions.cs21
-rw-r--r--Xamarin.Forms.Core/LayoutConstraint.cs13
-rw-r--r--Xamarin.Forms.Core/LayoutExpandFlag.cs10
-rw-r--r--Xamarin.Forms.Core/LayoutOptions.cs39
-rw-r--r--Xamarin.Forms.Core/LayoutOptionsConverter.cs25
-rw-r--r--Xamarin.Forms.Core/LineBreakMode.cs12
-rw-r--r--Xamarin.Forms.Core/ListProxy.cs488
-rw-r--r--Xamarin.Forms.Core/ListView.cs540
-rw-r--r--Xamarin.Forms.Core/ListViewCachingStrategy.cs8
-rw-r--r--Xamarin.Forms.Core/LockingSemaphore.cs51
-rw-r--r--Xamarin.Forms.Core/Log.cs25
-rw-r--r--Xamarin.Forms.Core/LogListener.cs7
-rw-r--r--Xamarin.Forms.Core/MasterBehavior.cs11
-rw-r--r--Xamarin.Forms.Core/MasterDetailPage.cs229
-rw-r--r--Xamarin.Forms.Core/MeasureFlags.cs11
-rw-r--r--Xamarin.Forms.Core/MenuItem.cs117
-rw-r--r--Xamarin.Forms.Core/MergedStyle.cs162
-rw-r--r--Xamarin.Forms.Core/MessagingCenter.cs131
-rw-r--r--Xamarin.Forms.Core/ModalEventArgs.cs14
-rw-r--r--Xamarin.Forms.Core/ModalPoppedEventArgs.cs9
-rw-r--r--Xamarin.Forms.Core/ModalPoppingEventArgs.cs11
-rw-r--r--Xamarin.Forms.Core/ModalPushedEventArgs.cs9
-rw-r--r--Xamarin.Forms.Core/ModalPushingEventArgs.cs9
-rw-r--r--Xamarin.Forms.Core/MultiPage.cs359
-rw-r--r--Xamarin.Forms.Core/NameScopeExtensions.cs17
-rw-r--r--Xamarin.Forms.Core/NamedSize.cs11
-rw-r--r--Xamarin.Forms.Core/NavigationEventArgs.cs17
-rw-r--r--Xamarin.Forms.Core/NavigationMenu.cs71
-rw-r--r--Xamarin.Forms.Core/NavigationModel.cs177
-rw-r--r--Xamarin.Forms.Core/NavigationPage.cs411
-rw-r--r--Xamarin.Forms.Core/NavigationProxy.cs233
-rw-r--r--Xamarin.Forms.Core/NavigationRequestedEventArgs.cs26
-rw-r--r--Xamarin.Forms.Core/NotifyCollectionChangedEventArgsEx.cs65
-rw-r--r--Xamarin.Forms.Core/NotifyCollectionChangedEventArgsExtensions.cs105
-rw-r--r--Xamarin.Forms.Core/NullEffect.cs13
-rw-r--r--Xamarin.Forms.Core/NumericExtensions.cs17
-rw-r--r--Xamarin.Forms.Core/NumericKeyboard.cs6
-rw-r--r--Xamarin.Forms.Core/ObservableList.cs112
-rw-r--r--Xamarin.Forms.Core/ObservableWrapper.cs256
-rw-r--r--Xamarin.Forms.Core/OnIdiom.cs21
-rw-r--r--Xamarin.Forms.Core/OnPlatform.cs27
-rw-r--r--Xamarin.Forms.Core/OpenGLView.cs38
-rw-r--r--Xamarin.Forms.Core/OrderedDictionary.cs451
-rw-r--r--Xamarin.Forms.Core/Page.cs403
-rw-r--r--Xamarin.Forms.Core/PanGestureRecognizer.cs37
-rw-r--r--Xamarin.Forms.Core/PanUpdatedEventArgs.cs27
-rw-r--r--Xamarin.Forms.Core/ParameterAttribute.cs15
-rw-r--r--Xamarin.Forms.Core/Performance.cs93
-rw-r--r--Xamarin.Forms.Core/Picker.cs54
-rw-r--r--Xamarin.Forms.Core/PinchGestureRecognizer.cs51
-rw-r--r--Xamarin.Forms.Core/PinchGestureUpdatedEventArgs.cs24
-rw-r--r--Xamarin.Forms.Core/PlatformEffect.cs28
-rw-r--r--Xamarin.Forms.Core/Point.cs95
-rw-r--r--Xamarin.Forms.Core/PointTypeConverter.cs21
-rw-r--r--Xamarin.Forms.Core/PreserveAttribute.cs23
-rw-r--r--Xamarin.Forms.Core/ProgressBar.cs26
-rw-r--r--Xamarin.Forms.Core/Properties/AssemblyInfo.cs56
-rw-r--r--Xamarin.Forms.Core/Properties/GlobalAssemblyInfo.cs8
-rw-r--r--Xamarin.Forms.Core/PropertyChangingEventArgs.cs14
-rw-r--r--Xamarin.Forms.Core/PropertyChangingEventHandler.cs4
-rw-r--r--Xamarin.Forms.Core/ReadOnlyCastingList.cs35
-rw-r--r--Xamarin.Forms.Core/ReadOnlyListAdapter.cs100
-rw-r--r--Xamarin.Forms.Core/Rectangle.cs244
-rw-r--r--Xamarin.Forms.Core/RectangleTypeConverter.cs22
-rw-r--r--Xamarin.Forms.Core/ReflectionExtensions.cs68
-rw-r--r--Xamarin.Forms.Core/Registrar.cs147
-rw-r--r--Xamarin.Forms.Core/RelativeLayout.cs317
-rw-r--r--Xamarin.Forms.Core/RenderWithAttribute.cs15
-rw-r--r--Xamarin.Forms.Core/ResolutionGroupNameAttribute.cs15
-rw-r--r--Xamarin.Forms.Core/ResourceDictionary.cs135
-rw-r--r--Xamarin.Forms.Core/ResourcesChangedEventArgs.cs15
-rw-r--r--Xamarin.Forms.Core/ResourcesExtensions.cs62
-rw-r--r--Xamarin.Forms.Core/RoutingEffect.cs42
-rw-r--r--Xamarin.Forms.Core/RowDefinition.cs34
-rw-r--r--Xamarin.Forms.Core/RowDefinitionCollection.cs6
-rw-r--r--Xamarin.Forms.Core/ScrollOrientation.cs9
-rw-r--r--Xamarin.Forms.Core/ScrollToMode.cs10
-rw-r--r--Xamarin.Forms.Core/ScrollToPosition.cs10
-rw-r--r--Xamarin.Forms.Core/ScrollToRequestedEventArgs.cs56
-rw-r--r--Xamarin.Forms.Core/ScrollView.cs287
-rw-r--r--Xamarin.Forms.Core/ScrolledEventArgs.cs17
-rw-r--r--Xamarin.Forms.Core/SearchBar.cs156
-rw-r--r--Xamarin.Forms.Core/SelectedItemChangedEventArgs.cs14
-rw-r--r--Xamarin.Forms.Core/SelectedPositionChangedEventArgs.cs14
-rw-r--r--Xamarin.Forms.Core/SeparatorMenuItem.cs6
-rw-r--r--Xamarin.Forms.Core/SeparatorVisibility.cs8
-rw-r--r--Xamarin.Forms.Core/Setter.cs88
-rw-r--r--Xamarin.Forms.Core/SettersExtensions.cs29
-rw-r--r--Xamarin.Forms.Core/Size.cs110
-rw-r--r--Xamarin.Forms.Core/SizeRequest.cs29
-rw-r--r--Xamarin.Forms.Core/Slider.cs85
-rw-r--r--Xamarin.Forms.Core/Span.cs169
-rw-r--r--Xamarin.Forms.Core/SplitOrderedList.cs497
-rw-r--r--Xamarin.Forms.Core/StackLayout.cs460
-rw-r--r--Xamarin.Forms.Core/StackOrientation.cs8
-rw-r--r--Xamarin.Forms.Core/Stepper.cs94
-rw-r--r--Xamarin.Forms.Core/StreamImageSource.cs47
-rw-r--r--Xamarin.Forms.Core/StreamWrapper.cs81
-rw-r--r--Xamarin.Forms.Core/Style.cs184
-rw-r--r--Xamarin.Forms.Core/Switch.cs24
-rw-r--r--Xamarin.Forms.Core/SynchronizedList.cs130
-rw-r--r--Xamarin.Forms.Core/TabbedPage.cs17
-rw-r--r--Xamarin.Forms.Core/TableIntent.cs10
-rw-r--r--Xamarin.Forms.Core/TableModel.cs76
-rw-r--r--Xamarin.Forms.Core/TableRoot.cs60
-rw-r--r--Xamarin.Forms.Core/TableSection.cs137
-rw-r--r--Xamarin.Forms.Core/TableSectionBase.cs33
-rw-r--r--Xamarin.Forms.Core/TableView.cs228
-rw-r--r--Xamarin.Forms.Core/TapGestureRecognizer.cs95
-rw-r--r--Xamarin.Forms.Core/TappedEventArgs.cs14
-rw-r--r--Xamarin.Forms.Core/TargetIdiom.cs10
-rw-r--r--Xamarin.Forms.Core/TargetPlatform.cs11
-rw-r--r--Xamarin.Forms.Core/TelephoneKeyboard.cs6
-rw-r--r--Xamarin.Forms.Core/TemplateBinding.cs132
-rw-r--r--Xamarin.Forms.Core/TemplateExtensions.cs15
-rw-r--r--Xamarin.Forms.Core/TemplateUtilities.cs123
-rw-r--r--Xamarin.Forms.Core/TemplatedItemsList.cs1325
-rw-r--r--Xamarin.Forms.Core/TemplatedPage.cs38
-rw-r--r--Xamarin.Forms.Core/TemplatedView.cs68
-rw-r--r--Xamarin.Forms.Core/TextAlignment.cs9
-rw-r--r--Xamarin.Forms.Core/TextChangedEventArgs.cs17
-rw-r--r--Xamarin.Forms.Core/TextKeyboard.cs6
-rw-r--r--Xamarin.Forms.Core/Thickness.cs92
-rw-r--r--Xamarin.Forms.Core/ThicknessTypeConverter.cs35
-rw-r--r--Xamarin.Forms.Core/Ticker.cs117
-rw-r--r--Xamarin.Forms.Core/TimePicker.cs29
-rw-r--r--Xamarin.Forms.Core/ToggledEventArgs.cs14
-rw-r--r--Xamarin.Forms.Core/Toolbar.cs46
-rw-r--r--Xamarin.Forms.Core/ToolbarItem.cs57
-rw-r--r--Xamarin.Forms.Core/ToolbarItemEventArgs.cs14
-rw-r--r--Xamarin.Forms.Core/ToolbarItemOrder.cs9
-rw-r--r--Xamarin.Forms.Core/ToolbarTracker.cs184
-rw-r--r--Xamarin.Forms.Core/TrackableCollection.cs16
-rw-r--r--Xamarin.Forms.Core/Tweener.cs124
-rw-r--r--Xamarin.Forms.Core/TypeConverter.cs33
-rw-r--r--Xamarin.Forms.Core/TypeConverterAttribute.cs74
-rw-r--r--Xamarin.Forms.Core/TypeTypeConverter.cs31
-rw-r--r--Xamarin.Forms.Core/UnsolvableConstraintsException.cs11
-rw-r--r--Xamarin.Forms.Core/UriImageSource.cs223
-rw-r--r--Xamarin.Forms.Core/UriTypeConverter.cs24
-rw-r--r--Xamarin.Forms.Core/UrlKeyboard.cs6
-rw-r--r--Xamarin.Forms.Core/UrlWebViewSource.cs19
-rw-r--r--Xamarin.Forms.Core/ValueChangedEventArgs.cs17
-rw-r--r--Xamarin.Forms.Core/Vec2.cs14
-rw-r--r--Xamarin.Forms.Core/View.cs114
-rw-r--r--Xamarin.Forms.Core/ViewExtensions.cs197
-rw-r--r--Xamarin.Forms.Core/ViewState.cs12
-rw-r--r--Xamarin.Forms.Core/VisualElement.cs764
-rw-r--r--Xamarin.Forms.Core/WeakReferenceExtensions.cs16
-rw-r--r--Xamarin.Forms.Core/WebNavigatedEventArgs.cs12
-rw-r--r--Xamarin.Forms.Core/WebNavigatingEventArgs.cs11
-rw-r--r--Xamarin.Forms.Core/WebNavigationEvent.cs10
-rw-r--r--Xamarin.Forms.Core/WebNavigationEventArgs.cs20
-rw-r--r--Xamarin.Forms.Core/WebNavigationResult.cs10
-rw-r--r--Xamarin.Forms.Core/WebView.cs126
-rw-r--r--Xamarin.Forms.Core/WebViewSource.cs28
-rw-r--r--Xamarin.Forms.Core/WebViewSourceTypeConverter.cs15
-rw-r--r--Xamarin.Forms.Core/Xamarin.Forms.Core.csproj408
-rw-r--r--Xamarin.Forms.Core/Xamarin.Forms.Core.nuspec14
-rw-r--r--Xamarin.Forms.Core/XamlParseException.cs30
-rw-r--r--Xamarin.Forms.Core/XmlLineInfo.cs29
-rw-r--r--Xamarin.Forms.CustomAttributes/Properties/AssemblyInfo.cs30
-rw-r--r--Xamarin.Forms.CustomAttributes/TestAttributes.cs737
-rw-r--r--Xamarin.Forms.CustomAttributes/UiTestAttribute.cs33
-rw-r--r--Xamarin.Forms.CustomAttributes/Xamarin.Forms.CustomAttributes.csproj61
-rw-r--r--Xamarin.Forms.Loader/ExemptMembers.cs157
-rw-r--r--Xamarin.Forms.Loader/FormsLoader.cs51
-rw-r--r--Xamarin.Forms.Loader/FormsMember.cs17
-rw-r--r--Xamarin.Forms.Loader/FormsType.cs46
-rw-r--r--Xamarin.Forms.Loader/ILoaderElement.cs7
-rw-r--r--Xamarin.Forms.Loader/InvalidTestCloudUploadParameters.cs17
-rw-r--r--Xamarin.Forms.Loader/LoaderException.cs8
-rw-r--r--Xamarin.Forms.Loader/LoaderExtensions.cs126
-rw-r--r--Xamarin.Forms.Loader/Logger.cs30
-rw-r--r--Xamarin.Forms.Loader/LoggerWriter.cs8
-rw-r--r--Xamarin.Forms.Loader/MissingCategoryOnTestFixtureException.cs17
-rw-r--r--Xamarin.Forms.Loader/Properties/AssemblyInfo.cs42
-rw-r--r--Xamarin.Forms.Loader/TestMember.cs43
-rw-r--r--Xamarin.Forms.Loader/TestType.cs41
-rw-r--r--Xamarin.Forms.Loader/Xamarin.Forms.Loader.csproj108
-rw-r--r--Xamarin.Forms.Loader/packages.config4
-rw-r--r--Xamarin.Forms.Maps.Android/FormsMaps.cs43
-rw-r--r--Xamarin.Forms.Maps.Android/GeocoderBackend.cs36
-rw-r--r--Xamarin.Forms.Maps.Android/MapRenderer.cs308
-rw-r--r--Xamarin.Forms.Maps.Android/Properties/AssemblyInfo.cs23
-rw-r--r--Xamarin.Forms.Maps.Android/Xamarin.Forms.Maps.Android.csproj121
-rw-r--r--Xamarin.Forms.Maps.Android/packages.config9
-rw-r--r--Xamarin.Forms.Maps.Design/Properties/AssemblyInfo.cs5
-rw-r--r--Xamarin.Forms.Maps.Design/Xamarin.Forms.Maps.Design.csproj79
-rw-r--r--Xamarin.Forms.Maps.Design/packages.config4
-rw-r--r--Xamarin.Forms.Maps.UWP/FormsMaps.cs32
-rw-r--r--Xamarin.Forms.Maps.UWP/GeocoderBackend.cs86
-rw-r--r--Xamarin.Forms.Maps.UWP/MapRenderer.cs297
-rw-r--r--Xamarin.Forms.Maps.UWP/Properties/AssemblyInfo.cs29
-rw-r--r--Xamarin.Forms.Maps.UWP/Properties/Xamarin.Forms.Maps.UWP.rd.xml33
-rw-r--r--Xamarin.Forms.Maps.UWP/PushPin.cs70
-rw-r--r--Xamarin.Forms.Maps.UWP/Xamarin.Forms.Maps.UWP.csproj142
-rw-r--r--Xamarin.Forms.Maps.UWP/project.json16
-rw-r--r--Xamarin.Forms.Maps.WP8/FormsMaps.cs29
-rw-r--r--Xamarin.Forms.Maps.WP8/GeocoderBackend.cs95
-rw-r--r--Xamarin.Forms.Maps.WP8/MapRenderer.cs250
-rw-r--r--Xamarin.Forms.Maps.WP8/Properties/AssemblyInfo.cs26
-rw-r--r--Xamarin.Forms.Maps.WP8/README_FIRST.txt3
-rw-r--r--Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Add.pngbin0 -> 339 bytes
-rw-r--r--Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Cancel.pngbin0 -> 350 bytes
-rw-r--r--Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Check.pngbin0 -> 414 bytes
-rw-r--r--Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Delete.pngbin0 -> 445 bytes
-rw-r--r--Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Select.pngbin0 -> 863 bytes
-rw-r--r--Xamarin.Forms.Maps.WP8/Xamarin.Forms.Maps.WP8.csproj167
-rw-r--r--Xamarin.Forms.Maps.WP8/packages.config4
-rw-r--r--Xamarin.Forms.Maps.WinRT.Phone/Properties/AssemblyInfo.cs29
-rw-r--r--Xamarin.Forms.Maps.WinRT.Phone/Xamarin.Forms.Maps.WinRT.Phone.csproj129
-rw-r--r--Xamarin.Forms.Maps.WinRT.Tablet/GeocoderBackend.cs52
-rw-r--r--Xamarin.Forms.Maps.WinRT.Tablet/MapRenderer.cs249
-rw-r--r--Xamarin.Forms.Maps.WinRT.Tablet/Properties/AssemblyInfo.cs34
-rw-r--r--Xamarin.Forms.Maps.WinRT.Tablet/Xamarin.Forms.Maps.WinRT.Tablet.csproj149
-rw-r--r--Xamarin.Forms.Maps.iOS/FormsMaps.cs34
-rw-r--r--Xamarin.Forms.Maps.iOS/GeocoderBackend.cs61
-rw-r--r--Xamarin.Forms.Maps.iOS/MapRenderer.cs327
-rw-r--r--Xamarin.Forms.Maps.iOS/Properties/AssemblyInfo.cs25
-rw-r--r--Xamarin.Forms.Maps.iOS/Xamarin.Forms.Maps.iOS.Classic.csproj78
-rw-r--r--Xamarin.Forms.Maps.iOS/Xamarin.Forms.Maps.iOS.csproj76
-rw-r--r--Xamarin.Forms.Maps/Distance.cs78
-rw-r--r--Xamarin.Forms.Maps/Geocoder.cs27
-rw-r--r--Xamarin.Forms.Maps/Map.cs107
-rw-r--r--Xamarin.Forms.Maps/MapSpan.cs116
-rw-r--r--Xamarin.Forms.Maps/MapType.cs9
-rw-r--r--Xamarin.Forms.Maps/Pin.cs99
-rw-r--r--Xamarin.Forms.Maps/PinType.cs10
-rw-r--r--Xamarin.Forms.Maps/Position.cs47
-rw-r--r--Xamarin.Forms.Maps/Properties/AssemblyInfo.cs29
-rw-r--r--Xamarin.Forms.Maps/Xamarin.Forms.Maps.csproj73
-rw-r--r--Xamarin.Forms.Platform.Android.FormsViewGroup/Jars/formsviewgroup.jarbin0 -> 1647 bytes
-rw-r--r--Xamarin.Forms.Platform.Android.FormsViewGroup/Properties/AssemblyInfo.cs13
-rw-r--r--Xamarin.Forms.Platform.Android.FormsViewGroup/Transforms/Metadata.xml12
-rw-r--r--Xamarin.Forms.Platform.Android.FormsViewGroup/Xamarin.Forms.Platform.Android.FormsViewGroup.csproj68
-rw-r--r--Xamarin.Forms.Platform.Android/AndroidActivity.cs9
-rw-r--r--Xamarin.Forms.Platform.Android/AndroidApplicationLifecycleState.cs14
-rw-r--r--Xamarin.Forms.Platform.Android/AndroidTicker.cs43
-rw-r--r--Xamarin.Forms.Platform.Android/AndroidTitleBarVisibility.cs8
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/ButtonRenderer.cs243
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/CarouselPageRenderer.cs155
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/FormsAppCompatActivity.cs452
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/FormsFragmentPagerAdapter.cs59
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/FormsViewPager.cs34
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/FragmentContainer.cs111
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/FrameRenderer.cs215
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/IManageFragments.cs13
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/MasterDetailPageRenderer.cs355
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs789
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/PickerRenderer.cs141
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/Platform.cs394
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/Resource.cs31
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/SwitchRenderer.cs92
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/TabbedPageRenderer.cs322
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/ViewRenderer.cs7
-rw-r--r--Xamarin.Forms.Platform.Android/CellAdapter.cs327
-rw-r--r--Xamarin.Forms.Platform.Android/Cells/BaseCellView.cs208
-rw-r--r--Xamarin.Forms.Platform.Android/Cells/CellFactory.cs41
-rw-r--r--Xamarin.Forms.Platform.Android/Cells/CellRenderer.cs131
-rw-r--r--Xamarin.Forms.Platform.Android/Cells/EntryCellEditText.cs45
-rw-r--r--Xamarin.Forms.Platform.Android/Cells/EntryCellRenderer.cs119
-rw-r--r--Xamarin.Forms.Platform.Android/Cells/EntryCellView.cs145
-rw-r--r--Xamarin.Forms.Platform.Android/Cells/ImageCellRenderer.cs37
-rw-r--r--Xamarin.Forms.Platform.Android/Cells/SwitchCellRenderer.cs55
-rw-r--r--Xamarin.Forms.Platform.Android/Cells/SwitchCellView.cs25
-rw-r--r--Xamarin.Forms.Platform.Android/Cells/TextCellRenderer.cs78
-rw-r--r--Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs178
-rw-r--r--Xamarin.Forms.Platform.Android/ColorExtensions.cs40
-rw-r--r--Xamarin.Forms.Platform.Android/ContextExtensions.cs58
-rw-r--r--Xamarin.Forms.Platform.Android/Deserializer.cs89
-rw-r--r--Xamarin.Forms.Platform.Android/ElementChangedEventArgs.cs17
-rw-r--r--Xamarin.Forms.Platform.Android/ExportCellAttribute.cs12
-rw-r--r--Xamarin.Forms.Platform.Android/ExportImageSourceHandlerAttribute.cs12
-rw-r--r--Xamarin.Forms.Platform.Android/ExportRendererAttribute.cs12
-rw-r--r--Xamarin.Forms.Platform.Android/Extensions.cs40
-rw-r--r--Xamarin.Forms.Platform.Android/Forms.cs514
-rw-r--r--Xamarin.Forms.Platform.Android/FormsApplicationActivity.cs319
-rw-r--r--Xamarin.Forms.Platform.Android/GenericMenuClickListener.cs22
-rw-r--r--Xamarin.Forms.Platform.Android/GetDesiredSizeDelegate.cs4
-rw-r--r--Xamarin.Forms.Platform.Android/IDeviceInfoProvider.cs12
-rw-r--r--Xamarin.Forms.Platform.Android/IPlatformLayout.cs7
-rw-r--r--Xamarin.Forms.Platform.Android/IStartActivityForResult.cs14
-rw-r--r--Xamarin.Forms.Platform.Android/IVisualElementRenderer.cs22
-rw-r--r--Xamarin.Forms.Platform.Android/InnerGestureListener.cs146
-rw-r--r--Xamarin.Forms.Platform.Android/InnerScaleListener.cs68
-rw-r--r--Xamarin.Forms.Platform.Android/KeyboardManager.cs41
-rw-r--r--Xamarin.Forms.Platform.Android/LayoutExtensions.cs19
-rw-r--r--Xamarin.Forms.Platform.Android/MeasureSpecFactory.cs20
-rw-r--r--Xamarin.Forms.Platform.Android/NativeViewWrapper.cs22
-rw-r--r--Xamarin.Forms.Platform.Android/NativeViewWrapperRenderer.cs61
-rw-r--r--Xamarin.Forms.Platform.Android/OnLayoutDelegate.cs4
-rw-r--r--Xamarin.Forms.Platform.Android/OnMeasureDelegate.cs4
-rw-r--r--Xamarin.Forms.Platform.Android/PanGestureHandler.cs69
-rw-r--r--Xamarin.Forms.Platform.Android/PinchGestureHandler.cs76
-rw-r--r--Xamarin.Forms.Platform.Android/Platform.cs1056
-rw-r--r--Xamarin.Forms.Platform.Android/PlatformEffect.cs9
-rw-r--r--Xamarin.Forms.Platform.Android/PlatformRenderer.cs81
-rw-r--r--Xamarin.Forms.Platform.Android/Properties/AssemblyInfo.cs65
-rw-r--r--Xamarin.Forms.Platform.Android/RendererFactory.cs13
-rw-r--r--Xamarin.Forms.Platform.Android/RendererPool.cs88
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/AHorizontalScrollView.cs62
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ActionSheetRenderer.cs83
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ActivityIndicatorRenderer.cs59
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/AlignmentExtensions.cs33
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/BoxRenderer.cs43
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ButtonDrawable.cs150
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ButtonRenderer.cs252
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/CarouselPageAdapter.cs155
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/CarouselPageRenderer.cs100
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/CarouselViewExtensions.cs69
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/CarouselViewRenderer.cs353
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ConditionalFocusLayout.cs48
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/DatePickerRenderer.cs154
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/DescendantFocusToggler.cs42
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/EditorEditText.cs42
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/EditorRenderer.cs140
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/EntryEditText.cs42
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/EntryRenderer.cs189
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/FileImageSourceHandler.cs17
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/FontExtensions.cs93
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/FormattedStringExtensions.cs90
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/FormsImageView.cs36
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/FormsTextView.cs41
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/FormsWebChromeClient.cs74
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/FrameRenderer.cs195
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/GenericAnimatorListener.cs41
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/IDescendantFocusToggler.cs9
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/IImageSourceHandler.cs12
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/IToolbarButton.cs7
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ImageExtensions.cs26
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ImageLoaderSourceHandler.cs22
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs108
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/IntVector.cs86
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ItemViewAdapter.cs89
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/KeyboardExtensions.cs77
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/LabelRenderer.cs213
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs531
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs355
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/MasterDetailContainer.cs138
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/MasterDetailRenderer.cs348
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/MeasureSpecification.cs41
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/MeasureSpecificationType.cs13
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/NavigationMenuRenderer.cs152
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/NavigationRenderer.cs302
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ObjectJavaBox.cs14
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/OpenGLViewRenderer.cs102
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/PageContainer.cs30
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/PageRenderer.cs71
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/PhysicalLayoutManager.cs531
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/PickerRenderer.cs165
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ProgressBarRenderer.cs40
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ScrollViewContainer.cs75
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ScrollViewRenderer.cs331
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/SearchBarRenderer.cs236
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/SliderRenderer.cs98
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/StepperRenderer.cs94
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/StreamImagesourceHandler.cs22
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/SwitchRenderer.cs83
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/TabbedRenderer.cs75
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/TableViewModelRenderer.cs228
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/TableViewRenderer.cs44
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/TimePickerRenderer.cs95
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ToolbarButton.cs36
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ToolbarImageButton.cs41
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ToolbarRenderer.cs65
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ViewGroupExtensions.cs27
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/WebViewRenderer.cs206
-rw-r--r--Xamarin.Forms.Platform.Android/ResourceManager.cs71
-rw-r--r--Xamarin.Forms.Platform.Android/ResourcesProvider.cs68
-rw-r--r--Xamarin.Forms.Platform.Android/TapGestureHandler.cs52
-rw-r--r--Xamarin.Forms.Platform.Android/ViewExtensions.cs61
-rw-r--r--Xamarin.Forms.Platform.Android/ViewInitializedEventArgs.cs11
-rw-r--r--Xamarin.Forms.Platform.Android/ViewPool.cs79
-rw-r--r--Xamarin.Forms.Platform.Android/ViewRenderer.cs205
-rw-r--r--Xamarin.Forms.Platform.Android/VisualElementChangedEventArgs.cs9
-rw-r--r--Xamarin.Forms.Platform.Android/VisualElementExtensions.cs42
-rw-r--r--Xamarin.Forms.Platform.Android/VisualElementPackager.cs217
-rw-r--r--Xamarin.Forms.Platform.Android/VisualElementRenderer.cs392
-rw-r--r--Xamarin.Forms.Platform.Android/VisualElementRendererFlags.cs12
-rw-r--r--Xamarin.Forms.Platform.Android/VisualElementTracker.cs396
-rw-r--r--Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj259
-rw-r--r--Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.nuspec17
-rw-r--r--Xamarin.Forms.Platform.Android/packages.config11
-rw-r--r--Xamarin.Forms.Platform.UAP/FormsCommandBar.cs37
-rw-r--r--Xamarin.Forms.Platform.UAP/FormsTextBoxStyle.xaml199
-rw-r--r--Xamarin.Forms.Platform.UAP/IToolBarForegroundBinder.cs10
-rw-r--r--Xamarin.Forms.Platform.UAP/MasterDetailControl.cs222
-rw-r--r--Xamarin.Forms.Platform.UAP/MasterDetailPageRenderer.cs312
-rw-r--r--Xamarin.Forms.Platform.UAP/PageControl.xaml10
-rw-r--r--Xamarin.Forms.Platform.UAP/Properties/AssemblyInfo.cs60
-rw-r--r--Xamarin.Forms.Platform.UAP/Properties/Xamarin.Forms.Platform.UAP.rd.xml33
-rw-r--r--Xamarin.Forms.Platform.UAP/Resources.xaml1091
-rw-r--r--Xamarin.Forms.Platform.UAP/SearchBarRenderer.cs208
-rw-r--r--Xamarin.Forms.Platform.UAP/StepperControl.cs227
-rw-r--r--Xamarin.Forms.Platform.UAP/TabbedPageRenderer.cs264
-rw-r--r--Xamarin.Forms.Platform.UAP/Xamarin.Forms.Platform.UAP.csproj450
-rw-r--r--Xamarin.Forms.Platform.UAP/project.json16
-rw-r--r--Xamarin.Forms.Platform.WP8/ActivityIndicatorRenderer.cs36
-rw-r--r--Xamarin.Forms.Platform.WP8/AlignmentExtensions.cs33
-rw-r--r--Xamarin.Forms.Platform.WP8/Animatable.cs13
-rw-r--r--Xamarin.Forms.Platform.WP8/AsyncValue.cs89
-rw-r--r--Xamarin.Forms.Platform.WP8/BoxViewRenderer.cs17
-rw-r--r--Xamarin.Forms.Platform.WP8/ButtonRenderer.cs119
-rw-r--r--Xamarin.Forms.Platform.WP8/CarouselPageRenderer.cs219
-rw-r--r--Xamarin.Forms.Platform.WP8/CarouselViewRenderer.cs13
-rw-r--r--Xamarin.Forms.Platform.WP8/CellControl.cs101
-rw-r--r--Xamarin.Forms.Platform.WP8/CellTemplateSelector.cs60
-rw-r--r--Xamarin.Forms.Platform.WP8/CollapseWhenEmptyConverter.cs28
-rw-r--r--Xamarin.Forms.Platform.WP8/ConvertExtensions.cs17
-rw-r--r--Xamarin.Forms.Platform.WP8/Converters/CaseConverter.cs24
-rw-r--r--Xamarin.Forms.Platform.WP8/Converters/ColorConverter.cs24
-rw-r--r--Xamarin.Forms.Platform.WP8/Converters/HorizontalTextAlignmentConverter.cs20
-rw-r--r--Xamarin.Forms.Platform.WP8/Converters/ImageConverter.cs28
-rw-r--r--Xamarin.Forms.Platform.WP8/Converters/KeyboardConverter.cs19
-rw-r--r--Xamarin.Forms.Platform.WP8/CustomContextMenu.cs27
-rw-r--r--Xamarin.Forms.Platform.WP8/DataTemplateSelector.cs17
-rw-r--r--Xamarin.Forms.Platform.WP8/DatePickerRenderer.cs59
-rw-r--r--Xamarin.Forms.Platform.WP8/Deserializer.cs86
-rw-r--r--Xamarin.Forms.Platform.WP8/EditorRenderer.cs108
-rw-r--r--Xamarin.Forms.Platform.WP8/ElementChangedEventArgs.cs24
-rw-r--r--Xamarin.Forms.Platform.WP8/EntryRenderer.cs324
-rw-r--r--Xamarin.Forms.Platform.WP8/ExportCellAttribute.cs12
-rw-r--r--Xamarin.Forms.Platform.WP8/ExportImageSourceHandlerAttribute.cs12
-rw-r--r--Xamarin.Forms.Platform.WP8/ExportRendererAttribute.cs12
-rw-r--r--Xamarin.Forms.Platform.WP8/Extensions.cs30
-rw-r--r--Xamarin.Forms.Platform.WP8/FontExtensions.cs162
-rw-r--r--Xamarin.Forms.Platform.WP8/Forms.cs254
-rw-r--r--Xamarin.Forms.Platform.WP8/FormsApplicationPage.cs86
-rw-r--r--Xamarin.Forms.Platform.WP8/FormsListPicker.cs25
-rw-r--r--Xamarin.Forms.Platform.WP8/FormsPhoneTextBox.cs236
-rw-r--r--Xamarin.Forms.Platform.WP8/FrameRenderer.cs57
-rw-r--r--Xamarin.Forms.Platform.WP8/FrameworkElementExtensions.cs73
-rw-r--r--Xamarin.Forms.Platform.WP8/ICellRenderer.cs7
-rw-r--r--Xamarin.Forms.Platform.WP8/IVisualElementRenderer.cs18
-rw-r--r--Xamarin.Forms.Platform.WP8/ImageRenderer.cs166
-rw-r--r--Xamarin.Forms.Platform.WP8/LabelRenderer.cs187
-rw-r--r--Xamarin.Forms.Platform.WP8/LayoutExtensions.cs27
-rw-r--r--Xamarin.Forms.Platform.WP8/ListViewRenderer.cs717
-rw-r--r--Xamarin.Forms.Platform.WP8/MD5.cs12
-rw-r--r--Xamarin.Forms.Platform.WP8/MD5CryptoServiceProvider.cs444
-rw-r--r--Xamarin.Forms.Platform.WP8/MasterDetailRenderer.cs183
-rw-r--r--Xamarin.Forms.Platform.WP8/NativeViewWrapper.cs24
-rw-r--r--Xamarin.Forms.Platform.WP8/NativeViewWrapperRenderer.cs62
-rw-r--r--Xamarin.Forms.Platform.WP8/NavigationMenuRenderer.cs85
-rw-r--r--Xamarin.Forms.Platform.WP8/NavigationPageRenderer.cs209
-rw-r--r--Xamarin.Forms.Platform.WP8/PageRenderer.cs18
-rw-r--r--Xamarin.Forms.Platform.WP8/PageToRendererConverter.cs24
-rw-r--r--Xamarin.Forms.Platform.WP8/PickerRenderer.cs256
-rw-r--r--Xamarin.Forms.Platform.WP8/Platform.cs628
-rw-r--r--Xamarin.Forms.Platform.WP8/PlatformEffect.cs8
-rw-r--r--Xamarin.Forms.Platform.WP8/ProgressBarRenderer.cs35
-rw-r--r--Xamarin.Forms.Platform.WP8/Properties/AssemblyInfo.cs78
-rw-r--r--Xamarin.Forms.Platform.WP8/RendererFactory.cs13
-rw-r--r--Xamarin.Forms.Platform.WP8/ResourcesProvider.cs59
-rw-r--r--Xamarin.Forms.Platform.WP8/ScrollViewRenderer.cs194
-rw-r--r--Xamarin.Forms.Platform.WP8/SearchBarRenderer.cs159
-rw-r--r--Xamarin.Forms.Platform.WP8/ServiceReferences.ClientConfig26
-rw-r--r--Xamarin.Forms.Platform.WP8/SliderRenderer.cs43
-rw-r--r--Xamarin.Forms.Platform.WP8/StepperRenderer.cs68
-rw-r--r--Xamarin.Forms.Platform.WP8/SwitchRenderer.cs50
-rw-r--r--Xamarin.Forms.Platform.WP8/TabbedPageRenderer.cs105
-rw-r--r--Xamarin.Forms.Platform.WP8/TableView.xaml31
-rw-r--r--Xamarin.Forms.Platform.WP8/TableView.xaml.cs10
-rw-r--r--Xamarin.Forms.Platform.WP8/TableViewRenderer.cs91
-rw-r--r--Xamarin.Forms.Platform.WP8/TextAlignmentToHorizontalAlignmentConverter.cs43
-rw-r--r--Xamarin.Forms.Platform.WP8/TextCellRenderer.cs88
-rw-r--r--Xamarin.Forms.Platform.WP8/TimePickerRenderer.cs60
-rw-r--r--Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Cancel.pngbin0 -> 350 bytes
-rw-r--r--Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Check.pngbin0 -> 414 bytes
-rw-r--r--Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Delete.pngbin0 -> 445 bytes
-rw-r--r--Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Select.pngbin0 -> 863 bytes
-rw-r--r--Xamarin.Forms.Platform.WP8/ViewExtensions.cs19
-rw-r--r--Xamarin.Forms.Platform.WP8/ViewRenderer.cs47
-rw-r--r--Xamarin.Forms.Platform.WP8/ViewToRendererConverter.cs77
-rw-r--r--Xamarin.Forms.Platform.WP8/VisualElementPackager.cs88
-rw-r--r--Xamarin.Forms.Platform.WP8/VisualElementRenderer.cs326
-rw-r--r--Xamarin.Forms.Platform.WP8/VisualElementTracker.cs370
-rw-r--r--Xamarin.Forms.Platform.WP8/WP8PlatformServices.cs232
-rw-r--r--Xamarin.Forms.Platform.WP8/WPResources.xaml542
-rw-r--r--Xamarin.Forms.Platform.WP8/WebViewRenderer.cs166
-rw-r--r--Xamarin.Forms.Platform.WP8/WinPhoneTicker.cs26
-rw-r--r--Xamarin.Forms.Platform.WP8/Xamarin.Forms.Platform.WP8.csproj245
-rw-r--r--Xamarin.Forms.Platform.WP8/packages.config4
-rw-r--r--Xamarin.Forms.Platform.WinRT.Phone/Forms.cs97
-rw-r--r--Xamarin.Forms.Platform.WinRT.Phone/FormsPivot.cs65
-rw-r--r--Xamarin.Forms.Platform.WinRT.Phone/FormsTextBoxStyle.xaml121
-rw-r--r--Xamarin.Forms.Platform.WinRT.Phone/PhoneResources.xaml694
-rw-r--r--Xamarin.Forms.Platform.WinRT.Phone/Properties/AssemblyInfo.cs14
-rw-r--r--Xamarin.Forms.Platform.WinRT.Phone/SearchBarRenderer.cs160
-rw-r--r--Xamarin.Forms.Platform.WinRT.Phone/SearchBox.xaml248
-rw-r--r--Xamarin.Forms.Platform.WinRT.Phone/SearchBox.xaml.cs157
-rw-r--r--Xamarin.Forms.Platform.WinRT.Phone/TabbedPageRenderer.cs284
-rw-r--r--Xamarin.Forms.Platform.WinRT.Phone/WindowsPhonePage.cs15
-rw-r--r--Xamarin.Forms.Platform.WinRT.Phone/WindowsPhonePlatform.cs41
-rw-r--r--Xamarin.Forms.Platform.WinRT.Phone/WindowsPhonePlatformServices.cs44
-rw-r--r--Xamarin.Forms.Platform.WinRT.Phone/WindowsPhoneResourcesProvider.cs72
-rw-r--r--Xamarin.Forms.Platform.WinRT.Phone/Xamarin.Forms.Platform.WinRT.Phone.csproj144
-rw-r--r--Xamarin.Forms.Platform.WinRT.Tablet/Forms.cs121
-rw-r--r--Xamarin.Forms.Platform.WinRT.Tablet/FormsListViewItemPresenter.cs36
-rw-r--r--Xamarin.Forms.Platform.WinRT.Tablet/FormsSearchBox.cs18
-rw-r--r--Xamarin.Forms.Platform.WinRT.Tablet/FormsTextBoxStyle.xaml257
-rw-r--r--Xamarin.Forms.Platform.WinRT.Tablet/Properties/AssemblyInfo.cs11
-rw-r--r--Xamarin.Forms.Platform.WinRT.Tablet/SearchBarRenderer.cs165
-rw-r--r--Xamarin.Forms.Platform.WinRT.Tablet/TabbedPageRenderer.cs236
-rw-r--r--Xamarin.Forms.Platform.WinRT.Tablet/TabletResources.xaml939
-rw-r--r--Xamarin.Forms.Platform.WinRT.Tablet/TabsControl.cs50
-rw-r--r--Xamarin.Forms.Platform.WinRT.Tablet/WindowsPage.cs17
-rw-r--r--Xamarin.Forms.Platform.WinRT.Tablet/WindowsPlatform.cs16
-rw-r--r--Xamarin.Forms.Platform.WinRT.Tablet/WindowsPlatformServices.cs17
-rw-r--r--Xamarin.Forms.Platform.WinRT.Tablet/WindowsResourcesProvider.cs82
-rw-r--r--Xamarin.Forms.Platform.WinRT.Tablet/Xamarin.Forms.Platform.WinRT.Tablet.csproj157
-rw-r--r--Xamarin.Forms.Platform.WinRT/ActivityIndicatorRenderer.cs68
-rw-r--r--Xamarin.Forms.Platform.WinRT/AlignmentExtensions.cs39
-rw-r--r--Xamarin.Forms.Platform.WinRT/AsyncValue.cs95
-rw-r--r--Xamarin.Forms.Platform.WinRT/BackgroundTracker.cs82
-rw-r--r--Xamarin.Forms.Platform.WinRT/BoolToVisibilityConverter.cs30
-rw-r--r--Xamarin.Forms.Platform.WinRT/BoxViewRenderer.cs31
-rw-r--r--Xamarin.Forms.Platform.WinRT/ButtonRenderer.cs160
-rw-r--r--Xamarin.Forms.Platform.WinRT/CarouselPageRenderer.cs180
-rw-r--r--Xamarin.Forms.Platform.WinRT/CarouselViewRenderer.cs220
-rw-r--r--Xamarin.Forms.Platform.WinRT/CaseConverter.cs29
-rw-r--r--Xamarin.Forms.Platform.WinRT/CellControl.cs342
-rw-r--r--Xamarin.Forms.Platform.WinRT/CollapseWhenEmptyConverter.cs33
-rw-r--r--Xamarin.Forms.Platform.WinRT/ColorConverter.cs30
-rw-r--r--Xamarin.Forms.Platform.WinRT/ConvertExtensions.cs23
-rw-r--r--Xamarin.Forms.Platform.WinRT/DatePickerRenderer.cs97
-rw-r--r--Xamarin.Forms.Platform.WinRT/DefaultRenderer.cs14
-rw-r--r--Xamarin.Forms.Platform.WinRT/EditorRenderer.cs155
-rw-r--r--Xamarin.Forms.Platform.WinRT/EntryCellTextBox.cs30
-rw-r--r--Xamarin.Forms.Platform.WinRT/EntryRenderer.cs212
-rw-r--r--Xamarin.Forms.Platform.WinRT/ExportRendererAttribute.cs34
-rw-r--r--Xamarin.Forms.Platform.WinRT/Extensions.cs46
-rw-r--r--Xamarin.Forms.Platform.WinRT/FileImageSourceHandler.cs29
-rw-r--r--Xamarin.Forms.Platform.WinRT/FileImageSourcePathConverter.cs26
-rw-r--r--Xamarin.Forms.Platform.WinRT/FontExtensions.cs75
-rw-r--r--Xamarin.Forms.Platform.WinRT/FormsButton.cs46
-rw-r--r--Xamarin.Forms.Platform.WinRT/FormsComboBox.cs68
-rw-r--r--Xamarin.Forms.Platform.WinRT/FormsDatePicker.cs76
-rw-r--r--Xamarin.Forms.Platform.WinRT/FormsTextBox.cs332
-rw-r--r--Xamarin.Forms.Platform.WinRT/FormsTimePicker.cs76
-rw-r--r--Xamarin.Forms.Platform.WinRT/FrameRenderer.cs71
-rw-r--r--Xamarin.Forms.Platform.WinRT/FrameworkElementExtensions.cs114
-rw-r--r--Xamarin.Forms.Platform.WinRT/HeightConverter.cs32
-rw-r--r--Xamarin.Forms.Platform.WinRT/HorizontalTextAlignmentConverter.cs24
-rw-r--r--Xamarin.Forms.Platform.WinRT/ICellRenderer.cs14
-rw-r--r--Xamarin.Forms.Platform.WinRT/IImageSourceHandler.cs16
-rw-r--r--Xamarin.Forms.Platform.WinRT/ITitleProvider.cs21
-rw-r--r--Xamarin.Forms.Platform.WinRT/IToolbarProvider.cs16
-rw-r--r--Xamarin.Forms.Platform.WinRT/IVisualElementRenderer.cs23
-rw-r--r--Xamarin.Forms.Platform.WinRT/IWrapperAware.cs14
-rw-r--r--Xamarin.Forms.Platform.WinRT/ImageConverter.cs33
-rw-r--r--Xamarin.Forms.Platform.WinRT/ImageLoaderSourceHandler.cs52
-rw-r--r--Xamarin.Forms.Platform.WinRT/ImageRenderer.cs132
-rw-r--r--Xamarin.Forms.Platform.WinRT/KeyboardConverter.cs27
-rw-r--r--Xamarin.Forms.Platform.WinRT/KeyboardExtensions.cs57
-rw-r--r--Xamarin.Forms.Platform.WinRT/LabelRenderer.cs202
-rw-r--r--Xamarin.Forms.Platform.WinRT/LayoutExtensions.cs33
-rw-r--r--Xamarin.Forms.Platform.WinRT/LayoutRenderer.cs55
-rw-r--r--Xamarin.Forms.Platform.WinRT/ListGroupHeaderPresenter.cs46
-rw-r--r--Xamarin.Forms.Platform.WinRT/ListViewGroupStyleSelector.cs18
-rw-r--r--Xamarin.Forms.Platform.WinRT/ListViewRenderer.cs634
-rw-r--r--Xamarin.Forms.Platform.WinRT/MasterBackgroundConverter.cs75
-rw-r--r--Xamarin.Forms.Platform.WinRT/MasterDetailControl.cs168
-rw-r--r--Xamarin.Forms.Platform.WinRT/MasterDetailPageRenderer.cs291
-rw-r--r--Xamarin.Forms.Platform.WinRT/MenuItemCommand.cs48
-rw-r--r--Xamarin.Forms.Platform.WinRT/NativeViewWrapper.cs30
-rw-r--r--Xamarin.Forms.Platform.WinRT/NativeViewWrapperRenderer.cs74
-rw-r--r--Xamarin.Forms.Platform.WinRT/NavigationPageRenderer.cs554
-rw-r--r--Xamarin.Forms.Platform.WinRT/PageControl.xaml10
-rw-r--r--Xamarin.Forms.Platform.WinRT/PageControl.xaml.cs166
-rw-r--r--Xamarin.Forms.Platform.WinRT/PageRenderer.cs80
-rw-r--r--Xamarin.Forms.Platform.WinRT/PageToRenderedElementConverter.cs31
-rw-r--r--Xamarin.Forms.Platform.WinRT/PickerRenderer.cs147
-rw-r--r--Xamarin.Forms.Platform.WinRT/Platform.cs721
-rw-r--r--Xamarin.Forms.Platform.WinRT/PlatformEffect.cs14
-rw-r--r--Xamarin.Forms.Platform.WinRT/ProgressBarRenderer.cs59
-rw-r--r--Xamarin.Forms.Platform.WinRT/Properties/AssemblyInfo.cs57
-rw-r--r--Xamarin.Forms.Platform.WinRT/RendererFactory.cs19
-rw-r--r--Xamarin.Forms.Platform.WinRT/Resources.xaml87
-rw-r--r--Xamarin.Forms.Platform.WinRT/ScrollViewRenderer.cs194
-rw-r--r--Xamarin.Forms.Platform.WinRT/SliderRenderer.cs59
-rw-r--r--Xamarin.Forms.Platform.WinRT/StepperControl.xaml90
-rw-r--r--Xamarin.Forms.Platform.WinRT/StepperControl.xaml.cs94
-rw-r--r--Xamarin.Forms.Platform.WinRT/StepperRenderer.cs72
-rw-r--r--Xamarin.Forms.Platform.WinRT/StreamImagesourceHandler.cs36
-rw-r--r--Xamarin.Forms.Platform.WinRT/SwitchRenderer.cs50
-rw-r--r--Xamarin.Forms.Platform.WinRT/TableViewRenderer.cs85
-rw-r--r--Xamarin.Forms.Platform.WinRT/TaskExtensions.cs40
-rw-r--r--Xamarin.Forms.Platform.WinRT/TextAlignmentToHorizontalAlignmentConverter.cs48
-rw-r--r--Xamarin.Forms.Platform.WinRT/TextCellRenderer.cs79
-rw-r--r--Xamarin.Forms.Platform.WinRT/TimePickerRenderer.cs75
-rw-r--r--Xamarin.Forms.Platform.WinRT/ViewExtensions.cs26
-rw-r--r--Xamarin.Forms.Platform.WinRT/ViewRenderer.cs37
-rw-r--r--Xamarin.Forms.Platform.WinRT/ViewToRendererConverter.cs113
-rw-r--r--Xamarin.Forms.Platform.WinRT/VisualElementChangedEventArgs.cs30
-rw-r--r--Xamarin.Forms.Platform.WinRT/VisualElementExtensions.cs56
-rw-r--r--Xamarin.Forms.Platform.WinRT/VisualElementPackager.cs147
-rw-r--r--Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs401
-rw-r--r--Xamarin.Forms.Platform.WinRT/VisualElementTracker.cs534
-rw-r--r--Xamarin.Forms.Platform.WinRT/WebViewRenderer.cs174
-rw-r--r--Xamarin.Forms.Platform.WinRT/WindowsBasePage.cs56
-rw-r--r--Xamarin.Forms.Platform.WinRT/WindowsBasePlatformServices.cs179
-rw-r--r--Xamarin.Forms.Platform.WinRT/WindowsDeviceInfo.cs110
-rw-r--r--Xamarin.Forms.Platform.WinRT/WindowsExpressionSearch.cs170
-rw-r--r--Xamarin.Forms.Platform.WinRT/WindowsIsolatedStorage.cs119
-rw-r--r--Xamarin.Forms.Platform.WinRT/WindowsSerializer.cs60
-rw-r--r--Xamarin.Forms.Platform.WinRT/WindowsTicker.cs32
-rw-r--r--Xamarin.Forms.Platform.WinRT/Xamarin.Forms.Platform.WinRT.csproj179
-rw-r--r--Xamarin.Forms.Platform.iOS/CADisplayLinkTicker.cs73
-rw-r--r--Xamarin.Forms.Platform.iOS/Cells/CellRenderer.cs77
-rw-r--r--Xamarin.Forms.Platform.iOS/Cells/CellTableViewCell.cs96
-rw-r--r--Xamarin.Forms.Platform.iOS/Cells/EntryCellRenderer.cs186
-rw-r--r--Xamarin.Forms.Platform.iOS/Cells/ImageCellRenderer.cs70
-rw-r--r--Xamarin.Forms.Platform.iOS/Cells/SwitchCellRenderer.cs94
-rw-r--r--Xamarin.Forms.Platform.iOS/Cells/TextCellRenderer.cs73
-rw-r--r--Xamarin.Forms.Platform.iOS/Cells/ViewCellRenderer.cs176
-rw-r--r--Xamarin.Forms.Platform.iOS/ContextActionCell.cs715
-rw-r--r--Xamarin.Forms.Platform.iOS/ContextScrollViewDelegate.cs298
-rw-r--r--Xamarin.Forms.Platform.iOS/Deserializer.cs89
-rw-r--r--Xamarin.Forms.Platform.iOS/ElementChangedEventArgs.cs24
-rw-r--r--Xamarin.Forms.Platform.iOS/EventTracker.cs303
-rw-r--r--Xamarin.Forms.Platform.iOS/ExportCellAttribute.cs12
-rw-r--r--Xamarin.Forms.Platform.iOS/ExportImageSourceHandlerAttribute.cs12
-rw-r--r--Xamarin.Forms.Platform.iOS/ExportRendererAttribute.cs29
-rw-r--r--Xamarin.Forms.Platform.iOS/Extensions/ArrayExtensions.cs38
-rw-r--r--Xamarin.Forms.Platform.iOS/Extensions/CellExtensions.cs41
-rw-r--r--Xamarin.Forms.Platform.iOS/Extensions/ColorExtensions.cs99
-rw-r--r--Xamarin.Forms.Platform.iOS/Extensions/DateExtensions.cs33
-rw-r--r--Xamarin.Forms.Platform.iOS/Extensions/Extensions.cs76
-rw-r--r--Xamarin.Forms.Platform.iOS/Extensions/ToolbarItemExtensions.cs228
-rw-r--r--Xamarin.Forms.Platform.iOS/Extensions/UIViewExtensions.cs66
-rw-r--r--Xamarin.Forms.Platform.iOS/Extensions/ViewExtensions.cs20
-rw-r--r--Xamarin.Forms.Platform.iOS/Forms.cs373
-rw-r--r--Xamarin.Forms.Platform.iOS/FormsApplicationDelegate.cs151
-rw-r--r--Xamarin.Forms.Platform.iOS/GlobalCloseContextGestureRecognizer.cs72
-rw-r--r--Xamarin.Forms.Platform.iOS/IVisualElementRenderer.cs27
-rw-r--r--Xamarin.Forms.Platform.iOS/LayoutExtensions.cs36
-rw-r--r--Xamarin.Forms.Platform.iOS/NativeViewWrapper.cs35
-rw-r--r--Xamarin.Forms.Platform.iOS/NativeViewWrapperRenderer.cs72
-rw-r--r--Xamarin.Forms.Platform.iOS/PageExtensions.cs33
-rw-r--r--Xamarin.Forms.Platform.iOS/Platform.cs505
-rw-r--r--Xamarin.Forms.Platform.iOS/PlatformEffect.cs14
-rw-r--r--Xamarin.Forms.Platform.iOS/PlatformRenderer.cs85
-rw-r--r--Xamarin.Forms.Platform.iOS/Properties/AssemblyInfo.cs69
-rw-r--r--Xamarin.Forms.Platform.iOS/RendererFactory.cs13
-rw-r--r--Xamarin.Forms.Platform.iOS/RendererPool.cs154
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/ActivityIndicatorRenderer.cs53
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/AlignmentExtensions.cs25
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/BoxRenderer.cs78
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/ButtonRenderer.cs190
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/CarouselPageRenderer.cs395
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/CarouselViewRenderer.cs454
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/DatePickerRenderer.cs122
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/EditorRenderer.cs159
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs184
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/ExportCellAttribute.cs11
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/ExportImageSourceHandlerAttribute.cs11
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/ExportRendererAttribute.cs30
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/FontExtensions.cs205
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/FormattedStringExtensions.cs82
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/FrameRenderer.cs61
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/ImageRenderer.cs209
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/KeyboardInsetTracker.cs109
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/KeyboardObserver.cs37
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/LabelRenderer.cs183
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs1119
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/NavigationMenuRenderer.cs152
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/NavigationRenderer.cs918
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/OpenGLViewRenderer.cs122
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/PageRenderer.cs218
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/PhoneMasterDetailRenderer.cs401
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/PickerRenderer.cs180
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/ProgressBarRenderer.cs67
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/ScrollViewRenderer.cs246
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/SearchBarRenderer.cs249
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/SliderRenderer.cs99
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/StepperRenderer.cs82
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/SwitchRenderer.cs52
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/TabbedRenderer.cs311
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/TableViewModelRenderer.cs157
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/TableViewRenderer.cs150
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/TabletMasterDetailRenderer.cs371
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/TimePickerRenderer.cs104
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/ToolbarRenderer.cs66
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/WebViewRenderer.cs270
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.Designer.cs81
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.ar.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.ca.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.cs.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.da.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.de.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.el.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.es.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.fi.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.fr.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.he.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.hi.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.hr.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.hu.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.id.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.it.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.ja.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.ko.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.ms.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.nb.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.nl.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.pl.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.pt-BR.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.pt.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.ro.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.ru.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.sk.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.sv.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.th.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.tr.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.uk.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.vi.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.zh-HK.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.zh-Hans.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/Resources/StringResources.zh-Hant.resx128
-rw-r--r--Xamarin.Forms.Platform.iOS/ResourcesProvider.cs72
-rw-r--r--Xamarin.Forms.Platform.iOS/ViewInitializedEventArgs.cs17
-rw-r--r--Xamarin.Forms.Platform.iOS/ViewRenderer.cs151
-rw-r--r--Xamarin.Forms.Platform.iOS/VisualElementPackager.cs179
-rw-r--r--Xamarin.Forms.Platform.iOS/VisualElementRenderer.cs273
-rw-r--r--Xamarin.Forms.Platform.iOS/VisualElementTracker.cs259
-rw-r--r--Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS.Classic.csproj257
-rw-r--r--Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS.csproj191
-rw-r--r--Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS.nuspec14
-rw-r--r--Xamarin.Forms.Platform/Properties/AssemblyInfo.cs32
-rw-r--r--Xamarin.Forms.Platform/Xamarin.Forms.Platform.cs125
-rw-r--r--Xamarin.Forms.Platform/Xamarin.Forms.Platform.csproj57
-rw-r--r--Xamarin.Forms.UITest.TestCloud/App.config6
-rw-r--r--Xamarin.Forms.UITest.TestCloud/DeviceSet.cs28
-rw-r--r--Xamarin.Forms.UITest.TestCloud/DeviceSets.cs154
-rw-r--r--Xamarin.Forms.UITest.TestCloud/LoaderActions.cs41
-rw-r--r--Xamarin.Forms.UITest.TestCloud/Mono.Options/ArgumentSource.cs78
-rw-r--r--Xamarin.Forms.UITest.TestCloud/Mono.Options/Option.cs221
-rw-r--r--Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionAction.cs4
-rw-r--r--Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionContext.cs21
-rw-r--r--Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionException.cs41
-rw-r--r--Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionSet.cs718
-rw-r--r--Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionValueCollection.cs182
-rw-r--r--Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionValueType.cs9
-rw-r--r--Xamarin.Forms.UITest.TestCloud/Mono.Options/ResponseFileSource.cs25
-rw-r--r--Xamarin.Forms.UITest.TestCloud/Mono.Options/StringCoda.cs237
-rw-r--r--Xamarin.Forms.UITest.TestCloud/Properties/AssemblyInfo.cs39
-rw-r--r--Xamarin.Forms.UITest.TestCloud/TestCloudUtils.cs82
-rw-r--r--Xamarin.Forms.UITest.TestCloud/Uploader.cs409
-rw-r--r--Xamarin.Forms.UITest.TestCloud/Xamarin.Forms.UITest.TestCloud.csproj156
-rw-r--r--Xamarin.Forms.UITest.TestCloud/packages.config5
-rw-r--r--Xamarin.Forms.UITest.Validator/App.config6
-rw-r--r--Xamarin.Forms.UITest.Validator/DomMemberModel.cs56
-rw-r--r--Xamarin.Forms.UITest.Validator/DomTypeModel.cs154
-rw-r--r--Xamarin.Forms.UITest.Validator/FormsUITest.cs15
-rw-r--r--Xamarin.Forms.UITest.Validator/LoaderActions.cs59
-rw-r--r--Xamarin.Forms.UITest.Validator/Properties/AssemblyInfo.cs39
-rw-r--r--Xamarin.Forms.UITest.Validator/UITestCoverage/Css/styles.css206
-rw-r--r--Xamarin.Forms.UITest.Validator/UITestCoverage/Js/script.js6
-rw-r--r--Xamarin.Forms.UITest.Validator/Validator.cs68
-rw-r--r--Xamarin.Forms.UITest.Validator/Xamarin.Forms.UITest.Validator.csproj126
-rw-r--r--Xamarin.Forms.UITest.Validator/packages.config5
-rw-r--r--Xamarin.Forms.Xaml.Design/AttributeTableBuilder.cs14
-rw-r--r--Xamarin.Forms.Xaml.Design/Properties/AssemblyInfo.cs7
-rw-r--r--Xamarin.Forms.Xaml.Design/RegisterMetadata.cs9
-rw-r--r--Xamarin.Forms.Xaml.Design/Xamarin.Forms.Xaml.Design.csproj79
-rw-r--r--Xamarin.Forms.Xaml.Design/packages.config4
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Compiled/FindByName.xaml10
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Compiled/FindByName.xaml.cs40
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Compiled/SetValue.xaml71
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Compiled/SetValue.xaml.cs191
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/ConstraintExpression.xaml15
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/ConstraintExpression.xaml.cs72
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/CustomXamlView.xaml7
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/CustomXamlView.xaml.cs14
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/DataTemplate.xaml46
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/DataTemplate.xaml.cs123
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/DummyBuildEngine.cs47
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/DynamicResource.xaml6
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/DynamicResource.xaml.cs41
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml16
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml.cs116
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/FactoryMethodTests.cs53
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/FactoryMethods.xaml58
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/FactoryMethods.xaml.cs115
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/FontConverterTests.cs27
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/GenericCollections.xaml13
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/GenericCollections.xaml.cs47
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/GenericsTests.xaml21
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/GenericsTests.xaml.cs91
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/ImplicitConversions.xaml21
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/ImplicitConversions.xaml.cs42
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/IsCompiledDefault.xaml5
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/IsCompiledDefault.xaml.cs33
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/IsCompiledSkip.xaml5
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/IsCompiledSkip.xaml.cs33
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/BPNotResolvedOnSubClass.xaml15
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/BPNotResolvedOnSubClass.xaml.cs48
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz24485.xaml15
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz24485.xaml.cs55
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz24910.xaml14
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz24910.xaml.cs119
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz27299.xaml14
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz27299.xaml.cs58
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz27863.xaml20
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz27863.xaml.cs39
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz27968.xaml14
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz27968.xaml.cs38
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz28545.xaml18
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz28545.xaml.cs36
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz28556.xaml27
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz28556.xaml.cs58
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz28689.xaml13
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz28689.xaml.cs39
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz28719.xaml23
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz28719.xaml.cs55
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz29300.xaml9
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz29300.xaml.cs82
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz30074.xaml12
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz30074.xaml.cs41
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz30684.xaml15
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz30684.xaml.cs35
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/A/Bz31234.xaml7
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/A/Bz31234.xaml.cs33
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/B/Bz31234.xaml7
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/B/Bz31234.xaml.cs15
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz31529.xaml10
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz31529.xaml.cs33
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz34037.xaml37
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz34037.xaml.cs91
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz36422.xaml21
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz36422.xaml.cs37
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz37306.xaml12
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz37306.xaml.cs31
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz37524.xaml22
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz37524.xaml.cs33
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue01.xaml10
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue01.xaml.cs35
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue02.xaml18
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue02.xaml.cs63
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1199.xaml10
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1199.xaml.cs35
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1213.xaml15
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1213.xaml.cs34
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1250.xaml13
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1250.xaml.cs49
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1306.xaml6
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1306.xaml.cs41
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1415.xaml7
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1415.xaml.cs37
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1438.xaml15
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1438.xaml.cs46
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1493.cs26
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1497.cs27
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1501.cs41
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1545.cs174
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1549.cs166
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1554.cs53
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1564.cs29
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1594.cs43
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1637.cs25
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1641.cs38
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue1794.cs58
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2016.xaml25
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2016.xaml.cs50
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2062.xaml12
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2062.xaml.cs32
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2114.xaml20
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2114.xaml.cs46
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2125.xaml7
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2125.xaml.cs33
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2152.xaml15
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2152.xaml.cs52
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml10
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml.cs37
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2489.xaml17
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2489.xaml.cs53
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2578.xaml21
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2578.xaml.cs47
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2659.xaml34
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2659.xaml.cs131
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2742.xaml13
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue2742.xaml.cs45
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue3076.xaml11
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue3076.xaml.cs55
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue3090.xaml8
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue3090.xaml.cs30
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue3106.xaml35
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Issue3106.xaml.cs32
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Pr3384.xaml7
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Pr3384.xaml.cs39
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/TestCases.cs212
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Unreported001.xaml11
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Unreported001.xaml.cs42
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Unreported002.xaml7
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Unreported002.xaml.cs33
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Unreported003.xaml26
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Unreported003.xaml.cs31
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/LoaderTests.cs808
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/MarkupExpressionParserTests.cs326
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/MarkupExtensionTests.cs211
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/McIgnorable.xaml13
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/McIgnorable.xaml.cs29
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/NameScopeTests.cs110
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/NullExtensionTests.cs21
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/OnPlatform.xaml27
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/OnPlatform.xaml.cs46
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/OnPlatformTests.cs118
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Properties/AssemblyInfo.cs3
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Speed/SimpleContentPage.xaml8
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Speed/SimpleContentPage.xaml.cs89
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/StaticExtensionTests.cs72
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/StringLiterals.xaml15
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/StringLiterals.xaml.cs37
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/StyleTests.xaml36
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/StyleTests.xaml.cs117
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/TriggerTests.xaml12
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/TriggerTests.xaml.cs39
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/TypeConverterTests.xaml12
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/TypeConverterTests.xaml.cs39
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/TypeConverterTestsLegacy.cs258
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/TypeExtensionTests.cs54
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/TypeLoader.xaml11
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/TypeLoader.xaml.cs54
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Validation/SetterOnNonBP.xaml14
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Validation/SetterOnNonBP.xaml.cs34
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Validation/StaticExtensionException.xaml10
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Validation/StaticExtensionException.xaml.cs33
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Validation/TypeMismatch.xaml9
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Validation/TypeMismatch.xaml.cs32
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/ViewExtensionsTest.cs59
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/X2009Primitives.xaml42
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/X2009Primitives.xaml.cs233
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XArray.xaml12
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XArray.xaml.cs45
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XNull.xaml11
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XNull.xaml.cs32
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XReference.xaml37
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XReference.xaml.cs71
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XStatic.xaml14
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XStatic.xaml.cs65
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj608
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XamlC/FieldReferenceExtensionsTests.cs96
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XamlC/MethodReferenceExtensionsTests.cs92
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XamlC/PropertyDefinitionExtensionsTests.cs75
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XamlParseExceptionConstraint.cs67
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XamlgFileLockTests.cs43
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XamlgTests.cs300
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/app.config11
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/packages.config5
-rw-r--r--Xamarin.Forms.Xaml.Xamlc/Xamarin.Forms.Xaml.Xamlc.csproj59
-rw-r--r--Xamarin.Forms.Xaml.Xamlc/Xamlc.cs69
-rw-r--r--Xamarin.Forms.Xaml.Xamlg/Mono.Options/Options.cs1490
-rw-r--r--Xamarin.Forms.Xaml.Xamlg/Program.cs20
-rw-r--r--Xamarin.Forms.Xaml.Xamlg/Properties/AssemblyInfo.cs31
-rw-r--r--Xamarin.Forms.Xaml.Xamlg/Xamarin.Forms.Xaml.Xamlg.csproj65
-rw-r--r--Xamarin.Forms.Xaml.Xamlg/Xamlg.cs93
-rw-r--r--Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs439
-rw-r--r--Xamarin.Forms.Xaml/CreateValuesVisitor.cs369
-rw-r--r--Xamarin.Forms.Xaml/ExpandMarkupsVisitor.cs187
-rw-r--r--Xamarin.Forms.Xaml/FillResourceDictionariesVisitor.cs127
-rw-r--r--Xamarin.Forms.Xaml/HydratationContext.cs22
-rw-r--r--Xamarin.Forms.Xaml/IDictionaryExtensions.cs14
-rw-r--r--Xamarin.Forms.Xaml/IExpressionParser.cs15
-rw-r--r--Xamarin.Forms.Xaml/MarkupExpressionParser.cs227
-rw-r--r--Xamarin.Forms.Xaml/MarkupExtensionParser.cs80
-rw-r--r--Xamarin.Forms.Xaml/MarkupExtensions/ArrayExtension.cs39
-rw-r--r--Xamarin.Forms.Xaml/MarkupExtensions/BindingExtension.cs36
-rw-r--r--Xamarin.Forms.Xaml/MarkupExtensions/DynamicResourceExtension.cs27
-rw-r--r--Xamarin.Forms.Xaml/MarkupExtensions/NullExtension.cs12
-rw-r--r--Xamarin.Forms.Xaml/MarkupExtensions/ReferenceExtension.cs39
-rw-r--r--Xamarin.Forms.Xaml/MarkupExtensions/StaticExtension.cs50
-rw-r--r--Xamarin.Forms.Xaml/MarkupExtensions/StaticResourceExtension.cs44
-rw-r--r--Xamarin.Forms.Xaml/MarkupExtensions/TemplateBindingExtension.cs34
-rw-r--r--Xamarin.Forms.Xaml/MarkupExtensions/TypeExtension.cs26
-rw-r--r--Xamarin.Forms.Xaml/NamescopingVisitor.cs79
-rw-r--r--Xamarin.Forms.Xaml/Properties/AssemblyInfo.cs25
-rw-r--r--Xamarin.Forms.Xaml/RegisterXNamesVisitor.cs72
-rw-r--r--Xamarin.Forms.Xaml/TypeArgumentsParser.cs54
-rw-r--r--Xamarin.Forms.Xaml/TypeConversionExtensions.cs162
-rw-r--r--Xamarin.Forms.Xaml/ValueConverterProvider.cs13
-rw-r--r--Xamarin.Forms.Xaml/ViewExtensions.cs46
-rw-r--r--Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.csproj92
-rw-r--r--Xamarin.Forms.Xaml/XamlCompilationAttribute.cs41
-rw-r--r--Xamarin.Forms.Xaml/XamlLoader.cs208
-rw-r--r--Xamarin.Forms.Xaml/XamlNode.cs234
-rw-r--r--Xamarin.Forms.Xaml/XamlNodeVisitor.cs62
-rw-r--r--Xamarin.Forms.Xaml/XamlParser.cs349
-rw-r--r--Xamarin.Forms.Xaml/XamlServiceProvider.cs309
-rw-r--r--Xamarin.Forms.Xaml/XmlName.cs58
-rw-r--r--Xamarin.Forms.Xaml/XmlnsHelper.cs56
-rw-r--r--Xamarin.Forms.iOS.UITests/Device.cs21
-rw-r--r--Xamarin.Forms.iOS.UITests/Legacy-BaseTestFixture.cs113
-rw-r--r--Xamarin.Forms.iOS.UITests/Legacy-PlatformHelpers.cs135
-rw-r--r--Xamarin.Forms.iOS.UITests/Makefile15
-rw-r--r--Xamarin.Forms.iOS.UITests/PlatformQueries.cs118
-rw-r--r--Xamarin.Forms.iOS.UITests/Properties/AssemblyInfo.cs36
-rw-r--r--Xamarin.Forms.iOS.UITests/TestHelpers.cs34
-rw-r--r--Xamarin.Forms.iOS.UITests/Xamarin.Forms.iOS.UITests.csproj82
-rw-r--r--Xamarin.Forms.iOS.UITests/packages.config5
-rw-r--r--Xamarin.Forms.sln1532
-rw-r--r--Xamarin.Forms.sln.DotSettings670
-rw-r--r--docs/APIDocs.projitems14
-rw-r--r--docs/APIDocs.shproj12
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/DynamicResource.xml53
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/IDataTemplate.xml38
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/IDynamicResourceHandler.xml38
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/INameScope.xml103
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/NameScope.xml183
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IMarkupExtension.xml72
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IMarkupExtension`1.xml49
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IProvideValueTarget.xml65
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IRootObjectProvider.xml43
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IValueProvider.xml37
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IXamlTypeResolver.xml97
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IXmlLineInfoProvider.xml33
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/XamlParseException.xml59
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/XmlLineInfo.xml108
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/AbsoluteLayout+IAbsoluteList`1.xml98
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/AbsoluteLayout.xml653
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/AbsoluteLayoutFlags.xml191
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ActivityIndicator.xml177
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Animation.xml285
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/AnimationExtensions.xml313
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Application.xml314
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Aspect.xml86
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BackButtonPressedEventArgs.xml56
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BaseMenuItem.xml37
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Behavior.xml130
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Behavior`1.xml136
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindableObject.xml748
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindableObjectExtensions.xml161
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangedDelegate.xml32
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangedDelegate`1.xml40
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangingDelegate.xml32
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangingDelegate`1.xml40
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CoerceValueDelegate.xml31
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CoerceValueDelegate`1.xml35
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CreateDefaultValueDelegate.xml26
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CreateDefaultValueDelegate`2.xml40
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+ValidateValueDelegate.xml31
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+ValidateValueDelegate`1.xml39
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty.xml904
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindablePropertyConverter.xml148
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindablePropertyKey.xml65
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Binding.xml320
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindingBase.xml172
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindingCondition.xml102
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindingMode.xml149
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BindingTypeConverter.xml117
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BoundsConstraint.xml52
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BoundsTypeConverter.xml117
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/BoxView.xml179
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Button.xml719
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/CarouselPage.xml134
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/CarouselView.xml230
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Cell.xml508
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/CollectionSynchronizationCallback.xml34
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Color.xml1221
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ColorTypeConverter.xml133
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ColumnDefinition.xml135
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ColumnDefinitionCollection.xml57
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Command.xml249
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Command`1.xml90
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Condition.xml21
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Constraint.xml135
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ConstraintExpression.xml222
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ConstraintType.xml83
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ConstraintTypeConverter.xml117
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ContentPage.xml146
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ContentPresenter.xml114
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ContentPropertyAttribute.xml94
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ContentView.xml192
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ControlTemplate.xml47
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/DataTemplate.xml351
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/DataTemplateSelector.xml121
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/DataTrigger.xml161
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/DateChangedEventArgs.xml92
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/DatePicker.xml319
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/DefinitionCollection`1.xml392
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/DependencyAttribute.xml51
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/DependencyFetchTarget.xml70
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/DependencyService.xml119
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Device+Styles.xml237
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Device.xml289
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Easing.xml495
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Editor.xml300
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Effect.xml130
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Element.xml885
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ElementEventArgs.xml75
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ElementTemplate.xml55
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Entry.xml496
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/EntryCell.xml474
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/EventTrigger.xml142
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ExportEffectAttribute.xml65
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/FileImageSource.xml187
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/FileImageSourceConverter.xml97
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/FocusEventArgs.xml97
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Font.xml591
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/FontAttributes.xml80
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/FontSizeConverter.xml162
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/FontTypeConverter.xml117
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/FormattedString.xml157
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Frame.xml181
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/GestureRecognizer.xml69
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/GestureState.xml143
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/GestureStatus.xml78
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Grid+IGridList`1.xml204
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Grid.xml1002
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/GridLength.xml316
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/GridLengthTypeConverter.xml131
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/GridUnitType.xml86
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/HandlerAttribute.xml76
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/HtmlWebViewSource.xml129
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IAnimatable.xml65
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IApplicationController.xml34
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IAttachedObject.xml71
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ICarouselViewController.xml95
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IDefinition.xml47
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IEffectControlProvider.xml34
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IElementController.xml82
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IExtendedTypeConverter.xml68
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IGestureRecognizer.xml24
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IItemViewController.xml96
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ILayout.xml42
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ILayoutController.xml37
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/INativeElementView.xml33
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/INavigation.xml389
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IOpenGLViewController.xml36
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IPageContainer`1.xml52
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IPlatform.xml123
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IPlatformEngine.xml70
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IRegisterable.xml20
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IScrollViewController.xml104
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IValueConverter.xml85
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IViewContainer`1.xml53
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IViewController.xml21
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/IVisualElementController.xml41
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Image.xml364
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ImageCell.xml177
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ImageSource.xml382
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ImageSourceConverter.xml98
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/InputView.xml69
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ItemTappedEventArgs.xml92
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ItemVisibilityEventArgs.xml71
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ItemsView.xml206
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ItemsView`1.xml338
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Keyboard.xml209
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/KeyboardFlags.xml108
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/KeyboardTypeConverter.xml141
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Label.xml663
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Layout.xml563
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/LayoutAlignment.xml108
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/LayoutOptions.xml265
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/LayoutOptionsConverter.xml97
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Layout`1.xml213
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/LineBreakMode.xml143
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ListView.xml1531
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ListViewCachingStrategy.xml64
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/MasterBehavior.xml105
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/MasterDetailPage.xml466
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/MeasureFlags.xml50
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/MenuItem.xml297
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/MessagingCenter.xml263
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ModalEventArgs.xml59
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPoppedEventArgs.xml40
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPoppingEventArgs.xml59
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPushedEventArgs.xml40
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPushingEventArgs.xml40
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/MultiPage`1.xml599
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/MultiTrigger.xml109
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/NameScopeExtensions.xml56
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/NamedSize.xml120
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/NavigationEventArgs.xml78
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/NavigationMenu.xml90
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/NavigationPage.xml815
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/OnIdiom`1.xml127
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/OnPlatform`1.xml139
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/OpenGLView.xml221
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Page.xml875
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/PanGestureRecognizer.xml82
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/PanUpdatedEventArgs.xml129
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Picker.xml294
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/PinchGestureRecognizer.xml49
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/PinchGestureUpdatedEventArgs.xml117
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/PlatformEffect`2.xml103
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Point.xml459
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/PointTypeConverter.xml117
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ProgressBar.xml156
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/PropertyChangingEventArgs.xml68
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/PropertyChangingEventHandler.xml30
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/PropertyCondition.xml122
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Rectangle.xml935
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/RectangleTypeConverter.xml117
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/RelativeLayout+IRelativeList`1.xml132
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/RelativeLayout.xml513
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/RenderWithAttribute.xml64
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ResolutionGroupNameAttribute.xml62
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ResourceDictionary.xml473
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/RoutingEffect.xml66
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/RowDefinition.xml135
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/RowDefinitionCollection.xml46
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollOrientation.xml77
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollToMode.xml51
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollToPosition.xml88
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollToRequestedEventArgs.xml128
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollView.xml485
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ScrolledEventArgs.xml76
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/SearchBar.xml588
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/SelectedItemChangedEventArgs.xml68
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/SelectedPositionChangedEventArgs.xml50
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/SeparatorVisibility.xml54
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Setter.xml131
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/SettersExtensions.xml101
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Size.xml425
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/SizeRequest.xml144
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Slider.xml320
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Span.xml214
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/StackLayout.xml357
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/StackOrientation.xml64
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Stepper.xml371
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/StreamImageSource.xml114
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Style.xml259
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Switch.xml193
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/SwitchCell.xml230
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TabbedPage.xml211
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TableIntent.xml103
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TableRoot.xml68
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TableSection.xml68
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TableSectionBase.xml125
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TableSectionBase`1.xml504
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TableView.xml353
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TapGestureRecognizer.xml361
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TappedEventArgs.xml68
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TargetIdiom.xml104
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TargetPlatform.xml120
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TemplateBinding.xml112
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TemplateExtensions.xml53
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TemplatedPage.xml62
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TemplatedView.xml114
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TextAlignment.xml83
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TextCell.xml382
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TextChangedEventArgs.xml92
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Thickness.xml402
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ThicknessTypeConverter.xml117
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TimePicker.xml150
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ToggledEventArgs.xml68
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ToolbarItem.xml303
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ToolbarItemOrder.xml83
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Trigger.xml135
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TriggerAction.xml80
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TriggerAction`1.xml93
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TriggerBase.xml147
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TypeConverter.xml158
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TypeConverterAttribute.xml184
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/TypeTypeConverter.xml154
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/UnsolvableConstraintsException.xml46
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/UriImageSource.xml135
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/UriTypeConverter.xml117
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/UrlWebViewSource.xml86
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ValueChangedEventArgs.xml92
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/Vec2.xml90
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/View.xml290
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ViewCell.xml74
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ViewExtensions.xml338
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ViewState.xml88
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/VisualElement.xml1913
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigatedEventArgs.xml65
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigatingEventArgs.xml63
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigationEvent.xml88
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigationEventArgs.xml101
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigationResult.xml88
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/WebView.xml381
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/WebViewSource.xml117
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/WebViewSourceTypeConverter.xml117
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/AbsoluteLayout.TripleScreenShot.pngbin0 -> 113629 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ActivityIndicator.TripleScreenShot.pngbin0 -> 93364 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/BindableObject.BasicInitialization.pngbin0 -> 35696 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/BoxView.TripleScreenShot.pngbin0 -> 100377 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Button.TripleScreenShot.pngbin0 -> 105470 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/CarouselPage.TripleScreenShot.pngbin0 -> 125916 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Cell.Gallery.pngbin0 -> 54001 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ContentView.TripleScreenShot.pngbin0 -> 173506 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/DatePicker.TripleScreenShot.pngbin0 -> 119226 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.BounceIn.pngbin0 -> 8980 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.BounceOut.pngbin0 -> 8936 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.CubicIn.pngbin0 -> 7360 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.CubicInOut.pngbin0 -> 7633 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.CubicOut.pngbin0 -> 7689 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.Linear.pngbin0 -> 7881 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SinIn.gifbin0 -> 2661 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SinInOut.gifbin0 -> 2654 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SinOut.gifbin0 -> 2692 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SpringIn.pngbin0 -> 7782 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SpringOut.pngbin0 -> 7897 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Editor.TripleScreenShot.pngbin0 -> 139540 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Element.Hierarchy.pngbin0 -> 48554 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Entry.TripleScreenShot.pngbin0 -> 135737 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/EntryCell.TripleScreenShot.pngbin0 -> 138987 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Frame.TripleScreenShot.pngbin0 -> 101698 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Grid.TripleScreenShot.pngbin0 -> 108346 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/IDefinition.DefinitionCollectionRelation.pngbin0 -> 11555 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ImageCell.TripleScreenShot.pngbin0 -> 103061 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Label.TripleScreenShot.pngbin0 -> 131227 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Layout.Hierarchy.pngbin0 -> 48565 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ListView.TripleScreenShot.pngbin0 -> 134960 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/NavigationPage.TitleIcon.pngbin0 -> 14483 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/OpenGLView.Example.pngbin0 -> 45020 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Picker.TripleScreenShot.pngbin0 -> 114990 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ProgressBar.TripleScreenShot.pngbin0 -> 93154 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ScrollView.TripleScreenShot.pngbin0 -> 212772 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/SearchBar.TripleScreenShot.pngbin0 -> 129248 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Slider.TripleScreenShot.pngbin0 -> 94643 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/StackLayout.TripleScreenShot.pngbin0 -> 149122 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Stepper.TripleScreenShot.pngbin0 -> 96494 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Switch.TripleScreenShot.pngbin0 -> 95616 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/SwitchCell.TripleScreenShot.pngbin0 -> 98935 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TabbedPage.TripleScreenShot.pngbin0 -> 111211 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableSectionBase.Hierarchy.pngbin0 -> 10074 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableView.Sections.Android.pngbin0 -> 311961 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableView.Sections.iOS.pngbin0 -> 184334 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableView.TripleScreenShot.pngbin0 -> 122346 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TextCell.TripleScreenShot.pngbin0 -> 98397 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TimePicker.TripleScreenShot.pngbin0 -> 101107 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TypeConverter.Hierarchy.pngbin0 -> 14293 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/WebView.TripleScreenShot.pngbin0 -> 165146 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/XamarinForms-ns.SharedProject.pngbin0 -> 37833 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/XamarinForms-ns.SolutionPad.pngbin0 -> 13352 bytes
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/_images/XamarinForms-ns.TripleScreenShot.pngbin0 -> 414685 bytes
-rw-r--r--docs/Xamarin.Forms.Core/index.xml1079
-rw-r--r--docs/Xamarin.Forms.Core/ns-.xml6
-rw-r--r--docs/Xamarin.Forms.Core/ns-Xamarin.Forms.Internals.xml6
-rw-r--r--docs/Xamarin.Forms.Core/ns-Xamarin.Forms.Xaml.xml6
-rw-r--r--docs/Xamarin.Forms.Core/ns-Xamarin.Forms.xml103
-rw-r--r--docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Distance.xml312
-rw-r--r--docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Geocoder.xml91
-rw-r--r--docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Map.xml363
-rw-r--r--docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/MapSpan.xml315
-rw-r--r--docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/MapType.xml79
-rw-r--r--docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Pin.xml333
-rw-r--r--docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/PinType.xml98
-rw-r--r--docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Position.xml192
-rw-r--r--docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/_images/Pin.Label.pngbin0 -> 699333 bytes
-rw-r--r--docs/Xamarin.Forms.Maps/index.xml98
-rw-r--r--docs/Xamarin.Forms.Maps/ns-Xamarin.Forms.Maps.xml59
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/NameScopeProvider.xml50
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/SimpleValueTargetProvider.xml70
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XamlServiceProvider.xml80
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XamlTypeResolver.xml88
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XmlLineInfoProvider.xml57
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XmlNamespaceResolver.xml122
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/ArrayExtension.xml177
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/BindingExtension.xml196
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/DynamicResourceExtension.xml130
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/Extensions.xml60
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/NullExtension.xml70
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/ReferenceExtension.xml96
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/StaticExtension.xml96
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/StaticResourceExtension.xml84
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/TemplateBindingExtension.xml160
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/TypeExtension.xml137
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XamlCompilationAttribute.xml58
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XamlCompilationOptions.xml56
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XamlParseException.xml19
-rw-r--r--docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XmlLineInfo.xml96
-rw-r--r--docs/Xamarin.Forms.Xaml/index.xml118
-rw-r--r--docs/Xamarin.Forms.Xaml/ns-Xamarin.Forms.Xaml.Internals.xml6
-rw-r--r--docs/Xamarin.Forms.Xaml/ns-Xamarin.Forms.Xaml.xml6
-rw-r--r--update-docs-windows.bat29
-rw-r--r--verify-nuspecs.ps1130
2604 files changed, 293360 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..3400ba98
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,14 @@
+# Set default behaviour, in case users don't have core.autocrlf set.
+* text=auto
+
+# Explicitly declare text files we want to always be normalized and converted
+# to native line endings on checkout.
+*.cs text
+
+# Declare files that will always have CRLF line endings on checkout.
+*.sln text eol=crlf
+
+# Denote all files that are truly binary and should not be modified.
+*.png binary
+*.jpg binary
+*.jpeg binary \ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..862be784
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,46 @@
+bin
+obj
+classic_bin
+classic_obj
+*.dll
+*.mdb
+*.exe
+*.log
+*.userprefs
+*.suo
+UpgradeLog*
+*UpgradeReport*
+*.user
+*.DS_Store
+*.ide
+.vs
+*.designer.cs
+*project.lock.json
+!*ControlResources*.designer.cs
+!*Resources.Designer.cs
+!Xamarin.Forms.VSTemplate/**/*.designer.cs
+!NuGet.exe
+*test-results*
+*/PerfLogs/*
+*.sap
+/packages
+!.xamarin-component/**
+*.xam
+Components/
+!GooglePlayServices/**
+.irb-history
+screenshot_*
+!Xamarin.Forms.Addin/libs/**
+!Xamarin.Forms.Addin/Packages/Xamarin.Forms.*.nupkg
+*.remove
+*/.metadata/*
+AndroidNative/FormsViewGroup/gen/com/xamarin/formsviewgroup/R.java
+AndroidNative/FormsViewGroup/gen/com/xamarin/formsviewgroup/BuildConfig.java
+*.psess
+TestResults/
+Xamarin.Forms.UITest.Validator/UITestCoverage/index.html
+!Xamarin.Forms.UITest.TestCloud/test-cloud.exe
+Xamarin.Forms.ControlGallery.Windows/AppPackages/
+Xamarin.Forms.ControlGallery.WindowsPhone/AppPackages/
+Xamarin.Forms.Controls/secrets.txt
+Xamarin.Forms.ControlGallery.Android/Properties/MapsKey.cs \ No newline at end of file
diff --git a/.nuget/NuGet.Config b/.nuget/NuGet.Config
new file mode 100644
index 00000000..6efc7f7b
--- /dev/null
+++ b/.nuget/NuGet.Config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <solution>
+ <add key="disableSourceControlIntegration" value="true" />
+ </solution>
+</configuration>
diff --git a/.nuget/NuGet.exe b/.nuget/NuGet.exe
new file mode 100644
index 00000000..cb3ed036
--- /dev/null
+++ b/.nuget/NuGet.exe
Binary files differ
diff --git a/.nuget/NuGet.targets b/.nuget/NuGet.targets
new file mode 100644
index 00000000..52824106
--- /dev/null
+++ b/.nuget/NuGet.targets
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
+
+ <!-- Enable the restore command to run before builds -->
+ <RestorePackages Condition=" '$(RestorePackages)' == '' ">false</RestorePackages>
+
+ <!-- Property that enables building a package from a project -->
+ <BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>
+
+ <!-- Determines if package restore consent is required to restore packages -->
+ <RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>
+
+ <!-- Download NuGet.exe if it does not already exist -->
+ <DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
+ </PropertyGroup>
+
+ <ItemGroup Condition=" '$(PackageSources)' == '' ">
+ <!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
+ <!-- The official NuGet package source (https://nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
+ <!--
+ <PackageSource Include="https://nuget.org/api/v2/" />
+ <PackageSource Include="https://my-nuget-source/nuget/" />
+ -->
+ </ItemGroup>
+
+ <PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
+ <!-- Windows specific commands -->
+ <NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
+ <PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
+ </PropertyGroup>
+
+ <PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
+ <!-- We need to launch nuget.exe with the mono command if we're not on windows -->
+ <NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
+ <PackagesConfig>packages.config</PackagesConfig>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <!-- NuGet command -->
+ <NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\NuGet.exe</NuGetExePath>
+ <PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
+
+ <NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
+ <NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>
+
+ <PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
+
+ <RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' "></RequireConsentSwitch>
+ <NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch>
+
+ <!-- Commands -->
+ <RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir "$(SolutionDir)\" </RestoreCommand>
+ <BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties Configuration=$(Configuration) $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>
+
+ <!-- We need to ensure packages are restored prior to assembly resolve -->
+ <BuildDependsOn Condition="$(RestorePackages) == 'true'">
+ RestorePackages;
+ $(BuildDependsOn);
+ </BuildDependsOn>
+
+ <!-- Make the build depend on restore packages -->
+ <BuildDependsOn Condition="$(BuildPackage) == 'true'">
+ $(BuildDependsOn);
+ BuildPackage;
+ </BuildDependsOn>
+ </PropertyGroup>
+
+ <Target Name="CheckPrerequisites">
+ <!-- Raise an error if we're unable to locate nuget.exe -->
+ <Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
+ <!--
+ Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
+ This effectively acts as a lock that makes sure that the download operation will only happen once and all
+ parallel builds will have to wait for it to complete.
+ -->
+ <MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT;DownloadNuGetExe=$(DownloadNuGetExe)" />
+ </Target>
+
+ <Target Name="_DownloadNuGet">
+ <DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
+ </Target>
+
+ <Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
+ <Exec Command="$(RestoreCommand)"
+ Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
+
+ <Exec Command="$(RestoreCommand)"
+ LogStandardErrorAsError="true"
+ Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
+ </Target>
+
+ <Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
+ <Exec Command="$(BuildCommand)"
+ Condition=" '$(OS)' != 'Windows_NT' " />
+
+ <Exec Command="$(BuildCommand)"
+ LogStandardErrorAsError="true"
+ Condition=" '$(OS)' == 'Windows_NT' " />
+ </Target>
+
+ <UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
+ <ParameterGroup>
+ <OutputFilename ParameterType="System.String" Required="true" />
+ </ParameterGroup>
+ <Task>
+ <Reference Include="System.Core" />
+ <Using Namespace="System" />
+ <Using Namespace="System.IO" />
+ <Using Namespace="System.Net" />
+ <Using Namespace="Microsoft.Build.Framework" />
+ <Using Namespace="Microsoft.Build.Utilities" />
+ <Code Type="Fragment" Language="cs">
+ <![CDATA[
+ try {
+ OutputFilename = Path.GetFullPath(OutputFilename);
+
+ Log.LogMessage("Downloading latest version of NuGet.exe...");
+ WebClient webClient = new WebClient();
+ webClient.DownloadFile("https://nuget.org/nuget.exe", OutputFilename);
+
+ return true;
+ }
+ catch (Exception ex) {
+ Log.LogErrorFromException(ex);
+ return false;
+ }
+ ]]>
+ </Code>
+ </Task>
+ </UsingTask>
+</Project>
diff --git a/.nuget/packages.config b/.nuget/packages.config
new file mode 100644
index 00000000..7025a729
--- /dev/null
+++ b/.nuget/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit.Runners" version="2.6.3" />
+</packages> \ No newline at end of file
diff --git a/.nuspec/Xamarin.Forms.Debug.targets b/.nuspec/Xamarin.Forms.Debug.targets
new file mode 100644
index 00000000..c3d21c23
--- /dev/null
+++ b/.nuspec/Xamarin.Forms.Debug.targets
@@ -0,0 +1,80 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <UsingTask TaskName="Xamarin.Forms.Build.Tasks.XamlGTask" AssemblyFile="Xamarin.Forms.Build.Tasks.dll"/>
+ <UsingTask TaskName="Xamarin.Forms.Build.Tasks.XamlCTask" AssemblyFile="Xamarin.Forms.Build.Tasks.dll"/>
+ <UsingTask TaskName="Xamarin.Forms.Build.Tasks.DebugXamlCTask" AssemblyFile="Xamarin.Forms.Build.Tasks.dll"/>
+ <UsingTask TaskName="Xamarin.Forms.Build.Tasks.FixedCreateCSharpManifestResourceName" AssemblyFile="Xamarin.Forms.Build.Tasks.dll"/>
+
+ <PropertyGroup>
+ <PrepareResourcesDependsOn>
+ XamlG;
+ $(PrepareResourcesDependsOn);
+ </PrepareResourcesDependsOn>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <CompileDependsOn>
+ $(CompileDependsOn);
+ GenerateDebugCode;
+ XamlC;
+ </CompileDependsOn>
+ </PropertyGroup>
+
+ <Target Name="UpdateDesignTimeXaml" Condition="'$(UseHostCompilerIfAvailable)' == 'true'" DependsOnTargets="PrepareResources; Compile"/>
+
+ <Target Name="XamlG" DependsOnTargets="$(XamlGDependsOn)"/>
+
+ <PropertyGroup>
+ <XamlGDependsOn>
+ _PreXamlG;
+ _CollectXamlFiles;
+ _CoreXamlG;
+ </XamlGDependsOn>
+ </PropertyGroup>
+
+ <Target Name="_PreXamlG">
+ <MakeDir Directories="$(IntermediateOutputPath)"/>
+ </Target>
+
+ <Target Name="_CollectXamlFiles">
+ <ItemGroup>
+ <_XamlResources Include="@(EmbeddedResource)" Condition="'%(Extension)' == '.xaml'"/>
+ </ItemGroup>
+ <FixedCreateCSharpManifestResourceName ResourceFiles="@(_XamlResources)" RootNamespace="$(RootNamespace)">
+ <Output TaskParameter="ResourceFilesWithManifestResourceNames" ItemName="XamlFiles" />
+ </FixedCreateCSharpManifestResourceName>
+ <ItemGroup>
+ <XamlGFiles Include="@(XamlFiles->'$(IntermediateOutputPath)%(ManifestResourceName).g$(DefaultLanguageSourceExtension)')"/>
+ <Compile Include="@(XamlGFiles)"/>
+ <FileWrites Include="@(XamlGFiles)"/>
+ </ItemGroup>
+ </Target>
+
+ <Target Name="_CoreXamlG"
+ Inputs = "@(XamlFiles)"
+ Outputs = "$(IntermediateOutputPath)%(ManifestResourceName).g$(DefaultLanguageSourceExtension)">
+ <XamlGTask
+ Source="@(XamlFiles)"
+ Language = "$(Language)"
+ AssemblyName = "$(AssemblyName)"
+ OutputFile = "$(IntermediateOutputPath)%(ManifestResourceName).g$(DefaultLanguageSourceExtension)">
+ </XamlGTask>
+ </Target>
+
+ <!-- duplicate legacy InitializeComponent, create a ctor with bool param -->
+ <Target Name="GenerateDebugCode">
+ <DebugXamlCTask
+ Assembly = "$(IntermediateOutputPath)$(TargetFileName)"
+ ReferencePath = "@(ReferencePath)"
+ DebugSymbols = "$(DebugSymbols)" />
+ </Target>
+
+ <Target Name="XamlC">
+ <XamlCTask
+ Assembly = "$(IntermediateOutputPath)$(TargetFileName)"
+ ReferencePath = "@(ReferencePath)"
+ DebugSymbols = "$(DebugSymbols)"
+ Verbosity = "4"
+ KeepXamlResources = "true"
+ OptimizeIL = "true" />
+ </Target>
+</Project>
diff --git a/.nuspec/Xamarin.Forms.Maps.nuspec b/.nuspec/Xamarin.Forms.Maps.nuspec
new file mode 100644
index 00000000..74806321
--- /dev/null
+++ b/.nuspec/Xamarin.Forms.Maps.nuspec
@@ -0,0 +1,135 @@
+<?xml version="1.0"?>
+<package >
+ <metadata>
+ <id>Xamarin.Forms.Maps$IdAppend$</id>
+ <version>$version$</version>
+ <authors>Xamarin, Inc.</authors>
+ <owners>Xamarin, Inc.</owners>
+ <tags>xamarin forms maps xamarinforms xamarinformsmaps xamarin.forms.maps</tags>
+ <licenseUrl>http://download.xamarin.com/content/licenses/Xamarin.Forms.rtf</licenseUrl>
+ <iconUrl>http://xamarin.com/content/images/nuget/xamarin.png</iconUrl>
+ <projectUrl>http://xamarin.com/forms</projectUrl>
+ <requireLicenseAcceptance>false</requireLicenseAcceptance>
+ <description>Maps models and renderers for Xamarin.Forms</description>
+ <copyright>Copyright 2013-2016</copyright>
+ <dependencies>
+ <group>
+ <dependency id="Xamarin.Forms$IdAppend$" version="$version$"/>
+ </group>
+ <group targetFramework="MonoAndroid10">
+ <dependency id="Xamarin.GooglePlayServices.Maps" version="[29.0.0.1]"/>
+ <dependency id="Xamarin.Android.Support.v7.MediaRouter" version="[23.1.1.1]"/>
+ <dependency id="Xamarin.Android.Support.v7.AppCompat" version="[23.1.1.1]"/>
+ <dependency id="Xamarin.Forms$IdAppend$" version="$version$"/>
+ </group>
+ </dependencies>
+ <references>
+ <group targetFramework="portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10">
+ <reference file="Xamarin.Forms.Maps.dll" />
+ </group>
+ <group targetFramework="Xamarin.iOS10">
+ <reference file="Xamarin.Forms.Maps.dll" />
+ <reference file="Xamarin.Forms.Maps.iOS.dll" />
+ </group>
+ <group targetFramework="MonoTouch10">
+ <reference file="Xamarin.Forms.Maps.dll" />
+ <reference file="Xamarin.Forms.Maps.iOS.Classic.dll" />
+ </group>
+ <group targetFramework="MonoAndroid10">
+ <reference file="Xamarin.Forms.Maps.dll" />
+ <reference file="Xamarin.Forms.Maps.Android.dll" />
+ </group>
+ <group targetFramework="win81">
+ <reference file="Xamarin.Forms.Maps.dll" />
+ </group>
+ <group targetFramework="wpa81">
+ <reference file="Xamarin.Forms.Maps.dll" />
+ <reference file="Xamarin.Forms.Maps.WinRT.Phone.dll" />
+ </group>
+ <group targetFramework="uap10.0">
+ <reference file="Xamarin.Forms.Maps.dll" />
+ <reference file="Xamarin.Forms.Maps.UWP.dll" />
+ </group>
+ <group targetFramework="WP80">
+ <reference file="Xamarin.Forms.Maps.dll" />
+ <reference file="Xamarin.Forms.Maps.WP8.dll" />
+ </group>
+ </references>
+ </metadata>
+ <files>
+ <file src="..\Xamarin.Forms.Maps\bin\$Configuration$\Xamarin.Forms.Maps.dll" target="lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\docs\Xamarin.Forms.Maps.xml" target="lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+
+ <file src="..\Xamarin.Forms.Maps.Android\bin\$Configuration$\Xamarin.Forms.Maps.Android.dll" target="lib\MonoAndroid10" />
+ <file src="..\Xamarin.Forms.Maps\bin\$Configuration$\Xamarin.Forms.Maps.dll" target="lib\MonoAndroid10" />
+ <file src="..\docs\Xamarin.Forms.Maps.xml" target="lib\MonoAndroid10" />
+
+ <file src="..\Xamarin.Forms.Maps.iOS\bin\iPhoneSimulator\$Configuration$\Xamarin.Forms.Maps.iOS.dll" target="lib\Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Maps\bin\$Configuration$\Xamarin.Forms.Maps.dll" target="lib\Xamarin.iOS10" />
+ <file src="..\docs\Xamarin.Forms.Maps.xml" target="lib\Xamarin.iOS10" />
+
+ <file src="..\Xamarin.Forms.Maps.iOS\classic_bin\iPhoneSimulator\$Configuration$\Xamarin.Forms.Maps.iOS.Classic.dll" target="lib\MonoTouch10" />
+ <file src="..\Xamarin.Forms.Maps\bin\$Configuration$\Xamarin.Forms.Maps.dll" target="lib\MonoTouch10" />
+ <file src="..\docs\Xamarin.Forms.Maps.xml" target="lib\MonoTouch10" />
+
+ <file src="..\Xamarin.Forms.Maps.WP8\bin\$Configuration$\Xamarin.Forms.Maps.WP8.dll" target="lib\WP80" />
+ <file src="..\Xamarin.Forms.Maps\bin\$Configuration$\Xamarin.Forms.Maps.dll" target="lib\WP80" />
+ <file src="..\docs\Xamarin.Forms.Maps.xml" target="lib\WP80" />
+
+ <!--UWP-->
+ <file src="..\Xamarin.Forms.Maps.UWP\bin\$Configuration$\Xamarin.Forms.Maps.UWP.dll" target="lib\uap10.0" />
+ <file src="..\Xamarin.Forms.Maps.UWP\bin\$Configuration$\Xamarin.Forms.Maps.UWP.pri" target="lib\uap10.0" />
+ <file src="..\Xamarin.Forms.Maps\bin\$Configuration$\Xamarin.Forms.Maps.dll" target="lib\uap10.0" />
+
+ <!--WinRT Phone-->
+ <file src="..\Xamarin.Forms.Maps.WinRT.Phone\bin\$Configuration$\Xamarin.Forms.Maps.WinRT.Phone.dll" target="lib\wpa81" />
+ <file src="..\Xamarin.Forms.Maps.WinRT.Phone\bin\$Configuration$\Xamarin.Forms.Maps.WinRT.Phone.pri" target="lib\wpa81" />
+ <file src="..\Xamarin.Forms.Maps\bin\$Configuration$\Xamarin.Forms.Maps.dll" target="lib\wpa81" />
+
+ <!--WinRT Tablet-->
+ <file src="Xamarin.Forms.Maps.targets" target="build\win81\Xamarin.Forms.Maps$IdAppend$.targets" />
+ <file src="Xamarin.Forms.Maps.props" target="build\win81\Xamarin.Forms.Maps$IdAppend$.props" />
+
+ <file src="..\Xamarin.Forms.Maps\bin\$Configuration$\Xamarin.Forms.Maps.dll" target="lib\win81" />
+ <file src="..\docs\Xamarin.Forms.Maps.xml" target="lib\win81" />
+
+ <file src="..\Xamarin.Forms.Maps.WinRT.Tablet\bin\x86\$Configuration$\Xamarin.Forms.Maps.WinRT.Tablet.dll" target="build\win81\x86" />
+ <file src="..\Xamarin.Forms.Maps.WinRT.Tablet\bin\x86\$Configuration$\Xamarin.Forms.Maps.WinRT.Tablet.pri" target="build\win81\x86" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\x86\$Configuration$\Xamarin.Forms.Platform.WinRT.Tablet.dll" target="build\win81\x86" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\x86\$Configuration$\Xamarin.Forms.Platform.WinRT.Tablet.pri" target="build\win81\x86" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\x86\$Configuration$\Xamarin.Forms.Platform.WinRT.Tablet.xr.xml" target="build\win81\x86\Xamarin.Forms.Platform.WinRT.Tablet" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\x86\$Configuration$\Resources.xbf" target="build\win81\x86\Xamarin.Forms.Platform.WinRT.Tablet" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\x86\$Configuration$\TabletResources.xbf" target="build\win81\x86\Xamarin.Forms.Platform.WinRT.Tablet" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\x86\$Configuration$\FormsTextBoxStyle.xbf" target="build\win81\x86\Xamarin.Forms.Platform.WinRT.Tablet" />
+
+ <file src="..\Xamarin.Forms.Maps.WinRT.Tablet\bin\x64\$Configuration$\Xamarin.Forms.Maps.WinRT.Tablet.dll" target="build\win81\x64" />
+ <file src="..\Xamarin.Forms.Maps.WinRT.Tablet\bin\x64\$Configuration$\Xamarin.Forms.Maps.WinRT.Tablet.pri" target="build\win81\x64" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\x64\$Configuration$\Xamarin.Forms.Platform.WinRT.Tablet.dll" target="build\win81\x64" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\x64\$Configuration$\Xamarin.Forms.Platform.WinRT.Tablet.pri" target="build\win81\x64" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\x64\$Configuration$\Xamarin.Forms.Platform.WinRT.Tablet.xr.xml" target="build\win81\x64\Xamarin.Forms.Platform.WinRT.Tablet" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\x64\$Configuration$\Resources.xbf" target="build\win81\x64\Xamarin.Forms.Platform.WinRT.Tablet" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\x64\$Configuration$\TabletResources.xbf" target="build\win81\x64\Xamarin.Forms.Platform.WinRT.Tablet" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\x64\$Configuration$\FormsTextBoxStyle.xbf" target="build\win81\x64\Xamarin.Forms.Platform.WinRT.Tablet" />
+
+ <file src="..\Xamarin.Forms.Maps.WinRT.Tablet\bin\ARM\$Configuration$\Xamarin.Forms.Maps.WinRT.Tablet.dll" target="build\win81\ARM" />
+ <file src="..\Xamarin.Forms.Maps.WinRT.Tablet\bin\ARM\$Configuration$\Xamarin.Forms.Maps.WinRT.Tablet.pri" target="build\win81\ARM" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\ARM\$Configuration$\Xamarin.Forms.Platform.WinRT.Tablet.dll" target="build\win81\ARM" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\ARM\$Configuration$\Xamarin.Forms.Platform.WinRT.Tablet.pri" target="build\win81\ARM" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\ARM\$Configuration$\Xamarin.Forms.Platform.WinRT.Tablet.xr.xml" target="build\win81\ARM\Xamarin.Forms.Platform.WinRT.Tablet" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\ARM\$Configuration$\Resources.xbf" target="build\win81\ARM\Xamarin.Forms.Platform.WinRT.Tablet" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\ARM\$Configuration$\TabletResources.xbf" target="build\win81\ARM\Xamarin.Forms.Platform.WinRT.Tablet" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\ARM\$Configuration$\FormsTextBoxStyle.xbf" target="build\win81\ARM\Xamarin.Forms.Platform.WinRT.Tablet" />
+
+ <!-- Xaml Design-time Stuff -->
+ <file src="..\Xamarin.Forms.Maps.Design\bin\$Configuration$\Xamarin.Forms.Maps.Design.dll" target="lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Design" />
+ <file src="..\Xamarin.Forms.Maps.Design\bin\$Configuration$\Xamarin.Forms.Maps.Design.dll" target="lib\MonoAndroid10\Design" />
+ <file src="..\Xamarin.Forms.Maps.Design\bin\$Configuration$\Xamarin.Forms.Maps.Design.dll" target="lib\Xamarin.iOS10\Design" />
+ <file src="..\Xamarin.Forms.Maps.Design\bin\$Configuration$\Xamarin.Forms.Maps.Design.dll" target="lib\MonoTouch10\Design" />
+ <file src="..\Xamarin.Forms.Maps.Design\bin\$Configuration$\Xamarin.Forms.Maps.Design.dll" target="lib\WP80\Design" />
+ <file src="..\Xamarin.Forms.Maps.Design\bin\$Configuration$\Xamarin.Forms.Maps.Design.dll" target="lib\wpa81\Design" />
+ <file src="..\Xamarin.Forms.Maps.Design\bin\$Configuration$\Xamarin.Forms.Maps.Design.dll" target="lib\win81\Design" />
+ <file src="..\Xamarin.Forms.Maps.Design\bin\$Configuration$\Xamarin.Forms.Maps.Design.dll" target="lib\uap10.0\Design" />
+
+
+ </files>
+</package>
diff --git a/.nuspec/Xamarin.Forms.Maps.props b/.nuspec/Xamarin.Forms.Maps.props
new file mode 100644
index 00000000..ffd4cfaf
--- /dev/null
+++ b/.nuspec/Xamarin.Forms.Maps.props
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'Windows' AND ( '$(Platform)' == 'x86' or '$(Platform)' == 'x64' or '$(Platform)' == 'ARM ')">
+ <SDKReference Include="Bing.Maps.Xaml, Version=1.313.0825.0">
+ <Name>Bing Maps for C#, C++, or Visual Basic</Name>
+ </SDKReference>
+ <SDKReference Include="Microsoft.VCLibs, version=12.0">
+ <Name>Microsoft Visual C++ 2013 Runtime Package for Windows</Name>
+ </SDKReference>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/.nuspec/Xamarin.Forms.Maps.targets b/.nuspec/Xamarin.Forms.Maps.targets
new file mode 100644
index 00000000..d95dc3b7
--- /dev/null
+++ b/.nuspec/Xamarin.Forms.Maps.targets
@@ -0,0 +1,22 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Target Name="Debug" BeforeTargets="BeforeBuild" >
+ <Message Text="TargetPlatformIdentifier - $(TargetPlatformIdentifier)" Importance="high"></Message>
+ </Target>
+
+ <Target Name="PlatformCheck" BeforeTargets="InjectReference"
+ Condition=" (('$(TargetPlatformIdentifier)' == 'Windows') AND ('$(Platform)' != 'x86') AND ('$(Platform)' != 'ARM') AND ('$(Platform)' != 'x64') )">
+ <Error Text="$(MSBuildThisFileName) does not work correctly on '$(Platform)'
+ platform. You need to specify platform (x86 / x64 or ARM)." />
+ </Target>
+
+ <Target Name="InjectReference" BeforeTargets="ResolveAssemblyReferences">
+ <ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'Windows' AND ( '$(Platform)' == 'x86' or '$(Platform)' == 'x64' or '$(Platform)' == 'ARM')">
+ <Reference Include="Xamarin.Forms.Maps.WinRT.Tablet">
+ <HintPath>$(MSBuildThisFileDirectory)$(Platform)\Xamarin.Forms.Maps.WinRT.Tablet.dll</HintPath>
+ </Reference>
+ <Reference Include="Xamarin.Forms.Platform.WinRT.Tablet">
+ <HintPath>$(MSBuildThisFileDirectory)$(Platform)\Xamarin.Forms.Platform.WinRT.Tablet.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ </Target>
+</Project>
diff --git a/.nuspec/Xamarin.Forms.nuspec b/.nuspec/Xamarin.Forms.nuspec
new file mode 100644
index 00000000..c9adf268
--- /dev/null
+++ b/.nuspec/Xamarin.Forms.nuspec
@@ -0,0 +1,240 @@
+<?xml version="1.0"?>
+<package >
+ <metadata>
+ <id>Xamarin.Forms$IdAppend$</id>
+ <version>1.0.0</version>
+ <authors>Xamarin Inc.</authors>
+ <owners>Xamarin Inc.</owners>
+ <tags>xamarin forms xamarinforms xamarin.forms</tags>
+ <licenseUrl>http://download.xamarin.com/content/licenses/Xamarin.Forms.rtf</licenseUrl>
+ <iconUrl>http://xamarin.com/content/images/nuget/xamarin.png</iconUrl>
+ <projectUrl>http://xamarin.com/forms</projectUrl>
+ <requireLicenseAcceptance>false</requireLicenseAcceptance>
+ <description>Build native UIs for iOS, Android, and Windows Phone from a single, shared C# codebase</description>
+ <copyright>Copyright 2013-2016</copyright>
+ <dependencies>
+ <group targetFramework="WP80">
+ <dependency id="WPtoolkit" version="4.2013.08.16"/>
+ </group>
+ <group targetFramework="MonoAndroid10">
+ <dependency id="Xamarin.Android.Support.v4" version="[23.1.1.1]"/>
+ <dependency id="Xamarin.Android.Support.Design" version="[23.1.1.1]"/>
+ <dependency id="Xamarin.Android.Support.v7.AppCompat" version="[23.1.1.1]"/>
+ <dependency id="Xamarin.Android.Support.v7.CardView" version="[23.1.1.1]"/>
+ <dependency id="Xamarin.Android.Support.v7.MediaRouter" version="[23.1.1.1]"/>
+ <dependency id="Xamarin.GooglePlayServices.AppIndexing" version="[29.0.0.1]"/>
+ </group>
+ </dependencies>
+ <references>
+ <group targetFramework="portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10">
+ <reference file="Xamarin.Forms.Core.dll" />
+ <reference file="Xamarin.Forms.Platform.dll" />
+ <reference file="Xamarin.Forms.Xaml.dll" />
+ </group>
+ <group targetFramework="Xamarin.iOS10">
+ <reference file="Xamarin.Forms.Core.dll" />
+ <reference file="Xamarin.Forms.Platform.dll" />
+ <reference file="Xamarin.Forms.Xaml.dll" />
+ <reference file="Xamarin.Forms.Platform.iOS.dll" />
+ </group>
+ <group targetFramework="MonoTouch10">
+ <reference file="Xamarin.Forms.Core.dll" />
+ <reference file="Xamarin.Forms.Platform.dll" />
+ <reference file="Xamarin.Forms.Xaml.dll" />
+ <reference file="Xamarin.Forms.Platform.iOS.Classic.dll" />
+ </group>
+ <group targetFramework="MonoAndroid10">
+ <reference file="Xamarin.Forms.Core.dll" />
+ <reference file="Xamarin.Forms.Platform.dll" />
+ <reference file="Xamarin.Forms.Xaml.dll" />
+ <reference file="FormsViewGroup.dll" />
+ <reference file="Xamarin.Forms.Platform.Android.dll" />
+ </group>
+ <group targetFramework="win81">
+ <reference file="Xamarin.Forms.Core.dll" />
+ <reference file="Xamarin.Forms.Platform.dll" />
+ <reference file="Xamarin.Forms.Xaml.dll" />
+ <reference file="Xamarin.Forms.Platform.WinRT.dll" />
+ <reference file="Xamarin.Forms.Platform.WinRT.Tablet.dll" />
+ </group>
+ <group targetFramework="wpa81">
+ <reference file="Xamarin.Forms.Core.dll" />
+ <reference file="Xamarin.Forms.Platform.dll" />
+ <reference file="Xamarin.Forms.Xaml.dll" />
+ <reference file="Xamarin.Forms.Platform.WinRT.dll" />
+ <reference file="Xamarin.Forms.Platform.WinRT.Phone.dll" />
+ </group>
+ <group targetFramework="uap10.0">
+ <reference file="Xamarin.Forms.Core.dll" />
+ <reference file="Xamarin.Forms.Platform.dll" />
+ <reference file="Xamarin.Forms.Xaml.dll" />
+ <reference file="Xamarin.Forms.Platform.UAP.dll" />
+ </group>
+ <group targetFramework="WP80">
+ <reference file="Xamarin.Forms.Core.dll" />
+ <reference file="Xamarin.Forms.Platform.dll" />
+ <reference file="Xamarin.Forms.Xaml.dll" />
+ <reference file="Xamarin.Forms.Platform.WP8.dll" />
+ </group>
+ </references>
+ </metadata>
+ <files>
+ <!--PCL-->
+ <file src="..\Xamarin.Forms.Core\bin\$Configuration$\Xamarin.Forms.Core.dll" target="lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Core\bin\$Configuration$\Xamarin.Forms.Core.*pdb" target="lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\docs\Xamarin.Forms.Core.xml" target="lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Xaml\bin\$Configuration$\Xamarin.Forms.Xaml.dll" target="lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Xaml\bin\$Configuration$\Xamarin.Forms.Xaml.*pdb" target="lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\docs\Xamarin.Forms.Xaml.xml" target="lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Platform\bin\$Configuration$\Xamarin.Forms.Platform.dll" target="lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Platform\bin\$Configuration$\Xamarin.Forms.Platform.*pdb" target="lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+
+ <!--Xaml PCL Stuff-->
+ <file src="Xamarin.Forms.targets" target="build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms$IdAppend$.targets" />
+ <file src="..\Xamarin.Forms.Build.Tasks\bin\$Configuration$\Xamarin.Forms.Build.Tasks.dll" target="build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Build.Tasks\bin\$Configuration$\Xamarin.Forms.Core.dll" target="build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Build.Tasks\bin\$Configuration$\Xamarin.Forms.Xaml.dll" target="build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+
+ <!-- Xaml Design-time Stuff -->
+ <file src="..\Xamarin.Forms.Core.Design\bin\$Configuration$\Xamarin.Forms.Core.Design.dll" target="lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Design" />
+ <file src="..\Xamarin.Forms.Xaml.Design\bin\$Configuration$\Xamarin.Forms.Xaml.Design.dll" target="lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Design" />
+
+ <file src="..\Xamarin.Forms.Core.Design\bin\$Configuration$\Xamarin.Forms.Core.Design.dll" target="lib\MonoAndroid10\Design" />
+ <file src="..\Xamarin.Forms.Xaml.Design\bin\$Configuration$\Xamarin.Forms.Xaml.Design.dll" target="lib\MonoAndroid10\Design" />
+
+ <file src="..\Xamarin.Forms.Core.Design\bin\$Configuration$\Xamarin.Forms.Core.Design.dll" target="lib\Xamarin.iOS10\Design" />
+ <file src="..\Xamarin.Forms.Xaml.Design\bin\$Configuration$\Xamarin.Forms.Xaml.Design.dll" target="lib\Xamarin.iOS10\Design" />
+
+ <file src="..\Xamarin.Forms.Core.Design\bin\$Configuration$\Xamarin.Forms.Core.Design.dll" target="lib\MonoTouch10\Design" />
+ <file src="..\Xamarin.Forms.Xaml.Design\bin\$Configuration$\Xamarin.Forms.Xaml.Design.dll" target="lib\MonoTouch10\Design" />
+
+ <file src="..\Xamarin.Forms.Core.Design\bin\$Configuration$\Xamarin.Forms.Core.Design.dll" target="lib\WP80\Design" />
+ <file src="..\Xamarin.Forms.Xaml.Design\bin\$Configuration$\Xamarin.Forms.Xaml.Design.dll" target="lib\WP80\Design" />
+
+ <file src="..\Xamarin.Forms.Core.Design\bin\$Configuration$\Xamarin.Forms.Core.Design.dll" target="lib\wpa81\Design" />
+ <file src="..\Xamarin.Forms.Xaml.Design\bin\$Configuration$\Xamarin.Forms.Xaml.Design.dll" target="lib\wpa81\Design" />
+
+ <file src="..\Xamarin.Forms.Core.Design\bin\$Configuration$\Xamarin.Forms.Core.Design.dll" target="lib\win81\Design" />
+ <file src="..\Xamarin.Forms.Xaml.Design\bin\$Configuration$\Xamarin.Forms.Xaml.Design.dll" target="lib\win81\Design" />
+
+ <file src="..\Xamarin.Forms.Core.Design\bin\$Configuration$\Xamarin.Forms.Core.Design.dll" target="lib\uap10.0\Design" />
+ <file src="..\Xamarin.Forms.Xaml.Design\bin\$Configuration$\Xamarin.Forms.Xaml.Design.dll" target="lib\uap10.0\Design" />
+
+ <!-- XamlC stuffs -->
+ <file src="..\Xamarin.Forms.Build.Tasks\bin\$Configuration$\Mono.Cecil.dll" target="build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Build.Tasks\bin\$Configuration$\Mono.Cecil.Mdb.dll" target="build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Build.Tasks\bin\$Configuration$\Mono.Cecil.Pdb.dll" target="build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Build.Tasks\bin\$Configuration$\Mono.Cecil.Rocks.dll" target="build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\ICSharpCode.Decompiler\bin\$Configuration$\ICSharpCode.Decompiler.dll" target="build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\ICSharpCode.Decompiler\bin\$Configuration$\ICSharpCode.NRefactory.dll" target="build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\ICSharpCode.Decompiler\bin\$Configuration$\ICSharpCode.NRefactory.Cecil.dll" target="build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\ICSharpCode.Decompiler\bin\$Configuration$\ICSharpCode.NRefactory.CSharp.dll" target="build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+ <file src="..\ICSharpCode.Decompiler\bin\$Configuration$\ICSharpCode.NRefactory.Xml.dll" target="build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10" />
+
+ <!--Android-->
+ <file src="..\Xamarin.Forms.Platform.Android\bin\$Configuration$\Xamarin.Forms.Platform.Android.dll" target="lib\MonoAndroid10" />
+ <file src="..\Xamarin.Forms.Platform.Android\bin\$Configuration$\Xamarin.Forms.Platform.Android.*pdb" target="lib\MonoAndroid10" />
+ <file src="..\Xamarin.Forms.Platform.Android.FormsViewGroup\bin\$Configuration$\FormsViewGroup.dll" target="lib\MonoAndroid10" />
+ <file src="..\Xamarin.Forms.Platform.Android.FormsViewGroup\bin\$Configuration$\FormsViewGroup.*pdb" target="lib\MonoAndroid10" />
+ <file src="..\Xamarin.Forms.Core\bin\$Configuration$\Xamarin.Forms.Core.dll" target="lib\MonoAndroid10" />
+ <file src="..\Xamarin.Forms.Core\bin\$Configuration$\Xamarin.Forms.Core.*pdb" target="lib\MonoAndroid10" />
+ <file src="..\docs\Xamarin.Forms.Core.xml" target="lib\MonoAndroid10" />
+ <file src="..\Xamarin.Forms.Xaml\bin\$Configuration$\Xamarin.Forms.Xaml.dll" target="lib\MonoAndroid10" />
+ <file src="..\Xamarin.Forms.Xaml\bin\$Configuration$\Xamarin.Forms.Xaml.*pdb" target="lib\MonoAndroid10" />
+ <file src="..\docs\Xamarin.Forms.Xaml.xml" target="lib\MonoAndroid10" />
+ <file src="..\Stubs\Xamarin.Forms.Platform.Android\bin\$Configuration$\Xamarin.Forms.Platform.dll" target="lib\MonoAndroid10" />
+
+ <!--iPhone Unified-->
+ <file src="..\Xamarin.Forms.Platform.iOS\bin\$Configuration$\Xamarin.Forms.Platform.iOS.dll" target="lib\Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Platform.iOS\bin\$Configuration$\Xamarin.Forms.Platform.iOS.*pdb" target="lib\Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Core\bin\$Configuration$\Xamarin.Forms.Core.dll" target="lib\Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Core\bin\$Configuration$\Xamarin.Forms.Core.*pdb" target="lib\Xamarin.iOS10" />
+ <file src="..\docs\Xamarin.Forms.Core.xml" target="lib\Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Xaml\bin\$Configuration$\Xamarin.Forms.Xaml.dll" target="lib\Xamarin.iOS10" />
+ <file src="..\Xamarin.Forms.Xaml\bin\$Configuration$\Xamarin.Forms.Xaml.*pdb" target="lib\Xamarin.iOS10" />
+ <file src="..\docs\Xamarin.Forms.Xaml.xml" target="lib\Xamarin.iOS10" />
+ <file src="..\Stubs\Xamarin.Forms.Platform.iOS\bin\iPhone\$Configuration$\Xamarin.Forms.Platform.dll" target="lib\Xamarin.iOS10" />
+
+ <!--iPhone Classic-->
+ <file src="..\Xamarin.Forms.Platform.iOS\classic_bin\iPhoneSimulator\$Configuration$\Xamarin.Forms.Platform.iOS.Classic.dll" target="lib\MonoTouch10" />
+ <file src="..\Xamarin.Forms.Platform.iOS\classic_bin\iPhoneSimulator\$Configuration$\Xamarin.Forms.Platform.iOS.Classic.*pdb" target="lib\MonoTouch10" />
+ <file src="..\Xamarin.Forms.Core\bin\$Configuration$\Xamarin.Forms.Core.dll" target="lib\MonoTouch10" />
+ <file src="..\Xamarin.Forms.Core\bin\$Configuration$\Xamarin.Forms.Core.*pdb" target="lib\MonoTouch10" />
+ <file src="..\docs\Xamarin.Forms.Core.xml" target="lib\MonoTouch10" />
+ <file src="..\Xamarin.Forms.Xaml\bin\$Configuration$\Xamarin.Forms.Xaml.dll" target="lib\MonoTouch10" />
+ <file src="..\Xamarin.Forms.Xaml\bin\$Configuration$\Xamarin.Forms.Xaml.*pdb" target="lib\MonoTouch10" />
+ <file src="..\docs\Xamarin.Forms.Xaml.xml" target="lib\MonoTouch10" />
+ <file src="..\Stubs\Xamarin.Forms.Platform.iOS.Classic\bin\iPhone\$Configuration$\Xamarin.Forms.Platform.dll" target="lib\MonoTouch10" />
+
+ <!--Windows Phone 8-->
+ <file src="..\Xamarin.Forms.Platform.WP8\bin\$Configuration$\Xamarin.Forms.Platform.WP8.dll" target="lib\WP80" />
+ <file src="..\Xamarin.Forms.Platform.WP8\bin\$Configuration$\Xamarin.Forms.Platform.WP8.*pdb" target="lib\WP80" />
+ <file src="..\Xamarin.Forms.Core\bin\$Configuration$\Xamarin.Forms.Core.dll" target="lib\WP80" />
+ <file src="..\Xamarin.Forms.Core\bin\$Configuration$\Xamarin.Forms.Core.*pdb" target="lib\WP80" />
+ <file src="..\docs\Xamarin.Forms.Core.xml" target="lib\WP80" />
+ <file src="..\Xamarin.Forms.Xaml\bin\$Configuration$\Xamarin.Forms.Xaml.dll" target="lib\WP80" />
+ <file src="..\Xamarin.Forms.Xaml\bin\$Configuration$\Xamarin.Forms.Xaml.*pdb" target="lib\WP80" />
+ <file src="..\docs\Xamarin.Forms.Xaml.xml" target="lib\WP80" />
+ <file src="..\Stubs\Xamarin.Forms.Platform.WP8\bin\$Configuration$\Xamarin.Forms.Platform.dll" target="lib\WP80" />
+
+ <!--WinRT Phone-->
+ <file src="..\Xamarin.Forms.Platform.WinRT\bin\$Configuration$\Xamarin.Forms.Platform.WinRT.dll" target="lib\wpa81" />
+ <file src="..\Xamarin.Forms.Platform.WinRT\bin\$Configuration$\Xamarin.Forms.Platform.WinRT.pri" target="lib\wpa81" />
+ <file src="..\Xamarin.Forms.Platform.WinRT\bin\$Configuration$\Xamarin.Forms.Platform.WinRT.xr.xml" target="lib\wpa81\Xamarin.Forms.Platform.WinRT" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Phone\bin\$Configuration$\Xamarin.Forms.Platform.WinRT.Phone.dll" target="lib\wpa81" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Phone\bin\$Configuration$\Xamarin.Forms.Platform.WinRT.Phone.pri" target="lib\wpa81" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Phone\bin\$Configuration$\Xamarin.Forms.Platform.WinRT.Phone.xr.xml" target="lib\wpa81\Xamarin.Forms.Platform.WinRT.Phone" />
+ <file src="..\Xamarin.Forms.Platform\bin\$Configuration$\Xamarin.Forms.Platform.dll" target="lib\wpa81" />
+
+ <file src="..\Xamarin.Forms.Platform.WinRT\bin\$Configuration$\PageControl.xbf" target="lib\wpa81\Xamarin.Forms.Platform.WinRT" />
+ <file src="..\Xamarin.Forms.Platform.WinRT\bin\$Configuration$\StepperControl.xbf" target="lib\wpa81\Xamarin.Forms.Platform.WinRT" />
+
+ <file src="..\Xamarin.Forms.Platform.WinRT.Phone\bin\$Configuration$\PhoneResources.xbf" target="lib\wpa81\Xamarin.Forms.Platform.WinRT.Phone" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Phone\bin\$Configuration$\FormsTextBoxStyle.xbf" target="lib\wpa81\Xamarin.Forms.Platform.WinRT.Phone" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Phone\bin\$Configuration$\Resources.xbf" target="lib\wpa81\Xamarin.Forms.Platform.WinRT.Phone" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Phone\bin\$Configuration$\SearchBox.xbf" target="lib\wpa81\Xamarin.Forms.Platform.WinRT.Phone" />
+
+ <file src="..\Xamarin.Forms.Core\bin\$Configuration$\Xamarin.Forms.Core.dll" target="lib\wpa81" />
+ <file src="..\docs\Xamarin.Forms.Core.xml" target="lib\wpa81" />
+ <file src="..\Xamarin.Forms.Xaml\bin\$Configuration$\Xamarin.Forms.Xaml.dll" target="lib\wpa81" />
+ <file src="..\docs\Xamarin.Forms.Xaml.xml" target="lib\wpa81" />
+
+ <!--WinRT Desktop-->
+ <file src="..\Xamarin.Forms.Platform.WinRT\bin\$Configuration$\Xamarin.Forms.Platform.WinRT.dll" target="lib\win81" />
+ <file src="..\Xamarin.Forms.Platform.WinRT\bin\$Configuration$\Xamarin.Forms.Platform.WinRT.pri" target="lib\win81" />
+ <file src="..\Xamarin.Forms.Platform.WinRT\bin\$Configuration$\Xamarin.Forms.Platform.WinRT.xr.xml" target="lib\win81\Xamarin.Forms.Platform.WinRT" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\$Configuration$\Xamarin.Forms.Platform.WinRT.Tablet.dll" target="lib\win81" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\$Configuration$\Xamarin.Forms.Platform.WinRT.Tablet.pri" target="lib\win81" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\$Configuration$\Xamarin.Forms.Platform.WinRT.Tablet.xr.xml" target="lib\win81\Xamarin.Forms.Platform.WinRT.Tablet" />
+ <file src="..\Xamarin.Forms.Platform\bin\$Configuration$\Xamarin.Forms.Platform.dll" target="lib\win81" />
+
+ <file src="..\Xamarin.Forms.Platform.WinRT\bin\$Configuration$\PageControl.xbf" target="lib\win81\Xamarin.Forms.Platform.WinRT" />
+ <file src="..\Xamarin.Forms.Platform.WinRT\bin\$Configuration$\StepperControl.xbf" target="lib\win81\Xamarin.Forms.Platform.WinRT" />
+
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\$Configuration$\Resources.xbf" target="lib\win81\Xamarin.Forms.Platform.WinRT.Tablet" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\$Configuration$\TabletResources.xbf" target="lib\win81\Xamarin.Forms.Platform.WinRT.Tablet" />
+ <file src="..\Xamarin.Forms.Platform.WinRT.Tablet\bin\$Configuration$\FormsTextBoxStyle.xbf" target="lib\win81\Xamarin.Forms.Platform.WinRT.Tablet" />
+
+ <file src="..\Xamarin.Forms.Core\bin\$Configuration$\Xamarin.Forms.Core.dll" target="lib\win81" />
+ <file src="..\docs\Xamarin.Forms.Core.xml" target="lib\win81" />
+ <file src="..\Xamarin.Forms.Xaml\bin\$Configuration$\Xamarin.Forms.Xaml.dll" target="lib\win81" />
+ <file src="..\docs\Xamarin.Forms.Xaml.xml" target="lib\win81" />
+
+ <!--UWP-->
+ <file src="..\Xamarin.Forms.Platform.UAP\bin\$Configuration$\Xamarin.Forms.Platform.UAP.dll" target="lib\uap10.0" />
+ <file src="..\Xamarin.Forms.Platform.UAP\bin\$Configuration$\Xamarin.Forms.Platform.UAP.pri" target="lib\uap10.0" />
+ <file src="..\Xamarin.Forms.Platform.UAP\bin\$Configuration$\Xamarin.Forms.Platform.UAP.xr.xml" target="lib\uap10.0\Xamarin.Forms.Platform.UAP" />
+ <file src="..\Xamarin.Forms.Platform\bin\$Configuration$\Xamarin.Forms.Platform.dll" target="lib\uap10.0" />
+
+ <file src="..\Xamarin.Forms.Platform.UAP\Properties\Xamarin.Forms.Platform.UAP.rd.xml" target="lib\uap10.0\Xamarin.Forms.Platform.UAP\Properties" />
+
+ <file src="..\Xamarin.Forms.Platform.UAP\bin\$Configuration$\PageControl.xbf" target="lib\uap10.0\Xamarin.Forms.Platform.UAP" />
+ <file src="..\Xamarin.Forms.Platform.UAP\bin\$Configuration$\Resources.xbf" target="lib\uap10.0\Xamarin.Forms.Platform.UAP" />
+ <file src="..\Xamarin.Forms.Platform.UAP\bin\$Configuration$\FormsTextBoxStyle.xbf" target="lib\uap10.0\Xamarin.Forms.Platform.UAP" />
+
+ <file src="..\Xamarin.Forms.Core\bin\$Configuration$\Xamarin.Forms.Core.dll" target="lib\uap10.0" />
+ <file src="..\docs\Xamarin.Forms.Core.xml" target="lib\uap10.0" />
+ <file src="..\Xamarin.Forms.Xaml\bin\$Configuration$\Xamarin.Forms.Xaml.dll" target="lib\uap10.0" />
+ <file src="..\docs\Xamarin.Forms.Xaml.xml" target="lib\uap10.0" />
+ </files>
+</package>
diff --git a/.nuspec/Xamarin.Forms.targets b/.nuspec/Xamarin.Forms.targets
new file mode 100644
index 00000000..0bb724d3
--- /dev/null
+++ b/.nuspec/Xamarin.Forms.targets
@@ -0,0 +1,69 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <UsingTask TaskName="Xamarin.Forms.Build.Tasks.XamlGTask" AssemblyFile="Xamarin.Forms.Build.Tasks.dll"/>
+ <UsingTask TaskName="Xamarin.Forms.Build.Tasks.FixedCreateCSharpManifestResourceName" AssemblyFile="Xamarin.Forms.Build.Tasks.dll"/>
+ <UsingTask TaskName="Xamarin.Forms.Build.Tasks.XamlCTask" AssemblyFile="Xamarin.Forms.Build.Tasks.dll"/>
+
+ <PropertyGroup>
+ <PrepareResourcesDependsOn>
+ XamlG;
+ $(PrepareResourcesDependsOn);
+ </PrepareResourcesDependsOn>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <CompileDependsOn>
+ $(CompileDependsOn);
+ XamlC;
+ </CompileDependsOn>
+ </PropertyGroup>
+
+ <Target Name="UpdateDesignTimeXaml" Condition="'$(UseHostCompilerIfAvailable)' == 'true'" DependsOnTargets="PrepareResources; Compile"/>
+
+ <Target Name="XamlG" DependsOnTargets="$(XamlGDependsOn)"/>
+
+ <PropertyGroup>
+ <XamlGDependsOn>
+ _PreXamlG;
+ _CollectXamlFiles;
+ _CoreXamlG;
+ </XamlGDependsOn>
+ </PropertyGroup>
+
+ <Target Name="_PreXamlG">
+ <MakeDir Directories="$(IntermediateOutputPath)"/>
+ </Target>
+
+ <Target Name="_CollectXamlFiles">
+ <ItemGroup>
+ <_XamlResources Include="@(EmbeddedResource)" Condition="'%(Extension)' == '.xaml' AND '$(DefaultLanguageSourceExtension)' == '.cs'"/>
+ </ItemGroup>
+ <FixedCreateCSharpManifestResourceName ResourceFiles="@(_XamlResources)" RootNamespace="$(RootNamespace)">
+ <Output TaskParameter="ResourceFilesWithManifestResourceNames" ItemName="XamlFiles" />
+ </FixedCreateCSharpManifestResourceName>
+ <ItemGroup>
+ <XamlGFiles Include="@(XamlFiles->'$(IntermediateOutputPath)%(ManifestResourceName).g$(DefaultLanguageSourceExtension)')"/>
+ <Compile Include="@(XamlGFiles)"/>
+ <FileWrites Include="@(XamlGFiles)"/>
+ </ItemGroup>
+ </Target>
+
+ <Target Name="_CoreXamlG"
+ Inputs = "@(XamlFiles)"
+ Outputs = "$(IntermediateOutputPath)%(ManifestResourceName).g$(DefaultLanguageSourceExtension)">
+ <XamlGTask
+ Source="@(XamlFiles)"
+ Language = "$(Language)"
+ AssemblyName = "$(AssemblyName)"
+ OutputFile = "$(IntermediateOutputPath)%(ManifestResourceName).g$(DefaultLanguageSourceExtension)">
+ </XamlGTask>
+ </Target>
+
+ <Target Name="XamlC">
+ <XamlCTask
+ Assembly = "$(IntermediateOutputPath)$(TargetFileName)"
+ ReferencePath = "@(ReferencePath)"
+ Verbosity = "2"
+ OptimizeIL = "true"
+ DebugSymbols = "$(DebugSymbols)" />
+ </Target>
+</Project>
diff --git a/AndroidNative/FormsViewGroup/.classpath b/AndroidNative/FormsViewGroup/.classpath
new file mode 100644
index 00000000..7bc01d9a
--- /dev/null
+++ b/AndroidNative/FormsViewGroup/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/AndroidNative/FormsViewGroup/.project b/AndroidNative/FormsViewGroup/.project
new file mode 100644
index 00000000..752a5a15
--- /dev/null
+++ b/AndroidNative/FormsViewGroup/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>FormsViewGroup</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/AndroidNative/FormsViewGroup/.settings/org.eclipse.jdt.core.prefs b/AndroidNative/FormsViewGroup/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000..b080d2dd
--- /dev/null
+++ b/AndroidNative/FormsViewGroup/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/AndroidNative/FormsViewGroup/AndroidManifest.xml b/AndroidNative/FormsViewGroup/AndroidManifest.xml
new file mode 100644
index 00000000..bc4108dc
--- /dev/null
+++ b/AndroidNative/FormsViewGroup/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.xamarin.formsviewgroup"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="15"
+ android:targetSdkVersion="15" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ </application>
+
+</manifest>
diff --git a/AndroidNative/FormsViewGroup/libs/android-support-v4.jar b/AndroidNative/FormsViewGroup/libs/android-support-v4.jar
new file mode 100644
index 00000000..c31cede4
--- /dev/null
+++ b/AndroidNative/FormsViewGroup/libs/android-support-v4.jar
Binary files differ
diff --git a/AndroidNative/FormsViewGroup/proguard-project.txt b/AndroidNative/FormsViewGroup/proguard-project.txt
new file mode 100644
index 00000000..f2fe1559
--- /dev/null
+++ b/AndroidNative/FormsViewGroup/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/AndroidNative/FormsViewGroup/project.properties b/AndroidNative/FormsViewGroup/project.properties
new file mode 100644
index 00000000..7e2ca64f
--- /dev/null
+++ b/AndroidNative/FormsViewGroup/project.properties
@@ -0,0 +1,15 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-20
+android.library=true
diff --git a/AndroidNative/FormsViewGroup/res/drawable-hdpi/ic_launcher.png b/AndroidNative/FormsViewGroup/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000..96a442e5
--- /dev/null
+++ b/AndroidNative/FormsViewGroup/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/AndroidNative/FormsViewGroup/res/drawable-mdpi/ic_launcher.png b/AndroidNative/FormsViewGroup/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000..359047df
--- /dev/null
+++ b/AndroidNative/FormsViewGroup/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/AndroidNative/FormsViewGroup/res/drawable-xhdpi/ic_launcher.png b/AndroidNative/FormsViewGroup/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..71c6d760
--- /dev/null
+++ b/AndroidNative/FormsViewGroup/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/AndroidNative/FormsViewGroup/res/values-v11/styles.xml b/AndroidNative/FormsViewGroup/res/values-v11/styles.xml
new file mode 100644
index 00000000..3c02242a
--- /dev/null
+++ b/AndroidNative/FormsViewGroup/res/values-v11/styles.xml
@@ -0,0 +1,11 @@
+<resources>
+
+ <!--
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+ <!-- API 11 theme customizations can go here. -->
+ </style>
+
+</resources>
diff --git a/AndroidNative/FormsViewGroup/res/values-v14/styles.xml b/AndroidNative/FormsViewGroup/res/values-v14/styles.xml
new file mode 100644
index 00000000..a91fd037
--- /dev/null
+++ b/AndroidNative/FormsViewGroup/res/values-v14/styles.xml
@@ -0,0 +1,12 @@
+<resources>
+
+ <!--
+ Base application theme for API 14+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+ <!-- API 14 theme customizations can go here. -->
+ </style>
+
+</resources>
diff --git a/AndroidNative/FormsViewGroup/res/values/strings.xml b/AndroidNative/FormsViewGroup/res/values/strings.xml
new file mode 100644
index 00000000..605dd46e
--- /dev/null
+++ b/AndroidNative/FormsViewGroup/res/values/strings.xml
@@ -0,0 +1,5 @@
+<resources>
+
+ <string name="app_name">FormsViewGroup</string>
+
+</resources>
diff --git a/AndroidNative/FormsViewGroup/res/values/styles.xml b/AndroidNative/FormsViewGroup/res/values/styles.xml
new file mode 100644
index 00000000..6ce89c7b
--- /dev/null
+++ b/AndroidNative/FormsViewGroup/res/values/styles.xml
@@ -0,0 +1,20 @@
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
diff --git a/AndroidNative/FormsViewGroup/src/com/xamarin/forms/platform/android/FormsViewGroup.java b/AndroidNative/FormsViewGroup/src/com/xamarin/forms/platform/android/FormsViewGroup.java
new file mode 100644
index 00000000..2168f323
--- /dev/null
+++ b/AndroidNative/FormsViewGroup/src/com/xamarin/forms/platform/android/FormsViewGroup.java
@@ -0,0 +1,96 @@
+package com.xamarin.forms.platform.android;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.ViewGroup;
+import android.view.*;
+
+
+public class FormsViewGroup extends ViewGroup {
+
+ public FormsViewGroup(Context context) {
+ super(context);
+ // TODO Auto-generated constructor stub
+ }
+
+ public FormsViewGroup(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ // TODO Auto-generated constructor stub
+ }
+
+ public FormsViewGroup(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ // TODO Auto-generated constructor stub
+ }
+
+ public void measureAndLayout (int widthMeasureSpec, int heightMeasureSpec, int l, int t, int r, int b)
+ {
+ measure (widthMeasureSpec, heightMeasureSpec);
+ layout (l, t, r, b);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ }
+
+ boolean inputTransparent;
+
+ protected void setInputTransparent (boolean value)
+ {
+ inputTransparent = value;
+ }
+
+ protected boolean getInputTransparent ()
+ {
+ return inputTransparent;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent (MotionEvent ev)
+ {
+ if (inputTransparent)
+ return false;
+
+ return super.onInterceptTouchEvent(ev);
+ }
+
+ @Override
+ public boolean onTouchEvent (MotionEvent ev)
+ {
+ if (inputTransparent)
+ return false;
+
+ return super.onTouchEvent(ev);
+ }
+
+ public void sendBatchUpdate (
+ float pivotX,
+ float pivotY,
+ int visibility,
+ boolean enabled,
+ float opacity,
+ float rotation,
+ float rotationX,
+ float rotationY,
+ float scale,
+ float translationX,
+ float translationY){
+ setPivotX (pivotX);
+ setPivotY (pivotY);
+
+ if (getVisibility () != visibility)
+ setVisibility (visibility);
+
+ if (isEnabled () != enabled)
+ setEnabled (enabled);
+
+ setAlpha (opacity);
+ setRotation (rotation);
+ setRotationX (rotationX);
+ setRotationY (rotationY);
+ setScaleX (scale);
+ setScaleY (scale);
+ setTranslationX (translationX);
+ setTranslationY (translationY);
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Annotations.cs b/ICSharpCode.Decompiler/Ast/Annotations.cs
new file mode 100644
index 00000000..ec9fd61f
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Annotations.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using ICSharpCode.Decompiler.ILAst;
+using ICSharpCode.NRefactory.CSharp;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.Ast
+{
+ public class TypeInformation
+ {
+ public readonly TypeReference InferredType;
+ public readonly TypeReference ExpectedType;
+
+ public TypeInformation(TypeReference inferredType, TypeReference expectedType)
+ {
+ InferredType = inferredType;
+ ExpectedType = expectedType;
+ }
+ }
+
+ public class LdTokenAnnotation {}
+
+ /// <summary>
+ /// Annotation that is applied to the body expression of an Expression.Lambda() call.
+ /// </summary>
+ public class ParameterDeclarationAnnotation
+ {
+ public readonly List<ParameterDeclaration> Parameters = new List<ParameterDeclaration>();
+
+ public ParameterDeclarationAnnotation(ILExpression expr)
+ {
+ Debug.Assert(expr.Code == ILCode.ExpressionTreeParameterDeclarations);
+ for (int i = 0; i < expr.Arguments.Count - 1; i++) {
+ ILExpression p = expr.Arguments[i];
+ // p looks like this:
+ // stloc(v, call(Expression::Parameter, call(Type::GetTypeFromHandle, ldtoken(...)), ldstr(...)))
+ ILVariable v = (ILVariable)p.Operand;
+ TypeReference typeRef = (TypeReference)p.Arguments[0].Arguments[0].Arguments[0].Operand;
+ string name = (string)p.Arguments[0].Arguments[1].Operand;
+ Parameters.Add(new ParameterDeclaration(AstBuilder.ConvertType(typeRef), name).WithAnnotation(v));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Annotation that is applied to a LambdaExpression that was produced by an expression tree.
+ /// </summary>
+ public class ExpressionTreeLambdaAnnotation
+ {
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs
new file mode 100644
index 00000000..faab2725
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs
@@ -0,0 +1,1690 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.Ast.Transforms;
+using ICSharpCode.Decompiler.ILAst;
+using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.Utils;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.Ast
+{
+ using Ast = NRefactory.CSharp;
+ using VarianceModifier = NRefactory.TypeSystem.VarianceModifier;
+
+ [Flags]
+ public enum ConvertTypeOptions
+ {
+ None = 0,
+ IncludeNamespace = 1,
+ IncludeTypeParameterDefinitions = 2,
+ DoNotUsePrimitiveTypeNames = 4
+ }
+
+ public class AstBuilder
+ {
+ DecompilerContext context;
+ SyntaxTree syntaxTree = new SyntaxTree();
+ Dictionary<string, NamespaceDeclaration> astNamespaces = new Dictionary<string, NamespaceDeclaration>();
+ bool transformationsHaveRun;
+
+ public AstBuilder(DecompilerContext context)
+ {
+ if (context == null)
+ throw new ArgumentNullException("context");
+ this.context = context;
+ DecompileMethodBodies = true;
+ }
+
+ public static bool MemberIsHidden(MemberReference member, DecompilerSettings settings)
+ {
+ MethodDefinition method = member as MethodDefinition;
+ if (method != null) {
+ if (method.IsGetter || method.IsSetter || method.IsAddOn || method.IsRemoveOn)
+ return true;
+ if (settings.AnonymousMethods && method.HasGeneratedName() && method.IsCompilerGenerated())
+ return true;
+ }
+
+ TypeDefinition type = member as TypeDefinition;
+ if (type != null) {
+ if (type.DeclaringType != null) {
+ if (settings.AnonymousMethods && IsClosureType(type))
+ return true;
+ if (settings.YieldReturn && YieldReturnDecompiler.IsCompilerGeneratorEnumerator(type))
+ return true;
+ if (settings.AsyncAwait && AsyncDecompiler.IsCompilerGeneratedStateMachine(type))
+ return true;
+ } else if (type.IsCompilerGenerated()) {
+ if (type.Name.StartsWith("<PrivateImplementationDetails>", StringComparison.Ordinal))
+ return true;
+ if (type.IsAnonymousType())
+ return true;
+ }
+ }
+
+ FieldDefinition field = member as FieldDefinition;
+ if (field != null) {
+ if (field.IsCompilerGenerated()) {
+ if (settings.AnonymousMethods && IsAnonymousMethodCacheField(field))
+ return true;
+ if (settings.AutomaticProperties && IsAutomaticPropertyBackingField(field))
+ return true;
+ if (settings.SwitchStatementOnString && IsSwitchOnStringCache(field))
+ return true;
+ }
+ // event-fields are not [CompilerGenerated]
+ if (settings.AutomaticEvents && field.DeclaringType.Events.Any(ev => ev.Name == field.Name))
+ return true;
+ }
+
+ return false;
+ }
+
+ static bool IsSwitchOnStringCache(FieldDefinition field)
+ {
+ return field.Name.StartsWith("<>f__switch", StringComparison.Ordinal);
+ }
+
+ static bool IsAutomaticPropertyBackingField(FieldDefinition field)
+ {
+ return field.HasGeneratedName() && field.Name.EndsWith("BackingField", StringComparison.Ordinal);
+ }
+
+ static bool IsAnonymousMethodCacheField(FieldDefinition field)
+ {
+ return field.Name.StartsWith("CS$<>", StringComparison.Ordinal) || field.Name.StartsWith("<>f__am", StringComparison.Ordinal);
+ }
+
+ static bool IsClosureType(TypeDefinition type)
+ {
+ return type.HasGeneratedName() && type.IsCompilerGenerated() && (type.Name.Contains("DisplayClass") || type.Name.Contains("AnonStorey"));
+ }
+
+ /// <summary>
+ /// Runs the C# transformations on the compilation unit.
+ /// </summary>
+ public void RunTransformations()
+ {
+ RunTransformations(null);
+ }
+
+ public void RunTransformations(Predicate<IAstTransform> transformAbortCondition)
+ {
+ TransformationPipeline.RunTransformationsUntil(syntaxTree, transformAbortCondition, context);
+ transformationsHaveRun = true;
+ }
+
+ /// <summary>
+ /// Gets the abstract source tree.
+ /// </summary>
+ public SyntaxTree SyntaxTree {
+ get { return syntaxTree; }
+ }
+
+ /// <summary>
+ /// Generates C# code from the abstract source tree.
+ /// </summary>
+ /// <remarks>This method adds ParenthesizedExpressions into the AST, and will run transformations if <see cref="RunTransformations"/> was not called explicitly</remarks>
+ public void GenerateCode(ITextOutput output)
+ {
+ if (!transformationsHaveRun)
+ RunTransformations();
+
+ syntaxTree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
+ var outputFormatter = new TextTokenWriter(output, context) { FoldBraces = context.Settings.FoldBraces };
+ var formattingPolicy = context.Settings.CSharpFormattingOptions;
+ syntaxTree.AcceptVisitor(new CSharpOutputVisitor(outputFormatter, formattingPolicy));
+ }
+
+ public void AddAssembly(AssemblyDefinition assemblyDefinition, bool onlyAssemblyLevel = false)
+ {
+ AddAssembly(assemblyDefinition.MainModule, onlyAssemblyLevel);
+ }
+
+ public void AddAssembly(ModuleDefinition moduleDefinition, bool onlyAssemblyLevel = false)
+ {
+ if (moduleDefinition.Assembly != null && moduleDefinition.Assembly.Name.Version != null) {
+ syntaxTree.AddChild(
+ new AttributeSection {
+ AttributeTarget = "assembly",
+ Attributes = {
+ new NRefactory.CSharp.Attribute {
+ Type = new SimpleType("AssemblyVersion")
+ .WithAnnotation(new TypeReference(
+ "System.Reflection", "AssemblyVersionAttribute",
+ moduleDefinition, moduleDefinition.TypeSystem.Corlib)),
+ Arguments = {
+ new PrimitiveExpression(moduleDefinition.Assembly.Name.Version.ToString())
+ }
+ }
+ }
+ }, EntityDeclaration.AttributeRole);
+ }
+
+ if (moduleDefinition.Assembly != null) {
+ ConvertCustomAttributes(syntaxTree, moduleDefinition.Assembly, "assembly");
+ ConvertSecurityAttributes(syntaxTree, moduleDefinition.Assembly, "assembly");
+ }
+ ConvertCustomAttributes(syntaxTree, moduleDefinition, "module");
+ AddTypeForwarderAttributes(syntaxTree, moduleDefinition, "assembly");
+
+ if (!onlyAssemblyLevel) {
+ foreach (TypeDefinition typeDef in moduleDefinition.Types) {
+ // Skip the <Module> class
+ if (typeDef.Name == "<Module>") continue;
+ // Skip any hidden types
+ if (MemberIsHidden(typeDef, context.Settings))
+ continue;
+
+ AddType(typeDef);
+ }
+ }
+ }
+
+ void AddTypeForwarderAttributes(SyntaxTree astCompileUnit, ModuleDefinition module, string target)
+ {
+ if (!module.HasExportedTypes)
+ return;
+ foreach (ExportedType type in module.ExportedTypes) {
+ if (type.IsForwarder) {
+ var forwardedType = CreateTypeOfExpression(new TypeReference(type.Namespace, type.Name, module, type.Scope));
+ astCompileUnit.AddChild(
+ new AttributeSection {
+ AttributeTarget = target,
+ Attributes = {
+ new NRefactory.CSharp.Attribute {
+ Type = new SimpleType("TypeForwardedTo")
+ .WithAnnotation(new TypeReference(
+ "System.Runtime.CompilerServices", "TypeForwardedToAttribute",
+ module, module.TypeSystem.Corlib)),
+ Arguments = { forwardedType }
+ }
+ }
+ }, EntityDeclaration.AttributeRole);
+ }
+ }
+ }
+
+ NamespaceDeclaration GetCodeNamespace(string name)
+ {
+ if (string.IsNullOrEmpty(name)) {
+ return null;
+ }
+ if (astNamespaces.ContainsKey(name)) {
+ return astNamespaces[name];
+ } else {
+ // Create the namespace
+ NamespaceDeclaration astNamespace = new NamespaceDeclaration { Name = name };
+ syntaxTree.Members.Add(astNamespace);
+ astNamespaces[name] = astNamespace;
+ return astNamespace;
+ }
+ }
+
+ public void AddType(TypeDefinition typeDef)
+ {
+ var astType = CreateType(typeDef);
+ NamespaceDeclaration astNS = GetCodeNamespace(typeDef.Namespace);
+ if (astNS != null) {
+ astNS.Members.Add(astType);
+ } else {
+ syntaxTree.Members.Add(astType);
+ }
+ }
+
+ public void AddMethod(MethodDefinition method)
+ {
+ AstNode node = method.IsConstructor ? (AstNode)CreateConstructor(method) : CreateMethod(method);
+ syntaxTree.Members.Add(node);
+ }
+
+ public void AddProperty(PropertyDefinition property)
+ {
+ syntaxTree.Members.Add(CreateProperty(property));
+ }
+
+ public void AddField(FieldDefinition field)
+ {
+ syntaxTree.Members.Add(CreateField(field));
+ }
+
+ public void AddEvent(EventDefinition ev)
+ {
+ syntaxTree.Members.Add(CreateEvent(ev));
+ }
+
+ /// <summary>
+ /// Creates the AST for a type definition.
+ /// </summary>
+ /// <param name="typeDef"></param>
+ /// <returns>TypeDeclaration or DelegateDeclaration.</returns>
+ public EntityDeclaration CreateType(TypeDefinition typeDef)
+ {
+ // create type
+ TypeDefinition oldCurrentType = context.CurrentType;
+ context.CurrentType = typeDef;
+ TypeDeclaration astType = new TypeDeclaration();
+ ConvertAttributes(astType, typeDef);
+ astType.AddAnnotation(typeDef);
+ astType.Modifiers = ConvertModifiers(typeDef);
+ astType.Name = CleanName(typeDef.Name);
+
+ if (typeDef.IsEnum) { // NB: Enum is value type
+ astType.ClassType = ClassType.Enum;
+ astType.Modifiers &= ~Modifiers.Sealed;
+ } else if (typeDef.IsValueType) {
+ astType.ClassType = ClassType.Struct;
+ astType.Modifiers &= ~Modifiers.Sealed;
+ } else if (typeDef.IsInterface) {
+ astType.ClassType = ClassType.Interface;
+ astType.Modifiers &= ~Modifiers.Abstract;
+ } else {
+ astType.ClassType = ClassType.Class;
+ }
+
+ IEnumerable<GenericParameter> genericParameters = typeDef.GenericParameters;
+ if (typeDef.DeclaringType != null && typeDef.DeclaringType.HasGenericParameters)
+ genericParameters = genericParameters.Skip(typeDef.DeclaringType.GenericParameters.Count);
+ astType.TypeParameters.AddRange(MakeTypeParameters(genericParameters));
+ astType.Constraints.AddRange(MakeConstraints(genericParameters));
+
+ EntityDeclaration result = astType;
+ if (typeDef.IsEnum) {
+ long expectedEnumMemberValue = 0;
+ bool forcePrintingInitializers = IsFlagsEnum(typeDef);
+ TypeCode baseType = TypeCode.Int32;
+ foreach (FieldDefinition field in typeDef.Fields) {
+ if (!field.IsStatic) {
+ // the value__ field
+ if (field.FieldType != typeDef.Module.TypeSystem.Int32) {
+ astType.AddChild(ConvertType(field.FieldType), Roles.BaseType);
+ baseType = TypeAnalysis.GetTypeCode(field.FieldType);
+ }
+ } else {
+ EnumMemberDeclaration enumMember = new EnumMemberDeclaration();
+ enumMember.AddAnnotation(field);
+ enumMember.Name = CleanName(field.Name);
+ long memberValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false);
+ if (forcePrintingInitializers || memberValue != expectedEnumMemberValue) {
+ enumMember.AddChild(new PrimitiveExpression(CSharpPrimitiveCast.Cast(baseType, field.Constant, false)), EnumMemberDeclaration.InitializerRole);
+ }
+ expectedEnumMemberValue = memberValue + 1;
+ astType.AddChild(enumMember, Roles.TypeMemberRole);
+ }
+ }
+ } else if (typeDef.BaseType != null && typeDef.BaseType.FullName == "System.MulticastDelegate") {
+ DelegateDeclaration dd = new DelegateDeclaration();
+ dd.Modifiers = astType.Modifiers & ~Modifiers.Sealed;
+ dd.Name = astType.Name;
+ dd.AddAnnotation(typeDef);
+ astType.Attributes.MoveTo(dd.Attributes);
+ astType.TypeParameters.MoveTo(dd.TypeParameters);
+ astType.Constraints.MoveTo(dd.Constraints);
+ foreach (var m in typeDef.Methods) {
+ if (m.Name == "Invoke") {
+ dd.ReturnType = ConvertType(m.ReturnType, m.MethodReturnType);
+ dd.Parameters.AddRange(MakeParameters(m));
+ ConvertAttributes(dd, m.MethodReturnType, m.Module);
+ }
+ }
+ result = dd;
+ } else {
+ // Base type
+ if (typeDef.BaseType != null && !typeDef.IsValueType && typeDef.BaseType.FullName != "System.Object") {
+ astType.AddChild(ConvertType(typeDef.BaseType), Roles.BaseType);
+ }
+ foreach (var i in typeDef.Interfaces)
+ astType.AddChild(ConvertType(i), Roles.BaseType);
+
+ AddTypeMembers(astType, typeDef);
+
+ if (astType.Members.OfType<IndexerDeclaration>().Any(idx => idx.PrivateImplementationType.IsNull)) {
+ // Remove the [DefaultMember] attribute if the class contains indexers
+ foreach (AttributeSection section in astType.Attributes) {
+ foreach (Ast.Attribute attr in section.Attributes) {
+ TypeReference tr = attr.Type.Annotation<TypeReference>();
+ if (tr != null && tr.Name == "DefaultMemberAttribute" && tr.Namespace == "System.Reflection") {
+ attr.Remove();
+ }
+ }
+ if (section.Attributes.Count == 0)
+ section.Remove();
+ }
+ }
+ }
+
+ context.CurrentType = oldCurrentType;
+ return result;
+ }
+
+ internal static string CleanName(string name)
+ {
+ int pos = name.LastIndexOf('`');
+ if (pos >= 0)
+ name = name.Substring(0, pos);
+ pos = name.LastIndexOf('.');
+ if (pos >= 0)
+ name = name.Substring(pos + 1);
+ return name;
+ }
+
+ #region Create TypeOf Expression
+ /// <summary>
+ /// Creates a typeof-expression for the specified type.
+ /// </summary>
+ public static TypeOfExpression CreateTypeOfExpression(TypeReference type)
+ {
+ return new TypeOfExpression(AddEmptyTypeArgumentsForUnboundGenerics(ConvertType(type)));
+ }
+
+ static AstType AddEmptyTypeArgumentsForUnboundGenerics(AstType type)
+ {
+ TypeReference typeRef = type.Annotation<TypeReference>();
+ if (typeRef == null)
+ return type;
+ TypeDefinition typeDef = typeRef.Resolve(); // need to resolve to figure out the number of type parameters
+ if (typeDef == null || !typeDef.HasGenericParameters)
+ return type;
+ SimpleType sType = type as SimpleType;
+ MemberType mType = type as MemberType;
+ if (sType != null) {
+ while (typeDef.GenericParameters.Count > sType.TypeArguments.Count) {
+ sType.TypeArguments.Add(new SimpleType(""));
+ }
+ }
+
+ if (mType != null) {
+ AddEmptyTypeArgumentsForUnboundGenerics(mType.Target);
+
+ int outerTypeParamCount = typeDef.DeclaringType == null ? 0 : typeDef.DeclaringType.GenericParameters.Count;
+
+ while (typeDef.GenericParameters.Count - outerTypeParamCount > mType.TypeArguments.Count) {
+ mType.TypeArguments.Add(new SimpleType(""));
+ }
+ }
+
+ return type;
+ }
+ #endregion
+
+ #region Convert Type Reference
+ /// <summary>
+ /// Converts a type reference.
+ /// </summary>
+ /// <param name="type">The Cecil type reference that should be converted into
+ /// a type system type reference.</param>
+ /// <param name="typeAttributes">Attributes associated with the Cecil type reference.
+ /// This is used to support the 'dynamic' type.</param>
+ public static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes = null, ConvertTypeOptions options = ConvertTypeOptions.None)
+ {
+ int typeIndex = 0;
+ return ConvertType(type, typeAttributes, ref typeIndex, options);
+ }
+
+ static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex, ConvertTypeOptions options)
+ {
+ while (type is OptionalModifierType || type is RequiredModifierType) {
+ type = ((TypeSpecification)type).ElementType;
+ }
+ if (type == null) {
+ return AstType.Null;
+ }
+
+ if (type is ByReferenceType) {
+ typeIndex++;
+ // by reference type cannot be represented in C#; so we'll represent it as a pointer instead
+ return ConvertType((type as ByReferenceType).ElementType, typeAttributes, ref typeIndex, options)
+ .MakePointerType();
+ } else if (type is PointerType) {
+ typeIndex++;
+ return ConvertType((type as PointerType).ElementType, typeAttributes, ref typeIndex, options)
+ .MakePointerType();
+ } else if (type is ArrayType) {
+ typeIndex++;
+ return ConvertType((type as ArrayType).ElementType, typeAttributes, ref typeIndex, options)
+ .MakeArrayType((type as ArrayType).Rank);
+ } else if (type is GenericInstanceType) {
+ GenericInstanceType gType = (GenericInstanceType)type;
+ if (gType.ElementType.Namespace == "System" && gType.ElementType.Name == "Nullable`1" && gType.GenericArguments.Count == 1) {
+ typeIndex++;
+ return new ComposedType {
+ BaseType = ConvertType(gType.GenericArguments[0], typeAttributes, ref typeIndex, options),
+ HasNullableSpecifier = true
+ };
+ }
+ AstType baseType = ConvertType(gType.ElementType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions);
+ List<AstType> typeArguments = new List<AstType>();
+ foreach (var typeArgument in gType.GenericArguments) {
+ typeIndex++;
+ typeArguments.Add(ConvertType(typeArgument, typeAttributes, ref typeIndex, options));
+ }
+ ApplyTypeArgumentsTo(baseType, typeArguments);
+ return baseType;
+ } else if (type is GenericParameter) {
+ return new SimpleType(type.Name);
+ } else if (type.IsNested) {
+ AstType typeRef = ConvertType(type.DeclaringType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions);
+ string namepart = NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name);
+ MemberType memberType = new MemberType { Target = typeRef, MemberName = namepart };
+ memberType.AddAnnotation(type);
+ if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) {
+ AddTypeParameterDefininitionsTo(type, memberType);
+ }
+ return memberType;
+ } else {
+ string ns = type.Namespace ?? string.Empty;
+ string name = type.Name;
+ if (name == null)
+ throw new InvalidOperationException("type.Name returned null. Type: " + type.ToString());
+
+ if (name == "Object" && ns == "System" && HasDynamicAttribute(typeAttributes, typeIndex)) {
+ return new PrimitiveType("dynamic");
+ } else {
+ if (ns == "System") {
+ if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames)
+ != ConvertTypeOptions.DoNotUsePrimitiveTypeNames) {
+ switch (name) {
+ case "SByte":
+ return new PrimitiveType("sbyte");
+ case "Int16":
+ return new PrimitiveType("short");
+ case "Int32":
+ return new PrimitiveType("int");
+ case "Int64":
+ return new PrimitiveType("long");
+ case "Byte":
+ return new PrimitiveType("byte");
+ case "UInt16":
+ return new PrimitiveType("ushort");
+ case "UInt32":
+ return new PrimitiveType("uint");
+ case "UInt64":
+ return new PrimitiveType("ulong");
+ case "String":
+ return new PrimitiveType("string");
+ case "Single":
+ return new PrimitiveType("float");
+ case "Double":
+ return new PrimitiveType("double");
+ case "Decimal":
+ return new PrimitiveType("decimal");
+ case "Char":
+ return new PrimitiveType("char");
+ case "Boolean":
+ return new PrimitiveType("bool");
+ case "Void":
+ return new PrimitiveType("void");
+ case "Object":
+ return new PrimitiveType("object");
+ }
+ }
+ }
+
+ name = NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(name);
+
+ AstType astType;
+ if ((options & ConvertTypeOptions.IncludeNamespace) == ConvertTypeOptions.IncludeNamespace && ns.Length > 0) {
+ string[] parts = ns.Split('.');
+ AstType nsType = new SimpleType(parts[0]);
+ for (int i = 1; i < parts.Length; i++) {
+ nsType = new MemberType { Target = nsType, MemberName = parts[i] };
+ }
+ astType = new MemberType { Target = nsType, MemberName = name };
+ } else {
+ astType = new SimpleType(name);
+ }
+ astType.AddAnnotation(type);
+
+ if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) {
+ AddTypeParameterDefininitionsTo(type, astType);
+ }
+ return astType;
+ }
+ }
+ }
+
+ static void AddTypeParameterDefininitionsTo(TypeReference type, AstType astType)
+ {
+ if (type.HasGenericParameters) {
+ List<AstType> typeArguments = new List<AstType>();
+ foreach (GenericParameter gp in type.GenericParameters) {
+ typeArguments.Add(new SimpleType(gp.Name));
+ }
+ ApplyTypeArgumentsTo(astType, typeArguments);
+ }
+ }
+
+ static void ApplyTypeArgumentsTo(AstType baseType, List<AstType> typeArguments)
+ {
+ SimpleType st = baseType as SimpleType;
+ if (st != null) {
+ st.TypeArguments.AddRange(typeArguments);
+ }
+ MemberType mt = baseType as MemberType;
+ if (mt != null) {
+ TypeReference type = mt.Annotation<TypeReference>();
+ if (type != null) {
+ int typeParameterCount;
+ NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
+ if (typeParameterCount > typeArguments.Count)
+ typeParameterCount = typeArguments.Count;
+ mt.TypeArguments.AddRange(typeArguments.GetRange(typeArguments.Count - typeParameterCount, typeParameterCount));
+ typeArguments.RemoveRange(typeArguments.Count - typeParameterCount, typeParameterCount);
+ if (typeArguments.Count > 0)
+ ApplyTypeArgumentsTo(mt.Target, typeArguments);
+ } else {
+ mt.TypeArguments.AddRange(typeArguments);
+ }
+ }
+ }
+
+ const string DynamicAttributeFullName = "System.Runtime.CompilerServices.DynamicAttribute";
+
+ static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex)
+ {
+ if (attributeProvider == null || !attributeProvider.HasCustomAttributes)
+ return false;
+ foreach (CustomAttribute a in attributeProvider.CustomAttributes) {
+ if (a.Constructor.DeclaringType.FullName == DynamicAttributeFullName) {
+ if (a.ConstructorArguments.Count == 1) {
+ CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[];
+ if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool)
+ return (bool)values[typeIndex].Value;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+ #endregion
+
+ #region ConvertModifiers
+ Modifiers ConvertModifiers(TypeDefinition typeDef)
+ {
+ Modifiers modifiers = Modifiers.None;
+ if (typeDef.IsNestedPrivate)
+ modifiers |= Modifiers.Private;
+ else if (typeDef.IsNestedAssembly || typeDef.IsNestedFamilyAndAssembly || typeDef.IsNotPublic)
+ modifiers |= Modifiers.Internal;
+ else if (typeDef.IsNestedFamily)
+ modifiers |= Modifiers.Protected;
+ else if (typeDef.IsNestedFamilyOrAssembly)
+ modifiers |= Modifiers.Protected | Modifiers.Internal;
+ else if (typeDef.IsPublic || typeDef.IsNestedPublic)
+ modifiers |= Modifiers.Public;
+
+ if (typeDef.IsAbstract && typeDef.IsSealed)
+ modifiers |= Modifiers.Static;
+ else if (typeDef.IsAbstract)
+ modifiers |= Modifiers.Abstract;
+ else if (typeDef.IsSealed)
+ modifiers |= Modifiers.Sealed;
+
+ return modifiers;
+ }
+
+ Modifiers ConvertModifiers(FieldDefinition fieldDef)
+ {
+ Modifiers modifiers = Modifiers.None;
+ if (fieldDef.IsPrivate)
+ modifiers |= Modifiers.Private;
+ else if (fieldDef.IsAssembly || fieldDef.IsFamilyAndAssembly)
+ modifiers |= Modifiers.Internal;
+ else if (fieldDef.IsFamily)
+ modifiers |= Modifiers.Protected;
+ else if (fieldDef.IsFamilyOrAssembly)
+ modifiers |= Modifiers.Protected | Modifiers.Internal;
+ else if (fieldDef.IsPublic)
+ modifiers |= Modifiers.Public;
+
+ if (fieldDef.IsLiteral) {
+ modifiers |= Modifiers.Const;
+ } else {
+ if (fieldDef.IsStatic)
+ modifiers |= Modifiers.Static;
+
+ if (fieldDef.IsInitOnly)
+ modifiers |= Modifiers.Readonly;
+ }
+
+ RequiredModifierType modreq = fieldDef.FieldType as RequiredModifierType;
+ if (modreq != null && modreq.ModifierType.FullName == typeof(IsVolatile).FullName)
+ modifiers |= Modifiers.Volatile;
+
+ return modifiers;
+ }
+
+ Modifiers ConvertModifiers(MethodDefinition methodDef)
+ {
+ if (methodDef == null)
+ return Modifiers.None;
+ Modifiers modifiers = Modifiers.None;
+ if (methodDef.IsPrivate)
+ modifiers |= Modifiers.Private;
+ else if (methodDef.IsAssembly || methodDef.IsFamilyAndAssembly)
+ modifiers |= Modifiers.Internal;
+ else if (methodDef.IsFamily)
+ modifiers |= Modifiers.Protected;
+ else if (methodDef.IsFamilyOrAssembly)
+ modifiers |= Modifiers.Protected | Modifiers.Internal;
+ else if (methodDef.IsPublic)
+ modifiers |= Modifiers.Public;
+
+ if (methodDef.IsStatic)
+ modifiers |= Modifiers.Static;
+
+ if (methodDef.IsAbstract) {
+ modifiers |= Modifiers.Abstract;
+ if (!methodDef.IsNewSlot)
+ modifiers |= Modifiers.Override;
+ } else if (methodDef.IsFinal) {
+ if (!methodDef.IsNewSlot) {
+ modifiers |= Modifiers.Sealed | Modifiers.Override;
+ }
+ } else if (methodDef.IsVirtual) {
+ if (methodDef.IsNewSlot)
+ modifiers |= Modifiers.Virtual;
+ else
+ modifiers |= Modifiers.Override;
+ }
+ if (!methodDef.HasBody && !methodDef.IsAbstract)
+ modifiers |= Modifiers.Extern;
+
+ return modifiers;
+ }
+
+ #endregion
+
+ void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef)
+ {
+ // Nested types
+ foreach (TypeDefinition nestedTypeDef in typeDef.NestedTypes) {
+ if (MemberIsHidden(nestedTypeDef, context.Settings))
+ continue;
+ var nestedType = CreateType(nestedTypeDef);
+ SetNewModifier(nestedType);
+ astType.AddChild(nestedType, Roles.TypeMemberRole);
+ }
+
+ // Add fields
+ foreach(FieldDefinition fieldDef in typeDef.Fields) {
+ if (MemberIsHidden(fieldDef, context.Settings)) continue;
+ astType.AddChild(CreateField(fieldDef), Roles.TypeMemberRole);
+ }
+
+ // Add events
+ foreach(EventDefinition eventDef in typeDef.Events) {
+ astType.AddChild(CreateEvent(eventDef), Roles.TypeMemberRole);
+ }
+
+ // Add properties
+ foreach(PropertyDefinition propDef in typeDef.Properties) {
+ astType.Members.Add(CreateProperty(propDef));
+ }
+
+ // Add methods
+ foreach(MethodDefinition methodDef in typeDef.Methods) {
+ if (MemberIsHidden(methodDef, context.Settings)) continue;
+
+ if (methodDef.IsConstructor)
+ astType.Members.Add(CreateConstructor(methodDef));
+ else
+ astType.Members.Add(CreateMethod(methodDef));
+ }
+ }
+
+ EntityDeclaration CreateMethod(MethodDefinition methodDef)
+ {
+ MethodDeclaration astMethod = new MethodDeclaration();
+ astMethod.AddAnnotation(methodDef);
+ astMethod.ReturnType = ConvertType(methodDef.ReturnType, methodDef.MethodReturnType);
+ astMethod.Name = CleanName(methodDef.Name);
+ astMethod.TypeParameters.AddRange(MakeTypeParameters(methodDef.GenericParameters));
+ astMethod.Parameters.AddRange(MakeParameters(methodDef));
+ // constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly
+ if (!methodDef.IsVirtual || (methodDef.IsNewSlot && !methodDef.IsPrivate)) astMethod.Constraints.AddRange(MakeConstraints(methodDef.GenericParameters));
+ if (!methodDef.DeclaringType.IsInterface) {
+ if (IsExplicitInterfaceImplementation(methodDef)) {
+ astMethod.PrivateImplementationType = ConvertType(methodDef.Overrides.First().DeclaringType);
+ } else {
+ astMethod.Modifiers = ConvertModifiers(methodDef);
+ if (methodDef.IsVirtual == methodDef.IsNewSlot)
+ SetNewModifier(astMethod);
+ }
+ astMethod.Body = CreateMethodBody(methodDef, astMethod.Parameters);
+ if (context.CurrentMethodIsAsync) {
+ astMethod.Modifiers |= Modifiers.Async;
+ context.CurrentMethodIsAsync = false;
+ }
+ }
+ ConvertAttributes(astMethod, methodDef);
+ if (methodDef.HasCustomAttributes && astMethod.Parameters.Count > 0) {
+ foreach (CustomAttribute ca in methodDef.CustomAttributes) {
+ if (ca.AttributeType.Name == "ExtensionAttribute" && ca.AttributeType.Namespace == "System.Runtime.CompilerServices") {
+ astMethod.Parameters.First().ParameterModifier = ParameterModifier.This;
+ }
+ }
+ }
+
+ // Convert MethodDeclaration to OperatorDeclaration if possible
+ if (methodDef.IsSpecialName && !methodDef.HasGenericParameters) {
+ OperatorType? opType = OperatorDeclaration.GetOperatorType(methodDef.Name);
+ if (opType.HasValue) {
+ OperatorDeclaration op = new OperatorDeclaration();
+ op.CopyAnnotationsFrom(astMethod);
+ op.ReturnType = astMethod.ReturnType.Detach();
+ op.OperatorType = opType.Value;
+ op.Modifiers = astMethod.Modifiers;
+ astMethod.Parameters.MoveTo(op.Parameters);
+ astMethod.Attributes.MoveTo(op.Attributes);
+ op.Body = astMethod.Body.Detach();
+ return op;
+ }
+ }
+ return astMethod;
+ }
+
+ bool IsExplicitInterfaceImplementation(MethodDefinition methodDef)
+ {
+ return methodDef.HasOverrides && methodDef.IsPrivate;
+ }
+
+ IEnumerable<TypeParameterDeclaration> MakeTypeParameters(IEnumerable<GenericParameter> genericParameters)
+ {
+ foreach (var gp in genericParameters) {
+ TypeParameterDeclaration tp = new TypeParameterDeclaration();
+ tp.Name = CleanName(gp.Name);
+ if (gp.IsContravariant)
+ tp.Variance = VarianceModifier.Contravariant;
+ else if (gp.IsCovariant)
+ tp.Variance = VarianceModifier.Covariant;
+ ConvertCustomAttributes(tp, gp);
+ yield return tp;
+ }
+ }
+
+ IEnumerable<Constraint> MakeConstraints(IEnumerable<GenericParameter> genericParameters)
+ {
+ foreach (var gp in genericParameters) {
+ Constraint c = new Constraint();
+ c.TypeParameter = new SimpleType(CleanName(gp.Name));
+ // class/struct must be first
+ if (gp.HasReferenceTypeConstraint)
+ c.BaseTypes.Add(new PrimitiveType("class"));
+ if (gp.HasNotNullableValueTypeConstraint)
+ c.BaseTypes.Add(new PrimitiveType("struct"));
+
+ foreach (var constraintType in gp.Constraints) {
+ if (gp.HasNotNullableValueTypeConstraint && constraintType.FullName == "System.ValueType")
+ continue;
+ c.BaseTypes.Add(ConvertType(constraintType));
+ }
+
+ if (gp.HasDefaultConstructorConstraint && !gp.HasNotNullableValueTypeConstraint)
+ c.BaseTypes.Add(new PrimitiveType("new")); // new() must be last
+ if (c.BaseTypes.Any())
+ yield return c;
+ }
+ }
+
+ ConstructorDeclaration CreateConstructor(MethodDefinition methodDef)
+ {
+ ConstructorDeclaration astMethod = new ConstructorDeclaration();
+ astMethod.AddAnnotation(methodDef);
+ astMethod.Modifiers = ConvertModifiers(methodDef);
+ if (methodDef.IsStatic) {
+ // don't show visibility for static ctors
+ astMethod.Modifiers &= ~Modifiers.VisibilityMask;
+ }
+ astMethod.Name = CleanName(methodDef.DeclaringType.Name);
+ astMethod.Parameters.AddRange(MakeParameters(methodDef));
+ astMethod.Body = CreateMethodBody(methodDef, astMethod.Parameters);
+ ConvertAttributes(astMethod, methodDef);
+ if (methodDef.IsStatic && methodDef.DeclaringType.IsBeforeFieldInit && !astMethod.Body.IsNull) {
+ astMethod.Body.InsertChildAfter(null, new Comment(" Note: this type is marked as 'beforefieldinit'."), Roles.Comment);
+ }
+ return astMethod;
+ }
+
+ Modifiers FixUpVisibility(Modifiers m)
+ {
+ Modifiers v = m & Modifiers.VisibilityMask;
+ // If any of the modifiers is public, use that
+ if ((v & Modifiers.Public) == Modifiers.Public)
+ return Modifiers.Public | (m & ~Modifiers.VisibilityMask);
+ // If both modifiers are private, no need to fix anything
+ if (v == Modifiers.Private)
+ return m;
+ // Otherwise, use the other modifiers (internal and/or protected)
+ return m & ~Modifiers.Private;
+ }
+
+ EntityDeclaration CreateProperty(PropertyDefinition propDef)
+ {
+ PropertyDeclaration astProp = new PropertyDeclaration();
+ astProp.AddAnnotation(propDef);
+ var accessor = propDef.GetMethod ?? propDef.SetMethod;
+ Modifiers getterModifiers = Modifiers.None;
+ Modifiers setterModifiers = Modifiers.None;
+ if (IsExplicitInterfaceImplementation(accessor)) {
+ astProp.PrivateImplementationType = ConvertType(accessor.Overrides.First().DeclaringType);
+ } else if (!propDef.DeclaringType.IsInterface) {
+ getterModifiers = ConvertModifiers(propDef.GetMethod);
+ setterModifiers = ConvertModifiers(propDef.SetMethod);
+ astProp.Modifiers = FixUpVisibility(getterModifiers | setterModifiers);
+ try {
+ if (accessor.IsVirtual && !accessor.IsNewSlot && (propDef.GetMethod == null || propDef.SetMethod == null)) {
+ foreach (var basePropDef in TypesHierarchyHelpers.FindBaseProperties(propDef)) {
+ if (basePropDef.GetMethod != null && basePropDef.SetMethod != null) {
+ var propVisibilityModifiers = ConvertModifiers(basePropDef.GetMethod) | ConvertModifiers(basePropDef.SetMethod);
+ astProp.Modifiers = FixUpVisibility((astProp.Modifiers & ~Modifiers.VisibilityMask) | (propVisibilityModifiers & Modifiers.VisibilityMask));
+ break;
+ } else if ((basePropDef.GetMethod ?? basePropDef.SetMethod).IsNewSlot) {
+ break;
+ }
+ }
+ }
+ } catch (ReferenceResolvingException) {
+ // TODO: add some kind of notification (a comment?) about possible problems with decompiled code due to unresolved references.
+ }
+ }
+ astProp.Name = CleanName(propDef.Name);
+ astProp.ReturnType = ConvertType(propDef.PropertyType, propDef);
+
+ if (propDef.GetMethod != null) {
+ astProp.Getter = new Accessor();
+ astProp.Getter.Body = CreateMethodBody(propDef.GetMethod);
+ astProp.Getter.AddAnnotation(propDef.GetMethod);
+ ConvertAttributes(astProp.Getter, propDef.GetMethod);
+
+ if ((getterModifiers & Modifiers.VisibilityMask) != (astProp.Modifiers & Modifiers.VisibilityMask))
+ astProp.Getter.Modifiers = getterModifiers & Modifiers.VisibilityMask;
+ }
+ if (propDef.SetMethod != null) {
+ astProp.Setter = new Accessor();
+ astProp.Setter.Body = CreateMethodBody(propDef.SetMethod);
+ astProp.Setter.AddAnnotation(propDef.SetMethod);
+ ConvertAttributes(astProp.Setter, propDef.SetMethod);
+ ParameterDefinition lastParam = propDef.SetMethod.Parameters.LastOrDefault();
+ if (lastParam != null) {
+ ConvertCustomAttributes(astProp.Setter, lastParam, "param");
+ if (lastParam.HasMarshalInfo) {
+ astProp.Setter.Attributes.Add(new AttributeSection(ConvertMarshalInfo(lastParam, propDef.Module)) { AttributeTarget = "param" });
+ }
+ }
+
+ if ((setterModifiers & Modifiers.VisibilityMask) != (astProp.Modifiers & Modifiers.VisibilityMask))
+ astProp.Setter.Modifiers = setterModifiers & Modifiers.VisibilityMask;
+ }
+ ConvertCustomAttributes(astProp, propDef);
+
+ EntityDeclaration member = astProp;
+ if(propDef.IsIndexer())
+ member = ConvertPropertyToIndexer(astProp, propDef);
+ if(!accessor.HasOverrides && !accessor.DeclaringType.IsInterface)
+ if (accessor.IsVirtual == accessor.IsNewSlot)
+ SetNewModifier(member);
+ return member;
+ }
+
+ IndexerDeclaration ConvertPropertyToIndexer(PropertyDeclaration astProp, PropertyDefinition propDef)
+ {
+ var astIndexer = new IndexerDeclaration();
+ astIndexer.CopyAnnotationsFrom(astProp);
+ astProp.Attributes.MoveTo(astIndexer.Attributes);
+ astIndexer.Modifiers = astProp.Modifiers;
+ astIndexer.PrivateImplementationType = astProp.PrivateImplementationType.Detach();
+ astIndexer.ReturnType = astProp.ReturnType.Detach();
+ astIndexer.Getter = astProp.Getter.Detach();
+ astIndexer.Setter = astProp.Setter.Detach();
+ astIndexer.Parameters.AddRange(MakeParameters(propDef.Parameters));
+ return astIndexer;
+ }
+
+ EntityDeclaration CreateEvent(EventDefinition eventDef)
+ {
+ if (eventDef.AddMethod != null && eventDef.AddMethod.IsAbstract) {
+ // An abstract event cannot be custom
+ EventDeclaration astEvent = new EventDeclaration();
+ ConvertCustomAttributes(astEvent, eventDef);
+ astEvent.AddAnnotation(eventDef);
+ astEvent.Variables.Add(new VariableInitializer(CleanName(eventDef.Name)));
+ astEvent.ReturnType = ConvertType(eventDef.EventType, eventDef);
+ if (!eventDef.DeclaringType.IsInterface)
+ astEvent.Modifiers = ConvertModifiers(eventDef.AddMethod);
+ return astEvent;
+ } else {
+ CustomEventDeclaration astEvent = new CustomEventDeclaration();
+ ConvertCustomAttributes(astEvent, eventDef);
+ astEvent.AddAnnotation(eventDef);
+ astEvent.Name = CleanName(eventDef.Name);
+ astEvent.ReturnType = ConvertType(eventDef.EventType, eventDef);
+ if (eventDef.AddMethod == null || !IsExplicitInterfaceImplementation(eventDef.AddMethod))
+ astEvent.Modifiers = ConvertModifiers(eventDef.AddMethod);
+ else
+ astEvent.PrivateImplementationType = ConvertType(eventDef.AddMethod.Overrides.First().DeclaringType);
+
+ if (eventDef.AddMethod != null) {
+ astEvent.AddAccessor = new Accessor {
+ Body = CreateMethodBody(eventDef.AddMethod)
+ }.WithAnnotation(eventDef.AddMethod);
+ ConvertAttributes(astEvent.AddAccessor, eventDef.AddMethod);
+ }
+ if (eventDef.RemoveMethod != null) {
+ astEvent.RemoveAccessor = new Accessor {
+ Body = CreateMethodBody(eventDef.RemoveMethod)
+ }.WithAnnotation(eventDef.RemoveMethod);
+ ConvertAttributes(astEvent.RemoveAccessor, eventDef.RemoveMethod);
+ }
+ MethodDefinition accessor = eventDef.AddMethod ?? eventDef.RemoveMethod;
+ if (accessor.IsVirtual == accessor.IsNewSlot) {
+ SetNewModifier(astEvent);
+ }
+ return astEvent;
+ }
+ }
+
+ public bool DecompileMethodBodies { get; set; }
+
+ BlockStatement CreateMethodBody(MethodDefinition method, IEnumerable<ParameterDeclaration> parameters = null)
+ {
+ if (DecompileMethodBodies)
+ return AstMethodBodyBuilder.CreateMethodBody(method, context, parameters);
+ else
+ return null;
+ }
+
+ FieldDeclaration CreateField(FieldDefinition fieldDef)
+ {
+ FieldDeclaration astField = new FieldDeclaration();
+ astField.AddAnnotation(fieldDef);
+ VariableInitializer initializer = new VariableInitializer(CleanName(fieldDef.Name));
+ astField.AddChild(initializer, Roles.Variable);
+ astField.ReturnType = ConvertType(fieldDef.FieldType, fieldDef);
+ astField.Modifiers = ConvertModifiers(fieldDef);
+ if (fieldDef.HasConstant) {
+ initializer.Initializer = CreateExpressionForConstant(fieldDef.Constant, fieldDef.FieldType, fieldDef.DeclaringType.IsEnum);
+ }
+ ConvertAttributes(astField, fieldDef);
+ SetNewModifier(astField);
+ return astField;
+ }
+
+ static Expression CreateExpressionForConstant(object constant, TypeReference type, bool isEnumMemberDeclaration = false)
+ {
+ if (constant == null) {
+ if (type.IsValueType && !(type.Namespace == "System" && type.Name == "Nullable`1"))
+ return new DefaultValueExpression(ConvertType(type));
+ else
+ return new NullReferenceExpression();
+ } else {
+ TypeCode c = Type.GetTypeCode(constant.GetType());
+ if (c >= TypeCode.SByte && c <= TypeCode.UInt64 && !isEnumMemberDeclaration) {
+ return MakePrimitive((long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constant, false), type);
+ } else {
+ return new PrimitiveExpression(constant);
+ }
+ }
+ }
+
+ public static IEnumerable<ParameterDeclaration> MakeParameters(MethodDefinition method, bool isLambda = false)
+ {
+ var parameters = MakeParameters(method.Parameters, isLambda);
+ if (method.CallingConvention == MethodCallingConvention.VarArg) {
+ return parameters.Concat(new[] { new ParameterDeclaration { Type = new PrimitiveType("__arglist") } });
+ } else {
+ return parameters;
+ }
+ }
+
+ public static IEnumerable<ParameterDeclaration> MakeParameters(IEnumerable<ParameterDefinition> paramCol, bool isLambda = false)
+ {
+ foreach(ParameterDefinition paramDef in paramCol) {
+ ParameterDeclaration astParam = new ParameterDeclaration();
+ astParam.AddAnnotation(paramDef);
+ if (!(isLambda && paramDef.ParameterType.ContainsAnonymousType()))
+ astParam.Type = ConvertType(paramDef.ParameterType, paramDef);
+ astParam.Name = paramDef.Name;
+
+ if (paramDef.ParameterType is ByReferenceType) {
+ astParam.ParameterModifier = (!paramDef.IsIn && paramDef.IsOut) ? ParameterModifier.Out : ParameterModifier.Ref;
+ ComposedType ct = astParam.Type as ComposedType;
+ if (ct != null && ct.PointerRank > 0)
+ ct.PointerRank--;
+ }
+
+ if (paramDef.HasCustomAttributes) {
+ foreach (CustomAttribute ca in paramDef.CustomAttributes) {
+ if (ca.AttributeType.Name == "ParamArrayAttribute" && ca.AttributeType.Namespace == "System")
+ astParam.ParameterModifier = ParameterModifier.Params;
+ }
+ }
+ if (paramDef.IsOptional) {
+ astParam.DefaultExpression = CreateExpressionForConstant(paramDef.Constant, paramDef.ParameterType);
+ }
+
+ ConvertCustomAttributes(astParam, paramDef);
+ ModuleDefinition module = ((MethodDefinition)paramDef.Method).Module;
+ if (paramDef.HasMarshalInfo) {
+ astParam.Attributes.Add(new AttributeSection(ConvertMarshalInfo(paramDef, module)));
+ }
+ if (astParam.ParameterModifier != ParameterModifier.Out) {
+ if (paramDef.IsIn)
+ astParam.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(InAttribute), module)));
+ if (paramDef.IsOut)
+ astParam.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(OutAttribute), module)));
+ }
+ yield return astParam;
+ }
+ }
+
+ #region ConvertAttributes
+ void ConvertAttributes(EntityDeclaration attributedNode, TypeDefinition typeDefinition)
+ {
+ ConvertCustomAttributes(attributedNode, typeDefinition);
+ ConvertSecurityAttributes(attributedNode, typeDefinition);
+
+ // Handle the non-custom attributes:
+ #region SerializableAttribute
+ if (typeDefinition.IsSerializable)
+ attributedNode.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(SerializableAttribute))));
+ #endregion
+
+ #region ComImportAttribute
+ if (typeDefinition.IsImport)
+ attributedNode.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(ComImportAttribute))));
+ #endregion
+
+ #region StructLayoutAttribute
+ LayoutKind layoutKind = LayoutKind.Auto;
+ switch (typeDefinition.Attributes & TypeAttributes.LayoutMask) {
+ case TypeAttributes.SequentialLayout:
+ layoutKind = LayoutKind.Sequential;
+ break;
+ case TypeAttributes.ExplicitLayout:
+ layoutKind = LayoutKind.Explicit;
+ break;
+ }
+ CharSet charSet = CharSet.None;
+ switch (typeDefinition.Attributes & TypeAttributes.StringFormatMask) {
+ case TypeAttributes.AnsiClass:
+ charSet = CharSet.Ansi;
+ break;
+ case TypeAttributes.AutoClass:
+ charSet = CharSet.Auto;
+ break;
+ case TypeAttributes.UnicodeClass:
+ charSet = CharSet.Unicode;
+ break;
+ }
+ LayoutKind defaultLayoutKind = (typeDefinition.IsValueType && !typeDefinition.IsEnum) ? LayoutKind.Sequential: LayoutKind.Auto;
+ if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || typeDefinition.PackingSize > 0 || typeDefinition.ClassSize > 0) {
+ var structLayout = CreateNonCustomAttribute(typeof(StructLayoutAttribute));
+ structLayout.Arguments.Add(new IdentifierExpression("LayoutKind").Member(layoutKind.ToString()));
+ if (charSet != CharSet.Ansi) {
+ structLayout.AddNamedArgument("CharSet", new IdentifierExpression("CharSet").Member(charSet.ToString()));
+ }
+ if (typeDefinition.PackingSize > 0) {
+ structLayout.AddNamedArgument("Pack", new PrimitiveExpression((int)typeDefinition.PackingSize));
+ }
+ if (typeDefinition.ClassSize > 0) {
+ structLayout.AddNamedArgument("Size", new PrimitiveExpression((int)typeDefinition.ClassSize));
+ }
+ attributedNode.Attributes.Add(new AttributeSection(structLayout));
+ }
+ #endregion
+ }
+
+ void ConvertAttributes(EntityDeclaration attributedNode, MethodDefinition methodDefinition)
+ {
+ ConvertCustomAttributes(attributedNode, methodDefinition);
+ ConvertSecurityAttributes(attributedNode, methodDefinition);
+
+ MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask;
+
+ #region DllImportAttribute
+ if (methodDefinition.HasPInvokeInfo && methodDefinition.PInvokeInfo != null) {
+ PInvokeInfo info = methodDefinition.PInvokeInfo;
+ Ast.Attribute dllImport = CreateNonCustomAttribute(typeof(DllImportAttribute));
+ dllImport.Arguments.Add(new PrimitiveExpression(info.Module.Name));
+
+ if (info.IsBestFitDisabled)
+ dllImport.AddNamedArgument("BestFitMapping", new PrimitiveExpression(false));
+ if (info.IsBestFitEnabled)
+ dllImport.AddNamedArgument("BestFitMapping", new PrimitiveExpression(true));
+
+ CallingConvention callingConvention;
+ switch (info.Attributes & PInvokeAttributes.CallConvMask) {
+ case PInvokeAttributes.CallConvCdecl:
+ callingConvention = CallingConvention.Cdecl;
+ break;
+ case PInvokeAttributes.CallConvFastcall:
+ callingConvention = CallingConvention.FastCall;
+ break;
+ case PInvokeAttributes.CallConvStdCall:
+ callingConvention = CallingConvention.StdCall;
+ break;
+ case PInvokeAttributes.CallConvThiscall:
+ callingConvention = CallingConvention.ThisCall;
+ break;
+ case PInvokeAttributes.CallConvWinapi:
+ callingConvention = CallingConvention.Winapi;
+ break;
+ default:
+ throw new NotSupportedException("unknown calling convention");
+ }
+ if (callingConvention != CallingConvention.Winapi)
+ dllImport.AddNamedArgument("CallingConvention", new IdentifierExpression("CallingConvention").Member(callingConvention.ToString()));
+
+ CharSet charSet = CharSet.None;
+ switch (info.Attributes & PInvokeAttributes.CharSetMask) {
+ case PInvokeAttributes.CharSetAnsi:
+ charSet = CharSet.Ansi;
+ break;
+ case PInvokeAttributes.CharSetAuto:
+ charSet = CharSet.Auto;
+ break;
+ case PInvokeAttributes.CharSetUnicode:
+ charSet = CharSet.Unicode;
+ break;
+ }
+ if (charSet != CharSet.None)
+ dllImport.AddNamedArgument("CharSet", new IdentifierExpression("CharSet").Member(charSet.ToString()));
+
+ if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != methodDefinition.Name)
+ dllImport.AddNamedArgument("EntryPoint", new PrimitiveExpression(info.EntryPoint));
+
+ if (info.IsNoMangle)
+ dllImport.AddNamedArgument("ExactSpelling", new PrimitiveExpression(true));
+
+ if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig)
+ implAttributes &= ~MethodImplAttributes.PreserveSig;
+ else
+ dllImport.AddNamedArgument("PreserveSig", new PrimitiveExpression(false));
+
+ if (info.SupportsLastError)
+ dllImport.AddNamedArgument("SetLastError", new PrimitiveExpression(true));
+
+ if (info.IsThrowOnUnmappableCharDisabled)
+ dllImport.AddNamedArgument("ThrowOnUnmappableChar", new PrimitiveExpression(false));
+ if (info.IsThrowOnUnmappableCharEnabled)
+ dllImport.AddNamedArgument("ThrowOnUnmappableChar", new PrimitiveExpression(true));
+
+ attributedNode.Attributes.Add(new AttributeSection(dllImport));
+ }
+ #endregion
+
+ #region PreserveSigAttribute
+ if (implAttributes == MethodImplAttributes.PreserveSig) {
+ attributedNode.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(PreserveSigAttribute))));
+ implAttributes = 0;
+ }
+ #endregion
+
+ #region MethodImplAttribute
+ if (implAttributes != 0) {
+ Ast.Attribute methodImpl = CreateNonCustomAttribute(typeof(MethodImplAttribute));
+ TypeReference methodImplOptions = new TypeReference(
+ "System.Runtime.CompilerServices", "MethodImplOptions",
+ methodDefinition.Module, methodDefinition.Module.TypeSystem.Corlib);
+ methodImpl.Arguments.Add(MakePrimitive((long)implAttributes, methodImplOptions));
+ attributedNode.Attributes.Add(new AttributeSection(methodImpl));
+ }
+ #endregion
+
+ ConvertAttributes(attributedNode, methodDefinition.MethodReturnType, methodDefinition.Module);
+ }
+
+ void ConvertAttributes(EntityDeclaration attributedNode, MethodReturnType methodReturnType, ModuleDefinition module)
+ {
+ ConvertCustomAttributes(attributedNode, methodReturnType, "return");
+ if (methodReturnType.HasMarshalInfo) {
+ var marshalInfo = ConvertMarshalInfo(methodReturnType, module);
+ attributedNode.Attributes.Add(new AttributeSection(marshalInfo) { AttributeTarget = "return" });
+ }
+ }
+
+ internal static void ConvertAttributes(EntityDeclaration attributedNode, FieldDefinition fieldDefinition, string attributeTarget = null)
+ {
+ ConvertCustomAttributes(attributedNode, fieldDefinition);
+
+ #region FieldOffsetAttribute
+ if (fieldDefinition.HasLayoutInfo) {
+ Ast.Attribute fieldOffset = CreateNonCustomAttribute(typeof(FieldOffsetAttribute), fieldDefinition.Module);
+ fieldOffset.Arguments.Add(new PrimitiveExpression(fieldDefinition.Offset));
+ attributedNode.Attributes.Add(new AttributeSection(fieldOffset) { AttributeTarget = attributeTarget });
+ }
+ #endregion
+
+ #region NonSerializedAttribute
+ if (fieldDefinition.IsNotSerialized) {
+ Ast.Attribute nonSerialized = CreateNonCustomAttribute(typeof(NonSerializedAttribute), fieldDefinition.Module);
+ attributedNode.Attributes.Add(new AttributeSection(nonSerialized) { AttributeTarget = attributeTarget });
+ }
+ #endregion
+
+ if (fieldDefinition.HasMarshalInfo) {
+ attributedNode.Attributes.Add(new AttributeSection(ConvertMarshalInfo(fieldDefinition, fieldDefinition.Module)) { AttributeTarget = attributeTarget });
+ }
+ }
+
+ #region MarshalAsAttribute (ConvertMarshalInfo)
+ static Ast.Attribute ConvertMarshalInfo(IMarshalInfoProvider marshalInfoProvider, ModuleDefinition module)
+ {
+ MarshalInfo marshalInfo = marshalInfoProvider.MarshalInfo;
+ Ast.Attribute attr = CreateNonCustomAttribute(typeof(MarshalAsAttribute), module);
+ var unmanagedType = new TypeReference("System.Runtime.InteropServices", "UnmanagedType", module, module.TypeSystem.Corlib);
+ attr.Arguments.Add(MakePrimitive((int)marshalInfo.NativeType, unmanagedType));
+
+ FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo;
+ if (fami != null) {
+ attr.AddNamedArgument("SizeConst", new PrimitiveExpression(fami.Size));
+ if (fami.ElementType != NativeType.None)
+ attr.AddNamedArgument("ArraySubType", MakePrimitive((int)fami.ElementType, unmanagedType));
+ }
+ SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo;
+ if (sami != null && sami.ElementType != VariantType.None) {
+ var varEnum = new TypeReference("System.Runtime.InteropServices", "VarEnum", module, module.TypeSystem.Corlib);
+ attr.AddNamedArgument("SafeArraySubType", MakePrimitive((int)sami.ElementType, varEnum));
+ }
+ ArrayMarshalInfo ami = marshalInfo as ArrayMarshalInfo;
+ if (ami != null) {
+ if (ami.ElementType != NativeType.Max)
+ attr.AddNamedArgument("ArraySubType", MakePrimitive((int)ami.ElementType, unmanagedType));
+ if (ami.Size >= 0)
+ attr.AddNamedArgument("SizeConst", new PrimitiveExpression(ami.Size));
+ if (ami.SizeParameterMultiplier != 0 && ami.SizeParameterIndex >= 0)
+ attr.AddNamedArgument("SizeParamIndex", new PrimitiveExpression(ami.SizeParameterIndex));
+ }
+ CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo;
+ if (cmi != null) {
+ attr.AddNamedArgument("MarshalType", new PrimitiveExpression(cmi.ManagedType.FullName));
+ if (!string.IsNullOrEmpty(cmi.Cookie))
+ attr.AddNamedArgument("MarshalCookie", new PrimitiveExpression(cmi.Cookie));
+ }
+ FixedSysStringMarshalInfo fssmi = marshalInfo as FixedSysStringMarshalInfo;
+ if (fssmi != null) {
+ attr.AddNamedArgument("SizeConst", new PrimitiveExpression(fssmi.Size));
+ }
+ return attr;
+ }
+ #endregion
+
+ Ast.Attribute CreateNonCustomAttribute(Type attributeType)
+ {
+ return CreateNonCustomAttribute(attributeType, context.CurrentType != null ? context.CurrentType.Module : null);
+ }
+
+ static Ast.Attribute CreateNonCustomAttribute(Type attributeType, ModuleDefinition module)
+ {
+ Debug.Assert(attributeType.Name.EndsWith("Attribute", StringComparison.Ordinal));
+ Ast.Attribute attr = new Ast.Attribute();
+ attr.Type = new SimpleType(attributeType.Name.Substring(0, attributeType.Name.Length - "Attribute".Length));
+ if (module != null) {
+ attr.Type.AddAnnotation(new TypeReference(attributeType.Namespace, attributeType.Name, module, module.TypeSystem.Corlib));
+ }
+ return attr;
+ }
+
+ static void ConvertCustomAttributes(AstNode attributedNode, ICustomAttributeProvider customAttributeProvider, string attributeTarget = null)
+ {
+ EntityDeclaration entityDecl = attributedNode as EntityDeclaration;
+ if (customAttributeProvider.HasCustomAttributes) {
+ var attributes = new List<NRefactory.CSharp.Attribute>();
+ foreach (var customAttribute in customAttributeProvider.CustomAttributes.OrderBy(a => a.AttributeType.FullName)) {
+ if (customAttribute.AttributeType.Name == "ExtensionAttribute" && customAttribute.AttributeType.Namespace == "System.Runtime.CompilerServices") {
+ // don't show the ExtensionAttribute (it's converted to the 'this' modifier)
+ continue;
+ }
+ if (customAttribute.AttributeType.Name == "ParamArrayAttribute" && customAttribute.AttributeType.Namespace == "System") {
+ // don't show the ParamArrayAttribute (it's converted to the 'params' modifier)
+ continue;
+ }
+ // if the method is async, remove [DebuggerStepThrough] and [Async
+ if (entityDecl != null && entityDecl.HasModifier(Modifiers.Async)) {
+ if (customAttribute.AttributeType.Name == "DebuggerStepThroughAttribute" && customAttribute.AttributeType.Namespace == "System.Diagnostics") {
+ continue;
+ }
+ if (customAttribute.AttributeType.Name == "AsyncStateMachineAttribute" && customAttribute.AttributeType.Namespace == "System.Runtime.CompilerServices") {
+ continue;
+ }
+ }
+
+ var attribute = new NRefactory.CSharp.Attribute();
+ attribute.AddAnnotation(customAttribute);
+ attribute.Type = ConvertType(customAttribute.AttributeType);
+ attributes.Add(attribute);
+
+ SimpleType st = attribute.Type as SimpleType;
+ if (st != null && st.Identifier.EndsWith("Attribute", StringComparison.Ordinal)) {
+ st.Identifier = st.Identifier.Substring(0, st.Identifier.Length - "Attribute".Length);
+ }
+
+ if(customAttribute.HasConstructorArguments) {
+ foreach (var parameter in customAttribute.ConstructorArguments) {
+ Expression parameterValue = ConvertArgumentValue(parameter);
+ attribute.Arguments.Add(parameterValue);
+ }
+ }
+ if (customAttribute.HasProperties) {
+ TypeDefinition resolvedAttributeType = customAttribute.AttributeType.Resolve();
+ foreach (var propertyNamedArg in customAttribute.Properties) {
+ var propertyReference = resolvedAttributeType != null ? resolvedAttributeType.Properties.FirstOrDefault(pr => pr.Name == propertyNamedArg.Name) : null;
+ var propertyName = new IdentifierExpression(propertyNamedArg.Name).WithAnnotation(propertyReference);
+ var argumentValue = ConvertArgumentValue(propertyNamedArg.Argument);
+ attribute.Arguments.Add(new AssignmentExpression(propertyName, argumentValue));
+ }
+ }
+
+ if (customAttribute.HasFields) {
+ TypeDefinition resolvedAttributeType = customAttribute.AttributeType.Resolve();
+ foreach (var fieldNamedArg in customAttribute.Fields) {
+ var fieldReference = resolvedAttributeType != null ? resolvedAttributeType.Fields.FirstOrDefault(f => f.Name == fieldNamedArg.Name) : null;
+ var fieldName = new IdentifierExpression(fieldNamedArg.Name).WithAnnotation(fieldReference);
+ var argumentValue = ConvertArgumentValue(fieldNamedArg.Argument);
+ attribute.Arguments.Add(new AssignmentExpression(fieldName, argumentValue));
+ }
+ }
+ }
+
+ if (attributeTarget == "module" || attributeTarget == "assembly") {
+ // use separate section for each attribute
+ foreach (var attribute in attributes) {
+ var section = new AttributeSection();
+ section.AttributeTarget = attributeTarget;
+ section.Attributes.Add(attribute);
+ attributedNode.AddChild(section, EntityDeclaration.AttributeRole);
+ }
+ } else if (attributes.Count > 0) {
+ // use single section for all attributes
+ var section = new AttributeSection();
+ section.AttributeTarget = attributeTarget;
+ section.Attributes.AddRange(attributes);
+ attributedNode.AddChild(section, EntityDeclaration.AttributeRole);
+ }
+ }
+ }
+
+ static void ConvertSecurityAttributes(AstNode attributedNode, ISecurityDeclarationProvider secDeclProvider, string attributeTarget = null)
+ {
+ if (!secDeclProvider.HasSecurityDeclarations)
+ return;
+ var attributes = new List<NRefactory.CSharp.Attribute>();
+ foreach (var secDecl in secDeclProvider.SecurityDeclarations.OrderBy(d => d.Action)) {
+ foreach (var secAttribute in secDecl.SecurityAttributes.OrderBy(a => a.AttributeType.FullName)) {
+ var attribute = new NRefactory.CSharp.Attribute();
+ attribute.AddAnnotation(secAttribute);
+ attribute.Type = ConvertType(secAttribute.AttributeType);
+ attributes.Add(attribute);
+
+ SimpleType st = attribute.Type as SimpleType;
+ if (st != null && st.Identifier.EndsWith("Attribute", StringComparison.Ordinal)) {
+ st.Identifier = st.Identifier.Substring(0, st.Identifier.Length - "Attribute".Length);
+ }
+
+ var module = secAttribute.AttributeType.Module;
+ var securityActionType = new TypeReference("System.Security.Permissions", "SecurityAction", module, module.TypeSystem.Corlib);
+ attribute.Arguments.Add(MakePrimitive((int)secDecl.Action, securityActionType));
+
+ if (secAttribute.HasProperties) {
+ TypeDefinition resolvedAttributeType = secAttribute.AttributeType.Resolve();
+ foreach (var propertyNamedArg in secAttribute.Properties) {
+ var propertyReference = resolvedAttributeType != null ? resolvedAttributeType.Properties.FirstOrDefault(pr => pr.Name == propertyNamedArg.Name) : null;
+ var propertyName = new IdentifierExpression(propertyNamedArg.Name).WithAnnotation(propertyReference);
+ var argumentValue = ConvertArgumentValue(propertyNamedArg.Argument);
+ attribute.Arguments.Add(new AssignmentExpression(propertyName, argumentValue));
+ }
+ }
+
+ if (secAttribute.HasFields) {
+ TypeDefinition resolvedAttributeType = secAttribute.AttributeType.Resolve();
+ foreach (var fieldNamedArg in secAttribute.Fields) {
+ var fieldReference = resolvedAttributeType != null ? resolvedAttributeType.Fields.FirstOrDefault(f => f.Name == fieldNamedArg.Name) : null;
+ var fieldName = new IdentifierExpression(fieldNamedArg.Name).WithAnnotation(fieldReference);
+ var argumentValue = ConvertArgumentValue(fieldNamedArg.Argument);
+ attribute.Arguments.Add(new AssignmentExpression(fieldName, argumentValue));
+ }
+ }
+ }
+ }
+ if (attributeTarget == "module" || attributeTarget == "assembly") {
+ // use separate section for each attribute
+ foreach (var attribute in attributes) {
+ var section = new AttributeSection();
+ section.AttributeTarget = attributeTarget;
+ section.Attributes.Add(attribute);
+ attributedNode.AddChild(section, EntityDeclaration.AttributeRole);
+ }
+ } else if (attributes.Count > 0) {
+ // use single section for all attributes
+ var section = new AttributeSection();
+ section.AttributeTarget = attributeTarget;
+ section.Attributes.AddRange(attributes);
+ attributedNode.AddChild(section, EntityDeclaration.AttributeRole);
+ }
+ }
+
+ static Expression ConvertArgumentValue(CustomAttributeArgument argument)
+ {
+ if (argument.Value is CustomAttributeArgument[]) {
+ ArrayInitializerExpression arrayInit = new ArrayInitializerExpression();
+ foreach (CustomAttributeArgument element in (CustomAttributeArgument[])argument.Value) {
+ arrayInit.Elements.Add(ConvertArgumentValue(element));
+ }
+ ArrayType arrayType = argument.Type as ArrayType;
+ return new ArrayCreateExpression {
+ Type = ConvertType(arrayType != null ? arrayType.ElementType : argument.Type),
+ AdditionalArraySpecifiers = { new ArraySpecifier() },
+ Initializer = arrayInit
+ };
+ } else if (argument.Value is CustomAttributeArgument) {
+ // occurs with boxed arguments
+ return ConvertArgumentValue((CustomAttributeArgument)argument.Value);
+ }
+ var type = argument.Type.Resolve();
+ if (type != null && type.IsEnum) {
+ return MakePrimitive(Convert.ToInt64(argument.Value), type);
+ } else if (argument.Value is TypeReference) {
+ return CreateTypeOfExpression((TypeReference)argument.Value);
+ } else {
+ return new PrimitiveExpression(argument.Value);
+ }
+ }
+ #endregion
+
+ internal static Expression MakePrimitive(long val, TypeReference type)
+ {
+ if (TypeAnalysis.IsBoolean(type) && val == 0)
+ return new PrimitiveExpression(false);
+ else if (TypeAnalysis.IsBoolean(type) && val == 1)
+ return new PrimitiveExpression(true);
+ else if (val == 0 && type is PointerType)
+ return new NullReferenceExpression();
+ if (type != null)
+ { // cannot rely on type.IsValueType, it's not set for typerefs (but is set for typespecs)
+ TypeDefinition enumDefinition = type.Resolve();
+ if (enumDefinition != null && enumDefinition.IsEnum) {
+ TypeCode enumBaseTypeCode = TypeCode.Int32;
+ foreach (FieldDefinition field in enumDefinition.Fields) {
+ if (field.IsStatic && Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false), val))
+ return ConvertType(type).Member(field.Name).WithAnnotation(field);
+ else if (!field.IsStatic)
+ enumBaseTypeCode = TypeAnalysis.GetTypeCode(field.FieldType); // use primitive type of the enum
+ }
+ if (IsFlagsEnum(enumDefinition)) {
+ long enumValue = val;
+ Expression expr = null;
+ long negatedEnumValue = ~val;
+ // limit negatedEnumValue to the appropriate range
+ switch (enumBaseTypeCode) {
+ case TypeCode.Byte:
+ case TypeCode.SByte:
+ negatedEnumValue &= byte.MaxValue;
+ break;
+ case TypeCode.Int16:
+ case TypeCode.UInt16:
+ negatedEnumValue &= ushort.MaxValue;
+ break;
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ negatedEnumValue &= uint.MaxValue;
+ break;
+ }
+ Expression negatedExpr = null;
+ foreach (FieldDefinition field in enumDefinition.Fields.Where(fld => fld.IsStatic)) {
+ long fieldValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false);
+ if (fieldValue == 0)
+ continue; // skip None enum value
+
+ if ((fieldValue & enumValue) == fieldValue) {
+ var fieldExpression = ConvertType(type).Member(field.Name).WithAnnotation(field);
+ if (expr == null)
+ expr = fieldExpression;
+ else
+ expr = new BinaryOperatorExpression(expr, BinaryOperatorType.BitwiseOr, fieldExpression);
+
+ enumValue &= ~fieldValue;
+ }
+ if ((fieldValue & negatedEnumValue) == fieldValue) {
+ var fieldExpression = ConvertType(type).Member(field.Name).WithAnnotation(field);
+ if (negatedExpr == null)
+ negatedExpr = fieldExpression;
+ else
+ negatedExpr = new BinaryOperatorExpression(negatedExpr, BinaryOperatorType.BitwiseOr, fieldExpression);
+
+ negatedEnumValue &= ~fieldValue;
+ }
+ }
+ if (enumValue == 0 && expr != null) {
+ if (!(negatedEnumValue == 0 && negatedExpr != null && negatedExpr.Descendants.Count() < expr.Descendants.Count())) {
+ return expr;
+ }
+ }
+ if (negatedEnumValue == 0 && negatedExpr != null) {
+ return new UnaryOperatorExpression(UnaryOperatorType.BitNot, negatedExpr);
+ }
+ }
+ return new PrimitiveExpression(CSharpPrimitiveCast.Cast(enumBaseTypeCode, val, false)).CastTo(ConvertType(type));
+ }
+ }
+ TypeCode code = TypeAnalysis.GetTypeCode(type);
+ if (code == TypeCode.Object || code == TypeCode.Empty)
+ code = TypeCode.Int32;
+ return new PrimitiveExpression(CSharpPrimitiveCast.Cast(code, val, false));
+ }
+
+ static bool IsFlagsEnum(TypeDefinition type)
+ {
+ if (!type.HasCustomAttributes)
+ return false;
+
+ return type.CustomAttributes.Any(attr => attr.AttributeType.FullName == "System.FlagsAttribute");
+ }
+
+ /// <summary>
+ /// Sets new modifier if the member hides some other member from a base type.
+ /// </summary>
+ /// <param name="member">The node of the member which new modifier state should be determined.</param>
+ static void SetNewModifier(EntityDeclaration member)
+ {
+ try {
+ bool addNewModifier = false;
+ if (member is IndexerDeclaration) {
+ var propertyDef = member.Annotation<PropertyDefinition>();
+ var baseProperties =
+ TypesHierarchyHelpers.FindBaseProperties(propertyDef);
+ addNewModifier = baseProperties.Any();
+ } else
+ addNewModifier = HidesBaseMember(member);
+
+ if (addNewModifier)
+ member.Modifiers |= Modifiers.New;
+ }
+ catch (ReferenceResolvingException) {
+ // TODO: add some kind of notification (a comment?) about possible problems with decompiled code due to unresolved references.
+ }
+ }
+
+ static bool HidesBaseMember(EntityDeclaration member)
+ {
+ var memberDefinition = member.Annotation<IMemberDefinition>();
+ bool addNewModifier = false;
+ var methodDefinition = memberDefinition as MethodDefinition;
+ if (methodDefinition != null) {
+ addNewModifier = HidesByName(memberDefinition, includeBaseMethods: false);
+ if (!addNewModifier)
+ addNewModifier = TypesHierarchyHelpers.FindBaseMethods(methodDefinition).Any();
+ } else
+ addNewModifier = HidesByName(memberDefinition, includeBaseMethods: true);
+ return addNewModifier;
+ }
+
+ /// <summary>
+ /// Determines whether any base class member has the same name as the given member.
+ /// </summary>
+ /// <param name="member">The derived type's member.</param>
+ /// <param name="includeBaseMethods">true if names of methods declared in base types should also be checked.</param>
+ /// <returns>true if any base member has the same name as given member, otherwise false.</returns>
+ static bool HidesByName(IMemberDefinition member, bool includeBaseMethods)
+ {
+ Debug.Assert(!(member is PropertyDefinition) || !((PropertyDefinition)member).IsIndexer());
+
+ if (member.DeclaringType.BaseType != null) {
+ var baseTypeRef = member.DeclaringType.BaseType;
+ while (baseTypeRef != null) {
+ var baseType = baseTypeRef.ResolveOrThrow();
+ if (baseType.HasProperties && AnyIsHiddenBy(baseType.Properties, member, m => !m.IsIndexer()))
+ return true;
+ if (baseType.HasEvents && AnyIsHiddenBy(baseType.Events, member))
+ return true;
+ if (baseType.HasFields && AnyIsHiddenBy(baseType.Fields, member))
+ return true;
+ if (includeBaseMethods && baseType.HasMethods
+ && AnyIsHiddenBy(baseType.Methods, member, m => !m.IsSpecialName))
+ return true;
+ if (baseType.HasNestedTypes && AnyIsHiddenBy(baseType.NestedTypes, member))
+ return true;
+ baseTypeRef = baseType.BaseType;
+ }
+ }
+ return false;
+ }
+
+ static bool AnyIsHiddenBy<T>(IEnumerable<T> members, IMemberDefinition derived, Predicate<T> condition = null)
+ where T : IMemberDefinition
+ {
+ return members.Any(m => m.Name == derived.Name
+ && (condition == null || condition(m))
+ && TypesHierarchyHelpers.IsVisibleFromDerived(m, derived.DeclaringType));
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
new file mode 100644
index 00000000..a4d80e59
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
@@ -0,0 +1,1220 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+
+using ICSharpCode.Decompiler.Ast.Transforms;
+using ICSharpCode.Decompiler.ILAst;
+using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.PatternMatching;
+using ICSharpCode.NRefactory.Utils;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.Ast
+{
+ using Ast = NRefactory.CSharp;
+ using Cecil = Mono.Cecil;
+
+ public class AstMethodBodyBuilder
+ {
+ MethodDefinition methodDef;
+ TypeSystem typeSystem;
+ DecompilerContext context;
+ HashSet<ILVariable> localVariablesToDefine = new HashSet<ILVariable>(); // local variables that are missing a definition
+
+ /// <summary>
+ /// Creates the body for the method definition.
+ /// </summary>
+ /// <param name="methodDef">Method definition to decompile.</param>
+ /// <param name="context">Decompilation context.</param>
+ /// <param name="parameters">Parameter declarations of the method being decompiled.
+ /// These are used to update the parameter names when the decompiler generates names for the parameters.</param>
+ /// <returns>Block for the method body</returns>
+ public static BlockStatement CreateMethodBody(MethodDefinition methodDef,
+ DecompilerContext context,
+ IEnumerable<ParameterDeclaration> parameters = null)
+ {
+ MethodDefinition oldCurrentMethod = context.CurrentMethod;
+ Debug.Assert(oldCurrentMethod == null || oldCurrentMethod == methodDef);
+ context.CurrentMethod = methodDef;
+ context.CurrentMethodIsAsync = false;
+ try {
+ AstMethodBodyBuilder builder = new AstMethodBodyBuilder();
+ builder.methodDef = methodDef;
+ builder.context = context;
+ builder.typeSystem = methodDef.Module.TypeSystem;
+ if (Debugger.IsAttached) {
+ return builder.CreateMethodBody(parameters);
+ } else {
+ try {
+ return builder.CreateMethodBody(parameters);
+ } catch (OperationCanceledException) {
+ throw;
+ } catch (Exception ex) {
+ throw new DecompilerException(methodDef, ex);
+ }
+ }
+ } finally {
+ context.CurrentMethod = oldCurrentMethod;
+ }
+ }
+
+ public BlockStatement CreateMethodBody(IEnumerable<ParameterDeclaration> parameters)
+ {
+ if (methodDef.Body == null) {
+ return null;
+ }
+
+ context.CancellationToken.ThrowIfCancellationRequested();
+ ILBlock ilMethod = new ILBlock();
+ ILAstBuilder astBuilder = new ILAstBuilder();
+ ilMethod.Body = astBuilder.Build(methodDef, true, context);
+
+ context.CancellationToken.ThrowIfCancellationRequested();
+ ILAstOptimizer bodyGraph = new ILAstOptimizer();
+ bodyGraph.Optimize(context, ilMethod);
+ context.CancellationToken.ThrowIfCancellationRequested();
+
+ var localVariables = ilMethod.GetSelfAndChildrenRecursive<ILExpression>().Select(e => e.Operand as ILVariable)
+ .Where(v => v != null && !v.IsParameter).Distinct();
+ Debug.Assert(context.CurrentMethod == methodDef);
+ NameVariables.AssignNamesToVariables(context, astBuilder.Parameters, localVariables, ilMethod);
+
+ if (parameters != null) {
+ foreach (var pair in (from p in parameters
+ join v in astBuilder.Parameters on p.Annotation<ParameterDefinition>() equals v.OriginalParameter
+ select new { p, v.Name }))
+ {
+ pair.p.Name = pair.Name;
+ }
+ }
+
+ context.CancellationToken.ThrowIfCancellationRequested();
+ BlockStatement astBlock = TransformBlock(ilMethod);
+ CommentStatement.ReplaceAll(astBlock); // convert CommentStatements to Comments
+
+ Statement insertionPoint = astBlock.Statements.FirstOrDefault();
+ foreach (ILVariable v in localVariablesToDefine) {
+ AstType type;
+ if (v.Type.ContainsAnonymousType())
+ type = new SimpleType("var");
+ else
+ type = AstBuilder.ConvertType(v.Type);
+ var newVarDecl = new VariableDeclarationStatement(type, v.Name);
+ newVarDecl.Variables.Single().AddAnnotation(v);
+ astBlock.Statements.InsertBefore(insertionPoint, newVarDecl);
+ }
+
+ astBlock.AddAnnotation(new MethodDebugSymbols(methodDef) { LocalVariables = localVariables.ToList() });
+
+ return astBlock;
+ }
+
+ BlockStatement TransformBlock(ILBlock block)
+ {
+ BlockStatement astBlock = new BlockStatement();
+ if (block != null) {
+ foreach(ILNode node in block.GetChildren()) {
+ astBlock.Statements.AddRange(TransformNode(node));
+ }
+ }
+ return astBlock;
+ }
+
+ IEnumerable<Statement> TransformNode(ILNode node)
+ {
+ if (node is ILLabel) {
+ yield return new LabelStatement { Label = ((ILLabel)node).Name };
+ } else if (node is ILExpression) {
+ List<ILRange> ilRanges = ILRange.OrderAndJoin(node.GetSelfAndChildrenRecursive<ILExpression>().SelectMany(e => e.ILRanges));
+ AstNode codeExpr = TransformExpression((ILExpression)node);
+ if (codeExpr != null) {
+ codeExpr = codeExpr.WithAnnotation(ilRanges);
+ if (codeExpr is Expression) {
+ yield return new ExpressionStatement { Expression = (Expression)codeExpr };
+ } else if (codeExpr is Statement) {
+ yield return (Statement)codeExpr;
+ } else {
+ throw new Exception();
+ }
+ }
+ } else if (node is ILWhileLoop) {
+ ILWhileLoop ilLoop = (ILWhileLoop)node;
+ WhileStatement whileStmt = new WhileStatement() {
+ Condition = ilLoop.Condition != null ? (Expression)TransformExpression(ilLoop.Condition) : new PrimitiveExpression(true),
+ EmbeddedStatement = TransformBlock(ilLoop.BodyBlock)
+ };
+ yield return whileStmt;
+ } else if (node is ILCondition) {
+ ILCondition conditionalNode = (ILCondition)node;
+ bool hasFalseBlock = conditionalNode.FalseBlock.EntryGoto != null || conditionalNode.FalseBlock.Body.Count > 0;
+ yield return new IfElseStatement {
+ Condition = (Expression)TransformExpression(conditionalNode.Condition),
+ TrueStatement = TransformBlock(conditionalNode.TrueBlock),
+ FalseStatement = hasFalseBlock ? TransformBlock(conditionalNode.FalseBlock) : null
+ };
+ } else if (node is ILSwitch) {
+ ILSwitch ilSwitch = (ILSwitch)node;
+ if (TypeAnalysis.IsBoolean(ilSwitch.Condition.InferredType) && (
+ from cb in ilSwitch.CaseBlocks
+ where cb.Values != null
+ from val in cb.Values
+ select val
+ ).Any(val => val != 0 && val != 1))
+ {
+ // If switch cases contain values other then 0 and 1, force the condition to be non-boolean
+ ilSwitch.Condition.ExpectedType = typeSystem.Int32;
+ }
+ SwitchStatement switchStmt = new SwitchStatement() { Expression = (Expression)TransformExpression(ilSwitch.Condition) };
+ foreach (var caseBlock in ilSwitch.CaseBlocks) {
+ SwitchSection section = new SwitchSection();
+ if (caseBlock.Values != null) {
+ section.CaseLabels.AddRange(caseBlock.Values.Select(i => new CaseLabel() { Expression = AstBuilder.MakePrimitive(i, ilSwitch.Condition.ExpectedType ?? ilSwitch.Condition.InferredType) }));
+ } else {
+ section.CaseLabels.Add(new CaseLabel());
+ }
+ section.Statements.Add(TransformBlock(caseBlock));
+ switchStmt.SwitchSections.Add(section);
+ }
+ yield return switchStmt;
+ } else if (node is ILTryCatchBlock) {
+ ILTryCatchBlock tryCatchNode = ((ILTryCatchBlock)node);
+ var tryCatchStmt = new TryCatchStatement();
+ tryCatchStmt.TryBlock = TransformBlock(tryCatchNode.TryBlock);
+ foreach (var catchClause in tryCatchNode.CatchBlocks) {
+ if (catchClause.ExceptionVariable == null
+ && (catchClause.ExceptionType == null || catchClause.ExceptionType.MetadataType == MetadataType.Object))
+ {
+ tryCatchStmt.CatchClauses.Add(new CatchClause { Body = TransformBlock(catchClause) });
+ } else {
+ tryCatchStmt.CatchClauses.Add(
+ new CatchClause {
+ Type = AstBuilder.ConvertType(catchClause.ExceptionType),
+ VariableName = catchClause.ExceptionVariable == null ? null : catchClause.ExceptionVariable.Name,
+ Body = TransformBlock(catchClause)
+ }.WithAnnotation(catchClause.ExceptionVariable));
+ }
+ }
+ if (tryCatchNode.FinallyBlock != null)
+ tryCatchStmt.FinallyBlock = TransformBlock(tryCatchNode.FinallyBlock);
+ if (tryCatchNode.FaultBlock != null) {
+ CatchClause cc = new CatchClause();
+ cc.Body = TransformBlock(tryCatchNode.FaultBlock);
+ cc.Body.Add(new ThrowStatement()); // rethrow
+ tryCatchStmt.CatchClauses.Add(cc);
+ }
+ yield return tryCatchStmt;
+ } else if (node is ILFixedStatement) {
+ ILFixedStatement fixedNode = (ILFixedStatement)node;
+ FixedStatement fixedStatement = new FixedStatement();
+ foreach (ILExpression initializer in fixedNode.Initializers) {
+ Debug.Assert(initializer.Code == ILCode.Stloc);
+ ILVariable v = (ILVariable)initializer.Operand;
+ fixedStatement.Variables.Add(
+ new VariableInitializer {
+ Name = v.Name,
+ Initializer = (Expression)TransformExpression(initializer.Arguments[0])
+ }.WithAnnotation(v));
+ }
+ fixedStatement.Type = AstBuilder.ConvertType(((ILVariable)fixedNode.Initializers[0].Operand).Type);
+ fixedStatement.EmbeddedStatement = TransformBlock(fixedNode.BodyBlock);
+ yield return fixedStatement;
+ } else if (node is ILBlock) {
+ yield return TransformBlock((ILBlock)node);
+ } else {
+ throw new Exception("Unknown node type");
+ }
+ }
+
+ AstNode TransformExpression(ILExpression expr)
+ {
+ AstNode node = TransformByteCode(expr);
+ Expression astExpr = node as Expression;
+
+ // get IL ranges - used in debugger
+ List<ILRange> ilRanges = ILRange.OrderAndJoin(expr.GetSelfAndChildrenRecursive<ILExpression>().SelectMany(e => e.ILRanges));
+ AstNode result;
+
+ if (astExpr != null)
+ result = Convert(astExpr, expr.InferredType, expr.ExpectedType);
+ else
+ result = node;
+
+ if (result != null)
+ result = result.WithAnnotation(new TypeInformation(expr.InferredType, expr.ExpectedType));
+
+ if (result != null)
+ return result.WithAnnotation(ilRanges);
+
+ return result;
+ }
+
+ AstNode TransformByteCode(ILExpression byteCode)
+ {
+ object operand = byteCode.Operand;
+ AstType operandAsTypeRef = AstBuilder.ConvertType(operand as TypeReference);
+
+ List<Expression> args = new List<Expression>();
+ foreach(ILExpression arg in byteCode.Arguments) {
+ args.Add((Expression)TransformExpression(arg));
+ }
+ Expression arg1 = args.Count >= 1 ? args[0] : null;
+ Expression arg2 = args.Count >= 2 ? args[1] : null;
+ Expression arg3 = args.Count >= 3 ? args[2] : null;
+
+ switch (byteCode.Code) {
+ #region Arithmetic
+ case ILCode.Add:
+ case ILCode.Add_Ovf:
+ case ILCode.Add_Ovf_Un:
+ {
+ BinaryOperatorExpression boe;
+ if (byteCode.InferredType is PointerType) {
+ boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
+ if (byteCode.Arguments[0].ExpectedType is PointerType ||
+ byteCode.Arguments[1].ExpectedType is PointerType) {
+ boe.AddAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation);
+ }
+ } else {
+ boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
+ }
+ boe.AddAnnotation(byteCode.Code == ILCode.Add ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation);
+ return boe;
+ }
+ case ILCode.Sub:
+ case ILCode.Sub_Ovf:
+ case ILCode.Sub_Ovf_Un:
+ {
+ BinaryOperatorExpression boe;
+ if (byteCode.InferredType is PointerType) {
+ boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
+ if (byteCode.Arguments[0].ExpectedType is PointerType) {
+ boe.WithAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation);
+ }
+ } else {
+ boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
+ }
+ boe.AddAnnotation(byteCode.Code == ILCode.Sub ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation);
+ return boe;
+ }
+ case ILCode.Div: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2);
+ case ILCode.Div_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2);
+ case ILCode.Mul: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.UncheckedAnnotation);
+ case ILCode.Mul_Ovf: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.CheckedAnnotation);
+ case ILCode.Mul_Ovf_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.CheckedAnnotation);
+ case ILCode.Rem: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2);
+ case ILCode.Rem_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2);
+ case ILCode.And: return new BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseAnd, arg2);
+ case ILCode.Or: return new BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseOr, arg2);
+ case ILCode.Xor: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ExclusiveOr, arg2);
+ case ILCode.Shl: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftLeft, arg2);
+ case ILCode.Shr: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2);
+ case ILCode.Shr_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2);
+ case ILCode.Neg: return new UnaryOperatorExpression(UnaryOperatorType.Minus, arg1).WithAnnotation(AddCheckedBlocks.UncheckedAnnotation);
+ case ILCode.Not: return new UnaryOperatorExpression(UnaryOperatorType.BitNot, arg1);
+ case ILCode.PostIncrement:
+ case ILCode.PostIncrement_Ovf:
+ case ILCode.PostIncrement_Ovf_Un:
+ {
+ if (arg1 is DirectionExpression)
+ arg1 = ((DirectionExpression)arg1).Expression.Detach();
+ var uoe = new UnaryOperatorExpression(
+ (int)byteCode.Operand > 0 ? UnaryOperatorType.PostIncrement : UnaryOperatorType.PostDecrement, arg1);
+ uoe.AddAnnotation((byteCode.Code == ILCode.PostIncrement) ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation);
+ return uoe;
+ }
+ #endregion
+ #region Arrays
+ case ILCode.Newarr: {
+ var ace = new ArrayCreateExpression();
+ ace.Type = operandAsTypeRef;
+ ComposedType ct = operandAsTypeRef as ComposedType;
+ if (ct != null) {
+ // change "new (int[,])[10] to new int[10][,]"
+ ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers);
+ }
+ if (byteCode.Code == ILCode.InitArray) {
+ ace.Initializer = new ArrayInitializerExpression();
+ ace.Initializer.Elements.AddRange(args);
+ } else {
+ ace.Arguments.Add(arg1);
+ }
+ return ace;
+ }
+ case ILCode.InitArray: {
+ var ace = new ArrayCreateExpression();
+ ace.Type = operandAsTypeRef;
+ ComposedType ct = operandAsTypeRef as ComposedType;
+ var arrayType = (ArrayType) operand;
+ if (ct != null)
+ {
+ // change "new (int[,])[10] to new int[10][,]"
+ ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers);
+ ace.Initializer = new ArrayInitializerExpression();
+ }
+ var newArgs = new List<Expression>();
+ foreach (var arrayDimension in arrayType.Dimensions.Skip(1).Reverse())
+ {
+ int length = (int)arrayDimension.UpperBound - (int)arrayDimension.LowerBound;
+ for (int j = 0; j < args.Count; j += length)
+ {
+ var child = new ArrayInitializerExpression();
+ child.Elements.AddRange(args.GetRange(j, length));
+ newArgs.Add(child);
+ }
+ var temp = args;
+ args = newArgs;
+ newArgs = temp;
+ newArgs.Clear();
+ }
+ ace.Initializer.Elements.AddRange(args);
+ return ace;
+ }
+ case ILCode.Ldlen: return arg1.Member("Length");
+ case ILCode.Ldelem_I:
+ case ILCode.Ldelem_I1:
+ case ILCode.Ldelem_I2:
+ case ILCode.Ldelem_I4:
+ case ILCode.Ldelem_I8:
+ case ILCode.Ldelem_U1:
+ case ILCode.Ldelem_U2:
+ case ILCode.Ldelem_U4:
+ case ILCode.Ldelem_R4:
+ case ILCode.Ldelem_R8:
+ case ILCode.Ldelem_Ref:
+ case ILCode.Ldelem_Any:
+ return arg1.Indexer(arg2);
+ case ILCode.Ldelema:
+ return MakeRef(arg1.Indexer(arg2));
+ case ILCode.Stelem_I:
+ case ILCode.Stelem_I1:
+ case ILCode.Stelem_I2:
+ case ILCode.Stelem_I4:
+ case ILCode.Stelem_I8:
+ case ILCode.Stelem_R4:
+ case ILCode.Stelem_R8:
+ case ILCode.Stelem_Ref:
+ case ILCode.Stelem_Any:
+ return new AssignmentExpression(arg1.Indexer(arg2), arg3);
+ case ILCode.CompoundAssignment:
+ {
+ CastExpression cast = arg1 as CastExpression;
+ var boe = cast != null ? (BinaryOperatorExpression)cast.Expression : arg1 as BinaryOperatorExpression;
+ // AssignmentExpression doesn't support overloaded operators so they have to be processed to BinaryOperatorExpression
+ if (boe == null) {
+ var tmp = new ParenthesizedExpression(arg1);
+ ReplaceMethodCallsWithOperators.ProcessInvocationExpression((InvocationExpression)arg1);
+ boe = (BinaryOperatorExpression)tmp.Expression;
+ }
+ var assignment = new AssignmentExpression {
+ Left = boe.Left.Detach(),
+ Operator = ReplaceMethodCallsWithOperators.GetAssignmentOperatorForBinaryOperator(boe.Operator),
+ Right = boe.Right.Detach()
+ }.CopyAnnotationsFrom(boe);
+ // We do not mark the resulting assignment as RestoreOriginalAssignOperatorAnnotation, because
+ // the operator cannot be translated back to the expanded form (as the left-hand expression
+ // would be evaluated twice, and might have side-effects)
+ if (cast != null) {
+ cast.Expression = assignment;
+ return cast;
+ } else {
+ return assignment;
+ }
+ }
+ #endregion
+ #region Comparison
+ case ILCode.Ceq: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2);
+ case ILCode.Cne: return new BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2);
+ case ILCode.Cgt: return new BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
+ case ILCode.Cgt_Un: {
+ // can also mean Inequality, when used with object references
+ TypeReference arg1Type = byteCode.Arguments[0].InferredType;
+ if (arg1Type != null && !arg1Type.IsValueType) goto case ILCode.Cne;
+
+ // when comparing signed integral values using Cgt_Un with 0
+ // the Ast should actually contain InEquality since "(uint)a > 0u" is identical to "a != 0"
+ if (arg1Type.IsSignedIntegralType())
+ {
+ var p = arg2 as PrimitiveExpression;
+ if (p != null && p.Value.IsZero()) goto case ILCode.Cne;
+ }
+
+ goto case ILCode.Cgt;
+ }
+ case ILCode.Cle_Un: {
+ // can also mean Equality, when used with object references
+ TypeReference arg1Type = byteCode.Arguments[0].InferredType;
+ if (arg1Type != null && !arg1Type.IsValueType) goto case ILCode.Ceq;
+
+ // when comparing signed integral values using Cle_Un with 0
+ // the Ast should actually contain Equality since "(uint)a <= 0u" is identical to "a == 0"
+ if (arg1Type.IsSignedIntegralType())
+ {
+ var p = arg2 as PrimitiveExpression;
+ if (p != null && p.Value.IsZero()) goto case ILCode.Ceq;
+ }
+
+ goto case ILCode.Cle;
+ }
+ case ILCode.Cle: return new BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2);
+ case ILCode.Cge_Un:
+ case ILCode.Cge: return new BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2);
+ case ILCode.Clt_Un:
+ case ILCode.Clt: return new BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
+ #endregion
+ #region Logical
+ case ILCode.LogicNot: return new UnaryOperatorExpression(UnaryOperatorType.Not, arg1);
+ case ILCode.LogicAnd: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalAnd, arg2);
+ case ILCode.LogicOr: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalOr, arg2);
+ case ILCode.TernaryOp: return new ConditionalExpression() { Condition = arg1, TrueExpression = arg2, FalseExpression = arg3 };
+ case ILCode.NullCoalescing: return new BinaryOperatorExpression(arg1, BinaryOperatorType.NullCoalescing, arg2);
+ #endregion
+ #region Branch
+ case ILCode.Br: return new GotoStatement(((ILLabel)byteCode.Operand).Name);
+ case ILCode.Brtrue:
+ return new IfElseStatement() {
+ Condition = arg1,
+ TrueStatement = new BlockStatement() {
+ new GotoStatement(((ILLabel)byteCode.Operand).Name)
+ }
+ };
+ case ILCode.LoopOrSwitchBreak: return new BreakStatement();
+ case ILCode.LoopContinue: return new ContinueStatement();
+ #endregion
+ #region Conversions
+ case ILCode.Conv_I1:
+ case ILCode.Conv_I2:
+ case ILCode.Conv_I4:
+ case ILCode.Conv_I8:
+ case ILCode.Conv_U1:
+ case ILCode.Conv_U2:
+ case ILCode.Conv_U4:
+ case ILCode.Conv_U8:
+ case ILCode.Conv_I:
+ case ILCode.Conv_U:
+ {
+ // conversion was handled by Convert() function using the info from type analysis
+ CastExpression cast = arg1 as CastExpression;
+ if (cast != null) {
+ cast.AddAnnotation(AddCheckedBlocks.UncheckedAnnotation);
+ }
+ return arg1;
+ }
+ case ILCode.Conv_R4:
+ case ILCode.Conv_R8:
+ case ILCode.Conv_R_Un: // TODO
+ return arg1;
+ case ILCode.Conv_Ovf_I1:
+ case ILCode.Conv_Ovf_I2:
+ case ILCode.Conv_Ovf_I4:
+ case ILCode.Conv_Ovf_I8:
+ case ILCode.Conv_Ovf_U1:
+ case ILCode.Conv_Ovf_U2:
+ case ILCode.Conv_Ovf_U4:
+ case ILCode.Conv_Ovf_U8:
+ case ILCode.Conv_Ovf_I1_Un:
+ case ILCode.Conv_Ovf_I2_Un:
+ case ILCode.Conv_Ovf_I4_Un:
+ case ILCode.Conv_Ovf_I8_Un:
+ case ILCode.Conv_Ovf_U1_Un:
+ case ILCode.Conv_Ovf_U2_Un:
+ case ILCode.Conv_Ovf_U4_Un:
+ case ILCode.Conv_Ovf_U8_Un:
+ case ILCode.Conv_Ovf_I:
+ case ILCode.Conv_Ovf_U:
+ case ILCode.Conv_Ovf_I_Un:
+ case ILCode.Conv_Ovf_U_Un:
+ {
+ // conversion was handled by Convert() function using the info from type analysis
+ CastExpression cast = arg1 as CastExpression;
+ if (cast != null) {
+ cast.AddAnnotation(AddCheckedBlocks.CheckedAnnotation);
+ }
+ return arg1;
+ }
+ case ILCode.Unbox_Any:
+ // unboxing does not require a cast if the argument was an isinst instruction
+ if (arg1 is AsExpression && byteCode.Arguments[0].Code == ILCode.Isinst && TypeAnalysis.IsSameType(operand as TypeReference, byteCode.Arguments[0].Operand as TypeReference))
+ return arg1;
+ else
+ goto case ILCode.Castclass;
+ case ILCode.Castclass:
+ if ((byteCode.Arguments[0].InferredType != null && byteCode.Arguments[0].InferredType.IsGenericParameter) || ((TypeReference)operand).IsGenericParameter)
+ return arg1.CastTo(new PrimitiveType("object")).CastTo(operandAsTypeRef);
+ else
+ return arg1.CastTo(operandAsTypeRef);
+ case ILCode.Isinst:
+ return arg1.CastAs(operandAsTypeRef);
+ case ILCode.Box:
+ return arg1;
+ case ILCode.Unbox:
+ return MakeRef(arg1.CastTo(operandAsTypeRef));
+ #endregion
+ #region Indirect
+ case ILCode.Ldind_Ref:
+ case ILCode.Ldobj:
+ if (arg1 is DirectionExpression)
+ return ((DirectionExpression)arg1).Expression.Detach();
+ else
+ return new UnaryOperatorExpression(UnaryOperatorType.Dereference, arg1);
+ case ILCode.Stind_Ref:
+ case ILCode.Stobj:
+ if (arg1 is DirectionExpression)
+ return new AssignmentExpression(((DirectionExpression)arg1).Expression.Detach(), arg2);
+ else
+ return new AssignmentExpression(new UnaryOperatorExpression(UnaryOperatorType.Dereference, arg1), arg2);
+ #endregion
+ case ILCode.Arglist:
+ return new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.ArgListAccess };
+ case ILCode.Break: return InlineAssembly(byteCode, args);
+ case ILCode.Call:
+ case ILCode.CallGetter:
+ case ILCode.CallSetter:
+ return TransformCall(false, byteCode, args);
+ case ILCode.Callvirt:
+ case ILCode.CallvirtGetter:
+ case ILCode.CallvirtSetter:
+ return TransformCall(true, byteCode, args);
+ case ILCode.Ldftn: {
+ MethodReference cecilMethod = ((MethodReference)operand);
+ var expr = new IdentifierExpression(cecilMethod.Name);
+ expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod));
+ expr.AddAnnotation(cecilMethod);
+ return new IdentifierExpression("ldftn").Invoke(expr)
+ .WithAnnotation(new DelegateConstruction.Annotation(false));
+ }
+ case ILCode.Ldvirtftn: {
+ MethodReference cecilMethod = ((MethodReference)operand);
+ var expr = new IdentifierExpression(cecilMethod.Name);
+ expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod));
+ expr.AddAnnotation(cecilMethod);
+ return new IdentifierExpression("ldvirtftn").Invoke(expr)
+ .WithAnnotation(new DelegateConstruction.Annotation(true));
+ }
+ case ILCode.Calli: return InlineAssembly(byteCode, args);
+ case ILCode.Ckfinite: return InlineAssembly(byteCode, args);
+ case ILCode.Constrained: return InlineAssembly(byteCode, args);
+ case ILCode.Cpblk: return InlineAssembly(byteCode, args);
+ case ILCode.Cpobj: return InlineAssembly(byteCode, args);
+ case ILCode.Dup: return arg1;
+ case ILCode.Endfilter: return InlineAssembly(byteCode, args);
+ case ILCode.Endfinally: return null;
+ case ILCode.Initblk: return InlineAssembly(byteCode, args);
+ case ILCode.Initobj: return InlineAssembly(byteCode, args);
+ case ILCode.DefaultValue:
+ return MakeDefaultValue((TypeReference)operand);
+ case ILCode.Jmp: return InlineAssembly(byteCode, args);
+ case ILCode.Ldc_I4:
+ return AstBuilder.MakePrimitive((int)operand, byteCode.InferredType);
+ case ILCode.Ldc_I8:
+ return AstBuilder.MakePrimitive((long)operand, byteCode.InferredType);
+ case ILCode.Ldc_R4:
+ case ILCode.Ldc_R8:
+ case ILCode.Ldc_Decimal:
+ return new PrimitiveExpression(operand);
+ case ILCode.Ldfld:
+ if (arg1 is DirectionExpression)
+ arg1 = ((DirectionExpression)arg1).Expression.Detach();
+ return arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand);
+ case ILCode.Ldsfld:
+ return AstBuilder.ConvertType(((FieldReference)operand).DeclaringType)
+ .Member(((FieldReference)operand).Name).WithAnnotation(operand);
+ case ILCode.Stfld:
+ if (arg1 is DirectionExpression)
+ arg1 = ((DirectionExpression)arg1).Expression.Detach();
+ return new AssignmentExpression(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand), arg2);
+ case ILCode.Stsfld:
+ return new AssignmentExpression(
+ AstBuilder.ConvertType(((FieldReference)operand).DeclaringType)
+ .Member(((FieldReference)operand).Name).WithAnnotation(operand),
+ arg1);
+ case ILCode.Ldflda:
+ if (arg1 is DirectionExpression)
+ arg1 = ((DirectionExpression)arg1).Expression.Detach();
+ return MakeRef(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand));
+ case ILCode.Ldsflda:
+ return MakeRef(
+ AstBuilder.ConvertType(((FieldReference)operand).DeclaringType)
+ .Member(((FieldReference)operand).Name).WithAnnotation(operand));
+ case ILCode.Ldloc: {
+ ILVariable v = (ILVariable)operand;
+ if (!v.IsParameter)
+ localVariablesToDefine.Add((ILVariable)operand);
+ Expression expr;
+ if (v.IsParameter && v.OriginalParameter.Index < 0)
+ expr = new ThisReferenceExpression();
+ else
+ expr = new IdentifierExpression(((ILVariable)operand).Name).WithAnnotation(operand);
+ return v.IsParameter && v.Type is ByReferenceType ? MakeRef(expr) : expr;
+ }
+ case ILCode.Ldloca: {
+ ILVariable v = (ILVariable)operand;
+ if (v.IsParameter && v.OriginalParameter.Index < 0)
+ return MakeRef(new ThisReferenceExpression());
+ if (!v.IsParameter)
+ localVariablesToDefine.Add((ILVariable)operand);
+ return MakeRef(new IdentifierExpression(((ILVariable)operand).Name).WithAnnotation(operand));
+ }
+ case ILCode.Ldnull: return new NullReferenceExpression();
+ case ILCode.Ldstr: return new PrimitiveExpression(operand);
+ case ILCode.Ldtoken:
+ if (operand is TypeReference) {
+ return AstBuilder.CreateTypeOfExpression((TypeReference)operand).Member("TypeHandle");
+ } else {
+ Expression referencedEntity;
+ string loadName;
+ string handleName;
+ if (operand is FieldReference) {
+ loadName = "fieldof";
+ handleName = "FieldHandle";
+ FieldReference fr = (FieldReference)operand;
+ referencedEntity = AstBuilder.ConvertType(fr.DeclaringType).Member(fr.Name).WithAnnotation(fr);
+ } else if (operand is MethodReference) {
+ loadName = "methodof";
+ handleName = "MethodHandle";
+ MethodReference mr = (MethodReference)operand;
+ var methodParameters = mr.Parameters.Select(p => new TypeReferenceExpression(AstBuilder.ConvertType(p.ParameterType)));
+ referencedEntity = AstBuilder.ConvertType(mr.DeclaringType).Invoke(mr.Name, methodParameters).WithAnnotation(mr);
+ } else {
+ loadName = "ldtoken";
+ handleName = "Handle";
+ referencedEntity = new IdentifierExpression(FormatByteCodeOperand(byteCode.Operand));
+ }
+ return new IdentifierExpression(loadName).Invoke(referencedEntity).WithAnnotation(new LdTokenAnnotation()).Member(handleName);
+ }
+ case ILCode.Leave: return new GotoStatement() { Label = ((ILLabel)operand).Name };
+ case ILCode.Localloc:
+ {
+ PointerType ptrType = byteCode.InferredType as PointerType;
+ TypeReference type;
+ if (ptrType != null) {
+ type = ptrType.ElementType;
+ } else {
+ type = typeSystem.Byte;
+ }
+ return new StackAllocExpression {
+ Type = AstBuilder.ConvertType(type),
+ CountExpression = arg1
+ };
+ }
+ case ILCode.Mkrefany:
+ {
+ DirectionExpression dir = arg1 as DirectionExpression;
+ if (dir != null) {
+ return new UndocumentedExpression {
+ UndocumentedExpressionType = UndocumentedExpressionType.MakeRef,
+ Arguments = { dir.Expression.Detach() }
+ };
+ } else {
+ return InlineAssembly(byteCode, args);
+ }
+ }
+ case ILCode.Refanytype:
+ return new UndocumentedExpression {
+ UndocumentedExpressionType = UndocumentedExpressionType.RefType,
+ Arguments = { arg1 }
+ }.Member("TypeHandle");
+ case ILCode.Refanyval:
+ return MakeRef(
+ new UndocumentedExpression {
+ UndocumentedExpressionType = UndocumentedExpressionType.RefValue,
+ Arguments = { arg1, new TypeReferenceExpression(operandAsTypeRef) }
+ });
+ case ILCode.Newobj: {
+ TypeReference declaringType = ((MethodReference)operand).DeclaringType;
+ if (declaringType is ArrayType) {
+ ComposedType ct = AstBuilder.ConvertType((ArrayType)declaringType) as ComposedType;
+ if (ct != null && ct.ArraySpecifiers.Count >= 1) {
+ var ace = new ArrayCreateExpression();
+ ct.ArraySpecifiers.First().Remove();
+ ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers);
+ ace.Type = ct;
+ ace.Arguments.AddRange(args);
+ return ace;
+ }
+ }
+ if (declaringType.IsAnonymousType()) {
+ MethodDefinition ctor = ((MethodReference)operand).Resolve();
+ if (methodDef != null) {
+ AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression();
+ if (CanInferAnonymousTypePropertyNamesFromArguments(args, ctor.Parameters)) {
+ atce.Initializers.AddRange(args);
+ } else {
+ for (int i = 0; i < args.Count; i++) {
+ atce.Initializers.Add(
+ new NamedExpression {
+ Name = ctor.Parameters[i].Name,
+ Expression = args[i]
+ });
+ }
+ }
+ return atce;
+ }
+ }
+ var oce = new ObjectCreateExpression();
+ oce.Type = AstBuilder.ConvertType(declaringType);
+ oce.Arguments.AddRange(args);
+ return oce.WithAnnotation(operand);
+ }
+ case ILCode.No: return InlineAssembly(byteCode, args);
+ case ILCode.Nop: return null;
+ case ILCode.Pop: return arg1;
+ case ILCode.Readonly: return InlineAssembly(byteCode, args);
+ case ILCode.Ret:
+ if (methodDef.ReturnType.FullName != "System.Void") {
+ return new ReturnStatement { Expression = arg1 };
+ } else {
+ return new ReturnStatement();
+ }
+ case ILCode.Rethrow: return new ThrowStatement();
+ case ILCode.Sizeof: return new SizeOfExpression { Type = operandAsTypeRef };
+ case ILCode.Stloc: {
+ ILVariable locVar = (ILVariable)operand;
+ if (!locVar.IsParameter)
+ localVariablesToDefine.Add(locVar);
+ return new AssignmentExpression(new IdentifierExpression(locVar.Name).WithAnnotation(locVar), arg1);
+ }
+ case ILCode.Switch: return InlineAssembly(byteCode, args);
+ case ILCode.Tail: return InlineAssembly(byteCode, args);
+ case ILCode.Throw: return new ThrowStatement { Expression = arg1 };
+ case ILCode.Unaligned: return InlineAssembly(byteCode, args);
+ case ILCode.Volatile: return InlineAssembly(byteCode, args);
+ case ILCode.YieldBreak:
+ return new YieldBreakStatement();
+ case ILCode.YieldReturn:
+ return new YieldReturnStatement { Expression = arg1 };
+ case ILCode.InitObject:
+ case ILCode.InitCollection:
+ {
+ ArrayInitializerExpression initializer = new ArrayInitializerExpression();
+ for (int i = 1; i < args.Count; i++) {
+ Match m = objectInitializerPattern.Match(args[i]);
+ if (m.Success) {
+ MemberReferenceExpression mre = m.Get<MemberReferenceExpression>("left").Single();
+ initializer.Elements.Add(
+ new NamedExpression {
+ Name = mre.MemberName,
+ Expression = m.Get<Expression>("right").Single().Detach()
+ }.CopyAnnotationsFrom(mre));
+ } else {
+ m = collectionInitializerPattern.Match(args[i]);
+ if (m.Success) {
+ if (m.Get("arg").Count() == 1) {
+ initializer.Elements.Add(m.Get<Expression>("arg").Single().Detach());
+ } else {
+ ArrayInitializerExpression argList = new ArrayInitializerExpression();
+ foreach (var expr in m.Get<Expression>("arg")) {
+ argList.Elements.Add(expr.Detach());
+ }
+ initializer.Elements.Add(argList);
+ }
+ } else {
+ initializer.Elements.Add(args[i]);
+ }
+ }
+ }
+ ObjectCreateExpression oce = arg1 as ObjectCreateExpression;
+ DefaultValueExpression dve = arg1 as DefaultValueExpression;
+ if (oce != null) {
+ oce.Initializer = initializer;
+ return oce;
+ } else if (dve != null) {
+ oce = new ObjectCreateExpression(dve.Type.Detach());
+ oce.CopyAnnotationsFrom(dve);
+ oce.Initializer = initializer;
+ return oce;
+ } else {
+ return new AssignmentExpression(arg1, initializer);
+ }
+ }
+ case ILCode.InitializedObject:
+ return new InitializedObjectExpression();
+ case ILCode.Wrap:
+ return arg1.WithAnnotation(PushNegation.LiftedOperatorAnnotation);
+ case ILCode.AddressOf:
+ return MakeRef(arg1);
+ case ILCode.ExpressionTreeParameterDeclarations:
+ args[args.Count - 1].AddAnnotation(new ParameterDeclarationAnnotation(byteCode));
+ return args[args.Count - 1];
+ case ILCode.Await:
+ return new UnaryOperatorExpression(UnaryOperatorType.Await, UnpackDirectionExpression(arg1));
+ case ILCode.NullableOf:
+ case ILCode.ValueOf:
+ return arg1;
+ default:
+ throw new Exception("Unknown OpCode: " + byteCode.Code);
+ }
+ }
+
+ internal static bool CanInferAnonymousTypePropertyNamesFromArguments(IList<Expression> args, IList<ParameterDefinition> parameters)
+ {
+ for (int i = 0; i < args.Count; i++) {
+ string inferredName;
+ if (args[i] is IdentifierExpression)
+ inferredName = ((IdentifierExpression)args[i]).Identifier;
+ else if (args[i] is MemberReferenceExpression)
+ inferredName = ((MemberReferenceExpression)args[i]).MemberName;
+ else
+ inferredName = null;
+
+ if (inferredName != parameters[i].Name) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static readonly AstNode objectInitializerPattern = new AssignmentExpression(
+ new MemberReferenceExpression {
+ Target = new InitializedObjectExpression(),
+ MemberName = Pattern.AnyString
+ }.WithName("left"),
+ new AnyNode("right")
+ );
+
+ static readonly AstNode collectionInitializerPattern = new InvocationExpression {
+ Target = new MemberReferenceExpression {
+ Target = new InitializedObjectExpression(),
+ MemberName = "Add"
+ },
+ Arguments = { new Repeat(new AnyNode("arg")) }
+ };
+
+ sealed class InitializedObjectExpression : IdentifierExpression
+ {
+ public InitializedObjectExpression() : base("__initialized_object__") {}
+
+ protected override bool DoMatch(AstNode other, Match match)
+ {
+ return other is InitializedObjectExpression;
+ }
+ }
+
+ Expression MakeDefaultValue(TypeReference type)
+ {
+ TypeDefinition typeDef = type.Resolve();
+ if (typeDef != null) {
+ if (TypeAnalysis.IsIntegerOrEnum(typeDef))
+ return AstBuilder.MakePrimitive(0, typeDef);
+ else if (!typeDef.IsValueType)
+ return new NullReferenceExpression();
+ switch (typeDef.FullName) {
+ case "System.Nullable`1":
+ return new NullReferenceExpression();
+ case "System.Single":
+ return new PrimitiveExpression(0f);
+ case "System.Double":
+ return new PrimitiveExpression(0.0);
+ case "System.Decimal":
+ return new PrimitiveExpression(0m);
+ }
+ }
+ return new DefaultValueExpression { Type = AstBuilder.ConvertType(type) };
+ }
+
+ AstNode TransformCall(bool isVirtual, ILExpression byteCode, List<Expression> args)
+ {
+ MethodReference cecilMethod = (MethodReference)byteCode.Operand;
+ MethodDefinition cecilMethodDef = cecilMethod.Resolve();
+ Expression target;
+ List<Expression> methodArgs = new List<Expression>(args);
+ if (cecilMethod.HasThis) {
+ target = methodArgs[0];
+ methodArgs.RemoveAt(0);
+
+ // Unpack any DirectionExpression that is used as target for the call
+ // (calling methods on value types implicitly passes the first argument by reference)
+ target = UnpackDirectionExpression(target);
+
+ if (cecilMethodDef != null) {
+ // convert null.ToLower() to ((string)null).ToLower()
+ if (target is NullReferenceExpression)
+ target = target.CastTo(AstBuilder.ConvertType(cecilMethod.DeclaringType));
+
+ if (cecilMethodDef.DeclaringType.IsInterface) {
+ TypeReference tr = byteCode.Arguments[0].InferredType;
+ if (tr != null) {
+ TypeDefinition td = tr.Resolve();
+ if (td != null && !td.IsInterface) {
+ // Calling an interface method on a non-interface object:
+ // we need to introduce an explicit cast
+ target = target.CastTo(AstBuilder.ConvertType(cecilMethod.DeclaringType));
+ }
+ }
+ }
+ }
+ } else {
+ target = new TypeReferenceExpression { Type = AstBuilder.ConvertType(cecilMethod.DeclaringType) };
+ }
+ if (target is ThisReferenceExpression && !isVirtual) {
+ // a non-virtual call on "this" might be a "base"-call.
+ if (cecilMethod.DeclaringType.GetElementType() != methodDef.DeclaringType) {
+ // If we're not calling a method in the current class; we must be calling one in the base class.
+ target = new BaseReferenceExpression();
+ }
+ }
+
+ if (cecilMethod.Name == ".ctor" && cecilMethod.DeclaringType.IsValueType) {
+ // On value types, the constructor can be called.
+ // This is equivalent to 'target = new ValueType(args);'.
+ ObjectCreateExpression oce = new ObjectCreateExpression();
+ oce.Type = AstBuilder.ConvertType(cecilMethod.DeclaringType);
+ oce.AddAnnotation(cecilMethod);
+ AdjustArgumentsForMethodCall(cecilMethod, methodArgs);
+ oce.Arguments.AddRange(methodArgs);
+ return new AssignmentExpression(target, oce);
+ }
+
+ if (cecilMethod.Name == "Get" && cecilMethod.DeclaringType is ArrayType && methodArgs.Count > 1) {
+ return target.Indexer(methodArgs);
+ } else if (cecilMethod.Name == "Set" && cecilMethod.DeclaringType is ArrayType && methodArgs.Count > 2) {
+ return new AssignmentExpression(target.Indexer(methodArgs.GetRange(0, methodArgs.Count - 1)), methodArgs.Last());
+ }
+
+ // Test whether the method is an accessor:
+ if (cecilMethodDef != null) {
+ if (cecilMethodDef.IsGetter && methodArgs.Count == 0) {
+ foreach (var prop in cecilMethodDef.DeclaringType.Properties) {
+ if (prop.GetMethod == cecilMethodDef)
+ return target.Member(prop.Name).WithAnnotation(prop).WithAnnotation(cecilMethod);
+ }
+ } else if (cecilMethodDef.IsGetter) { // with parameters
+ PropertyDefinition indexer = GetIndexer(cecilMethodDef);
+ if (indexer != null)
+ return target.Indexer(methodArgs).WithAnnotation(indexer).WithAnnotation(cecilMethod);
+ } else if (cecilMethodDef.IsSetter && methodArgs.Count == 1) {
+ foreach (var prop in cecilMethodDef.DeclaringType.Properties) {
+ if (prop.SetMethod == cecilMethodDef)
+ return new AssignmentExpression(target.Member(prop.Name).WithAnnotation(prop).WithAnnotation(cecilMethod), methodArgs[0]);
+ }
+ } else if (cecilMethodDef.IsSetter && methodArgs.Count > 1) {
+ PropertyDefinition indexer = GetIndexer(cecilMethodDef);
+ if (indexer != null)
+ return new AssignmentExpression(
+ target.Indexer(methodArgs.GetRange(0, methodArgs.Count - 1)).WithAnnotation(indexer).WithAnnotation(cecilMethod),
+ methodArgs[methodArgs.Count - 1]
+ );
+ } else if (cecilMethodDef.IsAddOn && methodArgs.Count == 1) {
+ foreach (var ev in cecilMethodDef.DeclaringType.Events) {
+ if (ev.AddMethod == cecilMethodDef) {
+ return new AssignmentExpression {
+ Left = target.Member(ev.Name).WithAnnotation(ev).WithAnnotation(cecilMethod),
+ Operator = AssignmentOperatorType.Add,
+ Right = methodArgs[0]
+ };
+ }
+ }
+ } else if (cecilMethodDef.IsRemoveOn && methodArgs.Count == 1) {
+ foreach (var ev in cecilMethodDef.DeclaringType.Events) {
+ if (ev.RemoveMethod == cecilMethodDef) {
+ return new AssignmentExpression {
+ Left = target.Member(ev.Name).WithAnnotation(ev).WithAnnotation(cecilMethod),
+ Operator = AssignmentOperatorType.Subtract,
+ Right = methodArgs[0]
+ };
+ }
+ }
+ } else if (cecilMethodDef.Name == "Invoke" && cecilMethodDef.DeclaringType.BaseType != null && cecilMethodDef.DeclaringType.BaseType.FullName == "System.MulticastDelegate") {
+ AdjustArgumentsForMethodCall(cecilMethod, methodArgs);
+ return target.Invoke(methodArgs).WithAnnotation(cecilMethod);
+ }
+ }
+ // Default invocation
+ AdjustArgumentsForMethodCall(cecilMethodDef ?? cecilMethod, methodArgs);
+ return target.Invoke(cecilMethod.Name, ConvertTypeArguments(cecilMethod), methodArgs).WithAnnotation(cecilMethod);
+ }
+
+ static Expression UnpackDirectionExpression(Expression target)
+ {
+ if (target is DirectionExpression) {
+ return ((DirectionExpression)target).Expression.Detach();
+ } else {
+ return target;
+ }
+ }
+
+ static void AdjustArgumentsForMethodCall(MethodReference cecilMethod, List<Expression> methodArgs)
+ {
+ // Convert 'ref' into 'out' where necessary
+ for (int i = 0; i < methodArgs.Count && i < cecilMethod.Parameters.Count; i++) {
+ DirectionExpression dir = methodArgs[i] as DirectionExpression;
+ ParameterDefinition p = cecilMethod.Parameters[i];
+ if (dir != null && p.IsOut && !p.IsIn)
+ dir.FieldDirection = FieldDirection.Out;
+ }
+ }
+
+ internal static PropertyDefinition GetIndexer(MethodDefinition cecilMethodDef)
+ {
+ TypeDefinition typeDef = cecilMethodDef.DeclaringType;
+ string indexerName = null;
+ foreach (CustomAttribute ca in typeDef.CustomAttributes) {
+ if (ca.Constructor.FullName == "System.Void System.Reflection.DefaultMemberAttribute::.ctor(System.String)") {
+ indexerName = ca.ConstructorArguments.Single().Value as string;
+ break;
+ }
+ }
+ if (indexerName == null)
+ return null;
+ foreach (PropertyDefinition prop in typeDef.Properties) {
+ if (prop.Name == indexerName) {
+ if (prop.GetMethod == cecilMethodDef || prop.SetMethod == cecilMethodDef)
+ return prop;
+ }
+ }
+ return null;
+ }
+
+ #if DEBUG
+ static readonly ConcurrentDictionary<ILCode, int> unhandledOpcodes = new ConcurrentDictionary<ILCode, int>();
+ #endif
+
+ [Conditional("DEBUG")]
+ public static void ClearUnhandledOpcodes()
+ {
+ #if DEBUG
+ unhandledOpcodes.Clear();
+ #endif
+ }
+
+ [Conditional("DEBUG")]
+ public static void PrintNumberOfUnhandledOpcodes()
+ {
+ #if DEBUG
+ foreach (var pair in unhandledOpcodes) {
+ Debug.WriteLine("AddMethodBodyBuilder unhandled opcode: {1}x {0}", pair.Key, pair.Value);
+ }
+ #endif
+ }
+
+ static Expression InlineAssembly(ILExpression byteCode, List<Expression> args)
+ {
+ #if DEBUG
+ unhandledOpcodes.AddOrUpdate(byteCode.Code, c => 1, (c, n) => n+1);
+ #endif
+ // Output the operand of the unknown IL code as well
+ if (byteCode.Operand != null) {
+ args.Insert(0, new IdentifierExpression(FormatByteCodeOperand(byteCode.Operand)));
+ }
+ return new IdentifierExpression(byteCode.Code.GetName()).Invoke(args);
+ }
+
+ static string FormatByteCodeOperand(object operand)
+ {
+ if (operand == null) {
+ return string.Empty;
+ //} else if (operand is ILExpression) {
+ // return string.Format("IL_{0:X2}", ((ILExpression)operand).Offset);
+ } else if (operand is MethodReference) {
+ return ((MethodReference)operand).Name + "()";
+ } else if (operand is TypeReference) {
+ return ((TypeReference)operand).FullName;
+ } else if (operand is VariableDefinition) {
+ return ((VariableDefinition)operand).Name;
+ } else if (operand is ParameterDefinition) {
+ return ((ParameterDefinition)operand).Name;
+ } else if (operand is FieldReference) {
+ return ((FieldReference)operand).Name;
+ } else if (operand is string) {
+ return "\"" + operand + "\"";
+ } else if (operand is int) {
+ return operand.ToString();
+ } else {
+ return operand.ToString();
+ }
+ }
+
+ static IEnumerable<AstType> ConvertTypeArguments(MethodReference cecilMethod)
+ {
+ GenericInstanceMethod g = cecilMethod as GenericInstanceMethod;
+ if (g == null)
+ return null;
+ if (g.GenericArguments.Any(ta => ta.ContainsAnonymousType()))
+ return null;
+ return g.GenericArguments.Select(t => AstBuilder.ConvertType(t));
+ }
+
+ static DirectionExpression MakeRef(Expression expr)
+ {
+ return new DirectionExpression { Expression = expr, FieldDirection = FieldDirection.Ref };
+ }
+
+ Expression Convert(Expression expr, TypeReference actualType, TypeReference reqType)
+ {
+ if (actualType == null || reqType == null || TypeAnalysis.IsSameType(actualType, reqType)) {
+ return expr;
+ } else if (actualType is ByReferenceType && reqType is PointerType && expr is DirectionExpression) {
+ return Convert(
+ new UnaryOperatorExpression(UnaryOperatorType.AddressOf, ((DirectionExpression)expr).Expression.Detach()),
+ new PointerType(((ByReferenceType)actualType).ElementType),
+ reqType);
+ } else if (actualType is PointerType && reqType is ByReferenceType) {
+ expr = Convert(expr, actualType, new PointerType(((ByReferenceType)reqType).ElementType));
+ return new DirectionExpression {
+ FieldDirection = FieldDirection.Ref,
+ Expression = new UnaryOperatorExpression(UnaryOperatorType.Dereference, expr)
+ };
+ } else if (actualType is PointerType && reqType is PointerType) {
+ if (actualType.FullName != reqType.FullName)
+ return expr.CastTo(AstBuilder.ConvertType(reqType));
+ else
+ return expr;
+ } else {
+ bool actualIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(actualType);
+ bool requiredIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(reqType);
+
+ if (TypeAnalysis.IsBoolean(reqType)) {
+ if (TypeAnalysis.IsBoolean(actualType))
+ return expr;
+ if (actualIsIntegerOrEnum) {
+ return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, AstBuilder.MakePrimitive(0, actualType));
+ } else {
+ return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, new NullReferenceExpression());
+ }
+ }
+ if (TypeAnalysis.IsBoolean(actualType) && requiredIsIntegerOrEnum) {
+ return new ConditionalExpression {
+ Condition = expr,
+ TrueExpression = AstBuilder.MakePrimitive(1, reqType),
+ FalseExpression = AstBuilder.MakePrimitive(0, reqType)
+ };
+ }
+
+ if (expr is PrimitiveExpression && !requiredIsIntegerOrEnum && TypeAnalysis.IsEnum(actualType))
+ {
+ return expr.CastTo(AstBuilder.ConvertType(actualType));
+ }
+
+ bool actualIsPrimitiveType = actualIsIntegerOrEnum
+ || actualType.MetadataType == MetadataType.Single || actualType.MetadataType == MetadataType.Double;
+ bool requiredIsPrimitiveType = requiredIsIntegerOrEnum
+ || reqType.MetadataType == MetadataType.Single || reqType.MetadataType == MetadataType.Double;
+ if (actualIsPrimitiveType && requiredIsPrimitiveType) {
+ return expr.CastTo(AstBuilder.ConvertType(reqType));
+ }
+ return expr;
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/CommentStatement.cs b/ICSharpCode.Decompiler/Ast/CommentStatement.cs
new file mode 100644
index 00000000..39bc2450
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/CommentStatement.cs
@@ -0,0 +1,69 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Linq;
+using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.PatternMatching;
+
+namespace ICSharpCode.Decompiler.Ast
+{
+ /// <summary>
+ /// Allows storing comments inside IEnumerable{Statement}. Used in the AstMethodBuilder.
+ /// CommentStatement nodes are replaced with regular comments later on.
+ /// </summary>
+ internal class CommentStatement : Statement
+ {
+ string comment;
+
+ public CommentStatement(string comment)
+ {
+ if (comment == null)
+ throw new ArgumentNullException("comment");
+ this.comment = comment;
+ }
+
+ public override void AcceptVisitor(IAstVisitor visitor)
+ {
+ }
+
+ public override T AcceptVisitor<T>(IAstVisitor<T> visitor)
+ {
+ return default(T);
+ }
+
+ public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
+ {
+ return default(S);
+ }
+
+ public static void ReplaceAll(AstNode tree)
+ {
+ foreach (var cs in tree.Descendants.OfType<CommentStatement>()) {
+ cs.Parent.InsertChildBefore(cs, new Comment(cs.comment), Roles.Comment);
+ cs.Remove();
+ }
+ }
+
+ protected override bool DoMatch(AstNode other, Match match)
+ {
+ CommentStatement o = other as CommentStatement;
+ return o != null && MatchString(comment, o.comment);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/DecompilerContext.cs b/ICSharpCode.Decompiler/Ast/DecompilerContext.cs
new file mode 100644
index 00000000..d055de1d
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/DecompilerContext.cs
@@ -0,0 +1,71 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using ICSharpCode.Decompiler.Ast;
+using ICSharpCode.NRefactory.TypeSystem;
+using ICSharpCode.NRefactory.TypeSystem.Implementation;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler
+{
+ public class DecompilerContext
+ {
+ public ModuleDefinition CurrentModule;
+ public CancellationToken CancellationToken;
+ public TypeDefinition CurrentType;
+ public MethodDefinition CurrentMethod;
+ public DecompilerSettings Settings = new DecompilerSettings();
+ public bool CurrentMethodIsAsync;
+
+// public ITypeResolveContext TypeResolveContext;
+// public IProjectContent ProjectContent;
+
+ public DecompilerContext(ModuleDefinition currentModule)
+ {
+ if (currentModule == null)
+ throw new ArgumentNullException("currentModule");
+ CurrentModule = currentModule;
+
+// this.ProjectContent = new CecilTypeResolveContext(currentModule);
+// List<ITypeResolveContext> resolveContexts = new List<ITypeResolveContext>();
+// resolveContexts.Add(this.ProjectContent);
+// foreach (AssemblyNameReference r in currentModule.AssemblyReferences) {
+// AssemblyDefinition d = currentModule.AssemblyResolver.Resolve(r);
+// if (d != null) {
+// resolveContexts.Add(new CecilTypeResolveContext(d.MainModule));
+// }
+// }
+// this.TypeResolveContext = new CompositeTypeResolveContext(resolveContexts);
+ }
+
+ /// <summary>
+ /// Used to pass variable names from a method to its anonymous methods.
+ /// </summary>
+ internal List<string> ReservedVariableNames = new List<string>();
+
+ public DecompilerContext Clone()
+ {
+ DecompilerContext ctx = (DecompilerContext)MemberwiseClone();
+ ctx.ReservedVariableNames = new List<string>(ctx.ReservedVariableNames);
+ return ctx;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs b/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs
new file mode 100644
index 00000000..80730061
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs
@@ -0,0 +1,86 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.PatternMatching;
+
+namespace ICSharpCode.Decompiler.Ast
+{
+ internal static class NRefactoryExtensions
+ {
+ public static T WithAnnotation<T>(this T node, object annotation) where T : AstNode
+ {
+ if (annotation != null)
+ node.AddAnnotation(annotation);
+ return node;
+ }
+
+ public static T CopyAnnotationsFrom<T>(this T node, AstNode other) where T : AstNode
+ {
+ foreach (object annotation in other.Annotations) {
+ node.AddAnnotation(annotation);
+ }
+ return node;
+ }
+
+ public static T Detach<T>(this T node) where T : AstNode
+ {
+ node.Remove();
+ return node;
+ }
+
+ public static Expression WithName(this Expression node, string patternGroupName)
+ {
+ return new NamedNode(patternGroupName, node);
+ }
+
+ public static Statement WithName(this Statement node, string patternGroupName)
+ {
+ return new NamedNode(patternGroupName, node);
+ }
+
+ public static void AddNamedArgument(this NRefactory.CSharp.Attribute attribute, string name, Expression argument)
+ {
+ attribute.Arguments.Add(new AssignmentExpression(new IdentifierExpression(name), argument));
+ }
+
+ public static AstType ToType(this Pattern pattern)
+ {
+ return pattern;
+ }
+
+ public static Expression ToExpression(this Pattern pattern)
+ {
+ return pattern;
+ }
+
+ public static Statement ToStatement(this Pattern pattern)
+ {
+ return pattern;
+ }
+
+ public static Statement GetNextStatement(this Statement statement)
+ {
+ AstNode next = statement.NextSibling;
+ while (next != null && !(next is Statement))
+ next = next.NextSibling;
+ return (Statement)next;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/NameVariables.cs b/ICSharpCode.Decompiler/Ast/NameVariables.cs
new file mode 100644
index 00000000..3da808cb
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/NameVariables.cs
@@ -0,0 +1,347 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using ICSharpCode.Decompiler.ILAst;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.Ast
+{
+ public class NameVariables
+ {
+ static readonly Dictionary<string, string> typeNameToVariableNameDict = new Dictionary<string, string> {
+ { "System.Boolean", "flag" },
+ { "System.Byte", "b" },
+ { "System.SByte", "b" },
+ { "System.Int16", "num" },
+ { "System.Int32", "num" },
+ { "System.Int64", "num" },
+ { "System.UInt16", "num" },
+ { "System.UInt32", "num" },
+ { "System.UInt64", "num" },
+ { "System.Single", "num" },
+ { "System.Double", "num" },
+ { "System.Decimal", "num" },
+ { "System.String", "text" },
+ { "System.Object", "obj" },
+ { "System.Char", "c" }
+ };
+
+
+ public static void AssignNamesToVariables(DecompilerContext context, IEnumerable<ILVariable> parameters, IEnumerable<ILVariable> variables, ILBlock methodBody)
+ {
+ NameVariables nv = new NameVariables();
+ nv.context = context;
+ nv.fieldNamesInCurrentType = context.CurrentType.Fields.Select(f => f.Name).ToList();
+ // First mark existing variable names as reserved.
+ foreach (string name in context.ReservedVariableNames)
+ nv.AddExistingName(name);
+ foreach (var p in parameters)
+ nv.AddExistingName(p.Name);
+ foreach (var v in variables) {
+ if (v.IsGenerated) {
+ // don't introduce names for variables generated by ILSpy - keep "expr"/"arg"
+ nv.AddExistingName(v.Name);
+ } else if (v.OriginalVariable != null && context.Settings.UseDebugSymbols) {
+ string varName = v.OriginalVariable.Name;
+ if (string.IsNullOrEmpty(varName) || varName.StartsWith("V_", StringComparison.Ordinal) || !IsValidName(varName))
+ {
+ // don't use the name from the debug symbols if it looks like a generated name
+ v.Name = null;
+ } else {
+ // use the name from the debug symbols
+ // (but ensure we don't use the same name for two variables)
+ v.Name = nv.GetAlternativeName(varName);
+ }
+ } else {
+ v.Name = null;
+ }
+ }
+ // Now generate names:
+ foreach (ILVariable p in parameters) {
+ if (string.IsNullOrEmpty(p.Name))
+ p.Name = nv.GenerateNameForVariable(p, methodBody);
+ }
+ foreach (ILVariable varDef in variables) {
+ if (string.IsNullOrEmpty(varDef.Name))
+ varDef.Name = nv.GenerateNameForVariable(varDef, methodBody);
+ }
+ }
+
+ static bool IsValidName(string varName)
+ {
+ if (string.IsNullOrEmpty(varName))
+ return false;
+ if (!(char.IsLetter(varName[0]) || varName[0] == '_'))
+ return false;
+ for (int i = 1; i < varName.Length; i++) {
+ if (!(char.IsLetterOrDigit(varName[i]) || varName[i] == '_'))
+ return false;
+ }
+ return true;
+ }
+
+ DecompilerContext context;
+ List<string> fieldNamesInCurrentType;
+ Dictionary<string, int> typeNames = new Dictionary<string, int>();
+
+ public void AddExistingName(string name)
+ {
+ if (string.IsNullOrEmpty(name))
+ return;
+ int number;
+ string nameWithoutDigits = SplitName(name, out number);
+ int existingNumber;
+ if (typeNames.TryGetValue(nameWithoutDigits, out existingNumber)) {
+ typeNames[nameWithoutDigits] = Math.Max(number, existingNumber);
+ } else {
+ typeNames.Add(nameWithoutDigits, number);
+ }
+ }
+
+ string SplitName(string name, out int number)
+ {
+ // First, identify whether the name already ends with a number:
+ int pos = name.Length;
+ while (pos > 0 && name[pos-1] >= '0' && name[pos-1] <= '9')
+ pos--;
+ if (pos < name.Length) {
+ if (int.TryParse(name.Substring(pos), out number)) {
+ return name.Substring(0, pos);
+ }
+ }
+ number = 1;
+ return name;
+ }
+
+ const char maxLoopVariableName = 'n';
+
+ public string GetAlternativeName(string oldVariableName)
+ {
+ if (oldVariableName.Length == 1 && oldVariableName[0] >= 'i' && oldVariableName[0] <= maxLoopVariableName) {
+ for (char c = 'i'; c <= maxLoopVariableName; c++) {
+ if (!typeNames.ContainsKey(c.ToString())) {
+ typeNames.Add(c.ToString(), 1);
+ return c.ToString();
+ }
+ }
+ }
+
+ int number;
+ string nameWithoutDigits = SplitName(oldVariableName, out number);
+
+ if (!typeNames.ContainsKey(nameWithoutDigits)) {
+ typeNames.Add(nameWithoutDigits, number - 1);
+ }
+ int count = ++typeNames[nameWithoutDigits];
+ if (count != 1) {
+ return nameWithoutDigits + count.ToString();
+ } else {
+ return nameWithoutDigits;
+ }
+ }
+
+ string GenerateNameForVariable(ILVariable variable, ILBlock methodBody)
+ {
+ string proposedName = null;
+ if (variable.Type == context.CurrentType.Module.TypeSystem.Int32) {
+ // test whether the variable might be a loop counter
+ bool isLoopCounter = false;
+ foreach (ILWhileLoop loop in methodBody.GetSelfAndChildrenRecursive<ILWhileLoop>()) {
+ ILExpression expr = loop.Condition;
+ while (expr != null && expr.Code == ILCode.LogicNot)
+ expr = expr.Arguments[0];
+ if (expr != null) {
+ switch (expr.Code) {
+ case ILCode.Clt:
+ case ILCode.Clt_Un:
+ case ILCode.Cgt:
+ case ILCode.Cgt_Un:
+ case ILCode.Cle:
+ case ILCode.Cle_Un:
+ case ILCode.Cge:
+ case ILCode.Cge_Un:
+ ILVariable loadVar;
+ if (expr.Arguments[0].Match(ILCode.Ldloc, out loadVar) && loadVar == variable) {
+ isLoopCounter = true;
+ }
+ break;
+ }
+ }
+ }
+ if (isLoopCounter) {
+ // For loop variables, use i,j,k,l,m,n
+ for (char c = 'i'; c <= maxLoopVariableName; c++) {
+ if (!typeNames.ContainsKey(c.ToString())) {
+ proposedName = c.ToString();
+ break;
+ }
+ }
+ }
+ }
+ if (string.IsNullOrEmpty(proposedName)) {
+ var proposedNameForStores =
+ (from expr in methodBody.GetSelfAndChildrenRecursive<ILExpression>()
+ where expr.Code == ILCode.Stloc && expr.Operand == variable
+ select GetNameFromExpression(expr.Arguments.Single())
+ ).Except(fieldNamesInCurrentType).ToList();
+ if (proposedNameForStores.Count == 1) {
+ proposedName = proposedNameForStores[0];
+ }
+ }
+ if (string.IsNullOrEmpty(proposedName)) {
+ var proposedNameForLoads =
+ (from expr in methodBody.GetSelfAndChildrenRecursive<ILExpression>()
+ from i in Enumerable.Range(0, expr.Arguments.Count)
+ let arg = expr.Arguments[i]
+ where arg.Code == ILCode.Ldloc && arg.Operand == variable
+ select GetNameForArgument(expr, i)
+ ).Except(fieldNamesInCurrentType).ToList();
+ if (proposedNameForLoads.Count == 1) {
+ proposedName = proposedNameForLoads[0];
+ }
+ }
+ if (string.IsNullOrEmpty(proposedName)) {
+ proposedName = GetNameByType(variable.Type);
+ }
+
+ // remove any numbers from the proposed name
+ int number;
+ proposedName = SplitName(proposedName, out number);
+
+ if (!typeNames.ContainsKey(proposedName)) {
+ typeNames.Add(proposedName, 0);
+ }
+ int count = ++typeNames[proposedName];
+ if (count > 1) {
+ return proposedName + count.ToString();
+ } else {
+ return proposedName;
+ }
+ }
+
+ static string GetNameFromExpression(ILExpression expr)
+ {
+ switch (expr.Code) {
+ case ILCode.Ldfld:
+ case ILCode.Ldsfld:
+ return CleanUpVariableName(((FieldReference)expr.Operand).Name);
+ case ILCode.Call:
+ case ILCode.Callvirt:
+ case ILCode.CallGetter:
+ case ILCode.CallvirtGetter:
+ MethodReference mr = (MethodReference)expr.Operand;
+ if (mr.Name.StartsWith("get_", StringComparison.OrdinalIgnoreCase) && mr.Parameters.Count == 0) {
+ // use name from properties, but not from indexers
+ return CleanUpVariableName(mr.Name.Substring(4));
+ } else if (mr.Name.StartsWith("Get", StringComparison.OrdinalIgnoreCase) && mr.Name.Length >= 4 && char.IsUpper(mr.Name[3])) {
+ // use name from Get-methods
+ return CleanUpVariableName(mr.Name.Substring(3));
+ }
+ break;
+ }
+ return null;
+ }
+
+ static string GetNameForArgument(ILExpression parent, int i)
+ {
+ switch (parent.Code) {
+ case ILCode.Stfld:
+ case ILCode.Stsfld:
+ if (i == parent.Arguments.Count - 1) // last argument is stored value
+ return CleanUpVariableName(((FieldReference)parent.Operand).Name);
+ else
+ break;
+ case ILCode.Call:
+ case ILCode.Callvirt:
+ case ILCode.Newobj:
+ case ILCode.CallGetter:
+ case ILCode.CallvirtGetter:
+ case ILCode.CallSetter:
+ case ILCode.CallvirtSetter:
+ MethodReference methodRef = (MethodReference)parent.Operand;
+ if (methodRef.Parameters.Count == 1 && i == parent.Arguments.Count - 1) {
+ // argument might be value of a setter
+ if (methodRef.Name.StartsWith("set_", StringComparison.OrdinalIgnoreCase)) {
+ return CleanUpVariableName(methodRef.Name.Substring(4));
+ } else if (methodRef.Name.StartsWith("Set", StringComparison.OrdinalIgnoreCase) && methodRef.Name.Length >= 4 && char.IsUpper(methodRef.Name[3])) {
+ return CleanUpVariableName(methodRef.Name.Substring(3));
+ }
+ }
+ MethodDefinition methodDef = methodRef.Resolve();
+ if (methodDef != null) {
+ var p = methodDef.Parameters.ElementAtOrDefault((parent.Code != ILCode.Newobj && methodDef.HasThis) ? i - 1 : i);
+ if (p != null && !string.IsNullOrEmpty(p.Name))
+ return CleanUpVariableName(p.Name);
+ }
+ break;
+ case ILCode.Ret:
+ return "result";
+ }
+ return null;
+ }
+
+ string GetNameByType(TypeReference type)
+ {
+ type = TypeAnalysis.UnpackModifiers(type);
+
+ GenericInstanceType git = type as GenericInstanceType;
+ if (git != null && git.ElementType.FullName == "System.Nullable`1" && git.GenericArguments.Count == 1) {
+ type = ((GenericInstanceType)type).GenericArguments[0];
+ }
+
+ string name;
+ if (type.IsArray) {
+ name = "array";
+ } else if (type.IsPointer || type.IsByReference) {
+ name = "ptr";
+ } else if (type.Name.EndsWith("Exception", StringComparison.Ordinal)) {
+ name = "ex";
+ } else if (!typeNameToVariableNameDict.TryGetValue(type.FullName, out name)) {
+ name = type.Name;
+ // remove the 'I' for interfaces
+ if (name.Length >= 3 && name[0] == 'I' && char.IsUpper(name[1]) && char.IsLower(name[2]))
+ name = name.Substring(1);
+ name = CleanUpVariableName(name);
+ }
+ return name;
+ }
+
+ static string CleanUpVariableName(string name)
+ {
+ // remove the backtick (generics)
+ int pos = name.IndexOf('`');
+ if (pos >= 0)
+ name = name.Substring(0, pos);
+
+ // remove field prefix:
+ if (name.Length > 2 && name.StartsWith("m_", StringComparison.Ordinal))
+ name = name.Substring(2);
+ else if (name.Length > 1 && name[0] == '_')
+ name = name.Substring(1);
+
+ if (name.Length == 0)
+ return "obj";
+ else
+ return char.ToLower(name[0]) + name.Substring(1);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs b/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs
new file mode 100644
index 00000000..fed08aaa
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs
@@ -0,0 +1,369 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.ILAst;
+using ICSharpCode.NRefactory;
+using ICSharpCode.NRefactory.CSharp;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.Ast
+{
+ public class TextTokenWriter : TokenWriter
+ {
+ readonly ITextOutput output;
+ readonly DecompilerContext context;
+ readonly Stack<AstNode> nodeStack = new Stack<AstNode>();
+ int braceLevelWithinType = -1;
+ bool inDocumentationComment = false;
+ bool firstUsingDeclaration;
+ bool lastUsingDeclaration;
+
+ TextLocation? lastEndOfLine;
+
+ public bool FoldBraces = false;
+
+ public TextTokenWriter(ITextOutput output, DecompilerContext context)
+ {
+ if (output == null)
+ throw new ArgumentNullException("output");
+ if (context == null)
+ throw new ArgumentNullException("context");
+ this.output = output;
+ this.context = context;
+ }
+
+ public override void WriteIdentifier(Identifier identifier)
+ {
+ var definition = GetCurrentDefinition();
+ if (definition != null) {
+ output.WriteDefinition(identifier.Name, definition, false);
+ return;
+ }
+
+ object memberRef = GetCurrentMemberReference();
+
+ if (memberRef != null) {
+ output.WriteReference(identifier.Name, memberRef);
+ return;
+ }
+
+ definition = GetCurrentLocalDefinition();
+ if (definition != null) {
+ output.WriteDefinition(identifier.Name, definition);
+ return;
+ }
+
+ memberRef = GetCurrentLocalReference();
+ if (memberRef != null) {
+ output.WriteReference(identifier.Name, memberRef, true);
+ return;
+ }
+
+ if (firstUsingDeclaration) {
+ output.MarkFoldStart(defaultCollapsed: true);
+ firstUsingDeclaration = false;
+ }
+
+ output.Write(identifier.Name);
+ }
+
+ MemberReference GetCurrentMemberReference()
+ {
+ AstNode node = nodeStack.Peek();
+ MemberReference memberRef = node.Annotation<MemberReference>();
+ if (memberRef == null && node.Role == Roles.TargetExpression && (node.Parent is InvocationExpression || node.Parent is ObjectCreateExpression)) {
+ memberRef = node.Parent.Annotation<MemberReference>();
+ }
+ if (node is IdentifierExpression && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression && memberRef != null) {
+ var declaringType = memberRef.DeclaringType.Resolve();
+ if (declaringType != null && declaringType.IsDelegate())
+ return null;
+ }
+ return FilterMemberReference(memberRef);
+ }
+
+ MemberReference FilterMemberReference(MemberReference memberRef)
+ {
+ if (memberRef == null)
+ return null;
+
+ if (context.Settings.AutomaticEvents && memberRef is FieldDefinition) {
+ var field = (FieldDefinition)memberRef;
+ return field.DeclaringType.Events.FirstOrDefault(ev => ev.Name == field.Name) ?? memberRef;
+ }
+
+ return memberRef;
+ }
+
+ object GetCurrentLocalReference()
+ {
+ AstNode node = nodeStack.Peek();
+ ILVariable variable = node.Annotation<ILVariable>();
+ if (variable != null) {
+ if (variable.OriginalParameter != null)
+ return variable.OriginalParameter;
+ //if (variable.OriginalVariable != null)
+ // return variable.OriginalVariable;
+ return variable;
+ }
+
+ var gotoStatement = node as GotoStatement;
+ if (gotoStatement != null)
+ {
+ var method = nodeStack.Select(nd => nd.Annotation<MethodReference>()).FirstOrDefault(mr => mr != null);
+ if (method != null)
+ return method.ToString() + gotoStatement.Label;
+ }
+
+ return null;
+ }
+
+ object GetCurrentLocalDefinition()
+ {
+ AstNode node = nodeStack.Peek();
+ if (node is Identifier && node.Parent != null)
+ node = node.Parent;
+
+ var parameterDef = node.Annotation<ParameterDefinition>();
+ if (parameterDef != null)
+ return parameterDef;
+
+ if (node is VariableInitializer || node is CatchClause || node is ForeachStatement) {
+ var variable = node.Annotation<ILVariable>();
+ if (variable != null) {
+ if (variable.OriginalParameter != null)
+ return variable.OriginalParameter;
+ //if (variable.OriginalVariable != null)
+ // return variable.OriginalVariable;
+ return variable;
+ }
+ }
+
+ var label = node as LabelStatement;
+ if (label != null) {
+ var method = nodeStack.Select(nd => nd.Annotation<MethodReference>()).FirstOrDefault(mr => mr != null);
+ if (method != null)
+ return method.ToString() + label.Label;
+ }
+
+ return null;
+ }
+
+ object GetCurrentDefinition()
+ {
+ if (nodeStack == null || nodeStack.Count == 0)
+ return null;
+
+ var node = nodeStack.Peek();
+ if (node is Identifier)
+ node = node.Parent;
+ if (IsDefinition(node))
+ return node.Annotation<MemberReference>();
+
+ return null;
+ }
+
+ public override void WriteKeyword(Role role, string keyword)
+ {
+ output.Write(keyword);
+ }
+
+ public override void WriteToken(Role role, string token)
+ {
+ // Attach member reference to token only if there's no identifier in the current node.
+ MemberReference memberRef = GetCurrentMemberReference();
+ var node = nodeStack.Peek();
+ if (memberRef != null && node.GetChildByRole(Roles.Identifier).IsNull)
+ output.WriteReference(token, memberRef);
+ else
+ output.Write(token);
+ }
+
+ public override void Space()
+ {
+ output.Write(' ');
+ }
+
+ public void OpenBrace(BraceStyle style)
+ {
+ if (braceLevelWithinType >= 0 || nodeStack.Peek() is TypeDeclaration)
+ braceLevelWithinType++;
+ if (nodeStack.OfType<BlockStatement>().Count() <= 1 || FoldBraces) {
+ output.MarkFoldStart(defaultCollapsed: braceLevelWithinType == 1);
+ }
+ output.WriteLine();
+ output.WriteLine("{");
+ output.Indent();
+ }
+
+ public void CloseBrace(BraceStyle style)
+ {
+ output.Unindent();
+ output.Write('}');
+ if (nodeStack.OfType<BlockStatement>().Count() <= 1 || FoldBraces)
+ output.MarkFoldEnd();
+ if (braceLevelWithinType >= 0)
+ braceLevelWithinType--;
+ }
+
+ public override void Indent()
+ {
+ output.Indent();
+ }
+
+ public override void Unindent()
+ {
+ output.Unindent();
+ }
+
+ public override void NewLine()
+ {
+ if (lastUsingDeclaration) {
+ output.MarkFoldEnd();
+ lastUsingDeclaration = false;
+ }
+ lastEndOfLine = output.Location;
+ output.WriteLine();
+ }
+
+ public override void WriteComment(CommentType commentType, string content)
+ {
+ switch (commentType) {
+ case CommentType.SingleLine:
+ output.Write("//");
+ output.WriteLine(content);
+ break;
+ case CommentType.MultiLine:
+ output.Write("/*");
+ output.Write(content);
+ output.Write("*/");
+ break;
+ case CommentType.Documentation:
+ bool isLastLine = !(nodeStack.Peek().NextSibling is Comment);
+ if (!inDocumentationComment && !isLastLine) {
+ inDocumentationComment = true;
+ output.MarkFoldStart("///" + content, true);
+ }
+ output.Write("///");
+ output.Write(content);
+ if (inDocumentationComment && isLastLine) {
+ inDocumentationComment = false;
+ output.MarkFoldEnd();
+ }
+ output.WriteLine();
+ break;
+ default:
+ output.Write(content);
+ break;
+ }
+ }
+
+ public override void WritePreProcessorDirective(PreProcessorDirectiveType type, string argument)
+ {
+ // pre-processor directive must start on its own line
+ output.Write('#');
+ output.Write(type.ToString().ToLowerInvariant());
+ if (!string.IsNullOrEmpty(argument)) {
+ output.Write(' ');
+ output.Write(argument);
+ }
+ output.WriteLine();
+ }
+
+ public override void WritePrimitiveValue(object value, string literalValue = null)
+ {
+ new TextWriterTokenWriter(new TextOutputWriter(output)).WritePrimitiveValue(value, literalValue);
+ }
+
+ public override void WritePrimitiveType(string type)
+ {
+ output.Write(type);
+ if (type == "new") {
+ output.Write("()");
+ }
+ }
+
+ Stack<TextLocation> startLocations = new Stack<TextLocation>();
+ Stack<MethodDebugSymbols> symbolsStack = new Stack<MethodDebugSymbols>();
+
+ public override void StartNode(AstNode node)
+ {
+ if (nodeStack.Count == 0) {
+ if (IsUsingDeclaration(node)) {
+ firstUsingDeclaration = !IsUsingDeclaration(node.PrevSibling);
+ lastUsingDeclaration = !IsUsingDeclaration(node.NextSibling);
+ } else {
+ firstUsingDeclaration = false;
+ lastUsingDeclaration = false;
+ }
+ }
+ nodeStack.Push(node);
+ startLocations.Push(output.Location);
+
+ if (node is EntityDeclaration && node.Annotation<MemberReference>() != null && node.GetChildByRole(Roles.Identifier).IsNull)
+ output.WriteDefinition("", node.Annotation<MemberReference>(), false);
+
+ if (node.Annotation<MethodDebugSymbols>() != null) {
+ symbolsStack.Push(node.Annotation<MethodDebugSymbols>());
+ symbolsStack.Peek().StartLocation = startLocations.Peek();
+ }
+ }
+
+ bool IsUsingDeclaration(AstNode node)
+ {
+ return node is UsingDeclaration || node is UsingAliasDeclaration;
+ }
+
+ public override void EndNode(AstNode node)
+ {
+ if (nodeStack.Pop() != node)
+ throw new InvalidOperationException();
+
+ var startLocation = startLocations.Pop();
+
+ // code mappings
+ var ranges = node.Annotation<List<ILRange>>();
+ if (symbolsStack.Count > 0 && ranges != null && ranges.Count > 0) {
+ // Ignore the newline which was printed at the end of the statement
+ TextLocation endLocation = (node is Statement) ? (lastEndOfLine ?? output.Location) : output.Location;
+ symbolsStack.Peek().SequencePoints.Add(
+ new SequencePoint() {
+ ILRanges = ILRange.OrderAndJoin(ranges).ToArray(),
+ StartLocation = startLocation,
+ EndLocation = endLocation
+ });
+ }
+
+ if (node.Annotation<MethodDebugSymbols>() != null) {
+ symbolsStack.Peek().EndLocation = output.Location;
+ output.AddDebugSymbols(symbolsStack.Pop());
+ }
+ }
+
+ static bool IsDefinition(AstNode node)
+ {
+ return node is EntityDeclaration
+ || (node is VariableInitializer && node.Parent is FieldDeclaration)
+ || node is FixedVariableInitializer;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/AddCheckedBlocks.cs b/ICSharpCode.Decompiler/Ast/Transforms/AddCheckedBlocks.cs
new file mode 100644
index 00000000..dc018eb1
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/AddCheckedBlocks.cs
@@ -0,0 +1,368 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Linq;
+using ICSharpCode.Decompiler.ILAst;
+using ICSharpCode.NRefactory.CSharp;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ /// <summary>
+ /// Add checked/unchecked blocks.
+ /// </summary>
+ public class AddCheckedBlocks : IAstTransform
+ {
+ #region Annotation
+ sealed class CheckedUncheckedAnnotation {
+ /// <summary>
+ /// true=checked, false=unchecked
+ /// </summary>
+ public bool IsChecked;
+ }
+
+ public static readonly object CheckedAnnotation = new CheckedUncheckedAnnotation { IsChecked = true };
+ public static readonly object UncheckedAnnotation = new CheckedUncheckedAnnotation { IsChecked = false };
+ #endregion
+
+ /*
+ We treat placing checked/unchecked blocks as an optimization problem, with the following goals:
+ 1. Use minimum number of checked blocks+expressions
+ 2. Prefer checked expressions over checked blocks
+ 3. Make the scope of checked expressions as small as possible
+ 4. Open checked blocks as late as possible, and close checked blocks as late as possible
+ (where goal 1 has the highest priority)
+
+ Goal 4a (open checked blocks as late as possible) is necessary so that we don't move variable declarations
+ into checked blocks, as the variable might still be used after the checked block.
+ (this could cause DeclareVariables to omit the variable declaration, producing incorrect code)
+ Goal 4b (close checked blocks as late as possible) makes the code look nicer in this case:
+ checked {
+ int c = a + b;
+ int r = a + c;
+ return r;
+ }
+ If the checked block was closed as early as possible, the variable r would have to be declared outside
+ (this would work, but look badly)
+ */
+
+ #region struct Cost
+ struct Cost
+ {
+ // highest possible cost so that the Blocks+Expressions addition doesn't overflow
+ public static readonly Cost Infinite = new Cost(0x3fffffff, 0x3fffffff);
+
+ public readonly int Blocks;
+ public readonly int Expressions;
+
+ public Cost(int blocks, int expressions)
+ {
+ Blocks = blocks;
+ Expressions = expressions;
+ }
+
+ public static bool operator <(Cost a, Cost b)
+ {
+ return a.Blocks + a.Expressions < b.Blocks + b.Expressions
+ || a.Blocks + a.Expressions == b.Blocks + b.Expressions && a.Blocks < b.Blocks;
+ }
+
+ public static bool operator >(Cost a, Cost b)
+ {
+ return a.Blocks + a.Expressions > b.Blocks + b.Expressions
+ || a.Blocks + a.Expressions == b.Blocks + b.Expressions && a.Blocks > b.Blocks;
+ }
+
+ public static bool operator <=(Cost a, Cost b)
+ {
+ return a.Blocks + a.Expressions < b.Blocks + b.Expressions
+ || a.Blocks + a.Expressions == b.Blocks + b.Expressions && a.Blocks <= b.Blocks;
+ }
+
+ public static bool operator >=(Cost a, Cost b)
+ {
+ return a.Blocks + a.Expressions > b.Blocks + b.Expressions
+ || a.Blocks + a.Expressions == b.Blocks + b.Expressions && a.Blocks >= b.Blocks;
+ }
+
+ public static Cost operator +(Cost a, Cost b)
+ {
+ return new Cost(a.Blocks + b.Blocks, a.Expressions + b.Expressions);
+ }
+
+ public override string ToString()
+ {
+ return string.Format("[{0} + {1}]", Blocks, Expressions);
+ }
+ }
+ #endregion
+
+ #region class InsertedNode
+ /// <summary>
+ /// Holds the blocks and expressions that should be inserted
+ /// </summary>
+ abstract class InsertedNode
+ {
+ public static InsertedNode operator +(InsertedNode a, InsertedNode b)
+ {
+ if (a == null)
+ return b;
+ if (b == null)
+ return a;
+ return new InsertedNodeList(a, b);
+ }
+
+ public abstract void Insert();
+ }
+
+ class InsertedNodeList : InsertedNode
+ {
+ readonly InsertedNode child1, child2;
+
+ public InsertedNodeList(InsertedNode child1, InsertedNode child2)
+ {
+ this.child1 = child1;
+ this.child2 = child2;
+ }
+
+ public override void Insert()
+ {
+ child1.Insert();
+ child2.Insert();
+ }
+ }
+
+ class InsertedExpression : InsertedNode
+ {
+ readonly Expression expression;
+ readonly bool isChecked;
+
+ public InsertedExpression(Expression expression, bool isChecked)
+ {
+ this.expression = expression;
+ this.isChecked = isChecked;
+ }
+
+ public override void Insert()
+ {
+ if (isChecked)
+ expression.ReplaceWith(e => new CheckedExpression { Expression = e });
+ else
+ expression.ReplaceWith(e => new UncheckedExpression { Expression = e });
+ }
+ }
+
+ class ConvertCompoundAssignment : InsertedNode
+ {
+ readonly Expression expression;
+ readonly bool isChecked;
+
+ public ConvertCompoundAssignment(Expression expression, bool isChecked)
+ {
+ this.expression = expression;
+ this.isChecked = isChecked;
+ }
+
+ public override void Insert()
+ {
+ AssignmentExpression assign = expression.Annotation<ReplaceMethodCallsWithOperators.RestoreOriginalAssignOperatorAnnotation>().Restore(expression);
+ expression.ReplaceWith(assign);
+ if (isChecked)
+ assign.Right = new CheckedExpression { Expression = assign.Right.Detach() };
+ else
+ assign.Right = new UncheckedExpression { Expression = assign.Right.Detach() };
+ }
+ }
+
+ class InsertedBlock : InsertedNode
+ {
+ readonly Statement firstStatement; // inclusive
+ readonly Statement lastStatement; // exclusive
+ readonly bool isChecked;
+
+ public InsertedBlock(Statement firstStatement, Statement lastStatement, bool isChecked)
+ {
+ this.firstStatement = firstStatement;
+ this.lastStatement = lastStatement;
+ this.isChecked = isChecked;
+ }
+
+ public override void Insert()
+ {
+ BlockStatement newBlock = new BlockStatement();
+ // Move all statements except for the first
+ Statement next;
+ for (Statement stmt = firstStatement.GetNextStatement(); stmt != lastStatement; stmt = next) {
+ next = stmt.GetNextStatement();
+ newBlock.Add(stmt.Detach());
+ }
+ // Replace the first statement with the new (un)checked block
+ if (isChecked)
+ firstStatement.ReplaceWith(new CheckedStatement { Body = newBlock });
+ else
+ firstStatement.ReplaceWith(new UncheckedStatement { Body = newBlock });
+ // now also move the first node into the new block
+ newBlock.Statements.InsertAfter(null, firstStatement);
+ }
+ }
+ #endregion
+
+ #region class Result
+ /// <summary>
+ /// Holds the result of an insertion operation.
+ /// </summary>
+ class Result
+ {
+ public Cost CostInCheckedContext;
+ public InsertedNode NodesToInsertInCheckedContext;
+ public Cost CostInUncheckedContext;
+ public InsertedNode NodesToInsertInUncheckedContext;
+ }
+ #endregion
+
+ public void Run(AstNode node)
+ {
+ BlockStatement block = node as BlockStatement;
+ if (block == null) {
+ for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
+ Run(child);
+ }
+ } else {
+ Result r = GetResultFromBlock(block);
+ if (r.NodesToInsertInUncheckedContext != null)
+ r.NodesToInsertInUncheckedContext.Insert();
+ }
+ }
+
+ Result GetResultFromBlock(BlockStatement block)
+ {
+ // For a block, we are tracking 4 possibilities:
+ // a) context is checked, no unchecked block open
+ Cost costCheckedContext = new Cost(0, 0);
+ InsertedNode nodesCheckedContext = null;
+ // b) context is checked, an unchecked block is open
+ Cost costCheckedContextUncheckedBlockOpen = Cost.Infinite;
+ InsertedNode nodesCheckedContextUncheckedBlockOpen = null;
+ Statement uncheckedBlockStart = null;
+ // c) context is unchecked, no checked block open
+ Cost costUncheckedContext = new Cost(0, 0);
+ InsertedNode nodesUncheckedContext = null;
+ // d) context is unchecked, a checked block is open
+ Cost costUncheckedContextCheckedBlockOpen = Cost.Infinite;
+ InsertedNode nodesUncheckedContextCheckedBlockOpen = null;
+ Statement checkedBlockStart = null;
+
+ Statement statement = block.Statements.FirstOrDefault();
+ while (true) {
+ // Blocks can be closed 'for free'. We use '<=' so that blocks are closed as late as possible (goal 4b)
+ if (costCheckedContextUncheckedBlockOpen <= costCheckedContext) {
+ costCheckedContext = costCheckedContextUncheckedBlockOpen;
+ nodesCheckedContext = nodesCheckedContextUncheckedBlockOpen + new InsertedBlock(uncheckedBlockStart, statement, false);
+ }
+ if (costUncheckedContextCheckedBlockOpen <= costUncheckedContext) {
+ costUncheckedContext = costUncheckedContextCheckedBlockOpen;
+ nodesUncheckedContext = nodesUncheckedContextCheckedBlockOpen + new InsertedBlock(checkedBlockStart, statement, true);
+ }
+ if (statement == null)
+ break;
+ // Now try opening blocks. We use '<=' so that blocks are opened as late as possible. (goal 4a)
+ if (costCheckedContext + new Cost(1, 0) <= costCheckedContextUncheckedBlockOpen) {
+ costCheckedContextUncheckedBlockOpen = costCheckedContext + new Cost(1, 0);
+ nodesCheckedContextUncheckedBlockOpen = nodesCheckedContext;
+ uncheckedBlockStart = statement;
+ }
+ if (costUncheckedContext + new Cost(1, 0) <= costUncheckedContextCheckedBlockOpen) {
+ costUncheckedContextCheckedBlockOpen = costUncheckedContext + new Cost(1, 0);
+ nodesUncheckedContextCheckedBlockOpen = nodesUncheckedContext;
+ checkedBlockStart = statement;
+ }
+ // Now handle the statement
+ Result stmtResult = GetResult(statement);
+
+ costCheckedContext += stmtResult.CostInCheckedContext;
+ nodesCheckedContext += stmtResult.NodesToInsertInCheckedContext;
+ costCheckedContextUncheckedBlockOpen += stmtResult.CostInUncheckedContext;
+ nodesCheckedContextUncheckedBlockOpen += stmtResult.NodesToInsertInUncheckedContext;
+ costUncheckedContext += stmtResult.CostInUncheckedContext;
+ nodesUncheckedContext += stmtResult.NodesToInsertInUncheckedContext;
+ costUncheckedContextCheckedBlockOpen += stmtResult.CostInCheckedContext;
+ nodesUncheckedContextCheckedBlockOpen += stmtResult.NodesToInsertInCheckedContext;
+
+ statement = statement.GetNextStatement();
+ }
+
+ return new Result {
+ CostInCheckedContext = costCheckedContext, NodesToInsertInCheckedContext = nodesCheckedContext,
+ CostInUncheckedContext = costUncheckedContext, NodesToInsertInUncheckedContext = nodesUncheckedContext
+ };
+ }
+
+ Result GetResult(AstNode node)
+ {
+ if (node is BlockStatement)
+ return GetResultFromBlock((BlockStatement)node);
+ Result result = new Result();
+ for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
+ Result childResult = GetResult(child);
+ result.CostInCheckedContext += childResult.CostInCheckedContext;
+ result.NodesToInsertInCheckedContext += childResult.NodesToInsertInCheckedContext;
+ result.CostInUncheckedContext += childResult.CostInUncheckedContext;
+ result.NodesToInsertInUncheckedContext += childResult.NodesToInsertInUncheckedContext;
+ }
+ Expression expr = node as Expression;
+ if (expr != null) {
+ CheckedUncheckedAnnotation annotation = expr.Annotation<CheckedUncheckedAnnotation>();
+ if (annotation != null) {
+ // If the annotation requires this node to be in a specific context, add a huge cost to the other context
+ // That huge cost gives us the option to ignore a required checked/unchecked expression when there wouldn't be any
+ // solution otherwise. (e.g. "for (checked(M().x += 1); true; unchecked(M().x += 2)) {}")
+ if (annotation.IsChecked)
+ result.CostInUncheckedContext += new Cost(10000, 0);
+ else
+ result.CostInCheckedContext += new Cost(10000, 0);
+ }
+ // Embed this node in an checked/unchecked expression:
+ if (expr.Parent is ExpressionStatement) {
+ // We cannot use checked/unchecked for top-level-expressions.
+ // However, we could try converting a compound assignment (checked(a+=b);) or unary operator (checked(a++);)
+ // back to its old form.
+ if (expr.Annotation<ReplaceMethodCallsWithOperators.RestoreOriginalAssignOperatorAnnotation>() != null) {
+ // We use '<' so that expressions are introduced on the deepest level possible (goal 3)
+ if (result.CostInCheckedContext + new Cost(1, 1) < result.CostInUncheckedContext) {
+ result.CostInUncheckedContext = result.CostInCheckedContext + new Cost(1, 1);
+ result.NodesToInsertInUncheckedContext = result.NodesToInsertInCheckedContext + new ConvertCompoundAssignment(expr, true);
+ } else if (result.CostInUncheckedContext + new Cost(1, 1) < result.CostInCheckedContext) {
+ result.CostInCheckedContext = result.CostInUncheckedContext + new Cost(1, 1);
+ result.NodesToInsertInCheckedContext = result.NodesToInsertInUncheckedContext + new ConvertCompoundAssignment(expr, false);
+ }
+ }
+ } else if (expr.Role.IsValid(Expression.Null)) {
+ // We use '<' so that expressions are introduced on the deepest level possible (goal 3)
+ if (result.CostInCheckedContext + new Cost(0, 1) < result.CostInUncheckedContext) {
+ result.CostInUncheckedContext = result.CostInCheckedContext + new Cost(0, 1);
+ result.NodesToInsertInUncheckedContext = result.NodesToInsertInCheckedContext + new InsertedExpression(expr, true);
+ } else if (result.CostInUncheckedContext + new Cost(0, 1) < result.CostInCheckedContext) {
+ result.CostInCheckedContext = result.CostInUncheckedContext + new Cost(0, 1);
+ result.NodesToInsertInCheckedContext = result.NodesToInsertInUncheckedContext + new InsertedExpression(expr, false);
+ }
+ }
+ }
+ return result;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/CombineQueryExpressions.cs b/ICSharpCode.Decompiler/Ast/Transforms/CombineQueryExpressions.cs
new file mode 100644
index 00000000..a0d1ca8c
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/CombineQueryExpressions.cs
@@ -0,0 +1,179 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Linq;
+using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.PatternMatching;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ /// <summary>
+ /// Combines query expressions and removes transparent identifiers.
+ /// </summary>
+ public class CombineQueryExpressions : IAstTransform
+ {
+ readonly DecompilerContext context;
+
+ public CombineQueryExpressions(DecompilerContext context)
+ {
+ this.context = context;
+ }
+
+ public void Run(AstNode compilationUnit)
+ {
+ if (!context.Settings.QueryExpressions)
+ return;
+ CombineQueries(compilationUnit);
+ }
+
+ static readonly InvocationExpression castPattern = new InvocationExpression {
+ Target = new MemberReferenceExpression {
+ Target = new AnyNode("inExpr"),
+ MemberName = "Cast",
+ TypeArguments = { new AnyNode("targetType") }
+ }};
+
+ void CombineQueries(AstNode node)
+ {
+ for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
+ CombineQueries(child);
+ }
+ QueryExpression query = node as QueryExpression;
+ if (query != null) {
+ QueryFromClause fromClause = (QueryFromClause)query.Clauses.First();
+ QueryExpression innerQuery = fromClause.Expression as QueryExpression;
+ if (innerQuery != null) {
+ if (TryRemoveTransparentIdentifier(query, fromClause, innerQuery)) {
+ RemoveTransparentIdentifierReferences(query);
+ } else {
+ QueryContinuationClause continuation = new QueryContinuationClause();
+ continuation.PrecedingQuery = innerQuery.Detach();
+ continuation.Identifier = fromClause.Identifier;
+ fromClause.ReplaceWith(continuation);
+ }
+ } else {
+ Match m = castPattern.Match(fromClause.Expression);
+ if (m.Success) {
+ fromClause.Type = m.Get<AstType>("targetType").Single().Detach();
+ fromClause.Expression = m.Get<Expression>("inExpr").Single().Detach();
+ }
+ }
+ }
+ }
+
+ static readonly QuerySelectClause selectTransparentIdentifierPattern = new QuerySelectClause {
+ Expression = new Choice {
+ new AnonymousTypeCreateExpression {
+ Initializers = {
+ new NamedExpression {
+ Name = Pattern.AnyString,
+ Expression = new IdentifierExpression(Pattern.AnyString)
+ }.WithName("nae1"),
+ new NamedExpression {
+ Name = Pattern.AnyString,
+ Expression = new AnyNode("nae2Expr")
+ }.WithName("nae2")
+ }
+ },
+ new AnonymousTypeCreateExpression {
+ Initializers = {
+ new NamedNode("identifier", new IdentifierExpression(Pattern.AnyString)),
+ new AnyNode("nae2Expr")
+ }
+ }
+ }};
+
+ bool IsTransparentIdentifier(string identifier)
+ {
+ return identifier.StartsWith("<>", StringComparison.Ordinal) && identifier.Contains("TransparentIdentifier");
+ }
+
+ bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery)
+ {
+ if (!IsTransparentIdentifier(fromClause.Identifier))
+ return false;
+ Match match = selectTransparentIdentifierPattern.Match(innerQuery.Clauses.Last());
+ if (!match.Success)
+ return false;
+ QuerySelectClause selectClause = (QuerySelectClause)innerQuery.Clauses.Last();
+ NamedExpression nae1 = match.Get<NamedExpression>("nae1").SingleOrDefault();
+ NamedExpression nae2 = match.Get<NamedExpression>("nae2").SingleOrDefault();
+ if (nae1 != null && nae1.Name != ((IdentifierExpression)nae1.Expression).Identifier)
+ return false;
+ Expression nae2Expr = match.Get<Expression>("nae2Expr").Single();
+ IdentifierExpression nae2IdentExpr = nae2Expr as IdentifierExpression;
+ if (nae2IdentExpr != null && (nae2 == null || nae2.Name == nae2IdentExpr.Identifier)) {
+ // from * in (from x in ... select new { x = x, y = y }) ...
+ // =>
+ // from x in ... ...
+ fromClause.Remove();
+ selectClause.Remove();
+ // Move clauses from innerQuery to query
+ QueryClause insertionPos = null;
+ foreach (var clause in innerQuery.Clauses) {
+ query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
+ }
+ } else {
+ // from * in (from x in ... select new { x = x, y = expr }) ...
+ // =>
+ // from x in ... let y = expr ...
+ fromClause.Remove();
+ selectClause.Remove();
+ // Move clauses from innerQuery to query
+ QueryClause insertionPos = null;
+ foreach (var clause in innerQuery.Clauses) {
+ query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
+ }
+ string ident;
+ if (nae2 != null)
+ ident = nae2.Name;
+ else if (nae2Expr is IdentifierExpression)
+ ident = ((IdentifierExpression)nae2Expr).Identifier;
+ else if (nae2Expr is MemberReferenceExpression)
+ ident = ((MemberReferenceExpression)nae2Expr).MemberName;
+ else
+ throw new InvalidOperationException("Could not infer name from initializer in AnonymousTypeCreateExpression");
+ query.Clauses.InsertAfter(insertionPos, new QueryLetClause { Identifier = ident, Expression = nae2Expr.Detach() });
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Removes all occurrences of transparent identifiers
+ /// </summary>
+ void RemoveTransparentIdentifierReferences(AstNode node)
+ {
+ foreach (AstNode child in node.Children) {
+ RemoveTransparentIdentifierReferences(child);
+ }
+ MemberReferenceExpression mre = node as MemberReferenceExpression;
+ if (mre != null) {
+ IdentifierExpression ident = mre.Target as IdentifierExpression;
+ if (ident != null && IsTransparentIdentifier(ident.Identifier)) {
+ IdentifierExpression newIdent = new IdentifierExpression(mre.MemberName);
+ mre.TypeArguments.MoveTo(newIdent.TypeArguments);
+ newIdent.CopyAnnotationsFrom(mre);
+ newIdent.RemoveAnnotations<PropertyDeclaration>(); // remove the reference to the property of the anonymous type
+ mre.ReplaceWith(newIdent);
+ return;
+ }
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs b/ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs
new file mode 100644
index 00000000..1d1f3d08
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs
@@ -0,0 +1,111 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Diagnostics;
+using ICSharpCode.NRefactory.CSharp;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ /// <summary>
+ /// Base class for AST visitors that need the current type/method context info.
+ /// </summary>
+ public abstract class ContextTrackingVisitor<TResult> : DepthFirstAstVisitor<object, TResult>, IAstTransform
+ {
+ protected readonly DecompilerContext context;
+
+ protected ContextTrackingVisitor(DecompilerContext context)
+ {
+ if (context == null)
+ throw new ArgumentNullException("context");
+ this.context = context;
+ }
+
+ public override TResult VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
+ {
+ TypeDefinition oldType = context.CurrentType;
+ try {
+ context.CurrentType = typeDeclaration.Annotation<TypeDefinition>();
+ return base.VisitTypeDeclaration(typeDeclaration, data);
+ } finally {
+ context.CurrentType = oldType;
+ }
+ }
+
+ public override TResult VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
+ {
+ Debug.Assert(context.CurrentMethod == null);
+ try {
+ context.CurrentMethod = methodDeclaration.Annotation<MethodDefinition>();
+ return base.VisitMethodDeclaration(methodDeclaration, data);
+ } finally {
+ context.CurrentMethod = null;
+ }
+ }
+
+ public override TResult VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data)
+ {
+ Debug.Assert(context.CurrentMethod == null);
+ try {
+ context.CurrentMethod = constructorDeclaration.Annotation<MethodDefinition>();
+ return base.VisitConstructorDeclaration(constructorDeclaration, data);
+ } finally {
+ context.CurrentMethod = null;
+ }
+ }
+
+ public override TResult VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration, object data)
+ {
+ Debug.Assert(context.CurrentMethod == null);
+ try {
+ context.CurrentMethod = destructorDeclaration.Annotation<MethodDefinition>();
+ return base.VisitDestructorDeclaration(destructorDeclaration, data);
+ } finally {
+ context.CurrentMethod = null;
+ }
+ }
+
+ public override TResult VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data)
+ {
+ Debug.Assert(context.CurrentMethod == null);
+ try {
+ context.CurrentMethod = operatorDeclaration.Annotation<MethodDefinition>();
+ return base.VisitOperatorDeclaration(operatorDeclaration, data);
+ } finally {
+ context.CurrentMethod = null;
+ }
+ }
+
+ public override TResult VisitAccessor(Accessor accessor, object data)
+ {
+ Debug.Assert(context.CurrentMethod == null);
+ try {
+ context.CurrentMethod = accessor.Annotation<MethodDefinition>();
+ return base.VisitAccessor(accessor, data);
+ } finally {
+ context.CurrentMethod = null;
+ }
+ }
+
+ void IAstTransform.Run(AstNode node)
+ {
+ node.AcceptVisitor(this, null);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs b/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs
new file mode 100644
index 00000000..36811c18
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs
@@ -0,0 +1,183 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.PatternMatching;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ /// <summary>
+ /// If the first element of a constructor is a chained constructor call, convert it into a constructor initializer.
+ /// </summary>
+ public class ConvertConstructorCallIntoInitializer : DepthFirstAstVisitor<object, object>, IAstTransform
+ {
+ public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data)
+ {
+ ExpressionStatement stmt = constructorDeclaration.Body.Statements.FirstOrDefault() as ExpressionStatement;
+ if (stmt == null)
+ return null;
+ InvocationExpression invocation = stmt.Expression as InvocationExpression;
+ if (invocation == null)
+ return null;
+ MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression;
+ if (mre != null && mre.MemberName == ".ctor") {
+ ConstructorInitializer ci = new ConstructorInitializer();
+ if (mre.Target is ThisReferenceExpression)
+ ci.ConstructorInitializerType = ConstructorInitializerType.This;
+ else if (mre.Target is BaseReferenceExpression)
+ ci.ConstructorInitializerType = ConstructorInitializerType.Base;
+ else
+ return null;
+ // Move arguments from invocation to initializer:
+ invocation.Arguments.MoveTo(ci.Arguments);
+ // Add the initializer: (unless it is the default 'base()')
+ if (!(ci.ConstructorInitializerType == ConstructorInitializerType.Base && ci.Arguments.Count == 0))
+ constructorDeclaration.Initializer = ci.WithAnnotation(invocation.Annotation<MethodReference>());
+ // Remove the statement:
+ stmt.Remove();
+ }
+ return null;
+ }
+
+ static readonly ExpressionStatement fieldInitializerPattern = new ExpressionStatement {
+ Expression = new AssignmentExpression {
+ Left = new NamedNode("fieldAccess", new MemberReferenceExpression {
+ Target = new ThisReferenceExpression(),
+ MemberName = Pattern.AnyString
+ }),
+ Operator = AssignmentOperatorType.Assign,
+ Right = new AnyNode("initializer")
+ }
+ };
+
+ static readonly AstNode thisCallPattern = new ExpressionStatement(new ThisReferenceExpression().Invoke(".ctor", new Repeat(new AnyNode())));
+
+ public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
+ {
+ // Handle initializers on instance fields
+ HandleInstanceFieldInitializers(typeDeclaration.Members);
+
+ // Now convert base constructor calls to initializers:
+ base.VisitTypeDeclaration(typeDeclaration, data);
+
+ // Remove single empty constructor:
+ RemoveSingleEmptyConstructor(typeDeclaration);
+
+ // Handle initializers on static fields:
+ HandleStaticFieldInitializers(typeDeclaration.Members);
+ return null;
+ }
+
+ void HandleInstanceFieldInitializers(IEnumerable<AstNode> members)
+ {
+ var instanceCtors = members.OfType<ConstructorDeclaration>().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray();
+ var instanceCtorsNotChainingWithThis = instanceCtors.Where(ctor => !thisCallPattern.IsMatch(ctor.Body.Statements.FirstOrDefault())).ToArray();
+ if (instanceCtorsNotChainingWithThis.Length > 0) {
+ MethodDefinition ctorMethodDef = instanceCtorsNotChainingWithThis[0].Annotation<MethodDefinition>();
+ if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsValueType)
+ return;
+
+ // Recognize field initializers:
+ // Convert first statement in all ctors (if all ctors have the same statement) into a field initializer.
+ bool allSame;
+ do {
+ Match m = fieldInitializerPattern.Match(instanceCtorsNotChainingWithThis[0].Body.FirstOrDefault());
+ if (!m.Success)
+ break;
+
+ FieldDefinition fieldDef = m.Get<AstNode>("fieldAccess").Single().Annotation<FieldReference>().ResolveWithinSameModule();
+ if (fieldDef == null)
+ break;
+ AstNode fieldOrEventDecl = members.FirstOrDefault(f => f.Annotation<FieldDefinition>() == fieldDef);
+ if (fieldOrEventDecl == null)
+ break;
+ Expression initializer = m.Get<Expression>("initializer").Single();
+ // 'this'/'base' cannot be used in field initializers
+ if (initializer.DescendantsAndSelf.Any(n => n is ThisReferenceExpression || n is BaseReferenceExpression))
+ break;
+
+ allSame = true;
+ for (int i = 1; i < instanceCtorsNotChainingWithThis.Length; i++) {
+ if (!instanceCtors[0].Body.First().IsMatch(instanceCtorsNotChainingWithThis[i].Body.FirstOrDefault()))
+ allSame = false;
+ }
+ if (allSame) {
+ foreach (var ctor in instanceCtorsNotChainingWithThis)
+ ctor.Body.First().Remove();
+ fieldOrEventDecl.GetChildrenByRole(Roles.Variable).Single().Initializer = initializer.Detach();
+ }
+ } while (allSame);
+ }
+ }
+
+ void RemoveSingleEmptyConstructor(TypeDeclaration typeDeclaration)
+ {
+ var instanceCtors = typeDeclaration.Members.OfType<ConstructorDeclaration>().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray();
+ if (instanceCtors.Length == 1) {
+ ConstructorDeclaration emptyCtor = new ConstructorDeclaration();
+ emptyCtor.Modifiers = ((typeDeclaration.Modifiers & Modifiers.Abstract) == Modifiers.Abstract ? Modifiers.Protected : Modifiers.Public);
+ emptyCtor.Body = new BlockStatement();
+ if (emptyCtor.IsMatch(instanceCtors[0]))
+ instanceCtors[0].Remove();
+ }
+ }
+
+ void HandleStaticFieldInitializers(IEnumerable<AstNode> members)
+ {
+ // Convert static constructor into field initializers if the class is BeforeFieldInit
+ var staticCtor = members.OfType<ConstructorDeclaration>().FirstOrDefault(c => (c.Modifiers & Modifiers.Static) == Modifiers.Static);
+ if (staticCtor != null) {
+ MethodDefinition ctorMethodDef = staticCtor.Annotation<MethodDefinition>();
+ if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsBeforeFieldInit) {
+ while (true) {
+ ExpressionStatement es = staticCtor.Body.Statements.FirstOrDefault() as ExpressionStatement;
+ if (es == null)
+ break;
+ AssignmentExpression assignment = es.Expression as AssignmentExpression;
+ if (assignment == null || assignment.Operator != AssignmentOperatorType.Assign)
+ break;
+ FieldDefinition fieldDef = assignment.Left.Annotation<FieldReference>().ResolveWithinSameModule();
+ if (fieldDef == null || !fieldDef.IsStatic)
+ break;
+ FieldDeclaration fieldDecl = members.OfType<FieldDeclaration>().FirstOrDefault(f => f.Annotation<FieldDefinition>() == fieldDef);
+ if (fieldDecl == null)
+ break;
+ fieldDecl.Variables.Single().Initializer = assignment.Right.Detach();
+ es.Remove();
+ }
+ if (staticCtor.Body.Statements.Count == 0)
+ staticCtor.Remove();
+ }
+ }
+ }
+
+ void IAstTransform.Run(AstNode node)
+ {
+ // If we're viewing some set of members (fields are direct children of CompilationUnit),
+ // we also need to handle those:
+ HandleInstanceFieldInitializers(node.Children);
+ HandleStaticFieldInitializers(node.Children);
+
+ node.AcceptVisitor(this, null);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/CustomPatterns.cs b/ICSharpCode.Decompiler/Ast/Transforms/CustomPatterns.cs
new file mode 100644
index 00000000..b80c56af
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/CustomPatterns.cs
@@ -0,0 +1,109 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Linq;
+using System.Reflection;
+using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.PatternMatching;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ internal sealed class TypePattern : Pattern
+ {
+ readonly string ns;
+ readonly string name;
+
+ public TypePattern(Type type)
+ {
+ ns = type.Namespace;
+ name = type.Name;
+ }
+
+ public override bool DoMatch(INode other, Match match)
+ {
+ ComposedType ct = other as ComposedType;
+ AstType o;
+ if (ct != null && !ct.HasNullableSpecifier && ct.PointerRank == 0 && !ct.ArraySpecifiers.Any()) {
+ // Special case: ILSpy sometimes produces a ComposedType but then removed all array specifiers
+ // from it. In that case, we need to look at the base type for the annotations.
+ o = ct.BaseType;
+ } else {
+ o = other as AstType;
+ if (o == null)
+ return false;
+ }
+ TypeReference tr = o.Annotation<TypeReference>();
+ return tr != null && tr.Namespace == ns && tr.Name == name;
+ }
+
+ public override string ToString()
+ {
+ return name;
+ }
+ }
+
+ internal sealed class LdTokenPattern : Pattern
+ {
+ AnyNode childNode;
+
+ public LdTokenPattern(string groupName)
+ {
+ childNode = new AnyNode(groupName);
+ }
+
+ public override bool DoMatch(INode other, Match match)
+ {
+ InvocationExpression ie = other as InvocationExpression;
+ if (ie != null && ie.Annotation<LdTokenAnnotation>() != null && ie.Arguments.Count == 1) {
+ return childNode.DoMatch(ie.Arguments.Single(), match);
+ }
+ return false;
+ }
+
+ public override string ToString()
+ {
+ return "ldtoken(...)";
+ }
+ }
+
+ /// <summary>
+ /// typeof-Pattern that applies on the expanded form of typeof (prior to ReplaceMethodCallsWithOperators)
+ /// </summary>
+ internal sealed class TypeOfPattern : Pattern
+ {
+ INode childNode;
+
+ public TypeOfPattern(string groupName)
+ {
+ childNode = new TypePattern(typeof(Type)).ToType().Invoke(
+ "GetTypeFromHandle", new TypeOfExpression(new AnyNode(groupName)).Member("TypeHandle"));
+ }
+
+ public override bool DoMatch(INode other, Match match)
+ {
+ return childNode.DoMatch(other, match);
+ }
+
+ public override string ToString()
+ {
+ return "typeof(...)";
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs b/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs
new file mode 100644
index 00000000..298682af
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs
@@ -0,0 +1,58 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.PatternMatching;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ /// <summary>
+ /// Transforms decimal constant fields.
+ /// </summary>
+ public class DecimalConstantTransform : DepthFirstAstVisitor<object, object>, IAstTransform
+ {
+ static readonly PrimitiveType decimalType = new PrimitiveType("decimal");
+
+ public override object VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data)
+ {
+ const Modifiers staticReadOnly = Modifiers.Static | Modifiers.Readonly;
+ if ((fieldDeclaration.Modifiers & staticReadOnly) == staticReadOnly && decimalType.IsMatch(fieldDeclaration.ReturnType)) {
+ foreach (var attributeSection in fieldDeclaration.Attributes) {
+ foreach (var attribute in attributeSection.Attributes) {
+ TypeReference tr = attribute.Type.Annotation<TypeReference>();
+ if (tr != null && tr.Name == "DecimalConstantAttribute" && tr.Namespace == "System.Runtime.CompilerServices") {
+ attribute.Remove();
+ if (attributeSection.Attributes.Count == 0)
+ attributeSection.Remove();
+ fieldDeclaration.Modifiers = (fieldDeclaration.Modifiers & ~staticReadOnly) | Modifiers.Const;
+ return null;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public void Run(AstNode compilationUnit)
+ {
+ compilationUnit.AcceptVisitor(this, null);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs b/ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs
new file mode 100644
index 00000000..a27f30b4
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs
@@ -0,0 +1,368 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+using ICSharpCode.Decompiler.ILAst;
+using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.CSharp.Analysis;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ /// <summary>
+ /// Moves variable declarations to improved positions.
+ /// </summary>
+ public class DeclareVariables : IAstTransform
+ {
+ sealed class VariableToDeclare
+ {
+ public AstType Type;
+ public string Name;
+ public ILVariable ILVariable;
+
+ public AssignmentExpression ReplacedAssignment;
+ public Statement InsertionPoint;
+ }
+
+ readonly CancellationToken cancellationToken;
+ List<VariableToDeclare> variablesToDeclare = new List<VariableToDeclare>();
+
+ public DeclareVariables(DecompilerContext context)
+ {
+ cancellationToken = context.CancellationToken;
+ }
+
+ public void Run(AstNode node)
+ {
+ Run(node, null);
+ // Declare all the variables at the end, after all the logic has run.
+ // This is done so that definite assignment analysis can work on a single representation and doesn't have to be updated
+ // when we change the AST.
+ foreach (var v in variablesToDeclare) {
+ if (v.ReplacedAssignment == null) {
+ BlockStatement block = (BlockStatement)v.InsertionPoint.Parent;
+ var decl = new VariableDeclarationStatement((AstType)v.Type.Clone(), v.Name);
+ if (v.ILVariable != null)
+ decl.Variables.Single().AddAnnotation(v.ILVariable);
+ block.Statements.InsertBefore(
+ v.InsertionPoint,
+ decl);
+ }
+ }
+ // First do all the insertions, then do all the replacements. This is necessary because a replacement might remove our reference point from the AST.
+ foreach (var v in variablesToDeclare) {
+ if (v.ReplacedAssignment != null) {
+ // We clone the right expression so that it doesn't get removed from the old ExpressionStatement,
+ // which might be still in use by the definite assignment graph.
+ VariableInitializer initializer = new VariableInitializer(v.Name, v.ReplacedAssignment.Right.Detach()).CopyAnnotationsFrom(v.ReplacedAssignment).WithAnnotation(v.ILVariable);
+ VariableDeclarationStatement varDecl = new VariableDeclarationStatement {
+ Type = (AstType)v.Type.Clone(),
+ Variables = { initializer }
+ };
+ ExpressionStatement es = v.ReplacedAssignment.Parent as ExpressionStatement;
+ if (es != null) {
+ // Note: if this crashes with 'Cannot replace the root node', check whether two variables were assigned the same name
+ es.ReplaceWith(varDecl.CopyAnnotationsFrom(es));
+ } else {
+ v.ReplacedAssignment.ReplaceWith(varDecl);
+ }
+ }
+ }
+ variablesToDeclare = null;
+ }
+
+ void Run(AstNode node, DefiniteAssignmentAnalysis daa)
+ {
+ BlockStatement block = node as BlockStatement;
+ if (block != null) {
+ var variables = block.Statements.TakeWhile(stmt => stmt is VariableDeclarationStatement)
+ .Cast<VariableDeclarationStatement>().ToList();
+ if (variables.Count > 0) {
+ // remove old variable declarations:
+ foreach (VariableDeclarationStatement varDecl in variables) {
+ Debug.Assert(varDecl.Variables.Single().Initializer.IsNull);
+ varDecl.Remove();
+ }
+ if (daa == null) {
+ // If possible, reuse the DefiniteAssignmentAnalysis that was created for the parent block
+ daa = new DefiniteAssignmentAnalysis(block, cancellationToken);
+ }
+ foreach (VariableDeclarationStatement varDecl in variables) {
+ VariableInitializer initializer = varDecl.Variables.Single();
+ string variableName = initializer.Name;
+ ILVariable v = initializer.Annotation<ILVariable>();
+ bool allowPassIntoLoops = initializer.Annotation<DelegateConstruction.CapturedVariableAnnotation>() == null;
+ DeclareVariableInBlock(daa, block, varDecl.Type, variableName, v, allowPassIntoLoops);
+ }
+ }
+ }
+ for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
+ Run(child, daa);
+ }
+ }
+
+ void DeclareVariableInBlock(DefiniteAssignmentAnalysis daa, BlockStatement block, AstType type, string variableName, ILVariable v, bool allowPassIntoLoops)
+ {
+ // declarationPoint: The point where the variable would be declared, if we decide to declare it in this block
+ Statement declarationPoint = null;
+ // Check whether we can move down the variable into the sub-blocks
+ bool canMoveVariableIntoSubBlocks = FindDeclarationPoint(daa, variableName, allowPassIntoLoops, block, out declarationPoint);
+ if (declarationPoint == null) {
+ // The variable isn't used at all
+ return;
+ }
+ if (canMoveVariableIntoSubBlocks) {
+ // Declare the variable within the sub-blocks
+ foreach (Statement stmt in block.Statements) {
+ ForStatement forStmt = stmt as ForStatement;
+ if (forStmt != null && forStmt.Initializers.Count == 1) {
+ // handle the special case of moving a variable into the for initializer
+ if (TryConvertAssignmentExpressionIntoVariableDeclaration(forStmt.Initializers.Single(), type, variableName))
+ continue;
+ }
+ UsingStatement usingStmt = stmt as UsingStatement;
+ if (usingStmt != null && usingStmt.ResourceAcquisition is AssignmentExpression) {
+ // handle the special case of moving a variable into a using statement
+ if (TryConvertAssignmentExpressionIntoVariableDeclaration((Expression)usingStmt.ResourceAcquisition, type, variableName))
+ continue;
+ }
+ IfElseStatement ies = stmt as IfElseStatement;
+ if (ies != null) {
+ foreach (var child in IfElseChainChildren(ies)) {
+ BlockStatement subBlock = child as BlockStatement;
+ if (subBlock != null)
+ DeclareVariableInBlock(daa, subBlock, type, variableName, v, allowPassIntoLoops);
+ }
+ continue;
+ }
+ foreach (AstNode child in stmt.Children) {
+ BlockStatement subBlock = child as BlockStatement;
+ if (subBlock != null) {
+ DeclareVariableInBlock(daa, subBlock, type, variableName, v, allowPassIntoLoops);
+ } else if (HasNestedBlocks(child)) {
+ foreach (BlockStatement nestedSubBlock in child.Children.OfType<BlockStatement>()) {
+ DeclareVariableInBlock(daa, nestedSubBlock, type, variableName, v, allowPassIntoLoops);
+ }
+ }
+ }
+ }
+ } else {
+ // Try converting an assignment expression into a VariableDeclarationStatement
+ if (!TryConvertAssignmentExpressionIntoVariableDeclaration(declarationPoint, type, variableName)) {
+ // Declare the variable in front of declarationPoint
+ variablesToDeclare.Add(new VariableToDeclare { Type = type, Name = variableName, ILVariable = v, InsertionPoint = declarationPoint });
+ }
+ }
+ }
+
+ bool TryConvertAssignmentExpressionIntoVariableDeclaration(Statement declarationPoint, AstType type, string variableName)
+ {
+ // convert the declarationPoint into a VariableDeclarationStatement
+ ExpressionStatement es = declarationPoint as ExpressionStatement;
+ if (es != null) {
+ return TryConvertAssignmentExpressionIntoVariableDeclaration(es.Expression, type, variableName);
+ }
+ return false;
+ }
+
+ bool TryConvertAssignmentExpressionIntoVariableDeclaration(Expression expression, AstType type, string variableName)
+ {
+ AssignmentExpression ae = expression as AssignmentExpression;
+ if (ae != null && ae.Operator == AssignmentOperatorType.Assign) {
+ IdentifierExpression ident = ae.Left as IdentifierExpression;
+ if (ident != null && ident.Identifier == variableName) {
+ variablesToDeclare.Add(new VariableToDeclare { Type = type, Name = variableName, ILVariable = ident.Annotation<ILVariable>(), ReplacedAssignment = ae });
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Finds the declaration point for the variable within the specified block.
+ /// </summary>
+ /// <param name="daa">
+ /// Definite assignment analysis, must be prepared for 'block' or one of its parents.
+ /// </param>
+ /// <param name="varDecl">The variable to declare</param>
+ /// <param name="block">The block in which the variable should be declared</param>
+ /// <param name="declarationPoint">
+ /// Output parameter: the first statement within 'block' where the variable needs to be declared.
+ /// </param>
+ /// <returns>
+ /// Returns whether it is possible to move the variable declaration into sub-blocks.
+ /// </returns>
+ public static bool FindDeclarationPoint(DefiniteAssignmentAnalysis daa, VariableDeclarationStatement varDecl, BlockStatement block, out Statement declarationPoint)
+ {
+ string variableName = varDecl.Variables.Single().Name;
+ bool allowPassIntoLoops = varDecl.Variables.Single().Annotation<DelegateConstruction.CapturedVariableAnnotation>() == null;
+ return FindDeclarationPoint(daa, variableName, allowPassIntoLoops, block, out declarationPoint);
+ }
+
+ static bool FindDeclarationPoint(DefiniteAssignmentAnalysis daa, string variableName, bool allowPassIntoLoops, BlockStatement block, out Statement declarationPoint)
+ {
+ // declarationPoint: The point where the variable would be declared, if we decide to declare it in this block
+ declarationPoint = null;
+ foreach (Statement stmt in block.Statements) {
+ if (UsesVariable(stmt, variableName)) {
+ if (declarationPoint == null)
+ declarationPoint = stmt;
+ if (!CanMoveVariableUseIntoSubBlock(stmt, variableName, allowPassIntoLoops)) {
+ // If it's not possible to move the variable use into a nested block,
+ // we need to declare the variable in this block
+ return false;
+ }
+ // If we can move the variable into the sub-block, we need to ensure that the remaining code
+ // does not use the value that was assigned by the first sub-block
+ Statement nextStatement = stmt.GetNextStatement();
+ if (nextStatement != null) {
+ // Analyze the range from the next statement to the end of the block
+ daa.SetAnalyzedRange(nextStatement, block);
+ daa.Analyze(variableName);
+ if (daa.UnassignedVariableUses.Count > 0) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ static bool CanMoveVariableUseIntoSubBlock(Statement stmt, string variableName, bool allowPassIntoLoops)
+ {
+ if (!allowPassIntoLoops && (stmt is ForStatement || stmt is ForeachStatement || stmt is DoWhileStatement || stmt is WhileStatement))
+ return false;
+
+ ForStatement forStatement = stmt as ForStatement;
+ if (forStatement != null && forStatement.Initializers.Count == 1) {
+ // for-statement is special case: we can move variable declarations into the initializer
+ ExpressionStatement es = forStatement.Initializers.Single() as ExpressionStatement;
+ if (es != null) {
+ AssignmentExpression ae = es.Expression as AssignmentExpression;
+ if (ae != null && ae.Operator == AssignmentOperatorType.Assign) {
+ IdentifierExpression ident = ae.Left as IdentifierExpression;
+ if (ident != null && ident.Identifier == variableName) {
+ return !UsesVariable(ae.Right, variableName);
+ }
+ }
+ }
+ }
+
+ UsingStatement usingStatement = stmt as UsingStatement;
+ if (usingStatement != null) {
+ // using-statement is special case: we can move variable declarations into the initializer
+ AssignmentExpression ae = usingStatement.ResourceAcquisition as AssignmentExpression;
+ if (ae != null && ae.Operator == AssignmentOperatorType.Assign) {
+ IdentifierExpression ident = ae.Left as IdentifierExpression;
+ if (ident != null && ident.Identifier == variableName) {
+ return !UsesVariable(ae.Right, variableName);
+ }
+ }
+ }
+
+ IfElseStatement ies = stmt as IfElseStatement;
+ if (ies != null) {
+ foreach (var child in IfElseChainChildren(ies)) {
+ if (!(child is BlockStatement) && UsesVariable(child, variableName))
+ return false;
+ }
+ return true;
+ }
+
+ // We can move the variable into a sub-block only if the variable is used in only that sub-block (and not in expressions such as the loop condition)
+ for (AstNode child = stmt.FirstChild; child != null; child = child.NextSibling) {
+ if (!(child is BlockStatement) && UsesVariable(child, variableName)) {
+ if (HasNestedBlocks(child)) {
+ // catch clauses/switch sections can contain nested blocks
+ for (AstNode grandchild = child.FirstChild; grandchild != null; grandchild = grandchild.NextSibling) {
+ if (!(grandchild is BlockStatement) && UsesVariable(grandchild, variableName))
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ static IEnumerable<AstNode> IfElseChainChildren(IfElseStatement ies)
+ {
+ IfElseStatement prev;
+ do {
+ yield return ies.Condition;
+ yield return ies.TrueStatement;
+ prev = ies;
+ ies = ies.FalseStatement as IfElseStatement;
+ } while (ies != null);
+ if (!prev.FalseStatement.IsNull)
+ yield return prev.FalseStatement;
+ }
+
+ static bool HasNestedBlocks(AstNode node)
+ {
+ return node is CatchClause || node is SwitchSection;
+ }
+
+ static bool UsesVariable(AstNode node, string variableName)
+ {
+ IdentifierExpression ie = node as IdentifierExpression;
+ if (ie != null && ie.Identifier == variableName)
+ return true;
+
+ FixedStatement fixedStatement = node as FixedStatement;
+ if (fixedStatement != null) {
+ foreach (VariableInitializer v in fixedStatement.Variables) {
+ if (v.Name == variableName)
+ return false; // no need to introduce the variable here
+ }
+ }
+
+ ForeachStatement foreachStatement = node as ForeachStatement;
+ if (foreachStatement != null) {
+ if (foreachStatement.VariableName == variableName)
+ return false; // no need to introduce the variable here
+ }
+
+ UsingStatement usingStatement = node as UsingStatement;
+ if (usingStatement != null) {
+ VariableDeclarationStatement varDecl = usingStatement.ResourceAcquisition as VariableDeclarationStatement;
+ if (varDecl != null) {
+ foreach (VariableInitializer v in varDecl.Variables) {
+ if (v.Name == variableName)
+ return false; // no need to introduce the variable here
+ }
+ }
+ }
+
+ CatchClause catchClause = node as CatchClause;
+ if (catchClause != null && catchClause.VariableName == variableName) {
+ return false; // no need to introduce the variable here
+ }
+
+ for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
+ if (UsesVariable(child, variableName))
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
new file mode 100644
index 00000000..04b2293d
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
@@ -0,0 +1,502 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.ILAst;
+using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.PatternMatching;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ /// <summary>
+ /// Converts "new Action(obj, ldftn(func))" into "new Action(obj.func)".
+ /// For anonymous methods, creates an AnonymousMethodExpression.
+ /// Also gets rid of any "Display Classes" left over after inlining an anonymous method.
+ /// </summary>
+ public class DelegateConstruction : ContextTrackingVisitor<object>
+ {
+ internal sealed class Annotation
+ {
+ /// <summary>
+ /// ldftn or ldvirtftn?
+ /// </summary>
+ public readonly bool IsVirtual;
+
+ public Annotation(bool isVirtual)
+ {
+ IsVirtual = isVirtual;
+ }
+ }
+
+ internal sealed class CapturedVariableAnnotation
+ {
+ }
+
+ List<string> currentlyUsedVariableNames = new List<string>();
+
+ public DelegateConstruction(DecompilerContext context) : base(context)
+ {
+ }
+
+ public override object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data)
+ {
+ if (objectCreateExpression.Arguments.Count == 2) {
+ Expression obj = objectCreateExpression.Arguments.First();
+ Expression func = objectCreateExpression.Arguments.Last();
+ Annotation annotation = func.Annotation<Annotation>();
+ if (annotation != null) {
+ IdentifierExpression methodIdent = (IdentifierExpression)((InvocationExpression)func).Arguments.Single();
+ MethodReference method = methodIdent.Annotation<MethodReference>();
+ if (method != null) {
+ if (HandleAnonymousMethod(objectCreateExpression, obj, method))
+ return null;
+ // Perform the transformation to "new Action(obj.func)".
+ obj.Remove();
+ methodIdent.Remove();
+ if (!annotation.IsVirtual && obj is ThisReferenceExpression) {
+ // maybe it's getting the pointer of a base method?
+ if (method.DeclaringType.GetElementType() != context.CurrentType) {
+ obj = new BaseReferenceExpression();
+ }
+ }
+ if (!annotation.IsVirtual && obj is NullReferenceExpression && !method.HasThis) {
+ // We're loading a static method.
+ // However it is possible to load extension methods with an instance, so we compare the number of arguments:
+ bool isExtensionMethod = false;
+ TypeReference delegateType = objectCreateExpression.Type.Annotation<TypeReference>();
+ if (delegateType != null) {
+ TypeDefinition delegateTypeDef = delegateType.Resolve();
+ if (delegateTypeDef != null) {
+ MethodDefinition invokeMethod = delegateTypeDef.Methods.FirstOrDefault(m => m.Name == "Invoke");
+ if (invokeMethod != null) {
+ isExtensionMethod = (invokeMethod.Parameters.Count + 1 == method.Parameters.Count);
+ }
+ }
+ }
+ if (!isExtensionMethod) {
+ obj = new TypeReferenceExpression { Type = AstBuilder.ConvertType(method.DeclaringType) };
+ }
+ }
+ // now transform the identifier into a member reference
+ MemberReferenceExpression mre = new MemberReferenceExpression();
+ mre.Target = obj;
+ mre.MemberName = methodIdent.Identifier;
+ methodIdent.TypeArguments.MoveTo(mre.TypeArguments);
+ mre.AddAnnotation(method);
+ objectCreateExpression.Arguments.Clear();
+ objectCreateExpression.Arguments.Add(mre);
+ return null;
+ }
+ }
+ }
+ return base.VisitObjectCreateExpression(objectCreateExpression, data);
+ }
+
+ internal static bool IsAnonymousMethod(DecompilerContext context, MethodDefinition method)
+ {
+ if (method == null || !(method.HasGeneratedName() || method.Name.Contains("$")))
+ return false;
+ if (!(method.IsCompilerGenerated() || IsPotentialClosure(context, method.DeclaringType)))
+ return false;
+ return true;
+ }
+
+ bool HandleAnonymousMethod(ObjectCreateExpression objectCreateExpression, Expression target, MethodReference methodRef)
+ {
+ if (!context.Settings.AnonymousMethods)
+ return false; // anonymous method decompilation is disabled
+ if (target != null && !(target is IdentifierExpression || target is ThisReferenceExpression || target is NullReferenceExpression))
+ return false; // don't copy arbitrary expressions, deal with identifiers only
+
+ // Anonymous methods are defined in the same assembly
+ MethodDefinition method = methodRef.ResolveWithinSameModule();
+ if (!IsAnonymousMethod(context, method))
+ return false;
+
+ // Create AnonymousMethodExpression and prepare parameters
+ AnonymousMethodExpression ame = new AnonymousMethodExpression();
+ ame.CopyAnnotationsFrom(objectCreateExpression); // copy ILRanges etc.
+ ame.RemoveAnnotations<MethodReference>(); // remove reference to delegate ctor
+ ame.AddAnnotation(method); // add reference to anonymous method
+ ame.Parameters.AddRange(AstBuilder.MakeParameters(method, isLambda: true));
+ ame.HasParameterList = true;
+
+ // rename variables so that they don't conflict with the parameters:
+ foreach (ParameterDeclaration pd in ame.Parameters) {
+ EnsureVariableNameIsAvailable(objectCreateExpression, pd.Name);
+ }
+
+ // Decompile the anonymous method:
+
+ DecompilerContext subContext = context.Clone();
+ subContext.CurrentMethod = method;
+ subContext.CurrentMethodIsAsync = false;
+ subContext.ReservedVariableNames.AddRange(currentlyUsedVariableNames);
+ BlockStatement body = AstMethodBodyBuilder.CreateMethodBody(method, subContext, ame.Parameters);
+ TransformationPipeline.RunTransformationsUntil(body, v => v is DelegateConstruction, subContext);
+ body.AcceptVisitor(this, null);
+
+
+ bool isLambda = false;
+ if (ame.Parameters.All(p => p.ParameterModifier == ParameterModifier.None)) {
+ isLambda = (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement);
+ }
+ // Remove the parameter list from an AnonymousMethodExpression if the original method had no names,
+ // and the parameters are not used in the method body
+ if (!isLambda && method.Parameters.All(p => string.IsNullOrEmpty(p.Name))) {
+ var parameterReferencingIdentifiers =
+ from ident in body.Descendants.OfType<IdentifierExpression>()
+ let v = ident.Annotation<ILVariable>()
+ where v != null && v.IsParameter && method.Parameters.Contains(v.OriginalParameter)
+ select ident;
+ if (!parameterReferencingIdentifiers.Any()) {
+ ame.Parameters.Clear();
+ ame.HasParameterList = false;
+ }
+ }
+
+ // Replace all occurrences of 'this' in the method body with the delegate's target:
+ foreach (AstNode node in body.Descendants) {
+ if (node is ThisReferenceExpression)
+ node.ReplaceWith(target.Clone());
+ }
+ Expression replacement;
+ if (isLambda) {
+ LambdaExpression lambda = new LambdaExpression();
+ lambda.CopyAnnotationsFrom(ame);
+ ame.Parameters.MoveTo(lambda.Parameters);
+ Expression returnExpr = ((ReturnStatement)body.Statements.Single()).Expression;
+ returnExpr.Remove();
+ lambda.Body = returnExpr;
+ replacement = lambda;
+ } else {
+ ame.Body = body;
+ replacement = ame;
+ }
+ var expectedType = objectCreateExpression.Annotation<TypeInformation>().ExpectedType.Resolve();
+ if (expectedType != null && !expectedType.IsDelegate()) {
+ var simplifiedDelegateCreation = (ObjectCreateExpression)objectCreateExpression.Clone();
+ simplifiedDelegateCreation.Arguments.Clear();
+ simplifiedDelegateCreation.Arguments.Add(replacement);
+ replacement = simplifiedDelegateCreation;
+ }
+ objectCreateExpression.ReplaceWith(replacement);
+ return true;
+ }
+
+ internal static bool IsPotentialClosure(DecompilerContext context, TypeDefinition potentialDisplayClass)
+ {
+ if (potentialDisplayClass == null || !potentialDisplayClass.IsCompilerGeneratedOrIsInCompilerGeneratedClass())
+ return false;
+ // check that methodContainingType is within containingType
+ while (potentialDisplayClass != context.CurrentType) {
+ potentialDisplayClass = potentialDisplayClass.DeclaringType;
+ if (potentialDisplayClass == null)
+ return false;
+ }
+ return true;
+ }
+
+ public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
+ {
+ if (context.Settings.ExpressionTrees && ExpressionTreeConverter.CouldBeExpressionTree(invocationExpression)) {
+ Expression converted = ExpressionTreeConverter.TryConvert(context, invocationExpression);
+ if (converted != null) {
+ invocationExpression.ReplaceWith(converted);
+ return converted.AcceptVisitor(this, data);
+ }
+ }
+ return base.VisitInvocationExpression(invocationExpression, data);
+ }
+
+ #region Track current variables
+ public override object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
+ {
+ Debug.Assert(currentlyUsedVariableNames.Count == 0);
+ try {
+ currentlyUsedVariableNames.AddRange(methodDeclaration.Parameters.Select(p => p.Name));
+ return base.VisitMethodDeclaration(methodDeclaration, data);
+ } finally {
+ currentlyUsedVariableNames.Clear();
+ }
+ }
+
+ public override object VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data)
+ {
+ Debug.Assert(currentlyUsedVariableNames.Count == 0);
+ try {
+ currentlyUsedVariableNames.AddRange(operatorDeclaration.Parameters.Select(p => p.Name));
+ return base.VisitOperatorDeclaration(operatorDeclaration, data);
+ } finally {
+ currentlyUsedVariableNames.Clear();
+ }
+ }
+
+ public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data)
+ {
+ Debug.Assert(currentlyUsedVariableNames.Count == 0);
+ try {
+ currentlyUsedVariableNames.AddRange(constructorDeclaration.Parameters.Select(p => p.Name));
+ return base.VisitConstructorDeclaration(constructorDeclaration, data);
+ } finally {
+ currentlyUsedVariableNames.Clear();
+ }
+ }
+
+ public override object VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration, object data)
+ {
+ Debug.Assert(currentlyUsedVariableNames.Count == 0);
+ try {
+ currentlyUsedVariableNames.AddRange(indexerDeclaration.Parameters.Select(p => p.Name));
+ return base.VisitIndexerDeclaration(indexerDeclaration, data);
+ } finally {
+ currentlyUsedVariableNames.Clear();
+ }
+ }
+
+ public override object VisitAccessor(Accessor accessor, object data)
+ {
+ try {
+ currentlyUsedVariableNames.Add("value");
+ return base.VisitAccessor(accessor, data);
+ } finally {
+ currentlyUsedVariableNames.RemoveAt(currentlyUsedVariableNames.Count - 1);
+ }
+ }
+
+ public override object VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, object data)
+ {
+ foreach (VariableInitializer v in variableDeclarationStatement.Variables)
+ currentlyUsedVariableNames.Add(v.Name);
+ return base.VisitVariableDeclarationStatement(variableDeclarationStatement, data);
+ }
+
+ public override object VisitFixedStatement(FixedStatement fixedStatement, object data)
+ {
+ foreach (VariableInitializer v in fixedStatement.Variables)
+ currentlyUsedVariableNames.Add(v.Name);
+ return base.VisitFixedStatement(fixedStatement, data);
+ }
+ #endregion
+
+ static readonly ExpressionStatement displayClassAssignmentPattern =
+ new ExpressionStatement(new AssignmentExpression(
+ new NamedNode("variable", new IdentifierExpression(Pattern.AnyString)),
+ new ObjectCreateExpression { Type = new AnyNode("type") }
+ ));
+
+ public override object VisitBlockStatement(BlockStatement blockStatement, object data)
+ {
+ int numberOfVariablesOutsideBlock = currentlyUsedVariableNames.Count;
+ base.VisitBlockStatement(blockStatement, data);
+ foreach (ExpressionStatement stmt in blockStatement.Statements.OfType<ExpressionStatement>().ToArray()) {
+ Match displayClassAssignmentMatch = displayClassAssignmentPattern.Match(stmt);
+ if (!displayClassAssignmentMatch.Success)
+ continue;
+
+ ILVariable variable = displayClassAssignmentMatch.Get<AstNode>("variable").Single().Annotation<ILVariable>();
+ if (variable == null)
+ continue;
+ TypeDefinition type = variable.Type.ResolveWithinSameModule();
+ if (!IsPotentialClosure(context, type))
+ continue;
+ if (displayClassAssignmentMatch.Get<AstType>("type").Single().Annotation<TypeReference>().ResolveWithinSameModule() != type)
+ continue;
+
+ // Looks like we found a display class creation. Now let's verify that the variable is used only for field accesses:
+ bool ok = true;
+ foreach (var identExpr in blockStatement.Descendants.OfType<IdentifierExpression>()) {
+ if (identExpr.Identifier == variable.Name && identExpr != displayClassAssignmentMatch.Get("variable").Single()) {
+ if (!(identExpr.Parent is MemberReferenceExpression && identExpr.Parent.Annotation<FieldReference>() != null))
+ ok = false;
+ }
+ }
+ if (!ok)
+ continue;
+ Dictionary<FieldReference, AstNode> dict = new Dictionary<FieldReference, AstNode>();
+
+ // Delete the variable declaration statement:
+ VariableDeclarationStatement displayClassVarDecl = PatternStatementTransform.FindVariableDeclaration(stmt, variable.Name);
+ if (displayClassVarDecl != null)
+ displayClassVarDecl.Remove();
+
+ // Delete the assignment statement:
+ AstNode cur = stmt.NextSibling;
+ stmt.Remove();
+
+ // Delete any following statements as long as they assign parameters to the display class
+ BlockStatement rootBlock = blockStatement.Ancestors.OfType<BlockStatement>().LastOrDefault() ?? blockStatement;
+ List<ILVariable> parameterOccurrances = rootBlock.Descendants.OfType<IdentifierExpression>()
+ .Select(n => n.Annotation<ILVariable>()).Where(p => p != null && p.IsParameter).ToList();
+ AstNode next;
+ for (; cur != null; cur = next) {
+ next = cur.NextSibling;
+
+ // Test for the pattern:
+ // "variableName.MemberName = right;"
+ ExpressionStatement closureFieldAssignmentPattern = new ExpressionStatement(
+ new AssignmentExpression(
+ new NamedNode("left", new MemberReferenceExpression {
+ Target = new IdentifierExpression(variable.Name),
+ MemberName = Pattern.AnyString
+ }),
+ new AnyNode("right")
+ )
+ );
+ Match m = closureFieldAssignmentPattern.Match(cur);
+ if (m.Success) {
+ FieldDefinition fieldDef = m.Get<MemberReferenceExpression>("left").Single().Annotation<FieldReference>().ResolveWithinSameModule();
+ AstNode right = m.Get<AstNode>("right").Single();
+ bool isParameter = false;
+ bool isDisplayClassParentPointerAssignment = false;
+ if (right is ThisReferenceExpression) {
+ isParameter = true;
+ } else if (right is IdentifierExpression) {
+ // handle parameters only if the whole method contains no other occurrence except for 'right'
+ ILVariable v = right.Annotation<ILVariable>();
+ isParameter = v.IsParameter && parameterOccurrances.Count(c => c == v) == 1;
+ if (!isParameter && IsPotentialClosure(context, v.Type.ResolveWithinSameModule())) {
+ // parent display class within the same method
+ // (closure2.localsX = closure1;)
+ isDisplayClassParentPointerAssignment = true;
+ }
+ } else if (right is MemberReferenceExpression) {
+ // copy of parent display class reference from an outer lambda
+ // closure2.localsX = this.localsY
+ MemberReferenceExpression mre = m.Get<MemberReferenceExpression>("right").Single();
+ do {
+ // descend into the targets of the mre as long as the field types are closures
+ FieldDefinition fieldDef2 = mre.Annotation<FieldReference>().ResolveWithinSameModule();
+ if (fieldDef2 == null || !IsPotentialClosure(context, fieldDef2.FieldType.ResolveWithinSameModule())) {
+ break;
+ }
+ // if we finally get to a this reference, it's copying a display class parent pointer
+ if (mre.Target is ThisReferenceExpression) {
+ isDisplayClassParentPointerAssignment = true;
+ }
+ mre = mre.Target as MemberReferenceExpression;
+ } while (mre != null);
+ }
+ if (isParameter || isDisplayClassParentPointerAssignment) {
+ dict[fieldDef] = right;
+ cur.Remove();
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ // Now create variables for all fields of the display class (except for those that we already handled as parameters)
+ List<Tuple<AstType, ILVariable>> variablesToDeclare = new List<Tuple<AstType, ILVariable>>();
+ foreach (FieldDefinition field in type.Fields) {
+ if (field.IsStatic)
+ continue; // skip static fields
+ if (dict.ContainsKey(field)) // skip field if it already was handled as parameter
+ continue;
+ string capturedVariableName = field.Name;
+ if (capturedVariableName.StartsWith("$VB$Local_", StringComparison.Ordinal) && capturedVariableName.Length > 10)
+ capturedVariableName = capturedVariableName.Substring(10);
+ EnsureVariableNameIsAvailable(blockStatement, capturedVariableName);
+ currentlyUsedVariableNames.Add(capturedVariableName);
+ ILVariable ilVar = new ILVariable
+ {
+ IsGenerated = true,
+ Name = capturedVariableName,
+ Type = field.FieldType,
+ };
+ variablesToDeclare.Add(Tuple.Create(AstBuilder.ConvertType(field.FieldType, field), ilVar));
+ dict[field] = new IdentifierExpression(capturedVariableName).WithAnnotation(ilVar);
+ }
+
+ // Now figure out where the closure was accessed and use the simpler replacement expression there:
+ foreach (var identExpr in blockStatement.Descendants.OfType<IdentifierExpression>()) {
+ if (identExpr.Identifier == variable.Name) {
+ MemberReferenceExpression mre = (MemberReferenceExpression)identExpr.Parent;
+ AstNode replacement;
+ if (dict.TryGetValue(mre.Annotation<FieldReference>().ResolveWithinSameModule(), out replacement)) {
+ mre.ReplaceWith(replacement.Clone());
+ }
+ }
+ }
+ // Now insert the variable declarations (we can do this after the replacements only so that the scope detection works):
+ Statement insertionPoint = blockStatement.Statements.FirstOrDefault();
+ foreach (var tuple in variablesToDeclare) {
+ var newVarDecl = new VariableDeclarationStatement(tuple.Item1, tuple.Item2.Name);
+ newVarDecl.Variables.Single().AddAnnotation(new CapturedVariableAnnotation());
+ newVarDecl.Variables.Single().AddAnnotation(tuple.Item2);
+ blockStatement.Statements.InsertBefore(insertionPoint, newVarDecl);
+ }
+ }
+ currentlyUsedVariableNames.RemoveRange(numberOfVariablesOutsideBlock, currentlyUsedVariableNames.Count - numberOfVariablesOutsideBlock);
+ return null;
+ }
+
+ void EnsureVariableNameIsAvailable(AstNode currentNode, string name)
+ {
+ int pos = currentlyUsedVariableNames.IndexOf(name);
+ if (pos < 0) {
+ // name is still available
+ return;
+ }
+ // Naming conflict. Let's rename the existing variable so that the field keeps the name from metadata.
+ NameVariables nv = new NameVariables();
+ // Add currently used variable and parameter names
+ foreach (string nameInUse in currentlyUsedVariableNames)
+ nv.AddExistingName(nameInUse);
+ // variables declared in child nodes of this block
+ foreach (VariableInitializer vi in currentNode.Descendants.OfType<VariableInitializer>())
+ nv.AddExistingName(vi.Name);
+ // parameters in child lambdas
+ foreach (ParameterDeclaration pd in currentNode.Descendants.OfType<ParameterDeclaration>())
+ nv.AddExistingName(pd.Name);
+
+ string newName = nv.GetAlternativeName(name);
+ currentlyUsedVariableNames[pos] = newName;
+
+ // find top-most block
+ AstNode topMostBlock = currentNode.Ancestors.OfType<BlockStatement>().LastOrDefault() ?? currentNode;
+
+ // rename identifiers
+ foreach (IdentifierExpression ident in topMostBlock.Descendants.OfType<IdentifierExpression>()) {
+ if (ident.Identifier == name) {
+ ident.Identifier = newName;
+ ILVariable v = ident.Annotation<ILVariable>();
+ if (v != null)
+ v.Name = newName;
+ }
+ }
+ // rename variable declarations
+ foreach (VariableInitializer vi in topMostBlock.Descendants.OfType<VariableInitializer>()) {
+ if (vi.Name == name) {
+ vi.Name = newName;
+ ILVariable v = vi.Annotation<ILVariable>();
+ if (v != null)
+ v.Name = newName;
+ }
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs b/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs
new file mode 100644
index 00000000..2327200d
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs
@@ -0,0 +1,875 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using ICSharpCode.Decompiler.ILAst;
+using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.PatternMatching;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ public class ExpressionTreeConverter
+ {
+ #region static TryConvert method
+ public static bool CouldBeExpressionTree(InvocationExpression expr)
+ {
+ if (expr != null && expr.Arguments.Count == 2) {
+ MethodReference mr = expr.Annotation<MethodReference>();
+ return mr != null && mr.Name == "Lambda" && mr.DeclaringType.FullName == "System.Linq.Expressions.Expression";
+ }
+ return false;
+ }
+
+ public static Expression TryConvert(DecompilerContext context, Expression expr)
+ {
+ Expression converted = new ExpressionTreeConverter(context).Convert(expr);
+ if (converted != null) {
+ converted.AddAnnotation(new ExpressionTreeLambdaAnnotation());
+ }
+ return converted;
+ }
+ #endregion
+
+ readonly DecompilerContext context;
+ Stack<LambdaExpression> activeLambdas = new Stack<LambdaExpression>();
+
+ ExpressionTreeConverter(DecompilerContext context)
+ {
+ this.context = context;
+ }
+
+ #region Main Convert method
+ Expression Convert(Expression expr)
+ {
+ InvocationExpression invocation = expr as InvocationExpression;
+ if (invocation != null) {
+ MethodReference mr = invocation.Annotation<MethodReference>();
+ if (mr != null && mr.DeclaringType.FullName == "System.Linq.Expressions.Expression") {
+ switch (mr.Name) {
+ case "Add":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.Add, false);
+ case "AddChecked":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.Add, true);
+ case "AddAssign":
+ return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Add, false);
+ case "AddAssignChecked":
+ return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Add, true);
+ case "And":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.BitwiseAnd);
+ case "AndAlso":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.ConditionalAnd);
+ case "AndAssign":
+ return ConvertAssignmentOperator(invocation, AssignmentOperatorType.BitwiseAnd);
+ case "ArrayAccess":
+ case "ArrayIndex":
+ return ConvertArrayIndex(invocation);
+ case "ArrayLength":
+ return ConvertArrayLength(invocation);
+ case "Assign":
+ return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Assign);
+ case "Call":
+ return ConvertCall(invocation);
+ case "Coalesce":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.NullCoalescing);
+ case "Condition":
+ return ConvertCondition(invocation);
+ case "Constant":
+ if (invocation.Arguments.Count >= 1)
+ return invocation.Arguments.First().Clone();
+ else
+ return NotSupported(expr);
+ case "Convert":
+ return ConvertCast(invocation, false);
+ case "ConvertChecked":
+ return ConvertCast(invocation, true);
+ case "Divide":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.Divide);
+ case "DivideAssign":
+ return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Divide);
+ case "Equal":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.Equality);
+ case "ExclusiveOr":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.ExclusiveOr);
+ case "ExclusiveOrAssign":
+ return ConvertAssignmentOperator(invocation, AssignmentOperatorType.ExclusiveOr);
+ case "Field":
+ return ConvertField(invocation);
+ case "GreaterThan":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.GreaterThan);
+ case "GreaterThanOrEqual":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.GreaterThanOrEqual);
+ case "Invoke":
+ return ConvertInvoke(invocation);
+ case "Lambda":
+ return ConvertLambda(invocation);
+ case "LeftShift":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.ShiftLeft);
+ case "LeftShiftAssign":
+ return ConvertAssignmentOperator(invocation, AssignmentOperatorType.ShiftLeft);
+ case "LessThan":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.LessThan);
+ case "LessThanOrEqual":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.LessThanOrEqual);
+ case "ListInit":
+ return ConvertListInit(invocation);
+ case "MemberInit":
+ return ConvertMemberInit(invocation);
+ case "Modulo":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.Modulus);
+ case "ModuloAssign":
+ return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Modulus);
+ case "Multiply":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.Multiply, false);
+ case "MultiplyChecked":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.Multiply, true);
+ case "MultiplyAssign":
+ return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Multiply, false);
+ case "MultiplyAssignChecked":
+ return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Multiply, true);
+ case "Negate":
+ return ConvertUnaryOperator(invocation, UnaryOperatorType.Minus, false);
+ case "NegateChecked":
+ return ConvertUnaryOperator(invocation, UnaryOperatorType.Minus, true);
+ case "New":
+ return ConvertNewObject(invocation);
+ case "NewArrayBounds":
+ return ConvertNewArrayBounds(invocation);
+ case "NewArrayInit":
+ return ConvertNewArrayInit(invocation);
+ case "Not":
+ return ConvertUnaryOperator(invocation, UnaryOperatorType.Not);
+ case "NotEqual":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.InEquality);
+ case "OnesComplement":
+ return ConvertUnaryOperator(invocation, UnaryOperatorType.BitNot);
+ case "Or":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.BitwiseOr);
+ case "OrAssign":
+ return ConvertAssignmentOperator(invocation, AssignmentOperatorType.BitwiseOr);
+ case "OrElse":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.ConditionalOr);
+ case "Property":
+ return ConvertProperty(invocation);
+ case "Quote":
+ if (invocation.Arguments.Count == 1)
+ return Convert(invocation.Arguments.Single());
+ else
+ return NotSupported(invocation);
+ case "RightShift":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.ShiftRight);
+ case "RightShiftAssign":
+ return ConvertAssignmentOperator(invocation, AssignmentOperatorType.ShiftRight);
+ case "Subtract":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.Subtract, false);
+ case "SubtractChecked":
+ return ConvertBinaryOperator(invocation, BinaryOperatorType.Subtract, true);
+ case "SubtractAssign":
+ return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Subtract, false);
+ case "SubtractAssignChecked":
+ return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Subtract, true);
+ case "TypeAs":
+ return ConvertTypeAs(invocation);
+ case "TypeIs":
+ return ConvertTypeIs(invocation);
+ }
+ }
+ }
+ IdentifierExpression ident = expr as IdentifierExpression;
+ if (ident != null) {
+ ILVariable v = ident.Annotation<ILVariable>();
+ if (v != null) {
+ foreach (LambdaExpression lambda in activeLambdas) {
+ foreach (ParameterDeclaration p in lambda.Parameters) {
+ if (p.Annotation<ILVariable>() == v)
+ return new IdentifierExpression(p.Name).WithAnnotation(v);
+ }
+ }
+ }
+ }
+ return NotSupported(expr);
+ }
+
+ Expression NotSupported(Expression expr)
+ {
+ Debug.WriteLine("Expression Tree Conversion Failed: '" + expr + "' is not supported");
+ return null;
+ }
+ #endregion
+
+ #region Convert Lambda
+ static readonly Expression emptyArrayPattern = new ArrayCreateExpression {
+ Type = new AnyNode(),
+ Arguments = { new PrimitiveExpression(0) }
+ };
+
+ Expression ConvertLambda(InvocationExpression invocation)
+ {
+ if (invocation.Arguments.Count != 2)
+ return NotSupported(invocation);
+ LambdaExpression lambda = new LambdaExpression();
+ Expression body = invocation.Arguments.First();
+ ArrayCreateExpression parameterArray = invocation.Arguments.Last() as ArrayCreateExpression;
+ if (parameterArray == null)
+ return NotSupported(invocation);
+
+ var annotation = body.Annotation<ParameterDeclarationAnnotation>();
+ if (annotation != null) {
+ lambda.Parameters.AddRange(annotation.Parameters);
+ } else {
+ // No parameter declaration annotation found.
+ if (!emptyArrayPattern.IsMatch(parameterArray))
+ return null;
+ }
+
+ activeLambdas.Push(lambda);
+ Expression convertedBody = Convert(body);
+ activeLambdas.Pop();
+ if (convertedBody == null)
+ return null;
+ lambda.Body = convertedBody;
+ return lambda;
+ }
+ #endregion
+
+ #region Convert Field
+ static readonly Expression getFieldFromHandlePattern =
+ new TypePattern(typeof(FieldInfo)).ToType().Invoke(
+ "GetFieldFromHandle",
+ new LdTokenPattern("field").ToExpression().Member("FieldHandle"),
+ new OptionalNode(new TypeOfExpression(new AnyNode("declaringType")).Member("TypeHandle"))
+ );
+
+ Expression ConvertField(InvocationExpression invocation)
+ {
+ if (invocation.Arguments.Count != 2)
+ return NotSupported(invocation);
+
+ Expression fieldInfoExpr = invocation.Arguments.ElementAt(1);
+ Match m = getFieldFromHandlePattern.Match(fieldInfoExpr);
+ if (!m.Success)
+ return NotSupported(invocation);
+
+ FieldReference fr = m.Get<AstNode>("field").Single().Annotation<FieldReference>();
+ if (fr == null)
+ return null;
+
+ Expression target = invocation.Arguments.ElementAt(0);
+ Expression convertedTarget;
+ if (target is NullReferenceExpression) {
+ if (m.Has("declaringType"))
+ convertedTarget = new TypeReferenceExpression(m.Get<AstType>("declaringType").Single().Clone());
+ else
+ convertedTarget = new TypeReferenceExpression(AstBuilder.ConvertType(fr.DeclaringType));
+ } else {
+ convertedTarget = Convert(target);
+ if (convertedTarget == null)
+ return null;
+ }
+
+ return convertedTarget.Member(fr.Name).WithAnnotation(fr);
+ }
+ #endregion
+
+ #region Convert Property
+ static readonly Expression getMethodFromHandlePattern =
+ new TypePattern(typeof(MethodBase)).ToType().Invoke(
+ "GetMethodFromHandle",
+ new LdTokenPattern("method").ToExpression().Member("MethodHandle"),
+ new OptionalNode(new TypeOfExpression(new AnyNode("declaringType")).Member("TypeHandle"))
+ ).CastTo(new TypePattern(typeof(MethodInfo)));
+
+ Expression ConvertProperty(InvocationExpression invocation)
+ {
+ if (invocation.Arguments.Count != 2)
+ return NotSupported(invocation);
+
+ Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(1));
+ if (!m.Success)
+ return NotSupported(invocation);
+
+ MethodReference mr = m.Get<AstNode>("method").Single().Annotation<MethodReference>();
+ if (mr == null)
+ return null;
+
+ Expression target = invocation.Arguments.ElementAt(0);
+ Expression convertedTarget;
+ if (target is NullReferenceExpression) {
+ if (m.Has("declaringType"))
+ convertedTarget = new TypeReferenceExpression(m.Get<AstType>("declaringType").Single().Clone());
+ else
+ convertedTarget = new TypeReferenceExpression(AstBuilder.ConvertType(mr.DeclaringType));
+ } else {
+ convertedTarget = Convert(target);
+ if (convertedTarget == null)
+ return null;
+ }
+
+ return convertedTarget.Member(GetPropertyName(mr)).WithAnnotation(mr);
+ }
+
+ string GetPropertyName(MethodReference accessor)
+ {
+ string name = accessor.Name;
+ if (name.StartsWith("get_", StringComparison.Ordinal) || name.StartsWith("set_", StringComparison.Ordinal))
+ name = name.Substring(4);
+ return name;
+ }
+ #endregion
+
+ #region Convert Call
+ Expression ConvertCall(InvocationExpression invocation)
+ {
+ if (invocation.Arguments.Count < 2)
+ return NotSupported(invocation);
+
+ Expression target;
+ int firstArgumentPosition;
+
+ Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(0));
+ if (m.Success) {
+ target = null;
+ firstArgumentPosition = 1;
+ } else {
+ m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(1));
+ if (!m.Success)
+ return NotSupported(invocation);
+ target = invocation.Arguments.ElementAt(0);
+ firstArgumentPosition = 2;
+ }
+
+ MethodReference mr = m.Get<AstNode>("method").Single().Annotation<MethodReference>();
+ if (mr == null)
+ return null;
+
+ Expression convertedTarget;
+ if (target == null || target is NullReferenceExpression) {
+ // static method
+ if (m.Has("declaringType"))
+ convertedTarget = new TypeReferenceExpression(m.Get<AstType>("declaringType").Single().Clone());
+ else
+ convertedTarget = new TypeReferenceExpression(AstBuilder.ConvertType(mr.DeclaringType));
+ } else {
+ convertedTarget = Convert(target);
+ if (convertedTarget == null)
+ return null;
+ }
+
+ MemberReferenceExpression mre = convertedTarget.Member(mr.Name);
+ GenericInstanceMethod gim = mr as GenericInstanceMethod;
+ if (gim != null) {
+ foreach (TypeReference tr in gim.GenericArguments) {
+ mre.TypeArguments.Add(AstBuilder.ConvertType(tr));
+ }
+ }
+ IList<Expression> arguments = null;
+ if (invocation.Arguments.Count == firstArgumentPosition + 1) {
+ Expression argumentArray = invocation.Arguments.ElementAt(firstArgumentPosition);
+ arguments = ConvertExpressionsArray(argumentArray);
+ }
+ if (arguments == null) {
+ arguments = new List<Expression>();
+ foreach (Expression argument in invocation.Arguments.Skip(firstArgumentPosition)) {
+ Expression convertedArgument = Convert(argument);
+ if (convertedArgument == null)
+ return null;
+ arguments.Add(convertedArgument);
+ }
+ }
+ MethodDefinition methodDef = mr.Resolve();
+ if (methodDef != null && methodDef.IsGetter) {
+ PropertyDefinition indexer = AstMethodBodyBuilder.GetIndexer(methodDef);
+ if (indexer != null)
+ return new IndexerExpression(mre.Target.Detach(), arguments).WithAnnotation(indexer);
+ }
+ return new InvocationExpression(mre, arguments).WithAnnotation(mr);
+ }
+
+ Expression ConvertInvoke(InvocationExpression invocation)
+ {
+ if (invocation.Arguments.Count != 2)
+ return NotSupported(invocation);
+
+ Expression convertedTarget = Convert(invocation.Arguments.ElementAt(0));
+ IList<Expression> convertedArguments = ConvertExpressionsArray(invocation.Arguments.ElementAt(1));
+ if (convertedTarget != null && convertedArguments != null)
+ return new InvocationExpression(convertedTarget, convertedArguments);
+ else
+ return null;
+ }
+ #endregion
+
+ #region Convert Binary Operator
+ static readonly Pattern trueOrFalse = new Choice {
+ new PrimitiveExpression(true),
+ new PrimitiveExpression(false)
+ };
+
+ Expression ConvertBinaryOperator(InvocationExpression invocation, BinaryOperatorType op, bool? isChecked = null)
+ {
+ if (invocation.Arguments.Count < 2)
+ return NotSupported(invocation);
+
+ Expression left = Convert(invocation.Arguments.ElementAt(0));
+ if (left == null)
+ return null;
+ Expression right = Convert(invocation.Arguments.ElementAt(1));
+ if (right == null)
+ return null;
+
+ BinaryOperatorExpression boe = new BinaryOperatorExpression(left, op, right);
+ if (isChecked != null)
+ boe.AddAnnotation(isChecked.Value ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation);
+
+ switch (invocation.Arguments.Count) {
+ case 2:
+ return boe;
+ case 3:
+ Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(2));
+ if (m.Success)
+ return boe.WithAnnotation(m.Get<AstNode>("method").Single().Annotation<MethodReference>());
+ else
+ return null;
+ case 4:
+ if (!trueOrFalse.IsMatch(invocation.Arguments.ElementAt(2)))
+ return null;
+ m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(3));
+ if (m.Success)
+ return boe.WithAnnotation(m.Get<AstNode>("method").Single().Annotation<MethodReference>());
+ else
+ return null;
+ default:
+ return NotSupported(invocation);
+ }
+ }
+ #endregion
+
+ #region Convert Assignment Operator
+ Expression ConvertAssignmentOperator(InvocationExpression invocation, AssignmentOperatorType op, bool? isChecked = null)
+ {
+ return NotSupported(invocation);
+ }
+ #endregion
+
+ #region Convert Unary Operator
+ Expression ConvertUnaryOperator(InvocationExpression invocation, UnaryOperatorType op, bool? isChecked = null)
+ {
+ if (invocation.Arguments.Count < 1)
+ return NotSupported(invocation);
+
+ Expression expr = Convert(invocation.Arguments.ElementAt(0));
+ if (expr == null)
+ return null;
+
+ UnaryOperatorExpression uoe = new UnaryOperatorExpression(op, expr);
+ if (isChecked != null)
+ uoe.AddAnnotation(isChecked.Value ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation);
+
+ switch (invocation.Arguments.Count) {
+ case 1:
+ return uoe;
+ case 2:
+ Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(1));
+ if (m.Success)
+ return uoe.WithAnnotation(m.Get<AstNode>("method").Single().Annotation<MethodReference>());
+ else
+ return null;
+ default:
+ return NotSupported(invocation);
+ }
+ }
+ #endregion
+
+ #region Convert Condition Operator
+ Expression ConvertCondition(InvocationExpression invocation)
+ {
+ if (invocation.Arguments.Count != 3)
+ return NotSupported(invocation);
+
+ Expression condition = Convert(invocation.Arguments.ElementAt(0));
+ Expression trueExpr = Convert(invocation.Arguments.ElementAt(1));
+ Expression falseExpr = Convert(invocation.Arguments.ElementAt(2));
+ if (condition != null && trueExpr != null && falseExpr != null)
+ return new ConditionalExpression(condition, trueExpr, falseExpr);
+ else
+ return null;
+ }
+ #endregion
+
+ #region Convert New Object
+ static readonly Expression newObjectCtorPattern = new TypePattern(typeof(MethodBase)).ToType().Invoke
+ (
+ "GetMethodFromHandle",
+ new LdTokenPattern("ctor").ToExpression().Member("MethodHandle"),
+ new OptionalNode(new TypeOfExpression(new AnyNode("declaringType")).Member("TypeHandle"))
+ ).CastTo(new TypePattern(typeof(ConstructorInfo)));
+
+ Expression ConvertNewObject(InvocationExpression invocation)
+ {
+ if (invocation.Arguments.Count < 1 || invocation.Arguments.Count > 3)
+ return NotSupported(invocation);
+
+ Match m = newObjectCtorPattern.Match(invocation.Arguments.First());
+ if (!m.Success)
+ return NotSupported(invocation);
+
+ MethodReference ctor = m.Get<AstNode>("ctor").Single().Annotation<MethodReference>();
+ if (ctor == null)
+ return null;
+
+ AstType declaringTypeNode;
+ TypeReference declaringType;
+ if (m.Has("declaringType")) {
+ declaringTypeNode = m.Get<AstType>("declaringType").Single().Clone();
+ declaringType = declaringTypeNode.Annotation<TypeReference>();
+ } else {
+ declaringTypeNode = AstBuilder.ConvertType(ctor.DeclaringType);
+ declaringType = ctor.DeclaringType;
+ }
+ if (declaringTypeNode == null)
+ return null;
+
+ ObjectCreateExpression oce = new ObjectCreateExpression(declaringTypeNode);
+ if (invocation.Arguments.Count >= 2) {
+ IList<Expression> arguments = ConvertExpressionsArray(invocation.Arguments.ElementAtOrDefault(1));
+ if (arguments == null)
+ return null;
+ oce.Arguments.AddRange(arguments);
+ }
+ if (invocation.Arguments.Count >= 3 && declaringType.IsAnonymousType()) {
+ MethodDefinition resolvedCtor = ctor.Resolve();
+ if (resolvedCtor == null || resolvedCtor.Parameters.Count != oce.Arguments.Count)
+ return null;
+ AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression();
+ var arguments = oce.Arguments.ToArray();
+ if (AstMethodBodyBuilder.CanInferAnonymousTypePropertyNamesFromArguments(arguments, resolvedCtor.Parameters)) {
+ oce.Arguments.MoveTo(atce.Initializers);
+ } else {
+ for (int i = 0; i < resolvedCtor.Parameters.Count; i++) {
+ atce.Initializers.Add(
+ new NamedExpression {
+ Name = resolvedCtor.Parameters[i].Name,
+ Expression = arguments[i].Detach()
+ });
+ }
+ }
+ return atce;
+ }
+
+ return oce;
+ }
+ #endregion
+
+ #region Convert ListInit
+ static readonly Pattern elementInitArrayPattern = ArrayInitializationPattern(
+ typeof(System.Linq.Expressions.ElementInit),
+ new TypePattern(typeof(System.Linq.Expressions.Expression)).ToType().Invoke("ElementInit", new AnyNode("methodInfos"), new AnyNode("addArgumentsArrays"))
+ );
+
+ Expression ConvertListInit(InvocationExpression invocation)
+ {
+ if (invocation.Arguments.Count != 2)
+ return NotSupported(invocation);
+ ObjectCreateExpression oce = Convert(invocation.Arguments.ElementAt(0)) as ObjectCreateExpression;
+ if (oce == null)
+ return null;
+ Expression elementsArray = invocation.Arguments.ElementAt(1);
+ ArrayInitializerExpression initializer = ConvertElementInit(elementsArray);
+ if (initializer != null) {
+ oce.Initializer = initializer;
+ return oce;
+ } else {
+ return null;
+ }
+ }
+
+ ArrayInitializerExpression ConvertElementInit(Expression elementsArray)
+ {
+ IList<Expression> elements = ConvertExpressionsArray(elementsArray);
+ if (elements != null) {
+ return new ArrayInitializerExpression(elements);
+ }
+ Match m = elementInitArrayPattern.Match(elementsArray);
+ if (!m.Success)
+ return null;
+ ArrayInitializerExpression result = new ArrayInitializerExpression();
+ foreach (var elementInit in m.Get<Expression>("addArgumentsArrays")) {
+ IList<Expression> arguments = ConvertExpressionsArray(elementInit);
+ if (arguments == null)
+ return null;
+ result.Elements.Add(new ArrayInitializerExpression(arguments));
+ }
+ return result;
+ }
+ #endregion
+
+ #region Convert MemberInit
+ Expression ConvertMemberInit(InvocationExpression invocation)
+ {
+ if (invocation.Arguments.Count != 2)
+ return NotSupported(invocation);
+ ObjectCreateExpression oce = Convert(invocation.Arguments.ElementAt(0)) as ObjectCreateExpression;
+ if (oce == null)
+ return null;
+ Expression elementsArray = invocation.Arguments.ElementAt(1);
+ ArrayInitializerExpression bindings = ConvertMemberBindings(elementsArray);
+ if (bindings == null)
+ return null;
+ oce.Initializer = bindings;
+ return oce;
+ }
+
+ static readonly Pattern memberBindingArrayPattern = ArrayInitializationPattern(typeof(System.Linq.Expressions.MemberBinding), new AnyNode("binding"));
+ static readonly INode expressionTypeReference = new TypeReferenceExpression(new TypePattern(typeof(System.Linq.Expressions.Expression)));
+
+ ArrayInitializerExpression ConvertMemberBindings(Expression elementsArray)
+ {
+ Match m = memberBindingArrayPattern.Match(elementsArray);
+ if (!m.Success)
+ return null;
+ ArrayInitializerExpression result = new ArrayInitializerExpression();
+ foreach (var binding in m.Get<Expression>("binding")) {
+ InvocationExpression bindingInvocation = binding as InvocationExpression;
+ if (bindingInvocation == null || bindingInvocation.Arguments.Count != 2)
+ return null;
+ MemberReferenceExpression bindingMRE = bindingInvocation.Target as MemberReferenceExpression;
+ if (bindingMRE == null || !expressionTypeReference.IsMatch(bindingMRE.Target))
+ return null;
+
+ Expression bindingTarget = bindingInvocation.Arguments.ElementAt(0);
+ Expression bindingValue = bindingInvocation.Arguments.ElementAt(1);
+
+ string memberName;
+ Match m2 = getMethodFromHandlePattern.Match(bindingTarget);
+ if (m2.Success) {
+ MethodReference setter = m2.Get<AstNode>("method").Single().Annotation<MethodReference>();
+ if (setter == null)
+ return null;
+ memberName = GetPropertyName(setter);
+ } else {
+ return null;
+ }
+
+ Expression convertedValue;
+ switch (bindingMRE.MemberName) {
+ case "Bind":
+ convertedValue = Convert(bindingValue);
+ break;
+ case "MemberBind":
+ convertedValue = ConvertMemberBindings(bindingValue);
+ break;
+ case "ListBind":
+ convertedValue = ConvertElementInit(bindingValue);
+ break;
+ default:
+ return null;
+ }
+ if (convertedValue == null)
+ return null;
+ result.Elements.Add(new NamedExpression(memberName, convertedValue));
+ }
+ return result;
+ }
+ #endregion
+
+ #region Convert Cast
+ Expression ConvertCast(InvocationExpression invocation, bool isChecked)
+ {
+ if (invocation.Arguments.Count < 2)
+ return null;
+ Expression converted = Convert(invocation.Arguments.ElementAt(0));
+ AstType type = ConvertTypeReference(invocation.Arguments.ElementAt(1));
+ if (converted != null && type != null) {
+ CastExpression cast = converted.CastTo(type);
+ cast.AddAnnotation(isChecked ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation);
+ switch (invocation.Arguments.Count) {
+ case 2:
+ return cast;
+ case 3:
+ Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(2));
+ if (m.Success)
+ return cast.WithAnnotation(m.Get<AstNode>("method").Single().Annotation<MethodReference>());
+ else
+ return null;
+ }
+ }
+ return null;
+ }
+ #endregion
+
+ #region ConvertExpressionsArray
+ static Pattern ArrayInitializationPattern(Type arrayElementType, INode elementPattern)
+ {
+ return new Choice {
+ new ArrayCreateExpression {
+ Type = new TypePattern(arrayElementType),
+ Arguments = { new PrimitiveExpression(0) }
+ },
+ new ArrayCreateExpression {
+ Type = new TypePattern(arrayElementType),
+ AdditionalArraySpecifiers = { new ArraySpecifier() },
+ Initializer = new ArrayInitializerExpression {
+ Elements = { new Repeat(elementPattern) }
+ }
+ }
+ };
+ }
+
+ static readonly Pattern expressionArrayPattern = ArrayInitializationPattern(typeof(System.Linq.Expressions.Expression), new AnyNode("elements"));
+
+ IList<Expression> ConvertExpressionsArray(Expression arrayExpression)
+ {
+ Match m = expressionArrayPattern.Match(arrayExpression);
+ if (m.Success) {
+ List<Expression> result = new List<Expression>();
+ foreach (Expression expr in m.Get<Expression>("elements")) {
+ Expression converted = Convert(expr);
+ if (converted == null)
+ return null;
+ result.Add(converted);
+ }
+ return result;
+ }
+ return null;
+ }
+ #endregion
+
+ #region Convert TypeAs/TypeIs
+ static readonly TypeOfPattern typeOfPattern = new TypeOfPattern("type");
+
+ AstType ConvertTypeReference(Expression typeOfExpression)
+ {
+ Match m = typeOfPattern.Match(typeOfExpression);
+ if (m.Success)
+ return m.Get<AstType>("type").Single().Clone();
+ else
+ return null;
+ }
+
+ Expression ConvertTypeAs(InvocationExpression invocation)
+ {
+ if (invocation.Arguments.Count != 2)
+ return null;
+ Expression converted = Convert(invocation.Arguments.ElementAt(0));
+ AstType type = ConvertTypeReference(invocation.Arguments.ElementAt(1));
+ if (converted != null && type != null)
+ return new AsExpression(converted, type);
+ return null;
+ }
+
+ Expression ConvertTypeIs(InvocationExpression invocation)
+ {
+ if (invocation.Arguments.Count != 2)
+ return null;
+ Expression converted = Convert(invocation.Arguments.ElementAt(0));
+ AstType type = ConvertTypeReference(invocation.Arguments.ElementAt(1));
+ if (converted != null && type != null)
+ return new IsExpression { Expression = converted, Type = type };
+ return null;
+ }
+ #endregion
+
+ #region Convert Array
+ Expression ConvertArrayIndex(InvocationExpression invocation)
+ {
+ if (invocation.Arguments.Count != 2)
+ return NotSupported(invocation);
+
+ Expression targetConverted = Convert(invocation.Arguments.First());
+ if (targetConverted == null)
+ return null;
+
+ Expression index = invocation.Arguments.ElementAt(1);
+ Expression indexConverted = Convert(index);
+ if (indexConverted != null) {
+ return new IndexerExpression(targetConverted, indexConverted);
+ }
+ IList<Expression> indexesConverted = ConvertExpressionsArray(index);
+ if (indexesConverted != null) {
+ return new IndexerExpression(targetConverted, indexesConverted);
+ }
+ return null;
+ }
+
+ Expression ConvertArrayLength(InvocationExpression invocation)
+ {
+ if (invocation.Arguments.Count != 1)
+ return NotSupported(invocation);
+
+ Expression targetConverted = Convert(invocation.Arguments.Single());
+ if (targetConverted != null)
+ return targetConverted.Member("Length");
+ else
+ return null;
+ }
+
+ Expression ConvertNewArrayInit(InvocationExpression invocation)
+ {
+ if (invocation.Arguments.Count != 2)
+ return NotSupported(invocation);
+
+ AstType elementType = ConvertTypeReference(invocation.Arguments.ElementAt(0));
+ IList<Expression> elements = ConvertExpressionsArray(invocation.Arguments.ElementAt(1));
+ if (elementType != null && elements != null) {
+ if (ContainsAnonymousType(elementType)) {
+ elementType = null;
+ }
+ return new ArrayCreateExpression {
+ Type = elementType,
+ AdditionalArraySpecifiers = { new ArraySpecifier() },
+ Initializer = new ArrayInitializerExpression(elements)
+ };
+ }
+ return null;
+ }
+
+ Expression ConvertNewArrayBounds(InvocationExpression invocation)
+ {
+ if (invocation.Arguments.Count != 2)
+ return NotSupported(invocation);
+
+ AstType elementType = ConvertTypeReference(invocation.Arguments.ElementAt(0));
+ IList<Expression> arguments = ConvertExpressionsArray(invocation.Arguments.ElementAt(1));
+ if (elementType != null && arguments != null) {
+ if (ContainsAnonymousType(elementType)) {
+ elementType = null;
+ }
+ ArrayCreateExpression ace = new ArrayCreateExpression();
+ ace.Type = elementType;
+ ace.Arguments.AddRange(arguments);
+ return ace;
+ }
+ return null;
+ }
+
+ bool ContainsAnonymousType(AstType type)
+ {
+ foreach (AstType t in type.DescendantsAndSelf.OfType<AstType>()) {
+ TypeReference tr = t.Annotation<TypeReference>();
+ if (tr != null && tr.IsAnonymousType())
+ return true;
+ }
+ return false;
+ }
+ #endregion
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/FlattenSwitchBlocks.cs b/ICSharpCode.Decompiler/Ast/Transforms/FlattenSwitchBlocks.cs
new file mode 100644
index 00000000..9595e81b
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/FlattenSwitchBlocks.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ICSharpCode.NRefactory.CSharp;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ internal class FlattenSwitchBlocks : IAstTransform
+ {
+ public void Run(AstNode compilationUnit)
+ {
+ foreach (var switchSection in compilationUnit.Descendants.OfType<SwitchSection>())
+ {
+ if (switchSection.Statements.Count != 1)
+ continue;
+
+ var blockStatement = switchSection.Statements.First() as BlockStatement;
+ if (blockStatement == null || blockStatement.Statements.Any(st => st is VariableDeclarationStatement))
+ continue;
+
+ blockStatement.Remove();
+ blockStatement.Statements.MoveTo(switchSection.Statements);
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/IntroduceExtensionMethods.cs b/ICSharpCode.Decompiler/Ast/Transforms/IntroduceExtensionMethods.cs
new file mode 100644
index 00000000..9f05285e
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/IntroduceExtensionMethods.cs
@@ -0,0 +1,66 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Linq;
+using ICSharpCode.NRefactory.CSharp;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ /// <summary>
+ /// Converts extension method calls into infix syntax.
+ /// </summary>
+ public class IntroduceExtensionMethods : IAstTransform
+ {
+ readonly DecompilerContext context;
+
+ public IntroduceExtensionMethods(DecompilerContext context)
+ {
+ this.context = context;
+ }
+
+ public void Run(AstNode compilationUnit)
+ {
+ foreach (InvocationExpression invocation in compilationUnit.Descendants.OfType<InvocationExpression>()) {
+ MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression;
+ MethodReference methodReference = invocation.Annotation<MethodReference>();
+ if (mre != null && mre.Target is TypeReferenceExpression && methodReference != null && invocation.Arguments.Any()) {
+ MethodDefinition d = methodReference.Resolve();
+ if (d != null) {
+ foreach (var ca in d.CustomAttributes) {
+ if (ca.AttributeType.Name == "ExtensionAttribute" && ca.AttributeType.Namespace == "System.Runtime.CompilerServices") {
+ var firstArgument = invocation.Arguments.First();
+ if (firstArgument is NullReferenceExpression)
+ firstArgument = firstArgument.ReplaceWith(expr => expr.CastTo(AstBuilder.ConvertType(d.Parameters.First().ParameterType)));
+ else
+ mre.Target = firstArgument.Detach();
+ if (invocation.Arguments.Any()) {
+ // HACK: removing type arguments should be done indepently from whether a method is an extension method,
+ // just by testing whether the arguments can be inferred
+ mre.TypeArguments.Clear();
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/IntroduceQueryExpressions.cs b/ICSharpCode.Decompiler/Ast/Transforms/IntroduceQueryExpressions.cs
new file mode 100644
index 00000000..0da56fe9
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/IntroduceQueryExpressions.cs
@@ -0,0 +1,295 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Diagnostics;
+using System.Linq;
+using ICSharpCode.NRefactory.CSharp;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ /// <summary>
+ /// Decompiles query expressions.
+ /// Based on C# 4.0 spec, §7.16.2 Query expression translation
+ /// </summary>
+ public class IntroduceQueryExpressions : IAstTransform
+ {
+ readonly DecompilerContext context;
+
+ public IntroduceQueryExpressions(DecompilerContext context)
+ {
+ this.context = context;
+ }
+
+ public void Run(AstNode compilationUnit)
+ {
+ if (!context.Settings.QueryExpressions)
+ return;
+ DecompileQueries(compilationUnit);
+ // After all queries were decompiled, detect degenerate queries (queries not property terminated with 'select' or 'group')
+ // and fix them, either by adding a degenerate select, or by combining them with another query.
+ foreach (QueryExpression query in compilationUnit.Descendants.OfType<QueryExpression>()) {
+ QueryFromClause fromClause = (QueryFromClause)query.Clauses.First();
+ if (IsDegenerateQuery(query)) {
+ // introduce select for degenerate query
+ query.Clauses.Add(new QuerySelectClause { Expression = new IdentifierExpression(fromClause.Identifier) });
+ }
+ // See if the data source of this query is a degenerate query,
+ // and combine the queries if possible.
+ QueryExpression innerQuery = fromClause.Expression as QueryExpression;
+ while (IsDegenerateQuery(innerQuery)) {
+ QueryFromClause innerFromClause = (QueryFromClause)innerQuery.Clauses.First();
+ if (fromClause.Identifier != innerFromClause.Identifier)
+ break;
+ // Replace the fromClause with all clauses from the inner query
+ fromClause.Remove();
+ QueryClause insertionPos = null;
+ foreach (var clause in innerQuery.Clauses) {
+ query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
+ }
+ fromClause = innerFromClause;
+ innerQuery = fromClause.Expression as QueryExpression;
+ }
+ }
+ }
+
+ bool IsDegenerateQuery(QueryExpression query)
+ {
+ if (query == null)
+ return false;
+ var lastClause = query.Clauses.LastOrDefault();
+ return !(lastClause is QuerySelectClause || lastClause is QueryGroupClause);
+ }
+
+ void DecompileQueries(AstNode node)
+ {
+ QueryExpression query = DecompileQuery(node as InvocationExpression);
+ if (query != null)
+ node.ReplaceWith(query);
+ for (AstNode child = (query ?? node).FirstChild; child != null; child = child.NextSibling) {
+ DecompileQueries(child);
+ }
+ }
+
+ QueryExpression DecompileQuery(InvocationExpression invocation)
+ {
+ if (invocation == null)
+ return null;
+ MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression;
+ if (mre == null)
+ return null;
+ switch (mre.MemberName) {
+ case "Select":
+ {
+ if (invocation.Arguments.Count != 1)
+ return null;
+ string parameterName;
+ Expression body;
+ if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out body)) {
+ QueryExpression query = new QueryExpression();
+ query.Clauses.Add(new QueryFromClause { Identifier = parameterName, Expression = mre.Target.Detach() });
+ query.Clauses.Add(new QuerySelectClause { Expression = body.Detach() });
+ return query;
+ }
+ return null;
+ }
+ case "GroupBy":
+ {
+ if (invocation.Arguments.Count == 2) {
+ string parameterName1, parameterName2;
+ Expression keySelector, elementSelector;
+ if (MatchSimpleLambda(invocation.Arguments.ElementAt(0), out parameterName1, out keySelector)
+ && MatchSimpleLambda(invocation.Arguments.ElementAt(1), out parameterName2, out elementSelector)
+ && parameterName1 == parameterName2)
+ {
+ QueryExpression query = new QueryExpression();
+ query.Clauses.Add(new QueryFromClause { Identifier = parameterName1, Expression = mre.Target.Detach() });
+ query.Clauses.Add(new QueryGroupClause { Projection = elementSelector.Detach(), Key = keySelector.Detach() });
+ return query;
+ }
+ } else if (invocation.Arguments.Count == 1) {
+ string parameterName;
+ Expression keySelector;
+ if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out keySelector)) {
+ QueryExpression query = new QueryExpression();
+ query.Clauses.Add(new QueryFromClause { Identifier = parameterName, Expression = mre.Target.Detach() });
+ query.Clauses.Add(new QueryGroupClause { Projection = new IdentifierExpression(parameterName), Key = keySelector.Detach() });
+ return query;
+ }
+ }
+ return null;
+ }
+ case "SelectMany":
+ {
+ if (invocation.Arguments.Count != 2)
+ return null;
+ string parameterName;
+ Expression collectionSelector;
+ if (!MatchSimpleLambda(invocation.Arguments.ElementAt(0), out parameterName, out collectionSelector))
+ return null;
+ LambdaExpression lambda = invocation.Arguments.ElementAt(1) as LambdaExpression;
+ if (lambda != null && lambda.Parameters.Count == 2 && lambda.Body is Expression) {
+ ParameterDeclaration p1 = lambda.Parameters.ElementAt(0);
+ ParameterDeclaration p2 = lambda.Parameters.ElementAt(1);
+ if (p1.Name == parameterName) {
+ QueryExpression query = new QueryExpression();
+ query.Clauses.Add(new QueryFromClause { Identifier = p1.Name, Expression = mre.Target.Detach() });
+ query.Clauses.Add(new QueryFromClause { Identifier = p2.Name, Expression = collectionSelector.Detach() });
+ query.Clauses.Add(new QuerySelectClause { Expression = ((Expression)lambda.Body).Detach() });
+ return query;
+ }
+ }
+ return null;
+ }
+ case "Where":
+ {
+ if (invocation.Arguments.Count != 1)
+ return null;
+ string parameterName;
+ Expression body;
+ if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out body)) {
+ QueryExpression query = new QueryExpression();
+ query.Clauses.Add(new QueryFromClause { Identifier = parameterName, Expression = mre.Target.Detach() });
+ query.Clauses.Add(new QueryWhereClause { Condition = body.Detach() });
+ return query;
+ }
+ return null;
+ }
+ case "OrderBy":
+ case "OrderByDescending":
+ case "ThenBy":
+ case "ThenByDescending":
+ {
+ if (invocation.Arguments.Count != 1)
+ return null;
+ string parameterName;
+ Expression orderExpression;
+ if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out orderExpression)) {
+ if (ValidateThenByChain(invocation, parameterName)) {
+ QueryOrderClause orderClause = new QueryOrderClause();
+ InvocationExpression tmp = invocation;
+ while (mre.MemberName == "ThenBy" || mre.MemberName == "ThenByDescending") {
+ // insert new ordering at beginning
+ orderClause.Orderings.InsertAfter(
+ null, new QueryOrdering {
+ Expression = orderExpression.Detach(),
+ Direction = (mre.MemberName == "ThenBy" ? QueryOrderingDirection.None : QueryOrderingDirection.Descending)
+ });
+
+ tmp = (InvocationExpression)mre.Target;
+ mre = (MemberReferenceExpression)tmp.Target;
+ MatchSimpleLambda(tmp.Arguments.Single(), out parameterName, out orderExpression);
+ }
+ // insert new ordering at beginning
+ orderClause.Orderings.InsertAfter(
+ null, new QueryOrdering {
+ Expression = orderExpression.Detach(),
+ Direction = (mre.MemberName == "OrderBy" ? QueryOrderingDirection.None : QueryOrderingDirection.Descending)
+ });
+
+ QueryExpression query = new QueryExpression();
+ query.Clauses.Add(new QueryFromClause { Identifier = parameterName, Expression = mre.Target.Detach() });
+ query.Clauses.Add(orderClause);
+ return query;
+ }
+ }
+ return null;
+ }
+ case "Join":
+ case "GroupJoin":
+ {
+ if (invocation.Arguments.Count != 4)
+ return null;
+ Expression source1 = mre.Target;
+ Expression source2 = invocation.Arguments.ElementAt(0);
+ string elementName1, elementName2;
+ Expression key1, key2;
+ if (!MatchSimpleLambda(invocation.Arguments.ElementAt(1), out elementName1, out key1))
+ return null;
+ if (!MatchSimpleLambda(invocation.Arguments.ElementAt(2), out elementName2, out key2))
+ return null;
+ LambdaExpression lambda = invocation.Arguments.ElementAt(3) as LambdaExpression;
+ if (lambda != null && lambda.Parameters.Count == 2 && lambda.Body is Expression) {
+ ParameterDeclaration p1 = lambda.Parameters.ElementAt(0);
+ ParameterDeclaration p2 = lambda.Parameters.ElementAt(1);
+ if (p1.Name == elementName1 && (p2.Name == elementName2 || mre.MemberName == "GroupJoin")) {
+ QueryExpression query = new QueryExpression();
+ query.Clauses.Add(new QueryFromClause { Identifier = elementName1, Expression = source1.Detach() });
+ QueryJoinClause joinClause = new QueryJoinClause();
+ joinClause.JoinIdentifier = elementName2; // join elementName2
+ joinClause.InExpression = source2.Detach(); // in source2
+ joinClause.OnExpression = key1.Detach(); // on key1
+ joinClause.EqualsExpression = key2.Detach(); // equals key2
+ if (mre.MemberName == "GroupJoin") {
+ joinClause.IntoIdentifier = p2.Name; // into p2.Name
+ }
+ query.Clauses.Add(joinClause);
+ query.Clauses.Add(new QuerySelectClause { Expression = ((Expression)lambda.Body).Detach() });
+ return query;
+ }
+ }
+ return null;
+ }
+ default:
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Ensure that all ThenBy's are correct, and that the list of ThenBy's is terminated by an 'OrderBy' invocation.
+ /// </summary>
+ bool ValidateThenByChain(InvocationExpression invocation, string expectedParameterName)
+ {
+ if (invocation == null || invocation.Arguments.Count != 1)
+ return false;
+ MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression;
+ if (mre == null)
+ return false;
+ string parameterName;
+ Expression body;
+ if (!MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out body))
+ return false;
+ if (parameterName != expectedParameterName)
+ return false;
+
+ if (mre.MemberName == "OrderBy" || mre.MemberName == "OrderByDescending")
+ return true;
+ else if (mre.MemberName == "ThenBy" || mre.MemberName == "ThenByDescending")
+ return ValidateThenByChain(mre.Target as InvocationExpression, expectedParameterName);
+ else
+ return false;
+ }
+
+ /// <summary>Matches simple lambdas of the form "a => b"</summary>
+ bool MatchSimpleLambda(Expression expr, out string parameterName, out Expression body)
+ {
+ LambdaExpression lambda = expr as LambdaExpression;
+ if (lambda != null && lambda.Parameters.Count == 1 && lambda.Body is Expression) {
+ ParameterDeclaration p = lambda.Parameters.Single();
+ if (p.ParameterModifier == ParameterModifier.None) {
+ parameterName = p.Name;
+ body = (Expression)lambda.Body;
+ return true;
+ }
+ }
+ parameterName = null;
+ body = null;
+ return false;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs b/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs
new file mode 100644
index 00000000..43548e38
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs
@@ -0,0 +1,106 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using ICSharpCode.NRefactory.CSharp;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ public class IntroduceUnsafeModifier : DepthFirstAstVisitor<object, bool>, IAstTransform
+ {
+ public static readonly object PointerArithmeticAnnotation = new PointerArithmetic();
+
+ sealed class PointerArithmetic {}
+
+ public void Run(AstNode compilationUnit)
+ {
+ compilationUnit.AcceptVisitor(this, null);
+ }
+
+ protected override bool VisitChildren(AstNode node, object data)
+ {
+ bool result = false;
+ for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
+ result |= child.AcceptVisitor(this, data);
+ }
+ if (result && node is EntityDeclaration && !(node is Accessor)) {
+ ((EntityDeclaration)node).Modifiers |= Modifiers.Unsafe;
+ return false;
+ }
+ return result;
+ }
+
+ public override bool VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, object data)
+ {
+ base.VisitPointerReferenceExpression(pointerReferenceExpression, data);
+ return true;
+ }
+
+ public override bool VisitComposedType(ComposedType composedType, object data)
+ {
+ if (composedType.PointerRank > 0)
+ return true;
+ else
+ return base.VisitComposedType(composedType, data);
+ }
+
+ public override bool VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)
+ {
+ bool result = base.VisitUnaryOperatorExpression(unaryOperatorExpression, data);
+ if (unaryOperatorExpression.Operator == UnaryOperatorType.Dereference) {
+ BinaryOperatorExpression bop = unaryOperatorExpression.Expression as BinaryOperatorExpression;
+ if (bop != null && bop.Operator == BinaryOperatorType.Add && bop.Annotation<PointerArithmetic>() != null) {
+ // transform "*(ptr + int)" to "ptr[int]"
+ IndexerExpression indexer = new IndexerExpression();
+ indexer.Target = bop.Left.Detach();
+ indexer.Arguments.Add(bop.Right.Detach());
+ indexer.CopyAnnotationsFrom(unaryOperatorExpression);
+ indexer.CopyAnnotationsFrom(bop);
+ unaryOperatorExpression.ReplaceWith(indexer);
+ }
+ return true;
+ } else if (unaryOperatorExpression.Operator == UnaryOperatorType.AddressOf) {
+ return true;
+ } else {
+ return result;
+ }
+ }
+
+ public override bool VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
+ {
+ bool result = base.VisitMemberReferenceExpression(memberReferenceExpression, data);
+ UnaryOperatorExpression uoe = memberReferenceExpression.Target as UnaryOperatorExpression;
+ if (uoe != null && uoe.Operator == UnaryOperatorType.Dereference) {
+ PointerReferenceExpression pre = new PointerReferenceExpression();
+ pre.Target = uoe.Expression.Detach();
+ pre.MemberName = memberReferenceExpression.MemberName;
+ memberReferenceExpression.TypeArguments.MoveTo(pre.TypeArguments);
+ pre.CopyAnnotationsFrom(uoe);
+ pre.CopyAnnotationsFrom(memberReferenceExpression);
+ memberReferenceExpression.ReplaceWith(pre);
+ }
+ return result;
+ }
+
+ public override bool VisitStackAllocExpression(StackAllocExpression stackAllocExpression, object data)
+ {
+ base.VisitStackAllocExpression(stackAllocExpression, data);
+ return true;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs b/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs
new file mode 100644
index 00000000..6e9cc4f5
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs
@@ -0,0 +1,359 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using ICSharpCode.NRefactory.CSharp;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ /// <summary>
+ /// Introduces using declarations.
+ /// </summary>
+ public class IntroduceUsingDeclarations : IAstTransform
+ {
+ DecompilerContext context;
+
+ public IntroduceUsingDeclarations(DecompilerContext context)
+ {
+ this.context = context;
+ }
+
+ public void Run(AstNode compilationUnit)
+ {
+ // First determine all the namespaces that need to be imported:
+ compilationUnit.AcceptVisitor(new FindRequiredImports(this), null);
+
+ importedNamespaces.Add("System"); // always import System, even when not necessary
+
+ if (context.Settings.UsingDeclarations) {
+ // Now add using declarations for those namespaces:
+ foreach (string ns in importedNamespaces.OrderByDescending(n => n)) {
+ // we go backwards (OrderByDescending) through the list of namespaces because we insert them backwards
+ // (always inserting at the start of the list)
+ string[] parts = ns.Split('.');
+ AstType nsType = new SimpleType(parts[0]);
+ for (int i = 1; i < parts.Length; i++) {
+ nsType = new MemberType { Target = nsType, MemberName = parts[i] };
+ }
+ compilationUnit.InsertChildAfter(null, new UsingDeclaration { Import = nsType }, SyntaxTree.MemberRole);
+ }
+ }
+
+ if (!context.Settings.FullyQualifyAmbiguousTypeNames)
+ return;
+
+ FindAmbiguousTypeNames(context.CurrentModule, internalsVisible: true);
+ foreach (AssemblyNameReference r in context.CurrentModule.AssemblyReferences) {
+ AssemblyDefinition d = context.CurrentModule.AssemblyResolver.Resolve(r);
+ if (d != null)
+ FindAmbiguousTypeNames(d.MainModule, internalsVisible: false);
+ }
+
+ // verify that the SimpleTypes refer to the correct type (no ambiguities)
+ compilationUnit.AcceptVisitor(new FullyQualifyAmbiguousTypeNamesVisitor(this), null);
+ }
+
+ readonly HashSet<string> declaredNamespaces = new HashSet<string>() { string.Empty };
+ readonly HashSet<string> importedNamespaces = new HashSet<string>();
+
+ // Note that we store type names with `n suffix, so we automatically disambiguate based on number of type parameters.
+ readonly HashSet<string> availableTypeNames = new HashSet<string>();
+ readonly HashSet<string> ambiguousTypeNames = new HashSet<string>();
+
+ sealed class FindRequiredImports : DepthFirstAstVisitor<object, object>
+ {
+ readonly IntroduceUsingDeclarations transform;
+ string currentNamespace;
+
+ public FindRequiredImports(IntroduceUsingDeclarations transform)
+ {
+ this.transform = transform;
+ currentNamespace = transform.context.CurrentType != null ? transform.context.CurrentType.Namespace : string.Empty;
+ }
+
+ bool IsParentOfCurrentNamespace(string ns)
+ {
+ if (ns.Length == 0)
+ return true;
+ if (currentNamespace.StartsWith(ns, StringComparison.Ordinal)) {
+ if (currentNamespace.Length == ns.Length)
+ return true;
+ if (currentNamespace[ns.Length] == '.')
+ return true;
+ }
+ return false;
+ }
+
+ public override object VisitSimpleType(SimpleType simpleType, object data)
+ {
+ TypeReference tr = simpleType.Annotation<TypeReference>();
+ if (tr != null && !IsParentOfCurrentNamespace(tr.Namespace)) {
+ transform.importedNamespaces.Add(tr.Namespace);
+ }
+ return base.VisitSimpleType(simpleType, data); // also visit type arguments
+ }
+
+ public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data)
+ {
+ string oldNamespace = currentNamespace;
+ foreach (string ident in namespaceDeclaration.Identifiers) {
+ currentNamespace = NamespaceDeclaration.BuildQualifiedName(currentNamespace, ident);
+ transform.declaredNamespaces.Add(currentNamespace);
+ }
+ base.VisitNamespaceDeclaration(namespaceDeclaration, data);
+ currentNamespace = oldNamespace;
+ return null;
+ }
+ }
+
+ void FindAmbiguousTypeNames(ModuleDefinition module, bool internalsVisible)
+ {
+ foreach (TypeDefinition type in module.Types) {
+ if (internalsVisible || type.IsPublic) {
+ if (importedNamespaces.Contains(type.Namespace) || declaredNamespaces.Contains(type.Namespace)) {
+ if (!availableTypeNames.Add(type.Name))
+ ambiguousTypeNames.Add(type.Name);
+ }
+ }
+ }
+ }
+
+ sealed class FullyQualifyAmbiguousTypeNamesVisitor : DepthFirstAstVisitor<object, object>
+ {
+ readonly IntroduceUsingDeclarations transform;
+ string currentNamespace;
+ HashSet<string> currentMemberTypes;
+ Dictionary<string, MemberReference> currentMembers;
+ bool isWithinTypeReferenceExpression;
+
+ public FullyQualifyAmbiguousTypeNamesVisitor(IntroduceUsingDeclarations transform)
+ {
+ this.transform = transform;
+ currentNamespace = transform.context.CurrentType != null ? transform.context.CurrentType.Namespace : string.Empty;
+ }
+
+ public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data)
+ {
+ string oldNamespace = currentNamespace;
+ foreach (string ident in namespaceDeclaration.Identifiers) {
+ currentNamespace = NamespaceDeclaration.BuildQualifiedName(currentNamespace, ident);
+ }
+ base.VisitNamespaceDeclaration(namespaceDeclaration, data);
+ currentNamespace = oldNamespace;
+ return null;
+ }
+
+ public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
+ {
+ HashSet<string> oldMemberTypes = currentMemberTypes;
+ currentMemberTypes = currentMemberTypes != null ? new HashSet<string>(currentMemberTypes) : new HashSet<string>();
+
+ Dictionary<string, MemberReference> oldMembers = currentMembers;
+ currentMembers = new Dictionary<string, MemberReference>();
+
+ TypeDefinition typeDef = typeDeclaration.Annotation<TypeDefinition>();
+ bool privateMembersVisible = true;
+ ModuleDefinition internalMembersVisibleInModule = typeDef.Module;
+ while (typeDef != null) {
+ foreach (GenericParameter gp in typeDef.GenericParameters) {
+ currentMemberTypes.Add(gp.Name);
+ }
+ foreach (TypeDefinition t in typeDef.NestedTypes) {
+ if (privateMembersVisible || IsVisible(t, internalMembersVisibleInModule))
+ currentMemberTypes.Add(t.Name.Substring(t.Name.LastIndexOf('+') + 1));
+ }
+
+ foreach (MethodDefinition method in typeDef.Methods) {
+ if (privateMembersVisible || IsVisible(method, internalMembersVisibleInModule))
+ AddCurrentMember(method);
+ }
+ foreach (PropertyDefinition property in typeDef.Properties) {
+ if (privateMembersVisible || IsVisible(property.GetMethod, internalMembersVisibleInModule) || IsVisible(property.SetMethod, internalMembersVisibleInModule))
+ AddCurrentMember(property);
+ }
+ foreach (EventDefinition ev in typeDef.Events) {
+ if (privateMembersVisible || IsVisible(ev.AddMethod, internalMembersVisibleInModule) || IsVisible(ev.RemoveMethod, internalMembersVisibleInModule))
+ AddCurrentMember(ev);
+ }
+ foreach (FieldDefinition f in typeDef.Fields) {
+ if (privateMembersVisible || IsVisible(f, internalMembersVisibleInModule))
+ AddCurrentMember(f);
+ }
+ // repeat with base class:
+ if (typeDef.BaseType != null)
+ typeDef = typeDef.BaseType.Resolve();
+ else
+ typeDef = null;
+ privateMembersVisible = false;
+ }
+
+ // Now add current members from outer classes:
+ if (oldMembers != null) {
+ foreach (var pair in oldMembers) {
+ // add members from outer classes only if the inner class doesn't define the member
+ if (!currentMembers.ContainsKey(pair.Key))
+ currentMembers.Add(pair.Key, pair.Value);
+ }
+ }
+
+ base.VisitTypeDeclaration(typeDeclaration, data);
+ currentMembers = oldMembers;
+ return null;
+ }
+
+ void AddCurrentMember(MemberReference m)
+ {
+ MemberReference existingMember;
+ if (currentMembers.TryGetValue(m.Name, out existingMember)) {
+ // We keep the existing member assignment if it was from another class (=from a derived class),
+ // because members in derived classes have precedence over members in base classes.
+ if (existingMember != null && existingMember.DeclaringType == m.DeclaringType) {
+ // Use null as value to signalize multiple members with the same name
+ currentMembers[m.Name] = null;
+ }
+ } else {
+ currentMembers.Add(m.Name, m);
+ }
+ }
+
+ bool IsVisible(MethodDefinition m, ModuleDefinition internalMembersVisibleInModule)
+ {
+ if (m == null)
+ return false;
+ switch (m.Attributes & MethodAttributes.MemberAccessMask) {
+ case MethodAttributes.FamANDAssem:
+ case MethodAttributes.Assembly:
+ return m.Module == internalMembersVisibleInModule;
+ case MethodAttributes.Family:
+ case MethodAttributes.FamORAssem:
+ case MethodAttributes.Public:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool IsVisible(FieldDefinition f, ModuleDefinition internalMembersVisibleInModule)
+ {
+ if (f == null)
+ return false;
+ switch (f.Attributes & FieldAttributes.FieldAccessMask) {
+ case FieldAttributes.FamANDAssem:
+ case FieldAttributes.Assembly:
+ return f.Module == internalMembersVisibleInModule;
+ case FieldAttributes.Family:
+ case FieldAttributes.FamORAssem:
+ case FieldAttributes.Public:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool IsVisible(TypeDefinition t, ModuleDefinition internalMembersVisibleInModule)
+ {
+ if (t == null)
+ return false;
+ switch (t.Attributes & TypeAttributes.VisibilityMask) {
+ case TypeAttributes.NotPublic:
+ case TypeAttributes.NestedAssembly:
+ case TypeAttributes.NestedFamANDAssem:
+ return t.Module == internalMembersVisibleInModule;
+ case TypeAttributes.NestedFamily:
+ case TypeAttributes.NestedFamORAssem:
+ case TypeAttributes.NestedPublic:
+ case TypeAttributes.Public:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public override object VisitSimpleType(SimpleType simpleType, object data)
+ {
+ // Handle type arguments first, so that the fixed-up type arguments get moved over to the MemberType,
+ // if we're also creating one here.
+ base.VisitSimpleType(simpleType, data);
+ TypeReference tr = simpleType.Annotation<TypeReference>();
+ // Fully qualify any ambiguous type names.
+ if (tr != null && IsAmbiguous(tr.Namespace, tr.Name)) {
+ AstType ns;
+ if (string.IsNullOrEmpty(tr.Namespace)) {
+ ns = new SimpleType("global");
+ } else {
+ string[] parts = tr.Namespace.Split('.');
+ if (IsAmbiguous(string.Empty, parts[0])) {
+ // conflict between namespace and type name/member name
+ ns = new MemberType { Target = new SimpleType("global"), IsDoubleColon = true, MemberName = parts[0] };
+ } else {
+ ns = new SimpleType(parts[0]);
+ }
+ for (int i = 1; i < parts.Length; i++) {
+ ns = new MemberType { Target = ns, MemberName = parts[i] };
+ }
+ }
+ MemberType mt = new MemberType();
+ mt.Target = ns;
+ mt.IsDoubleColon = string.IsNullOrEmpty(tr.Namespace);
+ mt.MemberName = simpleType.Identifier;
+ mt.CopyAnnotationsFrom(simpleType);
+ simpleType.TypeArguments.MoveTo(mt.TypeArguments);
+ simpleType.ReplaceWith(mt);
+ }
+ return null;
+ }
+
+ public override object VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data)
+ {
+ isWithinTypeReferenceExpression = true;
+ base.VisitTypeReferenceExpression(typeReferenceExpression, data);
+ isWithinTypeReferenceExpression = false;
+ return null;
+ }
+
+ bool IsAmbiguous(string ns, string name)
+ {
+ // If the type name conflicts with an inner class/type parameter, we need to fully-qualify it:
+ if (currentMemberTypes != null && currentMemberTypes.Contains(name))
+ return true;
+ // If the type name conflicts with a field/property etc. on the current class, we need to fully-qualify it,
+ // if we're inside an expression.
+ if (isWithinTypeReferenceExpression && currentMembers != null) {
+ MemberReference mr;
+ if (currentMembers.TryGetValue(name, out mr)) {
+ // However, in the special case where the member is a field or property with the same type
+ // as is requested, then we can use the short name (if it's not otherwise ambiguous)
+ PropertyDefinition prop = mr as PropertyDefinition;
+ FieldDefinition field = mr as FieldDefinition;
+ if (!(prop != null && prop.PropertyType.Namespace == ns && prop.PropertyType.Name == name)
+ && !(field != null && field.FieldType.Namespace == ns && field.FieldType.Name == name))
+ return true;
+ }
+ }
+ // If the type is defined in the current namespace,
+ // then we can use the short name even if we imported type with same name from another namespace.
+ if (ns == currentNamespace && !string.IsNullOrEmpty(ns))
+ return false;
+ return transform.ambiguousTypeNames.Contains(name);
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs b/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
new file mode 100644
index 00000000..d3ae46c1
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
@@ -0,0 +1,1123 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+
+using ICSharpCode.Decompiler.ILAst;
+using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.CSharp.Analysis;
+using ICSharpCode.NRefactory.PatternMatching;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ /// <summary>
+ /// Finds the expanded form of using statements using pattern matching and replaces it with a UsingStatement.
+ /// </summary>
+ public sealed class PatternStatementTransform : ContextTrackingVisitor<AstNode>, IAstTransform
+ {
+ public PatternStatementTransform(DecompilerContext context) : base(context)
+ {
+ }
+
+ #region Visitor Overrides
+ protected override AstNode VisitChildren(AstNode node, object data)
+ {
+ // Go through the children, and keep visiting a node as long as it changes.
+ // Because some transforms delete/replace nodes before and after the node being transformed, we rely
+ // on the transform's return value to know where we need to keep iterating.
+ for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
+ AstNode oldChild;
+ do {
+ oldChild = child;
+ child = child.AcceptVisitor(this, data);
+ Debug.Assert(child != null && child.Parent == node);
+ } while (child != oldChild);
+ }
+ return node;
+ }
+
+ public override AstNode VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
+ {
+ AstNode result;
+ if (context.Settings.UsingStatement) {
+ result = TransformUsings(expressionStatement);
+ if (result != null)
+ return result;
+ result = TransformNonGenericForEach(expressionStatement);
+ if (result != null)
+ return result;
+ }
+ result = TransformFor(expressionStatement);
+ if (result != null)
+ return result;
+ if (context.Settings.LockStatement) {
+ result = TransformLock(expressionStatement);
+ if (result != null)
+ return result;
+ }
+ return base.VisitExpressionStatement(expressionStatement, data);
+ }
+
+ public override AstNode VisitUsingStatement(UsingStatement usingStatement, object data)
+ {
+ if (context.Settings.ForEachStatement) {
+ AstNode result = TransformForeach(usingStatement);
+ if (result != null)
+ return result;
+ }
+ return base.VisitUsingStatement(usingStatement, data);
+ }
+
+ public override AstNode VisitWhileStatement(WhileStatement whileStatement, object data)
+ {
+ return TransformDoWhile(whileStatement) ?? base.VisitWhileStatement(whileStatement, data);
+ }
+
+ public override AstNode VisitIfElseStatement(IfElseStatement ifElseStatement, object data)
+ {
+ if (context.Settings.SwitchStatementOnString) {
+ AstNode result = TransformSwitchOnString(ifElseStatement);
+ if (result != null)
+ return result;
+ }
+ AstNode simplifiedIfElse = SimplifyCascadingIfElseStatements(ifElseStatement);
+ if (simplifiedIfElse != null)
+ return simplifiedIfElse;
+ return base.VisitIfElseStatement(ifElseStatement, data);
+ }
+
+ public override AstNode VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data)
+ {
+ if (context.Settings.AutomaticProperties) {
+ AstNode result = TransformAutomaticProperties(propertyDeclaration);
+ if (result != null)
+ return result;
+ }
+ return base.VisitPropertyDeclaration(propertyDeclaration, data);
+ }
+
+ public override AstNode VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration, object data)
+ {
+ // first apply transforms to the accessor bodies
+ base.VisitCustomEventDeclaration(eventDeclaration, data);
+ if (context.Settings.AutomaticEvents) {
+ AstNode result = TransformAutomaticEvents(eventDeclaration);
+ if (result != null)
+ return result;
+ }
+ return eventDeclaration;
+ }
+
+ public override AstNode VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
+ {
+ return TransformDestructor(methodDeclaration) ?? base.VisitMethodDeclaration(methodDeclaration, data);
+ }
+
+ public override AstNode VisitTryCatchStatement(TryCatchStatement tryCatchStatement, object data)
+ {
+ return TransformTryCatchFinally(tryCatchStatement) ?? base.VisitTryCatchStatement(tryCatchStatement, data);
+ }
+ #endregion
+
+ /// <summary>
+ /// $variable = $initializer;
+ /// </summary>
+ static readonly AstNode variableAssignPattern = new ExpressionStatement(
+ new AssignmentExpression(
+ new NamedNode("variable", new IdentifierExpression(Pattern.AnyString)),
+ new AnyNode("initializer")
+ ));
+
+ #region using
+ static Expression InvokeDispose(Expression identifier)
+ {
+ return new Choice {
+ identifier.Invoke("Dispose"),
+ identifier.Clone().CastTo(new TypePattern(typeof(IDisposable))).Invoke("Dispose")
+ };
+ }
+
+ static readonly AstNode usingTryCatchPattern = new TryCatchStatement {
+ TryBlock = new AnyNode(),
+ FinallyBlock = new BlockStatement {
+ new Choice {
+ { "valueType",
+ new ExpressionStatement(InvokeDispose(new NamedNode("ident", new IdentifierExpression(Pattern.AnyString))))
+ },
+ { "referenceType",
+ new IfElseStatement {
+ Condition = new BinaryOperatorExpression(
+ new NamedNode("ident", new IdentifierExpression(Pattern.AnyString)),
+ BinaryOperatorType.InEquality,
+ new NullReferenceExpression()
+ ),
+ TrueStatement = new BlockStatement {
+ new ExpressionStatement(InvokeDispose(new Backreference("ident")))
+ }
+ }
+ }
+ }.ToStatement()
+ }
+ };
+
+ public UsingStatement TransformUsings(ExpressionStatement node)
+ {
+ Match m1 = variableAssignPattern.Match(node);
+ if (!m1.Success) return null;
+ TryCatchStatement tryCatch = node.NextSibling as TryCatchStatement;
+ Match m2 = usingTryCatchPattern.Match(tryCatch);
+ if (!m2.Success) return null;
+ string variableName = m1.Get<IdentifierExpression>("variable").Single().Identifier;
+ if (variableName != m2.Get<IdentifierExpression>("ident").Single().Identifier)
+ return null;
+ if (m2.Has("valueType")) {
+ // if there's no if(x!=null), then it must be a value type
+ ILVariable v = m1.Get<AstNode>("variable").Single().Annotation<ILVariable>();
+ if (v == null || v.Type == null || !v.Type.IsValueType)
+ return null;
+ }
+
+ // There are two variants of the using statement:
+ // "using (var a = init)" and "using (expr)".
+ // The former declares a read-only variable 'a', and the latter declares an unnamed read-only variable
+ // to store the original value of 'expr'.
+ // This means that in order to introduce a using statement, in both cases we need to detect a read-only
+ // variable that is used only within that block.
+
+ if (HasAssignment(tryCatch, variableName))
+ return null;
+
+ VariableDeclarationStatement varDecl = FindVariableDeclaration(node, variableName);
+ if (varDecl == null || !(varDecl.Parent is BlockStatement))
+ return null;
+
+ // Validate that the variable is not used after the using statement:
+ if (!IsVariableValueUnused(varDecl, tryCatch))
+ return null;
+
+ node.Remove();
+
+ UsingStatement usingStatement = new UsingStatement();
+ usingStatement.EmbeddedStatement = tryCatch.TryBlock.Detach();
+ tryCatch.ReplaceWith(usingStatement);
+
+ // If possible, we'll eliminate the variable completely:
+ if (usingStatement.EmbeddedStatement.Descendants.OfType<IdentifierExpression>().Any(ident => ident.Identifier == variableName)) {
+ // variable is used, so we'll create a variable declaration
+ usingStatement.ResourceAcquisition = new VariableDeclarationStatement {
+ Type = (AstType)varDecl.Type.Clone(),
+ Variables = {
+ new VariableInitializer {
+ Name = variableName,
+ Initializer = m1.Get<Expression>("initializer").Single().Detach()
+ }.CopyAnnotationsFrom(node.Expression)
+ .WithAnnotation(m1.Get<AstNode>("variable").Single().Annotation<ILVariable>())
+ }
+ }.CopyAnnotationsFrom(node);
+ } else {
+ // the variable is never used; eliminate it:
+ usingStatement.ResourceAcquisition = m1.Get<Expression>("initializer").Single().Detach();
+ }
+ return usingStatement;
+ }
+
+ internal static VariableDeclarationStatement FindVariableDeclaration(AstNode node, string identifier)
+ {
+ while (node != null) {
+ while (node.PrevSibling != null) {
+ node = node.PrevSibling;
+ VariableDeclarationStatement varDecl = node as VariableDeclarationStatement;
+ if (varDecl != null && varDecl.Variables.Count == 1 && varDecl.Variables.Single().Name == identifier) {
+ return varDecl;
+ }
+ }
+ node = node.Parent;
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Gets whether the old variable value (assigned inside 'targetStatement' or earlier)
+ /// is read anywhere in the remaining scope of the variable declaration.
+ /// </summary>
+ bool IsVariableValueUnused(VariableDeclarationStatement varDecl, Statement targetStatement)
+ {
+ Debug.Assert(targetStatement.Ancestors.Contains(varDecl.Parent));
+ BlockStatement block = (BlockStatement)varDecl.Parent;
+ DefiniteAssignmentAnalysis daa = new DefiniteAssignmentAnalysis(block, context.CancellationToken);
+ daa.SetAnalyzedRange(targetStatement, block, startInclusive: false);
+ daa.Analyze(varDecl.Variables.Single().Name);
+ return daa.UnassignedVariableUses.Count == 0;
+ }
+
+ // I used this in the first implementation of the using-statement transform, but now no longer
+ // because there were problems when multiple using statements were using the same variable
+ // - no single using statement could be transformed without making the C# code invalid,
+ // but transforming both would work.
+ // We now use 'IsVariableValueUnused' which will perform the transform
+ // even if it results in two variables with the same name and overlapping scopes.
+ // (this issue could be fixed later by renaming one of the variables)
+
+ // I'm not sure whether the other consumers of 'CanMoveVariableDeclarationIntoStatement' should be changed the same way.
+ bool CanMoveVariableDeclarationIntoStatement(VariableDeclarationStatement varDecl, Statement targetStatement, out Statement declarationPoint)
+ {
+ Debug.Assert(targetStatement.Ancestors.Contains(varDecl.Parent));
+ // Find all blocks between targetStatement and varDecl.Parent
+ List<BlockStatement> blocks = targetStatement.Ancestors.TakeWhile(block => block != varDecl.Parent).OfType<BlockStatement>().ToList();
+ blocks.Add((BlockStatement)varDecl.Parent); // also handle the varDecl.Parent block itself
+ blocks.Reverse(); // go from parent blocks to child blocks
+ DefiniteAssignmentAnalysis daa = new DefiniteAssignmentAnalysis(blocks[0], context.CancellationToken);
+ declarationPoint = null;
+ foreach (BlockStatement block in blocks) {
+ if (!DeclareVariables.FindDeclarationPoint(daa, varDecl, block, out declarationPoint)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Gets whether there is an assignment to 'variableName' anywhere within the given node.
+ /// </summary>
+ bool HasAssignment(AstNode root, string variableName)
+ {
+ foreach (AstNode node in root.DescendantsAndSelf) {
+ IdentifierExpression ident = node as IdentifierExpression;
+ if (ident != null && ident.Identifier == variableName) {
+ if (ident.Parent is AssignmentExpression && ident.Role == AssignmentExpression.LeftRole
+ || ident.Parent is DirectionExpression)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ #endregion
+
+ #region foreach (generic)
+ static readonly UsingStatement genericForeachPattern = new UsingStatement {
+ ResourceAcquisition = new VariableDeclarationStatement {
+ Type = new AnyNode("enumeratorType"),
+ Variables = {
+ new NamedNode(
+ "enumeratorVariable",
+ new VariableInitializer {
+ Name = Pattern.AnyString,
+ Initializer = new AnyNode("collection").ToExpression().Invoke("GetEnumerator")
+ }
+ )
+ }
+ },
+ EmbeddedStatement = new BlockStatement {
+ new Repeat(
+ new VariableDeclarationStatement { Type = new AnyNode(), Variables = { new VariableInitializer(Pattern.AnyString) } }.WithName("variablesOutsideLoop")
+ ).ToStatement(),
+ new WhileStatement {
+ Condition = new IdentifierExpressionBackreference("enumeratorVariable").ToExpression().Invoke("MoveNext"),
+ EmbeddedStatement = new BlockStatement {
+ new Repeat(
+ new VariableDeclarationStatement {
+ Type = new AnyNode(),
+ Variables = { new VariableInitializer(Pattern.AnyString) }
+ }.WithName("variablesInsideLoop")
+ ).ToStatement(),
+ new AssignmentExpression {
+ Left = new IdentifierExpression(Pattern.AnyString).WithName("itemVariable"),
+ Operator = AssignmentOperatorType.Assign,
+ Right = new IdentifierExpressionBackreference("enumeratorVariable").ToExpression().Member("Current")
+ },
+ new Repeat(new AnyNode("statement")).ToStatement()
+ }
+ }.WithName("loop")
+ }};
+
+ public ForeachStatement TransformForeach(UsingStatement node)
+ {
+ Match m = genericForeachPattern.Match(node);
+ if (!m.Success)
+ return null;
+ if (!(node.Parent is BlockStatement) && m.Has("variablesOutsideLoop")) {
+ // if there are variables outside the loop, we need to put those into the parent block, and that won't work if the direct parent isn't a block
+ return null;
+ }
+ VariableInitializer enumeratorVar = m.Get<VariableInitializer>("enumeratorVariable").Single();
+ IdentifierExpression itemVar = m.Get<IdentifierExpression>("itemVariable").Single();
+ WhileStatement loop = m.Get<WhileStatement>("loop").Single();
+
+ // Find the declaration of the item variable:
+ // Because we look only outside the loop, we won't make the mistake of moving a captured variable across the loop boundary
+ VariableDeclarationStatement itemVarDecl = FindVariableDeclaration(loop, itemVar.Identifier);
+ if (itemVarDecl == null || !(itemVarDecl.Parent is BlockStatement))
+ return null;
+
+ // Now verify that we can move the variable declaration in front of the loop:
+ Statement declarationPoint;
+ CanMoveVariableDeclarationIntoStatement(itemVarDecl, loop, out declarationPoint);
+ // We ignore the return value because we don't care whether we can move the variable into the loop
+ // (that is possible only with non-captured variables).
+ // We just care that we can move it in front of the loop:
+ if (declarationPoint != loop)
+ return null;
+
+ BlockStatement newBody = new BlockStatement();
+ foreach (Statement stmt in m.Get<Statement>("variablesInsideLoop"))
+ newBody.Add(stmt.Detach());
+ foreach (Statement stmt in m.Get<Statement>("statement"))
+ newBody.Add(stmt.Detach());
+
+ ForeachStatement foreachStatement = new ForeachStatement {
+ VariableType = (AstType)itemVarDecl.Type.Clone(),
+ VariableName = itemVar.Identifier,
+ InExpression = m.Get<Expression>("collection").Single().Detach(),
+ EmbeddedStatement = newBody
+ }.WithAnnotation(itemVarDecl.Variables.Single().Annotation<ILVariable>());
+ if (foreachStatement.InExpression is BaseReferenceExpression) {
+ foreachStatement.InExpression = new ThisReferenceExpression().CopyAnnotationsFrom(foreachStatement.InExpression);
+ }
+ node.ReplaceWith(foreachStatement);
+ foreach (Statement stmt in m.Get<Statement>("variablesOutsideLoop")) {
+ ((BlockStatement)foreachStatement.Parent).Statements.InsertAfter(null, stmt.Detach());
+ }
+ return foreachStatement;
+ }
+ #endregion
+
+ #region foreach (non-generic)
+ ExpressionStatement getEnumeratorPattern = new ExpressionStatement(
+ new AssignmentExpression(
+ new NamedNode("left", new IdentifierExpression(Pattern.AnyString)),
+ new AnyNode("collection").ToExpression().Invoke("GetEnumerator")
+ ));
+
+ TryCatchStatement nonGenericForeachPattern = new TryCatchStatement {
+ TryBlock = new BlockStatement {
+ new WhileStatement {
+ Condition = new IdentifierExpression(Pattern.AnyString).WithName("enumerator").Invoke("MoveNext"),
+ EmbeddedStatement = new BlockStatement {
+ new AssignmentExpression(
+ new IdentifierExpression(Pattern.AnyString).WithName("itemVar"),
+ new Choice {
+ new Backreference("enumerator").ToExpression().Member("Current"),
+ new CastExpression {
+ Type = new AnyNode("castType"),
+ Expression = new Backreference("enumerator").ToExpression().Member("Current")
+ }
+ }
+ ),
+ new Repeat(new AnyNode("stmt")).ToStatement()
+ }
+ }.WithName("loop")
+ },
+ FinallyBlock = new BlockStatement {
+ new AssignmentExpression(
+ new IdentifierExpression(Pattern.AnyString).WithName("disposable"),
+ new Backreference("enumerator").ToExpression().CastAs(new TypePattern(typeof(IDisposable)))
+ ),
+ new IfElseStatement {
+ Condition = new BinaryOperatorExpression {
+ Left = new Backreference("disposable"),
+ Operator = BinaryOperatorType.InEquality,
+ Right = new NullReferenceExpression()
+ },
+ TrueStatement = new BlockStatement {
+ new Backreference("disposable").ToExpression().Invoke("Dispose")
+ }
+ }
+ }};
+
+ public ForeachStatement TransformNonGenericForEach(ExpressionStatement node)
+ {
+ Match m1 = getEnumeratorPattern.Match(node);
+ if (!m1.Success) return null;
+ AstNode tryCatch = node.NextSibling;
+ Match m2 = nonGenericForeachPattern.Match(tryCatch);
+ if (!m2.Success) return null;
+
+ IdentifierExpression enumeratorVar = m2.Get<IdentifierExpression>("enumerator").Single();
+ IdentifierExpression itemVar = m2.Get<IdentifierExpression>("itemVar").Single();
+ WhileStatement loop = m2.Get<WhileStatement>("loop").Single();
+
+ // verify that the getEnumeratorPattern assigns to the same variable as the nonGenericForeachPattern is reading from
+ if (!enumeratorVar.IsMatch(m1.Get("left").Single()))
+ return null;
+
+ VariableDeclarationStatement enumeratorVarDecl = FindVariableDeclaration(loop, enumeratorVar.Identifier);
+ if (enumeratorVarDecl == null || !(enumeratorVarDecl.Parent is BlockStatement))
+ return null;
+
+ // Find the declaration of the item variable:
+ // Because we look only outside the loop, we won't make the mistake of moving a captured variable across the loop boundary
+ VariableDeclarationStatement itemVarDecl = FindVariableDeclaration(loop, itemVar.Identifier);
+ if (itemVarDecl == null || !(itemVarDecl.Parent is BlockStatement))
+ return null;
+
+ // Now verify that we can move the variable declaration in front of the loop:
+ Statement declarationPoint;
+ CanMoveVariableDeclarationIntoStatement(itemVarDecl, loop, out declarationPoint);
+ // We ignore the return value because we don't care whether we can move the variable into the loop
+ // (that is possible only with non-captured variables).
+ // We just care that we can move it in front of the loop:
+ if (declarationPoint != loop)
+ return null;
+
+ ForeachStatement foreachStatement = new ForeachStatement
+ {
+ VariableType = itemVarDecl.Type.Clone(),
+ VariableName = itemVar.Identifier,
+ }.WithAnnotation(itemVarDecl.Variables.Single().Annotation<ILVariable>());
+ BlockStatement body = new BlockStatement();
+ foreachStatement.EmbeddedStatement = body;
+ ((BlockStatement)node.Parent).Statements.InsertBefore(node, foreachStatement);
+
+ body.Add(node.Detach());
+ body.Add((Statement)tryCatch.Detach());
+
+ // Now that we moved the whole try-catch into the foreach loop; verify that we can
+ // move the enumerator into the foreach loop:
+ CanMoveVariableDeclarationIntoStatement(enumeratorVarDecl, foreachStatement, out declarationPoint);
+ if (declarationPoint != foreachStatement) {
+ // oops, the enumerator variable can't be moved into the foreach loop
+ // Undo our AST changes:
+ ((BlockStatement)foreachStatement.Parent).Statements.InsertBefore(foreachStatement, node.Detach());
+ foreachStatement.ReplaceWith(tryCatch);
+ return null;
+ }
+
+ // Now create the correct body for the foreach statement:
+ foreachStatement.InExpression = m1.Get<Expression>("collection").Single().Detach();
+ if (foreachStatement.InExpression is BaseReferenceExpression) {
+ foreachStatement.InExpression = new ThisReferenceExpression().CopyAnnotationsFrom(foreachStatement.InExpression);
+ }
+ body.Statements.Clear();
+ body.Statements.AddRange(m2.Get<Statement>("stmt").Select(stmt => stmt.Detach()));
+
+ return foreachStatement;
+ }
+ #endregion
+
+ #region for
+ static readonly WhileStatement forPattern = new WhileStatement {
+ Condition = new BinaryOperatorExpression {
+ Left = new NamedNode("ident", new IdentifierExpression(Pattern.AnyString)),
+ Operator = BinaryOperatorType.Any,
+ Right = new AnyNode("endExpr")
+ },
+ EmbeddedStatement = new BlockStatement {
+ Statements = {
+ new Repeat(new AnyNode("statement")),
+ new NamedNode(
+ "increment",
+ new ExpressionStatement(
+ new AssignmentExpression {
+ Left = new Backreference("ident"),
+ Operator = AssignmentOperatorType.Any,
+ Right = new AnyNode()
+ }))
+ }
+ }};
+
+ public ForStatement TransformFor(ExpressionStatement node)
+ {
+ Match m1 = variableAssignPattern.Match(node);
+ if (!m1.Success) return null;
+ AstNode next = node.NextSibling;
+ Match m2 = forPattern.Match(next);
+ if (!m2.Success) return null;
+ // ensure the variable in the for pattern is the same as in the declaration
+ if (m1.Get<IdentifierExpression>("variable").Single().Identifier != m2.Get<IdentifierExpression>("ident").Single().Identifier)
+ return null;
+ WhileStatement loop = (WhileStatement)next;
+ node.Remove();
+ BlockStatement newBody = new BlockStatement();
+ foreach (Statement stmt in m2.Get<Statement>("statement"))
+ newBody.Add(stmt.Detach());
+ ForStatement forStatement = new ForStatement();
+ forStatement.Initializers.Add(node);
+ forStatement.Condition = loop.Condition.Detach();
+ forStatement.Iterators.Add(m2.Get<Statement>("increment").Single().Detach());
+ forStatement.EmbeddedStatement = newBody;
+ loop.ReplaceWith(forStatement);
+ return forStatement;
+ }
+ #endregion
+
+ #region doWhile
+ static readonly WhileStatement doWhilePattern = new WhileStatement {
+ Condition = new PrimitiveExpression(true),
+ EmbeddedStatement = new BlockStatement {
+ Statements = {
+ new Repeat(new AnyNode("statement")),
+ new IfElseStatement {
+ Condition = new AnyNode("condition"),
+ TrueStatement = new BlockStatement { new BreakStatement() }
+ }
+ }
+ }};
+
+ public DoWhileStatement TransformDoWhile(WhileStatement whileLoop)
+ {
+ Match m = doWhilePattern.Match(whileLoop);
+ if (m.Success) {
+ DoWhileStatement doLoop = new DoWhileStatement();
+ doLoop.Condition = new UnaryOperatorExpression(UnaryOperatorType.Not, m.Get<Expression>("condition").Single().Detach());
+ doLoop.Condition.AcceptVisitor(new PushNegation(), null);
+ BlockStatement block = (BlockStatement)whileLoop.EmbeddedStatement;
+ block.Statements.Last().Remove(); // remove if statement
+ doLoop.EmbeddedStatement = block.Detach();
+ whileLoop.ReplaceWith(doLoop);
+
+ // we may have to extract variable definitions out of the loop if they were used in the condition:
+ foreach (var varDecl in block.Statements.OfType<VariableDeclarationStatement>()) {
+ VariableInitializer v = varDecl.Variables.Single();
+ if (doLoop.Condition.DescendantsAndSelf.OfType<IdentifierExpression>().Any(i => i.Identifier == v.Name)) {
+ AssignmentExpression assign = new AssignmentExpression(new IdentifierExpression(v.Name), v.Initializer.Detach());
+ // move annotations from v to assign:
+ assign.CopyAnnotationsFrom(v);
+ v.RemoveAnnotations<object>();
+ // remove varDecl with assignment; and move annotations from varDecl to the ExpressionStatement:
+ varDecl.ReplaceWith(new ExpressionStatement(assign).CopyAnnotationsFrom(varDecl));
+ varDecl.RemoveAnnotations<object>();
+
+ // insert the varDecl above the do-while loop:
+ doLoop.Parent.InsertChildBefore(doLoop, varDecl, BlockStatement.StatementRole);
+ }
+ }
+ return doLoop;
+ }
+ return null;
+ }
+ #endregion
+
+ #region lock
+ static readonly AstNode lockFlagInitPattern = new ExpressionStatement(
+ new AssignmentExpression(
+ new NamedNode("variable", new IdentifierExpression(Pattern.AnyString)),
+ new PrimitiveExpression(false)
+ ));
+
+ static readonly AstNode lockTryCatchPattern = new TryCatchStatement {
+ TryBlock = new BlockStatement {
+ new OptionalNode(new VariableDeclarationStatement()).ToStatement(),
+ new TypePattern(typeof(System.Threading.Monitor)).ToType().Invoke(
+ "Enter", new AnyNode("enter"),
+ new DirectionExpression {
+ FieldDirection = FieldDirection.Ref,
+ Expression = new NamedNode("flag", new IdentifierExpression(Pattern.AnyString))
+ }),
+ new Repeat(new AnyNode()).ToStatement()
+ },
+ FinallyBlock = new BlockStatement {
+ new IfElseStatement {
+ Condition = new Backreference("flag"),
+ TrueStatement = new BlockStatement {
+ new TypePattern(typeof(System.Threading.Monitor)).ToType().Invoke("Exit", new AnyNode("exit"))
+ }
+ }
+ }};
+
+ static readonly AstNode oldMonitorCallPattern = new ExpressionStatement(
+ new TypePattern(typeof(System.Threading.Monitor)).ToType().Invoke("Enter", new AnyNode("enter"))
+ );
+
+ static readonly AstNode oldLockTryCatchPattern = new TryCatchStatement
+ {
+ TryBlock = new BlockStatement {
+ new Repeat(new AnyNode()).ToStatement()
+ },
+ FinallyBlock = new BlockStatement {
+ new TypePattern(typeof(System.Threading.Monitor)).ToType().Invoke("Exit", new AnyNode("exit"))
+ }
+ };
+
+ bool AnalyzeLockV2(ExpressionStatement node, out Expression enter, out Expression exit)
+ {
+ enter = null;
+ exit = null;
+ Match m1 = oldMonitorCallPattern.Match(node);
+ if (!m1.Success) return false;
+ Match m2 = oldLockTryCatchPattern.Match(node.NextSibling);
+ if (!m2.Success) return false;
+ enter = m1.Get<Expression>("enter").Single();
+ exit = m2.Get<Expression>("exit").Single();
+ return true;
+ }
+
+ bool AnalyzeLockV4(ExpressionStatement node, out Expression enter, out Expression exit)
+ {
+ enter = null;
+ exit = null;
+ Match m1 = lockFlagInitPattern.Match(node);
+ if (!m1.Success) return false;
+ Match m2 = lockTryCatchPattern.Match(node.NextSibling);
+ if (!m2.Success) return false;
+ enter = m2.Get<Expression>("enter").Single();
+ exit = m2.Get<Expression>("exit").Single();
+ return m1.Get<IdentifierExpression>("variable").Single().Identifier == m2.Get<IdentifierExpression>("flag").Single().Identifier;
+ }
+
+ public LockStatement TransformLock(ExpressionStatement node)
+ {
+ Expression enter, exit;
+ bool isV2 = AnalyzeLockV2(node, out enter, out exit);
+ if (isV2 || AnalyzeLockV4(node, out enter, out exit)) {
+ AstNode tryCatch = node.NextSibling;
+ if (!exit.IsMatch(enter)) {
+ // If exit and enter are not the same, then enter must be "exit = ..."
+ AssignmentExpression assign = enter as AssignmentExpression;
+ if (assign == null)
+ return null;
+ if (!exit.IsMatch(assign.Left))
+ return null;
+ enter = assign.Right;
+ // TODO: verify that 'obj' variable can be removed
+ }
+ // TODO: verify that 'flag' variable can be removed
+ // transform the code into a lock statement:
+ LockStatement l = new LockStatement();
+ l.Expression = enter.Detach();
+ l.EmbeddedStatement = ((TryCatchStatement)tryCatch).TryBlock.Detach();
+ if (!isV2) // Remove 'Enter()' call
+ ((BlockStatement)l.EmbeddedStatement).Statements.First().Remove();
+ tryCatch.ReplaceWith(l);
+ node.Remove(); // remove flag variable
+ return l;
+ }
+ return null;
+ }
+ #endregion
+
+ #region switch on strings
+ static readonly IfElseStatement switchOnStringPattern = new IfElseStatement {
+ Condition = new BinaryOperatorExpression {
+ Left = new AnyNode("switchExpr"),
+ Operator = BinaryOperatorType.InEquality,
+ Right = new NullReferenceExpression()
+ },
+ TrueStatement = new BlockStatement {
+ new IfElseStatement {
+ Condition = new BinaryOperatorExpression {
+ Left = new AnyNode("cachedDict"),
+ Operator = BinaryOperatorType.Equality,
+ Right = new NullReferenceExpression()
+ },
+ TrueStatement = new AnyNode("dictCreation")
+ },
+ new IfElseStatement {
+ Condition = new Backreference("cachedDict").ToExpression().Invoke(
+ "TryGetValue",
+ new NamedNode("switchVar", new IdentifierExpression(Pattern.AnyString)),
+ new DirectionExpression {
+ FieldDirection = FieldDirection.Out,
+ Expression = new IdentifierExpression(Pattern.AnyString).WithName("intVar")
+ }),
+ TrueStatement = new BlockStatement {
+ Statements = {
+ new NamedNode(
+ "switch", new SwitchStatement {
+ Expression = new IdentifierExpressionBackreference("intVar"),
+ SwitchSections = { new Repeat(new AnyNode()) }
+ })
+ }
+ }
+ },
+ new Repeat(new AnyNode("nonNullDefaultStmt")).ToStatement()
+ },
+ FalseStatement = new OptionalNode("nullStmt", new BlockStatement { Statements = { new Repeat(new AnyNode()) } })
+ };
+
+ public SwitchStatement TransformSwitchOnString(IfElseStatement node)
+ {
+ Match m = switchOnStringPattern.Match(node);
+ if (!m.Success)
+ return null;
+ // switchVar must be the same as switchExpr; or switchExpr must be an assignment and switchVar the left side of that assignment
+ if (!m.Get("switchVar").Single().IsMatch(m.Get("switchExpr").Single())) {
+ AssignmentExpression assign = m.Get("switchExpr").Single() as AssignmentExpression;
+ if (!(assign != null && m.Get("switchVar").Single().IsMatch(assign.Left)))
+ return null;
+ }
+ FieldReference cachedDictField = m.Get<AstNode>("cachedDict").Single().Annotation<FieldReference>();
+ if (cachedDictField == null)
+ return null;
+ List<Statement> dictCreation = m.Get<BlockStatement>("dictCreation").Single().Statements.ToList();
+ List<KeyValuePair<string, int>> dict = BuildDictionary(dictCreation);
+ SwitchStatement sw = m.Get<SwitchStatement>("switch").Single();
+ sw.Expression = m.Get<Expression>("switchExpr").Single().Detach();
+ foreach (SwitchSection section in sw.SwitchSections) {
+ List<CaseLabel> labels = section.CaseLabels.ToList();
+ section.CaseLabels.Clear();
+ foreach (CaseLabel label in labels) {
+ PrimitiveExpression expr = label.Expression as PrimitiveExpression;
+ if (expr == null || !(expr.Value is int))
+ continue;
+ int val = (int)expr.Value;
+ foreach (var pair in dict) {
+ if (pair.Value == val)
+ section.CaseLabels.Add(new CaseLabel { Expression = new PrimitiveExpression(pair.Key) });
+ }
+ }
+ }
+ if (m.Has("nullStmt")) {
+ SwitchSection section = new SwitchSection();
+ section.CaseLabels.Add(new CaseLabel { Expression = new NullReferenceExpression() });
+ BlockStatement block = m.Get<BlockStatement>("nullStmt").Single();
+ block.Statements.Add(new BreakStatement());
+ section.Statements.Add(block.Detach());
+ sw.SwitchSections.Add(section);
+ } else if (m.Has("nonNullDefaultStmt")) {
+ sw.SwitchSections.Add(
+ new SwitchSection {
+ CaseLabels = { new CaseLabel { Expression = new NullReferenceExpression() } },
+ Statements = { new BlockStatement { new BreakStatement() } }
+ });
+ }
+ if (m.Has("nonNullDefaultStmt")) {
+ SwitchSection section = new SwitchSection();
+ section.CaseLabels.Add(new CaseLabel());
+ BlockStatement block = new BlockStatement();
+ block.Statements.AddRange(m.Get<Statement>("nonNullDefaultStmt").Select(s => s.Detach()));
+ block.Add(new BreakStatement());
+ section.Statements.Add(block);
+ sw.SwitchSections.Add(section);
+ }
+ node.ReplaceWith(sw);
+ return sw;
+ }
+
+ List<KeyValuePair<string, int>> BuildDictionary(List<Statement> dictCreation)
+ {
+ if (context.Settings.ObjectOrCollectionInitializers && dictCreation.Count == 1)
+ return BuildDictionaryFromInitializer(dictCreation[0]);
+
+ return BuildDictionaryFromAddMethodCalls(dictCreation);
+ }
+
+ static readonly Statement assignInitializedDictionary = new ExpressionStatement {
+ Expression = new AssignmentExpression {
+ Left = new AnyNode().ToExpression(),
+ Right = new ObjectCreateExpression {
+ Type = new AnyNode(),
+ Arguments = { new Repeat(new AnyNode()) },
+ Initializer = new ArrayInitializerExpression {
+ Elements = { new Repeat(new AnyNode("dictJumpTable")) }
+ }
+ },
+ },
+ };
+
+ List<KeyValuePair<string, int>> BuildDictionaryFromInitializer(Statement statement)
+ {
+ List<KeyValuePair<string, int>> dict = new List<KeyValuePair<string, int>>();
+ Match m = assignInitializedDictionary.Match(statement);
+ if (!m.Success)
+ return dict;
+
+ foreach (ArrayInitializerExpression initializer in m.Get<ArrayInitializerExpression>("dictJumpTable")) {
+ KeyValuePair<string, int> pair;
+ if (TryGetPairFrom(initializer.Elements, out pair))
+ dict.Add(pair);
+ }
+
+ return dict;
+ }
+
+ static List<KeyValuePair<string, int>> BuildDictionaryFromAddMethodCalls(List<Statement> dictCreation)
+ {
+ List<KeyValuePair<string, int>> dict = new List<KeyValuePair<string, int>>();
+ for (int i = 0; i < dictCreation.Count; i++) {
+ ExpressionStatement es = dictCreation[i] as ExpressionStatement;
+ if (es == null)
+ continue;
+ InvocationExpression ie = es.Expression as InvocationExpression;
+ if (ie == null)
+ continue;
+
+ KeyValuePair<string, int> pair;
+ if (TryGetPairFrom(ie.Arguments, out pair))
+ dict.Add(pair);
+ }
+ return dict;
+ }
+
+ static bool TryGetPairFrom(AstNodeCollection<Expression> expressions, out KeyValuePair<string, int> pair)
+ {
+ PrimitiveExpression arg1 = expressions.ElementAtOrDefault(0) as PrimitiveExpression;
+ PrimitiveExpression arg2 = expressions.ElementAtOrDefault(1) as PrimitiveExpression;
+ if (arg1 != null && arg2 != null && arg1.Value is string && arg2.Value is int) {
+ pair = new KeyValuePair<string, int>((string)arg1.Value, (int)arg2.Value);
+ return true;
+ }
+
+ pair = default(KeyValuePair<string, int>);
+ return false;
+ }
+
+ #endregion
+
+ #region Automatic Properties
+ static readonly PropertyDeclaration automaticPropertyPattern = new PropertyDeclaration {
+ Attributes = { new Repeat(new AnyNode()) },
+ Modifiers = Modifiers.Any,
+ ReturnType = new AnyNode(),
+ PrivateImplementationType = new OptionalNode(new AnyNode()),
+ Name = Pattern.AnyString,
+ Getter = new Accessor {
+ Attributes = { new Repeat(new AnyNode()) },
+ Modifiers = Modifiers.Any,
+ Body = new BlockStatement {
+ new ReturnStatement {
+ Expression = new AnyNode("fieldReference")
+ }
+ }
+ },
+ Setter = new Accessor {
+ Attributes = { new Repeat(new AnyNode()) },
+ Modifiers = Modifiers.Any,
+ Body = new BlockStatement {
+ new AssignmentExpression {
+ Left = new Backreference("fieldReference"),
+ Right = new IdentifierExpression("value")
+ }
+ }}};
+
+ PropertyDeclaration TransformAutomaticProperties(PropertyDeclaration property)
+ {
+ PropertyDefinition cecilProperty = property.Annotation<PropertyDefinition>();
+ if (cecilProperty == null || cecilProperty.GetMethod == null || cecilProperty.SetMethod == null)
+ return null;
+ if (!(cecilProperty.GetMethod.IsCompilerGenerated() && cecilProperty.SetMethod.IsCompilerGenerated()))
+ return null;
+ Match m = automaticPropertyPattern.Match(property);
+ if (m.Success) {
+ FieldDefinition field = m.Get<AstNode>("fieldReference").Single().Annotation<FieldReference>().ResolveWithinSameModule();
+ if (field.IsCompilerGenerated() && field.DeclaringType == cecilProperty.DeclaringType) {
+ RemoveCompilerGeneratedAttribute(property.Getter.Attributes);
+ RemoveCompilerGeneratedAttribute(property.Setter.Attributes);
+ property.Getter.Body = null;
+ property.Setter.Body = null;
+ }
+ }
+ // Since the event instance is not changed, we can continue in the visitor as usual, so return null
+ return null;
+ }
+
+ void RemoveCompilerGeneratedAttribute(AstNodeCollection<AttributeSection> attributeSections)
+ {
+ foreach (AttributeSection section in attributeSections) {
+ foreach (var attr in section.Attributes) {
+ TypeReference tr = attr.Type.Annotation<TypeReference>();
+ if (tr != null && tr.Namespace == "System.Runtime.CompilerServices" && tr.Name == "CompilerGeneratedAttribute") {
+ attr.Remove();
+ }
+ }
+ if (section.Attributes.Count == 0)
+ section.Remove();
+ }
+ }
+ #endregion
+
+ #region Automatic Events
+ static readonly Accessor automaticEventPatternV4 = new Accessor {
+ Attributes = { new Repeat(new AnyNode()) },
+ Body = new BlockStatement {
+ new VariableDeclarationStatement { Type = new AnyNode("type"), Variables = { new AnyNode() } },
+ new VariableDeclarationStatement { Type = new Backreference("type"), Variables = { new AnyNode() } },
+ new VariableDeclarationStatement { Type = new Backreference("type"), Variables = { new AnyNode() } },
+ new AssignmentExpression {
+ Left = new NamedNode("var1", new IdentifierExpression(Pattern.AnyString)),
+ Operator = AssignmentOperatorType.Assign,
+ Right = new NamedNode(
+ "field",
+ new MemberReferenceExpression {
+ Target = new Choice { new ThisReferenceExpression(), new TypeReferenceExpression { Type = new AnyNode() } },
+ MemberName = Pattern.AnyString
+ })
+ },
+ new DoWhileStatement {
+ EmbeddedStatement = new BlockStatement {
+ new AssignmentExpression(new NamedNode("var2", new IdentifierExpression(Pattern.AnyString)), new IdentifierExpressionBackreference("var1")),
+ new AssignmentExpression {
+ Left = new NamedNode("var3", new IdentifierExpression(Pattern.AnyString)),
+ Operator = AssignmentOperatorType.Assign,
+ Right = new AnyNode("delegateCombine").ToExpression().Invoke(
+ new IdentifierExpressionBackreference("var2"),
+ new IdentifierExpression("value")
+ ).CastTo(new Backreference("type"))
+ },
+ new AssignmentExpression {
+ Left = new IdentifierExpressionBackreference("var1"),
+ Right = new TypePattern(typeof(System.Threading.Interlocked)).ToType().Invoke(
+ "CompareExchange",
+ new AstType[] { new Backreference("type") }, // type argument
+ new Expression[] { // arguments
+ new DirectionExpression { FieldDirection = FieldDirection.Ref, Expression = new Backreference("field") },
+ new IdentifierExpressionBackreference("var3"),
+ new IdentifierExpressionBackreference("var2")
+ }
+ )}
+ },
+ Condition = new BinaryOperatorExpression {
+ Left = new IdentifierExpressionBackreference("var1"),
+ Operator = BinaryOperatorType.InEquality,
+ Right = new IdentifierExpressionBackreference("var2")
+ }}
+ }};
+
+ bool CheckAutomaticEventV4Match(Match m, CustomEventDeclaration ev, bool isAddAccessor)
+ {
+ if (!m.Success)
+ return false;
+ if (m.Get<MemberReferenceExpression>("field").Single().MemberName != ev.Name)
+ return false; // field name must match event name
+ if (!ev.ReturnType.IsMatch(m.Get("type").Single()))
+ return false; // variable types must match event type
+ var combineMethod = m.Get<AstNode>("delegateCombine").Single().Parent.Annotation<MethodReference>();
+ if (combineMethod == null || combineMethod.Name != (isAddAccessor ? "Combine" : "Remove"))
+ return false;
+ return combineMethod.DeclaringType.FullName == "System.Delegate";
+ }
+
+ EventDeclaration TransformAutomaticEvents(CustomEventDeclaration ev)
+ {
+ Match m1 = automaticEventPatternV4.Match(ev.AddAccessor);
+ if (!CheckAutomaticEventV4Match(m1, ev, true))
+ return null;
+ Match m2 = automaticEventPatternV4.Match(ev.RemoveAccessor);
+ if (!CheckAutomaticEventV4Match(m2, ev, false))
+ return null;
+ EventDeclaration ed = new EventDeclaration();
+ ev.Attributes.MoveTo(ed.Attributes);
+ foreach (var attr in ev.AddAccessor.Attributes) {
+ attr.AttributeTarget = "method";
+ ed.Attributes.Add(attr.Detach());
+ }
+ ed.ReturnType = ev.ReturnType.Detach();
+ ed.Modifiers = ev.Modifiers;
+ ed.Variables.Add(new VariableInitializer(ev.Name));
+ ed.CopyAnnotationsFrom(ev);
+
+ EventDefinition eventDef = ev.Annotation<EventDefinition>();
+ if (eventDef != null) {
+ FieldDefinition field = eventDef.DeclaringType.Fields.FirstOrDefault(f => f.Name == ev.Name);
+ if (field != null) {
+ ed.AddAnnotation(field);
+ AstBuilder.ConvertAttributes(ed, field, "field");
+ }
+ }
+
+ ev.ReplaceWith(ed);
+ return ed;
+ }
+ #endregion
+
+ #region Destructor
+ static readonly MethodDeclaration destructorPattern = new MethodDeclaration {
+ Attributes = { new Repeat(new AnyNode()) },
+ Modifiers = Modifiers.Any,
+ ReturnType = new PrimitiveType("void"),
+ Name = "Finalize",
+ Body = new BlockStatement {
+ new TryCatchStatement {
+ TryBlock = new AnyNode("body"),
+ FinallyBlock = new BlockStatement {
+ new BaseReferenceExpression().Invoke("Finalize")
+ }
+ }
+ }
+ };
+
+ DestructorDeclaration TransformDestructor(MethodDeclaration methodDef)
+ {
+ Match m = destructorPattern.Match(methodDef);
+ if (m.Success) {
+ DestructorDeclaration dd = new DestructorDeclaration();
+ methodDef.Attributes.MoveTo(dd.Attributes);
+ dd.Modifiers = methodDef.Modifiers & ~(Modifiers.Protected | Modifiers.Override);
+ dd.Body = m.Get<BlockStatement>("body").Single().Detach();
+ dd.Name = AstBuilder.CleanName(context.CurrentType.Name);
+ methodDef.ReplaceWith(dd);
+ return dd;
+ }
+ return null;
+ }
+ #endregion
+
+ #region Try-Catch-Finally
+ static readonly TryCatchStatement tryCatchFinallyPattern = new TryCatchStatement {
+ TryBlock = new BlockStatement {
+ new TryCatchStatement {
+ TryBlock = new AnyNode(),
+ CatchClauses = { new Repeat(new AnyNode()) }
+ }
+ },
+ FinallyBlock = new AnyNode()
+ };
+
+ /// <summary>
+ /// Simplify nested 'try { try {} catch {} } finally {}'.
+ /// This transformation must run after the using/lock tranformations.
+ /// </summary>
+ TryCatchStatement TransformTryCatchFinally(TryCatchStatement tryFinally)
+ {
+ if (tryCatchFinallyPattern.IsMatch(tryFinally)) {
+ TryCatchStatement tryCatch = (TryCatchStatement)tryFinally.TryBlock.Statements.Single();
+ tryFinally.TryBlock = tryCatch.TryBlock.Detach();
+ tryCatch.CatchClauses.MoveTo(tryFinally.CatchClauses);
+ }
+ // Since the tryFinally instance is not changed, we can continue in the visitor as usual, so return null
+ return null;
+ }
+ #endregion
+
+ #region Simplify cascading if-else-if statements
+ static readonly IfElseStatement cascadingIfElsePattern = new IfElseStatement
+ {
+ Condition = new AnyNode(),
+ TrueStatement = new AnyNode(),
+ FalseStatement = new BlockStatement {
+ Statements = {
+ new NamedNode(
+ "nestedIfStatement",
+ new IfElseStatement {
+ Condition = new AnyNode(),
+ TrueStatement = new AnyNode(),
+ FalseStatement = new OptionalNode(new AnyNode())
+ }
+ )
+ }
+ }
+ };
+
+ AstNode SimplifyCascadingIfElseStatements(IfElseStatement node)
+ {
+ Match m = cascadingIfElsePattern.Match(node);
+ if (m.Success) {
+ IfElseStatement elseIf = m.Get<IfElseStatement>("nestedIfStatement").Single();
+ node.FalseStatement = elseIf.Detach();
+ }
+
+ return null;
+ }
+ #endregion
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs b/ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs
new file mode 100644
index 00000000..193c5e69
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs
@@ -0,0 +1,164 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.PatternMatching;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ public class PushNegation: DepthFirstAstVisitor<object, object>, IAstTransform
+ {
+ sealed class LiftedOperator { }
+ /// <summary>
+ /// Annotation for lifted operators that cannot be transformed by PushNegation
+ /// </summary>
+ public static readonly object LiftedOperatorAnnotation = new LiftedOperator();
+
+ public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unary, object data)
+ {
+ // lifted operators can't be transformed
+ if (unary.Annotation<LiftedOperator>() != null || unary.Expression.Annotation<LiftedOperator>() != null)
+ return base.VisitUnaryOperatorExpression(unary, data);
+
+ // Remove double negation
+ // !!a
+ if (unary.Operator == UnaryOperatorType.Not &&
+ unary.Expression is UnaryOperatorExpression &&
+ (unary.Expression as UnaryOperatorExpression).Operator == UnaryOperatorType.Not)
+ {
+ AstNode newNode = (unary.Expression as UnaryOperatorExpression).Expression;
+ unary.ReplaceWith(newNode);
+ return newNode.AcceptVisitor(this, data);
+ }
+
+ // Push through binary operation
+ // !((a) op (b))
+ BinaryOperatorExpression binaryOp = unary.Expression as BinaryOperatorExpression;
+ if (unary.Operator == UnaryOperatorType.Not && binaryOp != null) {
+ bool successful = true;
+ switch (binaryOp.Operator) {
+ case BinaryOperatorType.Equality:
+ binaryOp.Operator = BinaryOperatorType.InEquality;
+ break;
+ case BinaryOperatorType.InEquality:
+ binaryOp.Operator = BinaryOperatorType.Equality;
+ break;
+ case BinaryOperatorType.GreaterThan: // TODO: these are invalid for floats (stupid NaN)
+ binaryOp.Operator = BinaryOperatorType.LessThanOrEqual;
+ break;
+ case BinaryOperatorType.GreaterThanOrEqual:
+ binaryOp.Operator = BinaryOperatorType.LessThan;
+ break;
+ case BinaryOperatorType.LessThanOrEqual:
+ binaryOp.Operator = BinaryOperatorType.GreaterThan;
+ break;
+ case BinaryOperatorType.LessThan:
+ binaryOp.Operator = BinaryOperatorType.GreaterThanOrEqual;
+ break;
+ default:
+ successful = false;
+ break;
+ }
+ if (successful) {
+ unary.ReplaceWith(binaryOp);
+ return binaryOp.AcceptVisitor(this, data);
+ }
+
+ successful = true;
+ switch (binaryOp.Operator) {
+ case BinaryOperatorType.ConditionalAnd:
+ binaryOp.Operator = BinaryOperatorType.ConditionalOr;
+ break;
+ case BinaryOperatorType.ConditionalOr:
+ binaryOp.Operator = BinaryOperatorType.ConditionalAnd;
+ break;
+ default:
+ successful = false;
+ break;
+ }
+ if (successful) {
+ binaryOp.Left.ReplaceWith(e => new UnaryOperatorExpression(UnaryOperatorType.Not, e));
+ binaryOp.Right.ReplaceWith(e => new UnaryOperatorExpression(UnaryOperatorType.Not, e));
+ unary.ReplaceWith(binaryOp);
+ return binaryOp.AcceptVisitor(this, data);
+ }
+ }
+ return base.VisitUnaryOperatorExpression(unary, data);
+ }
+
+ readonly static AstNode asCastIsNullPattern = new BinaryOperatorExpression(
+ new AnyNode("expr").ToExpression().CastAs(new AnyNode("type")),
+ BinaryOperatorType.Equality,
+ new NullReferenceExpression()
+ );
+
+ readonly static AstNode asCastIsNotNullPattern = new BinaryOperatorExpression(
+ new AnyNode("expr").ToExpression().CastAs(new AnyNode("type")),
+ BinaryOperatorType.InEquality,
+ new NullReferenceExpression()
+ );
+
+ public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data)
+ {
+ // lifted operators can't be transformed
+ if (binaryOperatorExpression.Annotation<LiftedOperator>() != null)
+ return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data);
+
+ BinaryOperatorType op = binaryOperatorExpression.Operator;
+ bool? rightOperand = null;
+ if (binaryOperatorExpression.Right is PrimitiveExpression)
+ rightOperand = ((PrimitiveExpression)binaryOperatorExpression.Right).Value as bool?;
+ if (op == BinaryOperatorType.Equality && rightOperand == true || op == BinaryOperatorType.InEquality && rightOperand == false) {
+ // 'b == true' or 'b != false' is useless
+ binaryOperatorExpression.Left.AcceptVisitor(this, data);
+ binaryOperatorExpression.ReplaceWith(binaryOperatorExpression.Left);
+ return null;
+ } else if (op == BinaryOperatorType.Equality && rightOperand == false || op == BinaryOperatorType.InEquality && rightOperand == true) {
+ // 'b == false' or 'b != true' is a negation:
+ Expression left = binaryOperatorExpression.Left;
+ left.Remove();
+ UnaryOperatorExpression uoe = new UnaryOperatorExpression(UnaryOperatorType.Not, left);
+ binaryOperatorExpression.ReplaceWith(uoe);
+ return uoe.AcceptVisitor(this, data);
+ } else {
+ bool negate = false;
+ Match m = asCastIsNotNullPattern.Match(binaryOperatorExpression);
+ if (!m.Success) {
+ m = asCastIsNullPattern.Match(binaryOperatorExpression);
+ negate = true;
+ }
+ if (m.Success) {
+ Expression expr = m.Get<Expression>("expr").Single().Detach().IsType(m.Get<AstType>("type").Single().Detach());
+ if (negate)
+ expr = new UnaryOperatorExpression(UnaryOperatorType.Not, expr);
+ binaryOperatorExpression.ReplaceWith(expr);
+ return expr.AcceptVisitor(this, data);
+ } else {
+ return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data);
+ }
+ }
+ }
+ void IAstTransform.Run(AstNode node)
+ {
+ node.AcceptVisitor(this, null);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs b/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs
new file mode 100644
index 00000000..6a3f8f97
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs
@@ -0,0 +1,356 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using ICSharpCode.NRefactory.PatternMatching;
+using Mono.Cecil;
+using Ast = ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.CSharp;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ /// <summary>
+ /// Replaces method calls with the appropriate operator expressions.
+ /// Also simplifies "x = x op y" into "x op= y" where possible.
+ /// </summary>
+ public class ReplaceMethodCallsWithOperators : DepthFirstAstVisitor<object, object>, IAstTransform
+ {
+ static readonly MemberReferenceExpression typeHandleOnTypeOfPattern = new MemberReferenceExpression {
+ Target = new Choice {
+ new TypeOfExpression(new AnyNode()),
+ new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.RefType, Arguments = { new AnyNode() } }
+ },
+ MemberName = "TypeHandle"
+ };
+
+ DecompilerContext context;
+
+ public ReplaceMethodCallsWithOperators(DecompilerContext context)
+ {
+ this.context = context;
+ }
+
+ public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
+ {
+ base.VisitInvocationExpression(invocationExpression, data);
+ ProcessInvocationExpression(invocationExpression);
+ return null;
+ }
+
+ internal static void ProcessInvocationExpression(InvocationExpression invocationExpression)
+ {
+ MethodReference methodRef = invocationExpression.Annotation<MethodReference>();
+ if (methodRef == null)
+ return;
+ var arguments = invocationExpression.Arguments.ToArray();
+
+ // Reduce "String.Concat(a, b)" to "a + b"
+ if (methodRef.Name == "Concat" && methodRef.DeclaringType.FullName == "System.String" && arguments.Length >= 2)
+ {
+ invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression
+ Expression expr = arguments[0];
+ for (int i = 1; i < arguments.Length; i++) {
+ expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Add, arguments[i]);
+ }
+ invocationExpression.ReplaceWith(expr);
+ return;
+ }
+
+ switch (methodRef.FullName) {
+ case "System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)":
+ if (arguments.Length == 1) {
+ if (typeHandleOnTypeOfPattern.IsMatch(arguments[0])) {
+ invocationExpression.ReplaceWith(((MemberReferenceExpression)arguments[0]).Target);
+ return;
+ }
+ }
+ break;
+ case "System.Reflection.FieldInfo System.Reflection.FieldInfo::GetFieldFromHandle(System.RuntimeFieldHandle)":
+ if (arguments.Length == 1) {
+ MemberReferenceExpression mre = arguments[0] as MemberReferenceExpression;
+ if (mre != null && mre.MemberName == "FieldHandle" && mre.Target.Annotation<LdTokenAnnotation>() != null) {
+ invocationExpression.ReplaceWith(mre.Target);
+ return;
+ }
+ }
+ break;
+ case "System.Reflection.FieldInfo System.Reflection.FieldInfo::GetFieldFromHandle(System.RuntimeFieldHandle,System.RuntimeTypeHandle)":
+ if (arguments.Length == 2) {
+ MemberReferenceExpression mre1 = arguments[0] as MemberReferenceExpression;
+ MemberReferenceExpression mre2 = arguments[1] as MemberReferenceExpression;
+ if (mre1 != null && mre1.MemberName == "FieldHandle" && mre1.Target.Annotation<LdTokenAnnotation>() != null) {
+ if (mre2 != null && mre2.MemberName == "TypeHandle" && mre2.Target is TypeOfExpression) {
+ Expression oldArg = ((InvocationExpression)mre1.Target).Arguments.Single();
+ FieldReference field = oldArg.Annotation<FieldReference>();
+ if (field != null) {
+ AstType declaringType = ((TypeOfExpression)mre2.Target).Type.Detach();
+ oldArg.ReplaceWith(declaringType.Member(field.Name).WithAnnotation(field));
+ invocationExpression.ReplaceWith(mre1.Target);
+ return;
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ BinaryOperatorType? bop = GetBinaryOperatorTypeFromMetadataName(methodRef.Name);
+ if (bop != null && arguments.Length == 2) {
+ invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression
+ invocationExpression.ReplaceWith(
+ new BinaryOperatorExpression(arguments[0], bop.Value, arguments[1]).WithAnnotation(methodRef)
+ );
+ return;
+ }
+ UnaryOperatorType? uop = GetUnaryOperatorTypeFromMetadataName(methodRef.Name);
+ if (uop != null && arguments.Length == 1) {
+ arguments[0].Remove(); // detach argument
+ invocationExpression.ReplaceWith(
+ new UnaryOperatorExpression(uop.Value, arguments[0]).WithAnnotation(methodRef)
+ );
+ return;
+ }
+ if (methodRef.Name == "op_Explicit" && arguments.Length == 1) {
+ arguments[0].Remove(); // detach argument
+ invocationExpression.ReplaceWith(
+ arguments[0].CastTo(AstBuilder.ConvertType(methodRef.ReturnType, methodRef.MethodReturnType))
+ .WithAnnotation(methodRef)
+ );
+ return;
+ }
+ if (methodRef.Name == "op_Implicit" && arguments.Length == 1) {
+ invocationExpression.ReplaceWith(arguments[0]);
+ return;
+ }
+ if (methodRef.Name == "op_True" && arguments.Length == 1 && invocationExpression.Role == Roles.Condition) {
+ invocationExpression.ReplaceWith(arguments[0]);
+ return;
+ }
+
+ return;
+ }
+
+ static BinaryOperatorType? GetBinaryOperatorTypeFromMetadataName(string name)
+ {
+ switch (name) {
+ case "op_Addition":
+ return BinaryOperatorType.Add;
+ case "op_Subtraction":
+ return BinaryOperatorType.Subtract;
+ case "op_Multiply":
+ return BinaryOperatorType.Multiply;
+ case "op_Division":
+ return BinaryOperatorType.Divide;
+ case "op_Modulus":
+ return BinaryOperatorType.Modulus;
+ case "op_BitwiseAnd":
+ return BinaryOperatorType.BitwiseAnd;
+ case "op_BitwiseOr":
+ return BinaryOperatorType.BitwiseOr;
+ case "op_ExclusiveOr":
+ return BinaryOperatorType.ExclusiveOr;
+ case "op_LeftShift":
+ return BinaryOperatorType.ShiftLeft;
+ case "op_RightShift":
+ return BinaryOperatorType.ShiftRight;
+ case "op_Equality":
+ return BinaryOperatorType.Equality;
+ case "op_Inequality":
+ return BinaryOperatorType.InEquality;
+ case "op_LessThan":
+ return BinaryOperatorType.LessThan;
+ case "op_LessThanOrEqual":
+ return BinaryOperatorType.LessThanOrEqual;
+ case "op_GreaterThan":
+ return BinaryOperatorType.GreaterThan;
+ case "op_GreaterThanOrEqual":
+ return BinaryOperatorType.GreaterThanOrEqual;
+ default:
+ return null;
+ }
+ }
+
+ static UnaryOperatorType? GetUnaryOperatorTypeFromMetadataName(string name)
+ {
+ switch (name) {
+ case "op_LogicalNot":
+ return UnaryOperatorType.Not;
+ case "op_OnesComplement":
+ return UnaryOperatorType.BitNot;
+ case "op_UnaryNegation":
+ return UnaryOperatorType.Minus;
+ case "op_UnaryPlus":
+ return UnaryOperatorType.Plus;
+ case "op_Increment":
+ return UnaryOperatorType.Increment;
+ case "op_Decrement":
+ return UnaryOperatorType.Decrement;
+ default:
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// This annotation is used to convert a compound assignment "a += 2;" or increment operator "a++;"
+ /// back to the original "a = a + 2;". This is sometimes necessary when the checked/unchecked semantics
+ /// cannot be guaranteed otherwise (see CheckedUnchecked.ForWithCheckedInitializerAndUncheckedIterator test)
+ /// </summary>
+ public class RestoreOriginalAssignOperatorAnnotation
+ {
+ readonly BinaryOperatorExpression binaryOperatorExpression;
+
+ public RestoreOriginalAssignOperatorAnnotation(BinaryOperatorExpression binaryOperatorExpression)
+ {
+ this.binaryOperatorExpression = binaryOperatorExpression;
+ }
+
+ public AssignmentExpression Restore(Expression expression)
+ {
+ expression.RemoveAnnotations<RestoreOriginalAssignOperatorAnnotation>();
+ AssignmentExpression assign = expression as AssignmentExpression;
+ if (assign == null) {
+ UnaryOperatorExpression uoe = (UnaryOperatorExpression)expression;
+ assign = new AssignmentExpression(uoe.Expression.Detach(), new PrimitiveExpression(1));
+ } else {
+ assign.Operator = AssignmentOperatorType.Assign;
+ }
+ binaryOperatorExpression.Right = assign.Right.Detach();
+ assign.Right = binaryOperatorExpression;
+ return assign;
+ }
+ }
+
+ public override object VisitAssignmentExpression(AssignmentExpression assignment, object data)
+ {
+ base.VisitAssignmentExpression(assignment, data);
+ // Combine "x = x op y" into "x op= y"
+ BinaryOperatorExpression binary = assignment.Right as BinaryOperatorExpression;
+ if (binary != null && assignment.Operator == AssignmentOperatorType.Assign) {
+ if (CanConvertToCompoundAssignment(assignment.Left) && assignment.Left.IsMatch(binary.Left)) {
+ assignment.Operator = GetAssignmentOperatorForBinaryOperator(binary.Operator);
+ if (assignment.Operator != AssignmentOperatorType.Assign) {
+ // If we found a shorter operator, get rid of the BinaryOperatorExpression:
+ assignment.CopyAnnotationsFrom(binary);
+ assignment.Right = binary.Right;
+ assignment.AddAnnotation(new RestoreOriginalAssignOperatorAnnotation(binary));
+ }
+ }
+ }
+ if (context.Settings.IntroduceIncrementAndDecrement && (assignment.Operator == AssignmentOperatorType.Add || assignment.Operator == AssignmentOperatorType.Subtract)) {
+ // detect increment/decrement
+ if (assignment.Right.IsMatch(new PrimitiveExpression(1))) {
+ // only if it's not a custom operator
+ if (assignment.Annotation<MethodReference>() == null) {
+ UnaryOperatorType type;
+ // When the parent is an expression statement, pre- or post-increment doesn't matter;
+ // so we can pick post-increment which is more commonly used (for (int i = 0; i < x; i++))
+ if (assignment.Parent is ExpressionStatement)
+ type = (assignment.Operator == AssignmentOperatorType.Add) ? UnaryOperatorType.PostIncrement : UnaryOperatorType.PostDecrement;
+ else
+ type = (assignment.Operator == AssignmentOperatorType.Add) ? UnaryOperatorType.Increment : UnaryOperatorType.Decrement;
+ assignment.ReplaceWith(new UnaryOperatorExpression(type, assignment.Left.Detach()).CopyAnnotationsFrom(assignment));
+ }
+ }
+ }
+ return null;
+ }
+
+ public static AssignmentOperatorType GetAssignmentOperatorForBinaryOperator(BinaryOperatorType bop)
+ {
+ switch (bop) {
+ case BinaryOperatorType.Add:
+ return AssignmentOperatorType.Add;
+ case BinaryOperatorType.Subtract:
+ return AssignmentOperatorType.Subtract;
+ case BinaryOperatorType.Multiply:
+ return AssignmentOperatorType.Multiply;
+ case BinaryOperatorType.Divide:
+ return AssignmentOperatorType.Divide;
+ case BinaryOperatorType.Modulus:
+ return AssignmentOperatorType.Modulus;
+ case BinaryOperatorType.ShiftLeft:
+ return AssignmentOperatorType.ShiftLeft;
+ case BinaryOperatorType.ShiftRight:
+ return AssignmentOperatorType.ShiftRight;
+ case BinaryOperatorType.BitwiseAnd:
+ return AssignmentOperatorType.BitwiseAnd;
+ case BinaryOperatorType.BitwiseOr:
+ return AssignmentOperatorType.BitwiseOr;
+ case BinaryOperatorType.ExclusiveOr:
+ return AssignmentOperatorType.ExclusiveOr;
+ default:
+ return AssignmentOperatorType.Assign;
+ }
+ }
+
+ static bool CanConvertToCompoundAssignment(Expression left)
+ {
+ MemberReferenceExpression mre = left as MemberReferenceExpression;
+ if (mre != null)
+ return IsWithoutSideEffects(mre.Target);
+ IndexerExpression ie = left as IndexerExpression;
+ if (ie != null)
+ return IsWithoutSideEffects(ie.Target) && ie.Arguments.All(IsWithoutSideEffects);
+ UnaryOperatorExpression uoe = left as UnaryOperatorExpression;
+ if (uoe != null && uoe.Operator == UnaryOperatorType.Dereference)
+ return IsWithoutSideEffects(uoe.Expression);
+ return IsWithoutSideEffects(left);
+ }
+
+ static bool IsWithoutSideEffects(Expression left)
+ {
+ return left is ThisReferenceExpression || left is IdentifierExpression || left is TypeReferenceExpression || left is BaseReferenceExpression;
+ }
+
+ static readonly Expression getMethodOrConstructorFromHandlePattern =
+ new TypePattern(typeof(MethodBase)).ToType().Invoke(
+ "GetMethodFromHandle",
+ new NamedNode("ldtokenNode", new LdTokenPattern("method")).ToExpression().Member("MethodHandle"),
+ new OptionalNode(new TypeOfExpression(new AnyNode("declaringType")).Member("TypeHandle"))
+ ).CastTo(new Choice {
+ new TypePattern(typeof(MethodInfo)),
+ new TypePattern(typeof(ConstructorInfo))
+ });
+
+ public override object VisitCastExpression(CastExpression castExpression, object data)
+ {
+ base.VisitCastExpression(castExpression, data);
+ // Handle methodof
+ Match m = getMethodOrConstructorFromHandlePattern.Match(castExpression);
+ if (m.Success) {
+ MethodReference method = m.Get<AstNode>("method").Single().Annotation<MethodReference>();
+ if (m.Has("declaringType")) {
+ Expression newNode = m.Get<AstType>("declaringType").Single().Detach().Member(method.Name);
+ newNode = newNode.Invoke(method.Parameters.Select(p => new TypeReferenceExpression(AstBuilder.ConvertType(p.ParameterType, p))));
+ newNode.AddAnnotation(method);
+ m.Get<AstNode>("method").Single().ReplaceWith(newNode);
+ }
+ castExpression.ReplaceWith(m.Get<AstNode>("ldtokenNode").Single());
+ }
+ return null;
+ }
+
+ void IAstTransform.Run(AstNode node)
+ {
+ node.AcceptVisitor(this, null);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs b/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs
new file mode 100644
index 00000000..3091a109
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs
@@ -0,0 +1,65 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Threading;
+using ICSharpCode.NRefactory.CSharp;
+
+namespace ICSharpCode.Decompiler.Ast.Transforms
+{
+ public interface IAstTransform
+ {
+ void Run(AstNode compilationUnit);
+ }
+
+ public static class TransformationPipeline
+ {
+ public static IAstTransform[] CreatePipeline(DecompilerContext context)
+ {
+ return new IAstTransform[] {
+ new PushNegation(),
+ new DelegateConstruction(context),
+ new PatternStatementTransform(context),
+ new ReplaceMethodCallsWithOperators(context),
+ new IntroduceUnsafeModifier(),
+ new AddCheckedBlocks(),
+ new DeclareVariables(context), // should run after most transforms that modify statements
+ new ConvertConstructorCallIntoInitializer(), // must run after DeclareVariables
+ new DecimalConstantTransform(),
+ new IntroduceUsingDeclarations(context),
+ new IntroduceExtensionMethods(context), // must run after IntroduceUsingDeclarations
+ new IntroduceQueryExpressions(context), // must run after IntroduceExtensionMethods
+ new CombineQueryExpressions(context),
+ new FlattenSwitchBlocks(),
+ };
+ }
+
+ public static void RunTransformationsUntil(AstNode node, Predicate<IAstTransform> abortCondition, DecompilerContext context)
+ {
+ if (node == null)
+ return;
+
+ foreach (var transform in CreatePipeline(context)) {
+ context.CancellationToken.ThrowIfCancellationRequested();
+ if (abortCondition != null && abortCondition(transform))
+ return;
+ transform.Run(node);
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs b/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs
new file mode 100644
index 00000000..e4131904
--- /dev/null
+++ b/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs
@@ -0,0 +1,528 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.Ast
+{
+ public static class TypesHierarchyHelpers
+ {
+ public static bool IsBaseType(TypeDefinition baseType, TypeDefinition derivedType, bool resolveTypeArguments)
+ {
+ if (resolveTypeArguments)
+ return BaseTypes(derivedType).Any(t => t.Item == baseType);
+ else {
+ var comparableBaseType = baseType.Resolve();
+ if (comparableBaseType == null)
+ return false;
+ while (derivedType.BaseType != null) {
+ var resolvedBaseType = derivedType.BaseType.Resolve();
+ if (resolvedBaseType == null)
+ return false;
+ if (comparableBaseType == resolvedBaseType)
+ return true;
+ derivedType = resolvedBaseType;
+ }
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Determines whether one method overrides or hides another method.
+ /// </summary>
+ /// <param name="parentMethod">The method declared in a base type.</param>
+ /// <param name="childMethod">The method declared in a derived type.</param>
+ /// <returns>true if <paramref name="childMethod"/> hides or overrides <paramref name="parentMethod"/>,
+ /// otherwise false.</returns>
+ public static bool IsBaseMethod(MethodDefinition parentMethod, MethodDefinition childMethod)
+ {
+ if (parentMethod == null)
+ throw new ArgumentNullException("parentMethod");
+ if (childMethod == null)
+ throw new ArgumentNullException("childMethod");
+
+ if (parentMethod.Name != childMethod.Name)
+ return false;
+
+ if (parentMethod.HasParameters || childMethod.HasParameters)
+ if (!parentMethod.HasParameters || !childMethod.HasParameters || parentMethod.Parameters.Count != childMethod.Parameters.Count)
+ return false;
+
+ return FindBaseMethods(childMethod).Any(m => m == parentMethod);// || (parentMethod.HasGenericParameters && m.);
+ }
+
+ /// <summary>
+ /// Determines whether a property overrides or hides another property.
+ /// </summary>
+ /// <param name="parentProperty">The property declared in a base type.</param>
+ /// <param name="childProperty">The property declared in a derived type.</param>
+ /// <returns>true if the <paramref name="childProperty"/> hides or overrides <paramref name="parentProperty"/>,
+ /// otherwise false.</returns>
+ public static bool IsBaseProperty(PropertyDefinition parentProperty, PropertyDefinition childProperty)
+ {
+ if (parentProperty == null)
+ throw new ArgumentNullException("parentProperty");
+ if (childProperty == null)
+ throw new ArgumentNullException("childProperty");
+
+ if (parentProperty.Name != childProperty.Name)
+ return false;
+
+ if (parentProperty.HasParameters || childProperty.HasParameters)
+ if (!parentProperty.HasParameters || !childProperty.HasParameters || parentProperty.Parameters.Count != childProperty.Parameters.Count)
+ return false;
+
+ return FindBaseProperties(childProperty).Any(m => m == parentProperty);
+ }
+
+ public static bool IsBaseEvent(EventDefinition parentEvent, EventDefinition childEvent)
+ {
+ if (parentEvent.Name != childEvent.Name)
+ return false;
+
+ return FindBaseEvents(childEvent).Any(m => m == parentEvent);
+ }
+
+ /// <summary>
+ /// Finds all methods from base types overridden or hidden by the specified method.
+ /// </summary>
+ /// <param name="method">The method which overrides or hides methods from base types.</param>
+ /// <returns>Methods overriden or hidden by the specified method.</returns>
+ public static IEnumerable<MethodDefinition> FindBaseMethods(MethodDefinition method)
+ {
+ if (method == null)
+ throw new ArgumentNullException("method");
+
+ var typeContext = CreateGenericContext(method.DeclaringType);
+ var gMethod = typeContext.ApplyTo(method);
+
+ foreach (var baseType in BaseTypes(method.DeclaringType))
+ foreach (var baseMethod in baseType.Item.Methods)
+ if (MatchMethod(baseType.ApplyTo(baseMethod), gMethod) && IsVisibleFromDerived(baseMethod, method.DeclaringType)) {
+ yield return baseMethod;
+ if (baseMethod.IsNewSlot == baseMethod.IsVirtual)
+ yield break;
+ }
+ }
+
+ /// <summary>
+ /// Finds all properties from base types overridden or hidden by the specified property.
+ /// </summary>
+ /// <param name="property">The property which overrides or hides properties from base types.</param>
+ /// <returns>Properties overriden or hidden by the specified property.</returns>
+ public static IEnumerable<PropertyDefinition> FindBaseProperties(PropertyDefinition property)
+ {
+ if (property == null)
+ throw new ArgumentNullException("property");
+
+ if ((property.GetMethod ?? property.SetMethod).HasOverrides)
+ yield break;
+
+ var typeContext = CreateGenericContext(property.DeclaringType);
+ var gProperty = typeContext.ApplyTo(property);
+ bool isIndexer = property.IsIndexer();
+
+ foreach (var baseType in BaseTypes(property.DeclaringType))
+ foreach (var baseProperty in baseType.Item.Properties)
+ if (MatchProperty(baseType.ApplyTo(baseProperty), gProperty)
+ && IsVisibleFromDerived(baseProperty, property.DeclaringType)) {
+ if (isIndexer != baseProperty.IsIndexer())
+ continue;
+ yield return baseProperty;
+ var anyPropertyAccessor = baseProperty.GetMethod ?? baseProperty.SetMethod;
+ if (anyPropertyAccessor.IsNewSlot == anyPropertyAccessor.IsVirtual)
+ yield break;
+ }
+ }
+
+ public static IEnumerable<EventDefinition> FindBaseEvents(EventDefinition eventDef)
+ {
+ if (eventDef == null)
+ throw new ArgumentNullException("eventDef");
+
+ var typeContext = CreateGenericContext(eventDef.DeclaringType);
+ var gEvent = typeContext.ApplyTo(eventDef);
+
+ foreach (var baseType in BaseTypes(eventDef.DeclaringType))
+ foreach (var baseEvent in baseType.Item.Events)
+ if (MatchEvent(baseType.ApplyTo(baseEvent), gEvent) && IsVisibleFromDerived(baseEvent, eventDef.DeclaringType)) {
+ yield return baseEvent;
+ var anyEventAccessor = baseEvent.AddMethod ?? baseEvent.RemoveMethod;
+ if (anyEventAccessor.IsNewSlot == anyEventAccessor.IsVirtual)
+ yield break;
+ }
+
+ }
+
+ /// <summary>
+ /// Determinates whether member of the base type is visible from a derived type.
+ /// </summary>
+ /// <param name="baseMember">The member which visibility is checked.</param>
+ /// <param name="derivedType">The derived type.</param>
+ /// <returns>true if the member is visible from derived type, othewise false.</returns>
+ public static bool IsVisibleFromDerived(IMemberDefinition baseMember, TypeDefinition derivedType)
+ {
+ if (baseMember == null)
+ throw new ArgumentNullException("baseMember");
+ if (derivedType == null)
+ throw new ArgumentNullException("derivedType");
+
+ MethodAttributes attrs = GetAccessAttributes(baseMember) & MethodAttributes.MemberAccessMask;
+ if (attrs == MethodAttributes.Private)
+ return false;
+
+ if (baseMember.DeclaringType.Module == derivedType.Module)
+ return true;
+
+ if (attrs == MethodAttributes.Assembly || attrs == MethodAttributes.FamANDAssem) {
+ var derivedTypeAsm = derivedType.Module.Assembly;
+ var asm = baseMember.DeclaringType.Module.Assembly;
+
+ if (asm.HasCustomAttributes) {
+ var attributes = asm.CustomAttributes
+ .Where(attr => attr.AttributeType.FullName == "System.Runtime.CompilerServices.InternalsVisibleToAttribute");
+ foreach (var attribute in attributes) {
+ string assemblyName = attribute.ConstructorArguments[0].Value as string;
+ assemblyName = assemblyName.Split(',')[0]; // strip off any public key info
+ if (assemblyName == derivedTypeAsm.Name.Name)
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ static MethodAttributes GetAccessAttributes(IMemberDefinition member)
+ {
+ var fld = member as FieldDefinition;
+ if (fld != null)
+ return (MethodAttributes)fld.Attributes;
+
+ var method = member as MethodDefinition;
+ if (method != null)
+ return method.Attributes;
+
+ var prop = member as PropertyDefinition;
+ if (prop != null) {
+ return (prop.GetMethod ?? prop.SetMethod).Attributes;
+ }
+
+ var evnt = member as EventDefinition;
+ if (evnt != null) {
+ return (evnt.AddMethod ?? evnt.RemoveMethod).Attributes;
+ }
+
+ var nestedType = member as TypeDefinition;
+ if (nestedType != null) {
+ if (nestedType.IsNestedPrivate)
+ return MethodAttributes.Private;
+ if (nestedType.IsNestedAssembly || nestedType.IsNestedFamilyAndAssembly)
+ return MethodAttributes.Assembly;
+ return MethodAttributes.Public;
+ }
+
+ throw new NotSupportedException();
+ }
+
+ static bool MatchMethod(GenericContext<MethodDefinition> candidate, GenericContext<MethodDefinition> method)
+ {
+ var mCandidate = candidate.Item;
+ var mMethod = method.Item;
+ if (mCandidate.Name != mMethod.Name)
+ return false;
+
+ if (mCandidate.HasOverrides)
+ return false;
+
+ if (mCandidate.IsSpecialName != method.Item.IsSpecialName)
+ return false;
+
+ if (mCandidate.HasGenericParameters || mMethod.HasGenericParameters) {
+ if (!mCandidate.HasGenericParameters || !mMethod.HasGenericParameters || mCandidate.GenericParameters.Count != mMethod.GenericParameters.Count)
+ return false;
+ }
+
+ if (mCandidate.HasParameters || mMethod.HasParameters) {
+ if (!mCandidate.HasParameters || !mMethod.HasParameters || mCandidate.Parameters.Count != mMethod.Parameters.Count)
+ return false;
+
+ for (int index = 0; index < mCandidate.Parameters.Count; index++) {
+ if (!MatchParameters(candidate.ApplyTo(mCandidate.Parameters[index]), method.ApplyTo(mMethod.Parameters[index])))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static bool MatchInterfaceMethod(MethodDefinition candidate, MethodDefinition method, TypeReference interfaceContextType)
+ {
+ var candidateContext = CreateGenericContext(candidate.DeclaringType);
+ var gCandidate = candidateContext.ApplyTo(candidate);
+
+ if (interfaceContextType is GenericInstanceType) {
+ var methodContext = new GenericContext<TypeDefinition>(interfaceContextType.Resolve(), ((GenericInstanceType)interfaceContextType).GenericArguments);
+ var gMethod = methodContext.ApplyTo(method);
+ return MatchMethod(gCandidate, gMethod);
+ } else {
+ var methodContext = CreateGenericContext(interfaceContextType.Resolve());
+ var gMethod = candidateContext.ApplyTo(method);
+ return MatchMethod(gCandidate, gMethod);
+ }
+ }
+
+ static bool MatchProperty(GenericContext<PropertyDefinition> candidate, GenericContext<PropertyDefinition> property)
+ {
+ var mCandidate = candidate.Item;
+ var mProperty = property.Item;
+ if (mCandidate.Name != mProperty.Name)
+ return false;
+
+ if ((mCandidate.GetMethod ?? mCandidate.SetMethod).HasOverrides)
+ return false;
+
+ if (mCandidate.HasParameters || mProperty.HasParameters) {
+ if (!mCandidate.HasParameters || !mProperty.HasParameters || mCandidate.Parameters.Count != mProperty.Parameters.Count)
+ return false;
+
+ for (int index = 0; index < mCandidate.Parameters.Count; index++) {
+ if (!MatchParameters(candidate.ApplyTo(mCandidate.Parameters[index]), property.ApplyTo(mProperty.Parameters[index])))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ static bool MatchEvent(GenericContext<EventDefinition> candidate, GenericContext<EventDefinition> ev)
+ {
+ var mCandidate = candidate.Item;
+ var mEvent = ev.Item;
+ if (mCandidate.Name != mEvent.Name)
+ return false;
+
+ if ((mCandidate.AddMethod ?? mCandidate.RemoveMethod).HasOverrides)
+ return false;
+
+ if (!IsSameType(candidate.ResolveWithContext(mCandidate.EventType), ev.ResolveWithContext(mEvent.EventType)))
+ return false;
+
+ return true;
+ }
+
+ static bool MatchParameters(GenericContext<ParameterDefinition> baseParameterType, GenericContext<ParameterDefinition> parameterType)
+ {
+ if (baseParameterType.Item.IsIn != parameterType.Item.IsIn ||
+ baseParameterType.Item.IsOut != parameterType.Item.IsOut)
+ return false;
+ var baseParam = baseParameterType.ResolveWithContext(baseParameterType.Item.ParameterType);
+ var param = parameterType.ResolveWithContext(parameterType.Item.ParameterType);
+ return IsSameType(baseParam, param);
+ }
+
+ static bool IsSameType(TypeReference tr1, TypeReference tr2)
+ {
+ if (tr1 == tr2)
+ return true;
+ if (tr1 == null || tr2 == null)
+ return false;
+
+ if (tr1.GetType() != tr2.GetType())
+ return false;
+
+ if (tr1.Name == tr2.Name && tr1.FullName == tr2.FullName)
+ return true;
+
+ return false;
+ }
+
+ static IEnumerable<GenericContext<TypeDefinition>> BaseTypes(TypeDefinition type)
+ {
+ return BaseTypes(CreateGenericContext(type));
+ }
+
+ static IEnumerable<GenericContext<TypeDefinition>> BaseTypes(GenericContext<TypeDefinition> type)
+ {
+ while (type.Item.BaseType != null) {
+ var baseType = type.Item.BaseType;
+ var genericBaseType = baseType as GenericInstanceType;
+ if (genericBaseType != null) {
+ type = new GenericContext<TypeDefinition>(genericBaseType.ResolveOrThrow(),
+ genericBaseType.GenericArguments.Select(t => type.ResolveWithContext(t)));
+ } else
+ type = new GenericContext<TypeDefinition>(baseType.ResolveOrThrow());
+ yield return type;
+ }
+ }
+
+ static GenericContext<TypeDefinition> CreateGenericContext(TypeDefinition type)
+ {
+ return type.HasGenericParameters
+ ? new GenericContext<TypeDefinition>(type, type.GenericParameters)
+ : new GenericContext<TypeDefinition>(type);
+ }
+
+ struct GenericContext<T> where T : class
+ {
+ static readonly ReadOnlyCollection<TypeReference> Empty = new ReadOnlyCollection<TypeReference>(new List<TypeReference>());
+
+ static readonly GenericParameter UnresolvedGenericTypeParameter =
+ new DummyGenericParameterProvider(false).DummyParameter;
+
+ static readonly GenericParameter UnresolvedGenericMethodParameter =
+ new DummyGenericParameterProvider(true).DummyParameter;
+
+ public readonly T Item;
+ public readonly ReadOnlyCollection<TypeReference> TypeArguments;
+
+ public GenericContext(T item)
+ {
+ if (item == null)
+ throw new ArgumentNullException("item");
+
+ Item = item;
+ TypeArguments = Empty;
+ }
+
+ public GenericContext(T item, IEnumerable<TypeReference> typeArguments)
+ {
+ if (item == null)
+ throw new ArgumentNullException("item");
+
+ Item = item;
+ var list = new List<TypeReference>();
+ foreach (var arg in typeArguments) {
+ var resolved = arg != null ? arg.Resolve() : arg;
+ list.Add(resolved != null ? resolved : arg);
+ }
+ TypeArguments = new ReadOnlyCollection<TypeReference>(list);
+ }
+
+ GenericContext(T item, ReadOnlyCollection<TypeReference> typeArguments)
+ {
+ Item = item;
+ TypeArguments = typeArguments;
+ }
+
+ public TypeReference ResolveWithContext(TypeReference type)
+ {
+ var genericParameter = type as GenericParameter;
+ if (genericParameter != null)
+ if (genericParameter.Owner.GenericParameterType == GenericParameterType.Type)
+ return TypeArguments[genericParameter.Position];
+ else
+ return genericParameter.Owner.GenericParameterType == GenericParameterType.Type
+ ? UnresolvedGenericTypeParameter : UnresolvedGenericMethodParameter;
+ var typeSpecification = type as TypeSpecification;
+ if (typeSpecification != null) {
+ var resolvedElementType = ResolveWithContext(typeSpecification.ElementType);
+ return ReplaceElementType(typeSpecification, resolvedElementType);
+ }
+ return type.ResolveOrThrow();
+ }
+
+ TypeReference ReplaceElementType(TypeSpecification ts, TypeReference newElementType)
+ {
+ var arrayType = ts as ArrayType;
+ if (arrayType != null) {
+ if (newElementType == arrayType.ElementType)
+ return arrayType;
+ var newArrayType = new ArrayType(newElementType, arrayType.Rank);
+ for (int dimension = 0; dimension < arrayType.Rank; dimension++)
+ newArrayType.Dimensions[dimension] = arrayType.Dimensions[dimension];
+ return newArrayType;
+ }
+ var byReferenceType = ts as ByReferenceType;
+ if (byReferenceType != null) {
+ return new ByReferenceType(newElementType);
+ }
+ // TODO: should we throw an exception instead calling Resolve method?
+ return ts.ResolveOrThrow();
+ }
+
+ public GenericContext<T2> ApplyTo<T2>(T2 item) where T2 : class
+ {
+ return new GenericContext<T2>(item, TypeArguments);
+ }
+
+ class DummyGenericParameterProvider : IGenericParameterProvider
+ {
+ readonly GenericParameterType type;
+ readonly Mono.Collections.Generic.Collection<GenericParameter> parameters;
+
+ public DummyGenericParameterProvider(bool methodTypeParameter)
+ {
+ type = methodTypeParameter ? GenericParameterType.Method :
+ GenericParameterType.Type;
+ parameters = new Mono.Collections.Generic.Collection<GenericParameter>(1);
+ parameters.Add(new GenericParameter(this));
+ }
+
+ public GenericParameter DummyParameter
+ {
+ get { return parameters[0]; }
+ }
+
+ bool IGenericParameterProvider.HasGenericParameters
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ bool IGenericParameterProvider.IsDefinition
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ ModuleDefinition IGenericParameterProvider.Module
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ Mono.Collections.Generic.Collection<GenericParameter> IGenericParameterProvider.GenericParameters
+ {
+ get { return parameters; }
+ }
+
+ GenericParameterType IGenericParameterProvider.GenericParameterType
+ {
+ get { return type; }
+ }
+
+ MetadataToken IMetadataTokenProvider.MetadataToken
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ set
+ {
+ throw new NotImplementedException();
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/CecilExtensions.cs b/ICSharpCode.Decompiler/CecilExtensions.cs
new file mode 100644
index 00000000..0c7cb1e4
--- /dev/null
+++ b/ICSharpCode.Decompiler/CecilExtensions.cs
@@ -0,0 +1,374 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler
+{
+ /// <summary>
+ /// Cecil helper methods.
+ /// </summary>
+ public static class CecilExtensions
+ {
+ #region GetPushDelta / GetPopDelta
+ public static int GetPushDelta(this Instruction instruction)
+ {
+ OpCode code = instruction.OpCode;
+ switch (code.StackBehaviourPush) {
+ case StackBehaviour.Push0:
+ return 0;
+
+ case StackBehaviour.Push1:
+ case StackBehaviour.Pushi:
+ case StackBehaviour.Pushi8:
+ case StackBehaviour.Pushr4:
+ case StackBehaviour.Pushr8:
+ case StackBehaviour.Pushref:
+ return 1;
+
+ case StackBehaviour.Push1_push1:
+ return 2;
+
+ case StackBehaviour.Varpush:
+ if (code.FlowControl != FlowControl.Call)
+ break;
+
+ IMethodSignature method = (IMethodSignature) instruction.Operand;
+ return IsVoid (method.ReturnType) ? 0 : 1;
+ }
+
+ throw new NotSupportedException ();
+ }
+
+ public static int? GetPopDelta(this Instruction instruction, MethodDefinition methodDef)
+ {
+ OpCode code = instruction.OpCode;
+ switch (code.StackBehaviourPop) {
+ case StackBehaviour.Pop0:
+ return 0;
+ case StackBehaviour.Popi:
+ case StackBehaviour.Popref:
+ case StackBehaviour.Pop1:
+ return 1;
+
+ case StackBehaviour.Pop1_pop1:
+ case StackBehaviour.Popi_pop1:
+ case StackBehaviour.Popi_popi:
+ case StackBehaviour.Popi_popi8:
+ case StackBehaviour.Popi_popr4:
+ case StackBehaviour.Popi_popr8:
+ case StackBehaviour.Popref_pop1:
+ case StackBehaviour.Popref_popi:
+ return 2;
+
+ case StackBehaviour.Popi_popi_popi:
+ case StackBehaviour.Popref_popi_popi:
+ case StackBehaviour.Popref_popi_popi8:
+ case StackBehaviour.Popref_popi_popr4:
+ case StackBehaviour.Popref_popi_popr8:
+ case StackBehaviour.Popref_popi_popref:
+ return 3;
+
+ case StackBehaviour.PopAll:
+ return null;
+
+ case StackBehaviour.Varpop:
+ if (code == OpCodes.Ret)
+ return methodDef.ReturnType.IsVoid() ? 0 : 1;
+
+ if (code.FlowControl != FlowControl.Call)
+ break;
+
+ IMethodSignature method = (IMethodSignature) instruction.Operand;
+ int count = method.HasParameters ? method.Parameters.Count : 0;
+ if (method.HasThis && code != OpCodes.Newobj)
+ ++count;
+ if (code == OpCodes.Calli)
+ ++count; // calli takes a function pointer in additional to the normal args
+
+ return count;
+ }
+
+ throw new NotSupportedException ();
+ }
+
+ public static bool IsVoid(this TypeReference type)
+ {
+ while (type is OptionalModifierType || type is RequiredModifierType)
+ type = ((TypeSpecification)type).ElementType;
+ return type.MetadataType == MetadataType.Void;
+ }
+
+ public static bool IsValueTypeOrVoid(this TypeReference type)
+ {
+ while (type is OptionalModifierType || type is RequiredModifierType)
+ type = ((TypeSpecification)type).ElementType;
+ if (type is ArrayType)
+ return false;
+ return type.IsValueType || type.IsVoid();
+ }
+
+ /// <summary>
+ /// checks if the given TypeReference is one of the following types:
+ /// [sbyte, short, int, long, IntPtr]
+ /// </summary>
+ public static bool IsSignedIntegralType(this TypeReference type)
+ {
+ return type.MetadataType == MetadataType.SByte ||
+ type.MetadataType == MetadataType.Int16 ||
+ type.MetadataType == MetadataType.Int32 ||
+ type.MetadataType == MetadataType.Int64 ||
+ type.MetadataType == MetadataType.IntPtr;
+ }
+
+ /// <summary>
+ /// checks if the given value is a numeric zero-value.
+ /// NOTE that this only works for types: [sbyte, short, int, long, IntPtr, byte, ushort, uint, ulong, float, double and decimal]
+ /// </summary>
+ public static bool IsZero(this object value)
+ {
+ return value.Equals((sbyte)0) ||
+ value.Equals((short)0) ||
+ value.Equals(0) ||
+ value.Equals(0L) ||
+ value.Equals(IntPtr.Zero) ||
+ value.Equals((byte)0) ||
+ value.Equals((ushort)0) ||
+ value.Equals(0u) ||
+ value.Equals(0UL) ||
+ value.Equals(0.0f) ||
+ value.Equals(0.0) ||
+ value.Equals((decimal)0);
+
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Gets the (exclusive) end offset of this instruction.
+ /// </summary>
+ public static int GetEndOffset(this Instruction inst)
+ {
+ if (inst == null)
+ throw new ArgumentNullException("inst");
+ return inst.Offset + inst.GetSize();
+ }
+
+ public static string OffsetToString(int offset)
+ {
+ return string.Format("IL_{0:x4}", offset);
+ }
+
+ public static HashSet<MethodDefinition> GetAccessorMethods(this TypeDefinition type)
+ {
+ HashSet<MethodDefinition> accessorMethods = new HashSet<MethodDefinition>();
+ foreach (var property in type.Properties) {
+ accessorMethods.Add(property.GetMethod);
+ accessorMethods.Add(property.SetMethod);
+ if (property.HasOtherMethods) {
+ foreach (var m in property.OtherMethods)
+ accessorMethods.Add(m);
+ }
+ }
+ foreach (EventDefinition ev in type.Events) {
+ accessorMethods.Add(ev.AddMethod);
+ accessorMethods.Add(ev.RemoveMethod);
+ accessorMethods.Add(ev.InvokeMethod);
+ if (ev.HasOtherMethods) {
+ foreach (var m in ev.OtherMethods)
+ accessorMethods.Add(m);
+ }
+ }
+ return accessorMethods;
+ }
+
+ public static TypeDefinition ResolveWithinSameModule(this TypeReference type)
+ {
+ if (type != null && type.GetElementType().Module == type.Module)
+ return type.Resolve();
+ else
+ return null;
+ }
+
+ public static FieldDefinition ResolveWithinSameModule(this FieldReference field)
+ {
+ if (field != null && field.DeclaringType.GetElementType().Module == field.Module)
+ return field.Resolve();
+ else
+ return null;
+ }
+
+ public static MethodDefinition ResolveWithinSameModule(this MethodReference method)
+ {
+ if (method != null && method.DeclaringType.GetElementType().Module == method.Module)
+ return method.Resolve();
+ else
+ return null;
+ }
+
+ [Obsolete("throwing exceptions is considered a bug")]
+ public static TypeDefinition ResolveOrThrow(this TypeReference typeReference)
+ {
+ var resolved = typeReference.Resolve();
+ if (resolved == null)
+ throw new ReferenceResolvingException();
+ return resolved;
+ }
+
+ public static bool IsCompilerGenerated(this ICustomAttributeProvider provider)
+ {
+ if (provider != null && provider.HasCustomAttributes) {
+ foreach (CustomAttribute a in provider.CustomAttributes) {
+ if (a.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute")
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static bool IsCompilerGeneratedOrIsInCompilerGeneratedClass(this IMemberDefinition member)
+ {
+ if (member == null)
+ return false;
+ if (member.IsCompilerGenerated())
+ return true;
+ return IsCompilerGeneratedOrIsInCompilerGeneratedClass(member.DeclaringType);
+ }
+
+ public static TypeReference GetEnumUnderlyingType(this TypeDefinition type)
+ {
+ if (!type.IsEnum)
+ throw new ArgumentException("Type must be an enum", "type");
+
+ var fields = type.Fields;
+
+ for (int i = 0; i < fields.Count; i++)
+ {
+ var field = fields[i];
+ if (!field.IsStatic)
+ return field.FieldType;
+ }
+
+ throw new NotSupportedException();
+ }
+
+ public static bool IsAnonymousType(this TypeReference type)
+ {
+ if (type == null)
+ return false;
+ if (string.IsNullOrEmpty(type.Namespace) && type.HasGeneratedName() && (type.Name.Contains("AnonType") || type.Name.Contains("AnonymousType"))) {
+ TypeDefinition td = type.Resolve();
+ return td != null && td.IsCompilerGenerated();
+ }
+ return false;
+ }
+
+ public static bool HasGeneratedName(this MemberReference member)
+ {
+ return member.Name.StartsWith("<", StringComparison.Ordinal);
+ }
+
+ public static bool ContainsAnonymousType(this TypeReference type)
+ {
+ GenericInstanceType git = type as GenericInstanceType;
+ if (git != null) {
+ if (IsAnonymousType(git))
+ return true;
+ for (int i = 0; i < git.GenericArguments.Count; i++) {
+ if (git.GenericArguments[i].ContainsAnonymousType())
+ return true;
+ }
+ return false;
+ }
+ TypeSpecification typeSpec = type as TypeSpecification;
+ if (typeSpec != null)
+ return typeSpec.ElementType.ContainsAnonymousType();
+ else
+ return false;
+ }
+
+ public static string GetDefaultMemberName(this TypeDefinition type)
+ {
+ CustomAttribute attr;
+ return type.GetDefaultMemberName(out attr);
+ }
+
+ public static string GetDefaultMemberName(this TypeDefinition type, out CustomAttribute defaultMemberAttribute)
+ {
+ if (type.HasCustomAttributes)
+ foreach (CustomAttribute ca in type.CustomAttributes)
+ if (ca.Constructor.DeclaringType.Name == "DefaultMemberAttribute" && ca.Constructor.DeclaringType.Namespace == "System.Reflection"
+ && ca.Constructor.FullName == @"System.Void System.Reflection.DefaultMemberAttribute::.ctor(System.String)") {
+ defaultMemberAttribute = ca;
+ return ca.ConstructorArguments[0].Value as string;
+ }
+ defaultMemberAttribute = null;
+ return null;
+ }
+
+ public static bool IsIndexer(this PropertyDefinition property)
+ {
+ CustomAttribute attr;
+ return property.IsIndexer(out attr);
+ }
+
+ public static bool IsIndexer(this PropertyDefinition property, out CustomAttribute defaultMemberAttribute)
+ {
+ defaultMemberAttribute = null;
+ if (property.HasParameters) {
+ var accessor = property.GetMethod ?? property.SetMethod;
+ PropertyDefinition basePropDef = property;
+ if (accessor.HasOverrides) {
+ // if the property is explicitly implementing an interface, look up the property in the interface:
+ MethodDefinition baseAccessor = accessor.Overrides.First().Resolve();
+ if (baseAccessor != null) {
+ foreach (PropertyDefinition baseProp in baseAccessor.DeclaringType.Properties) {
+ if (baseProp.GetMethod == baseAccessor || baseProp.SetMethod == baseAccessor) {
+ basePropDef = baseProp;
+ break;
+ }
+ }
+ } else
+ return false;
+ }
+ CustomAttribute attr;
+ var defaultMemberName = basePropDef.DeclaringType.GetDefaultMemberName(out attr);
+ if (defaultMemberName == basePropDef.Name) {
+ defaultMemberAttribute = attr;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static bool IsDelegate(this TypeDefinition type)
+ {
+ if (type.BaseType != null && type.BaseType.Namespace == "System") {
+ if (type.BaseType.Name == "MulticastDelegate")
+ return true;
+ if (type.BaseType.Name == "Delegate" && type.Name != "MulticastDelegate")
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/CodeMappings.cs b/ICSharpCode.Decompiler/CodeMappings.cs
new file mode 100644
index 00000000..ee62f76c
--- /dev/null
+++ b/ICSharpCode.Decompiler/CodeMappings.cs
@@ -0,0 +1,57 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using ICSharpCode.Decompiler.ILAst;
+using ICSharpCode.NRefactory;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler
+{
+ /// <summary> Maps method's source code to IL </summary>
+ public class MethodDebugSymbols
+ {
+ public MethodDefinition CecilMethod { get; set; }
+ public List<ILVariable> LocalVariables { get; set; }
+ public List<SequencePoint> SequencePoints { get; set; }
+ public TextLocation StartLocation { get; set; }
+ public TextLocation EndLocation { get; set; }
+
+ public MethodDebugSymbols(MethodDefinition methodDef)
+ {
+ CecilMethod = methodDef;
+ LocalVariables = new List<ILVariable>();
+ SequencePoints = new List<SequencePoint>();
+ }
+ }
+
+ public class SequencePoint
+ {
+ public ILRange[] ILRanges { get; set; }
+ public TextLocation StartLocation { get; set; }
+ public TextLocation EndLocation { get; set; }
+ public int ILOffset { get { return ILRanges[0].From; } }
+
+ public override string ToString()
+ {
+ return string.Join(" ", ILRanges) + " " + StartLocation + "-" + EndLocation;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/DecompilerException.cs b/ICSharpCode.Decompiler/DecompilerException.cs
new file mode 100644
index 00000000..5f5f022f
--- /dev/null
+++ b/ICSharpCode.Decompiler/DecompilerException.cs
@@ -0,0 +1,42 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Runtime.Serialization;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler
+{
+ /// <summary>
+ /// Description of DecompilerException.
+ /// </summary>
+ public class DecompilerException : Exception, ISerializable
+ {
+ public MethodDefinition DecompiledMethod { get; set; }
+
+ public DecompilerException(MethodDefinition decompiledMethod, Exception innerException)
+ : base("Error decompiling " + decompiledMethod.FullName + Environment.NewLine, innerException)
+ {
+ }
+
+ // This constructor is needed for serialization.
+ protected DecompilerException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs
new file mode 100644
index 00000000..74bdc943
--- /dev/null
+++ b/ICSharpCode.Decompiler/DecompilerSettings.cs
@@ -0,0 +1,356 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.ComponentModel;
+using ICSharpCode.NRefactory.CSharp;
+
+namespace ICSharpCode.Decompiler
+{
+ /// <summary>
+ /// Settings for the decompiler.
+ /// </summary>
+ public class DecompilerSettings : INotifyPropertyChanged
+ {
+ bool anonymousMethods = true;
+
+ /// <summary>
+ /// Decompile anonymous methods/lambdas.
+ /// </summary>
+ public bool AnonymousMethods {
+ get { return anonymousMethods; }
+ set {
+ if (anonymousMethods != value) {
+ anonymousMethods = value;
+ OnPropertyChanged("AnonymousMethods");
+ }
+ }
+ }
+
+ bool expressionTrees = true;
+
+ /// <summary>
+ /// Decompile expression trees.
+ /// </summary>
+ public bool ExpressionTrees {
+ get { return expressionTrees; }
+ set {
+ if (expressionTrees != value) {
+ expressionTrees = value;
+ OnPropertyChanged("ExpressionTrees");
+ }
+ }
+ }
+
+ bool yieldReturn = true;
+
+ /// <summary>
+ /// Decompile enumerators.
+ /// </summary>
+ public bool YieldReturn {
+ get { return yieldReturn; }
+ set {
+ if (yieldReturn != value) {
+ yieldReturn = value;
+ OnPropertyChanged("YieldReturn");
+ }
+ }
+ }
+
+ bool asyncAwait = true;
+
+ /// <summary>
+ /// Decompile async methods.
+ /// </summary>
+ public bool AsyncAwait {
+ get { return asyncAwait; }
+ set {
+ if (asyncAwait != value) {
+ asyncAwait = value;
+ OnPropertyChanged("AsyncAwait");
+ }
+ }
+ }
+
+ bool automaticProperties = true;
+
+ /// <summary>
+ /// Decompile automatic properties
+ /// </summary>
+ public bool AutomaticProperties {
+ get { return automaticProperties; }
+ set {
+ if (automaticProperties != value) {
+ automaticProperties = value;
+ OnPropertyChanged("AutomaticProperties");
+ }
+ }
+ }
+
+ bool automaticEvents = true;
+
+ /// <summary>
+ /// Decompile automatic events
+ /// </summary>
+ public bool AutomaticEvents {
+ get { return automaticEvents; }
+ set {
+ if (automaticEvents != value) {
+ automaticEvents = value;
+ OnPropertyChanged("AutomaticEvents");
+ }
+ }
+ }
+
+ bool usingStatement = true;
+
+ /// <summary>
+ /// Decompile using statements.
+ /// </summary>
+ public bool UsingStatement {
+ get { return usingStatement; }
+ set {
+ if (usingStatement != value) {
+ usingStatement = value;
+ OnPropertyChanged("UsingStatement");
+ }
+ }
+ }
+
+ bool forEachStatement = true;
+
+ /// <summary>
+ /// Decompile foreach statements.
+ /// </summary>
+ public bool ForEachStatement {
+ get { return forEachStatement; }
+ set {
+ if (forEachStatement != value) {
+ forEachStatement = value;
+ OnPropertyChanged("ForEachStatement");
+ }
+ }
+ }
+
+ bool lockStatement = true;
+
+ /// <summary>
+ /// Decompile lock statements.
+ /// </summary>
+ public bool LockStatement {
+ get { return lockStatement; }
+ set {
+ if (lockStatement != value) {
+ lockStatement = value;
+ OnPropertyChanged("LockStatement");
+ }
+ }
+ }
+
+ bool switchStatementOnString = true;
+
+ public bool SwitchStatementOnString {
+ get { return switchStatementOnString; }
+ set {
+ if (switchStatementOnString != value) {
+ switchStatementOnString = value;
+ OnPropertyChanged("SwitchStatementOnString");
+ }
+ }
+ }
+
+ bool usingDeclarations = true;
+
+ public bool UsingDeclarations {
+ get { return usingDeclarations; }
+ set {
+ if (usingDeclarations != value) {
+ usingDeclarations = value;
+ OnPropertyChanged("UsingDeclarations");
+ }
+ }
+ }
+
+ bool queryExpressions = true;
+
+ public bool QueryExpressions {
+ get { return queryExpressions; }
+ set {
+ if (queryExpressions != value) {
+ queryExpressions = value;
+ OnPropertyChanged("QueryExpressions");
+ }
+ }
+ }
+
+ bool fullyQualifyAmbiguousTypeNames = true;
+
+ public bool FullyQualifyAmbiguousTypeNames {
+ get { return fullyQualifyAmbiguousTypeNames; }
+ set {
+ if (fullyQualifyAmbiguousTypeNames != value) {
+ fullyQualifyAmbiguousTypeNames = value;
+ OnPropertyChanged("FullyQualifyAmbiguousTypeNames");
+ }
+ }
+ }
+
+ bool useDebugSymbols = true;
+
+ /// <summary>
+ /// Gets/Sets whether to use variable names from debug symbols, if available.
+ /// </summary>
+ public bool UseDebugSymbols {
+ get { return useDebugSymbols; }
+ set {
+ if (useDebugSymbols != value) {
+ useDebugSymbols = value;
+ OnPropertyChanged("UseDebugSymbols");
+ }
+ }
+ }
+
+ bool objectCollectionInitializers = true;
+
+ /// <summary>
+ /// Gets/Sets whether to use C# 3.0 object/collection initializers
+ /// </summary>
+ public bool ObjectOrCollectionInitializers {
+ get { return objectCollectionInitializers; }
+ set {
+ if (objectCollectionInitializers != value) {
+ objectCollectionInitializers = value;
+ OnPropertyChanged("ObjectCollectionInitializers");
+ }
+ }
+ }
+
+ bool showXmlDocumentation = true;
+
+ /// <summary>
+ /// Gets/Sets whether to include XML documentation comments in the decompiled code
+ /// </summary>
+ public bool ShowXmlDocumentation {
+ get { return showXmlDocumentation; }
+ set {
+ if (showXmlDocumentation != value) {
+ showXmlDocumentation = value;
+ OnPropertyChanged("ShowXmlDocumentation");
+ }
+ }
+ }
+
+ bool foldBraces = false;
+
+ public bool FoldBraces {
+ get { return foldBraces; }
+ set {
+ if (foldBraces != value) {
+ foldBraces = value;
+ OnPropertyChanged("FoldBraces");
+ }
+ }
+ }
+
+ #region Options to aid VB decompilation
+ bool introduceIncrementAndDecrement = true;
+
+ /// <summary>
+ /// Gets/Sets whether to use increment and decrement operators
+ /// </summary>
+ public bool IntroduceIncrementAndDecrement {
+ get { return introduceIncrementAndDecrement; }
+ set {
+ if (introduceIncrementAndDecrement != value) {
+ introduceIncrementAndDecrement = value;
+ OnPropertyChanged("IntroduceIncrementAndDecrement");
+ }
+ }
+ }
+
+ bool makeAssignmentExpressions = true;
+
+ /// <summary>
+ /// Gets/Sets whether to use assignment expressions such as in while ((count = Do()) != 0) ;
+ /// </summary>
+ public bool MakeAssignmentExpressions {
+ get { return makeAssignmentExpressions; }
+ set {
+ if (makeAssignmentExpressions != value) {
+ makeAssignmentExpressions = value;
+ OnPropertyChanged("MakeAssignmentExpressions");
+ }
+ }
+ }
+
+ bool alwaysGenerateExceptionVariableForCatchBlocks = false;
+
+ /// <summary>
+ /// Gets/Sets whether to always generate exception variables in catch blocks
+ /// </summary>
+ public bool AlwaysGenerateExceptionVariableForCatchBlocks {
+ get { return alwaysGenerateExceptionVariableForCatchBlocks; }
+ set {
+ if (alwaysGenerateExceptionVariableForCatchBlocks != value) {
+ alwaysGenerateExceptionVariableForCatchBlocks = value;
+ OnPropertyChanged("AlwaysGenerateExceptionVariableForCatchBlocks");
+ }
+ }
+ }
+ #endregion
+
+ CSharpFormattingOptions csharpFormattingOptions;
+
+ public CSharpFormattingOptions CSharpFormattingOptions {
+ get {
+ if (csharpFormattingOptions == null) {
+ csharpFormattingOptions = FormattingOptionsFactory.CreateAllman();
+ csharpFormattingOptions.IndentSwitchBody = false;
+ csharpFormattingOptions.ArrayInitializerWrapping = Wrapping.WrapAlways;
+ }
+ return csharpFormattingOptions;
+ }
+ set {
+ if (value == null)
+ throw new ArgumentNullException();
+ if (csharpFormattingOptions != value) {
+ csharpFormattingOptions = value;
+ OnPropertyChanged("CSharpFormattingOptions");
+ }
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged(string propertyName)
+ {
+ if (PropertyChanged != null) {
+ PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+
+ public DecompilerSettings Clone()
+ {
+ DecompilerSettings settings = (DecompilerSettings)MemberwiseClone();
+ if (csharpFormattingOptions != null)
+ settings.csharpFormattingOptions = csharpFormattingOptions.Clone();
+ settings.PropertyChanged = null;
+ return settings;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
new file mode 100644
index 00000000..ea6e54db
--- /dev/null
+++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
@@ -0,0 +1,447 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.Disassembler
+{
+ public enum ILNameSyntax
+ {
+ /// <summary>
+ /// class/valuetype + TypeName (built-in types use keyword syntax)
+ /// </summary>
+ Signature,
+ /// <summary>
+ /// Like signature, but always refers to type parameters using their position
+ /// </summary>
+ SignatureNoNamedTypeParameters,
+ /// <summary>
+ /// [assembly]Full.Type.Name (even for built-in types)
+ /// </summary>
+ TypeName,
+ /// <summary>
+ /// Name (but built-in types use keyword syntax)
+ /// </summary>
+ ShortTypeName
+ }
+
+ public static class DisassemblerHelpers
+ {
+ public static void WriteOffsetReference(ITextOutput writer, Instruction instruction)
+ {
+ writer.WriteReference(CecilExtensions.OffsetToString(instruction.Offset), instruction);
+ }
+
+ public static void WriteTo(this ExceptionHandler exceptionHandler, ITextOutput writer)
+ {
+ writer.Write("Try ");
+ WriteOffsetReference(writer, exceptionHandler.TryStart);
+ writer.Write('-');
+ WriteOffsetReference(writer, exceptionHandler.TryEnd);
+ writer.Write(' ');
+ writer.Write(exceptionHandler.HandlerType.ToString());
+ if (exceptionHandler.FilterStart != null) {
+ writer.Write(' ');
+ WriteOffsetReference(writer, exceptionHandler.FilterStart);
+ writer.Write(" handler ");
+ }
+ if (exceptionHandler.CatchType != null) {
+ writer.Write(' ');
+ exceptionHandler.CatchType.WriteTo(writer);
+ }
+ writer.Write(' ');
+ WriteOffsetReference(writer, exceptionHandler.HandlerStart);
+ writer.Write('-');
+ WriteOffsetReference(writer, exceptionHandler.HandlerEnd);
+ }
+
+ public static void WriteTo(this Instruction instruction, ITextOutput writer)
+ {
+ writer.WriteDefinition(CecilExtensions.OffsetToString(instruction.Offset), instruction);
+ writer.Write(": ");
+ writer.WriteReference(instruction.OpCode.Name, instruction.OpCode);
+ if (instruction.Operand != null) {
+ writer.Write(' ');
+ if (instruction.OpCode == OpCodes.Ldtoken) {
+ if (instruction.Operand is MethodReference)
+ writer.Write("method ");
+ else if (instruction.Operand is FieldReference)
+ writer.Write("field ");
+ }
+ WriteOperand(writer, instruction.Operand);
+ }
+ }
+
+ static void WriteLabelList(ITextOutput writer, Instruction[] instructions)
+ {
+ writer.Write("(");
+ for(int i = 0; i < instructions.Length; i++) {
+ if(i != 0) writer.Write(", ");
+ WriteOffsetReference(writer, instructions[i]);
+ }
+ writer.Write(")");
+ }
+
+ static string ToInvariantCultureString(object value)
+ {
+ IConvertible convertible = value as IConvertible;
+ return(null != convertible)
+ ? convertible.ToString(System.Globalization.CultureInfo.InvariantCulture)
+ : value.ToString();
+ }
+
+ public static void WriteTo(this MethodReference method, ITextOutput writer)
+ {
+ if (method.ExplicitThis) {
+ writer.Write("instance explicit ");
+ }
+ else if (method.HasThis) {
+ writer.Write("instance ");
+ }
+ method.ReturnType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters);
+ writer.Write(' ');
+ if (method.DeclaringType != null) {
+ method.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName);
+ writer.Write("::");
+ }
+ MethodDefinition md = method as MethodDefinition;
+ if (md != null && md.IsCompilerControlled) {
+ writer.WriteReference(Escape(method.Name + "$PST" + method.MetadataToken.ToInt32().ToString("X8")), method);
+ } else {
+ writer.WriteReference(Escape(method.Name), method);
+ }
+ GenericInstanceMethod gim = method as GenericInstanceMethod;
+ if (gim != null) {
+ writer.Write('<');
+ for (int i = 0; i < gim.GenericArguments.Count; i++) {
+ if (i > 0)
+ writer.Write(", ");
+ gim.GenericArguments[i].WriteTo(writer);
+ }
+ writer.Write('>');
+ }
+ writer.Write("(");
+ var parameters = method.Parameters;
+ for(int i = 0; i < parameters.Count; ++i) {
+ if (i > 0) writer.Write(", ");
+ parameters[i].ParameterType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters);
+ }
+ writer.Write(")");
+ }
+
+ static void WriteTo(this FieldReference field, ITextOutput writer)
+ {
+ field.FieldType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters);
+ writer.Write(' ');
+ field.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName);
+ writer.Write("::");
+ writer.WriteReference(Escape(field.Name), field);
+ }
+
+ static bool IsValidIdentifierCharacter(char c)
+ {
+ return c == '_' || c == '$' || c == '@' || c == '?' || c == '`';
+ }
+
+ static bool IsValidIdentifier(string identifier)
+ {
+ if (string.IsNullOrEmpty(identifier))
+ return false;
+ if (!(char.IsLetter(identifier[0]) || IsValidIdentifierCharacter(identifier[0]))) {
+ // As a special case, .ctor and .cctor are valid despite starting with a dot
+ return identifier == ".ctor" || identifier == ".cctor";
+ }
+ for (int i = 1; i < identifier.Length; i++) {
+ if (!(char.IsLetterOrDigit(identifier[i]) || IsValidIdentifierCharacter(identifier[i]) || identifier[i] == '.'))
+ return false;
+ }
+ return true;
+ }
+
+ static readonly HashSet<string> ilKeywords = BuildKeywordList(
+ "abstract", "algorithm", "alignment", "ansi", "any", "arglist",
+ "array", "as", "assembly", "assert", "at", "auto", "autochar", "beforefieldinit",
+ "blob", "blob_object", "bool", "brnull", "brnull.s", "brzero", "brzero.s", "bstr",
+ "bytearray", "byvalstr", "callmostderived", "carray", "catch", "cdecl", "cf",
+ "char", "cil", "class", "clsid", "const", "currency", "custom", "date", "decimal",
+ "default", "demand", "deny", "endmac", "enum", "error", "explicit", "extends", "extern",
+ "false", "famandassem", "family", "famorassem", "fastcall", "fault", "field", "filetime",
+ "filter", "final", "finally", "fixed", "float", "float32", "float64", "forwardref",
+ "fromunmanaged", "handler", "hidebysig", "hresult", "idispatch", "il", "illegal",
+ "implements", "implicitcom", "implicitres", "import", "in", "inheritcheck", "init",
+ "initonly", "instance", "int", "int16", "int32", "int64", "int8", "interface", "internalcall",
+ "iunknown", "lasterr", "lcid", "linkcheck", "literal", "localloc", "lpstr", "lpstruct", "lptstr",
+ "lpvoid", "lpwstr", "managed", "marshal", "method", "modopt", "modreq", "native", "nested",
+ "newslot", "noappdomain", "noinlining", "nomachine", "nomangle", "nometadata", "noncasdemand",
+ "noncasinheritance", "noncaslinkdemand", "noprocess", "not", "not_in_gc_heap", "notremotable",
+ "notserialized", "null", "nullref", "object", "objectref", "opt", "optil", "out",
+ "permitonly", "pinned", "pinvokeimpl", "prefix1", "prefix2", "prefix3", "prefix4", "prefix5", "prefix6",
+ "prefix7", "prefixref", "prejitdeny", "prejitgrant", "preservesig", "private", "privatescope", "protected",
+ "public", "record", "refany", "reqmin", "reqopt", "reqrefuse", "reqsecobj", "request", "retval",
+ "rtspecialname", "runtime", "safearray", "sealed", "sequential", "serializable", "special", "specialname",
+ "static", "stdcall", "storage", "stored_object", "stream", "streamed_object", "string", "struct",
+ "synchronized", "syschar", "sysstring", "tbstr", "thiscall", "tls", "to", "true", "typedref",
+ "unicode", "unmanaged", "unmanagedexp", "unsigned", "unused", "userdefined", "value", "valuetype",
+ "vararg", "variant", "vector", "virtual", "void", "wchar", "winapi", "with", "wrapper",
+
+ // These are not listed as keywords in spec, but ILAsm treats them as such
+ "property", "type", "flags", "callconv", "strict"
+ );
+
+ static HashSet<string> BuildKeywordList(params string[] keywords)
+ {
+ HashSet<string> s = new HashSet<string>(keywords);
+ foreach (var field in typeof(OpCodes).GetFields()) {
+ s.Add(((OpCode)field.GetValue(null)).Name);
+ }
+ return s;
+ }
+
+ public static string Escape(string identifier)
+ {
+ if (IsValidIdentifier(identifier) && !ilKeywords.Contains(identifier)) {
+ return identifier;
+ } else {
+ // The ECMA specification says that ' inside SQString should be ecaped using an octal escape sequence,
+ // but we follow Microsoft's ILDasm and use \'.
+ return "'" + NRefactory.CSharp.TextWriterTokenWriter.ConvertString(identifier).Replace("'", "\\'") + "'";
+ }
+ }
+
+ public static void WriteTo(this TypeReference type, ITextOutput writer, ILNameSyntax syntax = ILNameSyntax.Signature)
+ {
+ ILNameSyntax syntaxForElementTypes = syntax == ILNameSyntax.SignatureNoNamedTypeParameters ? syntax : ILNameSyntax.Signature;
+ if (type is PinnedType) {
+ ((PinnedType)type).ElementType.WriteTo(writer, syntaxForElementTypes);
+ writer.Write(" pinned");
+ } else if (type is ArrayType) {
+ ArrayType at = (ArrayType)type;
+ at.ElementType.WriteTo(writer, syntaxForElementTypes);
+ writer.Write('[');
+ writer.Write(string.Join(", ", at.Dimensions));
+ writer.Write(']');
+ } else if (type is GenericParameter) {
+ writer.Write('!');
+ if (((GenericParameter)type).Owner.GenericParameterType == GenericParameterType.Method)
+ writer.Write('!');
+ if (string.IsNullOrEmpty(type.Name) || type.Name[0] == '!' || syntax == ILNameSyntax.SignatureNoNamedTypeParameters)
+ writer.Write(((GenericParameter)type).Position.ToString());
+ else
+ writer.Write(Escape(type.Name));
+ } else if (type is ByReferenceType) {
+ ((ByReferenceType)type).ElementType.WriteTo(writer, syntaxForElementTypes);
+ writer.Write('&');
+ } else if (type is PointerType) {
+ ((PointerType)type).ElementType.WriteTo(writer, syntaxForElementTypes);
+ writer.Write('*');
+ } else if (type is GenericInstanceType) {
+ type.GetElementType().WriteTo(writer, syntaxForElementTypes);
+ writer.Write('<');
+ var arguments = ((GenericInstanceType)type).GenericArguments;
+ for (int i = 0; i < arguments.Count; i++) {
+ if (i > 0)
+ writer.Write(", ");
+ arguments[i].WriteTo(writer, syntaxForElementTypes);
+ }
+ writer.Write('>');
+ } else if (type is OptionalModifierType) {
+ ((OptionalModifierType)type).ElementType.WriteTo(writer, syntax);
+ writer.Write(" modopt(");
+ ((OptionalModifierType)type).ModifierType.WriteTo(writer, ILNameSyntax.TypeName);
+ writer.Write(") ");
+ } else if (type is RequiredModifierType) {
+ ((RequiredModifierType)type).ElementType.WriteTo(writer, syntax);
+ writer.Write(" modreq(");
+ ((RequiredModifierType)type).ModifierType.WriteTo(writer, ILNameSyntax.TypeName);
+ writer.Write(") ");
+ } else {
+ string name = PrimitiveTypeName(type.FullName);
+ if (syntax == ILNameSyntax.ShortTypeName) {
+ if (name != null)
+ writer.Write(name);
+ else
+ writer.WriteReference(Escape(type.Name), type);
+ } else if ((syntax == ILNameSyntax.Signature || syntax == ILNameSyntax.SignatureNoNamedTypeParameters) && name != null) {
+ writer.Write(name);
+ } else {
+ if (syntax == ILNameSyntax.Signature || syntax == ILNameSyntax.SignatureNoNamedTypeParameters)
+ writer.Write(type.IsValueType ? "valuetype " : "class ");
+
+ if (type.DeclaringType != null) {
+ type.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName);
+ writer.Write('/');
+ writer.WriteReference(Escape(type.Name), type);
+ } else {
+ if (!type.IsDefinition && type.Scope != null && !(type is TypeSpecification))
+ writer.Write("[{0}]", Escape(type.Scope.Name));
+ writer.WriteReference(Escape(type.FullName), type);
+ }
+ }
+ }
+ }
+
+ public static void WriteOperand(ITextOutput writer, object operand)
+ {
+ if (operand == null)
+ throw new ArgumentNullException("operand");
+
+ Instruction targetInstruction = operand as Instruction;
+ if (targetInstruction != null) {
+ WriteOffsetReference(writer, targetInstruction);
+ return;
+ }
+
+ Instruction[] targetInstructions = operand as Instruction[];
+ if (targetInstructions != null) {
+ WriteLabelList(writer, targetInstructions);
+ return;
+ }
+
+ VariableReference variableRef = operand as VariableReference;
+ if (variableRef != null) {
+ if (string.IsNullOrEmpty(variableRef.Name))
+ writer.WriteReference(variableRef.Index.ToString(), variableRef);
+ else
+ writer.WriteReference(Escape(variableRef.Name), variableRef);
+ return;
+ }
+
+ ParameterReference paramRef = operand as ParameterReference;
+ if (paramRef != null) {
+ if (string.IsNullOrEmpty(paramRef.Name))
+ writer.WriteReference(paramRef.Index.ToString(), paramRef);
+ else
+ writer.WriteReference(Escape(paramRef.Name), paramRef);
+ return;
+ }
+
+ MethodReference methodRef = operand as MethodReference;
+ if (methodRef != null) {
+ methodRef.WriteTo(writer);
+ return;
+ }
+
+ TypeReference typeRef = operand as TypeReference;
+ if (typeRef != null) {
+ typeRef.WriteTo(writer, ILNameSyntax.TypeName);
+ return;
+ }
+
+ FieldReference fieldRef = operand as FieldReference;
+ if (fieldRef != null) {
+ fieldRef.WriteTo(writer);
+ return;
+ }
+
+ string s = operand as string;
+ if (s != null) {
+ writer.Write("\"" + NRefactory.CSharp.TextWriterTokenWriter.ConvertString(s) + "\"");
+ } else if (operand is char) {
+ writer.Write(((int)(char)operand).ToString());
+ } else if (operand is float) {
+ float val = (float)operand;
+ if (val == 0) {
+ if (1 / val == float.NegativeInfinity) {
+ // negative zero is a special case
+ writer.Write('-');
+ }
+ writer.Write("0.0");
+ } else if (float.IsInfinity(val) || float.IsNaN(val)) {
+ byte[] data = BitConverter.GetBytes(val);
+ writer.Write('(');
+ for (int i = 0; i < data.Length; i++) {
+ if (i > 0)
+ writer.Write(' ');
+ writer.Write(data[i].ToString("X2"));
+ }
+ writer.Write(')');
+ } else {
+ writer.Write(val.ToString("R", System.Globalization.CultureInfo.InvariantCulture));
+ }
+ } else if (operand is double) {
+ double val = (double)operand;
+ if (val == 0) {
+ if (1 / val == double.NegativeInfinity) {
+ // negative zero is a special case
+ writer.Write('-');
+ }
+ writer.Write("0.0");
+ } else if (double.IsInfinity(val) || double.IsNaN(val)) {
+ byte[] data = BitConverter.GetBytes(val);
+ writer.Write('(');
+ for (int i = 0; i < data.Length; i++) {
+ if (i > 0)
+ writer.Write(' ');
+ writer.Write(data[i].ToString("X2"));
+ }
+ writer.Write(')');
+ } else {
+ writer.Write(val.ToString("R", System.Globalization.CultureInfo.InvariantCulture));
+ }
+ } else if (operand is bool) {
+ writer.Write((bool)operand ? "true" : "false");
+ } else {
+ s = ToInvariantCultureString(operand);
+ writer.Write(s);
+ }
+ }
+
+ public static string PrimitiveTypeName(string fullName)
+ {
+ switch (fullName) {
+ case "System.SByte":
+ return "int8";
+ case "System.Int16":
+ return "int16";
+ case "System.Int32":
+ return "int32";
+ case "System.Int64":
+ return "int64";
+ case "System.Byte":
+ return "uint8";
+ case "System.UInt16":
+ return "uint16";
+ case "System.UInt32":
+ return "uint32";
+ case "System.UInt64":
+ return "uint64";
+ case "System.Single":
+ return "float32";
+ case "System.Double":
+ return "float64";
+ case "System.Void":
+ return "void";
+ case "System.Boolean":
+ return "bool";
+ case "System.String":
+ return "string";
+ case "System.Char":
+ return "char";
+ case "System.Object":
+ return "object";
+ case "System.IntPtr":
+ return "native int";
+ default:
+ return null;
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Disassembler/ILStructure.cs b/ICSharpCode.Decompiler/Disassembler/ILStructure.cs
new file mode 100644
index 00000000..ff9285b2
--- /dev/null
+++ b/ICSharpCode.Decompiler/Disassembler/ILStructure.cs
@@ -0,0 +1,228 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using ICSharpCode.Decompiler.FlowAnalysis;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.Disassembler
+{
+ /// <summary>
+ /// Specifies the type of an IL structure.
+ /// </summary>
+ public enum ILStructureType
+ {
+ /// <summary>
+ /// The root block of the method
+ /// </summary>
+ Root,
+ /// <summary>
+ /// A nested control structure representing a loop.
+ /// </summary>
+ Loop,
+ /// <summary>
+ /// A nested control structure representing a try block.
+ /// </summary>
+ Try,
+ /// <summary>
+ /// A nested control structure representing a catch, finally, or fault block.
+ /// </summary>
+ Handler,
+ /// <summary>
+ /// A nested control structure representing an exception filter block.
+ /// </summary>
+ Filter
+ }
+
+ /// <summary>
+ /// An IL structure.
+ /// </summary>
+ public class ILStructure
+ {
+ public readonly ILStructureType Type;
+
+ /// <summary>
+ /// Start position of the structure.
+ /// </summary>
+ public readonly int StartOffset;
+
+ /// <summary>
+ /// End position of the structure. (exclusive)
+ /// </summary>
+ public readonly int EndOffset;
+
+ /// <summary>
+ /// The exception handler associated with the Try, Filter or Handler block.
+ /// </summary>
+ public readonly ExceptionHandler ExceptionHandler;
+
+ /// <summary>
+ /// The loop's entry point.
+ /// </summary>
+ public readonly Instruction LoopEntryPoint;
+
+ /// <summary>
+ /// The list of child structures.
+ /// </summary>
+ public readonly List<ILStructure> Children = new List<ILStructure>();
+
+ public ILStructure(MethodBody body)
+ : this(ILStructureType.Root, 0, body.CodeSize)
+ {
+ // Build the tree of exception structures:
+ for (int i = 0; i < body.ExceptionHandlers.Count; i++) {
+ ExceptionHandler eh = body.ExceptionHandlers[i];
+ if (!body.ExceptionHandlers.Take(i).Any(oldEh => oldEh.TryStart == eh.TryStart && oldEh.TryEnd == eh.TryEnd))
+ AddNestedStructure(new ILStructure(ILStructureType.Try, eh.TryStart.Offset, eh.TryEnd.Offset, eh));
+ if (eh.HandlerType == ExceptionHandlerType.Filter)
+ AddNestedStructure(new ILStructure(ILStructureType.Filter, eh.FilterStart.Offset, eh.HandlerStart.Offset, eh));
+ AddNestedStructure(new ILStructure(ILStructureType.Handler, eh.HandlerStart.Offset, eh.HandlerEnd == null ? body.CodeSize : eh.HandlerEnd.Offset, eh));
+ }
+ // Very simple loop detection: look for backward branches
+ List<KeyValuePair<Instruction, Instruction>> allBranches = FindAllBranches(body);
+ // We go through the branches in reverse so that we find the biggest possible loop boundary first (think loops with "continue;")
+ for (int i = allBranches.Count - 1; i >= 0; i--) {
+ int loopEnd = allBranches[i].Key.GetEndOffset();
+ int loopStart = allBranches[i].Value.Offset;
+ if (loopStart < loopEnd) {
+ // We found a backward branch. This is a potential loop.
+ // Check that is has only one entry point:
+ Instruction entryPoint = null;
+
+ // entry point is first instruction in loop if prev inst isn't an unconditional branch
+ Instruction prev = allBranches[i].Value.Previous;
+ if (prev != null && !OpCodeInfo.IsUnconditionalBranch(prev.OpCode))
+ entryPoint = allBranches[i].Value;
+
+ bool multipleEntryPoints = false;
+ foreach (var pair in allBranches) {
+ if (pair.Key.Offset < loopStart || pair.Key.Offset >= loopEnd) {
+ if (loopStart <= pair.Value.Offset && pair.Value.Offset < loopEnd) {
+ // jump from outside the loop into the loop
+ if (entryPoint == null)
+ entryPoint = pair.Value;
+ else if (pair.Value != entryPoint)
+ multipleEntryPoints = true;
+ }
+ }
+ }
+ if (!multipleEntryPoints) {
+ AddNestedStructure(new ILStructure(ILStructureType.Loop, loopStart, loopEnd, entryPoint));
+ }
+ }
+ }
+ SortChildren();
+ }
+
+ public ILStructure(ILStructureType type, int startOffset, int endOffset, ExceptionHandler handler = null)
+ {
+ Debug.Assert(startOffset < endOffset);
+ Type = type;
+ StartOffset = startOffset;
+ EndOffset = endOffset;
+ ExceptionHandler = handler;
+ }
+
+ public ILStructure(ILStructureType type, int startOffset, int endOffset, Instruction loopEntryPoint)
+ {
+ Debug.Assert(startOffset < endOffset);
+ Type = type;
+ StartOffset = startOffset;
+ EndOffset = endOffset;
+ LoopEntryPoint = loopEntryPoint;
+ }
+
+ bool AddNestedStructure(ILStructure newStructure)
+ {
+ // special case: don't consider the loop-like structure of "continue;" statements to be nested loops
+ if (Type == ILStructureType.Loop && newStructure.Type == ILStructureType.Loop && newStructure.StartOffset == StartOffset)
+ return false;
+
+ // use <= for end-offset comparisons because both end and EndOffset are exclusive
+ Debug.Assert(StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= EndOffset);
+ foreach (ILStructure child in Children) {
+ if (child.StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= child.EndOffset) {
+ return child.AddNestedStructure(newStructure);
+ } else if (!(child.EndOffset <= newStructure.StartOffset || newStructure.EndOffset <= child.StartOffset)) {
+ // child and newStructure overlap
+ if (!(newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset)) {
+ // Invalid nesting, can't build a tree. -> Don't add the new structure.
+ return false;
+ }
+ }
+ }
+ // Move existing structures into the new structure:
+ for (int i = 0; i < Children.Count; i++) {
+ ILStructure child = Children[i];
+ if (newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset) {
+ Children.RemoveAt(i--);
+ newStructure.Children.Add(child);
+ }
+ }
+ // Add the structure here:
+ Children.Add(newStructure);
+ return true;
+ }
+
+ /// <summary>
+ /// Finds all branches. Returns list of source offset->target offset mapping.
+ /// Multiple entries for the same source offset are possible (switch statements).
+ /// The result is sorted by source offset.
+ /// </summary>
+ List<KeyValuePair<Instruction, Instruction>> FindAllBranches(MethodBody body)
+ {
+ var result = new List<KeyValuePair<Instruction, Instruction>>();
+ foreach (Instruction inst in body.Instructions) {
+ switch (inst.OpCode.OperandType) {
+ case OperandType.InlineBrTarget:
+ case OperandType.ShortInlineBrTarget:
+ result.Add(new KeyValuePair<Instruction, Instruction>(inst, (Instruction)inst.Operand));
+ break;
+ case OperandType.InlineSwitch:
+ foreach (Instruction target in (Instruction[])inst.Operand)
+ result.Add(new KeyValuePair<Instruction, Instruction>(inst, target));
+ break;
+ }
+ }
+ return result;
+ }
+
+ void SortChildren()
+ {
+ Children.Sort((a, b) => a.StartOffset.CompareTo(b.StartOffset));
+ foreach (ILStructure child in Children)
+ child.SortChildren();
+ }
+
+ /// <summary>
+ /// Gets the innermost structure containing the specified offset.
+ /// </summary>
+ public ILStructure GetInnermost(int offset)
+ {
+ Debug.Assert(StartOffset <= offset && offset < EndOffset);
+ foreach (ILStructure child in Children) {
+ if (child.StartOffset <= offset && offset < child.EndOffset)
+ return child.GetInnermost(offset);
+ }
+ return this;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
new file mode 100644
index 00000000..2b5db78b
--- /dev/null
+++ b/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
@@ -0,0 +1,239 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.FlowAnalysis;
+using ICSharpCode.Decompiler.ILAst;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.Disassembler
+{
+ /// <summary>
+ /// Disassembles a method body.
+ /// </summary>
+ public sealed class MethodBodyDisassembler
+ {
+ readonly ITextOutput output;
+ readonly bool detectControlStructure;
+ readonly CancellationToken cancellationToken;
+
+ public MethodBodyDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken)
+ {
+ if (output == null)
+ throw new ArgumentNullException("output");
+ this.output = output;
+ this.detectControlStructure = detectControlStructure;
+ this.cancellationToken = cancellationToken;
+ }
+
+ public void Disassemble(MethodBody body, MethodDebugSymbols debugSymbols)
+ {
+ // start writing IL code
+ MethodDefinition method = body.Method;
+ output.WriteLine("// Method begins at RVA 0x{0:x4}", method.RVA);
+ output.WriteLine("// Code size {0} (0x{0:x})", body.CodeSize);
+ output.WriteLine(".maxstack {0}", body.MaxStackSize);
+ if (method.DeclaringType.Module.Assembly != null && method.DeclaringType.Module.Assembly.EntryPoint == method)
+ output.WriteLine (".entrypoint");
+
+ if (method.Body.HasVariables) {
+ output.Write(".locals ");
+ if (method.Body.InitLocals)
+ output.Write("init ");
+ output.WriteLine("(");
+ output.Indent();
+ foreach (var v in method.Body.Variables) {
+ output.WriteDefinition("[" + v.Index + "] ", v);
+ v.VariableType.WriteTo(output);
+ if (!string.IsNullOrEmpty(v.Name)) {
+ output.Write(' ');
+ output.Write(DisassemblerHelpers.Escape(v.Name));
+ }
+ if (v.Index + 1 < method.Body.Variables.Count)
+ output.Write(',');
+ output.WriteLine();
+ }
+ output.Unindent();
+ output.WriteLine(")");
+ }
+ output.WriteLine();
+
+ if (detectControlStructure && body.Instructions.Count > 0) {
+ Instruction inst = body.Instructions[0];
+ HashSet<int> branchTargets = GetBranchTargets(body.Instructions);
+ WriteStructureBody(new ILStructure(body), branchTargets, ref inst, debugSymbols, method.Body.CodeSize);
+ } else {
+ foreach (var inst in method.Body.Instructions) {
+ var startLocation = output.Location;
+ inst.WriteTo(output);
+
+ if (debugSymbols != null) {
+ // add IL code mappings - used in debugger
+ debugSymbols.SequencePoints.Add(
+ new SequencePoint() {
+ StartLocation = output.Location,
+ EndLocation = output.Location,
+ ILRanges = new ILRange[] { new ILRange(inst.Offset, inst.Next == null ? method.Body.CodeSize : inst.Next.Offset) }
+ });
+ }
+
+ output.WriteLine();
+ }
+ if (method.Body.HasExceptionHandlers) {
+ output.WriteLine();
+ foreach (var eh in method.Body.ExceptionHandlers) {
+ eh.WriteTo(output);
+ output.WriteLine();
+ }
+ }
+ }
+ }
+
+ HashSet<int> GetBranchTargets(IEnumerable<Instruction> instructions)
+ {
+ HashSet<int> branchTargets = new HashSet<int>();
+ foreach (var inst in instructions) {
+ Instruction target = inst.Operand as Instruction;
+ if (target != null)
+ branchTargets.Add(target.Offset);
+ Instruction[] targets = inst.Operand as Instruction[];
+ if (targets != null)
+ foreach (Instruction t in targets)
+ branchTargets.Add(t.Offset);
+ }
+ return branchTargets;
+ }
+
+ void WriteStructureHeader(ILStructure s)
+ {
+ switch (s.Type) {
+ case ILStructureType.Loop:
+ output.Write("// loop start");
+ if (s.LoopEntryPoint != null) {
+ output.Write(" (head: ");
+ DisassemblerHelpers.WriteOffsetReference(output, s.LoopEntryPoint);
+ output.Write(')');
+ }
+ output.WriteLine();
+ break;
+ case ILStructureType.Try:
+ output.WriteLine(".try");
+ output.WriteLine("{");
+ break;
+ case ILStructureType.Handler:
+ switch (s.ExceptionHandler.HandlerType) {
+ case ExceptionHandlerType.Catch:
+ case ExceptionHandlerType.Filter:
+ output.Write("catch");
+ if (s.ExceptionHandler.CatchType != null) {
+ output.Write(' ');
+ s.ExceptionHandler.CatchType.WriteTo(output, ILNameSyntax.TypeName);
+ }
+ output.WriteLine();
+ break;
+ case ExceptionHandlerType.Finally:
+ output.WriteLine("finally");
+ break;
+ case ExceptionHandlerType.Fault:
+ output.WriteLine("fault");
+ break;
+ default:
+ throw new NotSupportedException();
+ }
+ output.WriteLine("{");
+ break;
+ case ILStructureType.Filter:
+ output.WriteLine("filter");
+ output.WriteLine("{");
+ break;
+ default:
+ throw new NotSupportedException();
+ }
+ output.Indent();
+ }
+
+ void WriteStructureBody(ILStructure s, HashSet<int> branchTargets, ref Instruction inst, MethodDebugSymbols debugSymbols, int codeSize)
+ {
+ bool isFirstInstructionInStructure = true;
+ bool prevInstructionWasBranch = false;
+ int childIndex = 0;
+ while (inst != null && inst.Offset < s.EndOffset) {
+ int offset = inst.Offset;
+ if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) {
+ ILStructure child = s.Children[childIndex++];
+ WriteStructureHeader(child);
+ WriteStructureBody(child, branchTargets, ref inst, debugSymbols, codeSize);
+ WriteStructureFooter(child);
+ } else {
+ if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) {
+ output.WriteLine(); // put an empty line after branches, and in front of branch targets
+ }
+ var startLocation = output.Location;
+ inst.WriteTo(output);
+
+ // add IL code mappings - used in debugger
+ if (debugSymbols != null) {
+ debugSymbols.SequencePoints.Add(
+ new SequencePoint() {
+ StartLocation = startLocation,
+ EndLocation = output.Location,
+ ILRanges = new ILRange[] { new ILRange(inst.Offset, inst.Next == null ? codeSize : inst.Next.Offset) }
+ });
+ }
+
+ output.WriteLine();
+
+ prevInstructionWasBranch = inst.OpCode.FlowControl == FlowControl.Branch
+ || inst.OpCode.FlowControl == FlowControl.Cond_Branch
+ || inst.OpCode.FlowControl == FlowControl.Return
+ || inst.OpCode.FlowControl == FlowControl.Throw;
+
+ inst = inst.Next;
+ }
+ isFirstInstructionInStructure = false;
+ }
+ }
+
+ void WriteStructureFooter(ILStructure s)
+ {
+ output.Unindent();
+ switch (s.Type) {
+ case ILStructureType.Loop:
+ output.WriteLine("// end loop");
+ break;
+ case ILStructureType.Try:
+ output.WriteLine("} // end .try");
+ break;
+ case ILStructureType.Handler:
+ output.WriteLine("} // end handler");
+ break;
+ case ILStructureType.Filter:
+ output.WriteLine("} // end filter");
+ break;
+ default:
+ throw new NotSupportedException();
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
new file mode 100644
index 00000000..2a374c3a
--- /dev/null
+++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
@@ -0,0 +1,1168 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using ICSharpCode.NRefactory;
+using Mono.Cecil;
+using Mono.Collections.Generic;
+
+namespace ICSharpCode.Decompiler.Disassembler
+{
+ /// <summary>
+ /// Disassembles type and member definitions.
+ /// </summary>
+ public sealed class ReflectionDisassembler
+ {
+ ITextOutput output;
+ CancellationToken cancellationToken;
+ bool isInType; // whether we are currently disassembling a whole type (-> defaultCollapsed for foldings)
+ MethodBodyDisassembler methodBodyDisassembler;
+ MemberReference currentMember;
+
+ public ReflectionDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken)
+ {
+ if (output == null)
+ throw new ArgumentNullException("output");
+ this.output = output;
+ this.cancellationToken = cancellationToken;
+ methodBodyDisassembler = new MethodBodyDisassembler(output, detectControlStructure, cancellationToken);
+ }
+
+ #region Disassemble Method
+ EnumNameCollection<MethodAttributes> methodAttributeFlags = new EnumNameCollection<MethodAttributes>() {
+ { MethodAttributes.Final, "final" },
+ { MethodAttributes.HideBySig, "hidebysig" },
+ { MethodAttributes.SpecialName, "specialname" },
+ { MethodAttributes.PInvokeImpl, null }, // handled separately
+ { MethodAttributes.UnmanagedExport, "export" },
+ { MethodAttributes.RTSpecialName, "rtspecialname" },
+ { MethodAttributes.RequireSecObject, "reqsecobj" },
+ { MethodAttributes.NewSlot, "newslot" },
+ { MethodAttributes.CheckAccessOnOverride, "strict" },
+ { MethodAttributes.Abstract, "abstract" },
+ { MethodAttributes.Virtual, "virtual" },
+ { MethodAttributes.Static, "static" },
+ { MethodAttributes.HasSecurity, null }, // ?? also invisible in ILDasm
+ };
+
+ EnumNameCollection<MethodAttributes> methodVisibility = new EnumNameCollection<MethodAttributes>() {
+ { MethodAttributes.Private, "private" },
+ { MethodAttributes.FamANDAssem, "famandassem" },
+ { MethodAttributes.Assembly, "assembly" },
+ { MethodAttributes.Family, "family" },
+ { MethodAttributes.FamORAssem, "famorassem" },
+ { MethodAttributes.Public, "public" },
+ };
+
+ EnumNameCollection<MethodCallingConvention> callingConvention = new EnumNameCollection<MethodCallingConvention>() {
+ { MethodCallingConvention.C, "unmanaged cdecl" },
+ { MethodCallingConvention.StdCall, "unmanaged stdcall" },
+ { MethodCallingConvention.ThisCall, "unmanaged thiscall" },
+ { MethodCallingConvention.FastCall, "unmanaged fastcall" },
+ { MethodCallingConvention.VarArg, "vararg" },
+ { MethodCallingConvention.Generic, null },
+ };
+
+ EnumNameCollection<MethodImplAttributes> methodCodeType = new EnumNameCollection<MethodImplAttributes>() {
+ { MethodImplAttributes.IL, "cil" },
+ { MethodImplAttributes.Native, "native" },
+ { MethodImplAttributes.OPTIL, "optil" },
+ { MethodImplAttributes.Runtime, "runtime" },
+ };
+
+ EnumNameCollection<MethodImplAttributes> methodImpl = new EnumNameCollection<MethodImplAttributes>() {
+ { MethodImplAttributes.Synchronized, "synchronized" },
+ { MethodImplAttributes.NoInlining, "noinlining" },
+ { MethodImplAttributes.NoOptimization, "nooptimization" },
+ { MethodImplAttributes.PreserveSig, "preservesig" },
+ { MethodImplAttributes.InternalCall, "internalcall" },
+ { MethodImplAttributes.ForwardRef, "forwardref" },
+ };
+
+ public void DisassembleMethod(MethodDefinition method)
+ {
+ // set current member
+ currentMember = method;
+
+ // write method header
+ output.WriteDefinition(".method ", method);
+ DisassembleMethodInternal(method);
+ }
+
+ void DisassembleMethodInternal(MethodDefinition method)
+ {
+ // .method public hidebysig specialname
+ // instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed
+ //
+
+ TextLocation startLocation = output.Location;
+
+ //emit flags
+ WriteEnum(method.Attributes & MethodAttributes.MemberAccessMask, methodVisibility);
+ WriteFlags(method.Attributes & ~MethodAttributes.MemberAccessMask, methodAttributeFlags);
+ if(method.IsCompilerControlled) output.Write("privatescope ");
+
+ if ((method.Attributes & MethodAttributes.PInvokeImpl) == MethodAttributes.PInvokeImpl) {
+ output.Write("pinvokeimpl");
+ if (method.HasPInvokeInfo && method.PInvokeInfo != null) {
+ PInvokeInfo info = method.PInvokeInfo;
+ output.Write("(\"" + NRefactory.CSharp.TextWriterTokenWriter.ConvertString(info.Module.Name) + "\"");
+
+ if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != method.Name)
+ output.Write(" as \"" + NRefactory.CSharp.TextWriterTokenWriter.ConvertString(info.EntryPoint) + "\"");
+
+ if (info.IsNoMangle)
+ output.Write(" nomangle");
+
+ if (info.IsCharSetAnsi)
+ output.Write(" ansi");
+ else if (info.IsCharSetAuto)
+ output.Write(" autochar");
+ else if (info.IsCharSetUnicode)
+ output.Write(" unicode");
+
+ if (info.SupportsLastError)
+ output.Write(" lasterr");
+
+ if (info.IsCallConvCdecl)
+ output.Write(" cdecl");
+ else if (info.IsCallConvFastcall)
+ output.Write(" fastcall");
+ else if (info.IsCallConvStdCall)
+ output.Write(" stdcall");
+ else if (info.IsCallConvThiscall)
+ output.Write(" thiscall");
+ else if (info.IsCallConvWinapi)
+ output.Write(" winapi");
+
+ output.Write(')');
+ }
+ output.Write(' ');
+ }
+
+ output.WriteLine();
+ output.Indent();
+ if (method.ExplicitThis) {
+ output.Write("instance explicit ");
+ } else if (method.HasThis) {
+ output.Write("instance ");
+ }
+
+ //call convention
+ WriteEnum(method.CallingConvention & (MethodCallingConvention)0x1f, callingConvention);
+
+ //return type
+ method.ReturnType.WriteTo(output);
+ output.Write(' ');
+ if (method.MethodReturnType.HasMarshalInfo) {
+ WriteMarshalInfo(method.MethodReturnType.MarshalInfo);
+ }
+
+ if (method.IsCompilerControlled) {
+ output.Write(DisassemblerHelpers.Escape(method.Name + "$PST" + method.MetadataToken.ToInt32().ToString("X8")));
+ } else {
+ output.Write(DisassemblerHelpers.Escape(method.Name));
+ }
+
+ WriteTypeParameters(output, method);
+
+ //( params )
+ output.Write(" (");
+ if (method.HasParameters) {
+ output.WriteLine();
+ output.Indent();
+ WriteParameters(method.Parameters);
+ output.Unindent();
+ }
+ output.Write(") ");
+ //cil managed
+ WriteEnum(method.ImplAttributes & MethodImplAttributes.CodeTypeMask, methodCodeType);
+ if ((method.ImplAttributes & MethodImplAttributes.ManagedMask) == MethodImplAttributes.Managed)
+ output.Write("managed ");
+ else
+ output.Write("unmanaged ");
+ WriteFlags(method.ImplAttributes & ~(MethodImplAttributes.CodeTypeMask | MethodImplAttributes.ManagedMask), methodImpl);
+
+ output.Unindent();
+ OpenBlock(defaultCollapsed: isInType);
+ WriteAttributes(method.CustomAttributes);
+ if (method.HasOverrides) {
+ foreach (var methodOverride in method.Overrides) {
+ output.Write(".override method ");
+ methodOverride.WriteTo(output);
+ output.WriteLine();
+ }
+ }
+ foreach (var p in method.Parameters) {
+ WriteParameterAttributes(p);
+ }
+ WriteSecurityDeclarations(method);
+
+ if (method.HasBody) {
+ // create IL code mappings - used in debugger
+ MethodDebugSymbols debugSymbols = new MethodDebugSymbols(method);
+ debugSymbols.StartLocation = startLocation;
+ methodBodyDisassembler.Disassemble(method.Body, debugSymbols);
+ debugSymbols.EndLocation = output.Location;
+ output.AddDebugSymbols(debugSymbols);
+ }
+
+ CloseBlock("end of method " + DisassemblerHelpers.Escape(method.DeclaringType.Name) + "::" + DisassemblerHelpers.Escape(method.Name));
+ }
+
+ #region Write Security Declarations
+ void WriteSecurityDeclarations(ISecurityDeclarationProvider secDeclProvider)
+ {
+ if (!secDeclProvider.HasSecurityDeclarations)
+ return;
+ foreach (var secdecl in secDeclProvider.SecurityDeclarations) {
+ output.Write(".permissionset ");
+ switch (secdecl.Action) {
+ case SecurityAction.Request:
+ output.Write("request");
+ break;
+ case SecurityAction.Demand:
+ output.Write("demand");
+ break;
+ case SecurityAction.Assert:
+ output.Write("assert");
+ break;
+ case SecurityAction.Deny:
+ output.Write("deny");
+ break;
+ case SecurityAction.PermitOnly:
+ output.Write("permitonly");
+ break;
+ case SecurityAction.LinkDemand:
+ output.Write("linkcheck");
+ break;
+ case SecurityAction.InheritDemand:
+ output.Write("inheritcheck");
+ break;
+ case SecurityAction.RequestMinimum:
+ output.Write("reqmin");
+ break;
+ case SecurityAction.RequestOptional:
+ output.Write("reqopt");
+ break;
+ case SecurityAction.RequestRefuse:
+ output.Write("reqrefuse");
+ break;
+ case SecurityAction.PreJitGrant:
+ output.Write("prejitgrant");
+ break;
+ case SecurityAction.PreJitDeny:
+ output.Write("prejitdeny");
+ break;
+ case SecurityAction.NonCasDemand:
+ output.Write("noncasdemand");
+ break;
+ case SecurityAction.NonCasLinkDemand:
+ output.Write("noncaslinkdemand");
+ break;
+ case SecurityAction.NonCasInheritance:
+ output.Write("noncasinheritance");
+ break;
+ default:
+ output.Write(secdecl.Action.ToString());
+ break;
+ }
+ output.WriteLine(" = {");
+ output.Indent();
+ for (int i = 0; i < secdecl.SecurityAttributes.Count; i++) {
+ SecurityAttribute sa = secdecl.SecurityAttributes[i];
+ if (sa.AttributeType.Scope == sa.AttributeType.Module) {
+ output.Write("class ");
+ output.Write(DisassemblerHelpers.Escape(GetAssemblyQualifiedName(sa.AttributeType)));
+ } else {
+ sa.AttributeType.WriteTo(output, ILNameSyntax.TypeName);
+ }
+ output.Write(" = {");
+ if (sa.HasFields || sa.HasProperties) {
+ output.WriteLine();
+ output.Indent();
+
+ foreach (CustomAttributeNamedArgument na in sa.Fields) {
+ output.Write("field ");
+ WriteSecurityDeclarationArgument(na);
+ output.WriteLine();
+ }
+
+ foreach (CustomAttributeNamedArgument na in sa.Properties) {
+ output.Write("property ");
+ WriteSecurityDeclarationArgument(na);
+ output.WriteLine();
+ }
+
+ output.Unindent();
+ }
+ output.Write('}');
+
+ if (i + 1< secdecl.SecurityAttributes.Count)
+ output.Write(',');
+ output.WriteLine();
+ }
+ output.Unindent();
+ output.WriteLine("}");
+ }
+ }
+
+ void WriteSecurityDeclarationArgument(CustomAttributeNamedArgument na)
+ {
+ TypeReference type = na.Argument.Type;
+ if (type.MetadataType == MetadataType.Class || type.MetadataType == MetadataType.ValueType) {
+ output.Write("enum ");
+ if (type.Scope != type.Module) {
+ output.Write("class ");
+ output.Write(DisassemblerHelpers.Escape(GetAssemblyQualifiedName(type)));
+ } else {
+ type.WriteTo(output, ILNameSyntax.TypeName);
+ }
+ } else {
+ type.WriteTo(output);
+ }
+ output.Write(' ');
+ output.Write(DisassemblerHelpers.Escape(na.Name));
+ output.Write(" = ");
+ if (na.Argument.Value is string) {
+ // secdecls use special syntax for strings
+ output.Write("string('{0}')", NRefactory.CSharp.TextWriterTokenWriter.ConvertString((string)na.Argument.Value).Replace("'", "\'"));
+ } else {
+ WriteConstant(na.Argument.Value);
+ }
+ }
+
+ string GetAssemblyQualifiedName(TypeReference type)
+ {
+ AssemblyNameReference anr = type.Scope as AssemblyNameReference;
+ if (anr == null) {
+ ModuleDefinition md = type.Scope as ModuleDefinition;
+ if (md != null) {
+ anr = md.Assembly.Name;
+ }
+ }
+ if (anr != null) {
+ return type.FullName + ", " + anr.FullName;
+ } else {
+ return type.FullName;
+ }
+ }
+ #endregion
+
+ #region WriteMarshalInfo
+ void WriteMarshalInfo(MarshalInfo marshalInfo)
+ {
+ output.Write("marshal(");
+ WriteNativeType(marshalInfo.NativeType, marshalInfo);
+ output.Write(") ");
+ }
+
+ void WriteNativeType(NativeType nativeType, MarshalInfo marshalInfo = null)
+ {
+ switch (nativeType) {
+ case NativeType.None:
+ break;
+ case NativeType.Boolean:
+ output.Write("bool");
+ break;
+ case NativeType.I1:
+ output.Write("int8");
+ break;
+ case NativeType.U1:
+ output.Write("unsigned int8");
+ break;
+ case NativeType.I2:
+ output.Write("int16");
+ break;
+ case NativeType.U2:
+ output.Write("unsigned int16");
+ break;
+ case NativeType.I4:
+ output.Write("int32");
+ break;
+ case NativeType.U4:
+ output.Write("unsigned int32");
+ break;
+ case NativeType.I8:
+ output.Write("int64");
+ break;
+ case NativeType.U8:
+ output.Write("unsigned int64");
+ break;
+ case NativeType.R4:
+ output.Write("float32");
+ break;
+ case NativeType.R8:
+ output.Write("float64");
+ break;
+ case NativeType.LPStr:
+ output.Write("lpstr");
+ break;
+ case NativeType.Int:
+ output.Write("int");
+ break;
+ case NativeType.UInt:
+ output.Write("unsigned int");
+ break;
+ case NativeType.Func:
+ goto default; // ??
+ case NativeType.Array:
+ ArrayMarshalInfo ami = (ArrayMarshalInfo)marshalInfo;
+ if (ami == null)
+ goto default;
+ if (ami.ElementType != NativeType.Max)
+ WriteNativeType(ami.ElementType);
+ output.Write('[');
+ if (ami.SizeParameterMultiplier == 0) {
+ output.Write(ami.Size.ToString());
+ } else {
+ if (ami.Size >= 0)
+ output.Write(ami.Size.ToString());
+ output.Write(" + ");
+ output.Write(ami.SizeParameterIndex.ToString());
+ }
+ output.Write(']');
+ break;
+ case NativeType.Currency:
+ output.Write("currency");
+ break;
+ case NativeType.BStr:
+ output.Write("bstr");
+ break;
+ case NativeType.LPWStr:
+ output.Write("lpwstr");
+ break;
+ case NativeType.LPTStr:
+ output.Write("lptstr");
+ break;
+ case NativeType.FixedSysString:
+ output.Write("fixed sysstring[{0}]", ((FixedSysStringMarshalInfo)marshalInfo).Size);
+ break;
+ case NativeType.IUnknown:
+ output.Write("iunknown");
+ break;
+ case NativeType.IDispatch:
+ output.Write("idispatch");
+ break;
+ case NativeType.Struct:
+ output.Write("struct");
+ break;
+ case NativeType.IntF:
+ output.Write("interface");
+ break;
+ case NativeType.SafeArray:
+ output.Write("safearray ");
+ SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo;
+ if (sami != null) {
+ switch (sami.ElementType) {
+ case VariantType.None:
+ break;
+ case VariantType.I2:
+ output.Write("int16");
+ break;
+ case VariantType.I4:
+ output.Write("int32");
+ break;
+ case VariantType.R4:
+ output.Write("float32");
+ break;
+ case VariantType.R8:
+ output.Write("float64");
+ break;
+ case VariantType.CY:
+ output.Write("currency");
+ break;
+ case VariantType.Date:
+ output.Write("date");
+ break;
+ case VariantType.BStr:
+ output.Write("bstr");
+ break;
+ case VariantType.Dispatch:
+ output.Write("idispatch");
+ break;
+ case VariantType.Error:
+ output.Write("error");
+ break;
+ case VariantType.Bool:
+ output.Write("bool");
+ break;
+ case VariantType.Variant:
+ output.Write("variant");
+ break;
+ case VariantType.Unknown:
+ output.Write("iunknown");
+ break;
+ case VariantType.Decimal:
+ output.Write("decimal");
+ break;
+ case VariantType.I1:
+ output.Write("int8");
+ break;
+ case VariantType.UI1:
+ output.Write("unsigned int8");
+ break;
+ case VariantType.UI2:
+ output.Write("unsigned int16");
+ break;
+ case VariantType.UI4:
+ output.Write("unsigned int32");
+ break;
+ case VariantType.Int:
+ output.Write("int");
+ break;
+ case VariantType.UInt:
+ output.Write("unsigned int");
+ break;
+ default:
+ output.Write(sami.ElementType.ToString());
+ break;
+ }
+ }
+ break;
+ case NativeType.FixedArray:
+ output.Write("fixed array");
+ FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo;
+ if (fami != null) {
+ output.Write("[{0}]", fami.Size);
+ if (fami.ElementType != NativeType.None) {
+ output.Write(' ');
+ WriteNativeType(fami.ElementType);
+ }
+ }
+ break;
+ case NativeType.ByValStr:
+ output.Write("byvalstr");
+ break;
+ case NativeType.ANSIBStr:
+ output.Write("ansi bstr");
+ break;
+ case NativeType.TBStr:
+ output.Write("tbstr");
+ break;
+ case NativeType.VariantBool:
+ output.Write("variant bool");
+ break;
+ case NativeType.ASAny:
+ output.Write("as any");
+ break;
+ case NativeType.LPStruct:
+ output.Write("lpstruct");
+ break;
+ case NativeType.CustomMarshaler:
+ CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo;
+ if (cmi == null)
+ goto default;
+ output.Write("custom(\"{0}\", \"{1}\"",
+ NRefactory.CSharp.TextWriterTokenWriter.ConvertString(cmi.ManagedType.FullName),
+ NRefactory.CSharp.TextWriterTokenWriter.ConvertString(cmi.Cookie));
+ if (cmi.Guid != Guid.Empty || !string.IsNullOrEmpty(cmi.UnmanagedType)) {
+ output.Write(", \"{0}\", \"{1}\"", cmi.Guid.ToString(), NRefactory.CSharp.TextWriterTokenWriter.ConvertString(cmi.UnmanagedType));
+ }
+ output.Write(')');
+ break;
+ case NativeType.Error:
+ output.Write("error");
+ break;
+ default:
+ output.Write(nativeType.ToString());
+ break;
+ }
+ }
+ #endregion
+
+ void WriteParameters(Collection<ParameterDefinition> parameters)
+ {
+ for (int i = 0; i < parameters.Count; i++) {
+ var p = parameters[i];
+ if (p.IsIn)
+ output.Write("[in] ");
+ if (p.IsOut)
+ output.Write("[out] ");
+ if (p.IsOptional)
+ output.Write("[opt] ");
+ p.ParameterType.WriteTo(output);
+ output.Write(' ');
+ if (p.HasMarshalInfo) {
+ WriteMarshalInfo(p.MarshalInfo);
+ }
+ output.WriteDefinition(DisassemblerHelpers.Escape(p.Name), p);
+ if (i < parameters.Count - 1)
+ output.Write(',');
+ output.WriteLine();
+ }
+ }
+
+ bool HasParameterAttributes(ParameterDefinition p)
+ {
+ return p.HasConstant || p.HasCustomAttributes;
+ }
+
+ void WriteParameterAttributes(ParameterDefinition p)
+ {
+ if (!HasParameterAttributes(p))
+ return;
+ output.Write(".param [{0}]", p.Index + 1);
+ if (p.HasConstant) {
+ output.Write(" = ");
+ WriteConstant(p.Constant);
+ }
+ output.WriteLine();
+ WriteAttributes(p.CustomAttributes);
+ }
+
+ void WriteConstant(object constant)
+ {
+ if (constant == null) {
+ output.Write("nullref");
+ } else {
+ string typeName = DisassemblerHelpers.PrimitiveTypeName(constant.GetType().FullName);
+ if (typeName != null && typeName != "string") {
+ output.Write(typeName);
+ output.Write('(');
+ float? cf = constant as float?;
+ double? cd = constant as double?;
+ if (cf.HasValue && (float.IsNaN(cf.Value) || float.IsInfinity(cf.Value))) {
+ output.Write("0x{0:x8}", BitConverter.ToInt32(BitConverter.GetBytes(cf.Value), 0));
+ } else if (cd.HasValue && (double.IsNaN(cd.Value) || double.IsInfinity(cd.Value))) {
+ output.Write("0x{0:x16}", BitConverter.DoubleToInt64Bits(cd.Value));
+ } else {
+ DisassemblerHelpers.WriteOperand(output, constant);
+ }
+ output.Write(')');
+ } else {
+ DisassemblerHelpers.WriteOperand(output, constant);
+ }
+ }
+ }
+ #endregion
+
+ #region Disassemble Field
+ EnumNameCollection<FieldAttributes> fieldVisibility = new EnumNameCollection<FieldAttributes>() {
+ { FieldAttributes.Private, "private" },
+ { FieldAttributes.FamANDAssem, "famandassem" },
+ { FieldAttributes.Assembly, "assembly" },
+ { FieldAttributes.Family, "family" },
+ { FieldAttributes.FamORAssem, "famorassem" },
+ { FieldAttributes.Public, "public" },
+ };
+
+ EnumNameCollection<FieldAttributes> fieldAttributes = new EnumNameCollection<FieldAttributes>() {
+ { FieldAttributes.Static, "static" },
+ { FieldAttributes.Literal, "literal" },
+ { FieldAttributes.InitOnly, "initonly" },
+ { FieldAttributes.SpecialName, "specialname" },
+ { FieldAttributes.RTSpecialName, "rtspecialname" },
+ { FieldAttributes.NotSerialized, "notserialized" },
+ };
+
+ public void DisassembleField(FieldDefinition field)
+ {
+ output.WriteDefinition(".field ", field);
+ if (field.HasLayoutInfo) {
+ output.Write("[" + field.Offset + "] ");
+ }
+ WriteEnum(field.Attributes & FieldAttributes.FieldAccessMask, fieldVisibility);
+ const FieldAttributes hasXAttributes = FieldAttributes.HasDefault | FieldAttributes.HasFieldMarshal | FieldAttributes.HasFieldRVA;
+ WriteFlags(field.Attributes & ~(FieldAttributes.FieldAccessMask | hasXAttributes), fieldAttributes);
+ if (field.HasMarshalInfo) {
+ WriteMarshalInfo(field.MarshalInfo);
+ }
+ field.FieldType.WriteTo(output);
+ output.Write(' ');
+ output.Write(DisassemblerHelpers.Escape(field.Name));
+ if ((field.Attributes & FieldAttributes.HasFieldRVA) == FieldAttributes.HasFieldRVA) {
+ output.Write(" at I_{0:x8}", field.RVA);
+ }
+ if (field.HasConstant) {
+ output.Write(" = ");
+ WriteConstant(field.Constant);
+ }
+ output.WriteLine();
+ if (field.HasCustomAttributes) {
+ output.MarkFoldStart();
+ WriteAttributes(field.CustomAttributes);
+ output.MarkFoldEnd();
+ }
+ }
+ #endregion
+
+ #region Disassemble Property
+ EnumNameCollection<PropertyAttributes> propertyAttributes = new EnumNameCollection<PropertyAttributes>() {
+ { PropertyAttributes.SpecialName, "specialname" },
+ { PropertyAttributes.RTSpecialName, "rtspecialname" },
+ { PropertyAttributes.HasDefault, "hasdefault" },
+ };
+
+ public void DisassembleProperty(PropertyDefinition property)
+ {
+ // set current member
+ currentMember = property;
+
+ output.WriteDefinition(".property ", property);
+ WriteFlags(property.Attributes, propertyAttributes);
+ if (property.HasThis)
+ output.Write("instance ");
+ property.PropertyType.WriteTo(output);
+ output.Write(' ');
+ output.Write(DisassemblerHelpers.Escape(property.Name));
+
+ output.Write("(");
+ if (property.HasParameters) {
+ output.WriteLine();
+ output.Indent();
+ WriteParameters(property.Parameters);
+ output.Unindent();
+ }
+ output.Write(")");
+
+ OpenBlock(false);
+ WriteAttributes(property.CustomAttributes);
+ WriteNestedMethod(".get", property.GetMethod);
+ WriteNestedMethod(".set", property.SetMethod);
+
+ foreach (var method in property.OtherMethods) {
+ WriteNestedMethod(".other", method);
+ }
+ CloseBlock();
+ }
+
+ void WriteNestedMethod(string keyword, MethodDefinition method)
+ {
+ if (method == null)
+ return;
+
+ output.Write(keyword);
+ output.Write(' ');
+ method.WriteTo(output);
+ output.WriteLine();
+ }
+ #endregion
+
+ #region Disassemble Event
+ EnumNameCollection<EventAttributes> eventAttributes = new EnumNameCollection<EventAttributes>() {
+ { EventAttributes.SpecialName, "specialname" },
+ { EventAttributes.RTSpecialName, "rtspecialname" },
+ };
+
+ public void DisassembleEvent(EventDefinition ev)
+ {
+ // set current member
+ currentMember = ev;
+
+ output.WriteDefinition(".event ", ev);
+ WriteFlags(ev.Attributes, eventAttributes);
+ ev.EventType.WriteTo(output, ILNameSyntax.TypeName);
+ output.Write(' ');
+ output.Write(DisassemblerHelpers.Escape(ev.Name));
+ OpenBlock(false);
+ WriteAttributes(ev.CustomAttributes);
+ WriteNestedMethod(".addon", ev.AddMethod);
+ WriteNestedMethod(".removeon", ev.RemoveMethod);
+ WriteNestedMethod(".fire", ev.InvokeMethod);
+ foreach (var method in ev.OtherMethods) {
+ WriteNestedMethod(".other", method);
+ }
+ CloseBlock();
+ }
+ #endregion
+
+ #region Disassemble Type
+ EnumNameCollection<TypeAttributes> typeVisibility = new EnumNameCollection<TypeAttributes>() {
+ { TypeAttributes.Public, "public" },
+ { TypeAttributes.NotPublic, "private" },
+ { TypeAttributes.NestedPublic, "nested public" },
+ { TypeAttributes.NestedPrivate, "nested private" },
+ { TypeAttributes.NestedAssembly, "nested assembly" },
+ { TypeAttributes.NestedFamily, "nested family" },
+ { TypeAttributes.NestedFamANDAssem, "nested famandassem" },
+ { TypeAttributes.NestedFamORAssem, "nested famorassem" },
+ };
+
+ EnumNameCollection<TypeAttributes> typeLayout = new EnumNameCollection<TypeAttributes>() {
+ { TypeAttributes.AutoLayout, "auto" },
+ { TypeAttributes.SequentialLayout, "sequential" },
+ { TypeAttributes.ExplicitLayout, "explicit" },
+ };
+
+ EnumNameCollection<TypeAttributes> typeStringFormat = new EnumNameCollection<TypeAttributes>() {
+ { TypeAttributes.AutoClass, "auto" },
+ { TypeAttributes.AnsiClass, "ansi" },
+ { TypeAttributes.UnicodeClass, "unicode" },
+ };
+
+ EnumNameCollection<TypeAttributes> typeAttributes = new EnumNameCollection<TypeAttributes>() {
+ { TypeAttributes.Abstract, "abstract" },
+ { TypeAttributes.Sealed, "sealed" },
+ { TypeAttributes.SpecialName, "specialname" },
+ { TypeAttributes.Import, "import" },
+ { TypeAttributes.Serializable, "serializable" },
+ { TypeAttributes.WindowsRuntime, "windowsruntime" },
+ { TypeAttributes.BeforeFieldInit, "beforefieldinit" },
+ { TypeAttributes.HasSecurity, null },
+ };
+
+ public void DisassembleType(TypeDefinition type)
+ {
+ // start writing IL
+ output.WriteDefinition(".class ", type);
+
+ if ((type.Attributes & TypeAttributes.ClassSemanticMask) == TypeAttributes.Interface)
+ output.Write("interface ");
+ WriteEnum(type.Attributes & TypeAttributes.VisibilityMask, typeVisibility);
+ WriteEnum(type.Attributes & TypeAttributes.LayoutMask, typeLayout);
+ WriteEnum(type.Attributes & TypeAttributes.StringFormatMask, typeStringFormat);
+ const TypeAttributes masks = TypeAttributes.ClassSemanticMask | TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.StringFormatMask;
+ WriteFlags(type.Attributes & ~masks, typeAttributes);
+
+ output.Write(DisassemblerHelpers.Escape(type.DeclaringType != null ? type.Name : type.FullName));
+ WriteTypeParameters(output, type);
+ output.MarkFoldStart(defaultCollapsed: isInType);
+ output.WriteLine();
+
+ if (type.BaseType != null) {
+ output.Indent();
+ output.Write("extends ");
+ type.BaseType.WriteTo(output, ILNameSyntax.TypeName);
+ output.WriteLine();
+ output.Unindent();
+ }
+ if (type.HasInterfaces) {
+ output.Indent();
+ for (int index = 0; index < type.Interfaces.Count; index++) {
+ if (index > 0)
+ output.WriteLine(",");
+ if (index == 0)
+ output.Write("implements ");
+ else
+ output.Write(" ");
+ type.Interfaces[index].WriteTo(output, ILNameSyntax.TypeName);
+ }
+ output.WriteLine();
+ output.Unindent();
+ }
+
+ output.WriteLine("{");
+ output.Indent();
+ bool oldIsInType = isInType;
+ isInType = true;
+ WriteAttributes(type.CustomAttributes);
+ WriteSecurityDeclarations(type);
+ if (type.HasLayoutInfo) {
+ output.WriteLine(".pack {0}", type.PackingSize);
+ output.WriteLine(".size {0}", type.ClassSize);
+ output.WriteLine();
+ }
+ if (type.HasNestedTypes) {
+ output.WriteLine("// Nested Types");
+ foreach (var nestedType in type.NestedTypes) {
+ cancellationToken.ThrowIfCancellationRequested();
+ DisassembleType(nestedType);
+ output.WriteLine();
+ }
+ output.WriteLine();
+ }
+ if (type.HasFields) {
+ output.WriteLine("// Fields");
+ foreach (var field in type.Fields) {
+ cancellationToken.ThrowIfCancellationRequested();
+ DisassembleField(field);
+ }
+ output.WriteLine();
+ }
+ if (type.HasMethods) {
+ output.WriteLine("// Methods");
+ foreach (var m in type.Methods) {
+ cancellationToken.ThrowIfCancellationRequested();
+ DisassembleMethod(m);
+ output.WriteLine();
+ }
+ }
+ if (type.HasEvents) {
+ output.WriteLine("// Events");
+ foreach (var ev in type.Events) {
+ cancellationToken.ThrowIfCancellationRequested();
+ DisassembleEvent(ev);
+ output.WriteLine();
+ }
+ output.WriteLine();
+ }
+ if (type.HasProperties) {
+ output.WriteLine("// Properties");
+ foreach (var prop in type.Properties) {
+ cancellationToken.ThrowIfCancellationRequested();
+ DisassembleProperty(prop);
+ }
+ output.WriteLine();
+ }
+ CloseBlock("end of class " + (type.DeclaringType != null ? type.Name : type.FullName));
+ isInType = oldIsInType;
+ }
+
+ void WriteTypeParameters(ITextOutput output, IGenericParameterProvider p)
+ {
+ if (p.HasGenericParameters) {
+ output.Write('<');
+ for (int i = 0; i < p.GenericParameters.Count; i++) {
+ if (i > 0)
+ output.Write(", ");
+ GenericParameter gp = p.GenericParameters[i];
+ if (gp.HasReferenceTypeConstraint) {
+ output.Write("class ");
+ } else if (gp.HasNotNullableValueTypeConstraint) {
+ output.Write("valuetype ");
+ }
+ if (gp.HasDefaultConstructorConstraint) {
+ output.Write(".ctor ");
+ }
+ if (gp.HasConstraints) {
+ output.Write('(');
+ for (int j = 0; j < gp.Constraints.Count; j++) {
+ if (j > 0)
+ output.Write(", ");
+ gp.Constraints[j].WriteTo(output, ILNameSyntax.TypeName);
+ }
+ output.Write(") ");
+ }
+ if (gp.IsContravariant) {
+ output.Write('-');
+ } else if (gp.IsCovariant) {
+ output.Write('+');
+ }
+ output.Write(DisassemblerHelpers.Escape(gp.Name));
+ }
+ output.Write('>');
+ }
+ }
+ #endregion
+
+ #region Helper methods
+ void WriteAttributes(Collection<CustomAttribute> attributes)
+ {
+ foreach (CustomAttribute a in attributes) {
+ output.Write(".custom ");
+ a.Constructor.WriteTo(output);
+ byte[] blob = a.GetBlob();
+ if (blob != null) {
+ output.Write(" = ");
+ WriteBlob(blob);
+ }
+ output.WriteLine();
+ }
+ }
+
+ void WriteBlob(byte[] blob)
+ {
+ output.Write("(");
+ output.Indent();
+
+ for (int i = 0; i < blob.Length; i++) {
+ if (i % 16 == 0 && i < blob.Length - 1) {
+ output.WriteLine();
+ } else {
+ output.Write(' ');
+ }
+ output.Write(blob[i].ToString("x2"));
+ }
+
+ output.WriteLine();
+ output.Unindent();
+ output.Write(")");
+ }
+
+ void OpenBlock(bool defaultCollapsed)
+ {
+ output.MarkFoldStart(defaultCollapsed: defaultCollapsed);
+ output.WriteLine();
+ output.WriteLine("{");
+ output.Indent();
+ }
+
+ void CloseBlock(string comment = null)
+ {
+ output.Unindent();
+ output.Write("}");
+ if (comment != null)
+ output.Write(" // " + comment);
+ output.MarkFoldEnd();
+ output.WriteLine();
+ }
+
+ void WriteFlags<T>(T flags, EnumNameCollection<T> flagNames) where T : struct
+ {
+ long val = Convert.ToInt64(flags);
+ long tested = 0;
+ foreach (var pair in flagNames) {
+ tested |= pair.Key;
+ if ((val & pair.Key) != 0 && pair.Value != null) {
+ output.Write(pair.Value);
+ output.Write(' ');
+ }
+ }
+ if ((val & ~tested) != 0)
+ output.Write("flag({0:x4}) ", val & ~tested);
+ }
+
+ void WriteEnum<T>(T enumValue, EnumNameCollection<T> enumNames) where T : struct
+ {
+ long val = Convert.ToInt64(enumValue);
+ foreach (var pair in enumNames) {
+ if (pair.Key == val) {
+ if (pair.Value != null) {
+ output.Write(pair.Value);
+ output.Write(' ');
+ }
+ return;
+ }
+ }
+ if (val != 0) {
+ output.Write("flag({0:x4})", val);
+ output.Write(' ');
+ }
+
+ }
+
+ sealed class EnumNameCollection<T> : IEnumerable<KeyValuePair<long, string>> where T : struct
+ {
+ List<KeyValuePair<long, string>> names = new List<KeyValuePair<long, string>>();
+
+ public void Add(T flag, string name)
+ {
+ names.Add(new KeyValuePair<long, string>(Convert.ToInt64(flag), name));
+ }
+
+ public IEnumerator<KeyValuePair<long, string>> GetEnumerator()
+ {
+ return names.GetEnumerator();
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return names.GetEnumerator();
+ }
+ }
+ #endregion
+
+ public void DisassembleNamespace(string nameSpace, IEnumerable<TypeDefinition> types)
+ {
+ if (!string.IsNullOrEmpty(nameSpace)) {
+ output.Write(".namespace " + DisassemblerHelpers.Escape(nameSpace));
+ OpenBlock(false);
+ }
+ bool oldIsInType = isInType;
+ isInType = true;
+ foreach (TypeDefinition td in types) {
+ cancellationToken.ThrowIfCancellationRequested();
+ DisassembleType(td);
+ output.WriteLine();
+ }
+ if (!string.IsNullOrEmpty(nameSpace)) {
+ CloseBlock();
+ isInType = oldIsInType;
+ }
+ }
+
+ public void WriteAssemblyHeader(AssemblyDefinition asm)
+ {
+ output.Write(".assembly ");
+ if (asm.Name.IsWindowsRuntime)
+ output.Write("windowsruntime ");
+ output.Write(DisassemblerHelpers.Escape(asm.Name.Name));
+ OpenBlock(false);
+ WriteAttributes(asm.CustomAttributes);
+ WriteSecurityDeclarations(asm);
+ if (asm.Name.PublicKey != null && asm.Name.PublicKey.Length > 0) {
+ output.Write(".publickey = ");
+ WriteBlob(asm.Name.PublicKey);
+ output.WriteLine();
+ }
+ if (asm.Name.HashAlgorithm != AssemblyHashAlgorithm.None) {
+ output.Write(".hash algorithm 0x{0:x8}", (int)asm.Name.HashAlgorithm);
+ if (asm.Name.HashAlgorithm == AssemblyHashAlgorithm.SHA1)
+ output.Write(" // SHA1");
+ output.WriteLine();
+ }
+ Version v = asm.Name.Version;
+ if (v != null) {
+ output.WriteLine(".ver {0}:{1}:{2}:{3}", v.Major, v.Minor, v.Build, v.Revision);
+ }
+ CloseBlock();
+ }
+
+ public void WriteAssemblyReferences(ModuleDefinition module)
+ {
+ foreach (var mref in module.ModuleReferences) {
+ output.WriteLine(".module extern {0}", DisassemblerHelpers.Escape(mref.Name));
+ }
+ foreach (var aref in module.AssemblyReferences) {
+ output.Write(".assembly extern ");
+ if (aref.IsWindowsRuntime)
+ output.Write("windowsruntime ");
+ output.Write(DisassemblerHelpers.Escape(aref.Name));
+ OpenBlock(false);
+ if (aref.PublicKeyToken != null) {
+ output.Write(".publickeytoken = ");
+ WriteBlob(aref.PublicKeyToken);
+ output.WriteLine();
+ }
+ if (aref.Version != null) {
+ output.WriteLine(".ver {0}:{1}:{2}:{3}", aref.Version.Major, aref.Version.Minor, aref.Version.Build, aref.Version.Revision);
+ }
+ CloseBlock();
+ }
+ }
+
+ public void WriteModuleHeader(ModuleDefinition module)
+ {
+ if (module.HasExportedTypes) {
+ foreach (ExportedType exportedType in module.ExportedTypes) {
+ output.Write(".class extern ");
+ if (exportedType.IsForwarder)
+ output.Write("forwarder ");
+ output.Write(exportedType.DeclaringType != null ? exportedType.Name : exportedType.FullName);
+ OpenBlock(false);
+ if (exportedType.DeclaringType != null)
+ output.WriteLine(".class extern {0}", DisassemblerHelpers.Escape(exportedType.DeclaringType.FullName));
+ else
+ output.WriteLine(".assembly extern {0}", DisassemblerHelpers.Escape(exportedType.Scope.Name));
+ CloseBlock();
+ }
+ }
+
+ output.WriteLine(".module {0}", module.Name);
+ output.WriteLine("// MVID: {0}", module.Mvid.ToString("B").ToUpperInvariant());
+ // TODO: imagebase, file alignment, stackreserve, subsystem
+ output.WriteLine(".corflags 0x{0:x} // {1}", module.Attributes, module.Attributes.ToString());
+
+ WriteAttributes(module.CustomAttributes);
+ }
+
+ public void WriteModuleContents(ModuleDefinition module)
+ {
+ foreach (TypeDefinition td in module.Types) {
+ DisassembleType(td);
+ output.WriteLine();
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowEdge.cs b/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowEdge.cs
new file mode 100644
index 00000000..98bd4399
--- /dev/null
+++ b/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowEdge.cs
@@ -0,0 +1,78 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+namespace ICSharpCode.Decompiler.FlowAnalysis
+{
+ /// <summary>
+ /// Describes the type of a control flow egde.
+ /// </summary>
+ public enum JumpType
+ {
+ /// <summary>
+ /// A regular control flow edge.
+ /// </summary>
+ Normal,
+ /// <summary>
+ /// Jump to exception handler (an exception occurred)
+ /// </summary>
+ JumpToExceptionHandler,
+ /// <summary>
+ /// Jump from try block to leave target:
+ /// This is not a real jump, as the finally handler is executed first!
+ /// </summary>
+ LeaveTry,
+ /// <summary>
+ /// Jump at endfinally (to any of the potential leave targets).
+ /// For any leave-instruction, control flow enters the finally block - the edge to the leave target (LeaveTry) is not a real control flow edge.
+ /// EndFinally edges are inserted at the end of the finally block, jumping to any of the targets of the leave instruction.
+ /// This edge type is only used when copying of finally blocks is disabled (with copying, a normal deterministic edge is used at each copy of the endfinally node).
+ /// </summary>
+ EndFinally
+ }
+
+ /// <summary>
+ /// Represents an edge in the control flow graph, pointing from Source to Target.
+ /// </summary>
+ public sealed class ControlFlowEdge
+ {
+ public readonly ControlFlowNode Source;
+ public readonly ControlFlowNode Target;
+ public readonly JumpType Type;
+
+ public ControlFlowEdge(ControlFlowNode source, ControlFlowNode target, JumpType type)
+ {
+ Source = source;
+ Target = target;
+ Type = type;
+ }
+
+ public override string ToString()
+ {
+ switch (Type) {
+ case JumpType.Normal:
+ return "#" + Target.BlockIndex;
+ case JumpType.JumpToExceptionHandler:
+ return "e:#" + Target.BlockIndex;
+ default:
+ return Type.ToString() + ":#" + Target.BlockIndex;
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraph.cs b/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraph.cs
new file mode 100644
index 00000000..7cc815a6
--- /dev/null
+++ b/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraph.cs
@@ -0,0 +1,191 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+
+using ICSharpCode.NRefactory.Utils;
+
+namespace ICSharpCode.Decompiler.FlowAnalysis
+{
+ /// <summary>
+ /// Contains the control flow graph.
+ /// </summary>
+ /// <remarks>Use ControlFlowGraph builder to create instances of the ControlFlowGraph.</remarks>
+ public sealed class ControlFlowGraph
+ {
+ readonly ReadOnlyCollection<ControlFlowNode> nodes;
+
+ public ControlFlowNode EntryPoint {
+ get { return nodes[0]; }
+ }
+
+ public ControlFlowNode RegularExit {
+ get { return nodes[1]; }
+ }
+
+ public ControlFlowNode ExceptionalExit {
+ get { return nodes[2]; }
+ }
+
+ public ReadOnlyCollection<ControlFlowNode> Nodes {
+ get { return nodes; }
+ }
+
+ internal ControlFlowGraph(ControlFlowNode[] nodes)
+ {
+ this.nodes = new ReadOnlyCollection<ControlFlowNode>(nodes);
+ Debug.Assert(EntryPoint.NodeType == ControlFlowNodeType.EntryPoint);
+ Debug.Assert(RegularExit.NodeType == ControlFlowNodeType.RegularExit);
+ Debug.Assert(ExceptionalExit.NodeType == ControlFlowNodeType.ExceptionalExit);
+ }
+
+ public GraphVizGraph ExportGraph()
+ {
+ GraphVizGraph graph = new GraphVizGraph();
+ foreach (ControlFlowNode node in nodes) {
+ graph.AddNode(new GraphVizNode(node.BlockIndex) { label = node.ToString(), shape = "box" });
+ }
+ foreach (ControlFlowNode node in nodes) {
+ foreach (ControlFlowEdge edge in node.Outgoing) {
+ GraphVizEdge e = new GraphVizEdge(edge.Source.BlockIndex, edge.Target.BlockIndex);
+ switch (edge.Type) {
+ case JumpType.Normal:
+ break;
+ case JumpType.LeaveTry:
+ case JumpType.EndFinally:
+ e.color = "red";
+ break;
+ default:
+ e.color = "gray";
+ //e.constraint = false;
+ break;
+ }
+ graph.AddEdge(e);
+ }
+ if (node.ImmediateDominator != null) {
+ graph.AddEdge(new GraphVizEdge(node.ImmediateDominator.BlockIndex, node.BlockIndex) { color = "green", constraint = false });
+ }
+ }
+ return graph;
+ }
+
+ /// <summary>
+ /// Resets "Visited" to false for all nodes in this graph.
+ /// </summary>
+ public void ResetVisited()
+ {
+ foreach (ControlFlowNode node in nodes) {
+ node.Visited = false;
+ }
+ }
+
+ /// <summary>
+ /// Computes the dominator tree.
+ /// </summary>
+ public void ComputeDominance(CancellationToken cancellationToken = default(CancellationToken))
+ {
+ // A Simple, Fast Dominance Algorithm
+ // Keith D. Cooper, Timothy J. Harvey and Ken Kennedy
+
+ EntryPoint.ImmediateDominator = EntryPoint;
+ bool changed = true;
+ while (changed) {
+ changed = false;
+ ResetVisited();
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ // for all nodes b except the entry point
+ EntryPoint.TraversePreOrder(
+ b => b.Successors,
+ b => {
+ if (b != EntryPoint) {
+ ControlFlowNode newIdom = b.Predecessors.First(block => block.Visited && block != b);
+ // for all other predecessors p of b
+ foreach (ControlFlowNode p in b.Predecessors) {
+ if (p != b && p.ImmediateDominator != null) {
+ newIdom = FindCommonDominator(p, newIdom);
+ }
+ }
+ if (b.ImmediateDominator != newIdom) {
+ b.ImmediateDominator = newIdom;
+ changed = true;
+ }
+ }
+ });
+ }
+ EntryPoint.ImmediateDominator = null;
+ foreach (ControlFlowNode node in nodes) {
+ if (node.ImmediateDominator != null)
+ node.ImmediateDominator.DominatorTreeChildren.Add(node);
+ }
+ }
+
+ static ControlFlowNode FindCommonDominator(ControlFlowNode b1, ControlFlowNode b2)
+ {
+ // Here we could use the postorder numbers to get rid of the hashset, see "A Simple, Fast Dominance Algorithm"
+ HashSet<ControlFlowNode> path1 = new HashSet<ControlFlowNode>();
+ while (b1 != null && path1.Add(b1))
+ b1 = b1.ImmediateDominator;
+ while (b2 != null) {
+ if (path1.Contains(b2))
+ return b2;
+ else
+ b2 = b2.ImmediateDominator;
+ }
+ throw new Exception("No common dominator found!");
+ }
+
+ /// <summary>
+ /// Computes dominance frontiers.
+ /// This method requires that the dominator tree is already computed!
+ /// </summary>
+ public void ComputeDominanceFrontier()
+ {
+ ResetVisited();
+
+ EntryPoint.TraversePostOrder(
+ b => b.DominatorTreeChildren,
+ n => {
+ //logger.WriteLine("Calculating dominance frontier for " + n.Name);
+ n.DominanceFrontier = new HashSet<ControlFlowNode>();
+ // DF_local computation
+ foreach (ControlFlowNode succ in n.Successors) {
+ if (succ.ImmediateDominator != n) {
+ //logger.WriteLine(" local: " + succ.Name);
+ n.DominanceFrontier.Add(succ);
+ }
+ }
+ // DF_up computation
+ foreach (ControlFlowNode child in n.DominatorTreeChildren) {
+ foreach (ControlFlowNode p in child.DominanceFrontier) {
+ if (p.ImmediateDominator != n) {
+ //logger.WriteLine(" DF_up: " + p.Name + " (child=" + child.Name);
+ n.DominanceFrontier.Add(p);
+ }
+ }
+ }
+ });
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraphBuilder.cs b/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraphBuilder.cs
new file mode 100644
index 00000000..7570884a
--- /dev/null
+++ b/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraphBuilder.cs
@@ -0,0 +1,439 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.FlowAnalysis
+{
+ /// <summary>
+ /// Constructs the Control Flow Graph from a Cecil method body.
+ /// </summary>
+ public sealed class ControlFlowGraphBuilder
+ {
+ public static ControlFlowGraph Build(MethodBody methodBody)
+ {
+ return new ControlFlowGraphBuilder(methodBody).Build();
+ }
+
+ // This option controls how finally blocks are handled:
+ // false means that the endfinally instruction will jump to any of the leave targets (EndFinally edge type).
+ // true means that a copy of the whole finally block is created for each leave target. In this case, each endfinally node will be connected with the leave
+ // target using a normal edge.
+ bool copyFinallyBlocks = false;
+
+ MethodBody methodBody;
+ int[] offsets; // array index = instruction index; value = IL offset
+ bool[] hasIncomingJumps; // array index = instruction index
+ List<ControlFlowNode> nodes = new List<ControlFlowNode>();
+ ControlFlowNode entryPoint;
+ ControlFlowNode regularExit;
+ ControlFlowNode exceptionalExit;
+
+ ControlFlowGraphBuilder(MethodBody methodBody)
+ {
+ this.methodBody = methodBody;
+ offsets = methodBody.Instructions.Select(i => i.Offset).ToArray();
+ hasIncomingJumps = new bool[methodBody.Instructions.Count];
+
+ entryPoint = new ControlFlowNode(0, 0, ControlFlowNodeType.EntryPoint);
+ nodes.Add(entryPoint);
+ regularExit = new ControlFlowNode(1, -1, ControlFlowNodeType.RegularExit);
+ nodes.Add(regularExit);
+ exceptionalExit = new ControlFlowNode(2, -1, ControlFlowNodeType.ExceptionalExit);
+ nodes.Add(exceptionalExit);
+ Debug.Assert(nodes.Count == 3);
+ }
+
+ /// <summary>
+ /// Determines the index of the instruction (for use with the hasIncomingJumps array)
+ /// </summary>
+ int GetInstructionIndex(Instruction inst)
+ {
+ int index = Array.BinarySearch(offsets, inst.Offset);
+ Debug.Assert(index >= 0);
+ return index;
+ }
+
+ /// <summary>
+ /// Builds the ControlFlowGraph.
+ /// </summary>
+ public ControlFlowGraph Build()
+ {
+ CalculateHasIncomingJumps();
+ CreateNodes();
+ CreateRegularControlFlow();
+ CreateExceptionalControlFlow();
+ if (copyFinallyBlocks)
+ CopyFinallyBlocksIntoLeaveEdges();
+ else
+ TransformLeaveEdges();
+ return new ControlFlowGraph(nodes.ToArray());
+ }
+
+ #region Step 1: calculate which instructions are the targets of jump instructions.
+ void CalculateHasIncomingJumps()
+ {
+ foreach (Instruction inst in methodBody.Instructions) {
+ if (inst.OpCode.OperandType == OperandType.InlineBrTarget || inst.OpCode.OperandType == OperandType.ShortInlineBrTarget) {
+ hasIncomingJumps[GetInstructionIndex((Instruction)inst.Operand)] = true;
+ } else if (inst.OpCode.OperandType == OperandType.InlineSwitch) {
+ foreach (Instruction i in (Instruction[])inst.Operand)
+ hasIncomingJumps[GetInstructionIndex(i)] = true;
+ }
+ }
+ foreach (ExceptionHandler eh in methodBody.ExceptionHandlers) {
+ if (eh.FilterStart != null) {
+ hasIncomingJumps[GetInstructionIndex(eh.FilterStart)] = true;
+ }
+ hasIncomingJumps[GetInstructionIndex(eh.HandlerStart)] = true;
+ }
+ }
+ #endregion
+
+ #region Step 2: create nodes
+ void CreateNodes()
+ {
+ // Step 2a: find basic blocks and create nodes for them
+ for (int i = 0; i < methodBody.Instructions.Count; i++) {
+ Instruction blockStart = methodBody.Instructions[i];
+ ExceptionHandler blockStartEH = FindInnermostExceptionHandler(blockStart.Offset);
+ // try and see how big we can make that block:
+ for (; i + 1 < methodBody.Instructions.Count; i++) {
+ Instruction inst = methodBody.Instructions[i];
+ if (IsBranch(inst.OpCode) || CanThrowException(inst.OpCode))
+ break;
+ if (hasIncomingJumps[i + 1])
+ break;
+ if (inst.Next != null) {
+ // ensure that blocks never contain instructions from different try blocks
+ ExceptionHandler instEH = FindInnermostExceptionHandler(inst.Next.Offset);
+ if (instEH != blockStartEH)
+ break;
+ }
+ }
+
+ nodes.Add(new ControlFlowNode(nodes.Count, blockStart, methodBody.Instructions[i]));
+ }
+ // Step 2b: Create special nodes for the exception handling constructs
+ foreach (ExceptionHandler handler in methodBody.ExceptionHandlers) {
+ if (handler.HandlerType == ExceptionHandlerType.Filter)
+ throw new NotSupportedException();
+ ControlFlowNode endFinallyOrFaultNode = null;
+ if (handler.HandlerType == ExceptionHandlerType.Finally || handler.HandlerType == ExceptionHandlerType.Fault) {
+ endFinallyOrFaultNode = new ControlFlowNode(nodes.Count, handler.HandlerEnd.Offset, ControlFlowNodeType.EndFinallyOrFault);
+ nodes.Add(endFinallyOrFaultNode);
+ }
+ nodes.Add(new ControlFlowNode(nodes.Count, handler, endFinallyOrFaultNode));
+ }
+ }
+ #endregion
+
+ #region Step 3: create edges for the normal flow of control (assuming no exceptions thrown)
+ void CreateRegularControlFlow()
+ {
+ CreateEdge(entryPoint, methodBody.Instructions[0], JumpType.Normal);
+ foreach (ControlFlowNode node in nodes) {
+ if (node.End != null) {
+ // create normal edges from one instruction to the next
+ if (!OpCodeInfo.IsUnconditionalBranch(node.End.OpCode))
+ CreateEdge(node, node.End.Next, JumpType.Normal);
+
+ // create edges for branch instructions
+ if (node.End.OpCode.OperandType == OperandType.InlineBrTarget || node.End.OpCode.OperandType == OperandType.ShortInlineBrTarget) {
+ if (node.End.OpCode == OpCodes.Leave || node.End.OpCode == OpCodes.Leave_S) {
+ var handlerBlock = FindInnermostHandlerBlock(node.End.Offset);
+ if (handlerBlock.NodeType == ControlFlowNodeType.FinallyOrFaultHandler)
+ CreateEdge(node, (Instruction)node.End.Operand, JumpType.LeaveTry);
+ else
+ CreateEdge(node, (Instruction)node.End.Operand, JumpType.Normal);
+ } else {
+ CreateEdge(node, (Instruction)node.End.Operand, JumpType.Normal);
+ }
+ } else if (node.End.OpCode.OperandType == OperandType.InlineSwitch) {
+ foreach (Instruction i in (Instruction[])node.End.Operand)
+ CreateEdge(node, i, JumpType.Normal);
+ }
+
+ // create edges for return instructions
+ if (node.End.OpCode.FlowControl == FlowControl.Return) {
+ switch (node.End.OpCode.Code) {
+ case Code.Ret:
+ CreateEdge(node, regularExit, JumpType.Normal);
+ break;
+ case Code.Endfinally:
+ ControlFlowNode handlerBlock = FindInnermostHandlerBlock(node.End.Offset);
+ if (handlerBlock.EndFinallyOrFaultNode == null)
+ throw new InvalidProgramException("Found endfinally in block " + handlerBlock);
+ CreateEdge(node, handlerBlock.EndFinallyOrFaultNode, JumpType.Normal);
+ break;
+ default:
+ throw new NotSupportedException(node.End.OpCode.ToString());
+ }
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region Step 4: create edges for the exceptional control flow (from instructions that might throw, to the innermost containing exception handler)
+ void CreateExceptionalControlFlow()
+ {
+ foreach (ControlFlowNode node in nodes) {
+ if (node.End != null && CanThrowException(node.End.OpCode)) {
+ CreateEdge(node, FindInnermostExceptionHandlerNode(node.End.Offset), JumpType.JumpToExceptionHandler);
+ }
+ if (node.ExceptionHandler != null) {
+ if (node.EndFinallyOrFaultNode != null) {
+ // For Fault and Finally blocks, create edge from "EndFinally" to next exception handler.
+ // This represents the exception bubbling up after finally block was executed.
+ CreateEdge(node.EndFinallyOrFaultNode, FindParentExceptionHandlerNode(node), JumpType.JumpToExceptionHandler);
+ } else {
+ // For Catch blocks, create edge from "CatchHandler" block (at beginning) to next exception handler.
+ // This represents the exception bubbling up because it did not match the type of the catch block.
+ CreateEdge(node, FindParentExceptionHandlerNode(node), JumpType.JumpToExceptionHandler);
+ }
+ CreateEdge(node, node.ExceptionHandler.HandlerStart, JumpType.Normal);
+ }
+ }
+ }
+
+ ExceptionHandler FindInnermostExceptionHandler(int instructionOffsetInTryBlock)
+ {
+ foreach (ExceptionHandler h in methodBody.ExceptionHandlers) {
+ if (h.TryStart.Offset <= instructionOffsetInTryBlock && instructionOffsetInTryBlock < h.TryEnd.Offset) {
+ return h;
+ }
+ }
+ return null;
+ }
+
+ ControlFlowNode FindInnermostExceptionHandlerNode(int instructionOffsetInTryBlock)
+ {
+ ExceptionHandler h = FindInnermostExceptionHandler(instructionOffsetInTryBlock);
+ if (h != null)
+ return nodes.Single(n => n.ExceptionHandler == h && n.CopyFrom == null);
+ else
+ return exceptionalExit;
+ }
+
+ ControlFlowNode FindInnermostHandlerBlock(int instructionOffset)
+ {
+ foreach (ExceptionHandler h in methodBody.ExceptionHandlers) {
+ if (h.TryStart.Offset <= instructionOffset && instructionOffset < h.TryEnd.Offset
+ || h.HandlerStart.Offset <= instructionOffset && instructionOffset < h.HandlerEnd.Offset)
+ {
+ return nodes.Single(n => n.ExceptionHandler == h && n.CopyFrom == null);
+ }
+ }
+ return exceptionalExit;
+ }
+
+ ControlFlowNode FindParentExceptionHandlerNode(ControlFlowNode exceptionHandler)
+ {
+ Debug.Assert(exceptionHandler.NodeType == ControlFlowNodeType.CatchHandler
+ || exceptionHandler.NodeType == ControlFlowNodeType.FinallyOrFaultHandler);
+ int offset = exceptionHandler.ExceptionHandler.TryStart.Offset;
+ for (int i = exceptionHandler.BlockIndex + 1; i < nodes.Count; i++) {
+ ExceptionHandler h = nodes[i].ExceptionHandler;
+ if (h != null && h.TryStart.Offset <= offset && offset < h.TryEnd.Offset)
+ return nodes[i];
+ }
+ return exceptionalExit;
+ }
+ #endregion
+
+ #region Step 5a: replace LeaveTry edges with EndFinally edges
+ // this is used only for copyFinallyBlocks==false; see Step 5b otherwise
+ void TransformLeaveEdges()
+ {
+ for (int i = nodes.Count - 1; i >= 0; i--) {
+ ControlFlowNode node = nodes[i];
+ if (node.End != null && node.Outgoing.Count == 1 && node.Outgoing[0].Type == JumpType.LeaveTry) {
+ Debug.Assert(node.End.OpCode == OpCodes.Leave || node.End.OpCode == OpCodes.Leave_S);
+
+ ControlFlowNode target = node.Outgoing[0].Target;
+ // remove the edge
+ target.Incoming.Remove(node.Outgoing[0]);
+ node.Outgoing.Clear();
+
+ ControlFlowNode handler = FindInnermostExceptionHandlerNode(node.End.Offset);
+ Debug.Assert(handler.NodeType == ControlFlowNodeType.FinallyOrFaultHandler);
+
+ CreateEdge(node, handler, JumpType.Normal);
+ CreateEdge(handler.EndFinallyOrFaultNode, target, JumpType.EndFinally);
+ }
+ }
+ }
+ #endregion
+
+ #region Step 5b: copy finally blocks into the LeaveTry edges
+ void CopyFinallyBlocksIntoLeaveEdges()
+ {
+ // We need to process try-finally blocks inside-out.
+ // We'll do that by going through all instructions in reverse order
+ for (int i = nodes.Count - 1; i >= 0; i--) {
+ ControlFlowNode node = nodes[i];
+ if (node.End != null && node.Outgoing.Count == 1 && node.Outgoing[0].Type == JumpType.LeaveTry) {
+ Debug.Assert(node.End.OpCode == OpCodes.Leave || node.End.OpCode == OpCodes.Leave_S);
+
+ ControlFlowNode target = node.Outgoing[0].Target;
+ // remove the edge
+ target.Incoming.Remove(node.Outgoing[0]);
+ node.Outgoing.Clear();
+
+ ControlFlowNode handler = FindInnermostExceptionHandlerNode(node.End.Offset);
+ Debug.Assert(handler.NodeType == ControlFlowNodeType.FinallyOrFaultHandler);
+
+ ControlFlowNode copy = CopyFinallySubGraph(handler, handler.EndFinallyOrFaultNode, target);
+ CreateEdge(node, copy, JumpType.Normal);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Creates a copy of all nodes pointing to 'end' and replaces those references with references to 'newEnd'.
+ /// Nodes pointing to the copied node are copied recursively to update those references, too.
+ /// This recursion stops at 'start'. The modified version of start is returned.
+ /// </summary>
+ ControlFlowNode CopyFinallySubGraph(ControlFlowNode start, ControlFlowNode end, ControlFlowNode newEnd)
+ {
+ return new CopyFinallySubGraphLogic(this, start, end, newEnd).CopyFinallySubGraph();
+ }
+
+ class CopyFinallySubGraphLogic
+ {
+ readonly ControlFlowGraphBuilder builder;
+ readonly Dictionary<ControlFlowNode, ControlFlowNode> oldToNew = new Dictionary<ControlFlowNode, ControlFlowNode>();
+ readonly ControlFlowNode start;
+ readonly ControlFlowNode end;
+ readonly ControlFlowNode newEnd;
+
+ public CopyFinallySubGraphLogic(ControlFlowGraphBuilder builder, ControlFlowNode start, ControlFlowNode end, ControlFlowNode newEnd)
+ {
+ this.builder = builder;
+ this.start = start;
+ this.end = end;
+ this.newEnd = newEnd;
+ }
+
+ internal ControlFlowNode CopyFinallySubGraph()
+ {
+ foreach (ControlFlowNode n in end.Predecessors) {
+ CollectNodes(n);
+ }
+ foreach (var pair in oldToNew)
+ ReconstructEdges(pair.Key, pair.Value);
+ return GetNew(start);
+ }
+
+ void CollectNodes(ControlFlowNode node)
+ {
+ if (node == end || node == newEnd)
+ throw new InvalidOperationException("unexpected cycle involving finally construct");
+ if (!oldToNew.ContainsKey(node)) {
+ int newBlockIndex = builder.nodes.Count;
+ ControlFlowNode copy;
+ switch (node.NodeType) {
+ case ControlFlowNodeType.Normal:
+ copy = new ControlFlowNode(newBlockIndex, node.Start, node.End);
+ break;
+ case ControlFlowNodeType.FinallyOrFaultHandler:
+ copy = new ControlFlowNode(newBlockIndex, node.ExceptionHandler, node.EndFinallyOrFaultNode);
+ break;
+ default:
+ // other nodes shouldn't occur when copying finally blocks
+ throw new NotSupportedException(node.NodeType.ToString());
+ }
+ copy.CopyFrom = node;
+ builder.nodes.Add(copy);
+ oldToNew.Add(node, copy);
+
+ if (node != start) {
+ foreach (ControlFlowNode n in node.Predecessors) {
+ CollectNodes(n);
+ }
+ }
+ }
+ }
+
+ void ReconstructEdges(ControlFlowNode oldNode, ControlFlowNode newNode)
+ {
+ foreach (ControlFlowEdge oldEdge in oldNode.Outgoing) {
+ builder.CreateEdge(newNode, GetNew(oldEdge.Target), oldEdge.Type);
+ }
+ }
+
+ ControlFlowNode GetNew(ControlFlowNode oldNode)
+ {
+ if (oldNode == end)
+ return newEnd;
+ ControlFlowNode newNode;
+ if (oldToNew.TryGetValue(oldNode, out newNode))
+ return newNode;
+ return oldNode;
+ }
+ }
+ #endregion
+
+ #region CreateEdge methods
+ void CreateEdge(ControlFlowNode fromNode, Instruction toInstruction, JumpType type)
+ {
+ CreateEdge(fromNode, nodes.Single(n => n.Start == toInstruction), type);
+ }
+
+ void CreateEdge(ControlFlowNode fromNode, ControlFlowNode toNode, JumpType type)
+ {
+ ControlFlowEdge edge = new ControlFlowEdge(fromNode, toNode, type);
+ fromNode.Outgoing.Add(edge);
+ toNode.Incoming.Add(edge);
+ }
+ #endregion
+
+ #region OpCode info
+ static bool CanThrowException(OpCode opcode)
+ {
+ if (opcode.OpCodeType == OpCodeType.Prefix)
+ return false;
+ return OpCodeInfo.Get(opcode).CanThrow;
+ }
+
+ static bool IsBranch(OpCode opcode)
+ {
+ if (opcode.OpCodeType == OpCodeType.Prefix)
+ return false;
+ switch (opcode.FlowControl) {
+ case FlowControl.Cond_Branch:
+ case FlowControl.Branch:
+ case FlowControl.Throw:
+ case FlowControl.Return:
+ return true;
+ case FlowControl.Next:
+ case FlowControl.Call:
+ return false;
+ default:
+ throw new NotSupportedException(opcode.FlowControl.ToString());
+ }
+ }
+ #endregion
+ }
+}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs b/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs
new file mode 100644
index 00000000..83294fd9
--- /dev/null
+++ b/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs
@@ -0,0 +1,305 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+
+using ICSharpCode.Decompiler.Disassembler;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.FlowAnalysis
+{
+ /// <summary>
+ /// Type of the control flow node
+ /// </summary>
+ public enum ControlFlowNodeType
+ {
+ /// <summary>
+ /// A normal node represents a basic block.
+ /// </summary>
+ Normal,
+ /// <summary>
+ /// The entry point of the method.
+ /// </summary>
+ EntryPoint,
+ /// <summary>
+ /// The exit point of the method (every ret instruction branches to this node)
+ /// </summary>
+ RegularExit,
+ /// <summary>
+ /// This node represents leaving a method irregularly by throwing an exception.
+ /// </summary>
+ ExceptionalExit,
+ /// <summary>
+ /// This node is used as a header for exception handler blocks.
+ /// </summary>
+ CatchHandler,
+ /// <summary>
+ /// This node is used as a header for finally blocks and fault blocks.
+ /// Every leave instruction in the try block leads to the handler of the containing finally block;
+ /// and exceptional control flow also leads to this handler.
+ /// </summary>
+ FinallyOrFaultHandler,
+ /// <summary>
+ /// This node is used as footer for finally blocks and fault blocks.
+ /// Depending on the "copyFinallyBlocks" option used when creating the graph, it is connected with all leave targets using
+ /// EndFinally edges (when not copying); or with a specific leave target using a normal edge (when copying).
+ /// For fault blocks, an exception edge is used to represent the "re-throwing" of the exception.
+ /// </summary>
+ EndFinallyOrFault
+ }
+
+ /// <summary>
+ /// Represents a block in the control flow graph.
+ /// </summary>
+ public sealed class ControlFlowNode
+ {
+ /// <summary>
+ /// Index of this node in the ControlFlowGraph.Nodes collection.
+ /// </summary>
+ public readonly int BlockIndex;
+
+ /// <summary>
+ /// Gets the IL offset of this node.
+ /// </summary>
+ public readonly int Offset;
+
+ /// <summary>
+ /// Type of the node.
+ /// </summary>
+ public readonly ControlFlowNodeType NodeType;
+
+ /// <summary>
+ /// If this node is a FinallyOrFaultHandler node, this field points to the corresponding EndFinallyOrFault node.
+ /// Otherwise, this field is null.
+ /// </summary>
+ public readonly ControlFlowNode EndFinallyOrFaultNode;
+
+ /// <summary>
+ /// Visited flag, used in various algorithms.
+ /// Before using it in your algorithm, reset it to false by calling ControlFlowGraph.ResetVisited();
+ /// </summary>
+ public bool Visited;
+
+ /// <summary>
+ /// Gets whether this node is reachable. Requires that dominance is computed!
+ /// </summary>
+ public bool IsReachable {
+ get { return ImmediateDominator != null || NodeType == ControlFlowNodeType.EntryPoint; }
+ }
+
+ /// <summary>
+ /// Signalizes that this node is a copy of another node.
+ /// </summary>
+ public ControlFlowNode CopyFrom { get; internal set; }
+
+ /// <summary>
+ /// Gets the immediate dominator (the parent in the dominator tree).
+ /// Null if dominance has not been calculated; or if the node is unreachable.
+ /// </summary>
+ public ControlFlowNode ImmediateDominator { get; internal set; }
+
+ /// <summary>
+ /// List of children in the dominator tree.
+ /// </summary>
+ public readonly List<ControlFlowNode> DominatorTreeChildren = new List<ControlFlowNode>();
+
+ /// <summary>
+ /// The dominance frontier of this node.
+ /// This is the set of nodes for which this node dominates a predecessor, but which are not strictly dominated by this node.
+ /// </summary>
+ /// <remarks>
+ /// b.DominanceFrontier = { y in CFG; (exists p in predecessors(y): b dominates p) and not (b strictly dominates y)}
+ /// </remarks>
+ public HashSet<ControlFlowNode> DominanceFrontier;
+
+ /// <summary>
+ /// Start of code block represented by this node. Only set for nodetype == Normal.
+ /// </summary>
+ public readonly Instruction Start;
+
+ /// <summary>
+ /// End of the code block represented by this node. Only set for nodetype == Normal.
+ /// The end is exclusive, the end instruction itself does not belong to this block.
+ /// </summary>
+ public readonly Instruction End;
+
+ /// <summary>
+ /// Gets the exception handler associated with this node.
+ /// Only set for nodetype == CatchHandler or nodetype == FinallyOrFaultHandler.
+ /// </summary>
+ public readonly ExceptionHandler ExceptionHandler;
+
+ /// <summary>
+ /// List of incoming control flow edges.
+ /// </summary>
+ public readonly List<ControlFlowEdge> Incoming = new List<ControlFlowEdge>();
+
+ /// <summary>
+ /// List of outgoing control flow edges.
+ /// </summary>
+ public readonly List<ControlFlowEdge> Outgoing = new List<ControlFlowEdge>();
+
+ /// <summary>
+ /// Any user data
+ /// </summary>
+ public object UserData;
+
+ internal ControlFlowNode(int blockIndex, int offset, ControlFlowNodeType nodeType)
+ {
+ BlockIndex = blockIndex;
+ Offset = offset;
+ NodeType = nodeType;
+ }
+
+ internal ControlFlowNode(int blockIndex, Instruction start, Instruction end)
+ {
+ if (start == null)
+ throw new ArgumentNullException("start");
+ if (end == null)
+ throw new ArgumentNullException("end");
+ BlockIndex = blockIndex;
+ NodeType = ControlFlowNodeType.Normal;
+ Start = start;
+ End = end;
+ Offset = start.Offset;
+ }
+
+ internal ControlFlowNode(int blockIndex, ExceptionHandler exceptionHandler, ControlFlowNode endFinallyOrFaultNode)
+ {
+ BlockIndex = blockIndex;
+ NodeType = endFinallyOrFaultNode != null ? ControlFlowNodeType.FinallyOrFaultHandler : ControlFlowNodeType.CatchHandler;
+ ExceptionHandler = exceptionHandler;
+ EndFinallyOrFaultNode = endFinallyOrFaultNode;
+ Debug.Assert((exceptionHandler.HandlerType == ExceptionHandlerType.Finally || exceptionHandler.HandlerType == ExceptionHandlerType.Fault) == (endFinallyOrFaultNode != null));
+ Offset = exceptionHandler.HandlerStart.Offset;
+ }
+
+ /// <summary>
+ /// Gets all predecessors (=sources of incoming edges)
+ /// </summary>
+ public IEnumerable<ControlFlowNode> Predecessors {
+ get {
+ return Incoming.Select(e => e.Source);
+ }
+ }
+
+ /// <summary>
+ /// Gets all successors (=targets of outgoing edges)
+ /// </summary>
+ public IEnumerable<ControlFlowNode> Successors {
+ get {
+ return Outgoing.Select(e => e.Target);
+ }
+ }
+
+ /// <summary>
+ /// Gets all instructions in this node.
+ /// Returns an empty list for special nodes that don't have any instructions.
+ /// </summary>
+ public IEnumerable<Instruction> Instructions {
+ get {
+ Instruction inst = Start;
+ if (inst != null) {
+ yield return inst;
+ while (inst != End) {
+ inst = inst.Next;
+ yield return inst;
+ }
+ }
+ }
+ }
+
+ public void TraversePreOrder(Func<ControlFlowNode, IEnumerable<ControlFlowNode>> children, Action<ControlFlowNode> visitAction)
+ {
+ if (Visited)
+ return;
+ Visited = true;
+ visitAction(this);
+ foreach (ControlFlowNode t in children(this))
+ t.TraversePreOrder(children, visitAction);
+ }
+
+ public void TraversePostOrder(Func<ControlFlowNode, IEnumerable<ControlFlowNode>> children, Action<ControlFlowNode> visitAction)
+ {
+ if (Visited)
+ return;
+ Visited = true;
+ foreach (ControlFlowNode t in children(this))
+ t.TraversePostOrder(children, visitAction);
+ visitAction(this);
+ }
+
+ public override string ToString()
+ {
+ StringWriter writer = new StringWriter();
+ switch (NodeType) {
+ case ControlFlowNodeType.Normal:
+ writer.Write("Block #{0}", BlockIndex);
+ if (Start != null)
+ writer.Write(": IL_{0:x4}", Start.Offset);
+ if (End != null)
+ writer.Write(" to IL_{0:x4}", End.GetEndOffset());
+ break;
+ case ControlFlowNodeType.CatchHandler:
+ case ControlFlowNodeType.FinallyOrFaultHandler:
+ writer.Write("Block #{0}: {1}: ", BlockIndex, NodeType);
+ DisassemblerHelpers.WriteTo(ExceptionHandler, new PlainTextOutput(writer));
+ break;
+ default:
+ writer.Write("Block #{0}: {1}", BlockIndex, NodeType);
+ break;
+ }
+// if (ImmediateDominator != null) {
+// writer.WriteLine();
+// writer.Write("ImmediateDominator: #{0}", ImmediateDominator.BlockIndex);
+// }
+ if (DominanceFrontier != null && DominanceFrontier.Any()) {
+ writer.WriteLine();
+ writer.Write("DominanceFrontier: " + string.Join(",", DominanceFrontier.OrderBy(d => d.BlockIndex).Select(d => d.BlockIndex.ToString())));
+ }
+ foreach (Instruction inst in Instructions) {
+ writer.WriteLine();
+ DisassemblerHelpers.WriteTo(inst, new PlainTextOutput(writer));
+ }
+ if (UserData != null) {
+ writer.WriteLine();
+ writer.Write(UserData.ToString());
+ }
+ return writer.ToString();
+ }
+
+ /// <summary>
+ /// Gets whether <c>this</c> dominates <paramref name="node"/>.
+ /// </summary>
+ public bool Dominates(ControlFlowNode node)
+ {
+ // TODO: this can be made O(1) by numbering the dominator tree
+ ControlFlowNode tmp = node;
+ while (tmp != null) {
+ if (tmp == this)
+ return true;
+ tmp = tmp.ImmediateDominator;
+ }
+ return false;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs b/ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs
new file mode 100644
index 00000000..b7b77e07
--- /dev/null
+++ b/ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs
@@ -0,0 +1,241 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.FlowAnalysis
+{
+ /// <summary>
+ /// Detects the structure of the control flow (exception blocks and loops).
+ /// </summary>
+ public class ControlStructureDetector
+ {
+ public static ControlStructure DetectStructure(ControlFlowGraph g, IEnumerable<ExceptionHandler> exceptionHandlers, CancellationToken cancellationToken)
+ {
+ ControlStructure root = new ControlStructure(new HashSet<ControlFlowNode>(g.Nodes), g.EntryPoint, ControlStructureType.Root);
+ // First build a structure tree out of the exception table
+ DetectExceptionHandling(root, g, exceptionHandlers);
+ // Then run the loop detection.
+ DetectLoops(g, root, cancellationToken);
+ return root;
+ }
+
+ #region Exception Handling
+ static void DetectExceptionHandling(ControlStructure current, ControlFlowGraph g, IEnumerable<ExceptionHandler> exceptionHandlers)
+ {
+ // We rely on the fact that the exception handlers are sorted so that the innermost come first.
+ // For each exception handler, we determine the nodes and substructures inside that handler, and move them into a new substructure.
+ // This is always possible because exception handlers are guaranteed (by the CLR spec) to be properly nested and non-overlapping;
+ // so they directly form the tree that we need.
+ foreach (ExceptionHandler eh in exceptionHandlers) {
+ var tryNodes = FindNodes(current, eh.TryStart, eh.TryEnd);
+ current.Nodes.ExceptWith(tryNodes);
+ ControlStructure tryBlock = new ControlStructure(
+ tryNodes,
+ g.Nodes.Single(n => n.Start == eh.TryStart),
+ ControlStructureType.Try);
+ tryBlock.ExceptionHandler = eh;
+ MoveControlStructures(current, tryBlock, eh.TryStart, eh.TryEnd);
+ current.Children.Add(tryBlock);
+
+ if (eh.FilterStart != null) {
+ throw new NotSupportedException();
+ }
+
+ var handlerNodes = FindNodes(current, eh.HandlerStart, eh.HandlerEnd);
+ var handlerNode = current.Nodes.Single(n => n.ExceptionHandler == eh);
+ handlerNodes.Add(handlerNode);
+ if (handlerNode.EndFinallyOrFaultNode != null)
+ handlerNodes.Add(handlerNode.EndFinallyOrFaultNode);
+ current.Nodes.ExceptWith(handlerNodes);
+ ControlStructure handlerBlock = new ControlStructure(
+ handlerNodes, handlerNode, ControlStructureType.Handler);
+ handlerBlock.ExceptionHandler = eh;
+ MoveControlStructures(current, handlerBlock, eh.HandlerStart, eh.HandlerEnd);
+ current.Children.Add(handlerBlock);
+ }
+ }
+
+ /// <summary>
+ /// Removes all nodes from start to end (exclusive) from this ControlStructure and moves them to the target structure.
+ /// </summary>
+ static HashSet<ControlFlowNode> FindNodes(ControlStructure current, Instruction startInst, Instruction endInst)
+ {
+ HashSet<ControlFlowNode> result = new HashSet<ControlFlowNode>();
+ int start = startInst.Offset;
+ int end = endInst.Offset;
+ foreach (var node in current.Nodes.ToArray()) {
+ if (node.Start != null && start <= node.Start.Offset && node.Start.Offset < end) {
+ result.Add(node);
+ }
+ }
+ return result;
+ }
+
+ static void MoveControlStructures(ControlStructure current, ControlStructure target, Instruction startInst, Instruction endInst)
+ {
+ for (int i = 0; i < current.Children.Count; i++) {
+ var child = current.Children[i];
+ if (startInst.Offset <= child.EntryPoint.Offset && child.EntryPoint.Offset < endInst.Offset) {
+ current.Children.RemoveAt(i--);
+ target.Children.Add(child);
+ target.AllNodes.UnionWith(child.AllNodes);
+ }
+ }
+ }
+ #endregion
+
+ #region Loop Detection
+ // Loop detection works like this:
+ // We find a top-level loop by looking for its entry point, which is characterized by a node dominating its own predecessor.
+ // Then we determine all other nodes that belong to such a loop (all nodes which lead to the entry point, and are dominated by it).
+ // Finally, we check whether our result conforms with potential existing exception structures, and create the substructure for the loop if successful.
+
+ // This algorithm is applied recursively for any substructures (both detected loops and exception blocks)
+
+ // But maybe we should get rid of this complex stuff and instead treat every backward jump as a loop?
+ // That should still work with the IL produced by compilers, and has the advantage that the detected loop bodies are consecutive IL regions.
+
+ static void DetectLoops(ControlFlowGraph g, ControlStructure current, CancellationToken cancellationToken)
+ {
+ if (!current.EntryPoint.IsReachable)
+ return;
+ g.ResetVisited();
+ cancellationToken.ThrowIfCancellationRequested();
+ FindLoops(current, current.EntryPoint);
+ foreach (ControlStructure loop in current.Children)
+ DetectLoops(g, loop, cancellationToken);
+ }
+
+ static void FindLoops(ControlStructure current, ControlFlowNode node)
+ {
+ if (node.Visited)
+ return;
+ node.Visited = true;
+ if (current.Nodes.Contains(node)
+ && node.DominanceFrontier.Contains(node)
+ && !(node == current.EntryPoint && current.Type == ControlStructureType.Loop))
+ {
+ HashSet<ControlFlowNode> loopContents = new HashSet<ControlFlowNode>();
+ FindLoopContents(current, loopContents, node, node);
+ List<ControlStructure> containedChildStructures = new List<ControlStructure>();
+ bool invalidNesting = false;
+ foreach (ControlStructure childStructure in current.Children) {
+ if (childStructure.AllNodes.IsSubsetOf(loopContents)) {
+ containedChildStructures.Add(childStructure);
+ } else if (childStructure.AllNodes.Intersect(loopContents).Any()) {
+ invalidNesting = true;
+ }
+ }
+ if (!invalidNesting) {
+ current.Nodes.ExceptWith(loopContents);
+ ControlStructure ctl = new ControlStructure(loopContents, node, ControlStructureType.Loop);
+ foreach (ControlStructure childStructure in containedChildStructures) {
+ ctl.Children.Add(childStructure);
+ current.Children.Remove(childStructure);
+ ctl.Nodes.ExceptWith(childStructure.AllNodes);
+ }
+ current.Children.Add(ctl);
+ }
+ }
+ foreach (var edge in node.Outgoing) {
+ FindLoops(current, edge.Target);
+ }
+ }
+
+ static void FindLoopContents(ControlStructure current, HashSet<ControlFlowNode> loopContents, ControlFlowNode loopHead, ControlFlowNode node)
+ {
+ if (current.AllNodes.Contains(node) && loopHead.Dominates(node) && loopContents.Add(node)) {
+ foreach (var edge in node.Incoming) {
+ FindLoopContents(current, loopContents, loopHead, edge.Source);
+ }
+ }
+ }
+ #endregion
+ }
+
+ public enum ControlStructureType
+ {
+ /// <summary>
+ /// The root block of the method
+ /// </summary>
+ Root,
+ /// <summary>
+ /// A nested control structure representing a loop.
+ /// </summary>
+ Loop,
+ /// <summary>
+ /// A nested control structure representing a try block.
+ /// </summary>
+ Try,
+ /// <summary>
+ /// A nested control structure representing a catch, finally, or fault block.
+ /// </summary>
+ Handler,
+ /// <summary>
+ /// A nested control structure representing an exception filter block.
+ /// </summary>
+ Filter
+ }
+
+ /// <summary>
+ /// Represents the structure detected by the <see cref="ControlStructureDetector"/>.
+ ///
+ /// This is a tree of ControlStructure nodes. Each node contains a set of CFG nodes, and every CFG node is contained in exactly one ControlStructure node.
+ /// </summary>
+ public class ControlStructure
+ {
+ public readonly ControlStructureType Type;
+ public readonly List<ControlStructure> Children = new List<ControlStructure>();
+
+ /// <summary>
+ /// The nodes in this control structure.
+ /// </summary>
+ public readonly HashSet<ControlFlowNode> Nodes;
+
+ /// <summary>
+ /// The nodes in this control structure and in all child control structures.
+ /// </summary>
+ public readonly HashSet<ControlFlowNode> AllNodes;
+
+ /// <summary>
+ /// The entry point of this control structure.
+ /// </summary>
+ public readonly ControlFlowNode EntryPoint;
+
+ /// <summary>
+ /// The exception handler associated with this Try,Handler or Finally structure.
+ /// </summary>
+ public ExceptionHandler ExceptionHandler;
+
+ public ControlStructure(HashSet<ControlFlowNode> nodes, ControlFlowNode entryPoint, ControlStructureType type)
+ {
+ if (nodes == null)
+ throw new ArgumentNullException("nodes");
+ Nodes = nodes;
+ EntryPoint = entryPoint;
+ Type = type;
+ AllNodes = new HashSet<ControlFlowNode>(nodes);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/OpCodeInfo.cs b/ICSharpCode.Decompiler/FlowAnalysis/OpCodeInfo.cs
new file mode 100644
index 00000000..e0dc724f
--- /dev/null
+++ b/ICSharpCode.Decompiler/FlowAnalysis/OpCodeInfo.cs
@@ -0,0 +1,312 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.FlowAnalysis
+{
+ /// <summary>
+ /// Additional info about opcodes.
+ /// </summary>
+ internal sealed class OpCodeInfo
+ {
+ public static bool IsUnconditionalBranch(OpCode opcode)
+ {
+ if (opcode.OpCodeType == OpCodeType.Prefix)
+ return false;
+ switch (opcode.FlowControl) {
+ case FlowControl.Branch:
+ case FlowControl.Throw:
+ case FlowControl.Return:
+ return true;
+ case FlowControl.Next:
+ case FlowControl.Call:
+ case FlowControl.Cond_Branch:
+ return false;
+ default:
+ throw new NotSupportedException(opcode.FlowControl.ToString());
+ }
+ }
+
+ static readonly OpCodeInfo[] knownOpCodes = {
+ #region Base Instructions
+ new OpCodeInfo(OpCodes.Add) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Add_Ovf) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Add_Ovf_Un) { CanThrow = true },
+ new OpCodeInfo(OpCodes.And) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Arglist) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Beq) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Beq_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Bge) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Bge_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Bge_Un) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Bge_Un_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Bgt) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Bgt_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Bgt_Un) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Bgt_Un_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ble) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ble_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ble_Un) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ble_Un_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Blt) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Blt_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Blt_Un) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Blt_Un_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Bne_Un) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Bne_Un_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Br) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Br_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Break) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Brfalse) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Brfalse_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Brtrue) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Brtrue_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Call) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Calli) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Ceq) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Cgt) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Cgt_Un) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ckfinite) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Clt) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Clt_Un) { CanThrow = false },
+ // conv.<to type>
+ new OpCodeInfo(OpCodes.Conv_I1) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Conv_I2) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Conv_I4) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Conv_I8) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Conv_R4) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Conv_R8) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Conv_U1) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Conv_U2) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Conv_U4) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Conv_U8) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Conv_I) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Conv_U) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Conv_R_Un) { CanThrow = false },
+ // conv.ovf.<to type>
+ new OpCodeInfo(OpCodes.Conv_Ovf_I1) { CanThrow = true},
+ new OpCodeInfo(OpCodes.Conv_Ovf_I2) { CanThrow = true},
+ new OpCodeInfo(OpCodes.Conv_Ovf_I4) { CanThrow = true},
+ new OpCodeInfo(OpCodes.Conv_Ovf_I8) { CanThrow = true},
+ new OpCodeInfo(OpCodes.Conv_Ovf_U1) { CanThrow = true},
+ new OpCodeInfo(OpCodes.Conv_Ovf_U2) { CanThrow = true},
+ new OpCodeInfo(OpCodes.Conv_Ovf_U4) { CanThrow = true},
+ new OpCodeInfo(OpCodes.Conv_Ovf_U8) { CanThrow = true},
+ new OpCodeInfo(OpCodes.Conv_Ovf_I) { CanThrow = true},
+ new OpCodeInfo(OpCodes.Conv_Ovf_U) { CanThrow = true},
+ // conv.ovf.<to type>.un
+ new OpCodeInfo(OpCodes.Conv_Ovf_I1_Un) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Conv_Ovf_I2_Un) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Conv_Ovf_I4_Un) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Conv_Ovf_I8_Un) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Conv_Ovf_U1_Un) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Conv_Ovf_U2_Un) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Conv_Ovf_U4_Un) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Conv_Ovf_U8_Un) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Conv_Ovf_I_Un) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Conv_Ovf_U_Un) { CanThrow = true },
+
+ //new OpCodeInfo(OpCodes.Cpblk) { CanThrow = true }, - no idea whether this might cause trouble for the type system, C# shouldn't use it so I'll disable it
+ new OpCodeInfo(OpCodes.Div) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Div_Un) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Dup) { CanThrow = true, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Endfilter) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Endfinally) { CanThrow = false },
+ //new OpCodeInfo(OpCodes.Initblk) { CanThrow = true }, - no idea whether this might cause trouble for the type system, C# shouldn't use it so I'll disable it
+ //new OpCodeInfo(OpCodes.Jmp) { CanThrow = true } - We don't support non-local control transfers.
+ new OpCodeInfo(OpCodes.Ldarg) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Ldarg_0) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Ldarg_1) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Ldarg_2) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Ldarg_3) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Ldarg_S) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Ldarga) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldarga_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldc_I4) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldc_I4_M1) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldc_I4_0) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldc_I4_1) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldc_I4_2) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldc_I4_3) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldc_I4_4) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldc_I4_5) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldc_I4_6) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldc_I4_7) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldc_I4_8) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldc_I4_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldc_I8) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldc_R4) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldc_R8) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldftn) { CanThrow = false },
+ // ldind.<type>
+ new OpCodeInfo(OpCodes.Ldind_I1) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Ldind_I2) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Ldind_I4) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Ldind_I8) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Ldind_U1) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Ldind_U2) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Ldind_U4) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Ldind_R4) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Ldind_R8) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Ldind_I) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Ldind_Ref) { CanThrow = true },
+ // the ldloc exceptions described in the spec can only occur on methods without .localsinit - but csc always sets that flag
+ new OpCodeInfo(OpCodes.Ldloc) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Ldloc_0) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Ldloc_1) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Ldloc_2) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Ldloc_3) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Ldloc_S) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Ldloca) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldloca_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldnull) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Leave) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Leave_S) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Localloc) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Mul) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Mul_Ovf) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Mul_Ovf_Un) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Neg) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Nop) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Not) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Or) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Pop) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Rem) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Rem_Un) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Ret) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Shl) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Shr) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Shr_Un) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Starg) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Starg_S) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Stind_I1) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Stind_I2) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Stind_I4) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Stind_I8) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Stind_R4) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Stind_R8) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Stind_I) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Stind_Ref) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Stloc) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Stloc_0) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Stloc_1) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Stloc_2) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Stloc_3) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Stloc_S) { CanThrow = false, IsMoveInstruction = true },
+ new OpCodeInfo(OpCodes.Sub) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Sub_Ovf) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Sub_Ovf_Un) { CanThrow = true },
+ new OpCodeInfo(OpCodes.Switch) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Xor) { CanThrow = false },
+ #endregion
+ #region Object model instructions
+ // CanThrow is true by default - most OO instructions can throw, so we don't specify CanThrow all of the time
+ new OpCodeInfo(OpCodes.Box),
+ new OpCodeInfo(OpCodes.Callvirt),
+ new OpCodeInfo(OpCodes.Castclass),
+ new OpCodeInfo(OpCodes.Cpobj),
+ new OpCodeInfo(OpCodes.Initobj) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Isinst) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldelem_Any),
+ // ldelem.<type>
+ new OpCodeInfo(OpCodes.Ldelem_I) ,
+ new OpCodeInfo(OpCodes.Ldelem_I1),
+ new OpCodeInfo(OpCodes.Ldelem_I2),
+ new OpCodeInfo(OpCodes.Ldelem_I4),
+ new OpCodeInfo(OpCodes.Ldelem_I8),
+ new OpCodeInfo(OpCodes.Ldelem_R4),
+ new OpCodeInfo(OpCodes.Ldelem_R8),
+ new OpCodeInfo(OpCodes.Ldelem_Ref),
+ new OpCodeInfo(OpCodes.Ldelem_U1),
+ new OpCodeInfo(OpCodes.Ldelem_U2),
+ new OpCodeInfo(OpCodes.Ldelem_U4),
+ new OpCodeInfo(OpCodes.Ldelema) ,
+ new OpCodeInfo(OpCodes.Ldfld) ,
+ new OpCodeInfo(OpCodes.Ldflda),
+ new OpCodeInfo(OpCodes.Ldlen) ,
+ new OpCodeInfo(OpCodes.Ldobj) ,
+ new OpCodeInfo(OpCodes.Ldsfld),
+ new OpCodeInfo(OpCodes.Ldsflda),
+ new OpCodeInfo(OpCodes.Ldstr) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldtoken) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Ldvirtftn),
+ new OpCodeInfo(OpCodes.Mkrefany),
+ new OpCodeInfo(OpCodes.Newarr),
+ new OpCodeInfo(OpCodes.Newobj),
+ new OpCodeInfo(OpCodes.Refanytype) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Refanyval),
+ new OpCodeInfo(OpCodes.Rethrow),
+ new OpCodeInfo(OpCodes.Sizeof) { CanThrow = false },
+ new OpCodeInfo(OpCodes.Stelem_Any),
+ new OpCodeInfo(OpCodes.Stelem_I1),
+ new OpCodeInfo(OpCodes.Stelem_I2),
+ new OpCodeInfo(OpCodes.Stelem_I4),
+ new OpCodeInfo(OpCodes.Stelem_I8),
+ new OpCodeInfo(OpCodes.Stelem_R4),
+ new OpCodeInfo(OpCodes.Stelem_R8),
+ new OpCodeInfo(OpCodes.Stelem_Ref),
+ new OpCodeInfo(OpCodes.Stfld),
+ new OpCodeInfo(OpCodes.Stobj),
+ new OpCodeInfo(OpCodes.Stsfld),
+ new OpCodeInfo(OpCodes.Throw),
+ new OpCodeInfo(OpCodes.Unbox),
+ new OpCodeInfo(OpCodes.Unbox_Any),
+ #endregion
+ };
+ static readonly Dictionary<Code, OpCodeInfo> knownOpCodeDict = knownOpCodes.ToDictionary(info => info.OpCode.Code);
+
+ public static OpCodeInfo Get(OpCode opCode)
+ {
+ return Get(opCode.Code);
+ }
+
+ public static OpCodeInfo Get(Code code)
+ {
+ OpCodeInfo info;
+ if (knownOpCodeDict.TryGetValue(code, out info))
+ return info;
+ else
+ throw new NotSupportedException(code.ToString());
+ }
+
+ OpCode opcode;
+
+ OpCodeInfo(OpCode opcode)
+ {
+ this.opcode = opcode;
+ CanThrow = true;
+ }
+
+ public OpCode OpCode { get { return opcode; } }
+
+ /// <summary>
+ /// 'Move' kind of instructions have one input (may be stack or local variable) and copy that value to all outputs (again stack or local variable).
+ /// </summary>
+ public bool IsMoveInstruction { get; private set; }
+
+ /// <summary>
+ /// Specifies whether this opcode is capable of throwing exceptions.
+ /// </summary>
+ public bool CanThrow { get; private set; }
+ }
+}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SimplifyByRefCalls.cs b/ICSharpCode.Decompiler/FlowAnalysis/SimplifyByRefCalls.cs
new file mode 100644
index 00000000..42c30914
--- /dev/null
+++ b/ICSharpCode.Decompiler/FlowAnalysis/SimplifyByRefCalls.cs
@@ -0,0 +1,174 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.FlowAnalysis
+{
+ /// <summary>
+ /// This is a transformation working on SSA form.
+ /// It removes ldloca instructions and replaces them with SpecialOpCode.PrepareByOutCall or SpecialOpCode.PrepareByRefCall.
+ /// This then allows the variable that had its address taken to also be transformed into SSA.
+ /// </summary>
+ internal sealed class SimplifyByRefCalls
+ {
+ public static bool MakeByRefCallsSimple(SsaForm ssaForm)
+ {
+ SimplifyByRefCalls instance = new SimplifyByRefCalls(ssaForm);
+ foreach (SsaBlock block in ssaForm.Blocks) {
+ for (int i = 0; i < block.Instructions.Count; i++) {
+ SsaInstruction inst = block.Instructions[i];
+ if (inst.Instruction != null) {
+ switch (inst.Instruction.OpCode.Code) {
+ case Code.Call:
+ case Code.Callvirt:
+ instance.MakeByRefCallSimple(block, ref i, (IMethodSignature)inst.Instruction.Operand);
+ break;
+ case Code.Initobj:
+ instance.MakeInitObjCallSimple(block, ref i);
+ break;
+ case Code.Ldfld:
+ instance.MakeLoadFieldCallSimple(block, ref i);
+ break;
+ }
+ }
+ }
+ }
+ instance.RemoveRedundantInstructions();
+ if (instance.couldSimplifySomething)
+ ssaForm.ComputeVariableUsage();
+ return instance.couldSimplifySomething;
+ }
+
+ readonly SsaForm ssaForm;
+
+ bool couldSimplifySomething;
+
+ // the list of ldloca instructions we will remove
+ readonly List<SsaInstruction> redundantLoadAddressInstructions = new List<SsaInstruction>();
+
+ SimplifyByRefCalls(SsaForm ssaForm)
+ {
+ this.ssaForm = ssaForm;
+ }
+
+ void MakeByRefCallSimple(SsaBlock block, ref int instructionIndexInBlock, IMethodSignature targetMethod)
+ {
+ SsaInstruction inst = block.Instructions[instructionIndexInBlock];
+ for (int i = 0; i < inst.Operands.Length; i++) {
+ SsaVariable operand = inst.Operands[i];
+ if (operand.IsSingleAssignment && operand.Usage.Count == 1 && IsLoadAddress(operand.Definition)) {
+ // address is used for this method call only
+
+ Instruction loadAddressInstruction = operand.Definition.Instruction;
+
+ // find target parameter type:
+ bool isOut;
+ if (i == 0 && targetMethod.HasThis) {
+ isOut = false;
+ } else {
+ ParameterDefinition parameter = targetMethod.Parameters[i - (targetMethod.HasThis ? 1 : 0)];
+ isOut = parameter.IsOut;
+ }
+
+ SsaVariable addressTakenOf = GetVariableFromLoadAddressInstruction(loadAddressInstruction);
+
+ // insert "Prepare" instruction on front
+ SpecialOpCode loadOpCode = isOut ? SpecialOpCode.PrepareByOutCall : SpecialOpCode.PrepareByRefCall;
+ block.Instructions.Insert(instructionIndexInBlock++, new SsaInstruction(
+ block, null, operand, new SsaVariable[] { addressTakenOf }, specialOpCode: loadOpCode));
+
+ // insert "WriteAfterByRefOrOutCall" instruction after call
+ block.Instructions.Insert(instructionIndexInBlock + 1, new SsaInstruction(
+ block, null, addressTakenOf, new SsaVariable[] { operand }, specialOpCode: SpecialOpCode.WriteAfterByRefOrOutCall));
+
+ couldSimplifySomething = true;
+
+ // remove the loadAddressInstruction later
+ // (later because it might be defined in the current block and we don't want instructionIndex to become invalid)
+ redundantLoadAddressInstructions.Add(operand.Definition);
+ }
+ }
+ }
+
+ SsaVariable GetVariableFromLoadAddressInstruction(Instruction loadAddressInstruction)
+ {
+ if (loadAddressInstruction.OpCode == OpCodes.Ldloca) {
+ return ssaForm.GetOriginalVariable((VariableReference)loadAddressInstruction.Operand);
+ } else {
+ Debug.Assert(loadAddressInstruction.OpCode == OpCodes.Ldarga);
+ return ssaForm.GetOriginalVariable((ParameterReference)loadAddressInstruction.Operand);
+ }
+ }
+
+ static bool IsLoadAddress(SsaInstruction inst)
+ {
+ return inst.Instruction != null && (inst.Instruction.OpCode == OpCodes.Ldloca || inst.Instruction.OpCode == OpCodes.Ldarga);
+ }
+
+ void MakeInitObjCallSimple(SsaBlock block, ref int instructionIndexInBlock)
+ {
+ SsaInstruction inst = block.Instructions[instructionIndexInBlock];
+ Debug.Assert(inst.Operands.Length == 1);
+ SsaVariable operand = inst.Operands[0];
+ if (operand.IsSingleAssignment && operand.Usage.Count == 1 && IsLoadAddress(operand.Definition)) {
+ // replace instruction with special "InitObj" instruction
+ block.Instructions[instructionIndexInBlock] = new SsaInstruction(
+ inst.ParentBlock, null, GetVariableFromLoadAddressInstruction(operand.Definition.Instruction), null,
+ specialOpCode: SpecialOpCode.InitObj,
+ typeOperand: (TypeReference)inst.Instruction.Operand);
+
+ couldSimplifySomething = true;
+
+ // remove the loadAddressInstruction later
+ redundantLoadAddressInstructions.Add(operand.Definition);
+ }
+ }
+
+ void MakeLoadFieldCallSimple(SsaBlock block, ref int instructionIndexInBlock)
+ {
+ SsaInstruction inst = block.Instructions[instructionIndexInBlock];
+ Debug.Assert(inst.Operands.Length == 1);
+ SsaVariable operand = inst.Operands[0];
+ if (operand.IsSingleAssignment && operand.Usage.Count == 1 && IsLoadAddress(operand.Definition)) {
+ // insert special "PrepareForFieldAccess" instruction in front
+ block.Instructions.Insert(instructionIndexInBlock++, new SsaInstruction(
+ inst.ParentBlock, null, operand,
+ new SsaVariable[] { GetVariableFromLoadAddressInstruction(operand.Definition.Instruction) },
+ specialOpCode: SpecialOpCode.PrepareForFieldAccess));
+
+ couldSimplifySomething = true;
+
+ // remove the loadAddressInstruction later
+ redundantLoadAddressInstructions.Add(operand.Definition);
+ }
+ }
+
+ void RemoveRedundantInstructions()
+ {
+ foreach (SsaInstruction inst in redundantLoadAddressInstructions) {
+ inst.ParentBlock.Instructions.Remove(inst);
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SsaBlock.cs b/ICSharpCode.Decompiler/FlowAnalysis/SsaBlock.cs
new file mode 100644
index 00000000..b1767b9b
--- /dev/null
+++ b/ICSharpCode.Decompiler/FlowAnalysis/SsaBlock.cs
@@ -0,0 +1,60 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace ICSharpCode.Decompiler.FlowAnalysis
+{
+ /// <summary>
+ /// A block in a control flow graph; with instructions represented by "SsaInstructions" (instructions use variables, no evaluation stack).
+ /// Usually these variables are in SSA form to make analysis easier.
+ /// </summary>
+ public sealed class SsaBlock
+ {
+ public readonly List<SsaBlock> Successors = new List<SsaBlock>();
+ public readonly List<SsaBlock> Predecessors = new List<SsaBlock>();
+ public readonly ControlFlowNodeType NodeType;
+ public readonly List<SsaInstruction> Instructions = new List<SsaInstruction>();
+
+ /// <summary>
+ /// The block index in the control flow graph.
+ /// This correspons to the node index in ControlFlowGraph.Nodes, so it can be used to retrieve the original CFG node and look
+ /// up additional information (e.g. dominance).
+ /// </summary>
+ public readonly int BlockIndex;
+
+ internal SsaBlock(ControlFlowNode node)
+ {
+ NodeType = node.NodeType;
+ BlockIndex = node.BlockIndex;
+ }
+
+ public override string ToString()
+ {
+ StringWriter writer = new StringWriter();
+ writer.Write("Block #{0} ({1})", BlockIndex, NodeType);
+ foreach (SsaInstruction inst in Instructions) {
+ writer.WriteLine();
+ inst.WriteTo(writer);
+ }
+ return writer.ToString();
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SsaForm.cs b/ICSharpCode.Decompiler/FlowAnalysis/SsaForm.cs
new file mode 100644
index 00000000..baf520eb
--- /dev/null
+++ b/ICSharpCode.Decompiler/FlowAnalysis/SsaForm.cs
@@ -0,0 +1,162 @@
+// Copyright (c) 2010 Daniel Grunwald
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+
+using ICSharpCode.NRefactory.Utils;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.FlowAnalysis
+{
+ /// <summary>
+ /// Represents a graph of SsaBlocks.
+ /// </summary>
+ public sealed class SsaForm
+ {
+ readonly SsaVariable[] parameters;
+ readonly SsaVariable[] locals;
+ public readonly ReadOnlyCollection<SsaVariable> OriginalVariables;
+ public readonly ReadOnlyCollection<SsaBlock> Blocks;
+ readonly bool methodHasThis;
+
+ public SsaBlock EntryPoint {
+ get { return Blocks[0]; }
+ }
+
+ public SsaBlock RegularExit {
+ get { return Blocks[1]; }
+ }
+
+ public SsaBlock ExceptionalExit {
+ get { return Blocks[2]; }
+ }
+
+ internal SsaForm(SsaBlock[] blocks, SsaVariable[] parameters, SsaVariable[] locals, SsaVariable[] stackLocations, bool methodHasThis)
+ {
+ this.parameters = parameters;
+ this.locals = locals;
+ Blocks = new ReadOnlyCollection<SsaBlock>(blocks);
+ OriginalVariables = new ReadOnlyCollection<SsaVariable>(parameters.Concat(locals).Concat(stackLocations).ToList());
+ this.methodHasThis = methodHasThis;
+
+ Debug.Assert(EntryPoint.NodeType == ControlFlowNodeType.EntryPoint);
+ Debug.Assert(RegularExit.NodeType == ControlFlowNodeType.RegularExit);
+ Debug.Assert(ExceptionalExit.NodeType == ControlFlowNodeType.ExceptionalExit);
+ for (int i = 0; i < OriginalVariables.Count; i++) {
+ OriginalVariables[i].OriginalVariableIndex = i;
+ }
+ }
+
+ public GraphVizGraph ExportBlockGraph(Func<SsaBlock, string> labelProvider = null)
+ {
+ if (labelProvider == null)
+ labelProvider = b => b.ToString();
+ GraphVizGraph graph = new GraphVizGraph();
+ foreach (SsaBlock block in Blocks) {
+ graph.AddNode(new GraphVizNode(block.BlockIndex) { label = labelProvider(block), shape = "box" });
+ }
+ foreach (SsaBlock block in Blocks) {
+ foreach (SsaBlock s in block.Successors) {
+ graph.AddEdge(new GraphVizEdge(block.BlockIndex, s.BlockIndex));
+ }
+ }
+ return graph;
+ }
+
+ public GraphVizGraph ExportVariableGraph(Func<SsaVariable, string> labelProvider = null)
+ {
+ if (labelProvider == null)
+ labelProvider = v => v.ToString();
+ GraphVizGraph graph = new GraphVizGraph();
+ foreach (SsaVariable v in AllVariables) {
+ graph.AddNode(new GraphVizNode(v.Name) { label = labelProvider(v) });
+ }
+ int instructionIndex = 0;
+ foreach (SsaBlock block in Blocks) {
+ foreach (SsaInstruction inst in block.Instructions) {
+ if (inst.Operands.Length == 0 && inst.Target == null)
+ continue;
+ string id = "instruction" + (++instructionIndex);
+ graph.AddNode(new GraphVizNode(id) { label = inst.ToString(), shape = "box" });
+ foreach (SsaVariable op in inst.Operands)
+ graph.AddEdge(new GraphVizEdge(op.Name, id));
+ if (inst.Target != null)
+ graph.AddEdge(new GraphVizEdge(id, inst.Target.Name));
+ }
+ }
+ return graph;
+ }
+
+ public SsaVariable GetOriginalVariable(ParameterReference parameter)
+ {
+ if (methodHasThis)
+ return parameters[parameter.Index + 1];
+ else
+ return parameters[parameter.Index];
+ }
+
+ public SsaVariable GetOriginalVariable(VariableReference variable)
+ {
+ return locals[variable.Index];
+ }
+
+ #region ComputeVariableUsage
+ public void ComputeVariableUsage()
+ {
+ // clear data from previous runs
+ foreach (SsaBlock block in Blocks) {
+ foreach (SsaInstruction inst in block.Instructions) {
+ foreach (SsaVariable v in inst.Operands) {
+ if (v.Usage != null)
+ v.Usage.Clear();
+ }
+ if (inst.Target != null && inst.Target.Usage != null)
+ inst.Target.Usage.Clear();
+ }
+ }
+ foreach (SsaBlock block in Blocks) {
+ foreach (SsaInstruction inst in block.Instructions) {
+ foreach (SsaVariable v in inst.Operands) {
+ if (v.Usage == null)
+ v.Usage = new List<SsaInstruction>();
+ v.Usage.Add(inst);
+ }
+ if (inst.Target != null && inst.Target.Usage == null)
+ inst.Target.Usage = new List<SsaInstruction>();
+ }
+ }
+ }
+ #endregion
+
+ public IEnumerable<SsaVariable> AllVariables {
+ get {
+ return (
+ from block in Blocks
+ from instruction in block.Instructions
+ where instruction.Target != null
+ select instruction.Target
+ ).Distinct();
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs b/ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs
new file mode 100644
index 00000000..c7c86a57
--- /dev/null
+++ b/ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs
@@ -0,0 +1,257 @@
+// Copyright (c) 2010 Daniel Grunwald
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.FlowAnalysis
+{
+ /// <summary>
+ /// Constructs "SsaForm" graph for a CFG.
+ /// This class transforms the method from stack-based IL to a register-based IL language.
+ /// Then it calls into TransformToSsa to convert the resulting graph to static single assignment form.
+ /// </summary>
+ public sealed class SsaFormBuilder
+ {
+ public static SsaForm Build(MethodDefinition method)
+ {
+ if (method == null)
+ throw new ArgumentNullException("method");
+ var cfg = ControlFlowGraphBuilder.Build(method.Body);
+ cfg.ComputeDominance();
+ cfg.ComputeDominanceFrontier();
+ var ssa = BuildRegisterIL(method, cfg);
+ TransformToSsa.Transform(cfg, ssa);
+ return ssa;
+ }
+
+ public static SsaForm BuildRegisterIL(MethodDefinition method, ControlFlowGraph cfg)
+ {
+ if (method == null)
+ throw new ArgumentNullException("method");
+ if (cfg == null)
+ throw new ArgumentNullException("cfg");
+ return new SsaFormBuilder(method, cfg).Build();
+ }
+
+ readonly MethodDefinition method;
+ readonly ControlFlowGraph cfg;
+
+ readonly SsaBlock[] blocks; // array index = block index
+ readonly int[] stackSizeAtBlockStart; // array index = block index
+
+ readonly SsaVariable[] parameters; // array index = parameter number
+ readonly SsaVariable[] locals; // array index = local number
+ readonly SsaVariable[] stackLocations; // array index = position on the IL evaluation stack
+ SsaForm ssaForm;
+
+ SsaFormBuilder(MethodDefinition method, ControlFlowGraph cfg)
+ {
+ this.method = method;
+ this.cfg = cfg;
+
+ blocks = new SsaBlock[cfg.Nodes.Count];
+ stackSizeAtBlockStart = new int[cfg.Nodes.Count];
+ for (int i = 0; i < stackSizeAtBlockStart.Length; i++) {
+ stackSizeAtBlockStart[i] = -1;
+ }
+ stackSizeAtBlockStart[cfg.EntryPoint.BlockIndex] = 0;
+
+ parameters = new SsaVariable[method.Parameters.Count + (method.HasThis ? 1 : 0)];
+ if (method.HasThis)
+ parameters[0] = new SsaVariable(method.Body.ThisParameter);
+ for (int i = 0; i < method.Parameters.Count; i++)
+ parameters[i + (method.HasThis ? 1 : 0)] = new SsaVariable(method.Parameters[i]);
+
+ locals = new SsaVariable[method.Body.Variables.Count];
+ for (int i = 0; i < locals.Length; i++)
+ locals[i] = new SsaVariable(method.Body.Variables[i]);
+
+ stackLocations = new SsaVariable[method.Body.MaxStackSize];
+ for (int i = 0; i < stackLocations.Length; i++) {
+ stackLocations[i] = new SsaVariable(i);
+ }
+ }
+
+ internal SsaForm Build()
+ {
+ CreateGraphStructure();
+ ssaForm = new SsaForm(blocks, parameters, locals, stackLocations, method.HasThis);
+ CreateInstructions(cfg.EntryPoint.BlockIndex);
+ CreateSpecialInstructions();
+ return ssaForm;
+ }
+
+ void CreateGraphStructure()
+ {
+ for (int i = 0; i < blocks.Length; i++) {
+ blocks[i] = new SsaBlock(cfg.Nodes[i]);
+ }
+ for (int i = 0; i < blocks.Length; i++) {
+ foreach (ControlFlowNode node in cfg.Nodes[i].Successors) {
+ blocks[i].Successors.Add(blocks[node.BlockIndex]);
+ blocks[node.BlockIndex].Predecessors.Add(blocks[i]);
+ }
+ }
+ }
+
+ void CreateInstructions(int blockIndex)
+ {
+ ControlFlowNode cfgNode = cfg.Nodes[blockIndex];
+ SsaBlock block = blocks[blockIndex];
+
+ int stackSize = stackSizeAtBlockStart[blockIndex];
+ Debug.Assert(stackSize >= 0);
+
+ List<Instruction> prefixes = new List<Instruction>();
+ foreach (Instruction inst in cfgNode.Instructions) {
+ if (inst.OpCode.OpCodeType == OpCodeType.Prefix) {
+ prefixes.Add(inst);
+ continue;
+ }
+
+ int popCount = inst.GetPopDelta(method) ?? stackSize;
+ stackSize -= popCount;
+ if (stackSize < 0)
+ throw new InvalidProgramException("IL stack underflow");
+
+ int pushCount = inst.GetPushDelta();
+ if (stackSize + pushCount > stackLocations.Length)
+ throw new InvalidProgramException("IL stack overflow");
+
+ SsaVariable target;
+ SsaVariable[] operands;
+ DetermineOperands(stackSize, inst, popCount, pushCount, out target, out operands);
+
+ Instruction[] prefixArray = prefixes.Count > 0 ? prefixes.ToArray() : null;
+ prefixes.Clear();
+
+ // ignore NOP instructions
+ if (!(inst.OpCode == OpCodes.Nop || inst.OpCode == OpCodes.Pop)) {
+ block.Instructions.Add(new SsaInstruction(block, inst, target, operands, prefixArray));
+ }
+ stackSize += pushCount;
+ }
+
+ foreach (ControlFlowEdge edge in cfgNode.Outgoing) {
+ int newStackSize;
+ switch (edge.Type) {
+ case JumpType.Normal:
+ newStackSize = stackSize;
+ break;
+ case JumpType.EndFinally:
+ if (stackSize != 0)
+ throw new NotSupportedException("stacksize must be 0 in endfinally edge");
+ newStackSize = 0;
+ break;
+ case JumpType.JumpToExceptionHandler:
+ switch (edge.Target.NodeType) {
+ case ControlFlowNodeType.FinallyOrFaultHandler:
+ newStackSize = 0;
+ break;
+ case ControlFlowNodeType.ExceptionalExit:
+ case ControlFlowNodeType.CatchHandler:
+ newStackSize = 1;
+ break;
+ default:
+ throw new NotSupportedException("unsupported target node type: " + edge.Target.NodeType);
+ }
+ break;
+ default:
+ throw new NotSupportedException("unsupported jump type: " + edge.Type);
+ }
+
+ int nextStackSize = stackSizeAtBlockStart[edge.Target.BlockIndex];
+ if (nextStackSize == -1) {
+ stackSizeAtBlockStart[edge.Target.BlockIndex] = newStackSize;
+ CreateInstructions(edge.Target.BlockIndex);
+ } else if (nextStackSize != newStackSize) {
+ throw new InvalidProgramException("Stack size doesn't match");
+ }
+ }
+ }
+
+ void DetermineOperands(int stackSize, Instruction inst, int popCount, int pushCount, out SsaVariable target, out SsaVariable[] operands)
+ {
+ switch (inst.OpCode.Code) {
+ case Code.Ldarg:
+ operands = new SsaVariable[] { ssaForm.GetOriginalVariable((ParameterReference)inst.Operand) };
+ target = stackLocations[stackSize];
+ break;
+ case Code.Starg:
+ operands = new SsaVariable[] { stackLocations[stackSize] };
+ target = ssaForm.GetOriginalVariable((ParameterReference)inst.Operand);
+ break;
+ case Code.Ldloc:
+ operands = new SsaVariable[] { ssaForm.GetOriginalVariable((VariableReference)inst.Operand) };
+ target = stackLocations[stackSize];
+ break;
+ case Code.Stloc:
+ operands = new SsaVariable[] { stackLocations[stackSize] };
+ target = ssaForm.GetOriginalVariable((VariableReference)inst.Operand);
+ break;
+ case Code.Dup:
+ operands = new SsaVariable[] { stackLocations[stackSize] };
+ target = stackLocations[stackSize + 1];
+ break;
+ default:
+ operands = new SsaVariable[popCount];
+ for (int i = 0; i < popCount; i++) {
+ operands[i] = stackLocations[stackSize + i];
+ }
+
+ switch (pushCount) {
+ case 0:
+ target = null;
+ break;
+ case 1:
+ target = stackLocations[stackSize];
+ break;
+ default:
+ throw new NotSupportedException("unsupported pushCount=" + pushCount);
+ }
+ break;
+ }
+ }
+
+ void CreateSpecialInstructions()
+ {
+ // Everything needs an initial write for the SSA transformation to work correctly.
+ foreach (SsaVariable v in parameters) {
+ ssaForm.EntryPoint.Instructions.Add(new SsaInstruction(ssaForm.EntryPoint, null, v, null, specialOpCode: SpecialOpCode.Parameter));
+ }
+ foreach (SsaVariable v in locals) {
+ ssaForm.EntryPoint.Instructions.Add(new SsaInstruction(ssaForm.EntryPoint, null, v, null, specialOpCode: SpecialOpCode.Uninitialized));
+ }
+ foreach (SsaVariable v in stackLocations) {
+ ssaForm.EntryPoint.Instructions.Add(new SsaInstruction(ssaForm.EntryPoint, null, v, null, specialOpCode: SpecialOpCode.Uninitialized));
+ }
+ foreach (SsaBlock b in blocks) {
+ if (b.NodeType == ControlFlowNodeType.CatchHandler) {
+ b.Instructions.Add(new SsaInstruction(b, null, stackLocations[0], null,
+ specialOpCode: SpecialOpCode.Exception,
+ typeOperand: cfg.Nodes[b.BlockIndex].ExceptionHandler.CatchType));
+ }
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SsaInstruction.cs b/ICSharpCode.Decompiler/FlowAnalysis/SsaInstruction.cs
new file mode 100644
index 00000000..c9375852
--- /dev/null
+++ b/ICSharpCode.Decompiler/FlowAnalysis/SsaInstruction.cs
@@ -0,0 +1,191 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Diagnostics;
+using System.IO;
+
+using ICSharpCode.Decompiler.Disassembler;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.FlowAnalysis
+{
+ public enum SpecialOpCode
+ {
+ /// <summary>
+ /// No special op code: SsaInstruction has a normal IL instruction
+ /// </summary>
+ None,
+ /// <summary>
+ /// Φ function: chooses the appropriate variable based on which CFG edge was used to enter this block
+ /// </summary>
+ Phi,
+ /// <summary>
+ /// Variable is read from before passing it by ref.
+ /// This instruction constructs a managed reference to the variable.
+ /// </summary>
+ PrepareByRefCall,
+ /// <summary>
+ /// This instruction constructs a managed reference to the variable.
+ /// The variable is not really read from.
+ /// </summary>
+ PrepareByOutCall,
+ /// <summary>
+ /// This instruction constructs a managed reference to the variable.
+ /// The reference is used for a field access on a value type.
+ /// </summary>
+ PrepareForFieldAccess,
+ /// <summary>
+ /// Variable is written to after passing it by ref or out.
+ /// </summary>
+ WriteAfterByRefOrOutCall,
+ /// <summary>
+ /// Variable is not initialized.
+ /// </summary>
+ Uninitialized,
+ /// <summary>
+ /// Value is passed in as parameter
+ /// </summary>
+ Parameter,
+ /// <summary>
+ /// Value is a caught exception.
+ /// TypeOperand is set to the exception type.
+ /// </summary>
+ Exception,
+ /// <summary>
+ /// Initialize a value type. Unlike the real initobj instruction, this one does not take an address
+ /// but assigns to the target variable.
+ /// TypeOperand is set to the type being created.
+ /// </summary>
+ InitObj
+ }
+
+ public sealed class SsaInstruction
+ {
+ public readonly SsaBlock ParentBlock;
+ public readonly SpecialOpCode SpecialOpCode;
+
+ /// <summary>
+ /// The original IL instruction.
+ /// May be null for "invented" instructions (SpecialOpCode != None).
+ /// </summary>
+ public readonly Instruction Instruction;
+
+ /// <summary>
+ /// Prefixes in front of the IL instruction.
+ /// </summary>
+ public readonly Instruction[] Prefixes;
+
+ /// <summary>
+ /// Gets the type operand. This is used only in combination with some special opcodes.
+ /// </summary>
+ public readonly TypeReference TypeOperand;
+
+ public SsaVariable Target;
+ public SsaVariable[] Operands;
+
+ static readonly SsaVariable[] emptyVariableArray = {};
+ static readonly Instruction[] emptyInstructionArray = {};
+
+ public SsaInstruction(SsaBlock parentBlock, Instruction instruction, SsaVariable target, SsaVariable[] operands,
+ Instruction[] prefixes = null, SpecialOpCode specialOpCode = SpecialOpCode.None,
+ TypeReference typeOperand = null)
+ {
+ ParentBlock = parentBlock;
+ Instruction = instruction;
+ Prefixes = prefixes ?? emptyInstructionArray;
+ Target = target;
+ Operands = operands ?? emptyVariableArray;
+ SpecialOpCode = specialOpCode;
+ TypeOperand = typeOperand;
+ Debug.Assert((typeOperand != null) == (specialOpCode == SpecialOpCode.Exception || specialOpCode == SpecialOpCode.InitObj));
+ }
+
+ /// <summary>
+ /// Gets whether this instruction is a simple assignment from one variable to another.
+ /// </summary>
+ public bool IsMoveInstruction {
+ get {
+ return Target != null && Operands.Length == 1 && Instruction != null && OpCodeInfo.Get(Instruction.OpCode).IsMoveInstruction;
+ }
+ }
+
+ public void ReplaceVariableInOperands(SsaVariable oldVar, SsaVariable newVar)
+ {
+ for (int i = 0; i < Operands.Length; i++) {
+ if (Operands[i] == oldVar)
+ Operands[i] = newVar;
+ }
+ }
+
+ public override string ToString()
+ {
+ StringWriter w = new StringWriter();
+ WriteTo(w);
+ return w.ToString();
+ }
+
+ public void WriteTo(TextWriter writer)
+ {
+ foreach (Instruction prefix in Prefixes) {
+ DisassemblerHelpers.WriteTo(prefix, new PlainTextOutput(writer));
+ writer.WriteLine();
+ }
+ if (Instruction != null && Instruction.Offset >= 0) {
+ writer.Write(CecilExtensions.OffsetToString(Instruction.Offset));
+ writer.Write(": ");
+ }
+ if (Target != null) {
+ writer.Write(Target.ToString());
+ writer.Write(" = ");
+ }
+ if (IsMoveInstruction) {
+ writer.Write(Operands[0].ToString());
+ if (Instruction != null) {
+ writer.Write(" (" + Instruction.OpCode.Name + ")");
+ }
+ } else {
+ if (Instruction == null) {
+ writer.Write(SpecialOpCode.ToString());
+ } else {
+ writer.Write(Instruction.OpCode.Name);
+ if(null != Instruction.Operand) {
+ writer.Write(' ');
+ DisassemblerHelpers.WriteOperand(new PlainTextOutput(writer), Instruction.Operand);
+ writer.Write(' ');
+ }
+ }
+ if (TypeOperand != null) {
+ writer.Write(' ');
+ writer.Write(TypeOperand.ToString());
+ writer.Write(' ');
+ }
+ if (Operands.Length > 0) {
+ writer.Write('(');
+ for (int i = 0; i < Operands.Length; i++) {
+ if (i > 0)
+ writer.Write(", ");
+ writer.Write(Operands[i].ToString());
+ }
+ writer.Write(')');
+ }
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SsaOptimization.cs b/ICSharpCode.Decompiler/FlowAnalysis/SsaOptimization.cs
new file mode 100644
index 00000000..71696992
--- /dev/null
+++ b/ICSharpCode.Decompiler/FlowAnalysis/SsaOptimization.cs
@@ -0,0 +1,138 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.FlowAnalysis
+{
+ /// <summary>
+ /// Contains some very simple optimizations that work on the SSA form.
+ /// </summary>
+ internal static class SsaOptimization
+ {
+ public static void Optimize(SsaForm ssaForm)
+ {
+ DirectlyStoreToVariables(ssaForm);
+ SimpleCopyPropagation(ssaForm);
+ RemoveDeadAssignments(ssaForm);
+ }
+
+ /// <summary>
+ /// When any instructions stores its result in a stack location that's used only once in a 'stloc' or 'starg' instruction,
+ /// we optimize this to directly store in the target location.
+ /// As optimization this is redundant (does the same as copy propagation), but it'll make us keep the variables named
+ /// after locals instead of keeping the temps as using only the simple copy propagation would do.
+ /// </summary>
+ public static void DirectlyStoreToVariables(SsaForm ssaForm)
+ {
+ foreach (SsaBlock block in ssaForm.Blocks) {
+ block.Instructions.RemoveAll(
+ inst => {
+ if (inst.Instruction != null && (inst.Instruction.OpCode == OpCodes.Stloc || inst.Instruction.OpCode == OpCodes.Starg)) {
+ SsaVariable target = inst.Target;
+ SsaVariable temp = inst.Operands[0];
+ if (target.IsSingleAssignment && temp.IsSingleAssignment && temp.Usage.Count == 1 && temp.IsStackLocation) {
+ temp.Definition.Target = target;
+ return true;
+ }
+ }
+ return false;
+ });
+ }
+ ssaForm.ComputeVariableUsage(); // update usage after we modified stuff
+ }
+
+ public static void SimpleCopyPropagation(SsaForm ssaForm, bool onlyForStackLocations = true)
+ {
+ foreach (SsaBlock block in ssaForm.Blocks) {
+ foreach (SsaInstruction inst in block.Instructions) {
+ if (inst.IsMoveInstruction && inst.Target.IsSingleAssignment && inst.Operands[0].IsSingleAssignment) {
+ if (inst.Target.IsStackLocation || !onlyForStackLocations) {
+ // replace all uses of 'target' with 'operands[0]'.
+ foreach (SsaInstruction useInstruction in inst.Target.Usage) {
+ useInstruction.ReplaceVariableInOperands(inst.Target, inst.Operands[0]);
+ }
+ }
+ }
+ }
+ }
+ ssaForm.ComputeVariableUsage(); // update usage after we modified stuff
+ }
+
+ public static void RemoveDeadAssignments(SsaForm ssaForm)
+ {
+ HashSet<SsaVariable> liveVariables = new HashSet<SsaVariable>();
+ // find variables that are used directly
+ foreach (SsaBlock block in ssaForm.Blocks) {
+ foreach (SsaInstruction inst in block.Instructions) {
+ if (!CanRemoveAsDeadCode(inst)) {
+ if (inst.Target != null)
+ liveVariables.Add(inst.Target);
+ foreach (SsaVariable op in inst.Operands) {
+ liveVariables.Add(op);
+ }
+ }
+ }
+ }
+ Queue<SsaVariable> queue = new Queue<SsaVariable>(liveVariables);
+ // find variables that are used indirectly
+ while (queue.Count > 0) {
+ SsaVariable v = queue.Dequeue();
+ if (v.IsSingleAssignment) {
+ foreach (SsaVariable op in v.Definition.Operands) {
+ if (liveVariables.Add(op))
+ queue.Enqueue(op);
+ }
+ }
+ }
+ // remove assignments to all unused variables
+ foreach (SsaBlock block in ssaForm.Blocks) {
+ block.Instructions.RemoveAll(
+ inst => {
+ if (inst.Target != null && !liveVariables.Contains(inst.Target)) {
+ Debug.Assert(inst.Target.IsSingleAssignment);
+ return true;
+ }
+ return false;
+ });
+ }
+ ssaForm.ComputeVariableUsage(); // update usage after we modified stuff
+ }
+
+ static bool CanRemoveAsDeadCode(SsaInstruction inst)
+ {
+ if (inst.Target != null && !inst.Target.IsSingleAssignment)
+ return false;
+ switch (inst.SpecialOpCode) {
+ case SpecialOpCode.Phi:
+ case SpecialOpCode.Exception:
+ case SpecialOpCode.Parameter:
+ case SpecialOpCode.Uninitialized:
+ return true;
+ case SpecialOpCode.None:
+ return inst.IsMoveInstruction;
+ default:
+ return false;
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SsaVariable.cs b/ICSharpCode.Decompiler/FlowAnalysis/SsaVariable.cs
new file mode 100644
index 00000000..902b7002
--- /dev/null
+++ b/ICSharpCode.Decompiler/FlowAnalysis/SsaVariable.cs
@@ -0,0 +1,91 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.FlowAnalysis
+{
+ /// <summary>
+ /// Represents a variable used with the SsaInstruction register-based instructions.
+ /// Despite what the name suggests, the variable is not necessarily in single-assignment form - take a look at "bool IsSingleAssignment".
+ /// </summary>
+ public sealed class SsaVariable
+ {
+ public int OriginalVariableIndex;
+ public readonly string Name;
+ public readonly bool IsStackLocation;
+
+ public readonly ParameterDefinition Parameter;
+ public readonly VariableDefinition Variable;
+
+ public SsaVariable(ParameterDefinition p)
+ {
+ Name = string.IsNullOrEmpty(p.Name) ? "param" + p.Index : p.Name;
+ Parameter = p;
+ }
+
+ public SsaVariable(VariableDefinition v)
+ {
+ Name = string.IsNullOrEmpty(v.Name) ? "V_" + v.Index : v.Name;
+ Variable = v;
+ }
+
+ public SsaVariable(int stackLocation)
+ {
+ Name = "stack" + stackLocation;
+ IsStackLocation = true;
+ }
+
+ public SsaVariable(SsaVariable original, string newName)
+ {
+ Name = newName;
+ IsStackLocation = original.IsStackLocation;
+ OriginalVariableIndex = original.OriginalVariableIndex;
+ Parameter = original.Parameter;
+ Variable = original.Variable;
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+
+ /// <summary>
+ /// Gets whether this variable has only a single assignment.
+ /// This field is initialized in TransformToSsa step.
+ /// </summary>
+ /// <remarks>Not all variables can be transformed to single assignment form: variables that have their address taken
+ /// cannot be represented in SSA (although SimplifyByRefCalls will get rid of the address-taking instruction in almost all cases)</remarks>
+ public bool IsSingleAssignment;
+
+ /// <summary>
+ /// Gets the instruction defining the variable.
+ /// This field is initialized in TransformToSsa step. It is only set for variables with a single assignment.
+ /// </summary>
+ public SsaInstruction Definition;
+
+ /// <summary>
+ /// Gets the places where a variable is used.
+ /// If a single instruction reads a variable 2 times (e.g. adding to itself), then it must be included 2 times in this list!
+ /// </summary>
+ public List<SsaInstruction> Usage;
+ }
+}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/TransformToSsa.cs b/ICSharpCode.Decompiler/FlowAnalysis/TransformToSsa.cs
new file mode 100644
index 00000000..47ff7bff
--- /dev/null
+++ b/ICSharpCode.Decompiler/FlowAnalysis/TransformToSsa.cs
@@ -0,0 +1,254 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.FlowAnalysis
+{
+ /// <summary>
+ /// Convers a method to static single assignment form.
+ /// </summary>
+ internal sealed class TransformToSsa
+ {
+ public static void Transform(ControlFlowGraph cfg, SsaForm ssa, bool optimize = true)
+ {
+ TransformToSsa transform = new TransformToSsa(cfg, ssa);
+ transform.ConvertVariablesToSsa();
+ SsaOptimization.RemoveDeadAssignments(ssa); // required so that 'MakeByRefCallsSimple' can detect more cases
+ if (SimplifyByRefCalls.MakeByRefCallsSimple(ssa)) {
+ transform.ConvertVariablesToSsa();
+ }
+ if (optimize)
+ SsaOptimization.Optimize(ssa);
+ }
+
+ readonly ControlFlowGraph cfg;
+ readonly SsaForm ssaForm;
+ readonly List<SsaInstruction>[] writeToOriginalVariables; // array index -> SsaVariable OriginalVariableIndex
+ readonly bool[] addressTaken; // array index -> SsaVariable OriginalVariableIndex; value = whether ldloca instruction was used with variable
+
+ TransformToSsa(ControlFlowGraph cfg, SsaForm ssaForm)
+ {
+ this.cfg = cfg;
+ this.ssaForm = ssaForm;
+ writeToOriginalVariables = new List<SsaInstruction>[ssaForm.OriginalVariables.Count];
+ addressTaken = new bool[ssaForm.OriginalVariables.Count];
+ }
+
+ #region CollectInformationAboutOriginalVariableUse
+ void CollectInformationAboutOriginalVariableUse()
+ {
+ Debug.Assert(addressTaken.Length == writeToOriginalVariables.Length);
+ for (int i = 0; i < writeToOriginalVariables.Length; i++) {
+ Debug.Assert(ssaForm.OriginalVariables[i].OriginalVariableIndex == i);
+
+ addressTaken[i] = false;
+ // writeToOriginalVariables is only used when placing phi functions
+ // we don't need to do that anymore for variables that are already in SSA form
+ if (ssaForm.OriginalVariables[i].IsSingleAssignment)
+ writeToOriginalVariables[i] = null;
+ else
+ writeToOriginalVariables[i] = new List<SsaInstruction>();
+ }
+ foreach (SsaBlock block in ssaForm.Blocks) {
+ foreach (SsaInstruction inst in block.Instructions) {
+ if (inst.Target != null ) {
+ var list = writeToOriginalVariables[inst.Target.OriginalVariableIndex];
+ if (list != null)
+ list.Add(inst);
+ }
+ if (inst.Instruction != null) {
+ if (inst.Instruction.OpCode == OpCodes.Ldloca) {
+ addressTaken[ssaForm.GetOriginalVariable((VariableDefinition)inst.Instruction.Operand).OriginalVariableIndex] = true;
+ } else if (inst.Instruction.OpCode == OpCodes.Ldarga) {
+ addressTaken[ssaForm.GetOriginalVariable((ParameterDefinition)inst.Instruction.Operand).OriginalVariableIndex] = true;
+ }
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region ConvertToSsa
+ void ConvertVariablesToSsa()
+ {
+ CollectInformationAboutOriginalVariableUse();
+ bool[] processVariable = new bool[ssaForm.OriginalVariables.Count];
+ foreach (SsaVariable variable in ssaForm.OriginalVariables) {
+ if (!variable.IsSingleAssignment && !addressTaken[variable.OriginalVariableIndex]) {
+ PlacePhiFunctions(variable);
+ processVariable[variable.OriginalVariableIndex] = true;
+ }
+ }
+ RenameVariables(processVariable);
+ foreach (SsaVariable variable in ssaForm.OriginalVariables) {
+ if (!addressTaken[variable.OriginalVariableIndex]) {
+ Debug.Assert(variable.IsSingleAssignment && variable.Definition != null);
+ }
+ }
+ ssaForm.ComputeVariableUsage();
+ }
+ #endregion
+
+ #region PlacePhiFunctions
+ void PlacePhiFunctions(SsaVariable variable)
+ {
+ cfg.ResetVisited();
+ HashSet<SsaBlock> blocksWithPhi = new HashSet<SsaBlock>();
+ Queue<ControlFlowNode> worklist = new Queue<ControlFlowNode>();
+ foreach (SsaInstruction writeInstruction in writeToOriginalVariables[variable.OriginalVariableIndex]) {
+ ControlFlowNode cfgNode = cfg.Nodes[writeInstruction.ParentBlock.BlockIndex];
+ if (!cfgNode.Visited) {
+ cfgNode.Visited = true;
+ worklist.Enqueue(cfgNode);
+ }
+ }
+ while (worklist.Count > 0) {
+ ControlFlowNode cfgNode = worklist.Dequeue();
+ foreach (ControlFlowNode dfNode in cfgNode.DominanceFrontier) {
+ // we don't need phi functions in the exit node
+ if (dfNode.NodeType == ControlFlowNodeType.RegularExit || dfNode.NodeType == ControlFlowNodeType.ExceptionalExit)
+ continue;
+ SsaBlock y = ssaForm.Blocks[dfNode.BlockIndex];
+ if (blocksWithPhi.Add(y)) {
+ // add a phi instruction in y
+ SsaVariable[] operands = Enumerable.Repeat(variable, dfNode.Incoming.Count).ToArray();
+ y.Instructions.Insert(0, new SsaInstruction(y, null, variable, operands, specialOpCode: SpecialOpCode.Phi));
+ if (!dfNode.Visited) {
+ dfNode.Visited = true;
+ worklist.Enqueue(dfNode);
+ }
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region RenameVariable
+ int tempVariableCounter = 1;
+
+ void RenameVariables(bool[] processVariable)
+ {
+ VariableRenamer r = new VariableRenamer(this, processVariable);
+ r.Visit(ssaForm.EntryPoint);
+ }
+
+ sealed class VariableRenamer
+ {
+ readonly TransformToSsa transform;
+ readonly ReadOnlyCollection<SsaVariable> inputVariables;
+ internal readonly Stack<SsaVariable>[] versionStacks;
+ int[] versionCounters; // specifies for each input variable the next version number
+
+ // processVariable = specifies for each input variable whether we should rename it
+ public VariableRenamer(TransformToSsa transform, bool[] processVariable)
+ {
+ this.transform = transform;
+ inputVariables = transform.ssaForm.OriginalVariables;
+ Debug.Assert(inputVariables.Count == processVariable.Length);
+ versionCounters = new int[inputVariables.Count];
+ versionStacks = new Stack<SsaVariable>[inputVariables.Count];
+ for (int i = 0; i < versionStacks.Length; i++) {
+ if (processVariable[i]) {
+ Debug.Assert(inputVariables[i].IsSingleAssignment == false);
+ // only create version stacks for the variables that we need to process and that weren't already processed earlier
+ versionStacks[i] = new Stack<SsaVariable>();
+ versionStacks[i].Push(inputVariables[i]);
+ }
+ }
+ }
+
+ SsaVariable MakeNewVersion(int variableIndex)
+ {
+ int versionCounter = ++versionCounters[variableIndex];
+ SsaVariable x = inputVariables[variableIndex];
+ if (versionCounter == 1) {
+ return x;
+ } else {
+ if (x.IsStackLocation) {
+ return new SsaVariable(x, "temp" + (transform.tempVariableCounter++));
+ } else {
+ return new SsaVariable(x, x.Name + "_" + versionCounter);
+ }
+ }
+ }
+
+ internal void Visit(SsaBlock block)
+ {
+ // duplicate top of all stacks
+ foreach (var stack in versionStacks) {
+ if (stack != null)
+ stack.Push(stack.Peek());
+ }
+
+ foreach (SsaInstruction s in block.Instructions) {
+ // replace all uses of variables being processed with their current version.
+ if (s.SpecialOpCode != SpecialOpCode.Phi) {
+ for (int i = 0; i < s.Operands.Length; i++) {
+ var stack = versionStacks[s.Operands[i].OriginalVariableIndex];
+ if (stack != null)
+ s.Operands[i] = stack.Peek();
+ }
+ }
+ // if we're writing to a variable we should process:
+ if (s.Target != null) {
+ int targetIndex = s.Target.OriginalVariableIndex;
+ if (versionStacks[targetIndex] != null) {
+ s.Target = MakeNewVersion(targetIndex);
+ s.Target.IsSingleAssignment = true;
+ s.Target.Definition = s;
+
+ // we already pushed our entry for this SsaBlock at the beginning (where we duplicated all stacks),
+ // so now replace the top element
+ versionStacks[targetIndex].Pop();
+ versionStacks[targetIndex].Push(s.Target);
+ }
+ }
+ }
+
+ foreach (SsaBlock succ in block.Successors) {
+ int j = succ.Predecessors.IndexOf(block);
+ Debug.Assert(j >= 0);
+ foreach (SsaInstruction f in succ.Instructions) {
+ if (f.SpecialOpCode == SpecialOpCode.Phi) {
+ var stack = versionStacks[f.Target.OriginalVariableIndex];
+ if (stack != null) {
+ f.Operands[j] = stack.Peek();
+ }
+ }
+ }
+ }
+ foreach (ControlFlowNode child in transform.cfg.Nodes[block.BlockIndex].DominatorTreeChildren)
+ Visit(transform.ssaForm.Blocks[child.BlockIndex]);
+ // restore stacks:
+ foreach (var stack in versionStacks) {
+ if (stack != null)
+ stack.Pop();
+ }
+ }
+ }
+ #endregion
+ }
+}
diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
new file mode 100644
index 00000000..2a0a5b63
--- /dev/null
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <PropertyGroup>
+ <ProjectGuid>{984CC812-9470-4A13-AFF9-CC44068D666C}</ProjectGuid>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <OutputType>Library</OutputType>
+ <RootNamespace>ICSharpCode.Decompiler</RootNamespace>
+ <AssemblyName>ICSharpCode.Decompiler</AssemblyName>
+ <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <AllowUnsafeBlocks>False</AllowUnsafeBlocks>
+ <NoStdLib>False</NoStdLib>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+ <SignAssembly>false</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\NRefactory\ICSharpCode.NRefactory.snk</AssemblyOriginatorKeyFile>
+ <DelaySign>False</DelaySign>
+ <AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <RegisterForComInterop>False</RegisterForComInterop>
+ <GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
+ <BaseAddress>448462848</BaseAddress>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <OutputPath>bin\Debug\</OutputPath>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>Full</DebugType>
+ <Optimize>False</Optimize>
+ <CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>PdbOnly</DebugType>
+ <Optimize>True</Optimize>
+ <CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
+ <DefineConstants>TRACE</DefineConstants>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="ICSharpCode.NRefactory">
+ <HintPath>..\packages\ICSharpCode.NRefactory.5.5.1\lib\Net40\ICSharpCode.NRefactory.dll</HintPath>
+ </Reference>
+ <Reference Include="ICSharpCode.NRefactory.Cecil">
+ <HintPath>..\packages\ICSharpCode.NRefactory.5.5.1\lib\Net40\ICSharpCode.NRefactory.Cecil.dll</HintPath>
+ </Reference>
+ <Reference Include="ICSharpCode.NRefactory.CSharp">
+ <HintPath>..\packages\ICSharpCode.NRefactory.5.5.1\lib\Net40\ICSharpCode.NRefactory.CSharp.dll</HintPath>
+ </Reference>
+ <Reference Include="ICSharpCode.NRefactory.Xml">
+ <HintPath>..\packages\ICSharpCode.NRefactory.5.5.1\lib\Net40\ICSharpCode.NRefactory.Xml.dll</HintPath>
+ </Reference>
+ <Reference Include="Mono.Cecil">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.dll</HintPath>
+ </Reference>
+ <Reference Include="Mono.Cecil.Mdb">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Mdb.dll</HintPath>
+ </Reference>
+ <Reference Include="Mono.Cecil.Pdb">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Pdb.dll</HintPath>
+ </Reference>
+ <Reference Include="Mono.Cecil.Rocks">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Ast\Annotations.cs" />
+ <Compile Include="Ast\AstBuilder.cs" />
+ <Compile Include="Ast\AstMethodBodyBuilder.cs" />
+ <Compile Include="Ast\CommentStatement.cs" />
+ <Compile Include="Ast\DecompilerContext.cs" />
+ <Compile Include="Ast\NameVariables.cs" />
+ <Compile Include="Ast\NRefactoryExtensions.cs" />
+ <Compile Include="Ast\TextTokenWriter.cs" />
+ <Compile Include="Ast\Transforms\AddCheckedBlocks.cs" />
+ <Compile Include="Ast\Transforms\CombineQueryExpressions.cs" />
+ <Compile Include="Ast\Transforms\ContextTrackingVisitor.cs" />
+ <Compile Include="Ast\Transforms\ConvertConstructorCallIntoInitializer.cs" />
+ <Compile Include="Ast\Transforms\CustomPatterns.cs" />
+ <Compile Include="Ast\Transforms\DecimalConstantTransform.cs" />
+ <Compile Include="Ast\Transforms\DeclareVariables.cs" />
+ <Compile Include="Ast\Transforms\DelegateConstruction.cs" />
+ <Compile Include="Ast\Transforms\ExpressionTreeConverter.cs" />
+ <Compile Include="Ast\Transforms\FlattenSwitchBlocks.cs" />
+ <Compile Include="Ast\Transforms\IntroduceExtensionMethods.cs" />
+ <Compile Include="Ast\Transforms\IntroduceQueryExpressions.cs" />
+ <Compile Include="Ast\Transforms\IntroduceUnsafeModifier.cs" />
+ <Compile Include="Ast\Transforms\IntroduceUsingDeclarations.cs" />
+ <Compile Include="Ast\Transforms\ReplaceMethodCallsWithOperators.cs" />
+ <Compile Include="Ast\Transforms\PushNegation.cs" />
+ <Compile Include="Ast\Transforms\TransformationPipeline.cs" />
+ <Compile Include="Ast\Transforms\PatternStatementTransform.cs" />
+ <Compile Include="Ast\TypesHierarchyHelpers.cs" />
+ <Compile Include="CecilExtensions.cs" />
+ <Compile Include="CodeMappings.cs" />
+ <Compile Include="DecompilerException.cs" />
+ <Compile Include="DecompilerSettings.cs" />
+ <Compile Include="Disassembler\DisassemblerHelpers.cs" />
+ <Compile Include="Disassembler\ILStructure.cs" />
+ <Compile Include="Disassembler\MethodBodyDisassembler.cs" />
+ <Compile Include="Disassembler\ReflectionDisassembler.cs" />
+ <Compile Include="FlowAnalysis\ControlFlowEdge.cs" />
+ <Compile Include="FlowAnalysis\ControlFlowGraph.cs" />
+ <Compile Include="FlowAnalysis\ControlFlowGraphBuilder.cs" />
+ <Compile Include="FlowAnalysis\ControlFlowNode.cs" />
+ <Compile Include="FlowAnalysis\ControlStructureDetector.cs" />
+ <Compile Include="FlowAnalysis\OpCodeInfo.cs" />
+ <Compile Include="FlowAnalysis\SimplifyByRefCalls.cs" />
+ <Compile Include="FlowAnalysis\SsaBlock.cs" />
+ <Compile Include="FlowAnalysis\SsaForm.cs" />
+ <Compile Include="FlowAnalysis\SsaFormBuilder.cs" />
+ <Compile Include="FlowAnalysis\SsaInstruction.cs" />
+ <Compile Include="FlowAnalysis\SsaOptimization.cs" />
+ <Compile Include="FlowAnalysis\SsaVariable.cs" />
+ <Compile Include="FlowAnalysis\TransformToSsa.cs" />
+ <Compile Include="ILAst\AsyncDecompiler.cs" />
+ <Compile Include="ILAst\LiftedOperators.cs" />
+ <Compile Include="ILAst\InitializerPeepholeTransforms.cs" />
+ <Compile Include="ILAst\DefaultDictionary.cs" />
+ <Compile Include="ILAst\GotoRemoval.cs" />
+ <Compile Include="ILAst\ILAstBuilder.cs" />
+ <Compile Include="ILAst\ILAstOptimizer.cs" />
+ <Compile Include="ILAst\ILAstTypes.cs" />
+ <Compile Include="ILAst\ILCodes.cs" />
+ <Compile Include="ILAst\ILInlining.cs" />
+ <Compile Include="ILAst\LoopsAndConditions.cs" />
+ <Compile Include="ILAst\PatternMatching.cs" />
+ <Compile Include="ILAst\PeepholeTransform.cs" />
+ <Compile Include="ILAst\SimpleControlFlow.cs" />
+ <Compile Include="ILAst\StateRange.cs" />
+ <Compile Include="ILAst\SymbolicExecution.cs" />
+ <Compile Include="ILAst\TypeAnalysis.cs" />
+ <Compile Include="ILAst\YieldReturnDecompiler.cs" />
+ <Compile Include="ITextOutput.cs" />
+ <Compile Include="PlainTextOutput.cs" />
+ <Compile Include="ReferenceResolvingException.cs" />
+ <Compile Include="TextOutputWriter.cs" />
+ <None Include="Properties\AssemblyInfo.template.cs" />
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup />
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+ </Target>
+</Project>
diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.sln b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.sln
new file mode 100644
index 00000000..daa5dc43
--- /dev/null
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.sln
@@ -0,0 +1,17 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Decompiler", "ICSharpCode.Decompiler.csproj", "{984CC812-9470-4A13-AFF9-CC44068D666C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/ICSharpCode.Decompiler/ILAst/AsyncDecompiler.cs b/ICSharpCode.Decompiler/ILAst/AsyncDecompiler.cs
new file mode 100644
index 00000000..801673f9
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/AsyncDecompiler.cs
@@ -0,0 +1,704 @@
+// Copyright (c) 2012 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ /// <summary>
+ /// Decompiler step for C# 5 async/await.
+ /// </summary>
+ internal class AsyncDecompiler
+ {
+ public static bool IsCompilerGeneratedStateMachine(TypeDefinition type)
+ {
+ if (!(type.DeclaringType != null && type.IsCompilerGenerated()))
+ return false;
+ foreach (TypeReference i in type.Interfaces) {
+ if (i.Namespace == "System.Runtime.CompilerServices" && i.Name == "IAsyncStateMachine")
+ return true;
+ }
+ return false;
+ }
+
+ enum AsyncMethodType
+ {
+ Void,
+ Task,
+ TaskOfT
+ }
+
+ DecompilerContext context;
+
+ // These fields are set by MatchTaskCreationPattern()
+ AsyncMethodType methodType;
+ int initialState;
+ TypeDefinition stateMachineStruct;
+ MethodDefinition moveNextMethod;
+ FieldDefinition builderField;
+ FieldDefinition stateField;
+ Dictionary<FieldDefinition, ILVariable> fieldToParameterMap = new Dictionary<FieldDefinition, ILVariable>();
+ ILVariable cachedStateVar;
+
+ // These fields are set by AnalyzeMoveNext()
+ int finalState = -2;
+ ILTryCatchBlock mainTryCatch;
+ ILLabel setResultAndExitLabel;
+ ILLabel exitLabel;
+ ILExpression resultExpr;
+
+ #region RunStep1() method
+ public static void RunStep1(DecompilerContext context, ILBlock method)
+ {
+ if (!context.Settings.AsyncAwait)
+ return; // abort if async decompilation is disabled
+ var yrd = new AsyncDecompiler();
+ yrd.context = context;
+ if (!yrd.MatchTaskCreationPattern(method))
+ return;
+ #if DEBUG
+ if (Debugger.IsAttached) {
+ yrd.Run();
+ } else {
+ #endif
+ try {
+ yrd.Run();
+ } catch (SymbolicAnalysisFailedException) {
+ return;
+ }
+ #if DEBUG
+ }
+ #endif
+ context.CurrentMethodIsAsync = true;
+
+ method.Body.Clear();
+ method.EntryGoto = null;
+ method.Body.AddRange(yrd.newTopLevelBody);
+ ILAstOptimizer.RemoveRedundantCode(method);
+ }
+
+ void Run()
+ {
+ AnalyzeMoveNext();
+ ValidateCatchBlock(mainTryCatch.CatchBlocks[0]);
+ AnalyzeStateMachine(mainTryCatch.TryBlock);
+ // AnalyzeStateMachine invokes ConvertBody
+ MarkGeneratedVariables();
+ YieldReturnDecompiler.TranslateFieldsToLocalAccess(newTopLevelBody, fieldToParameterMap);
+ }
+ #endregion
+
+ #region MatchTaskCreationPattern
+ bool MatchTaskCreationPattern(ILBlock method)
+ {
+ if (method.Body.Count < 5)
+ return false;
+ // Check the second-to-last instruction (the start call) first, as we can get the most information from that
+ MethodReference startMethod;
+ ILExpression loadStartTarget, loadStartArgument;
+ // call(AsyncTaskMethodBuilder::Start, ldloca(builder), ldloca(stateMachine))
+ if (!method.Body[method.Body.Count - 2].Match(ILCode.Call, out startMethod, out loadStartTarget, out loadStartArgument))
+ return false;
+ if (startMethod.Name != "Start" || startMethod.DeclaringType == null || startMethod.DeclaringType.Namespace != "System.Runtime.CompilerServices")
+ return false;
+ switch (startMethod.DeclaringType.Name) {
+ case "AsyncTaskMethodBuilder`1":
+ methodType = AsyncMethodType.TaskOfT;
+ break;
+ case "AsyncTaskMethodBuilder":
+ methodType = AsyncMethodType.Task;
+ break;
+ case "AsyncVoidMethodBuilder":
+ methodType = AsyncMethodType.Void;
+ break;
+ default:
+ return false;
+ }
+ ILVariable stateMachineVar, builderVar;
+ if (!loadStartTarget.Match(ILCode.Ldloca, out builderVar))
+ return false;
+ if (!loadStartArgument.Match(ILCode.Ldloca, out stateMachineVar))
+ return false;
+
+ stateMachineStruct = stateMachineVar.Type.ResolveWithinSameModule();
+ if (stateMachineStruct == null || !stateMachineStruct.IsValueType)
+ return false;
+ moveNextMethod = stateMachineStruct.Methods.FirstOrDefault(f => f.Name == "MoveNext");
+ if (moveNextMethod == null)
+ return false;
+
+ // Check third-to-last instruction (copy of builder):
+ // stloc(builder, ldfld(StateMachine::<>t__builder, ldloca(stateMachine)))
+ ILExpression loadBuilderExpr;
+ if (!method.Body[method.Body.Count - 3].MatchStloc(builderVar, out loadBuilderExpr))
+ return false;
+ FieldReference builderFieldRef;
+ ILExpression loadStateMachineForBuilderExpr;
+ if (!loadBuilderExpr.Match(ILCode.Ldfld, out builderFieldRef, out loadStateMachineForBuilderExpr))
+ return false;
+ if (!(loadStateMachineForBuilderExpr.MatchLdloca(stateMachineVar) || loadStateMachineForBuilderExpr.MatchLdloc(stateMachineVar)))
+ return false;
+ builderField = builderFieldRef.ResolveWithinSameModule();
+ if (builderField == null)
+ return false;
+
+ // Check the last instruction (ret)
+ if (methodType == AsyncMethodType.Void) {
+ if (!method.Body[method.Body.Count - 1].Match(ILCode.Ret))
+ return false;
+ } else {
+ // ret(call(AsyncTaskMethodBuilder::get_Task, ldflda(StateMachine::<>t__builder, ldloca(stateMachine))))
+ ILExpression returnValue;
+ if (!method.Body[method.Body.Count - 1].Match(ILCode.Ret, out returnValue))
+ return false;
+ MethodReference getTaskMethod;
+ ILExpression builderExpr;
+ if (!returnValue.Match(ILCode.Call, out getTaskMethod, out builderExpr))
+ return false;
+ ILExpression loadStateMachineForBuilderExpr2;
+ FieldReference builderField2;
+ if (!builderExpr.Match(ILCode.Ldflda, out builderField2, out loadStateMachineForBuilderExpr2))
+ return false;
+ if (builderField2.ResolveWithinSameModule() != builderField || !loadStateMachineForBuilderExpr2.MatchLdloca(stateMachineVar))
+ return false;
+ }
+
+ // Check the last field assignment - this should be the state field
+ ILExpression initialStateExpr;
+ if (!MatchStFld(method.Body[method.Body.Count - 4], stateMachineVar, out stateField, out initialStateExpr))
+ return false;
+ if (!initialStateExpr.Match(ILCode.Ldc_I4, out initialState))
+ return false;
+ if (initialState != -1)
+ return false;
+
+ // Check the second-to-last field assignment - this should be the builder field
+ FieldDefinition builderField3;
+ ILExpression builderInitialization;
+ if (!MatchStFld(method.Body[method.Body.Count - 5], stateMachineVar, out builderField3, out builderInitialization))
+ return false;
+ MethodReference createMethodRef;
+ if (builderField3 != builderField || !builderInitialization.Match(ILCode.Call, out createMethodRef))
+ return false;
+ if (createMethodRef.Name != "Create")
+ return false;
+
+ for (int i = 0; i < method.Body.Count - 5; i++) {
+ FieldDefinition field;
+ ILExpression fieldInit;
+ if (!MatchStFld(method.Body[i], stateMachineVar, out field, out fieldInit))
+ return false;
+ ILVariable v;
+ if (!fieldInit.Match(ILCode.Ldloc, out v))
+ return false;
+ if (!v.IsParameter)
+ return false;
+ fieldToParameterMap[field] = v;
+ }
+
+ return true;
+ }
+
+ static bool MatchStFld(ILNode stfld, ILVariable stateMachineVar, out FieldDefinition field, out ILExpression expr)
+ {
+ field = null;
+ FieldReference fieldRef;
+ ILExpression ldloca;
+ if (!stfld.Match(ILCode.Stfld, out fieldRef, out ldloca, out expr))
+ return false;
+ field = fieldRef.ResolveWithinSameModule();
+ return field != null && ldloca.MatchLdloca(stateMachineVar);
+ }
+ #endregion
+
+ #region Analyze MoveNext
+ void AnalyzeMoveNext()
+ {
+ ILBlock ilMethod = CreateILAst(moveNextMethod);
+
+ int startIndex;
+ if (ilMethod.Body.Count == 6) {
+ startIndex = 0;
+ } else if (ilMethod.Body.Count == 7) {
+ // stloc(cachedState, ldfld(valuetype StateMachineStruct::<>1__state, ldloc(this)))
+ ILExpression cachedStateInit;
+ if (!ilMethod.Body[0].Match(ILCode.Stloc, out cachedStateVar, out cachedStateInit))
+ throw new SymbolicAnalysisFailedException();
+ ILExpression instanceExpr;
+ FieldReference loadedField;
+ if (!cachedStateInit.Match(ILCode.Ldfld, out loadedField, out instanceExpr) || loadedField.ResolveWithinSameModule() != stateField || !instanceExpr.MatchThis())
+ throw new SymbolicAnalysisFailedException();
+ startIndex = 1;
+ } else {
+ throw new SymbolicAnalysisFailedException();
+ }
+
+ mainTryCatch = ilMethod.Body[startIndex + 0] as ILTryCatchBlock;
+ if (mainTryCatch == null || mainTryCatch.CatchBlocks.Count != 1)
+ throw new SymbolicAnalysisFailedException();
+ if (mainTryCatch.FaultBlock != null || mainTryCatch.FinallyBlock != null)
+ throw new SymbolicAnalysisFailedException();
+
+ setResultAndExitLabel = ilMethod.Body[startIndex + 1] as ILLabel;
+ if (setResultAndExitLabel == null)
+ throw new SymbolicAnalysisFailedException();
+
+ if (!MatchStateAssignment(ilMethod.Body[startIndex + 2], out finalState))
+ throw new SymbolicAnalysisFailedException();
+
+ // call(AsyncTaskMethodBuilder`1::SetResult, ldflda(StateMachine::<>t__builder, ldloc(this)), ldloc(<>t__result))
+ MethodReference setResultMethod;
+ ILExpression builderExpr;
+ if (methodType == AsyncMethodType.TaskOfT) {
+ if (!ilMethod.Body[startIndex + 3].Match(ILCode.Call, out setResultMethod, out builderExpr, out resultExpr))
+ throw new SymbolicAnalysisFailedException();
+ } else {
+ if (!ilMethod.Body[startIndex + 3].Match(ILCode.Call, out setResultMethod, out builderExpr))
+ throw new SymbolicAnalysisFailedException();
+ }
+ if (!(setResultMethod.Name == "SetResult" && IsBuilderFieldOnThis(builderExpr)))
+ throw new SymbolicAnalysisFailedException();
+
+ exitLabel = ilMethod.Body[startIndex + 4] as ILLabel;
+ if (exitLabel == null)
+ throw new SymbolicAnalysisFailedException();
+ }
+
+ /// <summary>
+ /// Creates ILAst for the specified method, optimized up to before the 'YieldReturn' step.
+ /// </summary>
+ ILBlock CreateILAst(MethodDefinition method)
+ {
+ if (method == null || !method.HasBody)
+ throw new SymbolicAnalysisFailedException();
+
+ ILBlock ilMethod = new ILBlock();
+ ILAstBuilder astBuilder = new ILAstBuilder();
+ ilMethod.Body = astBuilder.Build(method, true, context);
+ ILAstOptimizer optimizer = new ILAstOptimizer();
+ optimizer.Optimize(context, ilMethod, ILAstOptimizationStep.YieldReturn);
+ return ilMethod;
+ }
+
+ void ValidateCatchBlock(ILTryCatchBlock.CatchBlock catchBlock)
+ {
+ if (catchBlock.ExceptionType == null || catchBlock.ExceptionType.Name != "Exception")
+ throw new SymbolicAnalysisFailedException();
+ if (catchBlock.Body.Count != 3)
+ throw new SymbolicAnalysisFailedException();
+ int stateID;
+ if (!(MatchStateAssignment(catchBlock.Body[0], out stateID) && stateID == finalState))
+ throw new SymbolicAnalysisFailedException();
+ MethodReference setExceptionMethod;
+ ILExpression builderExpr, exceptionExpr;
+ if (!catchBlock.Body[1].Match(ILCode.Call, out setExceptionMethod, out builderExpr, out exceptionExpr))
+ throw new SymbolicAnalysisFailedException();
+ if (!(setExceptionMethod.Name == "SetException" && IsBuilderFieldOnThis(builderExpr) && exceptionExpr.MatchLdloc(catchBlock.ExceptionVariable)))
+ throw new SymbolicAnalysisFailedException();
+
+ ILLabel label;
+ if (!(catchBlock.Body[2].Match(ILCode.Leave, out label) && label == exitLabel))
+ throw new SymbolicAnalysisFailedException();
+ }
+
+ bool IsBuilderFieldOnThis(ILExpression builderExpr)
+ {
+ // ldflda(StateMachine::<>t__builder, ldloc(this))
+ FieldReference fieldRef;
+ ILExpression target;
+ return builderExpr.Match(ILCode.Ldflda, out fieldRef, out target)
+ && fieldRef.ResolveWithinSameModule() == builderField
+ && target.MatchThis();
+ }
+
+ bool MatchStateAssignment(ILNode stfld, out int stateID)
+ {
+ // stfld(StateMachine::<>1__state, ldloc(this), ldc.i4(stateId))
+ stateID = 0;
+ FieldReference fieldRef;
+ ILExpression target, val;
+ if (stfld.Match(ILCode.Stfld, out fieldRef, out target, out val)) {
+ return fieldRef.ResolveWithinSameModule() == stateField
+ && target.MatchThis()
+ && val.Match(ILCode.Ldc_I4, out stateID);
+ }
+ return false;
+ }
+
+ bool MatchRoslynStateAssignment(List<ILNode> block, int index, out int stateID)
+ {
+ // v = ldc.i4(stateId)
+ // stloc(cachedState, v)
+ // stfld(StateMachine::<>1__state, ldloc(this), v)
+ stateID = 0;
+ if (index < 0)
+ return false;
+ ILVariable v;
+ ILExpression val;
+ if (!block[index].Match(ILCode.Stloc, out v, out val) || !val.Match(ILCode.Ldc_I4, out stateID))
+ return false;
+ ILExpression loadV;
+ if (!block[index + 1].MatchStloc(cachedStateVar, out loadV) || !loadV.MatchLdloc(v))
+ return false;
+ ILExpression target;
+ FieldReference fieldRef;
+ if (block[index + 2].Match(ILCode.Stfld, out fieldRef, out target, out loadV)) {
+ return fieldRef.ResolveWithinSameModule() == stateField
+ && target.MatchThis()
+ && loadV.MatchLdloc(v);
+ }
+ return false;
+ }
+ #endregion
+
+ #region AnalyzeStateMachine
+ ILVariable doFinallyBodies;
+ List<ILNode> newTopLevelBody;
+
+ void AnalyzeStateMachine(ILBlock block)
+ {
+ var body = block.Body;
+ if (body.Count == 0)
+ throw new SymbolicAnalysisFailedException();
+ if (DetectDoFinallyBodies(body)) {
+ body.RemoveAt(0);
+ if (body.Count == 0)
+ throw new SymbolicAnalysisFailedException();
+ }
+ StateRangeAnalysis rangeAnalysis = new StateRangeAnalysis(body[0], StateRangeAnalysisMode.AsyncMoveNext, stateField, cachedStateVar);
+ int bodyLength = block.Body.Count;
+ int pos = rangeAnalysis.AssignStateRanges(body, bodyLength);
+ rangeAnalysis.EnsureLabelAtPos(body, ref pos, ref bodyLength);
+
+ var labelStateRangeMapping = rangeAnalysis.CreateLabelRangeMapping(body, pos, bodyLength);
+ newTopLevelBody = ConvertBody(body, pos, bodyLength, labelStateRangeMapping);
+ newTopLevelBody.Insert(0, MakeGoTo(labelStateRangeMapping, initialState));
+ newTopLevelBody.Add(setResultAndExitLabel);
+ if (methodType == AsyncMethodType.TaskOfT) {
+ newTopLevelBody.Add(new ILExpression(ILCode.Ret, null, resultExpr));
+ } else {
+ newTopLevelBody.Add(new ILExpression(ILCode.Ret, null));
+ }
+ }
+
+ bool DetectDoFinallyBodies(List<ILNode> body)
+ {
+ ILVariable v;
+ ILExpression initExpr;
+ if (!body[0].Match(ILCode.Stloc, out v, out initExpr))
+ return false;
+ int initialValue;
+ if (!(initExpr.Match(ILCode.Ldc_I4, out initialValue) && initialValue == 1))
+ return false;
+ doFinallyBodies = v;
+ return true;
+ }
+ #endregion
+
+ #region ConvertBody
+ ILExpression MakeGoTo(LabelRangeMapping mapping, int state)
+ {
+ foreach (var pair in mapping) {
+ if (pair.Value.Contains(state))
+ return new ILExpression(ILCode.Br, pair.Key);
+ }
+ throw new SymbolicAnalysisFailedException();
+ }
+
+ List<ILNode> ConvertBody(List<ILNode> body, int startPos, int bodyLength, LabelRangeMapping mapping)
+ {
+ List<ILNode> newBody = new List<ILNode>();
+ // Copy all instructions from the old body to newBody.
+ for (int pos = startPos; pos < bodyLength; pos++) {
+ ILTryCatchBlock tryCatchBlock = body[pos] as ILTryCatchBlock;
+ ILExpression expr = body[pos] as ILExpression;
+ if (expr != null && expr.Code == ILCode.Leave && expr.Operand == exitLabel) {
+ ILVariable awaiterVar;
+ FieldDefinition awaiterField;
+ int targetStateID;
+ HandleAwait(newBody, out awaiterVar, out awaiterField, out targetStateID);
+ MarkAsGeneratedVariable(awaiterVar);
+ newBody.Add(new ILExpression(ILCode.Await, null, new ILExpression(ILCode.Ldloca, awaiterVar)));
+ newBody.Add(MakeGoTo(mapping, targetStateID));
+ } else if (tryCatchBlock != null) {
+ ILTryCatchBlock newTryCatchBlock = new ILTryCatchBlock();
+ var tryBody = tryCatchBlock.TryBlock.Body;
+ if (tryBody.Count == 0)
+ throw new SymbolicAnalysisFailedException();
+ StateRangeAnalysis rangeAnalysis = new StateRangeAnalysis(tryBody[0], StateRangeAnalysisMode.AsyncMoveNext, stateField);
+ int tryBodyLength = tryBody.Count;
+ int posInTryBody = rangeAnalysis.AssignStateRanges(tryBody, tryBodyLength);
+ rangeAnalysis.EnsureLabelAtPos(tryBody, ref posInTryBody, ref tryBodyLength);
+
+ var mappingInTryBlock = rangeAnalysis.CreateLabelRangeMapping(tryBody, posInTryBody, tryBodyLength);
+ var newTryBody = ConvertBody(tryBody, posInTryBody, tryBodyLength, mappingInTryBlock);
+ newTryBody.Insert(0, MakeGoTo(mappingInTryBlock, initialState));
+
+ // If there's a label at the beginning of the state dispatcher, copy that
+ if (posInTryBody > 0 && tryBody.FirstOrDefault() is ILLabel)
+ newTryBody.Insert(0, tryBody.First());
+
+ newTryCatchBlock.TryBlock = new ILBlock(newTryBody);
+ newTryCatchBlock.CatchBlocks = new List<ILTryCatchBlock.CatchBlock>(tryCatchBlock.CatchBlocks);
+ newTryCatchBlock.FaultBlock = tryCatchBlock.FaultBlock;
+ if (tryCatchBlock.FinallyBlock != null)
+ newTryCatchBlock.FinallyBlock = new ILBlock(ConvertFinally(tryCatchBlock.FinallyBlock.Body));
+
+ newBody.Add(newTryCatchBlock);
+ } else {
+ newBody.Add(body[pos]);
+ }
+ }
+ return newBody;
+ }
+
+ List<ILNode> ConvertFinally(List<ILNode> body)
+ {
+ List<ILNode> newBody = new List<ILNode>(body);
+ if (newBody.Count == 0)
+ return newBody;
+ ILLabel endFinallyLabel;
+ ILExpression ceqExpr;
+ if (newBody[0].Match(ILCode.Brtrue, out endFinallyLabel, out ceqExpr)) {
+ ILExpression condition;
+ if (MatchLogicNot(ceqExpr, out condition)) {
+ if (condition.MatchLdloc(doFinallyBodies)) {
+ newBody.RemoveAt(0);
+ } else if (condition.Code == ILCode.Clt && condition.Arguments[0].MatchLdloc(cachedStateVar) && condition.Arguments[1].MatchLdcI4(0)) {
+ newBody.RemoveAt(0);
+ }
+ }
+ }
+ return newBody;
+ }
+
+ bool MatchLogicNot(ILExpression expr, out ILExpression arg)
+ {
+ ILExpression loadZero;
+ object unused;
+ if (expr.Match(ILCode.Ceq, out unused, out arg, out loadZero)) {
+ int num;
+ return loadZero.Match(ILCode.Ldc_I4, out num) && num == 0;
+ }
+ return expr.Match(ILCode.LogicNot, out arg);
+ }
+
+ void HandleAwait(List<ILNode> newBody, out ILVariable awaiterVar, out FieldDefinition awaiterField, out int targetStateID)
+ {
+ // Handle the instructions prior to the exit out of the method to detect what is being awaited.
+ // (analyses the last instructions in newBody and removes the analyzed instructions from newBody)
+
+ if (doFinallyBodies != null) {
+ // stloc(<>t__doFinallyBodies, ldc.i4(0))
+ ILExpression dfbInitExpr;
+ if (!newBody.LastOrDefault().MatchStloc(doFinallyBodies, out dfbInitExpr))
+ throw new SymbolicAnalysisFailedException();
+ int val;
+ if (!(dfbInitExpr.Match(ILCode.Ldc_I4, out val) && val == 0))
+ throw new SymbolicAnalysisFailedException();
+ newBody.RemoveAt(newBody.Count - 1); // remove doFinallyBodies assignment
+ }
+
+ // call(AsyncTaskMethodBuilder::AwaitUnsafeOnCompleted, ldflda(StateMachine::<>t__builder, ldloc(this)), ldloca(CS$0$0001), ldloc(this))
+ ILExpression callAwaitUnsafeOnCompleted = newBody.LastOrDefault() as ILExpression;
+ newBody.RemoveAt(newBody.Count - 1); // remove AwaitUnsafeOnCompleted call
+ if (callAwaitUnsafeOnCompleted == null || callAwaitUnsafeOnCompleted.Code != ILCode.Call)
+ throw new SymbolicAnalysisFailedException();
+ string methodName = ((MethodReference)callAwaitUnsafeOnCompleted.Operand).Name;
+ if (methodName != "AwaitUnsafeOnCompleted" && methodName != "AwaitOnCompleted")
+ throw new SymbolicAnalysisFailedException();
+ if (callAwaitUnsafeOnCompleted.Arguments.Count != 3)
+ throw new SymbolicAnalysisFailedException();
+ if (!callAwaitUnsafeOnCompleted.Arguments[1].Match(ILCode.Ldloca, out awaiterVar))
+ throw new SymbolicAnalysisFailedException();
+
+ // stfld(StateMachine::<>u__$awaiter6, ldloc(this), ldloc(CS$0$0001))
+ FieldReference awaiterFieldRef;
+ ILExpression loadThis, loadAwaiterVar;
+ if (!newBody.LastOrDefault().Match(ILCode.Stfld, out awaiterFieldRef, out loadThis, out loadAwaiterVar))
+ throw new SymbolicAnalysisFailedException();
+ newBody.RemoveAt(newBody.Count - 1); // remove awaiter field assignment
+ awaiterField = awaiterFieldRef.ResolveWithinSameModule();
+ if (!(awaiterField != null && loadThis.MatchThis() && loadAwaiterVar.MatchLdloc(awaiterVar)))
+ throw new SymbolicAnalysisFailedException();
+
+ // stfld(StateMachine::<>1__state, ldloc(this), ldc.i4(0))
+ if (MatchStateAssignment(newBody.LastOrDefault(), out targetStateID))
+ newBody.RemoveAt(newBody.Count - 1); // remove awaiter field assignment
+ else if (MatchRoslynStateAssignment(newBody, newBody.Count - 3, out targetStateID))
+ newBody.RemoveRange(newBody.Count - 3, 3); // remove awaiter field assignment
+ }
+ #endregion
+
+ #region MarkGeneratedVariables
+ int smallestGeneratedVariableIndex = int.MaxValue;
+
+ void MarkAsGeneratedVariable(ILVariable v)
+ {
+ if (v.OriginalVariable != null && v.OriginalVariable.Index >= 0) {
+ smallestGeneratedVariableIndex = Math.Min(smallestGeneratedVariableIndex, v.OriginalVariable.Index);
+ }
+ }
+
+ void MarkGeneratedVariables()
+ {
+ var expressions = new ILBlock(newTopLevelBody).GetSelfAndChildrenRecursive<ILExpression>();
+ foreach (var v in expressions.Select(e => e.Operand).OfType<ILVariable>()) {
+ if (v.OriginalVariable != null && v.OriginalVariable.Index >= smallestGeneratedVariableIndex)
+ v.IsGenerated = true;
+ }
+ }
+ #endregion
+
+ #region RunStep2() method
+ public static void RunStep2(DecompilerContext context, ILBlock method)
+ {
+ if (context.CurrentMethodIsAsync) {
+ Step2(method.Body);
+ ILAstOptimizer.RemoveRedundantCode(method);
+ // Repeat the inlining/copy propagation optimization because the conversion of field access
+ // to local variables can open up additional inlining possibilities.
+ ILInlining inlining = new ILInlining(method);
+ inlining.InlineAllVariables();
+ inlining.CopyPropagation();
+ }
+ }
+
+ static void Step2(List<ILNode> body)
+ {
+ for (int pos = 0; pos < body.Count; pos++) {
+ ILTryCatchBlock tc = body[pos] as ILTryCatchBlock;
+ if (tc != null) {
+ Step2(tc.TryBlock.Body);
+ } else {
+ Step2(body, ref pos);
+ }
+ }
+ }
+
+ static bool Step2(List<ILNode> body, ref int pos)
+ {
+ // stloc(CS$0$0001, callvirt(class System.Threading.Tasks.Task`1<bool>::GetAwaiter, awaiterExpr)
+ // brtrue(IL_7C, call(valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter`1<bool>::get_IsCompleted, ldloca(CS$0$0001)))
+ // await(ldloca(CS$0$0001))
+ // ...
+ // IL_7C:
+ // arg_8B_0 = call(valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter`1<bool>::GetResult, ldloca(CS$0$0001))
+ // initobj(valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter`1<bool>, ldloca(CS$0$0001))
+
+ ILExpression loadAwaiter;
+ ILVariable awaiterVar;
+ if (!body[pos].Match(ILCode.Await, out loadAwaiter))
+ return false;
+ if (!loadAwaiter.Match(ILCode.Ldloca, out awaiterVar))
+ return false;
+
+ ILVariable stackVar;
+ ILExpression stackExpr;
+ while (pos >= 1 && body[pos - 1].Match(ILCode.Stloc, out stackVar, out stackExpr))
+ pos--;
+
+ // stloc(CS$0$0001, callvirt(class System.Threading.Tasks.Task`1<bool>::GetAwaiter, awaiterExpr)
+ ILExpression getAwaiterCall;
+ if (!(pos >= 2 && body[pos - 2].MatchStloc(awaiterVar, out getAwaiterCall)))
+ return false;
+ MethodReference getAwaiterMethod;
+ ILExpression awaitedExpr;
+ if (!(getAwaiterCall.Match(ILCode.Call, out getAwaiterMethod, out awaitedExpr) || getAwaiterCall.Match(ILCode.Callvirt, out getAwaiterMethod, out awaitedExpr)))
+ return false;
+
+ if (awaitedExpr.Code == ILCode.AddressOf) {
+ // remove 'AddressOf()' when calling GetAwaiter() on a value type
+ awaitedExpr = awaitedExpr.Arguments[0];
+ }
+
+ // brtrue(IL_7C, call(valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter`1<bool>::get_IsCompleted, ldloca(CS$0$0001)))
+ ILLabel label;
+ ILExpression getIsCompletedCall;
+ if (!(pos >= 1 && body[pos - 1].Match(ILCode.Brtrue, out label, out getIsCompletedCall)))
+ return false;
+
+ int labelPos = body.IndexOf(label);
+ if (labelPos < pos)
+ return false;
+ for (int i = pos + 1; i < labelPos; i++) {
+ // validate that we aren't deleting any unexpected instructions -
+ // between the await and the label, there should only be the stack, awaiter and state logic
+ ILExpression expr = body[i] as ILExpression;
+ if (expr == null)
+ return false;
+ switch (expr.Code) {
+ case ILCode.Stloc:
+ case ILCode.Initobj:
+ case ILCode.Stfld:
+ case ILCode.Await:
+ // e.g.
+ // stloc(CS$0$0001, ldfld(StateMachine::<>u__$awaitere, ldloc(this)))
+ // initobj(valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter`1<bool>, ldloca(CS$0$0002_66))
+ // stfld('<AwaitInLoopCondition>d__d'::<>u__$awaitere, ldloc(this), ldloc(CS$0$0002_66))
+ // stfld('<AwaitInLoopCondition>d__d'::<>1__state, ldloc(this), ldc.i4(-1))
+ break;
+ default:
+ return false;
+ }
+ }
+ if (labelPos + 1 >= body.Count)
+ return false;
+ ILExpression resultAssignment = body[labelPos + 1] as ILExpression;
+ ILVariable resultVar;
+ ILExpression getResultCall;
+ bool isResultAssignment = resultAssignment.Match(ILCode.Stloc, out resultVar, out getResultCall);
+ if (!isResultAssignment)
+ getResultCall = resultAssignment;
+ if (!(getResultCall.Operand is MethodReference && ((MethodReference)getResultCall.Operand).Name == "GetResult"))
+ return false;
+
+ pos -= 2; // also delete 'stloc', 'brtrue' and 'await'
+ body.RemoveRange(pos, labelPos - pos);
+ Debug.Assert(body[pos] == label);
+
+ pos++;
+ if (isResultAssignment) {
+ Debug.Assert(body[pos] == resultAssignment);
+ resultAssignment.Arguments[0] = new ILExpression(ILCode.Await, null, awaitedExpr);
+ } else {
+ body[pos] = new ILExpression(ILCode.Await, null, awaitedExpr);
+ }
+
+ // if the awaiter variable is cleared out in the next instruction, remove that instruction
+ if (IsVariableReset(body.ElementAtOrDefault(pos + 1), awaiterVar)) {
+ body.RemoveAt(pos + 1);
+ }
+
+ return true;
+ }
+
+ static bool IsVariableReset(ILNode expr, ILVariable variable)
+ {
+ object unused;
+ ILExpression ldloca;
+ return expr.Match(ILCode.Initobj, out unused, out ldloca) && ldloca.MatchLdloca(variable);
+ }
+ #endregion
+ }
+}
diff --git a/ICSharpCode.Decompiler/ILAst/DefaultDictionary.cs b/ICSharpCode.Decompiler/ILAst/DefaultDictionary.cs
new file mode 100644
index 00000000..1e359a3d
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/DefaultDictionary.cs
@@ -0,0 +1,128 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ /// <summary>
+ /// Dictionary with default values.
+ /// </summary>
+ internal sealed class DefaultDictionary<TKey, TValue> : IDictionary<TKey, TValue>
+ {
+ readonly IDictionary<TKey, TValue> dict;
+ readonly Func<TKey, TValue> defaultProvider;
+
+ public DefaultDictionary(TValue defaultValue, IDictionary<TKey, TValue> dictionary = null)
+ : this(key => defaultValue, dictionary)
+ {
+ }
+
+ public DefaultDictionary(Func<TKey, TValue> defaultProvider = null, IDictionary<TKey, TValue> dictionary = null)
+ {
+ dict = dictionary ?? new Dictionary<TKey, TValue>();
+ this.defaultProvider = defaultProvider ?? (key => default(TValue));
+ }
+
+ public TValue this[TKey key] {
+ get {
+ TValue val;
+ if (dict.TryGetValue(key, out val))
+ return val;
+ else
+ return dict[key] = defaultProvider(key);
+ }
+ set {
+ dict[key] = value;
+ }
+ }
+
+ public ICollection<TKey> Keys {
+ get { return dict.Keys; }
+ }
+
+ public ICollection<TValue> Values {
+ get { return dict.Values; }
+ }
+
+ public int Count {
+ get { return dict.Count; }
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly {
+ get { return false; }
+ }
+
+ public bool ContainsKey(TKey key)
+ {
+ return dict.ContainsKey(key);
+ }
+
+ public void Add(TKey key, TValue value)
+ {
+ dict.Add(key, value);
+ }
+
+ public bool Remove(TKey key)
+ {
+ return dict.Remove(key);
+ }
+
+ public bool TryGetValue(TKey key, out TValue value)
+ {
+ return dict.TryGetValue(key, out value);
+ }
+
+ void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
+ {
+ dict.Add(item);
+ }
+
+ public void Clear()
+ {
+ dict.Clear();
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
+ {
+ return dict.Contains(item);
+ }
+
+ void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
+ {
+ dict.CopyTo(array, arrayIndex);
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
+ {
+ return dict.Remove(item);
+ }
+
+ IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
+ {
+ return dict.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return dict.GetEnumerator();
+ }
+ }
+} \ No newline at end of file
diff --git a/ICSharpCode.Decompiler/ILAst/GotoRemoval.cs b/ICSharpCode.Decompiler/ILAst/GotoRemoval.cs
new file mode 100644
index 00000000..fafe13e1
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/GotoRemoval.cs
@@ -0,0 +1,319 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ public class GotoRemoval
+ {
+ Dictionary<ILNode, ILNode> parent = new Dictionary<ILNode, ILNode>();
+ Dictionary<ILNode, ILNode> nextSibling = new Dictionary<ILNode, ILNode>();
+
+ public void RemoveGotos(ILBlock method)
+ {
+ // Build the navigation data
+ parent[method] = null;
+ foreach (ILNode node in method.GetSelfAndChildrenRecursive<ILNode>()) {
+ ILNode previousChild = null;
+ foreach (ILNode child in node.GetChildren()) {
+ if (parent.ContainsKey(child))
+ throw new Exception("The following expression is linked from several locations: " + child.ToString());
+ parent[child] = node;
+ if (previousChild != null)
+ nextSibling[previousChild] = child;
+ previousChild = child;
+ }
+ if (previousChild != null)
+ nextSibling[previousChild] = null;
+ }
+
+ // Simplify gotos
+ bool modified;
+ do {
+ modified = false;
+ foreach (ILExpression gotoExpr in method.GetSelfAndChildrenRecursive<ILExpression>(e => e.Code == ILCode.Br || e.Code == ILCode.Leave)) {
+ modified |= TrySimplifyGoto(gotoExpr);
+ }
+ } while(modified);
+
+ RemoveRedundantCode(method);
+ }
+
+ public static void RemoveRedundantCode(ILBlock method)
+ {
+ // Remove dead lables and nops
+ HashSet<ILLabel> liveLabels = new HashSet<ILLabel>(method.GetSelfAndChildrenRecursive<ILExpression>(e => e.IsBranch()).SelectMany(e => e.GetBranchTargets()));
+ foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
+ block.Body = block.Body.Where(n => !n.Match(ILCode.Nop) && !(n is ILLabel && !liveLabels.Contains((ILLabel)n))).ToList();
+ }
+
+ // Remove redundant continue
+ foreach(ILWhileLoop loop in method.GetSelfAndChildrenRecursive<ILWhileLoop>()) {
+ var body = loop.BodyBlock.Body;
+ if (body.Count > 0 && body.Last().Match(ILCode.LoopContinue)) {
+ body.RemoveAt(body.Count - 1);
+ }
+ }
+
+ // Remove redundant break at the end of case
+ // Remove redundant case blocks altogether
+ foreach(ILSwitch ilSwitch in method.GetSelfAndChildrenRecursive<ILSwitch>()) {
+ foreach(ILBlock ilCase in ilSwitch.CaseBlocks) {
+ Debug.Assert(ilCase.EntryGoto == null);
+
+ int count = ilCase.Body.Count;
+ if (count >= 2) {
+ if (ilCase.Body[count - 2].IsUnconditionalControlFlow() &&
+ ilCase.Body[count - 1].Match(ILCode.LoopOrSwitchBreak))
+ {
+ ilCase.Body.RemoveAt(count - 1);
+ }
+ }
+ }
+
+ var defaultCase = ilSwitch.CaseBlocks.SingleOrDefault(cb => cb.Values == null);
+ // If there is no default block, remove empty case blocks
+ if (defaultCase == null || (defaultCase.Body.Count == 1 && defaultCase.Body.Single().Match(ILCode.LoopOrSwitchBreak))) {
+ ilSwitch.CaseBlocks.RemoveAll(b => b.Body.Count == 1 && b.Body.Single().Match(ILCode.LoopOrSwitchBreak));
+ }
+ }
+
+ // Remove redundant return at the end of method
+ if (method.Body.Count > 0 && method.Body.Last().Match(ILCode.Ret) && ((ILExpression)method.Body.Last()).Arguments.Count == 0) {
+ method.Body.RemoveAt(method.Body.Count - 1);
+ }
+
+ // Remove unreachable return statements
+ bool modified = false;
+ foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
+ for (int i = 0; i < block.Body.Count - 1;) {
+ if (block.Body[i].IsUnconditionalControlFlow() && block.Body[i+1].Match(ILCode.Ret)) {
+ modified = true;
+ block.Body.RemoveAt(i+1);
+ } else {
+ i++;
+ }
+ }
+ }
+ if (modified) {
+ // More removals might be possible
+ new GotoRemoval().RemoveGotos(method);
+ }
+ }
+
+ IEnumerable<ILNode> GetParents(ILNode node)
+ {
+ ILNode current = node;
+ while(true) {
+ current = parent[current];
+ if (current == null)
+ yield break;
+ yield return current;
+ }
+ }
+
+ bool TrySimplifyGoto(ILExpression gotoExpr)
+ {
+ Debug.Assert(gotoExpr.Code == ILCode.Br || gotoExpr.Code == ILCode.Leave);
+ Debug.Assert(gotoExpr.Prefixes == null);
+ Debug.Assert(gotoExpr.Operand != null);
+
+ ILNode target = Enter(gotoExpr, new HashSet<ILNode>());
+ if (target == null)
+ return false;
+
+ // The gotoExper is marked as visited because we do not want to
+ // walk over node which we plan to modify
+
+ // The simulated path always has to start in the same try-block
+ // in other for the same finally blocks to be executed.
+
+ if (target == Exit(gotoExpr, new HashSet<ILNode>() { gotoExpr })) {
+ gotoExpr.Code = ILCode.Nop;
+ gotoExpr.Operand = null;
+ if (target is ILExpression)
+ ((ILExpression)target).ILRanges.AddRange(gotoExpr.ILRanges);
+ gotoExpr.ILRanges.Clear();
+ return true;
+ }
+
+ ILNode breakBlock = GetParents(gotoExpr).FirstOrDefault(n => n is ILWhileLoop || n is ILSwitch);
+ if (breakBlock != null && target == Exit(breakBlock, new HashSet<ILNode>() { gotoExpr })) {
+ gotoExpr.Code = ILCode.LoopOrSwitchBreak;
+ gotoExpr.Operand = null;
+ return true;
+ }
+
+ ILNode continueBlock = GetParents(gotoExpr).FirstOrDefault(n => n is ILWhileLoop);
+ if (continueBlock != null && target == Enter(continueBlock, new HashSet<ILNode>() { gotoExpr })) {
+ gotoExpr.Code = ILCode.LoopContinue;
+ gotoExpr.Operand = null;
+ return true;
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Get the first expression to be excecuted if the instruction pointer is at the start of the given node.
+ /// Try blocks may not be entered in any way. If possible, the try block is returned as the node to be executed.
+ /// </summary>
+ ILNode Enter(ILNode node, HashSet<ILNode> visitedNodes)
+ {
+ if (node == null)
+ throw new ArgumentNullException();
+
+ if (!visitedNodes.Add(node))
+ return null; // Infinite loop
+
+ ILLabel label = node as ILLabel;
+ if (label != null) {
+ return Exit(label, visitedNodes);
+ }
+
+ ILExpression expr = node as ILExpression;
+ if (expr != null) {
+ if (expr.Code == ILCode.Br || expr.Code == ILCode.Leave) {
+ ILLabel target = (ILLabel)expr.Operand;
+ // Early exit - same try-block
+ if (GetParents(expr).OfType<ILTryCatchBlock>().FirstOrDefault() == GetParents(target).OfType<ILTryCatchBlock>().FirstOrDefault())
+ return Enter(target, visitedNodes);
+ // Make sure we are not entering any try-block
+ var srcTryBlocks = GetParents(expr).OfType<ILTryCatchBlock>().Reverse().ToList();
+ var dstTryBlocks = GetParents(target).OfType<ILTryCatchBlock>().Reverse().ToList();
+ // Skip blocks that we are already in
+ int i = 0;
+ while(i < srcTryBlocks.Count && i < dstTryBlocks.Count && srcTryBlocks[i] == dstTryBlocks[i]) i++;
+ if (i == dstTryBlocks.Count) {
+ return Enter(target, visitedNodes);
+ } else {
+ ILTryCatchBlock dstTryBlock = dstTryBlocks[i];
+ // Check that the goto points to the start
+ ILTryCatchBlock current = dstTryBlock;
+ while(current != null) {
+ foreach(ILNode n in current.TryBlock.Body) {
+ if (n is ILLabel) {
+ if (n == target)
+ return dstTryBlock;
+ } else if (!n.Match(ILCode.Nop)) {
+ current = n as ILTryCatchBlock;
+ break;
+ }
+ }
+ }
+ return null;
+ }
+ } else if (expr.Code == ILCode.Nop) {
+ return Exit(expr, visitedNodes);
+ } else if (expr.Code == ILCode.LoopOrSwitchBreak) {
+ ILNode breakBlock = GetParents(expr).First(n => n is ILWhileLoop || n is ILSwitch);
+ return Exit(breakBlock, new HashSet<ILNode>() { expr });
+ } else if (expr.Code == ILCode.LoopContinue) {
+ ILNode continueBlock = GetParents(expr).First(n => n is ILWhileLoop);
+ return Enter(continueBlock, new HashSet<ILNode>() { expr });
+ } else {
+ return expr;
+ }
+ }
+
+ ILBlock block = node as ILBlock;
+ if (block != null) {
+ if (block.EntryGoto != null) {
+ return Enter(block.EntryGoto, visitedNodes);
+ } else if (block.Body.Count > 0) {
+ return Enter(block.Body[0], visitedNodes);
+ } else {
+ return Exit(block, visitedNodes);
+ }
+ }
+
+ ILCondition cond = node as ILCondition;
+ if (cond != null) {
+ return cond.Condition;
+ }
+
+ ILWhileLoop loop = node as ILWhileLoop;
+ if (loop != null) {
+ if (loop.Condition != null) {
+ return loop.Condition;
+ } else {
+ return Enter(loop.BodyBlock, visitedNodes);
+ }
+ }
+
+ ILTryCatchBlock tryCatch = node as ILTryCatchBlock;
+ if (tryCatch != null) {
+ return tryCatch;
+ }
+
+ ILSwitch ilSwitch = node as ILSwitch;
+ if (ilSwitch != null) {
+ return ilSwitch.Condition;
+ }
+
+ throw new NotSupportedException(node.GetType().ToString());
+ }
+
+ /// <summary>
+ /// Get the first expression to be excecuted if the instruction pointer is at the end of the given node
+ /// </summary>
+ ILNode Exit(ILNode node, HashSet<ILNode> visitedNodes)
+ {
+ if (node == null)
+ throw new ArgumentNullException();
+
+ ILNode nodeParent = parent[node];
+ if (nodeParent == null)
+ return null; // Exited main body
+
+ if (nodeParent is ILBlock) {
+ ILNode nextNode = nextSibling[node];
+ if (nextNode != null) {
+ return Enter(nextNode, visitedNodes);
+ } else {
+ return Exit(nodeParent, visitedNodes);
+ }
+ }
+
+ if (nodeParent is ILCondition) {
+ return Exit(nodeParent, visitedNodes);
+ }
+
+ if (nodeParent is ILTryCatchBlock) {
+ // Finally blocks are completely ignored.
+ // We rely on the fact that try blocks can not be entered.
+ return Exit(nodeParent, visitedNodes);
+ }
+
+ if (nodeParent is ILSwitch) {
+ return null; // Implicit exit from switch is not allowed
+ }
+
+ if (nodeParent is ILWhileLoop) {
+ return Enter(nodeParent, visitedNodes);
+ }
+
+ throw new NotSupportedException(nodeParent.GetType().ToString());
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
new file mode 100644
index 00000000..21b2b150
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
@@ -0,0 +1,839 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Cecil = Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ /// <summary>
+ /// Converts stack-based bytecode to variable-based bytecode by calculating use-define chains
+ /// </summary>
+ public class ILAstBuilder
+ {
+ /// <summary> Immutable </summary>
+ struct StackSlot
+ {
+ public readonly ByteCode[] Definitions; // Reaching definitions of this stack slot
+ public readonly ILVariable LoadFrom; // Variable used for storage of the value
+
+ public StackSlot(ByteCode[] definitions, ILVariable loadFrom)
+ {
+ Definitions = definitions;
+ LoadFrom = loadFrom;
+ }
+
+ public static StackSlot[] ModifyStack(StackSlot[] stack, int popCount, int pushCount, ByteCode pushDefinition)
+ {
+ StackSlot[] newStack = new StackSlot[stack.Length - popCount + pushCount];
+ Array.Copy(stack, newStack, stack.Length - popCount);
+ for (int i = stack.Length - popCount; i < newStack.Length; i++) {
+ newStack[i] = new StackSlot(new [] { pushDefinition }, null);
+ }
+ return newStack;
+ }
+ }
+
+ /// <summary> Immutable </summary>
+ struct VariableSlot
+ {
+ public readonly ByteCode[] Definitions; // Reaching deinitions of this variable
+ public readonly bool UnknownDefinition; // Used for initial state and exceptional control flow
+
+ static readonly VariableSlot UnknownInstance = new VariableSlot(new ByteCode[0], true);
+
+ public VariableSlot(ByteCode[] definitions, bool unknownDefinition)
+ {
+ Definitions = definitions;
+ UnknownDefinition = unknownDefinition;
+ }
+
+ public static VariableSlot[] CloneVariableState(VariableSlot[] state)
+ {
+ VariableSlot[] clone = new VariableSlot[state.Length];
+ Array.Copy(state, clone, state.Length);
+ return clone;
+ }
+
+ public static VariableSlot[] MakeUknownState(int varCount)
+ {
+ VariableSlot[] unknownVariableState = new VariableSlot[varCount];
+ for (int i = 0; i < unknownVariableState.Length; i++) {
+ unknownVariableState[i] = UnknownInstance;
+ }
+ return unknownVariableState;
+ }
+ }
+
+ sealed class ByteCode
+ {
+ public ILLabel Label; // Non-null only if needed
+ public int Offset;
+ public int EndOffset;
+ public ILCode Code;
+ public object Operand;
+ public int? PopCount; // Null means pop all
+ public int PushCount;
+ public string Name { get { return "IL_" + Offset.ToString("X2"); } }
+ public ByteCode Next;
+ public Instruction[] Prefixes; // Non-null only if needed
+ public StackSlot[] StackBefore; // Unique per bytecode; not shared
+ public VariableSlot[] VariablesBefore; // Unique per bytecode; not shared
+ public List<ILVariable> StoreTo; // Store result of instruction to those AST variables
+
+ public bool IsVariableDefinition {
+ get {
+ return (Code == ILCode.Stloc) || (Code == ILCode.Ldloca && Next != null && Next.Code == ILCode.Initobj);
+ }
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ // Label
+ sb.Append(Name);
+ sb.Append(':');
+ if (Label != null)
+ sb.Append('*');
+
+ // Name
+ sb.Append(' ');
+ if (Prefixes != null) {
+ foreach (var prefix in Prefixes) {
+ sb.Append(prefix.OpCode.Name);
+ sb.Append(' ');
+ }
+ }
+ sb.Append(Code.GetName());
+
+ if (Operand != null) {
+ sb.Append(' ');
+ if (Operand is Instruction) {
+ sb.Append("IL_" + ((Instruction)Operand).Offset.ToString("X2"));
+ } else if (Operand is Instruction[]) {
+ foreach(Instruction inst in (Instruction[])Operand) {
+ sb.Append("IL_" + inst.Offset.ToString("X2"));
+ sb.Append(" ");
+ }
+ } else if (Operand is ILLabel) {
+ sb.Append(((ILLabel)Operand).Name);
+ } else if (Operand is ILLabel[]) {
+ foreach(ILLabel label in (ILLabel[])Operand) {
+ sb.Append(label.Name);
+ sb.Append(" ");
+ }
+ } else {
+ sb.Append(Operand.ToString());
+ }
+ }
+
+ if (StackBefore != null) {
+ sb.Append(" StackBefore={");
+ bool first = true;
+ foreach (StackSlot slot in StackBefore) {
+ if (!first) sb.Append(",");
+ bool first2 = true;
+ foreach(ByteCode defs in slot.Definitions) {
+ if (!first2) sb.Append("|");
+ sb.AppendFormat("IL_{0:X2}", defs.Offset);
+ first2 = false;
+ }
+ first = false;
+ }
+ sb.Append("}");
+ }
+
+ if (StoreTo != null && StoreTo.Count > 0) {
+ sb.Append(" StoreTo={");
+ bool first = true;
+ foreach (ILVariable stackVar in StoreTo) {
+ if (!first) sb.Append(",");
+ sb.Append(stackVar.Name);
+ first = false;
+ }
+ sb.Append("}");
+ }
+
+ if (VariablesBefore != null) {
+ sb.Append(" VarsBefore={");
+ bool first = true;
+ foreach (VariableSlot varSlot in VariablesBefore) {
+ if (!first) sb.Append(",");
+ if (varSlot.UnknownDefinition) {
+ sb.Append("?");
+ } else {
+ bool first2 = true;
+ foreach (ByteCode storedBy in varSlot.Definitions) {
+ if (!first2) sb.Append("|");
+ sb.AppendFormat("IL_{0:X2}", storedBy.Offset);
+ first2 = false;
+ }
+ }
+ first = false;
+ }
+ sb.Append("}");
+ }
+
+ return sb.ToString();
+ }
+ }
+
+ MethodDefinition methodDef;
+ bool optimize;
+
+ // Virtual instructions to load exception on stack
+ Dictionary<ExceptionHandler, ByteCode> ldexceptions = new Dictionary<ExceptionHandler, ByteCode>();
+
+ DecompilerContext context;
+
+ public List<ILNode> Build(MethodDefinition methodDef, bool optimize, DecompilerContext context)
+ {
+ this.methodDef = methodDef;
+ this.optimize = optimize;
+ this.context = context;
+
+ if (methodDef.Body.Instructions.Count == 0) return new List<ILNode>();
+
+ List<ByteCode> body = StackAnalysis(methodDef);
+
+ List<ILNode> ast = ConvertToAst(body, new HashSet<ExceptionHandler>(methodDef.Body.ExceptionHandlers));
+
+ return ast;
+ }
+
+ static int offsetIdx;
+ List<ByteCode> StackAnalysis(MethodDefinition methodDef)
+ {
+ Dictionary<Instruction, ByteCode> instrToByteCode = new Dictionary<Instruction, ByteCode>();
+
+ // Create temporary structure for the stack analysis
+ List<ByteCode> body = new List<ByteCode>(methodDef.Body.Instructions.Count);
+ List<Instruction> prefixes = null;
+ foreach(Instruction inst in methodDef.Body.Instructions) {
+ if (inst.OpCode.OpCodeType == OpCodeType.Prefix) {
+ if (prefixes == null)
+ prefixes = new List<Instruction>(1);
+ prefixes.Add(inst);
+ continue;
+ }
+ ILCode code = (ILCode)inst.OpCode.Code;
+ object operand = inst.Operand;
+ ILCodeUtil.ExpandMacro(ref code, ref operand, methodDef.Body);
+ ByteCode byteCode = new ByteCode() {
+ Offset = inst.Offset,
+ EndOffset = inst.Next != null ? inst.Next.Offset : methodDef.Body.CodeSize,
+ Code = code,
+ Operand = operand,
+ PopCount = inst.GetPopDelta(methodDef),
+ PushCount = inst.GetPushDelta()
+ };
+ if (prefixes != null) {
+ instrToByteCode[prefixes[0]] = byteCode;
+ byteCode.Offset = prefixes[0].Offset;
+ byteCode.Prefixes = prefixes.ToArray();
+ prefixes = null;
+ } else {
+ instrToByteCode[inst] = byteCode;
+ }
+ body.Add(byteCode);
+ }
+ for (int i = 0; i < body.Count - 1; i++) {
+ body[i].Next = body[i + 1];
+ }
+
+ Stack<ByteCode> agenda = new Stack<ByteCode>();
+
+ int varCount = methodDef.Body.Variables.Count;
+
+ var exceptionHandlerStarts = new HashSet<ByteCode>(methodDef.Body.ExceptionHandlers.Select(eh => instrToByteCode[eh.HandlerStart]));
+
+ // Add known states
+ if(methodDef.Body.HasExceptionHandlers) {
+ foreach(ExceptionHandler ex in methodDef.Body.ExceptionHandlers) {
+ ByteCode handlerStart = instrToByteCode[ex.HandlerStart];
+ handlerStart.StackBefore = new StackSlot[0];
+ handlerStart.VariablesBefore = VariableSlot.MakeUknownState(varCount);
+ if (ex.HandlerType == ExceptionHandlerType.Catch || ex.HandlerType == ExceptionHandlerType.Filter) {
+ // Catch and Filter handlers start with the exeption on the stack
+ ByteCode ldexception = new ByteCode() {
+ Code = ILCode.Ldexception,
+ Operand = ex.CatchType,
+ PopCount = 0,
+ PushCount = 1
+ };
+ ldexceptions[ex] = ldexception;
+ handlerStart.StackBefore = new StackSlot[] { new StackSlot(new [] { ldexception }, null) };
+ }
+ agenda.Push(handlerStart);
+
+ if (ex.HandlerType == ExceptionHandlerType.Filter)
+ {
+ ByteCode filterStart = instrToByteCode[ex.FilterStart];
+ ByteCode ldexception = new ByteCode() {
+ Code = ILCode.Ldexception,
+ Operand = ex.CatchType,
+ PopCount = 0,
+ PushCount = 1
+ };
+ // TODO: ldexceptions[ex] = ldexception;
+ filterStart.StackBefore = new StackSlot[] { new StackSlot(new [] { ldexception }, null) };
+ filterStart.VariablesBefore = VariableSlot.MakeUknownState(varCount);
+ agenda.Push(filterStart);
+ }
+ }
+ }
+
+ body[0].StackBefore = new StackSlot[0];
+ body[0].VariablesBefore = VariableSlot.MakeUknownState(varCount);
+ agenda.Push(body[0]);
+
+ // Process agenda
+ while(agenda.Count > 0) {
+ ByteCode byteCode = agenda.Pop();
+
+ // Calculate new stack
+ StackSlot[] newStack = StackSlot.ModifyStack(byteCode.StackBefore, byteCode.PopCount ?? byteCode.StackBefore.Length, byteCode.PushCount, byteCode);
+
+ // Calculate new variable state
+ VariableSlot[] newVariableState = VariableSlot.CloneVariableState(byteCode.VariablesBefore);
+ if (byteCode.IsVariableDefinition) {
+ newVariableState[((VariableReference)byteCode.Operand).Index] = new VariableSlot(new [] { byteCode }, false);
+ }
+
+ // After the leave, finally block might have touched the variables
+ if (byteCode.Code == ILCode.Leave) {
+ newVariableState = VariableSlot.MakeUknownState(varCount);
+ }
+
+ // Find all successors
+ List<ByteCode> branchTargets = new List<ByteCode>();
+ if (!byteCode.Code.IsUnconditionalControlFlow()) {
+ if (exceptionHandlerStarts.Contains(byteCode.Next)) {
+ // Do not fall though down to exception handler
+ // It is invalid IL as per ECMA-335 12.4.2.8.1, but some obfuscators produce it
+ } else {
+ branchTargets.Add(byteCode.Next);
+ }
+ }
+ if (byteCode.Operand is Instruction[]) {
+ foreach(Instruction inst in (Instruction[])byteCode.Operand) {
+ ByteCode target = instrToByteCode[inst];
+ branchTargets.Add(target);
+ // The target of a branch must have label
+ if (target.Label == null) {
+ target.Label = new ILLabel() { Name = target.Name };
+ }
+ }
+ } else if (byteCode.Operand is Instruction) {
+ ByteCode target = instrToByteCode[(Instruction)byteCode.Operand];
+ branchTargets.Add(target);
+ // The target of a branch must have label
+ if (target.Label == null) {
+ target.Label = new ILLabel() { Name = target.Name };
+ }
+ }
+
+ // Apply the state to successors
+ foreach (ByteCode branchTarget in branchTargets) {
+ if (branchTarget.StackBefore == null && branchTarget.VariablesBefore == null) {
+ if (branchTargets.Count == 1) {
+ branchTarget.StackBefore = newStack;
+ branchTarget.VariablesBefore = newVariableState;
+ } else {
+ // Do not share data for several bytecodes
+ branchTarget.StackBefore = StackSlot.ModifyStack(newStack, 0, 0, null);
+ branchTarget.VariablesBefore = VariableSlot.CloneVariableState(newVariableState);
+ }
+ agenda.Push(branchTarget);
+ } else {
+ if (branchTarget.StackBefore.Length != newStack.Length) {
+ throw new Exception("Inconsistent stack size at " + byteCode.Name);
+ }
+
+ // Be careful not to change our new data - it might be reused for several branch targets.
+ // In general, be careful that two bytecodes never share data structures.
+
+ bool modified = false;
+
+ // Merge stacks - modify the target
+ for (int i = 0; i < newStack.Length; i++) {
+ ByteCode[] oldDefs = branchTarget.StackBefore[i].Definitions;
+ ByteCode[] newDefs = oldDefs.Union(newStack[i].Definitions);
+ if (newDefs.Length > oldDefs.Length) {
+ branchTarget.StackBefore[i] = new StackSlot(newDefs, null);
+ modified = true;
+ }
+ }
+
+ // Merge variables - modify the target
+ for (int i = 0; i < newVariableState.Length; i++) {
+ VariableSlot oldSlot = branchTarget.VariablesBefore[i];
+ VariableSlot newSlot = newVariableState[i];
+ if (!oldSlot.UnknownDefinition) {
+ if (newSlot.UnknownDefinition) {
+ branchTarget.VariablesBefore[i] = newSlot;
+ modified = true;
+ } else {
+ ByteCode[] oldDefs = oldSlot.Definitions;
+ ByteCode[] newDefs = oldDefs.Union(newSlot.Definitions);
+ if (newDefs.Length > oldDefs.Length) {
+ branchTarget.VariablesBefore[i] = new VariableSlot(newDefs, false);
+ modified = true;
+ }
+ }
+ }
+ }
+
+ if (modified) {
+ agenda.Push(branchTarget);
+ }
+ }
+ }
+ }
+
+ // Occasionally the compilers or obfuscators generate unreachable code (which might be intentionally invalid)
+ // I believe it is safe to just remove it
+ body.RemoveAll(b => b.StackBefore == null);
+
+ // Generate temporary variables to replace stack
+ foreach(ByteCode byteCode in body) {
+ int argIdx = 0;
+ int popCount = byteCode.PopCount ?? byteCode.StackBefore.Length;
+ for (int i = byteCode.StackBefore.Length - popCount; i < byteCode.StackBefore.Length; i++) {
+ var offset = byteCode.Offset != 0 ? byteCode.Offset : offsetIdx++;
+ ILVariable tmpVar = new ILVariable() { Name = string.Format("arg_{0:X2}_{1}", offset, argIdx), IsGenerated = true };
+ byteCode.StackBefore[i] = new StackSlot(byteCode.StackBefore[i].Definitions, tmpVar);
+ foreach(ByteCode pushedBy in byteCode.StackBefore[i].Definitions) {
+ if (pushedBy.StoreTo == null) {
+ pushedBy.StoreTo = new List<ILVariable>(1);
+ }
+ pushedBy.StoreTo.Add(tmpVar);
+ }
+ argIdx++;
+ }
+ }
+
+ // Try to use single temporary variable insted of several if possilbe (especially useful for dup)
+ // This has to be done after all temporary variables are assigned so we know about all loads
+ foreach(ByteCode byteCode in body) {
+ if (byteCode.StoreTo != null && byteCode.StoreTo.Count > 1) {
+ var locVars = byteCode.StoreTo;
+ // For each of the variables, find the location where it is loaded - there should be preciesly one
+ var loadedBy = locVars.Select(locVar => body.SelectMany(bc => bc.StackBefore).Single(s => s.LoadFrom == locVar)).ToList();
+ // We now know that all the variables have a single load,
+ // Let's make sure that they have also a single store - us
+ if (loadedBy.All(slot => slot.Definitions.Length == 1 && slot.Definitions[0] == byteCode)) {
+ // Great - we can reduce everything into single variable
+ var offset = byteCode.Offset != 0 ? byteCode.Offset : offsetIdx++;
+ ILVariable tmpVar = new ILVariable() { Name = string.Format("expr_{0:X2}", offset), IsGenerated = true };
+ byteCode.StoreTo = new List<ILVariable>() { tmpVar };
+ foreach(ByteCode bc in body) {
+ for (int i = 0; i < bc.StackBefore.Length; i++) {
+ // Is it one of the variable to be merged?
+ if (locVars.Contains(bc.StackBefore[i].LoadFrom)) {
+ // Replace with the new temp variable
+ bc.StackBefore[i] = new StackSlot(bc.StackBefore[i].Definitions, tmpVar);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Split and convert the normal local variables
+ ConvertLocalVariables(body);
+
+ // Convert branch targets to labels
+ foreach(ByteCode byteCode in body) {
+ if (byteCode.Operand is Instruction[]) {
+ List<ILLabel> newOperand = new List<ILLabel>();
+ foreach(Instruction target in (Instruction[])byteCode.Operand) {
+ newOperand.Add(instrToByteCode[target].Label);
+ }
+ byteCode.Operand = newOperand.ToArray();
+ } else if (byteCode.Operand is Instruction) {
+ byteCode.Operand = instrToByteCode[(Instruction)byteCode.Operand].Label;
+ }
+ }
+
+ // Convert parameters to ILVariables
+ ConvertParameters(body);
+
+ return body;
+ }
+
+ static bool IsDeterministicLdloca(ByteCode b)
+ {
+ var v = b.Operand;
+ b = b.Next;
+ if (b.Code == ILCode.Initobj) return true;
+
+ // instance method calls on value types use the variable ref deterministically
+ int stack = 1;
+ while (true) {
+ if (b.PopCount == null) return false;
+ stack -= b.PopCount.GetValueOrDefault();
+ if (stack == 0) break;
+ if (stack < 0) return false;
+ if (b.Code.IsConditionalControlFlow() || b.Code.IsUnconditionalControlFlow()) return false;
+ switch (b.Code) {
+ case ILCode.Ldloc:
+ case ILCode.Ldloca:
+ case ILCode.Stloc:
+ if (b.Operand == v) return false;
+ break;
+ }
+ stack += b.PushCount;
+ b = b.Next;
+ if (b == null) return false;
+ }
+ if (b.Code == ILCode.Ldfld || b.Code == ILCode.Stfld)
+ return true;
+ return (b.Code == ILCode.Call || b.Code == ILCode.Callvirt) && ((MethodReference)b.Operand).HasThis;
+ }
+
+ sealed class VariableInfo
+ {
+ public ILVariable Variable;
+ public List<ByteCode> Defs;
+ public List<ByteCode> Uses;
+ }
+
+ /// <summary>
+ /// If possible, separates local variables into several independent variables.
+ /// It should undo any compilers merging.
+ /// </summary>
+ void ConvertLocalVariables(List<ByteCode> body)
+ {
+ foreach(VariableDefinition varDef in methodDef.Body.Variables) {
+
+ // Find all definitions and uses of this variable
+ var defs = body.Where(b => b.Operand == varDef && b.IsVariableDefinition).ToList();
+ var uses = body.Where(b => b.Operand == varDef && !b.IsVariableDefinition).ToList();
+
+ List<VariableInfo> newVars;
+
+ // If the variable is pinned, use single variable.
+ // If any of the uses is from unknown definition, use single variable
+ // If any of the uses is ldloca with a nondeterministic usage pattern, use single variable
+ if (!optimize || varDef.IsPinned || uses.Any(b => b.VariablesBefore[varDef.Index].UnknownDefinition || (b.Code == ILCode.Ldloca && !IsDeterministicLdloca(b)))) {
+ newVars = new List<VariableInfo>(1) { new VariableInfo() {
+ Variable = new ILVariable() {
+ Name = string.IsNullOrEmpty(varDef.Name) ? "var_" + varDef.Index : varDef.Name,
+ Type = varDef.IsPinned ? ((PinnedType)varDef.VariableType).ElementType : varDef.VariableType,
+ OriginalVariable = varDef
+ },
+ Defs = defs,
+ Uses = uses
+ }};
+ } else {
+ // Create a new variable for each definition
+ newVars = defs.Select(def => new VariableInfo() {
+ Variable = new ILVariable() {
+ Name = (string.IsNullOrEmpty(varDef.Name) ? "var_" + varDef.Index : varDef.Name) + "_" + def.Offset.ToString("X2"),
+ Type = varDef.VariableType,
+ OriginalVariable = varDef
+ },
+ Defs = new List<ByteCode>() { def },
+ Uses = new List<ByteCode>()
+ }).ToList();
+
+ // VB.NET uses the 'init' to allow use of uninitialized variables.
+ // We do not really care about them too much - if the original variable
+ // was uninitialized at that point it means that no store was called and
+ // thus all our new variables must be uninitialized as well.
+ // So it does not matter which one we load.
+
+ // TODO: We should add explicit initialization so that C# code compiles.
+ // Remember to handle cases where one path inits the variable, but other does not.
+
+ // Add loads to the data structure; merge variables if necessary
+ foreach(ByteCode use in uses) {
+ ByteCode[] useDefs = use.VariablesBefore[varDef.Index].Definitions;
+ if (useDefs.Length == 1) {
+ VariableInfo newVar = newVars.Single(v => v.Defs.Contains(useDefs[0]));
+ newVar.Uses.Add(use);
+ } else {
+ List<VariableInfo> mergeVars = newVars.Where(v => v.Defs.Intersect(useDefs).Any()).ToList();
+ VariableInfo mergedVar = new VariableInfo() {
+ Variable = mergeVars[0].Variable,
+ Defs = mergeVars.SelectMany(v => v.Defs).ToList(),
+ Uses = mergeVars.SelectMany(v => v.Uses).ToList()
+ };
+ mergedVar.Uses.Add(use);
+ newVars = newVars.Except(mergeVars).ToList();
+ newVars.Add(mergedVar);
+ }
+ }
+ }
+
+ // Set bytecode operands
+ foreach(VariableInfo newVar in newVars) {
+ foreach(ByteCode def in newVar.Defs) {
+ def.Operand = newVar.Variable;
+ }
+ foreach(ByteCode use in newVar.Uses) {
+ use.Operand = newVar.Variable;
+ }
+ }
+ }
+ }
+
+ public List<ILVariable> Parameters = new List<ILVariable>();
+
+ void ConvertParameters(List<ByteCode> body)
+ {
+ ILVariable thisParameter = null;
+ if (methodDef.HasThis) {
+ TypeReference type = methodDef.DeclaringType;
+ thisParameter = new ILVariable();
+ thisParameter.Type = type.IsValueType ? new ByReferenceType(type) : type;
+ thisParameter.Name = "this";
+ thisParameter.OriginalParameter = methodDef.Body.ThisParameter;
+ }
+ foreach (ParameterDefinition p in methodDef.Parameters) {
+ Parameters.Add(new ILVariable { Type = p.ParameterType, Name = p.Name, OriginalParameter = p });
+ }
+ if (Parameters.Count > 0 && (methodDef.IsSetter || methodDef.IsAddOn || methodDef.IsRemoveOn)) {
+ // last parameter must be 'value', so rename it
+ Parameters.Last().Name = "value";
+ }
+ foreach (ByteCode byteCode in body) {
+ ParameterDefinition p;
+ switch (byteCode.Code) {
+ case ILCode.__Ldarg:
+ p = (ParameterDefinition)byteCode.Operand;
+ byteCode.Code = ILCode.Ldloc;
+ byteCode.Operand = p.Index < 0 ? thisParameter : Parameters[p.Index];
+ break;
+ case ILCode.__Starg:
+ p = (ParameterDefinition)byteCode.Operand;
+ byteCode.Code = ILCode.Stloc;
+ byteCode.Operand = p.Index < 0 ? thisParameter : Parameters[p.Index];
+ break;
+ case ILCode.__Ldarga:
+ p = (ParameterDefinition)byteCode.Operand;
+ byteCode.Code = ILCode.Ldloca;
+ byteCode.Operand = p.Index < 0 ? thisParameter : Parameters[p.Index];
+ break;
+ }
+ }
+ if (thisParameter != null)
+ Parameters.Add(thisParameter);
+ }
+
+ List<ILNode> ConvertToAst(List<ByteCode> body, HashSet<ExceptionHandler> ehs)
+ {
+ List<ILNode> ast = new List<ILNode>();
+
+ while (ehs.Any()) {
+ ILTryCatchBlock tryCatchBlock = new ILTryCatchBlock();
+
+ // Find the first and widest scope
+ int tryStart = ehs.Min(eh => eh.TryStart.Offset);
+ int tryEnd = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset);
+ var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).ToList();
+
+ // Remember that any part of the body migt have been removed due to unreachability
+
+ // Cut all instructions up to the try block
+ {
+ int tryStartIdx = 0;
+ while (tryStartIdx < body.Count && body[tryStartIdx].Offset < tryStart) tryStartIdx++;
+ ast.AddRange(ConvertToAst(body.CutRange(0, tryStartIdx)));
+ }
+
+ // Cut the try block
+ {
+ HashSet<ExceptionHandler> nestedEHs = new HashSet<ExceptionHandler>(ehs.Where(eh => (tryStart <= eh.TryStart.Offset && eh.TryEnd.Offset < tryEnd) || (tryStart < eh.TryStart.Offset && eh.TryEnd.Offset <= tryEnd)));
+ ehs.ExceptWith(nestedEHs);
+ int tryEndIdx = 0;
+ while (tryEndIdx < body.Count && body[tryEndIdx].Offset < tryEnd) tryEndIdx++;
+ tryCatchBlock.TryBlock = new ILBlock(ConvertToAst(body.CutRange(0, tryEndIdx), nestedEHs));
+ }
+
+ // Cut all handlers
+ tryCatchBlock.CatchBlocks = new List<ILTryCatchBlock.CatchBlock>();
+ foreach(ExceptionHandler eh in handlers) {
+ int handlerEndOffset = eh.HandlerEnd == null ? methodDef.Body.CodeSize : eh.HandlerEnd.Offset;
+ int startIdx = 0;
+ while (startIdx < body.Count && body[startIdx].Offset < eh.HandlerStart.Offset) startIdx++;
+ int endIdx = 0;
+ while (endIdx < body.Count && body[endIdx].Offset < handlerEndOffset) endIdx++;
+ HashSet<ExceptionHandler> nestedEHs = new HashSet<ExceptionHandler>(ehs.Where(e => (eh.HandlerStart.Offset <= e.TryStart.Offset && e.TryEnd.Offset < handlerEndOffset) || (eh.HandlerStart.Offset < e.TryStart.Offset && e.TryEnd.Offset <= handlerEndOffset)));
+ ehs.ExceptWith(nestedEHs);
+ List<ILNode> handlerAst = ConvertToAst(body.CutRange(startIdx, endIdx - startIdx), nestedEHs);
+ if (eh.HandlerType == ExceptionHandlerType.Catch) {
+ ILTryCatchBlock.CatchBlock catchBlock = new ILTryCatchBlock.CatchBlock() {
+ ExceptionType = eh.CatchType,
+ Body = handlerAst
+ };
+ // Handle the automatically pushed exception on the stack
+ ByteCode ldexception = ldexceptions[eh];
+ if (ldexception.StoreTo == null || ldexception.StoreTo.Count == 0) {
+ // Exception is not used
+ catchBlock.ExceptionVariable = null;
+ } else if (ldexception.StoreTo.Count == 1) {
+ ILExpression first = catchBlock.Body[0] as ILExpression;
+ if (first != null &&
+ first.Code == ILCode.Pop &&
+ first.Arguments[0].Code == ILCode.Ldloc &&
+ first.Arguments[0].Operand == ldexception.StoreTo[0])
+ {
+ // The exception is just poped - optimize it all away;
+ if (context.Settings.AlwaysGenerateExceptionVariableForCatchBlocks)
+ catchBlock.ExceptionVariable = new ILVariable() { Name = "ex_" + eh.HandlerStart.Offset.ToString("X2"), IsGenerated = true };
+ else
+ catchBlock.ExceptionVariable = null;
+ catchBlock.Body.RemoveAt(0);
+ } else {
+ catchBlock.ExceptionVariable = ldexception.StoreTo[0];
+ }
+ } else {
+ ILVariable exTemp = new ILVariable() { Name = "ex_" + eh.HandlerStart.Offset.ToString("X2"), IsGenerated = true };
+ catchBlock.ExceptionVariable = exTemp;
+ foreach(ILVariable storeTo in ldexception.StoreTo) {
+ catchBlock.Body.Insert(0, new ILExpression(ILCode.Stloc, storeTo, new ILExpression(ILCode.Ldloc, exTemp)));
+ }
+ }
+ tryCatchBlock.CatchBlocks.Add(catchBlock);
+ } else if (eh.HandlerType == ExceptionHandlerType.Finally) {
+ tryCatchBlock.FinallyBlock = new ILBlock(handlerAst);
+ } else if (eh.HandlerType == ExceptionHandlerType.Fault) {
+ tryCatchBlock.FaultBlock = new ILBlock(handlerAst);
+ } else {
+ // TODO: ExceptionHandlerType.Filter
+ }
+ }
+
+ ehs.ExceptWith(handlers);
+
+ ast.Add(tryCatchBlock);
+ }
+
+ // Add whatever is left
+ ast.AddRange(ConvertToAst(body));
+
+ return ast;
+ }
+
+ List<ILNode> ConvertToAst(List<ByteCode> body)
+ {
+ List<ILNode> ast = new List<ILNode>();
+
+ // Convert stack-based IL code to ILAst tree
+ foreach(ByteCode byteCode in body) {
+ ILRange ilRange = new ILRange(byteCode.Offset, byteCode.EndOffset);
+
+ if (byteCode.StackBefore == null) {
+ // Unreachable code
+ continue;
+ }
+
+ ILExpression expr = new ILExpression(byteCode.Code, byteCode.Operand);
+ expr.ILRanges.Add(ilRange);
+ if (byteCode.Prefixes != null && byteCode.Prefixes.Length > 0) {
+ ILExpressionPrefix[] prefixes = new ILExpressionPrefix[byteCode.Prefixes.Length];
+ for (int i = 0; i < prefixes.Length; i++) {
+ prefixes[i] = new ILExpressionPrefix((ILCode)byteCode.Prefixes[i].OpCode.Code, byteCode.Prefixes[i].Operand);
+ }
+ expr.Prefixes = prefixes;
+ }
+
+ // Label for this instruction
+ if (byteCode.Label != null) {
+ ast.Add(byteCode.Label);
+ }
+
+ // Reference arguments using temporary variables
+ int popCount = byteCode.PopCount ?? byteCode.StackBefore.Length;
+ for (int i = byteCode.StackBefore.Length - popCount; i < byteCode.StackBefore.Length; i++) {
+ StackSlot slot = byteCode.StackBefore[i];
+ expr.Arguments.Add(new ILExpression(ILCode.Ldloc, slot.LoadFrom));
+ }
+
+ // Store the result to temporary variable(s) if needed
+ if (byteCode.StoreTo == null || byteCode.StoreTo.Count == 0) {
+ ast.Add(expr);
+ } else if (byteCode.StoreTo.Count == 1) {
+ ast.Add(new ILExpression(ILCode.Stloc, byteCode.StoreTo[0], expr));
+ } else {
+ var offset = byteCode.Offset != 0 ? byteCode.Offset : offsetIdx++;
+ ILVariable tmpVar = new ILVariable() { Name = "expr_" + offset.ToString("X2"), IsGenerated = true };
+ ast.Add(new ILExpression(ILCode.Stloc, tmpVar, expr));
+ foreach(ILVariable storeTo in byteCode.StoreTo.AsEnumerable().Reverse()) {
+ ast.Add(new ILExpression(ILCode.Stloc, storeTo, new ILExpression(ILCode.Ldloc, tmpVar)));
+ }
+ }
+ }
+
+ return ast;
+ }
+ }
+
+ public static class ILAstBuilderExtensionMethods
+ {
+ public static List<T> CutRange<T>(this List<T> list, int start, int count)
+ {
+ List<T> ret = new List<T>(count);
+ for (int i = 0; i < count; i++) {
+ ret.Add(list[start + i]);
+ }
+ list.RemoveRange(start, count);
+ return ret;
+ }
+
+ public static T[] Union<T>(this T[] a, T b)
+ {
+ if (a.Length == 0)
+ return new[] { b };
+ if (Array.IndexOf(a, b) >= 0)
+ return a;
+ var res = new T[a.Length + 1];
+ Array.Copy(a, 0, res, 0, a.Length);
+ res[res.Length - 1] = b;
+ return res;
+ }
+
+ public static T[] Union<T>(this T[] a, T[] b)
+ {
+ if (a == b)
+ return a;
+ if (a.Length == 0)
+ return b;
+ if (b.Length == 0)
+ return a;
+ if (a.Length == 1) {
+ if (b.Length == 1)
+ return a[0].Equals(b[0]) ? a : new[] { a[0], b[0] };
+ return b.Union(a[0]);
+ }
+ if (b.Length == 1)
+ return a.Union(b[0]);
+ return Enumerable.Union(a, b).ToArray();
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
new file mode 100644
index 00000000..876718bc
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
@@ -0,0 +1,988 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using ICSharpCode.Decompiler.FlowAnalysis;
+using ICSharpCode.NRefactory.Utils;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Mono.CSharp;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ public enum ILAstOptimizationStep
+ {
+ RemoveRedundantCode,
+ ReduceBranchInstructionSet,
+ InlineVariables,
+ CopyPropagation,
+ YieldReturn,
+ AsyncAwait,
+ PropertyAccessInstructions,
+ SplitToMovableBlocks,
+ TypeInference,
+ HandlePointerArithmetic,
+ SimplifyShortCircuit,
+ SimplifyTernaryOperator,
+ SimplifyNullCoalescing,
+ JoinBasicBlocks,
+ SimplifyLogicNot,
+ SimplifyShiftOperators,
+ TypeConversionSimplifications,
+ SimplifyLdObjAndStObj,
+ SimplifyCustomShortCircuit,
+ SimplifyLiftedOperators,
+ TransformArrayInitializers,
+ TransformMultidimensionalArrayInitializers,
+ TransformObjectInitializers,
+ MakeAssignmentExpression,
+ IntroducePostIncrement,
+ InlineExpressionTreeParameterDeclarations,
+ InlineVariables2,
+ FindLoops,
+ FindConditions,
+ FlattenNestedMovableBlocks,
+ RemoveEndFinally,
+ RemoveRedundantCode2,
+ GotoRemoval,
+ DuplicateReturns,
+ GotoRemoval2,
+ ReduceIfNesting,
+ InlineVariables3,
+ CachedDelegateInitialization,
+ IntroduceFixedStatements,
+ RecombineVariables,
+ TypeInference2,
+ RemoveRedundantCode3,
+ None
+ }
+
+ public partial class ILAstOptimizer
+ {
+ int nextLabelIndex = 0;
+
+ DecompilerContext context;
+ TypeSystem typeSystem;
+ ILBlock method;
+
+ public void Optimize(DecompilerContext context, ILBlock method, ILAstOptimizationStep abortBeforeStep = ILAstOptimizationStep.None)
+ {
+ this.context = context;
+ typeSystem = context.CurrentMethod.Module.TypeSystem;
+ this.method = method;
+
+ if (abortBeforeStep == ILAstOptimizationStep.RemoveRedundantCode) return;
+ RemoveRedundantCode(method);
+
+ if (abortBeforeStep == ILAstOptimizationStep.ReduceBranchInstructionSet) return;
+ foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
+ ReduceBranchInstructionSet(block);
+ }
+ // ReduceBranchInstructionSet runs before inlining because the non-aggressive inlining heuristic
+ // looks at which type of instruction consumes the inlined variable.
+
+ if (abortBeforeStep == ILAstOptimizationStep.InlineVariables) return;
+ // Works better after simple goto removal because of the following debug pattern: stloc X; br Next; Next:; ldloc X
+ ILInlining inlining1 = new ILInlining(method);
+ inlining1.InlineAllVariables();
+
+ if (abortBeforeStep == ILAstOptimizationStep.CopyPropagation) return;
+ inlining1.CopyPropagation();
+
+ if (abortBeforeStep == ILAstOptimizationStep.YieldReturn) return;
+ YieldReturnDecompiler.Run(context, method);
+ AsyncDecompiler.RunStep1(context, method);
+
+ if (abortBeforeStep == ILAstOptimizationStep.AsyncAwait) return;
+ AsyncDecompiler.RunStep2(context, method);
+
+ if (abortBeforeStep == ILAstOptimizationStep.PropertyAccessInstructions) return;
+ IntroducePropertyAccessInstructions(method);
+
+ if (abortBeforeStep == ILAstOptimizationStep.SplitToMovableBlocks) return;
+ foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
+ SplitToBasicBlocks(block);
+ }
+
+ if (abortBeforeStep == ILAstOptimizationStep.TypeInference) return;
+ // Types are needed for the ternary operator optimization
+ TypeAnalysis.Run(context, method);
+
+ if (abortBeforeStep == ILAstOptimizationStep.HandlePointerArithmetic) return;
+ HandlePointerArithmetic(method);
+
+ foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
+ bool modified;
+ do {
+ modified = false;
+
+ if (abortBeforeStep == ILAstOptimizationStep.SimplifyShortCircuit) return;
+ modified |= block.RunOptimization(new SimpleControlFlow(context, method).SimplifyShortCircuit);
+
+ if (abortBeforeStep == ILAstOptimizationStep.SimplifyTernaryOperator) return;
+ modified |= block.RunOptimization(new SimpleControlFlow(context, method).SimplifyTernaryOperator);
+
+ if (abortBeforeStep == ILAstOptimizationStep.SimplifyNullCoalescing) return;
+ modified |= block.RunOptimization(new SimpleControlFlow(context, method).SimplifyNullCoalescing);
+
+ if (abortBeforeStep == ILAstOptimizationStep.JoinBasicBlocks) return;
+ modified |= block.RunOptimization(new SimpleControlFlow(context, method).JoinBasicBlocks);
+
+ if (abortBeforeStep == ILAstOptimizationStep.SimplifyLogicNot) return;
+ modified |= block.RunOptimization(SimplifyLogicNot);
+
+ if (abortBeforeStep == ILAstOptimizationStep.SimplifyShiftOperators) return;
+ modified |= block.RunOptimization(SimplifyShiftOperators);
+
+ if (abortBeforeStep == ILAstOptimizationStep.TypeConversionSimplifications) return;
+ modified |= block.RunOptimization(TypeConversionSimplifications);
+
+ if (abortBeforeStep == ILAstOptimizationStep.SimplifyLdObjAndStObj) return;
+ modified |= block.RunOptimization(SimplifyLdObjAndStObj);
+
+ if (abortBeforeStep == ILAstOptimizationStep.SimplifyCustomShortCircuit) return;
+ modified |= block.RunOptimization(new SimpleControlFlow(context, method).SimplifyCustomShortCircuit);
+
+ if (abortBeforeStep == ILAstOptimizationStep.SimplifyLiftedOperators) return;
+ modified |= block.RunOptimization(SimplifyLiftedOperators);
+
+ if (abortBeforeStep == ILAstOptimizationStep.TransformArrayInitializers) return;
+ modified |= block.RunOptimization(TransformArrayInitializers);
+
+ if (abortBeforeStep == ILAstOptimizationStep.TransformMultidimensionalArrayInitializers) return;
+ modified |= block.RunOptimization(TransformMultidimensionalArrayInitializers);
+
+ if (abortBeforeStep == ILAstOptimizationStep.TransformObjectInitializers) return;
+ modified |= block.RunOptimization(TransformObjectInitializers);
+
+ if (abortBeforeStep == ILAstOptimizationStep.MakeAssignmentExpression) return;
+ if (context.Settings.MakeAssignmentExpressions) {
+ modified |= block.RunOptimization(MakeAssignmentExpression);
+ }
+ modified |= block.RunOptimization(MakeCompoundAssignments);
+
+ if (abortBeforeStep == ILAstOptimizationStep.IntroducePostIncrement) return;
+ if (context.Settings.IntroduceIncrementAndDecrement) {
+ modified |= block.RunOptimization(IntroducePostIncrement);
+ }
+
+ if (abortBeforeStep == ILAstOptimizationStep.InlineExpressionTreeParameterDeclarations) return;
+ if (context.Settings.ExpressionTrees) {
+ modified |= block.RunOptimization(InlineExpressionTreeParameterDeclarations);
+ }
+
+ if (abortBeforeStep == ILAstOptimizationStep.InlineVariables2) return;
+ modified |= new ILInlining(method).InlineAllInBlock(block);
+ new ILInlining(method).CopyPropagation();
+
+ } while(modified);
+ }
+
+ if (abortBeforeStep == ILAstOptimizationStep.FindLoops) return;
+ foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
+ new LoopsAndConditions(context).FindLoops(block);
+ }
+
+ if (abortBeforeStep == ILAstOptimizationStep.FindConditions) return;
+ foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
+ new LoopsAndConditions(context).FindConditions(block);
+ }
+
+ if (abortBeforeStep == ILAstOptimizationStep.FlattenNestedMovableBlocks) return;
+ FlattenBasicBlocks(method);
+
+ if (abortBeforeStep == ILAstOptimizationStep.RemoveEndFinally) return;
+ RemoveEndFinally(method);
+
+ if (abortBeforeStep == ILAstOptimizationStep.RemoveRedundantCode2) return;
+ RemoveRedundantCode(method);
+
+ if (abortBeforeStep == ILAstOptimizationStep.GotoRemoval) return;
+ new GotoRemoval().RemoveGotos(method);
+
+ if (abortBeforeStep == ILAstOptimizationStep.DuplicateReturns) return;
+ DuplicateReturnStatements(method);
+
+ if (abortBeforeStep == ILAstOptimizationStep.GotoRemoval2) return;
+ new GotoRemoval().RemoveGotos(method);
+
+ if (abortBeforeStep == ILAstOptimizationStep.ReduceIfNesting) return;
+ ReduceIfNesting(method);
+
+ if (abortBeforeStep == ILAstOptimizationStep.InlineVariables3) return;
+ // The 2nd inlining pass is necessary because DuplicateReturns and the introduction of ternary operators
+ // open up additional inlining possibilities.
+ new ILInlining(method).InlineAllVariables();
+
+ if (abortBeforeStep == ILAstOptimizationStep.CachedDelegateInitialization) return;
+ if (context.Settings.AnonymousMethods) {
+ foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
+ for (int i = 0; i < block.Body.Count; i++) {
+ // TODO: Move before loops
+ CachedDelegateInitializationWithField(block, ref i);
+ CachedDelegateInitializationWithLocal(block, ref i);
+ }
+ }
+ }
+
+ if (abortBeforeStep == ILAstOptimizationStep.IntroduceFixedStatements) return;
+ // we need post-order traversal, not pre-order, for "fixed" to work correctly
+ foreach (ILBlock block in TreeTraversal.PostOrder<ILNode>(method, n => n.GetChildren()).OfType<ILBlock>()) {
+ for (int i = block.Body.Count - 1; i >= 0; i--) {
+ // TODO: Move before loops
+ if (i < block.Body.Count)
+ IntroduceFixedStatements(block.Body, i);
+ }
+ }
+
+ if (abortBeforeStep == ILAstOptimizationStep.RecombineVariables) return;
+ RecombineVariables(method);
+
+ if (abortBeforeStep == ILAstOptimizationStep.TypeInference2) return;
+ TypeAnalysis.Reset(method);
+ TypeAnalysis.Run(context, method);
+
+ if (abortBeforeStep == ILAstOptimizationStep.RemoveRedundantCode3) return;
+ GotoRemoval.RemoveRedundantCode(method);
+
+ // ReportUnassignedILRanges(method);
+ }
+
+ /// <summary>
+ /// Removes redundatant Br, Nop, Dup, Pop
+ /// Ignore arguments of 'leave'
+ /// </summary>
+ /// <param name="method"></param>
+ internal static void RemoveRedundantCode(ILBlock method)
+ {
+ Dictionary<ILLabel, int> labelRefCount = new Dictionary<ILLabel, int>();
+ foreach (ILLabel target in method.GetSelfAndChildrenRecursive<ILExpression>(e => e.IsBranch()).SelectMany(e => e.GetBranchTargets())) {
+ labelRefCount[target] = labelRefCount.GetOrDefault(target) + 1;
+ }
+
+ foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
+ List<ILNode> body = block.Body;
+ List<ILNode> newBody = new List<ILNode>(body.Count);
+ for (int i = 0; i < body.Count; i++) {
+ ILLabel target;
+ ILExpression popExpr;
+ if (body[i].Match(ILCode.Br, out target) && i+1 < body.Count && body[i+1] == target) {
+ // Ignore the branch
+ if (labelRefCount[target] == 1)
+ i++; // Ignore the label as well
+ } else if (body[i].Match(ILCode.Nop)){
+ // Ignore nop
+ } else if (body[i].Match(ILCode.Pop, out popExpr)) {
+ ILVariable v;
+ if (!popExpr.Match(ILCode.Ldloc, out v))
+ throw new Exception("Pop should have just ldloc at this stage");
+ // Best effort to move the ILRange to previous statement
+ ILVariable prevVar;
+ ILExpression prevExpr;
+ if (i - 1 >= 0 && body[i - 1].Match(ILCode.Stloc, out prevVar, out prevExpr) && prevVar == v)
+ prevExpr.ILRanges.AddRange(((ILExpression)body[i]).ILRanges);
+ // Ignore pop
+ } else {
+ ILLabel label = body[i] as ILLabel;
+ if (label != null) {
+ if (labelRefCount.GetOrDefault(label) > 0)
+ newBody.Add(label);
+ } else {
+ newBody.Add(body[i]);
+ }
+ }
+ }
+ block.Body = newBody;
+ }
+
+ // Ignore arguments of 'leave'
+ foreach (ILExpression expr in method.GetSelfAndChildrenRecursive<ILExpression>(e => e.Code == ILCode.Leave)) {
+ if (expr.Arguments.Any(arg => !arg.Match(ILCode.Ldloc)))
+ throw new Exception("Leave should have just ldloc at this stage");
+ expr.Arguments.Clear();
+ }
+
+ // 'dup' removal
+ foreach (ILExpression expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
+ for (int i = 0; i < expr.Arguments.Count; i++) {
+ ILExpression child;
+ if (expr.Arguments[i].Match(ILCode.Dup, out child)) {
+ child.ILRanges.AddRange(expr.Arguments[i].ILRanges);
+ expr.Arguments[i] = child;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Reduces the branch codes to just br and brtrue.
+ /// Moves ILRanges to the branch argument
+ /// </summary>
+ void ReduceBranchInstructionSet(ILBlock block)
+ {
+ for (int i = 0; i < block.Body.Count; i++) {
+ ILExpression expr = block.Body[i] as ILExpression;
+ if (expr != null && expr.Prefixes == null) {
+ ILCode op;
+ switch(expr.Code) {
+ case ILCode.Switch:
+ case ILCode.Brtrue:
+ expr.Arguments.Single().ILRanges.AddRange(expr.ILRanges);
+ expr.ILRanges.Clear();
+ continue;
+ case ILCode.__Brfalse: op = ILCode.LogicNot; break;
+ case ILCode.__Beq: op = ILCode.Ceq; break;
+ case ILCode.__Bne_Un: op = ILCode.Cne; break;
+ case ILCode.__Bgt: op = ILCode.Cgt; break;
+ case ILCode.__Bgt_Un: op = ILCode.Cgt_Un; break;
+ case ILCode.__Ble: op = ILCode.Cle; break;
+ case ILCode.__Ble_Un: op = ILCode.Cle_Un; break;
+ case ILCode.__Blt: op = ILCode.Clt; break;
+ case ILCode.__Blt_Un: op = ILCode.Clt_Un; break;
+ case ILCode.__Bge: op = ILCode.Cge; break;
+ case ILCode.__Bge_Un: op = ILCode.Cge_Un; break;
+ default:
+ continue;
+ }
+ var newExpr = new ILExpression(op, null, expr.Arguments);
+ block.Body[i] = new ILExpression(ILCode.Brtrue, expr.Operand, newExpr);
+ newExpr.ILRanges = expr.ILRanges;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Converts call and callvirt instructions that read/write properties into CallGetter/CallSetter instructions.
+ ///
+ /// CallGetter/CallSetter is used to allow the ILAst to represent "while ((SomeProperty = value) != null)".
+ ///
+ /// Also simplifies 'newobj(SomeDelegate, target, ldvirtftn(F, target))' to 'newobj(SomeDelegate, target, ldvirtftn(F))'
+ /// </summary>
+ void IntroducePropertyAccessInstructions(ILNode node)
+ {
+ ILExpression parentExpr = node as ILExpression;
+ if (parentExpr != null) {
+ for (int i = 0; i < parentExpr.Arguments.Count; i++) {
+ ILExpression expr = parentExpr.Arguments[i];
+ IntroducePropertyAccessInstructions(expr);
+ IntroducePropertyAccessInstructions(expr, parentExpr, i);
+ }
+ } else {
+ foreach (ILNode child in node.GetChildren()) {
+ IntroducePropertyAccessInstructions(child);
+ ILExpression expr = child as ILExpression;
+ if (expr != null) {
+ IntroducePropertyAccessInstructions(expr, null, -1);
+ }
+ }
+ }
+ }
+
+ void IntroducePropertyAccessInstructions(ILExpression expr, ILExpression parentExpr, int posInParent)
+ {
+ if (expr.Code == ILCode.Call || expr.Code == ILCode.Callvirt) {
+ MethodReference cecilMethod = (MethodReference)expr.Operand;
+ if (cecilMethod.DeclaringType is ArrayType) {
+ switch (cecilMethod.Name) {
+ case "Get":
+ expr.Code = ILCode.CallGetter;
+ break;
+ case "Set":
+ expr.Code = ILCode.CallSetter;
+ break;
+ case "Address":
+ ByReferenceType brt = cecilMethod.ReturnType as ByReferenceType;
+ if (brt != null) {
+ MethodReference getMethod = new MethodReference("Get", brt.ElementType, cecilMethod.DeclaringType);
+ foreach (var p in cecilMethod.Parameters)
+ getMethod.Parameters.Add(p);
+ getMethod.HasThis = cecilMethod.HasThis;
+ expr.Operand = getMethod;
+ }
+ expr.Code = ILCode.CallGetter;
+ if (parentExpr != null) {
+ parentExpr.Arguments[posInParent] = new ILExpression(ILCode.AddressOf, null, expr);
+ }
+ break;
+ }
+ } else {
+ MethodDefinition cecilMethodDef = cecilMethod.Resolve();
+ if (cecilMethodDef != null) {
+ if (cecilMethodDef.IsGetter)
+ expr.Code = (expr.Code == ILCode.Call) ? ILCode.CallGetter : ILCode.CallvirtGetter;
+ else if (cecilMethodDef.IsSetter)
+ expr.Code = (expr.Code == ILCode.Call) ? ILCode.CallSetter : ILCode.CallvirtSetter;
+ }
+ }
+ } else if (expr.Code == ILCode.Newobj && expr.Arguments.Count == 2) {
+ // Might be 'newobj(SomeDelegate, target, ldvirtftn(F, target))'.
+ ILVariable target;
+ if (expr.Arguments[0].Match(ILCode.Ldloc, out target)
+ && expr.Arguments[1].Code == ILCode.Ldvirtftn
+ && expr.Arguments[1].Arguments.Count == 1
+ && expr.Arguments[1].Arguments[0].MatchLdloc(target))
+ {
+ // Remove the 'target' argument from the ldvirtftn instruction.
+ // It's not needed in the translation to C#, and needs to be eliminated so that the target expression
+ // can be inlined.
+ expr.Arguments[1].Arguments.Clear();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Group input into a set of blocks that can be later arbitraliby schufled.
+ /// The method adds necessary branches to make control flow between blocks
+ /// explicit and thus order independent.
+ /// </summary>
+ void SplitToBasicBlocks(ILBlock block)
+ {
+ List<ILNode> basicBlocks = new List<ILNode>();
+
+ ILLabel entryLabel = block.Body.FirstOrDefault() as ILLabel ?? new ILLabel() { Name = "Block_" + (nextLabelIndex++) };
+ ILBasicBlock basicBlock = new ILBasicBlock();
+ basicBlocks.Add(basicBlock);
+ basicBlock.Body.Add(entryLabel);
+ block.EntryGoto = new ILExpression(ILCode.Br, entryLabel);
+
+ if (block.Body.Count > 0) {
+ if (block.Body[0] != entryLabel)
+ basicBlock.Body.Add(block.Body[0]);
+
+ for (int i = 1; i < block.Body.Count; i++) {
+ ILNode lastNode = block.Body[i - 1];
+ ILNode currNode = block.Body[i];
+
+ // Start a new basic block if necessary
+ if (currNode is ILLabel ||
+ currNode is ILTryCatchBlock || // Counts as label
+ lastNode.IsConditionalControlFlow() ||
+ lastNode.IsUnconditionalControlFlow())
+ {
+ // Try to reuse the label
+ ILLabel label = currNode as ILLabel ?? new ILLabel() { Name = "Block_" + (nextLabelIndex++).ToString() };
+
+ // Terminate the last block
+ if (!lastNode.IsUnconditionalControlFlow()) {
+ // Explicit branch from one block to other
+ basicBlock.Body.Add(new ILExpression(ILCode.Br, label));
+ }
+
+ // Start the new block
+ basicBlock = new ILBasicBlock();
+ basicBlocks.Add(basicBlock);
+ basicBlock.Body.Add(label);
+
+ // Add the node to the basic block
+ if (currNode != label)
+ basicBlock.Body.Add(currNode);
+ } else {
+ basicBlock.Body.Add(currNode);
+ }
+ }
+ }
+
+ block.Body = basicBlocks;
+ return;
+ }
+
+ void DuplicateReturnStatements(ILBlock method)
+ {
+ Dictionary<ILLabel, ILNode> nextSibling = new Dictionary<ILLabel, ILNode>();
+
+ // Build navigation data
+ foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
+ for (int i = 0; i < block.Body.Count - 1; i++) {
+ ILLabel curr = block.Body[i] as ILLabel;
+ if (curr != null) {
+ nextSibling[curr] = block.Body[i + 1];
+ }
+ }
+ }
+
+ // Duplicate returns
+ foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
+ for (int i = 0; i < block.Body.Count; i++) {
+ ILLabel targetLabel;
+ if (block.Body[i].Match(ILCode.Br, out targetLabel) || block.Body[i].Match(ILCode.Leave, out targetLabel)) {
+ // Skip extra labels
+ while(nextSibling.ContainsKey(targetLabel) && nextSibling[targetLabel] is ILLabel) {
+ targetLabel = (ILLabel)nextSibling[targetLabel];
+ }
+
+ // Inline return statement
+ ILNode target;
+ List<ILExpression> retArgs;
+ if (nextSibling.TryGetValue(targetLabel, out target)) {
+ if (target.Match(ILCode.Ret, out retArgs)) {
+ ILVariable locVar;
+ object constValue;
+ if (retArgs.Count == 0) {
+ block.Body[i] = new ILExpression(ILCode.Ret, null);
+ } else if (retArgs.Single().Match(ILCode.Ldloc, out locVar)) {
+ block.Body[i] = new ILExpression(ILCode.Ret, null, new ILExpression(ILCode.Ldloc, locVar));
+ } else if (retArgs.Single().Match(ILCode.Ldc_I4, out constValue)) {
+ block.Body[i] = new ILExpression(ILCode.Ret, null, new ILExpression(ILCode.Ldc_I4, constValue));
+ }
+ }
+ } else {
+ if (method.Body.Count > 0 && method.Body.Last() == targetLabel) {
+ // It exits the main method - so it is same as return;
+ block.Body[i] = new ILExpression(ILCode.Ret, null);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Flattens all nested basic blocks, except the the top level 'node' argument
+ /// </summary>
+ void FlattenBasicBlocks(ILNode node)
+ {
+ ILBlock block = node as ILBlock;
+ if (block != null) {
+ List<ILNode> flatBody = new List<ILNode>();
+ foreach (ILNode child in block.GetChildren()) {
+ FlattenBasicBlocks(child);
+ ILBasicBlock childAsBB = child as ILBasicBlock;
+ if (childAsBB != null) {
+ if (!(childAsBB.Body.FirstOrDefault() is ILLabel))
+ throw new Exception("Basic block has to start with a label. \n" + childAsBB.ToString());
+ if (childAsBB.Body.LastOrDefault() is ILExpression && !childAsBB.Body.LastOrDefault().IsUnconditionalControlFlow())
+ throw new Exception("Basci block has to end with unconditional control flow. \n" + childAsBB.ToString());
+ flatBody.AddRange(childAsBB.GetChildren());
+ } else {
+ flatBody.Add(child);
+ }
+ }
+ block.EntryGoto = null;
+ block.Body = flatBody;
+ } else if (node is ILExpression) {
+ // Optimization - no need to check expressions
+ } else if (node != null) {
+ // Recursively find all ILBlocks
+ foreach(ILNode child in node.GetChildren()) {
+ FlattenBasicBlocks(child);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Replace endfinally with jump to the end of the finally block
+ /// </summary>
+ void RemoveEndFinally(ILBlock method)
+ {
+ // Go thought the list in reverse so that we do the nested blocks first
+ foreach(var tryCatch in method.GetSelfAndChildrenRecursive<ILTryCatchBlock>(tc => tc.FinallyBlock != null).Reverse()) {
+ ILLabel label = new ILLabel() { Name = "EndFinally_" + nextLabelIndex++ };
+ tryCatch.FinallyBlock.Body.Add(label);
+ foreach(var block in tryCatch.FinallyBlock.GetSelfAndChildrenRecursive<ILBlock>()) {
+ for (int i = 0; i < block.Body.Count; i++) {
+ if (block.Body[i].Match(ILCode.Endfinally)) {
+ block.Body[i] = new ILExpression(ILCode.Br, label).WithILRanges(((ILExpression)block.Body[i]).ILRanges);
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Reduce the nesting of conditions.
+ /// It should be done on flat data that already had most gotos removed
+ /// </summary>
+ void ReduceIfNesting(ILNode node)
+ {
+ ILBlock block = node as ILBlock;
+ if (block != null) {
+ for (int i = 0; i < block.Body.Count; i++) {
+ ILCondition cond = block.Body[i] as ILCondition;
+ if (cond != null) {
+ bool trueExits = cond.TrueBlock.Body.LastOrDefault().IsUnconditionalControlFlow();
+ bool falseExits = cond.FalseBlock.Body.LastOrDefault().IsUnconditionalControlFlow();
+
+ if (trueExits) {
+ // Move the false block after the condition
+ block.Body.InsertRange(i + 1, cond.FalseBlock.GetChildren());
+ cond.FalseBlock = new ILBlock();
+ } else if (falseExits) {
+ // Move the true block after the condition
+ block.Body.InsertRange(i + 1, cond.TrueBlock.GetChildren());
+ cond.TrueBlock = new ILBlock();
+ }
+
+ // Eliminate empty true block
+ if (!cond.TrueBlock.GetChildren().Any() && cond.FalseBlock.GetChildren().Any()) {
+ // Swap bodies
+ ILBlock tmp = cond.TrueBlock;
+ cond.TrueBlock = cond.FalseBlock;
+ cond.FalseBlock = tmp;
+ cond.Condition = new ILExpression(ILCode.LogicNot, null, cond.Condition);
+ }
+ }
+ }
+ }
+
+ // We are changing the number of blocks so we use plain old recursion to get all blocks
+ foreach(ILNode child in node.GetChildren()) {
+ if (child != null && !(child is ILExpression))
+ ReduceIfNesting(child);
+ }
+ }
+
+ void RecombineVariables(ILBlock method)
+ {
+ // Recombine variables that were split when the ILAst was created
+ // This ensures that a single IL variable is a single C# variable (gets assigned only one name)
+ // The DeclareVariables transformation might then split up the C# variable again if it is used indendently in two separate scopes.
+ Dictionary<VariableDefinition, ILVariable> dict = new Dictionary<VariableDefinition, ILVariable>();
+ ReplaceVariables(
+ method,
+ delegate(ILVariable v) {
+ if (v.OriginalVariable == null)
+ return v;
+ ILVariable combinedVariable;
+ if (!dict.TryGetValue(v.OriginalVariable, out combinedVariable)) {
+ dict.Add(v.OriginalVariable, v);
+ combinedVariable = v;
+ }
+ return combinedVariable;
+ });
+ }
+
+ static void HandlePointerArithmetic(ILNode method)
+ {
+ foreach (ILExpression expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
+ List<ILExpression> args = expr.Arguments;
+ switch (expr.Code) {
+ case ILCode.Localloc:
+ args[0] = DivideBySize(args[0], ((PointerType)expr.InferredType).ElementType);
+ break;
+ case ILCode.Add:
+ case ILCode.Add_Ovf:
+ case ILCode.Add_Ovf_Un:
+ if (expr.InferredType is PointerType) {
+ if (args[0].ExpectedType is PointerType)
+ args[1] = DivideBySize(args[1], ((PointerType)expr.InferredType).ElementType);
+ else if (args[1].ExpectedType is PointerType)
+ args[0] = DivideBySize(args[0], ((PointerType)expr.InferredType).ElementType);
+ }
+ break;
+ case ILCode.Sub:
+ case ILCode.Sub_Ovf:
+ case ILCode.Sub_Ovf_Un:
+ if (expr.InferredType is PointerType) {
+ if (args[0].ExpectedType is PointerType)
+ args[1] = DivideBySize(args[1], ((PointerType)expr.InferredType).ElementType);
+ }
+ break;
+ }
+ }
+ }
+
+ static ILExpression UnwrapIntPtrCast(ILExpression expr)
+ {
+ if (expr.Code != ILCode.Conv_I && expr.Code != ILCode.Conv_U)
+ return expr;
+
+ ILExpression arg = expr.Arguments[0];
+ switch (arg.InferredType.MetadataType) {
+ case MetadataType.Byte:
+ case MetadataType.SByte:
+ case MetadataType.UInt16:
+ case MetadataType.Int16:
+ case MetadataType.UInt32:
+ case MetadataType.Int32:
+ case MetadataType.UInt64:
+ case MetadataType.Int64:
+ return arg;
+ }
+
+ return expr;
+ }
+
+ static ILExpression DivideBySize(ILExpression expr, TypeReference type)
+ {
+ expr = UnwrapIntPtrCast(expr);
+
+ ILExpression sizeOfExpression;
+ switch (TypeAnalysis.GetInformationAmount(type)) {
+ case 1:
+ case 8:
+ sizeOfExpression = new ILExpression(ILCode.Ldc_I4, 1);
+ break;
+ case 16:
+ sizeOfExpression = new ILExpression(ILCode.Ldc_I4, 2);
+ break;
+ case 32:
+ sizeOfExpression = new ILExpression(ILCode.Ldc_I4, 4);
+ break;
+ case 64:
+ sizeOfExpression = new ILExpression(ILCode.Ldc_I4, 8);
+ break;
+ default:
+ sizeOfExpression = new ILExpression(ILCode.Sizeof, type);
+ break;
+ }
+
+ if (expr.Code == ILCode.Mul || expr.Code == ILCode.Mul_Ovf || expr.Code == ILCode.Mul_Ovf_Un) {
+ ILExpression mulArg = expr.Arguments[1];
+ if (mulArg.Code == sizeOfExpression.Code && sizeOfExpression.Operand.Equals(mulArg.Operand))
+ return UnwrapIntPtrCast(expr.Arguments[0]);
+ }
+
+ if (expr.Code == sizeOfExpression.Code) {
+ if (sizeOfExpression.Operand.Equals(expr.Operand))
+ return new ILExpression(ILCode.Ldc_I4, 1);
+
+ if (expr.Code == ILCode.Ldc_I4) {
+ int offsetInBytes = (int)expr.Operand;
+ int elementSize = (int)sizeOfExpression.Operand;
+ int offsetInElements = offsetInBytes / elementSize;
+
+ // ensure integer division
+ if (offsetInElements * elementSize == offsetInBytes) {
+ expr.Operand = offsetInElements;
+ return expr;
+ }
+ }
+ }
+
+ return new ILExpression(ILCode.Div_Un, null, expr, sizeOfExpression);
+ }
+
+ public static void ReplaceVariables(ILNode node, Func<ILVariable, ILVariable> variableMapping)
+ {
+ ILExpression expr = node as ILExpression;
+ if (expr != null) {
+ ILVariable v = expr.Operand as ILVariable;
+ if (v != null)
+ expr.Operand = variableMapping(v);
+ foreach (ILExpression child in expr.Arguments)
+ ReplaceVariables(child, variableMapping);
+ } else {
+ var catchBlock = node as ILTryCatchBlock.CatchBlock;
+ if (catchBlock != null && catchBlock.ExceptionVariable != null) {
+ catchBlock.ExceptionVariable = variableMapping(catchBlock.ExceptionVariable);
+ }
+
+ foreach (ILNode child in node.GetChildren())
+ ReplaceVariables(child, variableMapping);
+ }
+ }
+
+ void ReportUnassignedILRanges(ILBlock method)
+ {
+ var unassigned = ILRange.Invert(method.GetSelfAndChildrenRecursive<ILExpression>().SelectMany(e => e.ILRanges), context.CurrentMethod.Body.CodeSize).ToList();
+ if (unassigned.Count > 0)
+ Debug.WriteLine(string.Format("Unassigned ILRanges for {0}.{1}: {2}", context.CurrentMethod.DeclaringType.Name, context.CurrentMethod.Name, string.Join(", ", unassigned.Select(r => r.ToString()))));
+ }
+ }
+
+ public static class ILAstOptimizerExtensionMethods
+ {
+ /// <summary>
+ /// Perform one pass of a given optimization on this block.
+ /// This block must consist of only basicblocks.
+ /// </summary>
+ public static bool RunOptimization(this ILBlock block, Func<List<ILNode>, ILBasicBlock, int, bool> optimization)
+ {
+ bool modified = false;
+ List<ILNode> body = block.Body;
+ for (int i = body.Count - 1; i >= 0; i--) {
+ if (i < body.Count && optimization(body, (ILBasicBlock)body[i], i)) {
+ modified = true;
+ }
+ }
+ return modified;
+ }
+
+ public static bool RunOptimization(this ILBlock block, Func<List<ILNode>, ILExpression, int, bool> optimization)
+ {
+ bool modified = false;
+ foreach (ILBasicBlock bb in block.Body) {
+ for (int i = bb.Body.Count - 1; i >= 0; i--) {
+ ILExpression expr = bb.Body.ElementAtOrDefault(i) as ILExpression;
+ if (expr != null && optimization(bb.Body, expr, i)) {
+ modified = true;
+ }
+ }
+ }
+ return modified;
+ }
+
+ public static bool IsConditionalControlFlow(this ILNode node)
+ {
+ ILExpression expr = node as ILExpression;
+ return expr != null && expr.Code.IsConditionalControlFlow();
+ }
+
+ public static bool IsUnconditionalControlFlow(this ILNode node)
+ {
+ ILExpression expr = node as ILExpression;
+ return expr != null && expr.Code.IsUnconditionalControlFlow();
+ }
+
+ /// <summary>
+ /// The expression has no effect on the program and can be removed
+ /// if its return value is not needed.
+ /// </summary>
+ public static bool HasNoSideEffects(this ILExpression expr)
+ {
+ // Remember that if expression can throw an exception, it is a side effect
+
+ switch(expr.Code) {
+ case ILCode.Ldloc:
+ case ILCode.Ldloca:
+ case ILCode.Ldstr:
+ case ILCode.Ldnull:
+ case ILCode.Ldc_I4:
+ case ILCode.Ldc_I8:
+ case ILCode.Ldc_R4:
+ case ILCode.Ldc_R8:
+ case ILCode.Ldc_Decimal:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public static bool IsStoreToArray(this ILCode code)
+ {
+ switch (code) {
+ case ILCode.Stelem_Any:
+ case ILCode.Stelem_I:
+ case ILCode.Stelem_I1:
+ case ILCode.Stelem_I2:
+ case ILCode.Stelem_I4:
+ case ILCode.Stelem_I8:
+ case ILCode.Stelem_R4:
+ case ILCode.Stelem_R8:
+ case ILCode.Stelem_Ref:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public static bool IsLoadFromArray(this ILCode code)
+ {
+ switch (code) {
+ case ILCode.Ldelem_Any:
+ case ILCode.Ldelem_I:
+ case ILCode.Ldelem_I1:
+ case ILCode.Ldelem_I2:
+ case ILCode.Ldelem_I4:
+ case ILCode.Ldelem_I8:
+ case ILCode.Ldelem_U1:
+ case ILCode.Ldelem_U2:
+ case ILCode.Ldelem_U4:
+ case ILCode.Ldelem_R4:
+ case ILCode.Ldelem_R8:
+ case ILCode.Ldelem_Ref:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Can the expression be used as a statement in C#?
+ /// </summary>
+ public static bool CanBeExpressionStatement(this ILExpression expr)
+ {
+ switch(expr.Code) {
+ case ILCode.Call:
+ case ILCode.Callvirt:
+ // property getters can't be expression statements, but all other method calls can be
+ MethodReference mr = (MethodReference)expr.Operand;
+ return !mr.Name.StartsWith("get_", StringComparison.Ordinal);
+ case ILCode.CallSetter:
+ case ILCode.CallvirtSetter:
+ case ILCode.Newobj:
+ case ILCode.Newarr:
+ case ILCode.Stloc:
+ case ILCode.Stobj:
+ case ILCode.Stsfld:
+ case ILCode.Stfld:
+ case ILCode.Stind_Ref:
+ case ILCode.Stelem_Any:
+ case ILCode.Stelem_I:
+ case ILCode.Stelem_I1:
+ case ILCode.Stelem_I2:
+ case ILCode.Stelem_I4:
+ case ILCode.Stelem_I8:
+ case ILCode.Stelem_R4:
+ case ILCode.Stelem_R8:
+ case ILCode.Stelem_Ref:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public static ILExpression WithILRanges(this ILExpression expr, IEnumerable<ILRange> ilranges)
+ {
+ expr.ILRanges.AddRange(ilranges);
+ return expr;
+ }
+
+ public static void RemoveTail(this List<ILNode> body, params ILCode[] codes)
+ {
+ for (int i = 0; i < codes.Length; i++) {
+ if (((ILExpression)body[body.Count - codes.Length + i]).Code != codes[i])
+ throw new Exception("Tailing code does not match expected.");
+ }
+ body.RemoveRange(body.Count - codes.Length, codes.Length);
+ }
+
+ public static V GetOrDefault<K,V>(this Dictionary<K, V> dict, K key)
+ {
+ V ret;
+ dict.TryGetValue(key, out ret);
+ return ret;
+ }
+
+ public static void RemoveOrThrow<T>(this ICollection<T> collection, T item)
+ {
+ if (!collection.Remove(item))
+ throw new Exception("The item was not found in the collection");
+ }
+
+ public static void RemoveOrThrow<K,V>(this Dictionary<K,V> collection, K key)
+ {
+ if (!collection.Remove(key))
+ throw new Exception("The key was not found in the dictionary");
+ }
+
+ public static bool ContainsReferenceTo(this ILExpression expr, ILVariable v)
+ {
+ if (expr.Operand == v)
+ return true;
+ foreach (var arg in expr.Arguments) {
+ if (ContainsReferenceTo(arg, v))
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
new file mode 100644
index 00000000..aab64e6e
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
@@ -0,0 +1,601 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.Disassembler;
+using ICSharpCode.NRefactory.Utils;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Mono.CSharp;
+using Cecil = Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ public abstract class ILNode
+ {
+ public IEnumerable<T> GetSelfAndChildrenRecursive<T>(Func<T, bool> predicate = null) where T: ILNode
+ {
+ List<T> result = new List<T>(16);
+ AccumulateSelfAndChildrenRecursive(result, predicate);
+ return result;
+ }
+
+ void AccumulateSelfAndChildrenRecursive<T>(List<T> list, Func<T, bool> predicate) where T:ILNode
+ {
+ // Note: RemoveEndFinally depends on self coming before children
+ T thisAsT = this as T;
+ if (thisAsT != null && (predicate == null || predicate(thisAsT)))
+ list.Add(thisAsT);
+ foreach (ILNode node in GetChildren()) {
+ if (node != null)
+ node.AccumulateSelfAndChildrenRecursive(list, predicate);
+ }
+ }
+
+ public virtual IEnumerable<ILNode> GetChildren()
+ {
+ yield break;
+ }
+
+ public override string ToString()
+ {
+ StringWriter w = new StringWriter();
+ WriteTo(new PlainTextOutput(w));
+ return w.ToString().Replace("\r\n", "; ");
+ }
+
+ public abstract void WriteTo(ITextOutput output);
+ }
+
+ public class ILBlock: ILNode
+ {
+ public ILExpression EntryGoto;
+
+ public List<ILNode> Body;
+
+ public ILBlock(params ILNode[] body)
+ {
+ Body = new List<ILNode>(body);
+ }
+
+ public ILBlock(List<ILNode> body)
+ {
+ Body = body;
+ }
+
+ public override IEnumerable<ILNode> GetChildren()
+ {
+ if (EntryGoto != null)
+ yield return EntryGoto;
+ foreach(ILNode child in Body) {
+ yield return child;
+ }
+ }
+
+ public override void WriteTo(ITextOutput output)
+ {
+ foreach(ILNode child in GetChildren()) {
+ child.WriteTo(output);
+ output.WriteLine();
+ }
+ }
+ }
+
+ public class ILBasicBlock: ILNode
+ {
+ /// <remarks> Body has to start with a label and end with unconditional control flow </remarks>
+ public List<ILNode> Body = new List<ILNode>();
+
+ public override IEnumerable<ILNode> GetChildren()
+ {
+ return Body;
+ }
+
+ public override void WriteTo(ITextOutput output)
+ {
+ foreach(ILNode child in GetChildren()) {
+ child.WriteTo(output);
+ output.WriteLine();
+ }
+ }
+ }
+
+ public class ILLabel: ILNode
+ {
+ public string Name;
+
+ public override void WriteTo(ITextOutput output)
+ {
+ output.WriteDefinition(Name + ":", this);
+ }
+ }
+
+ public class ILTryCatchBlock: ILNode
+ {
+ public class CatchBlock: ILBlock
+ {
+ public TypeReference ExceptionType;
+ public ILVariable ExceptionVariable;
+
+ public override void WriteTo(ITextOutput output)
+ {
+ output.Write("catch ");
+ output.WriteReference(ExceptionType.FullName, ExceptionType);
+ if (ExceptionVariable != null) {
+ output.Write(' ');
+ output.Write(ExceptionVariable.Name);
+ }
+ output.WriteLine(" {");
+ output.Indent();
+ base.WriteTo(output);
+ output.Unindent();
+ output.WriteLine("}");
+ }
+ }
+
+ public ILBlock TryBlock;
+ public List<CatchBlock> CatchBlocks;
+ public ILBlock FinallyBlock;
+ public ILBlock FaultBlock;
+
+ public override IEnumerable<ILNode> GetChildren()
+ {
+ if (TryBlock != null)
+ yield return TryBlock;
+ foreach (var catchBlock in CatchBlocks) {
+ yield return catchBlock;
+ }
+ if (FaultBlock != null)
+ yield return FaultBlock;
+ if (FinallyBlock != null)
+ yield return FinallyBlock;
+ }
+
+ public override void WriteTo(ITextOutput output)
+ {
+ output.WriteLine(".try {");
+ output.Indent();
+ TryBlock.WriteTo(output);
+ output.Unindent();
+ output.WriteLine("}");
+ foreach (CatchBlock block in CatchBlocks) {
+ block.WriteTo(output);
+ }
+ if (FaultBlock != null) {
+ output.WriteLine("fault {");
+ output.Indent();
+ FaultBlock.WriteTo(output);
+ output.Unindent();
+ output.WriteLine("}");
+ }
+ if (FinallyBlock != null) {
+ output.WriteLine("finally {");
+ output.Indent();
+ FinallyBlock.WriteTo(output);
+ output.Unindent();
+ output.WriteLine("}");
+ }
+ }
+ }
+
+ public class ILVariable
+ {
+ public string Name;
+ public bool IsGenerated;
+ public TypeReference Type;
+ public VariableDefinition OriginalVariable;
+ public ParameterDefinition OriginalParameter;
+
+ public bool IsPinned {
+ get { return OriginalVariable != null && OriginalVariable.IsPinned; }
+ }
+
+ public bool IsParameter {
+ get { return OriginalParameter != null; }
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+ }
+
+ public struct ILRange
+ {
+ public readonly int From;
+ public readonly int To; // Exlusive
+
+ public ILRange(int @from, int to)
+ {
+ From = @from;
+ To = to;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{0:X2}-{1:X2}", From, To);
+ }
+
+ public static List<ILRange> OrderAndJoin(IEnumerable<ILRange> input)
+ {
+ if (input == null)
+ throw new ArgumentNullException("Input is null!");
+
+ List<ILRange> result = new List<ILRange>();
+ foreach(ILRange curr in input.OrderBy(r => r.From)) {
+ if (result.Count > 0) {
+ // Merge consequtive ranges if possible
+ ILRange last = result[result.Count - 1];
+ if (curr.From <= last.To) {
+ result[result.Count - 1] = new ILRange(last.From, Math.Max(last.To, curr.To));
+ continue;
+ }
+ }
+ result.Add(curr);
+ }
+ return result;
+ }
+
+ public static List<ILRange> Invert(IEnumerable<ILRange> input, int codeSize)
+ {
+ if (input == null)
+ throw new ArgumentNullException("Input is null!");
+
+ if (codeSize <= 0)
+ throw new ArgumentException("Code size must be grater than 0");
+
+ List<ILRange> ordered = OrderAndJoin(input);
+ List<ILRange> result = new List<ILRange>(ordered.Count + 1);
+ if (ordered.Count == 0) {
+ result.Add(new ILRange(0, codeSize));
+ } else {
+ // Gap before the first element
+ if (ordered.First().From != 0)
+ result.Add(new ILRange(0, ordered.First().From));
+
+ // Gaps between elements
+ for (int i = 0; i < ordered.Count - 1; i++)
+ result.Add(new ILRange(ordered[i].To, ordered[i + 1].From));
+
+ // Gap after the last element
+ Debug.Assert(ordered.Last().To <= codeSize);
+ if (ordered.Last().To != codeSize)
+ result.Add(new ILRange(ordered.Last().To, codeSize));
+ }
+ return result;
+ }
+ }
+
+ public class ILExpressionPrefix
+ {
+ public readonly ILCode Code;
+ public readonly object Operand;
+
+ public ILExpressionPrefix(ILCode code, object operand = null)
+ {
+ Code = code;
+ Operand = operand;
+ }
+ }
+
+ public class ILExpression : ILNode
+ {
+ public ILCode Code { get; set; }
+ public object Operand { get; set; }
+ public List<ILExpression> Arguments { get; set; }
+ public ILExpressionPrefix[] Prefixes { get; set; }
+ // Mapping to the original instructions (useful for debugging)
+ public List<ILRange> ILRanges { get; set; }
+
+ public TypeReference ExpectedType { get; set; }
+ public TypeReference InferredType { get; set; }
+
+ public static readonly object AnyOperand = new object();
+
+ public ILExpression(ILCode code, object operand, List<ILExpression> args)
+ {
+ if (operand is ILExpression)
+ throw new ArgumentException("operand");
+
+ Code = code;
+ Operand = operand;
+ Arguments = new List<ILExpression>(args);
+ ILRanges = new List<ILRange>(1);
+ }
+
+ public ILExpression(ILCode code, object operand, params ILExpression[] args)
+ {
+ if (operand is ILExpression)
+ throw new ArgumentException("operand");
+
+ Code = code;
+ Operand = operand;
+ Arguments = new List<ILExpression>(args);
+ ILRanges = new List<ILRange>(1);
+ }
+
+ public void AddPrefix(ILExpressionPrefix prefix)
+ {
+ ILExpressionPrefix[] arr = Prefixes;
+ if (arr == null)
+ arr = new ILExpressionPrefix[1];
+ else
+ Array.Resize(ref arr, arr.Length + 1);
+ arr[arr.Length - 1] = prefix;
+ Prefixes = arr;
+ }
+
+ public ILExpressionPrefix GetPrefix(ILCode code)
+ {
+ var prefixes = Prefixes;
+ if (prefixes != null) {
+ foreach (ILExpressionPrefix p in prefixes) {
+ if (p.Code == code)
+ return p;
+ }
+ }
+ return null;
+ }
+
+ public override IEnumerable<ILNode> GetChildren()
+ {
+ return Arguments;
+ }
+
+ public bool IsBranch()
+ {
+ return Operand is ILLabel || Operand is ILLabel[];
+ }
+
+ public IEnumerable<ILLabel> GetBranchTargets()
+ {
+ if (Operand is ILLabel) {
+ return new ILLabel[] { (ILLabel)Operand };
+ } else if (Operand is ILLabel[]) {
+ return (ILLabel[])Operand;
+ } else {
+ return new ILLabel[] { };
+ }
+ }
+
+ public override void WriteTo(ITextOutput output)
+ {
+ if (Operand is ILVariable && ((ILVariable)Operand).IsGenerated) {
+ if (Code == ILCode.Stloc && InferredType == null) {
+ output.Write(((ILVariable)Operand).Name);
+ output.Write(" = ");
+ Arguments.First().WriteTo(output);
+ return;
+ } else if (Code == ILCode.Ldloc) {
+ output.Write(((ILVariable)Operand).Name);
+ if (InferredType != null) {
+ output.Write(':');
+ InferredType.WriteTo(output, ILNameSyntax.ShortTypeName);
+ if (ExpectedType != null && ExpectedType.FullName != InferredType.FullName) {
+ output.Write("[exp:");
+ ExpectedType.WriteTo(output, ILNameSyntax.ShortTypeName);
+ output.Write(']');
+ }
+ }
+ return;
+ }
+ }
+
+ if (Prefixes != null) {
+ foreach (var prefix in Prefixes) {
+ output.Write(prefix.Code.GetName());
+ output.Write(". ");
+ }
+ }
+
+ output.Write(Code.GetName());
+ if (InferredType != null) {
+ output.Write(':');
+ InferredType.WriteTo(output, ILNameSyntax.ShortTypeName);
+ if (ExpectedType != null && ExpectedType.FullName != InferredType.FullName) {
+ output.Write("[exp:");
+ ExpectedType.WriteTo(output, ILNameSyntax.ShortTypeName);
+ output.Write(']');
+ }
+ } else if (ExpectedType != null) {
+ output.Write("[exp:");
+ ExpectedType.WriteTo(output, ILNameSyntax.ShortTypeName);
+ output.Write(']');
+ }
+ output.Write('(');
+ bool first = true;
+ if (Operand != null) {
+ if (Operand is ILLabel) {
+ output.WriteReference(((ILLabel)Operand).Name, Operand);
+ } else if (Operand is ILLabel[]) {
+ ILLabel[] labels = (ILLabel[])Operand;
+ for (int i = 0; i < labels.Length; i++) {
+ if (i > 0)
+ output.Write(", ");
+ output.WriteReference(labels[i].Name, labels[i]);
+ }
+ } else if (Operand is MethodReference) {
+ MethodReference method = (MethodReference)Operand;
+ if (method.DeclaringType != null) {
+ method.DeclaringType.WriteTo(output, ILNameSyntax.ShortTypeName);
+ output.Write("::");
+ }
+ output.WriteReference(method.Name, method);
+ } else if (Operand is FieldReference) {
+ FieldReference field = (FieldReference)Operand;
+ field.DeclaringType.WriteTo(output, ILNameSyntax.ShortTypeName);
+ output.Write("::");
+ output.WriteReference(field.Name, field);
+ } else {
+ DisassemblerHelpers.WriteOperand(output, Operand);
+ }
+ first = false;
+ }
+ foreach (ILExpression arg in Arguments) {
+ if (!first) output.Write(", ");
+ arg.WriteTo(output);
+ first = false;
+ }
+ output.Write(')');
+ }
+ }
+
+ public class ILWhileLoop : ILNode
+ {
+ public ILExpression Condition;
+ public ILBlock BodyBlock;
+
+ public override IEnumerable<ILNode> GetChildren()
+ {
+ if (Condition != null)
+ yield return Condition;
+ if (BodyBlock != null)
+ yield return BodyBlock;
+ }
+
+ public override void WriteTo(ITextOutput output)
+ {
+ output.WriteLine("");
+ output.Write("loop (");
+ if (Condition != null)
+ Condition.WriteTo(output);
+ output.WriteLine(") {");
+ output.Indent();
+ BodyBlock.WriteTo(output);
+ output.Unindent();
+ output.WriteLine("}");
+ }
+ }
+
+ public class ILCondition : ILNode
+ {
+ public ILExpression Condition;
+ public ILBlock TrueBlock; // Branch was taken
+ public ILBlock FalseBlock; // Fall-though
+
+ public override IEnumerable<ILNode> GetChildren()
+ {
+ if (Condition != null)
+ yield return Condition;
+ if (TrueBlock != null)
+ yield return TrueBlock;
+ if (FalseBlock != null)
+ yield return FalseBlock;
+ }
+
+ public override void WriteTo(ITextOutput output)
+ {
+ output.Write("if (");
+ Condition.WriteTo(output);
+ output.WriteLine(") {");
+ output.Indent();
+ TrueBlock.WriteTo(output);
+ output.Unindent();
+ output.Write("}");
+ if (FalseBlock != null) {
+ output.WriteLine(" else {");
+ output.Indent();
+ FalseBlock.WriteTo(output);
+ output.Unindent();
+ output.WriteLine("}");
+ }
+ }
+ }
+
+ public class ILSwitch: ILNode
+ {
+ public class CaseBlock: ILBlock
+ {
+ public List<int> Values; // null for the default case
+
+ public override void WriteTo(ITextOutput output)
+ {
+ if (Values != null) {
+ foreach (int i in Values) {
+ output.WriteLine("case {0}:", i);
+ }
+ } else {
+ output.WriteLine("default:");
+ }
+ output.Indent();
+ base.WriteTo(output);
+ output.Unindent();
+ }
+ }
+
+ public ILExpression Condition;
+ public List<CaseBlock> CaseBlocks = new List<CaseBlock>();
+
+ public override IEnumerable<ILNode> GetChildren()
+ {
+ if (Condition != null)
+ yield return Condition;
+ foreach (ILBlock caseBlock in CaseBlocks) {
+ yield return caseBlock;
+ }
+ }
+
+ public override void WriteTo(ITextOutput output)
+ {
+ output.Write("switch (");
+ Condition.WriteTo(output);
+ output.WriteLine(") {");
+ output.Indent();
+ foreach (CaseBlock caseBlock in CaseBlocks) {
+ caseBlock.WriteTo(output);
+ }
+ output.Unindent();
+ output.WriteLine("}");
+ }
+ }
+
+ public class ILFixedStatement : ILNode
+ {
+ public List<ILExpression> Initializers = new List<ILExpression>();
+ public ILBlock BodyBlock;
+
+ public override IEnumerable<ILNode> GetChildren()
+ {
+ foreach (ILExpression initializer in Initializers)
+ yield return initializer;
+ if (BodyBlock != null)
+ yield return BodyBlock;
+ }
+
+ public override void WriteTo(ITextOutput output)
+ {
+ output.Write("fixed (");
+ for (int i = 0; i < Initializers.Count; i++) {
+ if (i > 0)
+ output.Write(", ");
+ Initializers[i].WriteTo(output);
+ }
+ output.WriteLine(") {");
+ output.Indent();
+ BodyBlock.WriteTo(output);
+ output.Unindent();
+ output.WriteLine("}");
+ }
+ }
+} \ No newline at end of file
diff --git a/ICSharpCode.Decompiler/ILAst/ILCodes.cs b/ICSharpCode.Decompiler/ILAst/ILCodes.cs
new file mode 100644
index 00000000..5ca063b7
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/ILCodes.cs
@@ -0,0 +1,490 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ public enum ILCode
+ {
+ // For convenience, the start is exactly identical to Mono.Cecil.Cil.Code
+ // Instructions that should not be used are prepended by __
+ Nop,
+ Break,
+ __Ldarg_0,
+ __Ldarg_1,
+ __Ldarg_2,
+ __Ldarg_3,
+ __Ldloc_0,
+ __Ldloc_1,
+ __Ldloc_2,
+ __Ldloc_3,
+ __Stloc_0,
+ __Stloc_1,
+ __Stloc_2,
+ __Stloc_3,
+ __Ldarg_S,
+ __Ldarga_S,
+ __Starg_S,
+ __Ldloc_S,
+ __Ldloca_S,
+ __Stloc_S,
+ Ldnull,
+ __Ldc_I4_M1,
+ __Ldc_I4_0,
+ __Ldc_I4_1,
+ __Ldc_I4_2,
+ __Ldc_I4_3,
+ __Ldc_I4_4,
+ __Ldc_I4_5,
+ __Ldc_I4_6,
+ __Ldc_I4_7,
+ __Ldc_I4_8,
+ __Ldc_I4_S,
+ Ldc_I4,
+ Ldc_I8,
+ Ldc_R4,
+ Ldc_R8,
+ Dup,
+ Pop,
+ Jmp,
+ Call,
+ Calli,
+ Ret,
+ __Br_S,
+ __Brfalse_S,
+ __Brtrue_S,
+ __Beq_S,
+ __Bge_S,
+ __Bgt_S,
+ __Ble_S,
+ __Blt_S,
+ __Bne_Un_S,
+ __Bge_Un_S,
+ __Bgt_Un_S,
+ __Ble_Un_S,
+ __Blt_Un_S,
+ Br,
+ __Brfalse,
+ Brtrue,
+ __Beq,
+ __Bge,
+ __Bgt,
+ __Ble,
+ __Blt,
+ __Bne_Un,
+ __Bge_Un,
+ __Bgt_Un,
+ __Ble_Un,
+ __Blt_Un,
+ Switch,
+ __Ldind_I1,
+ __Ldind_U1,
+ __Ldind_I2,
+ __Ldind_U2,
+ __Ldind_I4,
+ __Ldind_U4,
+ __Ldind_I8,
+ __Ldind_I,
+ __Ldind_R4,
+ __Ldind_R8,
+ Ldind_Ref,
+ Stind_Ref,
+ __Stind_I1,
+ __Stind_I2,
+ __Stind_I4,
+ __Stind_I8,
+ __Stind_R4,
+ __Stind_R8,
+ Add,
+ Sub,
+ Mul,
+ Div,
+ Div_Un,
+ Rem,
+ Rem_Un,
+ And,
+ Or,
+ Xor,
+ Shl,
+ Shr,
+ Shr_Un,
+ Neg,
+ Not,
+ Conv_I1,
+ Conv_I2,
+ Conv_I4,
+ Conv_I8,
+ Conv_R4,
+ Conv_R8,
+ Conv_U4,
+ Conv_U8,
+ Callvirt,
+ Cpobj,
+ Ldobj,
+ Ldstr,
+ Newobj,
+ Castclass,
+ Isinst,
+ Conv_R_Un,
+ Unbox,
+ Throw,
+ Ldfld,
+ Ldflda,
+ Stfld,
+ Ldsfld,
+ Ldsflda,
+ Stsfld,
+ Stobj,
+ Conv_Ovf_I1_Un,
+ Conv_Ovf_I2_Un,
+ Conv_Ovf_I4_Un,
+ Conv_Ovf_I8_Un,
+ Conv_Ovf_U1_Un,
+ Conv_Ovf_U2_Un,
+ Conv_Ovf_U4_Un,
+ Conv_Ovf_U8_Un,
+ Conv_Ovf_I_Un,
+ Conv_Ovf_U_Un,
+ Box,
+ Newarr,
+ Ldlen,
+ Ldelema,
+ Ldelem_I1,
+ Ldelem_U1,
+ Ldelem_I2,
+ Ldelem_U2,
+ Ldelem_I4,
+ Ldelem_U4,
+ Ldelem_I8,
+ Ldelem_I,
+ Ldelem_R4,
+ Ldelem_R8,
+ Ldelem_Ref,
+ Stelem_I,
+ Stelem_I1,
+ Stelem_I2,
+ Stelem_I4,
+ Stelem_I8,
+ Stelem_R4,
+ Stelem_R8,
+ Stelem_Ref,
+ Ldelem_Any,
+ Stelem_Any,
+ Unbox_Any,
+ Conv_Ovf_I1,
+ Conv_Ovf_U1,
+ Conv_Ovf_I2,
+ Conv_Ovf_U2,
+ Conv_Ovf_I4,
+ Conv_Ovf_U4,
+ Conv_Ovf_I8,
+ Conv_Ovf_U8,
+ Refanyval,
+ Ckfinite,
+ Mkrefany,
+ Ldtoken,
+ Conv_U2,
+ Conv_U1,
+ Conv_I,
+ Conv_Ovf_I,
+ Conv_Ovf_U,
+ Add_Ovf,
+ Add_Ovf_Un,
+ Mul_Ovf,
+ Mul_Ovf_Un,
+ Sub_Ovf,
+ Sub_Ovf_Un,
+ Endfinally,
+ Leave,
+ __Leave_S,
+ __Stind_I,
+ Conv_U,
+ Arglist,
+ Ceq,
+ Cgt,
+ Cgt_Un,
+ Clt,
+ Clt_Un,
+ Ldftn,
+ Ldvirtftn,
+ __Ldarg,
+ __Ldarga,
+ __Starg,
+ Ldloc,
+ Ldloca,
+ Stloc,
+ Localloc,
+ Endfilter,
+ Unaligned,
+ Volatile,
+ Tail,
+ Initobj,
+ Constrained,
+ Cpblk,
+ Initblk,
+ No,
+ Rethrow,
+ Sizeof,
+ Refanytype,
+ Readonly,
+
+ // Virtual codes - defined for convenience
+ Cne,
+ Cge,
+ Cge_Un,
+ Cle,
+ Cle_Un,
+ Ldexception, // Operand holds the CatchType for catch handler, null for filter
+ LogicNot,
+ LogicAnd,
+ LogicOr,
+ NullCoalescing,
+ InitArray, // Array Initializer
+
+ /// <summary>
+ /// Defines a barrier between the parent expression and the argument expression that prevents combining them
+ /// </summary>
+ Wrap,
+
+ // new Class { Prop = 1, Collection = { { 2, 3 }, {4, 5} }}
+ // is represented as:
+ // InitObject(newobj Class,
+ // CallSetter(Prop, InitializedObject, 1),
+ // InitCollection(CallGetter(Collection, InitializedObject))),
+ // Call(Add, InitializedObject, 2, 3),
+ // Call(Add, InitializedObject, 4, 5)))
+ InitObject, // Object initializer: first arg is newobj/defaultvalue, remaining args are the initializing statements
+ InitCollection, // Collection initializer: first arg is newobj/defaultvalue, remaining args are the initializing statements
+ InitializedObject, // Refers the the object being initialized (refers to first arg in parent InitObject or InitCollection instruction)
+
+ TernaryOp, // ?:
+ LoopOrSwitchBreak,
+ LoopContinue,
+ Ldc_Decimal,
+ YieldBreak,
+ YieldReturn,
+ /// <summary>
+ /// Represents the 'default(T)' instruction.
+ /// </summary>
+ /// <remarks>Introduced by SimplifyLdObjAndStObj step</remarks>
+ DefaultValue,
+ /// <summary>
+ /// ILExpression with a single child: binary operator.
+ /// This expression means that the binary operator will also assign the new value to its left-hand side.
+ /// 'CompoundAssignment' must not be used for local variables, as inlining (and other) optimizations don't know that it modifies the variable.
+ /// </summary>
+ /// <remarks>Introduced by MakeCompoundAssignments step</remarks>
+ CompoundAssignment,
+ /// <summary>
+ /// Represents the post-increment operator.
+ /// The first argument is the address of the variable to increment (ldloca instruction).
+ /// The second arugment is the amount the variable is incremented by (ldc.i4 instruction)
+ /// </summary>
+ /// <remarks>Introduced by IntroducePostIncrement step</remarks>
+ PostIncrement,
+ PostIncrement_Ovf, // checked variant of PostIncrement
+ PostIncrement_Ovf_Un, // checked variant of PostIncrement, for unsigned integers
+ /// <summary>Calls the getter of a static property (or indexer), or of an instance property on 'base'</summary>
+ CallGetter,
+ /// <summary>Calls the getter of an instance property (or indexer)</summary>
+ CallvirtGetter,
+ /// <summary>Calls the setter of a static property (or indexer), or of an instance property on 'base'</summary>
+ /// <remarks>This allows us to represent "while ((SomeProperty = val) != null) {}"</remarks>
+ CallSetter,
+ /// <summary>Calls the setter of a instance property (or indexer)</summary>
+ CallvirtSetter,
+ /// <summary>Simulates getting the address of the argument instruction.</summary>
+ /// <remarks>
+ /// Used for postincrement for properties, and to represent the Address() method on multi-dimensional arrays.
+ /// Also used when inlining a method call on a value type: "stloc(v, ...); call(M, ldloca(v));" becomes "call(M, AddressOf(...))"
+ /// </remarks>
+ AddressOf,
+ /// <summary>Simulates getting the value of a lifted operator's nullable argument</summary>
+ /// <remarks>
+ /// For example "stloc(v1, ...); stloc(v2, ...); logicand(ceq(call(Nullable`1::GetValueOrDefault, ldloca(v1)), ldloc(v2)), callgetter(Nullable`1::get_HasValue, ldloca(v1)))" becomes "wrap(ceq(ValueOf(...), ...))"
+ /// </remarks>
+ ValueOf,
+ /// <summary>Simulates creating a new nullable value from a value type argument</summary>
+ /// <remarks>
+ /// For example "stloc(v1, ...); stloc(v2, ...); ternaryop(callgetter(Nullable`1::get_HasValue, ldloca(v1)), newobj(Nullable`1::.ctor, add(call(Nullable`1::GetValueOrDefault, ldloca(v1)), ldloc(v2))), defaultvalue(Nullable`1))"
+ /// becomes "NullableOf(add(valueof(...), ...))"
+ /// </remarks>
+ NullableOf,
+ /// <summary>
+ /// Declares parameters that are used in an expression tree.
+ /// The last child of this node is the call constructing the expression tree, all other children are the
+ /// assignments to the ParameterExpression variables.
+ /// </summary>
+ ExpressionTreeParameterDeclarations,
+ /// <summary>
+ /// C# 5 await
+ /// </summary>
+ Await
+ }
+
+ public static class ILCodeUtil
+ {
+ public static string GetName(this ILCode code)
+ {
+ return code.ToString().ToLowerInvariant().TrimStart('_').Replace('_','.');
+ }
+
+ public static bool IsConditionalControlFlow(this ILCode code)
+ {
+ switch(code) {
+ case ILCode.__Brfalse_S:
+ case ILCode.__Brtrue_S:
+ case ILCode.__Beq_S:
+ case ILCode.__Bge_S:
+ case ILCode.__Bgt_S:
+ case ILCode.__Ble_S:
+ case ILCode.__Blt_S:
+ case ILCode.__Bne_Un_S:
+ case ILCode.__Bge_Un_S:
+ case ILCode.__Bgt_Un_S:
+ case ILCode.__Ble_Un_S:
+ case ILCode.__Blt_Un_S:
+ case ILCode.__Brfalse:
+ case ILCode.Brtrue:
+ case ILCode.__Beq:
+ case ILCode.__Bge:
+ case ILCode.__Bgt:
+ case ILCode.__Ble:
+ case ILCode.__Blt:
+ case ILCode.__Bne_Un:
+ case ILCode.__Bge_Un:
+ case ILCode.__Bgt_Un:
+ case ILCode.__Ble_Un:
+ case ILCode.__Blt_Un:
+ case ILCode.Switch:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public static bool IsUnconditionalControlFlow(this ILCode code)
+ {
+ switch(code) {
+ case ILCode.Br:
+ case ILCode.__Br_S:
+ case ILCode.Leave:
+ case ILCode.__Leave_S:
+ case ILCode.Ret:
+ case ILCode.Endfilter:
+ case ILCode.Endfinally:
+ case ILCode.Throw:
+ case ILCode.Rethrow:
+ case ILCode.LoopContinue:
+ case ILCode.LoopOrSwitchBreak:
+ case ILCode.YieldBreak:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public static void ExpandMacro(ref ILCode code, ref object operand, MethodBody methodBody)
+ {
+ switch (code) {
+ case ILCode.__Ldarg_0: code = ILCode.__Ldarg; operand = methodBody.GetParameter(0); break;
+ case ILCode.__Ldarg_1: code = ILCode.__Ldarg; operand = methodBody.GetParameter(1); break;
+ case ILCode.__Ldarg_2: code = ILCode.__Ldarg; operand = methodBody.GetParameter(2); break;
+ case ILCode.__Ldarg_3: code = ILCode.__Ldarg; operand = methodBody.GetParameter(3); break;
+ case ILCode.__Ldloc_0: code = ILCode.Ldloc; operand = methodBody.Variables[0]; break;
+ case ILCode.__Ldloc_1: code = ILCode.Ldloc; operand = methodBody.Variables[1]; break;
+ case ILCode.__Ldloc_2: code = ILCode.Ldloc; operand = methodBody.Variables[2]; break;
+ case ILCode.__Ldloc_3: code = ILCode.Ldloc; operand = methodBody.Variables[3]; break;
+ case ILCode.__Stloc_0: code = ILCode.Stloc; operand = methodBody.Variables[0]; break;
+ case ILCode.__Stloc_1: code = ILCode.Stloc; operand = methodBody.Variables[1]; break;
+ case ILCode.__Stloc_2: code = ILCode.Stloc; operand = methodBody.Variables[2]; break;
+ case ILCode.__Stloc_3: code = ILCode.Stloc; operand = methodBody.Variables[3]; break;
+ case ILCode.__Ldarg_S: code = ILCode.__Ldarg; break;
+ case ILCode.__Ldarga_S: code = ILCode.__Ldarga; break;
+ case ILCode.__Starg_S: code = ILCode.__Starg; break;
+ case ILCode.__Ldloc_S: code = ILCode.Ldloc; break;
+ case ILCode.__Ldloca_S: code = ILCode.Ldloca; break;
+ case ILCode.__Stloc_S: code = ILCode.Stloc; break;
+ case ILCode.__Ldc_I4_M1: code = ILCode.Ldc_I4; operand = -1; break;
+ case ILCode.__Ldc_I4_0: code = ILCode.Ldc_I4; operand = 0; break;
+ case ILCode.__Ldc_I4_1: code = ILCode.Ldc_I4; operand = 1; break;
+ case ILCode.__Ldc_I4_2: code = ILCode.Ldc_I4; operand = 2; break;
+ case ILCode.__Ldc_I4_3: code = ILCode.Ldc_I4; operand = 3; break;
+ case ILCode.__Ldc_I4_4: code = ILCode.Ldc_I4; operand = 4; break;
+ case ILCode.__Ldc_I4_5: code = ILCode.Ldc_I4; operand = 5; break;
+ case ILCode.__Ldc_I4_6: code = ILCode.Ldc_I4; operand = 6; break;
+ case ILCode.__Ldc_I4_7: code = ILCode.Ldc_I4; operand = 7; break;
+ case ILCode.__Ldc_I4_8: code = ILCode.Ldc_I4; operand = 8; break;
+ case ILCode.__Ldc_I4_S: code = ILCode.Ldc_I4; operand = (int) (sbyte) operand; break;
+ case ILCode.__Br_S: code = ILCode.Br; break;
+ case ILCode.__Brfalse_S: code = ILCode.__Brfalse; break;
+ case ILCode.__Brtrue_S: code = ILCode.Brtrue; break;
+ case ILCode.__Beq_S: code = ILCode.__Beq; break;
+ case ILCode.__Bge_S: code = ILCode.__Bge; break;
+ case ILCode.__Bgt_S: code = ILCode.__Bgt; break;
+ case ILCode.__Ble_S: code = ILCode.__Ble; break;
+ case ILCode.__Blt_S: code = ILCode.__Blt; break;
+ case ILCode.__Bne_Un_S: code = ILCode.__Bne_Un; break;
+ case ILCode.__Bge_Un_S: code = ILCode.__Bge_Un; break;
+ case ILCode.__Bgt_Un_S: code = ILCode.__Bgt_Un; break;
+ case ILCode.__Ble_Un_S: code = ILCode.__Ble_Un; break;
+ case ILCode.__Blt_Un_S: code = ILCode.__Blt_Un; break;
+ case ILCode.__Leave_S: code = ILCode.Leave; break;
+ case ILCode.__Ldind_I: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.IntPtr; break;
+ case ILCode.__Ldind_I1: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.SByte; break;
+ case ILCode.__Ldind_I2: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Int16; break;
+ case ILCode.__Ldind_I4: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Int32; break;
+ case ILCode.__Ldind_I8: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Int64; break;
+ case ILCode.__Ldind_U1: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Byte; break;
+ case ILCode.__Ldind_U2: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.UInt16; break;
+ case ILCode.__Ldind_U4: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.UInt32; break;
+ case ILCode.__Ldind_R4: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Single; break;
+ case ILCode.__Ldind_R8: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Double; break;
+ case ILCode.__Stind_I: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.IntPtr; break;
+ case ILCode.__Stind_I1: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Byte; break;
+ case ILCode.__Stind_I2: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Int16; break;
+ case ILCode.__Stind_I4: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Int32; break;
+ case ILCode.__Stind_I8: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Int64; break;
+ case ILCode.__Stind_R4: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Single; break;
+ case ILCode.__Stind_R8: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Double; break;
+ }
+ }
+
+ public static ParameterDefinition GetParameter (this MethodBody self, int index)
+ {
+ var method = self.Method;
+
+ if (method.HasThis) {
+ if (index == 0)
+ return self.ThisParameter;
+
+ index--;
+ }
+
+ var parameters = method.Parameters;
+
+ if (index < 0 || index >= parameters.Count)
+ return null;
+
+ return parameters [index];
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/ILAst/ILInlining.cs b/ICSharpCode.Decompiler/ILAst/ILInlining.cs
new file mode 100644
index 00000000..11140ef0
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/ILInlining.cs
@@ -0,0 +1,524 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ /// <summary>
+ /// Performs inlining transformations.
+ /// </summary>
+ public class ILInlining
+ {
+ readonly ILBlock method;
+ internal Dictionary<ILVariable, int> numStloc = new Dictionary<ILVariable, int>();
+ internal Dictionary<ILVariable, int> numLdloc = new Dictionary<ILVariable, int>();
+ internal Dictionary<ILVariable, int> numLdloca = new Dictionary<ILVariable, int>();
+
+ public ILInlining(ILBlock method)
+ {
+ this.method = method;
+ AnalyzeMethod();
+ }
+
+ void AnalyzeMethod()
+ {
+ numStloc.Clear();
+ numLdloc.Clear();
+ numLdloca.Clear();
+
+ // Analyse the whole method
+ AnalyzeNode(method);
+ }
+
+ /// <summary>
+ /// For each variable reference, adds <paramref name="direction"/> to the num* dicts.
+ /// Direction will be 1 for analysis, and -1 when removing a node from analysis.
+ /// </summary>
+ void AnalyzeNode(ILNode node, int direction = 1)
+ {
+ ILExpression expr = node as ILExpression;
+ if (expr != null) {
+ ILVariable locVar = expr.Operand as ILVariable;
+ if (locVar != null) {
+ if (expr.Code == ILCode.Stloc) {
+ numStloc[locVar] = numStloc.GetOrDefault(locVar) + direction;
+ } else if (expr.Code == ILCode.Ldloc) {
+ numLdloc[locVar] = numLdloc.GetOrDefault(locVar) + direction;
+ } else if (expr.Code == ILCode.Ldloca) {
+ numLdloca[locVar] = numLdloca.GetOrDefault(locVar) + direction;
+ } else {
+ throw new NotSupportedException(expr.Code.ToString());
+ }
+ }
+ foreach (ILExpression child in expr.Arguments)
+ AnalyzeNode(child, direction);
+ } else {
+ var catchBlock = node as ILTryCatchBlock.CatchBlock;
+ if (catchBlock != null && catchBlock.ExceptionVariable != null) {
+ numStloc[catchBlock.ExceptionVariable] = numStloc.GetOrDefault(catchBlock.ExceptionVariable) + direction;
+ }
+
+ foreach (ILNode child in node.GetChildren())
+ AnalyzeNode(child, direction);
+ }
+ }
+
+ public bool InlineAllVariables()
+ {
+ bool modified = false;
+ ILInlining i = new ILInlining(method);
+ foreach (ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>())
+ modified |= i.InlineAllInBlock(block);
+ return modified;
+ }
+
+ public bool InlineAllInBlock(ILBlock block)
+ {
+ bool modified = false;
+ List<ILNode> body = block.Body;
+ if (block is ILTryCatchBlock.CatchBlock && body.Count > 1) {
+ ILVariable v = ((ILTryCatchBlock.CatchBlock)block).ExceptionVariable;
+ if (v != null && v.IsGenerated) {
+ if (numLdloca.GetOrDefault(v) == 0 && numStloc.GetOrDefault(v) == 1 && numLdloc.GetOrDefault(v) == 1) {
+ ILVariable v2;
+ ILExpression ldException;
+ if (body[0].Match(ILCode.Stloc, out v2, out ldException) && ldException.MatchLdloc(v)) {
+ body.RemoveAt(0);
+ ((ILTryCatchBlock.CatchBlock)block).ExceptionVariable = v2;
+ modified = true;
+ }
+ }
+ }
+ }
+ for(int i = 0; i < body.Count - 1;) {
+ ILVariable locVar;
+ ILExpression expr;
+ if (body[i].Match(ILCode.Stloc, out locVar, out expr) && InlineOneIfPossible(block.Body, i, aggressive: false)) {
+ modified = true;
+ i = Math.Max(0, i - 1); // Go back one step
+ } else {
+ i++;
+ }
+ }
+ foreach(ILBasicBlock bb in body.OfType<ILBasicBlock>()) {
+ modified |= InlineAllInBasicBlock(bb);
+ }
+ return modified;
+ }
+
+ public bool InlineAllInBasicBlock(ILBasicBlock bb)
+ {
+ bool modified = false;
+ List<ILNode> body = bb.Body;
+ for(int i = 0; i < body.Count;) {
+ ILVariable locVar;
+ ILExpression expr;
+ if (body[i].Match(ILCode.Stloc, out locVar, out expr) && InlineOneIfPossible(bb.Body, i, aggressive: false)) {
+ modified = true;
+ i = Math.Max(0, i - 1); // Go back one step
+ } else {
+ i++;
+ }
+ }
+ return modified;
+ }
+
+ /// <summary>
+ /// Inlines instructions before pos into block.Body[pos].
+ /// </summary>
+ /// <returns>The number of instructions that were inlined.</returns>
+ public int InlineInto(List<ILNode> body, int pos, bool aggressive)
+ {
+ if (pos >= body.Count)
+ return 0;
+ int count = 0;
+ while (--pos >= 0) {
+ ILExpression expr = body[pos] as ILExpression;
+ if (expr == null || expr.Code != ILCode.Stloc)
+ break;
+ if (InlineOneIfPossible(body, pos, aggressive))
+ count++;
+ else
+ break;
+ }
+ return count;
+ }
+
+ /// <summary>
+ /// Aggressively inlines the stloc instruction at block.Body[pos] into the next instruction, if possible.
+ /// If inlining was possible; we will continue to inline (non-aggressively) into the the combined instruction.
+ /// </summary>
+ /// <remarks>
+ /// After the operation, pos will point to the new combined instruction.
+ /// </remarks>
+ public bool InlineIfPossible(List<ILNode> body, ref int pos)
+ {
+ if (InlineOneIfPossible(body, pos, true)) {
+ pos -= InlineInto(body, pos, false);
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Inlines the stloc instruction at block.Body[pos] into the next instruction, if possible.
+ /// </summary>
+ public bool InlineOneIfPossible(List<ILNode> body, int pos, bool aggressive)
+ {
+ ILVariable v;
+ ILExpression inlinedExpression;
+ if (body[pos].Match(ILCode.Stloc, out v, out inlinedExpression) && !v.IsPinned) {
+ if (InlineIfPossible(v, inlinedExpression, body.ElementAtOrDefault(pos+1), aggressive)) {
+ // Assign the ranges of the stloc instruction:
+ inlinedExpression.ILRanges.AddRange(((ILExpression)body[pos]).ILRanges);
+ // Remove the stloc instruction:
+ body.RemoveAt(pos);
+ return true;
+ } else if (numLdloc.GetOrDefault(v) == 0 && numLdloca.GetOrDefault(v) == 0) {
+ // The variable is never loaded
+ if (inlinedExpression.HasNoSideEffects()) {
+ // Remove completely
+ AnalyzeNode(body[pos], -1);
+ body.RemoveAt(pos);
+ return true;
+ } else if (inlinedExpression.CanBeExpressionStatement() && v.IsGenerated) {
+ // Assign the ranges of the stloc instruction:
+ inlinedExpression.ILRanges.AddRange(((ILExpression)body[pos]).ILRanges);
+ // Remove the stloc, but keep the inner expression
+ body[pos] = inlinedExpression;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Inlines 'expr' into 'next', if possible.
+ /// </summary>
+ bool InlineIfPossible(ILVariable v, ILExpression inlinedExpression, ILNode next, bool aggressive)
+ {
+ // ensure the variable is accessed only a single time
+ if (numStloc.GetOrDefault(v) != 1)
+ return false;
+ int ldloc = numLdloc.GetOrDefault(v);
+ if (ldloc > 1 || ldloc + numLdloca.GetOrDefault(v) != 1)
+ return false;
+
+ if (next is ILCondition)
+ next = ((ILCondition)next).Condition;
+ else if (next is ILWhileLoop)
+ next = ((ILWhileLoop)next).Condition;
+
+ ILExpression parent;
+ int pos;
+ if (FindLoadInNext(next as ILExpression, v, inlinedExpression, out parent, out pos) == true) {
+ if (ldloc == 0) {
+ if (!IsGeneratedValueTypeTemporary((ILExpression)next, parent, pos, v, inlinedExpression))
+ return false;
+ } else {
+ if (!aggressive && !v.IsGenerated && !NonAggressiveInlineInto((ILExpression)next, parent, inlinedExpression))
+ return false;
+ }
+
+ // Assign the ranges of the ldloc instruction:
+ inlinedExpression.ILRanges.AddRange(parent.Arguments[pos].ILRanges);
+
+ if (ldloc == 0) {
+ // it was an ldloca instruction, so we need to use the pseudo-opcode 'addressof' so that the types
+ // comes out correctly
+ parent.Arguments[pos] = new ILExpression(ILCode.AddressOf, null, inlinedExpression);
+ } else {
+ parent.Arguments[pos] = inlinedExpression;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Is this a temporary variable generated by the C# compiler for instance method calls on value type values
+ /// </summary>
+ /// <param name="next">The next top-level expression</param>
+ /// <param name="parent">The direct parent of the load within 'next'</param>
+ /// <param name="pos">Index of the load within 'parent'</param>
+ /// <param name="v">The variable being inlined.</param>
+ /// <param name="inlinedExpression">The expression being inlined</param>
+ bool IsGeneratedValueTypeTemporary(ILExpression next, ILExpression parent, int pos, ILVariable v, ILExpression inlinedExpression)
+ {
+ if (pos == 0 && v.Type != null && v.Type.IsValueType) {
+ // Inlining a value type variable is allowed only if the resulting code will maintain the semantics
+ // that the method is operating on a copy.
+ // Thus, we have to disallow inlining of other locals, fields, array elements, dereferenced pointers
+ switch (inlinedExpression.Code) {
+ case ILCode.Ldloc:
+ case ILCode.Stloc:
+ case ILCode.CompoundAssignment:
+ case ILCode.Ldelem_Any:
+ case ILCode.Ldelem_I:
+ case ILCode.Ldelem_I1:
+ case ILCode.Ldelem_I2:
+ case ILCode.Ldelem_I4:
+ case ILCode.Ldelem_I8:
+ case ILCode.Ldelem_R4:
+ case ILCode.Ldelem_R8:
+ case ILCode.Ldelem_Ref:
+ case ILCode.Ldelem_U1:
+ case ILCode.Ldelem_U2:
+ case ILCode.Ldelem_U4:
+ case ILCode.Ldobj:
+ case ILCode.Ldind_Ref:
+ return false;
+ case ILCode.Ldfld:
+ case ILCode.Stfld:
+ case ILCode.Ldsfld:
+ case ILCode.Stsfld:
+ // allow inlining field access only if it's a readonly field
+ FieldDefinition f = ((FieldReference)inlinedExpression.Operand).Resolve();
+ if (!(f != null && f.IsInitOnly))
+ return false;
+ break;
+ case ILCode.Call:
+ case ILCode.CallGetter:
+ // inlining runs both before and after IntroducePropertyAccessInstructions,
+ // so we have to handle both 'call' and 'callgetter'
+ MethodReference mr = (MethodReference)inlinedExpression.Operand;
+ // ensure that it's not an multi-dimensional array getter
+ if (mr.DeclaringType is ArrayType)
+ return false;
+ goto case ILCode.Callvirt;
+ case ILCode.Callvirt:
+ case ILCode.CallvirtGetter:
+ // don't inline foreach loop variables:
+ mr = (MethodReference)inlinedExpression.Operand;
+ if (mr.Name == "get_Current" && mr.HasThis)
+ return false;
+ break;
+ case ILCode.Castclass:
+ case ILCode.Unbox_Any:
+ // These are valid, but might occur as part of a foreach loop variable.
+ ILExpression arg = inlinedExpression.Arguments[0];
+ if (arg.Code == ILCode.CallGetter || arg.Code == ILCode.CallvirtGetter || arg.Code == ILCode.Call || arg.Code == ILCode.Callvirt) {
+ mr = (MethodReference)arg.Operand;
+ if (mr.Name == "get_Current" && mr.HasThis)
+ return false; // looks like a foreach loop variable, so don't inline it
+ }
+ break;
+ }
+
+ // inline the compiler-generated variable that are used when accessing a member on a value type:
+ switch (parent.Code) {
+ case ILCode.Call:
+ case ILCode.CallGetter:
+ case ILCode.CallSetter:
+ case ILCode.Callvirt:
+ case ILCode.CallvirtGetter:
+ case ILCode.CallvirtSetter:
+ MethodReference mr = (MethodReference)parent.Operand;
+ return mr.HasThis;
+ case ILCode.Stfld:
+ case ILCode.Ldfld:
+ case ILCode.Ldflda:
+ case ILCode.Await:
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Determines whether a variable should be inlined in non-aggressive mode, even though it is not a generated variable.
+ /// </summary>
+ /// <param name="next">The next top-level expression</param>
+ /// <param name="parent">The direct parent of the load within 'next'</param>
+ /// <param name="inlinedExpression">The expression being inlined</param>
+ bool NonAggressiveInlineInto(ILExpression next, ILExpression parent, ILExpression inlinedExpression)
+ {
+ if (inlinedExpression.Code == ILCode.DefaultValue)
+ return true;
+
+ switch (next.Code) {
+ case ILCode.Ret:
+ case ILCode.Brtrue:
+ return parent == next;
+ case ILCode.Switch:
+ return parent == next || (parent.Code == ILCode.Sub && parent == next.Arguments[0]);
+ default:
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether 'expressionBeingMoved' can be inlined into 'expr'.
+ /// </summary>
+ public bool CanInlineInto(ILExpression expr, ILVariable v, ILExpression expressionBeingMoved)
+ {
+ ILExpression parent;
+ int pos;
+ return FindLoadInNext(expr, v, expressionBeingMoved, out parent, out pos) == true;
+ }
+
+ /// <summary>
+ /// Finds the position to inline to.
+ /// </summary>
+ /// <returns>true = found; false = cannot continue search; null = not found</returns>
+ bool? FindLoadInNext(ILExpression expr, ILVariable v, ILExpression expressionBeingMoved, out ILExpression parent, out int pos)
+ {
+ parent = null;
+ pos = 0;
+ if (expr == null)
+ return false;
+ for (int i = 0; i < expr.Arguments.Count; i++) {
+ // Stop when seeing an opcode that does not guarantee that its operands will be evaluated.
+ // Inlining in that case might result in the inlined expresion not being evaluted.
+ if (i == 1 && (expr.Code == ILCode.LogicAnd || expr.Code == ILCode.LogicOr || expr.Code == ILCode.TernaryOp || expr.Code == ILCode.NullCoalescing))
+ return false;
+
+ ILExpression arg = expr.Arguments[i];
+
+ if ((arg.Code == ILCode.Ldloc || arg.Code == ILCode.Ldloca) && arg.Operand == v) {
+ parent = expr;
+ pos = i;
+ return true;
+ }
+ bool? r = FindLoadInNext(arg, v, expressionBeingMoved, out parent, out pos);
+ if (r != null)
+ return r;
+ }
+ if (IsSafeForInlineOver(expr, expressionBeingMoved))
+ return null; // continue searching
+ else
+ return false; // abort, inlining not possible
+ }
+
+ /// <summary>
+ /// Determines whether it is safe to move 'expressionBeingMoved' past 'expr'
+ /// </summary>
+ bool IsSafeForInlineOver(ILExpression expr, ILExpression expressionBeingMoved)
+ {
+ switch (expr.Code) {
+ case ILCode.Ldloc:
+ ILVariable loadedVar = (ILVariable)expr.Operand;
+ if (numLdloca.GetOrDefault(loadedVar) != 0) {
+ // abort, inlining is not possible
+ return false;
+ }
+ foreach (ILExpression potentialStore in expressionBeingMoved.GetSelfAndChildrenRecursive<ILExpression>()) {
+ if (potentialStore.Code == ILCode.Stloc && potentialStore.Operand == loadedVar)
+ return false;
+ }
+ // the expression is loading a non-forbidden variable
+ return true;
+ case ILCode.Ldloca:
+ case ILCode.Ldflda:
+ case ILCode.Ldsflda:
+ case ILCode.Ldelema:
+ case ILCode.AddressOf:
+ case ILCode.ValueOf:
+ case ILCode.NullableOf:
+ // address-loading instructions are safe if their arguments are safe
+ foreach (ILExpression arg in expr.Arguments) {
+ if (!IsSafeForInlineOver(arg, expressionBeingMoved))
+ return false;
+ }
+ return true;
+ default:
+ // instructions with no side-effects are safe (except for Ldloc and Ldloca which are handled separately)
+ return expr.HasNoSideEffects();
+ }
+ }
+
+ /// <summary>
+ /// Runs a very simple form of copy propagation.
+ /// Copy propagation is used in two cases:
+ /// 1) assignments from arguments to local variables
+ /// If the target variable is assigned to only once (so always is that argument) and the argument is never changed (no ldarga/starg),
+ /// then we can replace the variable with the argument.
+ /// 2) assignments of address-loading instructions to local variables
+ /// </summary>
+ public void CopyPropagation()
+ {
+ foreach (ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
+ for (int i = 0; i < block.Body.Count; i++) {
+ ILVariable v;
+ ILExpression copiedExpr;
+ if (block.Body[i].Match(ILCode.Stloc, out v, out copiedExpr)
+ && !v.IsParameter && numStloc.GetOrDefault(v) == 1 && numLdloca.GetOrDefault(v) == 0
+ && CanPerformCopyPropagation(copiedExpr, v))
+ {
+ // un-inline the arguments of the ldArg instruction
+ ILVariable[] uninlinedArgs = new ILVariable[copiedExpr.Arguments.Count];
+ for (int j = 0; j < uninlinedArgs.Length; j++) {
+ uninlinedArgs[j] = new ILVariable { IsGenerated = true, Name = v.Name + "_cp_" + j };
+ block.Body.Insert(i++, new ILExpression(ILCode.Stloc, uninlinedArgs[j], copiedExpr.Arguments[j]));
+ }
+
+ // perform copy propagation:
+ foreach (var expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
+ if (expr.Code == ILCode.Ldloc && expr.Operand == v) {
+ expr.Code = copiedExpr.Code;
+ expr.Operand = copiedExpr.Operand;
+ for (int j = 0; j < uninlinedArgs.Length; j++) {
+ expr.Arguments.Add(new ILExpression(ILCode.Ldloc, uninlinedArgs[j]));
+ }
+ }
+ }
+
+ block.Body.RemoveAt(i);
+ if (uninlinedArgs.Length > 0) {
+ // if we un-inlined stuff; we need to update the usage counters
+ AnalyzeMethod();
+ }
+ InlineInto(block.Body, i, aggressive: false); // maybe inlining gets possible after the removal of block.Body[i]
+ i -= uninlinedArgs.Length + 1;
+ }
+ }
+ }
+ }
+
+ bool CanPerformCopyPropagation(ILExpression expr, ILVariable copyVariable)
+ {
+ switch (expr.Code) {
+ case ILCode.Ldloca:
+ case ILCode.Ldelema:
+ case ILCode.Ldflda:
+ case ILCode.Ldsflda:
+ // All address-loading instructions always return the same value for a given operand/argument combination,
+ // so they can be safely copied.
+ return true;
+ case ILCode.Ldloc:
+ ILVariable v = (ILVariable)expr.Operand;
+ if (v.IsParameter) {
+ // Parameters can be copied only if they aren't assigned to (directly or indirectly via ldarga)
+ return numLdloca.GetOrDefault(v) == 0 && numStloc.GetOrDefault(v) == 0;
+ } else {
+ // Variables are be copied only if both they and the target copy variable are generated,
+ // and if the variable has only a single assignment
+ return v.IsGenerated && copyVariable.IsGenerated && numLdloca.GetOrDefault(v) == 0 && numStloc.GetOrDefault(v) == 1;
+ }
+ default:
+ return false;
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs b/ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs
new file mode 100644
index 00000000..4a4a8138
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs
@@ -0,0 +1,543 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ /// <summary>
+ /// IL AST transformation that introduces array, object and collection initializers.
+ /// </summary>
+ partial class ILAstOptimizer
+ {
+ #region Array Initializers
+ bool TransformArrayInitializers(List<ILNode> body, ILExpression expr, int pos)
+ {
+ ILVariable v, v3;
+ ILExpression newarrExpr;
+ TypeReference elementType;
+ ILExpression lengthExpr;
+ int arrayLength;
+ if (expr.Match(ILCode.Stloc, out v, out newarrExpr) &&
+ newarrExpr.Match(ILCode.Newarr, out elementType, out lengthExpr) &&
+ lengthExpr.Match(ILCode.Ldc_I4, out arrayLength) &&
+ arrayLength > 0) {
+ ILExpression[] newArr;
+ int initArrayPos;
+ if (ForwardScanInitializeArrayRuntimeHelper(body, pos + 1, v, elementType, arrayLength, out newArr, out initArrayPos)) {
+ var arrayType = new ArrayType(elementType, 1);
+ arrayType.Dimensions[0] = new ArrayDimension(0, arrayLength);
+ body[pos] = new ILExpression(ILCode.Stloc, v, new ILExpression(ILCode.InitArray, arrayType, newArr));
+ body.RemoveAt(initArrayPos);
+ }
+ // Put in a limit so that we don't consume too much memory if the code allocates a huge array
+ // and populates it extremely sparsly. However, 255 "null" elements in a row actually occur in the Mono C# compiler!
+ const int maxConsecutiveDefaultValueExpressions = 300;
+ List<ILExpression> operands = new List<ILExpression>();
+ int numberOfInstructionsToRemove = 0;
+ for (int j = pos + 1; j < body.Count; j++) {
+ ILExpression nextExpr = body[j] as ILExpression;
+ int arrayPos;
+ if (nextExpr != null &&
+ nextExpr.Code.IsStoreToArray() &&
+ nextExpr.Arguments[0].Match(ILCode.Ldloc, out v3) &&
+ v == v3 &&
+ nextExpr.Arguments[1].Match(ILCode.Ldc_I4, out arrayPos) &&
+ arrayPos >= operands.Count &&
+ arrayPos <= operands.Count + maxConsecutiveDefaultValueExpressions &&
+ !nextExpr.Arguments[2].ContainsReferenceTo(v3))
+ {
+ while (operands.Count < arrayPos)
+ operands.Add(new ILExpression(ILCode.DefaultValue, elementType));
+ operands.Add(nextExpr.Arguments[2]);
+ numberOfInstructionsToRemove++;
+ } else {
+ break;
+ }
+ }
+ if (operands.Count == arrayLength) {
+ var arrayType = new ArrayType(elementType, 1);
+ arrayType.Dimensions[0] = new ArrayDimension(0, arrayLength);
+ expr.Arguments[0] = new ILExpression(ILCode.InitArray, arrayType, operands);
+ body.RemoveRange(pos + 1, numberOfInstructionsToRemove);
+
+ new ILInlining(method).InlineIfPossible(body, ref pos);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool TransformMultidimensionalArrayInitializers(List<ILNode> body, ILExpression expr, int pos)
+ {
+ ILVariable v;
+ ILExpression newarrExpr;
+ MethodReference ctor;
+ List<ILExpression> ctorArgs;
+ ArrayType arrayType;
+ if (expr.Match(ILCode.Stloc, out v, out newarrExpr) &&
+ newarrExpr.Match(ILCode.Newobj, out ctor, out ctorArgs) &&
+ (arrayType = (ctor.DeclaringType as ArrayType)) != null &&
+ arrayType.Rank == ctorArgs.Count) {
+ // Clone the type, so we can muck about with the Dimensions
+ arrayType = new ArrayType(arrayType.ElementType, arrayType.Rank);
+ var arrayLengths = new int[arrayType.Rank];
+ for (int i = 0; i < arrayType.Rank; i++) {
+ if (!ctorArgs[i].Match(ILCode.Ldc_I4, out arrayLengths[i])) return false;
+ if (arrayLengths[i] <= 0) return false;
+ arrayType.Dimensions[i] = new ArrayDimension(0, arrayLengths[i]);
+ }
+
+ var totalElements = arrayLengths.Aggregate(1, (t, l) => t * l);
+ ILExpression[] newArr;
+ int initArrayPos;
+ if (ForwardScanInitializeArrayRuntimeHelper(body, pos + 1, v, arrayType, totalElements, out newArr, out initArrayPos)) {
+ body[pos] = new ILExpression(ILCode.Stloc, v, new ILExpression(ILCode.InitArray, arrayType, newArr));
+ body.RemoveAt(initArrayPos);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool ForwardScanInitializeArrayRuntimeHelper(List<ILNode> body, int pos, ILVariable array, TypeReference arrayType, int arrayLength, out ILExpression[] values, out int foundPos)
+ {
+ ILVariable v2;
+ MethodReference methodRef;
+ ILExpression methodArg1;
+ ILExpression methodArg2;
+ FieldReference fieldRef;
+ if (body.ElementAtOrDefault(pos).Match(ILCode.Call, out methodRef, out methodArg1, out methodArg2) &&
+ methodRef.DeclaringType.FullName == "System.Runtime.CompilerServices.RuntimeHelpers" &&
+ methodRef.Name == "InitializeArray" &&
+ methodArg1.Match(ILCode.Ldloc, out v2) &&
+ array == v2 &&
+ methodArg2.Match(ILCode.Ldtoken, out fieldRef))
+ {
+ FieldDefinition fieldDef = fieldRef.ResolveWithinSameModule();
+ if (fieldDef != null && fieldDef.InitialValue != null) {
+ ILExpression[] newArr = new ILExpression[arrayLength];
+ if (DecodeArrayInitializer(arrayType.GetElementType(), fieldDef.InitialValue, newArr))
+ {
+ values = newArr;
+ foundPos = pos;
+ return true;
+ }
+ }
+ }
+ values = null;
+ foundPos = -1;
+ return false;
+ }
+
+ static bool DecodeArrayInitializer(TypeReference elementTypeRef, byte[] initialValue, ILExpression[] output)
+ {
+ TypeCode elementType = TypeAnalysis.GetTypeCode(elementTypeRef);
+ switch (elementType) {
+ case TypeCode.Boolean:
+ case TypeCode.Byte:
+ return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)d[i]);
+ case TypeCode.SByte:
+ return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)unchecked((sbyte)d[i]));
+ case TypeCode.Int16:
+ return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)BitConverter.ToInt16(d, i));
+ case TypeCode.Char:
+ case TypeCode.UInt16:
+ return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)BitConverter.ToUInt16(d, i));
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToInt32);
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToInt64);
+ case TypeCode.Single:
+ return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToSingle);
+ case TypeCode.Double:
+ return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToDouble);
+ case TypeCode.Object:
+ var typeDef = elementTypeRef.ResolveWithinSameModule();
+ if (typeDef != null && typeDef.IsEnum)
+ return DecodeArrayInitializer(typeDef.GetEnumUnderlyingType(), initialValue, output);
+
+ return false;
+ default:
+ return false;
+ }
+ }
+
+ static bool DecodeArrayInitializer<T>(byte[] initialValue, ILExpression[] output, TypeCode elementType, Func<byte[], int, T> decoder)
+ {
+ int elementSize = ElementSizeOf(elementType);
+ if (initialValue.Length < (output.Length * elementSize))
+ return false;
+
+ ILCode code = LoadCodeFor(elementType);
+ for (int i = 0; i < output.Length; i++)
+ output[i] = new ILExpression(code, decoder(initialValue, i * elementSize));
+
+ return true;
+ }
+
+ static ILCode LoadCodeFor(TypeCode elementType)
+ {
+ switch (elementType) {
+ case TypeCode.Boolean:
+ case TypeCode.Byte:
+ case TypeCode.SByte:
+ case TypeCode.Char:
+ case TypeCode.Int16:
+ case TypeCode.UInt16:
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ return ILCode.Ldc_I4;
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ return ILCode.Ldc_I8;
+ case TypeCode.Single:
+ return ILCode.Ldc_R4;
+ case TypeCode.Double:
+ return ILCode.Ldc_R8;
+ default:
+ throw new ArgumentOutOfRangeException("elementType");
+ }
+ }
+
+ static int ElementSizeOf(TypeCode elementType)
+ {
+ switch (elementType) {
+ case TypeCode.Boolean:
+ case TypeCode.Byte:
+ case TypeCode.SByte:
+ return 1;
+ case TypeCode.Char:
+ case TypeCode.Int16:
+ case TypeCode.UInt16:
+ return 2;
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ case TypeCode.Single:
+ return 4;
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ case TypeCode.Double:
+ return 8;
+ default:
+ throw new ArgumentOutOfRangeException("elementType");
+ }
+ }
+ #endregion
+
+ /// <summary>
+ /// Handles both object and collection initializers.
+ /// </summary>
+ bool TransformObjectInitializers(List<ILNode> body, ILExpression expr, int pos)
+ {
+ if (!context.Settings.ObjectOrCollectionInitializers)
+ return false;
+
+ Debug.Assert(body[pos] == expr); // should be called for top-level expressions only
+ ILVariable v;
+ ILExpression newObjExpr;
+ TypeReference newObjType;
+ bool isValueType;
+ MethodReference ctor;
+ List<ILExpression> ctorArgs;
+ if (expr.Match(ILCode.Stloc, out v, out newObjExpr)) {
+ if (newObjExpr.Match(ILCode.Newobj, out ctor, out ctorArgs)) {
+ // v = newObj(ctor, ctorArgs)
+ newObjType = ctor.DeclaringType;
+ isValueType = false;
+ } else if (newObjExpr.Match(ILCode.DefaultValue, out newObjType)) {
+ // v = defaultvalue(type)
+ isValueType = true;
+ } else {
+ return false;
+ }
+ } else if (expr.Match(ILCode.Call, out ctor, out ctorArgs)) {
+ // call(SomeStruct::.ctor, ldloca(v), remainingArgs)
+ if (ctorArgs.Count > 0 && ctorArgs[0].Match(ILCode.Ldloca, out v)) {
+ isValueType = true;
+ newObjType = ctor.DeclaringType;
+ ctorArgs = new List<ILExpression>(ctorArgs);
+ ctorArgs.RemoveAt(0);
+ newObjExpr = new ILExpression(ILCode.Newobj, ctor, ctorArgs);
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ if (newObjType.IsValueType != isValueType)
+ return false;
+
+ int originalPos = pos;
+
+ // don't use object initializer syntax for closures
+ if (Ast.Transforms.DelegateConstruction.IsPotentialClosure(context, newObjType.ResolveWithinSameModule()))
+ return false;
+
+ ILExpression initializer = ParseObjectInitializer(body, ref pos, v, newObjExpr, IsCollectionType(newObjType), isValueType);
+
+ if (initializer.Arguments.Count == 1) // only newobj argument, no initializer elements
+ return false;
+ int totalElementCount = pos - originalPos - 1; // totalElementCount: includes elements from nested collections
+ Debug.Assert(totalElementCount >= initializer.Arguments.Count - 1);
+
+ // Verify that we can inline 'v' into the next instruction:
+
+ if (pos >= body.Count)
+ return false; // reached end of block, but there should be another instruction which consumes the initialized object
+
+ ILInlining inlining = new ILInlining(method);
+ if (isValueType) {
+ // one ldloc for the use of the initialized object
+ if (inlining.numLdloc.GetOrDefault(v) != 1)
+ return false;
+ // one ldloca for each initializer argument, and also for the ctor call (if it exists)
+ if (inlining.numLdloca.GetOrDefault(v) != totalElementCount + (expr.Code == ILCode.Call ? 1 : 0))
+ return false;
+ // one stloc for the initial store (if no ctor call was used)
+ if (inlining.numStloc.GetOrDefault(v) != (expr.Code == ILCode.Call ? 0 : 1))
+ return false;
+ } else {
+ // one ldloc for each initializer argument, and another ldloc for the use of the initialized object
+ if (inlining.numLdloc.GetOrDefault(v) != totalElementCount + 1)
+ return false;
+ if (!(inlining.numStloc.GetOrDefault(v) == 1 && inlining.numLdloca.GetOrDefault(v) == 0))
+ return false;
+ }
+ ILExpression nextExpr = body[pos] as ILExpression;
+ if (!inlining.CanInlineInto(nextExpr, v, initializer))
+ return false;
+
+ if (expr.Code == ILCode.Stloc) {
+ expr.Arguments[0] = initializer;
+ } else {
+ Debug.Assert(expr.Code == ILCode.Call);
+ expr.Code = ILCode.Stloc;
+ expr.Operand = v;
+ expr.Arguments.Clear();
+ expr.Arguments.Add(initializer);
+ }
+ // remove all the instructions that were pulled into the initializer
+ body.RemoveRange(originalPos + 1, pos - originalPos - 1);
+
+ // now that we know that it's an object initializer, change all the first arguments to 'InitializedObject'
+ ChangeFirstArgumentToInitializedObject(initializer);
+
+ inlining = new ILInlining(method);
+ inlining.InlineIfPossible(body, ref originalPos);
+
+ return true;
+ }
+
+ /// <summary>
+ /// Gets whether the type supports collection initializers.
+ /// </summary>
+ static bool IsCollectionType(TypeReference tr)
+ {
+ if (tr == null)
+ return false;
+ TypeDefinition td = tr.Resolve();
+ while (td != null) {
+ if (td.Interfaces.Any(intf => intf.Name == "IEnumerable" && intf.Namespace == "System.Collections"))
+ return true;
+ td = td.BaseType != null ? td.BaseType.Resolve() : null;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Gets whether 'expr' represents a setter in an object initializer.
+ /// ('CallvirtSetter(Property, v, value)')
+ /// </summary>
+ static bool IsSetterInObjectInitializer(ILExpression expr)
+ {
+ if (expr == null)
+ return false;
+ if (expr.Code == ILCode.CallvirtSetter || expr.Code == ILCode.CallSetter || expr.Code == ILCode.Stfld) {
+ return expr.Arguments.Count == 2;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Gets whether 'expr' represents the invocation of an 'Add' method in a collection initializer.
+ /// </summary>
+ static bool IsAddMethodCall(ILExpression expr)
+ {
+ MethodReference addMethod;
+ List<ILExpression> args;
+ if (expr.Match(ILCode.Callvirt, out addMethod, out args) || expr.Match(ILCode.Call, out addMethod, out args)) {
+ if (addMethod.Name == "Add" && addMethod.HasThis) {
+ return args.Count >= 2;
+ }
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Parses an object initializer.
+ /// </summary>
+ /// <param name="body">ILAst block</param>
+ /// <param name="pos">
+ /// Input: position of the instruction assigning to 'v'.
+ /// Output: first position after the object initializer
+ /// </param>
+ /// <param name="v">The variable that holds the object being initialized</param>
+ /// <param name="newObjExpr">The newobj instruction</param>
+ /// <returns>InitObject instruction</returns>
+ ILExpression ParseObjectInitializer(List<ILNode> body, ref int pos, ILVariable v, ILExpression newObjExpr, bool isCollection, bool isValueType)
+ {
+ // Take care not to modify any existing ILExpressions in here.
+ // We just construct new ones around the old ones, any modifications must wait until the whole
+ // object/collection initializer was analyzed.
+ ILExpression objectInitializer = new ILExpression(isCollection ? ILCode.InitCollection : ILCode.InitObject, null, newObjExpr);
+ List<ILExpression> initializerStack = new List<ILExpression>();
+ initializerStack.Add(objectInitializer);
+ while (++pos < body.Count) {
+ ILExpression nextExpr = body[pos] as ILExpression;
+ if (IsSetterInObjectInitializer(nextExpr)) {
+ if (!AdjustInitializerStack(initializerStack, nextExpr.Arguments[0], v, false, isValueType)) {
+ CleanupInitializerStackAfterFailedAdjustment(initializerStack);
+ break;
+ }
+ initializerStack[initializerStack.Count - 1].Arguments.Add(nextExpr);
+ } else if (IsAddMethodCall(nextExpr)) {
+ if (!AdjustInitializerStack(initializerStack, nextExpr.Arguments[0], v, true, isValueType)) {
+ CleanupInitializerStackAfterFailedAdjustment(initializerStack);
+ break;
+ }
+ initializerStack[initializerStack.Count - 1].Arguments.Add(nextExpr);
+ } else {
+ // can't match any more initializers: end of object initializer
+ break;
+ }
+ }
+ return objectInitializer;
+ }
+
+ static bool AdjustInitializerStack(List<ILExpression> initializerStack, ILExpression argument, ILVariable v, bool isCollection, bool isValueType)
+ {
+ // Argument is of the form 'getter(getter(...(v)))'
+ // Unpack it into a list of getters:
+ List<ILExpression> getters = new List<ILExpression>();
+ while (argument.Code == ILCode.CallvirtGetter || argument.Code == ILCode.CallGetter || argument.Code == ILCode.Ldfld) {
+ getters.Add(argument);
+ if (argument.Arguments.Count != 1)
+ return false;
+ argument = argument.Arguments[0];
+ }
+ // Ensure that the final argument is 'v'
+ if (isValueType) {
+ ILVariable loadedVar;
+ if (!(argument.Match(ILCode.Ldloca, out loadedVar) && loadedVar == v))
+ return false;
+ } else {
+ if (!argument.MatchLdloc(v))
+ return false;
+ }
+ // Now compare the getters with those that are currently active on the initializer stack:
+ int i;
+ for (i = 1; i <= Math.Min(getters.Count, initializerStack.Count - 1); i++) {
+ ILExpression g1 = initializerStack[i].Arguments[0]; // getter stored in initializer
+ ILExpression g2 = getters[getters.Count - i]; // matching getter from argument
+ if (g1.Operand != g2.Operand) {
+ // operands differ, so we abort the comparison
+ break;
+ }
+ }
+ // Remove all initializers from the stack that were not matched with one from the argument:
+ initializerStack.RemoveRange(i, initializerStack.Count - i);
+ // Now create new initializers for the remaining arguments:
+ for (; i <= getters.Count; i++) {
+ ILExpression g = getters[getters.Count - i];
+ MemberReference mr = (MemberReference)g.Operand;
+ TypeReference returnType;
+ if (mr is FieldReference)
+ returnType = TypeAnalysis.GetFieldType((FieldReference)mr);
+ else
+ returnType = TypeAnalysis.SubstituteTypeArgs(((MethodReference)mr).ReturnType, mr);
+
+ ILExpression nestedInitializer = new ILExpression(
+ IsCollectionType(returnType) ? ILCode.InitCollection : ILCode.InitObject,
+ null, g);
+ // add new initializer to its parent:
+ ILExpression parentInitializer = initializerStack[initializerStack.Count - 1];
+ if (parentInitializer.Code == ILCode.InitCollection) {
+ // can't add children to collection initializer
+ if (parentInitializer.Arguments.Count == 1) {
+ // convert empty collection initializer to object initializer
+ parentInitializer.Code = ILCode.InitObject;
+ } else {
+ return false;
+ }
+ }
+ parentInitializer.Arguments.Add(nestedInitializer);
+ initializerStack.Add(nestedInitializer);
+ }
+ ILExpression lastInitializer = initializerStack[initializerStack.Count - 1];
+ if (isCollection) {
+ return lastInitializer.Code == ILCode.InitCollection;
+ } else {
+ if (lastInitializer.Code == ILCode.InitCollection) {
+ if (lastInitializer.Arguments.Count == 1) {
+ // convert empty collection initializer to object initializer
+ lastInitializer.Code = ILCode.InitObject;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return true;
+ }
+ }
+ }
+
+ static void CleanupInitializerStackAfterFailedAdjustment(List<ILExpression> initializerStack)
+ {
+ // There might be empty nested initializers left over; so we'll remove those:
+ while (initializerStack.Count > 1 && initializerStack[initializerStack.Count - 1].Arguments.Count == 1) {
+ ILExpression parent = initializerStack[initializerStack.Count - 2];
+ Debug.Assert(parent.Arguments.Last() == initializerStack[initializerStack.Count - 1]);
+ parent.Arguments.RemoveAt(parent.Arguments.Count - 1);
+ initializerStack.RemoveAt(initializerStack.Count - 1);
+ }
+ }
+
+ static void ChangeFirstArgumentToInitializedObject(ILExpression initializer)
+ {
+ // Go through all elements in the initializer (so skip the newobj-instr. at the start)
+ for (int i = 1; i < initializer.Arguments.Count; i++) {
+ ILExpression element = initializer.Arguments[i];
+ if (element.Code == ILCode.InitCollection || element.Code == ILCode.InitObject) {
+ // nested collection/object initializer
+ ILExpression getCollection = element.Arguments[0];
+ getCollection.Arguments[0] = new ILExpression(ILCode.InitializedObject, null);
+ ChangeFirstArgumentToInitializedObject(element); // handle the collection elements
+ } else {
+ element.Arguments[0] = new ILExpression(ILCode.InitializedObject, null);
+ }
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/ILAst/LiftedOperators.cs b/ICSharpCode.Decompiler/ILAst/LiftedOperators.cs
new file mode 100644
index 00000000..9edeac74
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/LiftedOperators.cs
@@ -0,0 +1,528 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ partial class ILAstOptimizer
+ {
+ bool SimplifyLiftedOperators(List<ILNode> body, ILExpression expr, int pos)
+ {
+ if (!new PatternMatcher(typeSystem).SimplifyLiftedOperators(expr)) return false;
+
+ var inlining = new ILInlining(method);
+ while (--pos >= 0 && inlining.InlineIfPossible(body, ref pos)) ;
+
+ return true;
+ }
+
+ sealed class PatternMatcher
+ {
+ readonly TypeSystem typeSystem;
+ public PatternMatcher(TypeSystem typeSystem)
+ {
+ this.typeSystem = typeSystem;
+ }
+
+ public bool SimplifyLiftedOperators(ILExpression expr)
+ {
+ if (Simplify(expr)) return true;
+
+ bool modified = false;
+ foreach (var a in expr.Arguments)
+ modified |= SimplifyLiftedOperators(a);
+ return modified;
+ }
+
+ abstract class Pattern
+ {
+ public readonly Pattern[] Arguments;
+
+ protected Pattern(Pattern[] arguments)
+ {
+ Arguments = arguments;
+ }
+
+ public virtual bool Match(PatternMatcher pm, ILExpression e)
+ {
+ if (e.Arguments.Count != Arguments.Length || e.Prefixes != null) return false;
+ for (int i = 0; i < Arguments.Length; i++)
+ if (!Arguments[i].Match(pm, e.Arguments[i])) return false;
+ return true;
+ }
+
+ public virtual ILExpression BuildNew(PatternMatcher pm)
+ {
+ throw new NotSupportedException();
+ }
+
+ public static Pattern operator &(Pattern a, Pattern b)
+ {
+ return new ILPattern(ILCode.LogicAnd, a, b);
+ }
+
+ public static Pattern operator |(Pattern a, Pattern b)
+ {
+ return new ILPattern(ILCode.LogicOr, a, b);
+ }
+
+ public static Pattern operator !(Pattern a)
+ {
+ return new ILPattern(ILCode.LogicNot, a);
+ }
+ }
+
+ sealed class ILPattern : Pattern
+ {
+ readonly ILCode code;
+
+ public ILPattern(ILCode code, params Pattern[] arguments)
+ : base(arguments)
+ {
+ this.code = code;
+ }
+
+ public override bool Match(PatternMatcher pm, ILExpression e)
+ {
+ return e.Code == code && base.Match(pm, e);
+ }
+
+ public override ILExpression BuildNew(PatternMatcher pm)
+ {
+ var args = new ILExpression[Arguments.Length];
+ for (int i = 0; i < args.Length; i++) args[i] = Arguments[i].BuildNew(pm);
+ TypeReference t = null;
+ switch (code) {
+ case ILCode.Ceq:
+ case ILCode.Cne:
+ t = pm.typeSystem.Boolean;
+ break;
+ case ILCode.NullCoalescing:
+ t = args[1].InferredType;
+ break;
+ }
+ return new ILExpression(code, null, args) { InferredType = t };
+ }
+ }
+
+ sealed class MethodPattern : Pattern
+ {
+ readonly ILCode code;
+ readonly string method;
+
+ public MethodPattern(ILCode code, string method, params Pattern[] arguments)
+ : base(arguments)
+ {
+ this.code = code;
+ this.method = method;
+ }
+
+ public override bool Match(PatternMatcher pm, ILExpression e)
+ {
+ if (e.Code != code) return false;
+ var m = (MethodReference)e.Operand;
+ return m.Name == method && TypeAnalysis.IsNullableType(m.DeclaringType) && base.Match(pm, e);
+ }
+ }
+
+ enum OperatorType
+ {
+ Equality, InEquality, Comparison, Other
+ }
+
+ sealed class OperatorPattern : Pattern
+ {
+ OperatorType type;
+ bool simple;
+
+ public OperatorPattern() : base(null) { }
+
+ public OperatorPattern(OperatorType type, bool simple)
+ : this()
+ {
+ this.type = type;
+ this.simple = simple;
+ }
+
+ public override bool Match(PatternMatcher pm, ILExpression e)
+ {
+ switch (e.Code) {
+ case ILCode.Ceq:
+ if (type != OperatorType.Equality) return false;
+ break;
+ case ILCode.Cne:
+ if (type != OperatorType.InEquality) return false;
+ break;
+ case ILCode.Cgt:
+ case ILCode.Cgt_Un:
+ case ILCode.Cge:
+ case ILCode.Cge_Un:
+ case ILCode.Clt:
+ case ILCode.Clt_Un:
+ case ILCode.Cle:
+ case ILCode.Cle_Un:
+ if (type != OperatorType.Comparison) return false;
+ break;
+ case ILCode.Add:
+ case ILCode.Add_Ovf:
+ case ILCode.Add_Ovf_Un:
+ case ILCode.Sub:
+ case ILCode.Sub_Ovf:
+ case ILCode.Sub_Ovf_Un:
+ case ILCode.Mul:
+ case ILCode.Mul_Ovf:
+ case ILCode.Mul_Ovf_Un:
+ case ILCode.Div:
+ case ILCode.Div_Un:
+ case ILCode.Rem:
+ case ILCode.Rem_Un:
+ case ILCode.And:
+ case ILCode.Or:
+ case ILCode.Xor:
+ case ILCode.Shl:
+ case ILCode.Shr:
+ case ILCode.Shr_Un:
+ case ILCode.Not:
+ case ILCode.Neg:
+ case ILCode.LogicNot:
+ if (type != OperatorType.Other) return false;
+ break;
+ case ILCode.Call:
+ var m = e.Operand as MethodReference;
+ if (m == null || m.HasThis || !m.HasParameters || e.Arguments.Count > 2 || !IsCustomOperator(m.Name)) return false;
+ break;
+ default: return false;
+ }
+ if (pm.Operator != null) throw new InvalidOperationException();
+ pm.Operator = e;
+
+ var a0 = e.Arguments[0];
+ if (!simple) return VariableAGetValueOrDefault.Match(pm, a0) && VariableBGetValueOrDefault.Match(pm, e.Arguments[1]);
+ if (e.Arguments.Count == 1) return VariableAGetValueOrDefault.Match(pm, a0);
+ if (VariableAGetValueOrDefault.Match(pm, a0)) {
+ pm.SimpleOperand = e.Arguments[1];
+ pm.SimpleLeftOperand = false;
+ return true;
+ }
+ if (VariableAGetValueOrDefault.Match(pm, e.Arguments[1])) {
+ pm.SimpleOperand = a0;
+ pm.SimpleLeftOperand = true;
+ return true;
+ }
+ return false;
+ }
+
+ bool IsCustomOperator(string s)
+ {
+ switch (type) {
+ case OperatorType.Equality: return s == "op_Equality";
+ case OperatorType.InEquality: return s == "op_Inequality";
+ case OperatorType.Comparison:
+ if (s.Length < 11 || !s.StartsWith("op_", StringComparison.Ordinal)) return false;
+ switch (s) {
+ case "op_GreaterThan":
+ case "op_GreaterThanOrEqual":
+ case "op_LessThan":
+ case "op_LessThanOrEqual": return true;
+ default: return false;
+ }
+ default:
+ if (s.Length < 10 || !s.StartsWith("op_", StringComparison.Ordinal)) return false;
+ switch (s) {
+ case "op_Addition":
+ case "op_Subtraction":
+ case "op_Multiply":
+ case "op_Division":
+ case "op_Modulus":
+ case "op_BitwiseAnd":
+ case "op_BitwiseOr":
+ case "op_ExclusiveOr":
+ case "op_LeftShift":
+ case "op_RightShift":
+ case "op_UnaryNegation":
+ case "op_UnaryPlus":
+ case "op_LogicalNot":
+ case "op_OnesComplement":
+ case "op_Increment":
+ case "op_Decrement": return true;
+ default: return false;
+ }
+ }
+ }
+
+ public override ILExpression BuildNew(PatternMatcher pm)
+ {
+ var res = pm.Operator;
+ res.Arguments.Clear();
+ if (pm.SimpleLeftOperand) res.Arguments.Add(pm.SimpleOperand);
+ res.Arguments.Add(VariableA.BuildNew(pm));
+ if (pm.B != null) res.Arguments.Add(VariableB.BuildNew(pm));
+ else if (pm.SimpleOperand != null && !pm.SimpleLeftOperand) res.Arguments.Add(pm.SimpleOperand);
+ return res;
+ }
+ }
+
+ sealed class AnyPattern : Pattern
+ {
+ public AnyPattern() : base(null) { }
+
+ public override bool Match(PatternMatcher pm, ILExpression e)
+ {
+ if (pm.SimpleOperand != null) throw new InvalidOperationException();
+ pm.SimpleOperand = e;
+ return true;
+ }
+
+ public override ILExpression BuildNew(PatternMatcher pm)
+ {
+ return pm.SimpleOperand;
+ }
+ }
+
+ sealed class VariablePattern : Pattern
+ {
+ readonly ILCode code;
+ readonly bool b;
+
+ public VariablePattern(ILCode code, bool b)
+ : base(null)
+ {
+ this.code = code;
+ this.b = b;
+ }
+
+ public override bool Match(PatternMatcher pm, ILExpression e)
+ {
+ if (e.Code != code) return false;
+ var v = e.Operand as ILVariable;
+ return v != null && (b ? Capture(ref pm.B, v) : Capture(ref pm.A, v));
+ }
+
+ static bool Capture(ref ILVariable pmvar, ILVariable v)
+ {
+ if (pmvar != null) return pmvar == v;
+ pmvar = v;
+ return true;
+ }
+
+ static readonly ILExpression[] EmptyArguments = new ILExpression[0];
+ public override ILExpression BuildNew(PatternMatcher pm)
+ {
+ var v = b ? pm.B : pm.A;
+ var e = new ILExpression(ILCode.Ldloc, v, EmptyArguments);
+ if (TypeAnalysis.IsNullableType(v.Type)) e = new ILExpression(ILCode.ValueOf, null, e);
+ return e;
+ }
+ }
+
+ sealed class BooleanPattern : Pattern
+ {
+ public static readonly Pattern False = new BooleanPattern(false), True = new BooleanPattern(true);
+
+ readonly object value;
+ BooleanPattern(bool value)
+ : base(null)
+ {
+ this.value = Convert.ToInt32(value);
+ }
+
+ public override bool Match(PatternMatcher pm, ILExpression e)
+ {
+ return e.Code == ILCode.Ldc_I4 && TypeAnalysis.IsBoolean(e.InferredType) && Equals(e.Operand, value);
+ }
+
+ public override ILExpression BuildNew(PatternMatcher pm)
+ {
+ // boolean constants are wrapped inside a container to disable simplyfication of equality comparisons
+ return new ILExpression(ILCode.Wrap, null, new ILExpression(ILCode.Ldc_I4, value));
+ }
+ }
+
+ static readonly Pattern VariableRefA = new VariablePattern(ILCode.Ldloca, false), VariableRefB = new VariablePattern(ILCode.Ldloca, true);
+ static readonly Pattern VariableA = new VariablePattern(ILCode.Ldloc, false), VariableB = new VariablePattern(ILCode.Ldloc, true);
+ static readonly Pattern VariableAHasValue = new MethodPattern(ILCode.CallGetter, "get_HasValue", VariableRefA);
+ static readonly Pattern VariableAGetValueOrDefault = new MethodPattern(ILCode.Call, "GetValueOrDefault", VariableRefA);
+ static readonly Pattern VariableBHasValue = new MethodPattern(ILCode.CallGetter, "get_HasValue", VariableRefB);
+ static readonly Pattern VariableBGetValueOrDefault = new MethodPattern(ILCode.Call, "GetValueOrDefault", VariableRefB);
+ static readonly Pattern CeqHasValue = new ILPattern(ILCode.Ceq, VariableAHasValue, VariableBHasValue);
+ static readonly Pattern CneHasValue = new ILPattern(ILCode.Cne, VariableAHasValue, VariableBHasValue);
+ static readonly Pattern AndHasValue = new ILPattern(ILCode.And, VariableAHasValue, VariableBHasValue);
+ static readonly Pattern Any = new AnyPattern();
+ static readonly Pattern OperatorVariableAB = new OperatorPattern();
+
+ static OperatorPattern OperatorNN(OperatorType type)
+ {
+ return new OperatorPattern(type, false);
+ }
+
+ static OperatorPattern OperatorNV(OperatorType type)
+ {
+ return new OperatorPattern(type, true);
+ }
+
+ static Pattern NewObj(Pattern p)
+ {
+ return new MethodPattern(ILCode.Newobj, ".ctor", p);
+ }
+
+ static readonly Pattern[] Comparisons = new Pattern[] {
+ /* both operands nullable */
+ // == (primitive, decimal)
+ OperatorNN(OperatorType.Equality) & CeqHasValue,
+ // == (struct)
+ CeqHasValue & (!VariableAHasValue | OperatorNN(OperatorType.Equality)),
+ // != (primitive, decimal)
+ OperatorNN(OperatorType.InEquality) | CneHasValue,
+ // != (struct)
+ CneHasValue | (VariableAHasValue & OperatorNN(OperatorType.InEquality)),
+ // > , < , >= , <= (primitive, decimal)
+ OperatorNN(OperatorType.Comparison) & AndHasValue,
+ // > , < , >= , <= (struct)
+ AndHasValue & OperatorNN(OperatorType.Comparison),
+
+ /* only one operand nullable */
+ // == (primitive, decimal)
+ OperatorNV(OperatorType.Equality) & VariableAHasValue,
+ // == (struct)
+ VariableAHasValue & OperatorNV(OperatorType.Equality),
+ // != (primitive, decimal)
+ OperatorNV(OperatorType.InEquality) | !VariableAHasValue,
+ // != (struct)
+ !VariableAHasValue | OperatorNV(OperatorType.InEquality),
+ // > , <, >= , <= (primitive, decimal)
+ OperatorNV(OperatorType.Comparison) & VariableAHasValue,
+ // > , < , >= , <= (struct)
+ VariableAHasValue & OperatorNV(OperatorType.Comparison),
+ };
+
+ static readonly Pattern[] Other = new Pattern[] {
+ /* both operands nullable */
+ // & (bool)
+ new ILPattern(ILCode.TernaryOp, VariableAGetValueOrDefault | (!VariableBGetValueOrDefault & !VariableAHasValue), VariableB, VariableA),
+ new ILPattern(ILCode.And, VariableA, VariableB),
+ // | (bool)
+ new ILPattern(ILCode.TernaryOp, VariableAGetValueOrDefault | (!VariableBGetValueOrDefault & !VariableAHasValue), VariableA, VariableB),
+ new ILPattern(ILCode.Or, VariableA, VariableB),
+ // null coalescing
+ new ILPattern(ILCode.TernaryOp, VariableAHasValue, NewObj(VariableAGetValueOrDefault), VariableB),
+ new ILPattern(ILCode.NullCoalescing, VariableA, VariableB),
+ // all other
+ new ILPattern(ILCode.TernaryOp, AndHasValue, NewObj(OperatorNN(OperatorType.Other)), new ILPattern(ILCode.DefaultValue)),
+ OperatorVariableAB,
+
+ /* only one operand nullable */
+ // & (bool)
+ new ILPattern(ILCode.TernaryOp, Any, VariableA, NewObj(BooleanPattern.False)),
+ new ILPattern(ILCode.And, VariableA, Any),
+ // | (bool)
+ new ILPattern(ILCode.TernaryOp, Any, NewObj(BooleanPattern.True), VariableA),
+ new ILPattern(ILCode.Or, VariableA, Any),
+ // == true
+ VariableAGetValueOrDefault & VariableAHasValue,
+ new ILPattern(ILCode.Ceq, VariableA, BooleanPattern.True),
+ // != true
+ !VariableAGetValueOrDefault | !VariableAHasValue,
+ new ILPattern(ILCode.Cne, VariableA, BooleanPattern.True),
+ // == false
+ !VariableAGetValueOrDefault & VariableAHasValue,
+ new ILPattern(ILCode.Ceq, VariableA, BooleanPattern.False),
+ // != false
+ VariableAGetValueOrDefault | !VariableAHasValue,
+ new ILPattern(ILCode.Cne, VariableA, BooleanPattern.False),
+ // ?? true
+ !VariableAHasValue | VariableAGetValueOrDefault,
+ new ILPattern(ILCode.NullCoalescing, VariableA, BooleanPattern.True),
+ // ?? false
+ VariableAHasValue & VariableAGetValueOrDefault,
+ new ILPattern(ILCode.NullCoalescing, VariableA, BooleanPattern.False),
+ // null coalescing
+ new ILPattern(ILCode.TernaryOp, VariableAHasValue, VariableAGetValueOrDefault, Any),
+ new ILPattern(ILCode.NullCoalescing, VariableA, Any),
+ // all other
+ new ILPattern(ILCode.TernaryOp, VariableAHasValue, NewObj(OperatorNV(OperatorType.Other)), new ILPattern(ILCode.DefaultValue)),
+ OperatorVariableAB,
+ };
+
+ ILVariable A, B;
+ ILExpression Operator, SimpleOperand;
+ bool SimpleLeftOperand;
+
+ void Reset()
+ {
+ A = null;
+ B = null;
+ Operator = null;
+ SimpleOperand = null;
+ SimpleLeftOperand = false;
+ }
+
+ bool Simplify(ILExpression expr)
+ {
+ if (expr.Code == ILCode.TernaryOp || expr.Code == ILCode.LogicAnd || expr.Code == ILCode.LogicOr) {
+ Pattern[] ps;
+ if (expr.Code != ILCode.TernaryOp) {
+ ps = Comparisons;
+ for (int i = 0; i < ps.Length; i++) {
+ Reset();
+ if (!ps[i].Match(this, expr)) continue;
+ SetResult(expr, OperatorVariableAB.BuildNew(this));
+ return true;
+ }
+ }
+ ps = Other;
+ for (int i = 0; i < ps.Length; i += 2) {
+ Reset();
+ if (!ps[i].Match(this, expr)) continue;
+ var n = ps[i + 1].BuildNew(this);
+ SetResult(expr, n);
+ if (n.Code == ILCode.NullCoalescing) {
+ // if both operands are nullable then the result is also nullable
+ if (n.Arguments[1].Code == ILCode.ValueOf) {
+ n.Arguments[0] = n.Arguments[0].Arguments[0];
+ n.Arguments[1] = n.Arguments[1].Arguments[0];
+ }
+ } else if (n.Code != ILCode.Ceq && n.Code != ILCode.Cne) {
+ expr.Code = ILCode.NullableOf;
+ expr.InferredType = expr.ExpectedType = null;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static void SetResult(ILExpression expr, ILExpression n)
+ {
+ // IL ranges from removed nodes are assigned to the new operator expression
+ var removednodes = expr.GetSelfAndChildrenRecursive<ILExpression>().Except(n.GetSelfAndChildrenRecursive<ILExpression>());
+ n.ILRanges.AddRange(removednodes.SelectMany(el => el.ILRanges));
+ // the new expression is wrapped in a container so that negations aren't pushed through lifted comparison operations
+ expr.Code = ILCode.Wrap;
+ expr.Arguments.Clear();
+ expr.Arguments.Add(n);
+ expr.ILRanges.Clear();
+ expr.InferredType = n.InferredType;
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/ILAst/LoopsAndConditions.cs b/ICSharpCode.Decompiler/ILAst/LoopsAndConditions.cs
new file mode 100644
index 00000000..32095b03
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/LoopsAndConditions.cs
@@ -0,0 +1,443 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using ICSharpCode.Decompiler.FlowAnalysis;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ /// <summary>
+ /// Description of LoopsAndConditions.
+ /// </summary>
+ public class LoopsAndConditions
+ {
+ Dictionary<ILLabel, ControlFlowNode> labelToCfNode = new Dictionary<ILLabel, ControlFlowNode>();
+
+ readonly DecompilerContext context;
+
+ uint nextLabelIndex = 0;
+
+ public LoopsAndConditions(DecompilerContext context)
+ {
+ this.context = context;
+ }
+
+ public void FindLoops(ILBlock block)
+ {
+ if (block.Body.Count > 0) {
+ ControlFlowGraph graph;
+ graph = BuildGraph(block.Body, (ILLabel)block.EntryGoto.Operand);
+ graph.ComputeDominance(context.CancellationToken);
+ graph.ComputeDominanceFrontier();
+ block.Body = FindLoops(new HashSet<ControlFlowNode>(graph.Nodes.Skip(3)), graph.EntryPoint, false);
+ }
+ }
+
+ public void FindConditions(ILBlock block)
+ {
+ if (block.Body.Count > 0) {
+ ControlFlowGraph graph;
+ graph = BuildGraph(block.Body, (ILLabel)block.EntryGoto.Operand);
+ graph.ComputeDominance(context.CancellationToken);
+ graph.ComputeDominanceFrontier();
+ block.Body = FindConditions(new HashSet<ControlFlowNode>(graph.Nodes.Skip(3)), graph.EntryPoint);
+ }
+ }
+
+ ControlFlowGraph BuildGraph(List<ILNode> nodes, ILLabel entryLabel)
+ {
+ int index = 0;
+ List<ControlFlowNode> cfNodes = new List<ControlFlowNode>();
+ ControlFlowNode entryPoint = new ControlFlowNode(index++, 0, ControlFlowNodeType.EntryPoint);
+ cfNodes.Add(entryPoint);
+ ControlFlowNode regularExit = new ControlFlowNode(index++, -1, ControlFlowNodeType.RegularExit);
+ cfNodes.Add(regularExit);
+ ControlFlowNode exceptionalExit = new ControlFlowNode(index++, -1, ControlFlowNodeType.ExceptionalExit);
+ cfNodes.Add(exceptionalExit);
+
+ // Create graph nodes
+ labelToCfNode = new Dictionary<ILLabel, ControlFlowNode>();
+ Dictionary<ILNode, ControlFlowNode> astNodeToCfNode = new Dictionary<ILNode, ControlFlowNode>();
+ foreach(ILBasicBlock node in nodes) {
+ ControlFlowNode cfNode = new ControlFlowNode(index++, -1, ControlFlowNodeType.Normal);
+ cfNodes.Add(cfNode);
+ astNodeToCfNode[node] = cfNode;
+ cfNode.UserData = node;
+
+ // Find all contained labels
+ foreach(ILLabel label in node.GetSelfAndChildrenRecursive<ILLabel>()) {
+ labelToCfNode[label] = cfNode;
+ }
+ }
+
+ // Entry endge
+ ControlFlowNode entryNode = labelToCfNode[entryLabel];
+ ControlFlowEdge entryEdge = new ControlFlowEdge(entryPoint, entryNode, JumpType.Normal);
+ entryPoint.Outgoing.Add(entryEdge);
+ entryNode.Incoming.Add(entryEdge);
+
+ // Create edges
+ foreach(ILBasicBlock node in nodes) {
+ ControlFlowNode source = astNodeToCfNode[node];
+
+ // Find all branches
+ foreach(ILLabel target in node.GetSelfAndChildrenRecursive<ILExpression>(e => e.IsBranch()).SelectMany(e => e.GetBranchTargets())) {
+ ControlFlowNode destination;
+ // Labels which are out of out scope will not be in the collection
+ // Insert self edge only if we are sure we are a loop
+ if (labelToCfNode.TryGetValue(target, out destination) && (destination != source || target == node.Body.FirstOrDefault())) {
+ ControlFlowEdge edge = new ControlFlowEdge(source, destination, JumpType.Normal);
+ source.Outgoing.Add(edge);
+ destination.Incoming.Add(edge);
+ }
+ }
+ }
+
+ return new ControlFlowGraph(cfNodes.ToArray());
+ }
+
+ List<ILNode> FindLoops(HashSet<ControlFlowNode> scope, ControlFlowNode entryPoint, bool excludeEntryPoint)
+ {
+ List<ILNode> result = new List<ILNode>();
+
+ // Do not modify entry data
+ scope = new HashSet<ControlFlowNode>(scope);
+
+ Queue<ControlFlowNode> agenda = new Queue<ControlFlowNode>();
+ agenda.Enqueue(entryPoint);
+ while(agenda.Count > 0) {
+ ControlFlowNode node = agenda.Dequeue();
+
+ // If the node is a loop header
+ if (scope.Contains(node)
+ && node.DominanceFrontier.Contains(node)
+ && (node != entryPoint || !excludeEntryPoint))
+ {
+ HashSet<ControlFlowNode> loopContents = FindLoopContent(scope, node);
+
+ // If the first expression is a loop condition
+ ILBasicBlock basicBlock = (ILBasicBlock)node.UserData;
+ ILExpression condExpr;
+ ILLabel trueLabel;
+ ILLabel falseLabel;
+ // It has to be just brtrue - any preceding code would introduce goto
+ if(basicBlock.MatchSingleAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel))
+ {
+ ControlFlowNode trueTarget;
+ labelToCfNode.TryGetValue(trueLabel, out trueTarget);
+ ControlFlowNode falseTarget;
+ labelToCfNode.TryGetValue(falseLabel, out falseTarget);
+
+ // If one point inside the loop and the other outside
+ if ((!loopContents.Contains(trueTarget) && loopContents.Contains(falseTarget)) ||
+ (loopContents.Contains(trueTarget) && !loopContents.Contains(falseTarget)) )
+ {
+ loopContents.RemoveOrThrow(node);
+ scope.RemoveOrThrow(node);
+
+ // If false means enter the loop
+ if (loopContents.Contains(falseTarget) || falseTarget == node)
+ {
+ // Negate the condition
+ condExpr = new ILExpression(ILCode.LogicNot, null, condExpr);
+ ILLabel tmp = trueLabel;
+ trueLabel = falseLabel;
+ falseLabel = tmp;
+ }
+
+ ControlFlowNode postLoopTarget;
+ labelToCfNode.TryGetValue(falseLabel, out postLoopTarget);
+ if (postLoopTarget != null) {
+ // Pull more nodes into the loop
+ HashSet<ControlFlowNode> postLoopContents = FindDominatedNodes(scope, postLoopTarget);
+ var pullIn = scope.Except(postLoopContents).Where(n => node.Dominates(n));
+ loopContents.UnionWith(pullIn);
+ }
+
+ // Use loop to implement the brtrue
+ basicBlock.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
+ basicBlock.Body.Add(new ILWhileLoop() {
+ Condition = condExpr,
+ BodyBlock = new ILBlock() {
+ EntryGoto = new ILExpression(ILCode.Br, trueLabel),
+ Body = FindLoops(loopContents, node, false)
+ }
+ });
+ basicBlock.Body.Add(new ILExpression(ILCode.Br, falseLabel));
+ result.Add(basicBlock);
+
+ scope.ExceptWith(loopContents);
+ }
+ }
+
+ // Fallback method: while(true)
+ if (scope.Contains(node)) {
+ result.Add(new ILBasicBlock() {
+ Body = new List<ILNode>() {
+ new ILLabel() { Name = "Loop_" + (nextLabelIndex++) },
+ new ILWhileLoop() {
+ BodyBlock = new ILBlock() {
+ EntryGoto = new ILExpression(ILCode.Br, (ILLabel)basicBlock.Body.First()),
+ Body = FindLoops(loopContents, node, true)
+ }
+ },
+ },
+ });
+
+ scope.ExceptWith(loopContents);
+ }
+ }
+
+ // Using the dominator tree should ensure we find the the widest loop first
+ foreach(var child in node.DominatorTreeChildren) {
+ agenda.Enqueue(child);
+ }
+ }
+
+ // Add whatever is left
+ foreach(var node in scope) {
+ result.Add((ILNode)node.UserData);
+ }
+ scope.Clear();
+
+ return result;
+ }
+
+ List<ILNode> FindConditions(HashSet<ControlFlowNode> scope, ControlFlowNode entryNode)
+ {
+ List<ILNode> result = new List<ILNode>();
+
+ // Do not modify entry data
+ scope = new HashSet<ControlFlowNode>(scope);
+
+ Stack<ControlFlowNode> agenda = new Stack<ControlFlowNode>();
+ agenda.Push(entryNode);
+ while(agenda.Count > 0) {
+ ControlFlowNode node = agenda.Pop();
+
+ // Find a block that represents a simple condition
+ if (scope.Contains(node)) {
+
+ ILBasicBlock block = (ILBasicBlock)node.UserData;
+
+ {
+ // Switch
+ ILLabel[] caseLabels;
+ ILExpression switchArg;
+ ILLabel fallLabel;
+ if (block.MatchLastAndBr(ILCode.Switch, out caseLabels, out switchArg, out fallLabel)) {
+
+ // Replace the switch code with ILSwitch
+ ILSwitch ilSwitch = new ILSwitch() { Condition = switchArg };
+ block.Body.RemoveTail(ILCode.Switch, ILCode.Br);
+ block.Body.Add(ilSwitch);
+ block.Body.Add(new ILExpression(ILCode.Br, fallLabel));
+ result.Add(block);
+
+ // Remove the item so that it is not picked up as content
+ scope.RemoveOrThrow(node);
+
+ // Find the switch offset
+ int addValue = 0;
+ List<ILExpression> subArgs;
+ if (ilSwitch.Condition.Match(ILCode.Sub, out subArgs) && subArgs[1].Match(ILCode.Ldc_I4, out addValue)) {
+ ilSwitch.Condition = subArgs[0];
+ }
+
+ // Pull in code of cases
+ ControlFlowNode fallTarget = null;
+ labelToCfNode.TryGetValue(fallLabel, out fallTarget);
+
+ HashSet<ControlFlowNode> frontiers = new HashSet<ControlFlowNode>();
+ if (fallTarget != null)
+ frontiers.UnionWith(fallTarget.DominanceFrontier.Except(new [] { fallTarget }));
+
+ foreach(ILLabel condLabel in caseLabels) {
+ ControlFlowNode condTarget = null;
+ labelToCfNode.TryGetValue(condLabel, out condTarget);
+ if (condTarget != null)
+ frontiers.UnionWith(condTarget.DominanceFrontier.Except(new [] { condTarget }));
+ }
+
+ for (int i = 0; i < caseLabels.Length; i++) {
+ ILLabel condLabel = caseLabels[i];
+
+ // Find or create new case block
+ ILSwitch.CaseBlock caseBlock = ilSwitch.CaseBlocks.FirstOrDefault(b => b.EntryGoto.Operand == condLabel);
+ if (caseBlock == null) {
+ caseBlock = new ILSwitch.CaseBlock() {
+ Values = new List<int>(),
+ EntryGoto = new ILExpression(ILCode.Br, condLabel)
+ };
+ ilSwitch.CaseBlocks.Add(caseBlock);
+
+ ControlFlowNode condTarget = null;
+ labelToCfNode.TryGetValue(condLabel, out condTarget);
+ if (condTarget != null && !frontiers.Contains(condTarget)) {
+ HashSet<ControlFlowNode> content = FindDominatedNodes(scope, condTarget);
+ scope.ExceptWith(content);
+ caseBlock.Body.AddRange(FindConditions(content, condTarget));
+ // Add explicit break which should not be used by default, but the goto removal might decide to use it
+ caseBlock.Body.Add(new ILBasicBlock() {
+ Body = {
+ new ILLabel() { Name = "SwitchBreak_" + (nextLabelIndex++) },
+ new ILExpression(ILCode.LoopOrSwitchBreak, null)
+ }
+ });
+ }
+ }
+ caseBlock.Values.Add(i + addValue);
+ }
+
+ // Heuristis to determine if we want to use fallthough as default case
+ if (fallTarget != null && !frontiers.Contains(fallTarget)) {
+ HashSet<ControlFlowNode> content = FindDominatedNodes(scope, fallTarget);
+ if (content.Any()) {
+ var caseBlock = new ILSwitch.CaseBlock() { EntryGoto = new ILExpression(ILCode.Br, fallLabel) };
+ ilSwitch.CaseBlocks.Add(caseBlock);
+ block.Body.RemoveTail(ILCode.Br);
+
+ scope.ExceptWith(content);
+ caseBlock.Body.AddRange(FindConditions(content, fallTarget));
+ // Add explicit break which should not be used by default, but the goto removal might decide to use it
+ caseBlock.Body.Add(new ILBasicBlock() {
+ Body = {
+ new ILLabel() { Name = "SwitchBreak_" + (nextLabelIndex++) },
+ new ILExpression(ILCode.LoopOrSwitchBreak, null)
+ }
+ });
+ }
+ }
+ }
+
+ // Two-way branch
+ ILExpression condExpr;
+ ILLabel trueLabel;
+ ILLabel falseLabel;
+ if(block.MatchLastAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel)) {
+
+ // Swap bodies since that seems to be the usual C# order
+ ILLabel temp = trueLabel;
+ trueLabel = falseLabel;
+ falseLabel = temp;
+ condExpr = new ILExpression(ILCode.LogicNot, null, condExpr);
+
+ // Convert the brtrue to ILCondition
+ ILCondition ilCond = new ILCondition() {
+ Condition = condExpr,
+ TrueBlock = new ILBlock() { EntryGoto = new ILExpression(ILCode.Br, trueLabel) },
+ FalseBlock = new ILBlock() { EntryGoto = new ILExpression(ILCode.Br, falseLabel) }
+ };
+ block.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
+ block.Body.Add(ilCond);
+ result.Add(block);
+
+ // Remove the item immediately so that it is not picked up as content
+ scope.RemoveOrThrow(node);
+
+ ControlFlowNode trueTarget = null;
+ labelToCfNode.TryGetValue(trueLabel, out trueTarget);
+ ControlFlowNode falseTarget = null;
+ labelToCfNode.TryGetValue(falseLabel, out falseTarget);
+
+ // Pull in the conditional code
+ if (trueTarget != null && HasSingleEdgeEnteringBlock(trueTarget)) {
+ HashSet<ControlFlowNode> content = FindDominatedNodes(scope, trueTarget);
+ scope.ExceptWith(content);
+ ilCond.TrueBlock.Body.AddRange(FindConditions(content, trueTarget));
+ }
+ if (falseTarget != null && HasSingleEdgeEnteringBlock(falseTarget)) {
+ HashSet<ControlFlowNode> content = FindDominatedNodes(scope, falseTarget);
+ scope.ExceptWith(content);
+ ilCond.FalseBlock.Body.AddRange(FindConditions(content, falseTarget));
+ }
+ }
+ }
+
+ // Add the node now so that we have good ordering
+ if (scope.Contains(node)) {
+ result.Add((ILNode)node.UserData);
+ scope.Remove(node);
+ }
+ }
+
+ // depth-first traversal of dominator tree
+ for (int i = node.DominatorTreeChildren.Count - 1; i >= 0; i--) {
+ agenda.Push(node.DominatorTreeChildren[i]);
+ }
+ }
+
+ // Add whatever is left
+ foreach(var node in scope) {
+ result.Add((ILNode)node.UserData);
+ }
+
+ return result;
+ }
+
+ static bool HasSingleEdgeEnteringBlock(ControlFlowNode node)
+ {
+ return node.Incoming.Count(edge => !node.Dominates(edge.Source)) == 1;
+ }
+
+ static HashSet<ControlFlowNode> FindDominatedNodes(HashSet<ControlFlowNode> scope, ControlFlowNode head)
+ {
+ HashSet<ControlFlowNode> agenda = new HashSet<ControlFlowNode>();
+ HashSet<ControlFlowNode> result = new HashSet<ControlFlowNode>();
+ agenda.Add(head);
+
+ while(agenda.Count > 0) {
+ ControlFlowNode addNode = agenda.First();
+ agenda.Remove(addNode);
+
+ if (scope.Contains(addNode) && head.Dominates(addNode) && result.Add(addNode)) {
+ foreach (var successor in addNode.Successors) {
+ agenda.Add(successor);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ static HashSet<ControlFlowNode> FindLoopContent(HashSet<ControlFlowNode> scope, ControlFlowNode head)
+ {
+ var viaBackEdges = head.Predecessors.Where(p => head.Dominates(p));
+ HashSet<ControlFlowNode> agenda = new HashSet<ControlFlowNode>(viaBackEdges);
+ HashSet<ControlFlowNode> result = new HashSet<ControlFlowNode>();
+
+ while(agenda.Count > 0) {
+ ControlFlowNode addNode = agenda.First();
+ agenda.Remove(addNode);
+
+ if (scope.Contains(addNode) && head.Dominates(addNode) && result.Add(addNode)) {
+ foreach (var predecessor in addNode.Predecessors) {
+ agenda.Add(predecessor);
+ }
+ }
+ }
+ if (scope.Contains(head))
+ result.Add(head);
+
+ return result;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/ILAst/PatternMatching.cs b/ICSharpCode.Decompiler/ILAst/PatternMatching.cs
new file mode 100644
index 00000000..441088b9
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/PatternMatching.cs
@@ -0,0 +1,177 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ public static class PatternMatching
+ {
+ public static bool Match(this ILNode node, ILCode code)
+ {
+ ILExpression expr = node as ILExpression;
+ return expr != null && expr.Prefixes == null && expr.Code == code;
+ }
+
+ public static bool Match<T>(this ILNode node, ILCode code, out T operand)
+ {
+ ILExpression expr = node as ILExpression;
+ if (expr != null && expr.Prefixes == null && expr.Code == code && expr.Arguments.Count == 0) {
+ operand = (T)expr.Operand;
+ return true;
+ }
+ operand = default(T);
+ return false;
+ }
+
+ public static bool Match(this ILNode node, ILCode code, out List<ILExpression> args)
+ {
+ ILExpression expr = node as ILExpression;
+ if (expr != null && expr.Prefixes == null && expr.Code == code) {
+ Debug.Assert(expr.Operand == null);
+ args = expr.Arguments;
+ return true;
+ }
+ args = null;
+ return false;
+ }
+
+ public static bool Match(this ILNode node, ILCode code, out ILExpression arg)
+ {
+ List<ILExpression> args;
+ if (node.Match(code, out args) && args.Count == 1) {
+ arg = args[0];
+ return true;
+ }
+ arg = null;
+ return false;
+ }
+
+ public static bool Match<T>(this ILNode node, ILCode code, out T operand, out List<ILExpression> args)
+ {
+ ILExpression expr = node as ILExpression;
+ if (expr != null && expr.Prefixes == null && expr.Code == code) {
+ operand = (T)expr.Operand;
+ args = expr.Arguments;
+ return true;
+ }
+ operand = default(T);
+ args = null;
+ return false;
+ }
+
+ public static bool Match<T>(this ILNode node, ILCode code, out T operand, out ILExpression arg)
+ {
+ List<ILExpression> args;
+ if (node.Match(code, out operand, out args) && args.Count == 1) {
+ arg = args[0];
+ return true;
+ }
+ arg = null;
+ return false;
+ }
+
+ public static bool Match<T>(this ILNode node, ILCode code, out T operand, out ILExpression arg1, out ILExpression arg2)
+ {
+ List<ILExpression> args;
+ if (node.Match(code, out operand, out args) && args.Count == 2) {
+ arg1 = args[0];
+ arg2 = args[1];
+ return true;
+ }
+ arg1 = null;
+ arg2 = null;
+ return false;
+ }
+
+ public static bool MatchSingle<T>(this ILBasicBlock bb, ILCode code, out T operand, out ILExpression arg)
+ {
+ if (bb.Body.Count == 2 &&
+ bb.Body[0] is ILLabel &&
+ bb.Body[1].Match(code, out operand, out arg))
+ {
+ return true;
+ }
+ operand = default(T);
+ arg = null;
+ return false;
+ }
+
+ public static bool MatchSingleAndBr<T>(this ILBasicBlock bb, ILCode code, out T operand, out ILExpression arg, out ILLabel brLabel)
+ {
+ if (bb.Body.Count == 3 &&
+ bb.Body[0] is ILLabel &&
+ bb.Body[1].Match(code, out operand, out arg) &&
+ bb.Body[2].Match(ILCode.Br, out brLabel))
+ {
+ return true;
+ }
+ operand = default(T);
+ arg = null;
+ brLabel = null;
+ return false;
+ }
+
+ public static bool MatchLastAndBr<T>(this ILBasicBlock bb, ILCode code, out T operand, out ILExpression arg, out ILLabel brLabel)
+ {
+ if (bb.Body.ElementAtOrDefault(bb.Body.Count - 2).Match(code, out operand, out arg) &&
+ bb.Body.LastOrDefault().Match(ILCode.Br, out brLabel))
+ {
+ return true;
+ }
+ operand = default(T);
+ arg = null;
+ brLabel = null;
+ return false;
+ }
+
+ public static bool MatchThis(this ILNode node)
+ {
+ ILVariable v;
+ return node.Match(ILCode.Ldloc, out v) && v.IsParameter && v.OriginalParameter.Index == -1;
+ }
+
+ public static bool MatchLdloc(this ILNode node, ILVariable expectedVar)
+ {
+ ILVariable v;
+ return node.Match(ILCode.Ldloc, out v) && v == expectedVar;
+ }
+
+ public static bool MatchLdloca(this ILNode node, ILVariable expectedVar)
+ {
+ ILVariable v;
+ return node.Match(ILCode.Ldloca, out v) && v == expectedVar;
+ }
+
+ public static bool MatchStloc(this ILNode node, ILVariable expectedVar, out ILExpression expr)
+ {
+ ILVariable v;
+ return node.Match(ILCode.Stloc, out v, out expr) && v == expectedVar;
+ }
+
+ public static bool MatchLdcI4(this ILNode node, int expectedValue)
+ {
+ int v;
+ return node.Match(ILCode.Ldc_I4, out v) && v == expectedValue;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs b/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs
new file mode 100644
index 00000000..f514aa45
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs
@@ -0,0 +1,1103 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+
+using ICSharpCode.NRefactory.Utils;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ public partial class ILAstOptimizer
+ {
+ #region TypeConversionSimplifications
+ static bool TypeConversionSimplifications(List<ILNode> body, ILExpression expr, int pos)
+ {
+ bool modified = false;
+ modified |= TransformDecimalCtorToConstant(expr);
+ modified |= SimplifyLdcI4ConvI8(expr);
+ modified |= RemoveConvIFromArrayCreation(expr);
+ foreach(ILExpression arg in expr.Arguments) {
+ modified |= TypeConversionSimplifications(null, arg, -1);
+ }
+ return modified;
+ }
+
+ static bool TransformDecimalCtorToConstant(ILExpression expr)
+ {
+ MethodReference r;
+ List<ILExpression> args;
+ if (expr.Match(ILCode.Newobj, out r, out args) &&
+ r.DeclaringType.Namespace == "System" &&
+ r.DeclaringType.Name == "Decimal")
+ {
+ if (args.Count == 1) {
+ int val;
+ if (args[0].Match(ILCode.Ldc_I4, out val)) {
+ expr.Code = ILCode.Ldc_Decimal;
+ expr.Operand = new decimal(val);
+ expr.InferredType = r.DeclaringType;
+ expr.Arguments.Clear();
+ return true;
+ }
+ } else if (args.Count == 5) {
+ int lo, mid, hi, isNegative, scale;
+ if (expr.Arguments[0].Match(ILCode.Ldc_I4, out lo) &&
+ expr.Arguments[1].Match(ILCode.Ldc_I4, out mid) &&
+ expr.Arguments[2].Match(ILCode.Ldc_I4, out hi) &&
+ expr.Arguments[3].Match(ILCode.Ldc_I4, out isNegative) &&
+ expr.Arguments[4].Match(ILCode.Ldc_I4, out scale))
+ {
+ expr.Code = ILCode.Ldc_Decimal;
+ expr.Operand = new decimal(lo, mid, hi, isNegative != 0, (byte)scale);
+ expr.InferredType = r.DeclaringType;
+ expr.Arguments.Clear();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ static bool SimplifyLdcI4ConvI8(ILExpression expr)
+ {
+ ILExpression ldc;
+ int val;
+ if (expr.Match(ILCode.Conv_I8, out ldc) && ldc.Match(ILCode.Ldc_I4, out val)) {
+ expr.Code = ILCode.Ldc_I8;
+ expr.Operand = (long)val;
+ expr.Arguments.Clear();
+ return true;
+ }
+ return false;
+ }
+
+ static bool RemoveConvIFromArrayCreation(ILExpression expr)
+ {
+ TypeReference typeRef;
+ ILExpression length;
+ ILExpression input;
+ if (expr.Match(ILCode.Newarr, out typeRef, out length)) {
+ if (length.Match(ILCode.Conv_Ovf_I, out input) || length.Match(ILCode.Conv_I, out input)
+ || length.Match(ILCode.Conv_Ovf_I_Un, out input) || length.Match(ILCode.Conv_U, out input))
+ {
+ expr.Arguments[0] = input;
+ return true;
+ }
+ }
+ return false;
+ }
+ #endregion
+
+ #region SimplifyLdObjAndStObj
+ static bool SimplifyLdObjAndStObj(List<ILNode> body, ILExpression expr, int pos)
+ {
+ bool modified = false;
+ expr = SimplifyLdObjAndStObj(expr, ref modified);
+ if (modified && body != null)
+ body[pos] = expr;
+ for (int i = 0; i < expr.Arguments.Count; i++) {
+ expr.Arguments[i] = SimplifyLdObjAndStObj(expr.Arguments[i], ref modified);
+ modified |= SimplifyLdObjAndStObj(null, expr.Arguments[i], -1);
+ }
+ return modified;
+ }
+
+ static ILExpression SimplifyLdObjAndStObj(ILExpression expr, ref bool modified)
+ {
+ if (expr.Code == ILCode.Initobj) {
+ expr.Code = ILCode.Stobj;
+ expr.Arguments.Add(new ILExpression(ILCode.DefaultValue, expr.Operand));
+ modified = true;
+ } else if (expr.Code == ILCode.Cpobj) {
+ expr.Code = ILCode.Stobj;
+ expr.Arguments[1] = new ILExpression(ILCode.Ldobj, expr.Operand, expr.Arguments[1]);
+ modified = true;
+ }
+ ILExpression arg, arg2;
+ TypeReference type;
+ ILCode? newCode = null;
+ if (expr.Match(ILCode.Stobj, out type, out arg, out arg2)) {
+ switch (arg.Code) {
+ case ILCode.Ldelema: newCode = ILCode.Stelem_Any; break;
+ case ILCode.Ldloca: newCode = ILCode.Stloc; break;
+ case ILCode.Ldflda: newCode = ILCode.Stfld; break;
+ case ILCode.Ldsflda: newCode = ILCode.Stsfld; break;
+ }
+ } else if (expr.Match(ILCode.Ldobj, out type, out arg)) {
+ switch (arg.Code) {
+ case ILCode.Ldelema: newCode = ILCode.Ldelem_Any; break;
+ case ILCode.Ldloca: newCode = ILCode.Ldloc; break;
+ case ILCode.Ldflda: newCode = ILCode.Ldfld; break;
+ case ILCode.Ldsflda: newCode = ILCode.Ldsfld; break;
+ }
+ }
+ if (newCode != null) {
+ arg.Code = newCode.Value;
+ if (expr.Code == ILCode.Stobj) {
+ arg.InferredType = expr.InferredType;
+ arg.ExpectedType = expr.ExpectedType;
+ arg.Arguments.Add(arg2);
+ }
+ arg.ILRanges.AddRange(expr.ILRanges);
+ modified = true;
+ return arg;
+ } else {
+ return expr;
+ }
+ }
+ #endregion
+
+ #region CachedDelegateInitialization
+ void CachedDelegateInitializationWithField(ILBlock block, ref int i)
+ {
+ // if (logicnot(ldsfld(field))) {
+ // stsfld(field, newobj(Action::.ctor, ldnull(), ldftn(method)))
+ // } else {
+ // }
+ // ...(..., ldsfld(field), ...)
+
+ ILCondition c = block.Body[i] as ILCondition;
+ if (c == null || c.Condition == null && c.TrueBlock == null || c.FalseBlock == null)
+ return;
+ if (!(c.TrueBlock.Body.Count == 1 && c.FalseBlock.Body.Count == 0))
+ return;
+ if (!c.Condition.Match(ILCode.LogicNot))
+ return;
+ ILExpression condition = c.Condition.Arguments.Single() as ILExpression;
+ if (condition == null || condition.Code != ILCode.Ldsfld)
+ return;
+ FieldDefinition field = ((FieldReference)condition.Operand).ResolveWithinSameModule(); // field is defined in current assembly
+ if (field == null || !field.IsCompilerGeneratedOrIsInCompilerGeneratedClass())
+ return;
+ ILExpression stsfld = c.TrueBlock.Body[0] as ILExpression;
+ if (!(stsfld != null && stsfld.Code == ILCode.Stsfld && ((FieldReference)stsfld.Operand).ResolveWithinSameModule() == field))
+ return;
+ ILExpression newObj = stsfld.Arguments[0];
+ if (!(newObj.Code == ILCode.Newobj && newObj.Arguments.Count == 2))
+ return;
+ if (newObj.Arguments[0].Code != ILCode.Ldnull)
+ return;
+ if (newObj.Arguments[1].Code != ILCode.Ldftn)
+ return;
+ MethodDefinition anonymousMethod = ((MethodReference)newObj.Arguments[1].Operand).ResolveWithinSameModule(); // method is defined in current assembly
+ if (!Ast.Transforms.DelegateConstruction.IsAnonymousMethod(context, anonymousMethod))
+ return;
+
+ ILNode followingNode = block.Body.ElementAtOrDefault(i + 1);
+ if (followingNode != null && followingNode.GetSelfAndChildrenRecursive<ILExpression>().Count(
+ e => e.Code == ILCode.Ldsfld && ((FieldReference)e.Operand).ResolveWithinSameModule() == field) == 1)
+ {
+ foreach (ILExpression parent in followingNode.GetSelfAndChildrenRecursive<ILExpression>()) {
+ for (int j = 0; j < parent.Arguments.Count; j++) {
+ if (parent.Arguments[j].Code == ILCode.Ldsfld && ((FieldReference)parent.Arguments[j].Operand).ResolveWithinSameModule() == field) {
+ parent.Arguments[j] = newObj;
+ block.Body.RemoveAt(i);
+ i -= new ILInlining(method).InlineInto(block.Body, i, aggressive: false);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ void CachedDelegateInitializationWithLocal(ILBlock block, ref int i)
+ {
+ // if (logicnot(ldloc(v))) {
+ // stloc(v, newobj(Action::.ctor, ldloc(displayClass), ldftn(method)))
+ // } else {
+ // }
+ // ...(..., ldloc(v), ...)
+
+ ILCondition c = block.Body[i] as ILCondition;
+ if (c == null || c.Condition == null && c.TrueBlock == null || c.FalseBlock == null)
+ return;
+ if (!(c.TrueBlock.Body.Count == 1 && c.FalseBlock.Body.Count == 0))
+ return;
+ if (!c.Condition.Match(ILCode.LogicNot))
+ return;
+ ILExpression condition = c.Condition.Arguments.Single() as ILExpression;
+ if (condition == null || condition.Code != ILCode.Ldloc)
+ return;
+ ILVariable v = (ILVariable)condition.Operand;
+ ILExpression stloc = c.TrueBlock.Body[0] as ILExpression;
+ if (!(stloc != null && stloc.Code == ILCode.Stloc && (ILVariable)stloc.Operand == v))
+ return;
+ ILExpression newObj = stloc.Arguments[0];
+ if (!(newObj.Code == ILCode.Newobj && newObj.Arguments.Count == 2))
+ return;
+ if (newObj.Arguments[0].Code != ILCode.Ldloc)
+ return;
+ if (newObj.Arguments[1].Code != ILCode.Ldftn)
+ return;
+ MethodDefinition anonymousMethod = ((MethodReference)newObj.Arguments[1].Operand).ResolveWithinSameModule(); // method is defined in current assembly
+ if (!Ast.Transforms.DelegateConstruction.IsAnonymousMethod(context, anonymousMethod))
+ return;
+
+ ILNode followingNode = block.Body.ElementAtOrDefault(i + 1);
+ if (followingNode != null && followingNode.GetSelfAndChildrenRecursive<ILExpression>().Count(
+ e => e.Code == ILCode.Ldloc && (ILVariable)e.Operand == v) == 1)
+ {
+ ILInlining inlining = new ILInlining(method);
+ if (!(inlining.numLdloc.GetOrDefault(v) == 2 && inlining.numStloc.GetOrDefault(v) == 2 && inlining.numLdloca.GetOrDefault(v) == 0))
+ return;
+
+ // Find the store instruction that initializes the local to null:
+ foreach (ILBlock storeBlock in method.GetSelfAndChildrenRecursive<ILBlock>()) {
+ for (int j = 0; j < storeBlock.Body.Count; j++) {
+ ILVariable storedVar;
+ ILExpression storedExpr;
+ if (storeBlock.Body[j].Match(ILCode.Stloc, out storedVar, out storedExpr) && storedVar == v && storedExpr.Match(ILCode.Ldnull)) {
+ // Remove the instruction
+ storeBlock.Body.RemoveAt(j);
+ if (storeBlock == block && j < i)
+ i--;
+ break;
+ }
+ }
+ }
+
+ block.Body[i] = stloc; // remove the 'if (v==null)'
+ inlining = new ILInlining(method);
+ inlining.InlineIfPossible(block.Body, ref i);
+ }
+ }
+ #endregion
+
+ #region MakeAssignmentExpression
+ bool MakeAssignmentExpression(List<ILNode> body, ILExpression expr, int pos)
+ {
+ // exprVar = ...
+ // stloc(v, exprVar)
+ // ->
+ // exprVar = stloc(v, ...))
+ ILVariable exprVar;
+ ILExpression initializer;
+ if (!(expr.Match(ILCode.Stloc, out exprVar, out initializer) && exprVar.IsGenerated))
+ return false;
+ ILExpression nextExpr = body.ElementAtOrDefault(pos + 1) as ILExpression;
+ ILVariable v;
+ ILExpression stLocArg;
+ if (nextExpr.Match(ILCode.Stloc, out v, out stLocArg) && stLocArg.MatchLdloc(exprVar)) {
+ ILExpression store2 = body.ElementAtOrDefault(pos + 2) as ILExpression;
+ if (StoreCanBeConvertedToAssignment(store2, exprVar)) {
+ // expr_44 = ...
+ // stloc(v1, expr_44)
+ // anystore(v2, expr_44)
+ // ->
+ // stloc(v1, anystore(v2, ...))
+ ILInlining inlining = new ILInlining(method);
+ if (inlining.numLdloc.GetOrDefault(exprVar) == 2 && inlining.numStloc.GetOrDefault(exprVar) == 1) {
+ body.RemoveAt(pos + 2); // remove store2
+ body.RemoveAt(pos); // remove expr = ...
+ nextExpr.Arguments[0] = store2;
+ store2.Arguments[store2.Arguments.Count - 1] = initializer;
+
+ inlining.InlineIfPossible(body, ref pos);
+
+ return true;
+ }
+ }
+
+ body.RemoveAt(pos + 1); // remove stloc
+ nextExpr.Arguments[0] = initializer;
+ ((ILExpression)body[pos]).Arguments[0] = nextExpr;
+ return true;
+ } else if ((nextExpr.Code == ILCode.Stsfld || nextExpr.Code == ILCode.CallSetter || nextExpr.Code == ILCode.CallvirtSetter) && nextExpr.Arguments.Count == 1) {
+ // exprVar = ...
+ // stsfld(fld, exprVar)
+ // ->
+ // exprVar = stsfld(fld, ...))
+ if (nextExpr.Arguments[0].MatchLdloc(exprVar)) {
+ body.RemoveAt(pos + 1); // remove stsfld
+ nextExpr.Arguments[0] = initializer;
+ ((ILExpression)body[pos]).Arguments[0] = nextExpr;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool StoreCanBeConvertedToAssignment(ILExpression store, ILVariable exprVar)
+ {
+ if (store == null)
+ return false;
+ switch (store.Code) {
+ case ILCode.Stloc:
+ case ILCode.Stfld:
+ case ILCode.Stsfld:
+ case ILCode.Stobj:
+ case ILCode.CallSetter:
+ case ILCode.CallvirtSetter:
+ break;
+ default:
+ if (!store.Code.IsStoreToArray())
+ return false;
+ break;
+ }
+ return store.Arguments.Last().Code == ILCode.Ldloc && store.Arguments.Last().Operand == exprVar;
+ }
+ #endregion
+
+ #region MakeCompoundAssignments
+ bool MakeCompoundAssignments(List<ILNode> body, ILExpression expr, int pos)
+ {
+ bool modified = false;
+ modified |= MakeCompoundAssignment(expr);
+ // Static fields and local variables are not handled here - those are expressions without side effects
+ // and get handled by ReplaceMethodCallsWithOperators
+ // (which does a reversible transform to the short operator form, as the introduction of checked/unchecked might have to revert to the long form).
+ foreach (ILExpression arg in expr.Arguments) {
+ modified |= MakeCompoundAssignments(null, arg, -1);
+ }
+ if (modified && body != null)
+ new ILInlining(method).InlineInto(body, pos, aggressive: false);
+ return modified;
+ }
+
+ bool MakeCompoundAssignment(ILExpression expr)
+ {
+ // stelem.any(T, ldloc(array), ldloc(pos), <OP>(ldelem.any(T, ldloc(array), ldloc(pos)), <RIGHT>))
+ // or
+ // stobj(T, ldloc(ptr), <OP>(ldobj(T, ldloc(ptr)), <RIGHT>))
+ ILCode expectedLdelemCode;
+ switch (expr.Code) {
+ case ILCode.Stelem_Any:
+ expectedLdelemCode = ILCode.Ldelem_Any;
+ break;
+ case ILCode.Stfld:
+ expectedLdelemCode = ILCode.Ldfld;
+ break;
+ case ILCode.Stobj:
+ expectedLdelemCode = ILCode.Ldobj;
+ break;
+ case ILCode.CallSetter:
+ expectedLdelemCode = ILCode.CallGetter;
+ break;
+ case ILCode.CallvirtSetter:
+ expectedLdelemCode = ILCode.CallvirtGetter;
+ break;
+ default:
+ return false;
+ }
+
+ // all arguments except the last (so either array+pos, or ptr):
+ bool hasGeneratedVar = false;
+ for (int i = 0; i < expr.Arguments.Count - 1; i++) {
+ ILVariable inputVar;
+ if (!expr.Arguments[i].Match(ILCode.Ldloc, out inputVar))
+ return false;
+ hasGeneratedVar |= inputVar.IsGenerated;
+ }
+ // At least one of the variables must be generated; otherwise we just keep the expanded form.
+ // We do this because we want compound assignments to be represented in ILAst only when strictly necessary;
+ // other compound assignments will be introduced by ReplaceMethodCallsWithOperator
+ // (which uses a reversible transformation, see ReplaceMethodCallsWithOperator.RestoreOriginalAssignOperatorAnnotation)
+ if (!hasGeneratedVar)
+ return false;
+
+ ILExpression op = expr.Arguments.Last();
+ // in case of compound assignments with a lifted operator the result is inside NullableOf and the operand is inside ValueOf
+ bool liftedOperator = false;
+ if (op.Code == ILCode.NullableOf) {
+ op = op.Arguments[0];
+ liftedOperator = true;
+ }
+ if (!CanBeRepresentedAsCompoundAssignment(op))
+ return false;
+
+ ILExpression ldelem = op.Arguments[0];
+ if (liftedOperator) {
+ if (ldelem.Code != ILCode.ValueOf)
+ return false;
+ ldelem = ldelem.Arguments[0];
+ }
+ if (ldelem.Code != expectedLdelemCode)
+ return false;
+ Debug.Assert(ldelem.Arguments.Count == expr.Arguments.Count - 1);
+ for (int i = 0; i < ldelem.Arguments.Count; i++) {
+ if (!ldelem.Arguments[i].MatchLdloc((ILVariable)expr.Arguments[i].Operand))
+ return false;
+ }
+ expr.Code = ILCode.CompoundAssignment;
+ expr.Operand = null;
+ expr.Arguments.RemoveRange(0, ldelem.Arguments.Count);
+ // result is "CompoundAssignment(<OP>(ldelem.any(...), <RIGHT>))"
+ return true;
+ }
+
+ static bool CanBeRepresentedAsCompoundAssignment(ILExpression expr)
+ {
+ switch (expr.Code) {
+ case ILCode.Add:
+ case ILCode.Add_Ovf:
+ case ILCode.Add_Ovf_Un:
+ case ILCode.Sub:
+ case ILCode.Sub_Ovf:
+ case ILCode.Sub_Ovf_Un:
+ case ILCode.Mul:
+ case ILCode.Mul_Ovf:
+ case ILCode.Mul_Ovf_Un:
+ case ILCode.Div:
+ case ILCode.Div_Un:
+ case ILCode.Rem:
+ case ILCode.Rem_Un:
+ case ILCode.And:
+ case ILCode.Or:
+ case ILCode.Xor:
+ case ILCode.Shl:
+ case ILCode.Shr:
+ case ILCode.Shr_Un:
+ return true;
+ case ILCode.Call:
+ var m = expr.Operand as MethodReference;
+ if (m == null || m.HasThis || expr.Arguments.Count != 2) return false;
+ switch (m.Name) {
+ case "op_Addition":
+ case "op_Subtraction":
+ case "op_Multiply":
+ case "op_Division":
+ case "op_Modulus":
+ case "op_BitwiseAnd":
+ case "op_BitwiseOr":
+ case "op_ExclusiveOr":
+ case "op_LeftShift":
+ case "op_RightShift":
+ return true;
+ default:
+ return false;
+ }
+ default:
+ return false;
+ }
+ }
+ #endregion
+
+ #region IntroducePostIncrement
+
+ bool IntroducePostIncrement(List<ILNode> body, ILExpression expr, int pos)
+ {
+ bool modified = IntroducePostIncrementForVariables(body, expr, pos);
+ Debug.Assert(body[pos] == expr); // IntroducePostIncrementForVariables shouldn't change the expression reference
+ ILExpression newExpr = IntroducePostIncrementForInstanceFields(expr);
+ if (newExpr != null) {
+ modified = true;
+ body[pos] = newExpr;
+ new ILInlining(method).InlineIfPossible(body, ref pos);
+ }
+ return modified;
+ }
+
+ bool IntroducePostIncrementForVariables(List<ILNode> body, ILExpression expr, int pos)
+ {
+ // Works for variables and static fields/properties
+
+ // expr = ldloc(i)
+ // stloc(i, add(expr, ldc.i4(1)))
+ // ->
+ // expr = postincrement(1, ldloca(i))
+ ILVariable exprVar;
+ ILExpression exprInit;
+ if (!(expr.Match(ILCode.Stloc, out exprVar, out exprInit) && exprVar.IsGenerated))
+ return false;
+
+ //The next expression
+ ILExpression nextExpr = body.ElementAtOrDefault(pos + 1) as ILExpression;
+ if (nextExpr == null)
+ return false;
+
+ ILCode loadInstruction = exprInit.Code;
+ ILCode storeInstruction = nextExpr.Code;
+ bool recombineVariable = false;
+
+ // We only recognise local variables, static fields, and static getters with no arguments
+ switch (loadInstruction) {
+ case ILCode.Ldloc:
+ //Must be a matching store type
+ if (storeInstruction != ILCode.Stloc)
+ return false;
+ ILVariable loadVar = (ILVariable)exprInit.Operand;
+ ILVariable storeVar = (ILVariable)nextExpr.Operand;
+ if (loadVar != storeVar) {
+ if (loadVar.OriginalVariable != null && loadVar.OriginalVariable == storeVar.OriginalVariable)
+ recombineVariable = true;
+ else
+ return false;
+ }
+ break;
+ case ILCode.Ldsfld:
+ if (storeInstruction != ILCode.Stsfld)
+ return false;
+ if (exprInit.Operand != nextExpr.Operand)
+ return false;
+ break;
+ case ILCode.CallGetter:
+ // non-static getters would have the 'this' argument
+ if (exprInit.Arguments.Count != 0)
+ return false;
+ if (storeInstruction != ILCode.CallSetter)
+ return false;
+ if (!IsGetterSetterPair(exprInit.Operand, nextExpr.Operand))
+ return false;
+ break;
+ default:
+ return false;
+ }
+
+ ILExpression addExpr = nextExpr.Arguments[0];
+
+ int incrementAmount;
+ ILCode incrementCode = GetIncrementCode(addExpr, out incrementAmount);
+ if (!(incrementAmount != 0 && addExpr.Arguments[0].MatchLdloc(exprVar)))
+ return false;
+
+ if (recombineVariable) {
+ // Split local variable, unsplit these two instances
+ // replace nextExpr.Operand with exprInit.Operand
+ ReplaceVariables(method, oldVar => oldVar == nextExpr.Operand ? (ILVariable)exprInit.Operand : oldVar);
+ }
+
+ switch (loadInstruction) {
+ case ILCode.Ldloc:
+ exprInit.Code = ILCode.Ldloca;
+ break;
+ case ILCode.Ldsfld:
+ exprInit.Code = ILCode.Ldsflda;
+ break;
+ case ILCode.CallGetter:
+ exprInit = new ILExpression(ILCode.AddressOf, null, exprInit);
+ break;
+ }
+ expr.Arguments[0] = new ILExpression(incrementCode, incrementAmount, exprInit);
+ body.RemoveAt(pos + 1); // TODO ILRanges
+ return true;
+ }
+
+ static bool IsGetterSetterPair(object getterOperand, object setterOperand)
+ {
+ MethodReference getter = getterOperand as MethodReference;
+ MethodReference setter = setterOperand as MethodReference;
+ if (getter == null || setter == null)
+ return false;
+ if (!TypeAnalysis.IsSameType(getter.DeclaringType, setter.DeclaringType))
+ return false;
+ MethodDefinition getterDef = getter.Resolve();
+ MethodDefinition setterDef = setter.Resolve();
+ if (getterDef == null || setterDef == null)
+ return false;
+ foreach (PropertyDefinition prop in getterDef.DeclaringType.Properties) {
+ if (prop.GetMethod == getterDef)
+ return prop.SetMethod == setterDef;
+ }
+ return false;
+ }
+
+ ILExpression IntroducePostIncrementForInstanceFields(ILExpression expr)
+ {
+ // stfld(field, ldloc(instance), add(stloc(helperVar, ldfld(field, ldloc(instance))), ldc.i4(1)))
+ // -> stloc(helperVar, postincrement(1, ldflda(field, ldloc(instance))))
+
+ // Also works for array elements and pointers:
+
+ // stelem.any(T, ldloc(instance), ldloc(pos), add(stloc(helperVar, ldelem.any(T, ldloc(instance), ldloc(pos))), ldc.i4(1)))
+ // -> stloc(helperVar, postincrement(1, ldelema(ldloc(instance), ldloc(pos))))
+
+ // stobj(T, ldloc(ptr), add(stloc(helperVar, ldobj(T, ldloc(ptr)), ldc.i4(1))))
+ // -> stloc(helperVar, postIncrement(1, ldloc(ptr)))
+
+ // callsetter(set_P, ldloc(instance), add(stloc(helperVar, callgetter(get_P, ldloc(instance))), ldc.i4(1)))
+ // -> stloc(helperVar, postIncrement(1, propertyaddress. callgetter(get_P, ldloc(instance))))
+
+ if (!(expr.Code == ILCode.Stfld || expr.Code.IsStoreToArray() || expr.Code == ILCode.Stobj || expr.Code == ILCode.CallSetter || expr.Code == ILCode.CallvirtSetter))
+ return null;
+
+ // Test that all arguments except the last are ldloc (1 arg for fields and pointers, 2 args for arrays)
+ for (int i = 0; i < expr.Arguments.Count - 1; i++) {
+ if (expr.Arguments[i].Code != ILCode.Ldloc)
+ return null;
+ }
+
+ ILExpression addExpr = expr.Arguments[expr.Arguments.Count - 1];
+ int incrementAmount;
+ ILCode incrementCode = GetIncrementCode(addExpr, out incrementAmount);
+ ILVariable helperVar;
+ ILExpression initialValue;
+ if (!(incrementAmount != 0 && addExpr.Arguments[0].Match(ILCode.Stloc, out helperVar, out initialValue)))
+ return null;
+
+ if (expr.Code == ILCode.Stfld) {
+ if (initialValue.Code != ILCode.Ldfld)
+ return null;
+ // There might be two different FieldReference instances, so we compare the field's signatures:
+ FieldReference getField = (FieldReference)initialValue.Operand;
+ FieldReference setField = (FieldReference)expr.Operand;
+ if (!(TypeAnalysis.IsSameType(getField.DeclaringType, setField.DeclaringType)
+ && getField.Name == setField.Name && TypeAnalysis.IsSameType(getField.FieldType, setField.FieldType)))
+ {
+ return null;
+ }
+ } else if (expr.Code == ILCode.Stobj) {
+ if (!(initialValue.Code == ILCode.Ldobj && initialValue.Operand == expr.Operand))
+ return null;
+ } else if (expr.Code == ILCode.CallSetter) {
+ if (!(initialValue.Code == ILCode.CallGetter && IsGetterSetterPair(initialValue.Operand, expr.Operand)))
+ return null;
+ } else if (expr.Code == ILCode.CallvirtSetter) {
+ if (!(initialValue.Code == ILCode.CallvirtGetter && IsGetterSetterPair(initialValue.Operand, expr.Operand)))
+ return null;
+ } else {
+ if (!initialValue.Code.IsLoadFromArray())
+ return null;
+ }
+ Debug.Assert(expr.Arguments.Count - 1 == initialValue.Arguments.Count);
+ for (int i = 0; i < initialValue.Arguments.Count; i++) {
+ if (!initialValue.Arguments[i].MatchLdloc((ILVariable)expr.Arguments[i].Operand))
+ return null;
+ }
+
+ ILExpression stloc = addExpr.Arguments[0];
+ if (expr.Code == ILCode.Stobj) {
+ stloc.Arguments[0] = new ILExpression(ILCode.PostIncrement, incrementAmount, initialValue.Arguments[0]);
+ } else if (expr.Code == ILCode.CallSetter || expr.Code == ILCode.CallvirtSetter) {
+ initialValue = new ILExpression(ILCode.AddressOf, null, initialValue);
+ stloc.Arguments[0] = new ILExpression(ILCode.PostIncrement, incrementAmount, initialValue);
+ } else {
+ stloc.Arguments[0] = new ILExpression(ILCode.PostIncrement, incrementAmount, initialValue);
+ initialValue.Code = (expr.Code == ILCode.Stfld ? ILCode.Ldflda : ILCode.Ldelema);
+ }
+ // TODO: ILRanges?
+
+ return stloc;
+ }
+
+ ILCode GetIncrementCode(ILExpression addExpr, out int incrementAmount)
+ {
+ ILCode incrementCode;
+ bool decrement = false;
+ switch (addExpr.Code) {
+ case ILCode.Add:
+ incrementCode = ILCode.PostIncrement;
+ break;
+ case ILCode.Add_Ovf:
+ incrementCode = ILCode.PostIncrement_Ovf;
+ break;
+ case ILCode.Add_Ovf_Un:
+ incrementCode = ILCode.PostIncrement_Ovf_Un;
+ break;
+ case ILCode.Sub:
+ incrementCode = ILCode.PostIncrement;
+ decrement = true;
+ break;
+ case ILCode.Sub_Ovf:
+ incrementCode = ILCode.PostIncrement_Ovf;
+ decrement = true;
+ break;
+ case ILCode.Sub_Ovf_Un:
+ incrementCode = ILCode.PostIncrement_Ovf_Un;
+ decrement = true;
+ break;
+ default:
+ incrementAmount = 0;
+ return ILCode.Nop;
+ }
+ if (addExpr.Arguments[1].Match(ILCode.Ldc_I4, out incrementAmount)) {
+ if (incrementAmount == -1 || incrementAmount == 1) { // TODO pointer increment?
+ if (decrement)
+ incrementAmount = -incrementAmount;
+ return incrementCode;
+ }
+ }
+ incrementAmount = 0;
+ return ILCode.Nop;
+ }
+ #endregion
+
+ #region IntroduceFixedStatements
+ bool IntroduceFixedStatements(List<ILNode> body, int i)
+ {
+ ILExpression initValue;
+ ILVariable pinnedVar;
+ int initEndPos;
+ if (!MatchFixedInitializer(body, i, out pinnedVar, out initValue, out initEndPos))
+ return false;
+
+ ILFixedStatement fixedStmt = body.ElementAtOrDefault(initEndPos) as ILFixedStatement;
+ if (fixedStmt != null) {
+ ILExpression expr = fixedStmt.BodyBlock.Body.LastOrDefault() as ILExpression;
+ if (expr != null && expr.Code == ILCode.Stloc && expr.Operand == pinnedVar && IsNullOrZero(expr.Arguments[0])) {
+ // we found a second initializer for the existing fixed statement
+ fixedStmt.Initializers.Insert(0, initValue);
+ body.RemoveRange(i, initEndPos - i);
+ fixedStmt.BodyBlock.Body.RemoveAt(fixedStmt.BodyBlock.Body.Count - 1);
+ if (pinnedVar.Type.IsByReference)
+ pinnedVar.Type = new PointerType(((ByReferenceType)pinnedVar.Type).ElementType);
+ return true;
+ }
+ }
+
+ // find where pinnedVar is reset to 0:
+ int j;
+ for (j = initEndPos; j < body.Count; j++) {
+ ILVariable v2;
+ ILExpression storedVal;
+ // stloc(pinned_Var, conv.u(ldc.i4(0)))
+ if (body[j].Match(ILCode.Stloc, out v2, out storedVal) && v2 == pinnedVar) {
+ if (IsNullOrZero(storedVal)) {
+ break;
+ }
+ }
+ }
+ // Create fixed statement from i to j
+ fixedStmt = new ILFixedStatement();
+ fixedStmt.Initializers.Add(initValue);
+ fixedStmt.BodyBlock = new ILBlock(body.GetRange(initEndPos, j - initEndPos)); // from initEndPos to j-1 (inclusive)
+ body.RemoveRange(i + 1, Math.Min(j, body.Count - 1) - i); // from i+1 to j (inclusive)
+ body[i] = fixedStmt;
+ if (pinnedVar.Type.IsByReference)
+ pinnedVar.Type = new PointerType(((ByReferenceType)pinnedVar.Type).ElementType);
+
+ return true;
+ }
+
+ bool IsNullOrZero(ILExpression expr)
+ {
+ if (expr.Code == ILCode.Conv_U || expr.Code == ILCode.Conv_I)
+ expr = expr.Arguments[0];
+ return (expr.Code == ILCode.Ldc_I4 && (int)expr.Operand == 0) || expr.Code == ILCode.Ldnull;
+ }
+
+ bool MatchFixedInitializer(List<ILNode> body, int i, out ILVariable pinnedVar, out ILExpression initValue, out int nextPos)
+ {
+ if (body[i].Match(ILCode.Stloc, out pinnedVar, out initValue) && pinnedVar.IsPinned && !IsNullOrZero(initValue)) {
+ initValue = (ILExpression)body[i];
+ nextPos = i + 1;
+ HandleStringFixing(pinnedVar, body, ref nextPos, ref initValue);
+ return true;
+ }
+ ILCondition ifStmt = body[i] as ILCondition;
+ ILExpression arrayLoadingExpr;
+ if (ifStmt != null && MatchFixedArrayInitializerCondition(ifStmt.Condition, out arrayLoadingExpr)) {
+ ILVariable arrayVariable = (ILVariable)arrayLoadingExpr.Operand;
+ ILExpression trueValue;
+ if (ifStmt.TrueBlock != null && ifStmt.TrueBlock.Body.Count == 1
+ && ifStmt.TrueBlock.Body[0].Match(ILCode.Stloc, out pinnedVar, out trueValue)
+ && pinnedVar.IsPinned && IsNullOrZero(trueValue))
+ {
+ if (ifStmt.FalseBlock != null && ifStmt.FalseBlock.Body.Count == 1 && ifStmt.FalseBlock.Body[0] is ILFixedStatement) {
+ ILFixedStatement fixedStmt = (ILFixedStatement)ifStmt.FalseBlock.Body[0];
+ ILVariable stlocVar;
+ ILExpression falseValue;
+ if (fixedStmt.Initializers.Count == 1 && fixedStmt.BodyBlock.Body.Count == 0
+ && fixedStmt.Initializers[0].Match(ILCode.Stloc, out stlocVar, out falseValue) && stlocVar == pinnedVar)
+ {
+ ILVariable loadedVariable;
+ if (falseValue.Code == ILCode.Ldelema
+ && falseValue.Arguments[0].Match(ILCode.Ldloc, out loadedVariable) && loadedVariable == arrayVariable
+ && IsNullOrZero(falseValue.Arguments[1]))
+ {
+ // OK, we detected the pattern for fixing an array.
+ // Now check whether the loading expression was a store ot a temp. var
+ // that can be eliminated.
+ if (arrayLoadingExpr.Code == ILCode.Stloc) {
+ ILInlining inlining = new ILInlining(method);
+ if (inlining.numLdloc.GetOrDefault(arrayVariable) == 2 &&
+ inlining.numStloc.GetOrDefault(arrayVariable) == 1 && inlining.numLdloca.GetOrDefault(arrayVariable) == 0)
+ {
+ arrayLoadingExpr = arrayLoadingExpr.Arguments[0];
+ }
+ }
+ initValue = new ILExpression(ILCode.Stloc, pinnedVar, arrayLoadingExpr);
+ nextPos = i + 1;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ initValue = null;
+ nextPos = -1;
+ return false;
+ }
+
+ bool MatchFixedArrayInitializerCondition(ILExpression condition, out ILExpression initValue)
+ {
+ ILExpression logicAnd;
+ ILVariable arrayVar;
+ if (condition.Match(ILCode.LogicNot, out logicAnd) && logicAnd.Code == ILCode.LogicAnd) {
+ initValue = UnpackDoubleNegation(logicAnd.Arguments[0]);
+ ILExpression arrayVarInitializer;
+ if (initValue.Match(ILCode.Ldloc, out arrayVar)
+ || initValue.Match(ILCode.Stloc, out arrayVar, out arrayVarInitializer))
+ {
+ ILExpression arrayLength = logicAnd.Arguments[1];
+ if (arrayLength.Code == ILCode.Conv_I4)
+ arrayLength = arrayLength.Arguments[0];
+ return arrayLength.Code == ILCode.Ldlen && arrayLength.Arguments[0].MatchLdloc(arrayVar);
+ }
+ }
+ initValue = null;
+ return false;
+ }
+
+ ILExpression UnpackDoubleNegation(ILExpression expr)
+ {
+ ILExpression negated;
+ if (expr.Match(ILCode.LogicNot, out negated) && negated.Match(ILCode.LogicNot, out negated))
+ return negated;
+ else
+ return expr;
+ }
+
+ bool HandleStringFixing(ILVariable pinnedVar, List<ILNode> body, ref int pos, ref ILExpression fixedStmtInitializer)
+ {
+ // fixed (stloc(pinnedVar, ldloc(text))) {
+ // var1 = var2 = conv.i(ldloc(pinnedVar))
+ // if (logicnot(logicnot(var1))) {
+ // var2 = add(var1, call(RuntimeHelpers::get_OffsetToStringData))
+ // }
+ // stloc(ptrVar, var2)
+ // ...
+
+ if (pos >= body.Count)
+ return false;
+
+ ILVariable var1, var2;
+ ILExpression varAssignment, ptrInitialization;
+ if (!(body[pos].Match(ILCode.Stloc, out var1, out varAssignment) && varAssignment.Match(ILCode.Stloc, out var2, out ptrInitialization)))
+ return false;
+ if (!(var1.IsGenerated && var2.IsGenerated))
+ return false;
+ if (ptrInitialization.Code == ILCode.Conv_I || ptrInitialization.Code == ILCode.Conv_U)
+ ptrInitialization = ptrInitialization.Arguments[0];
+ if (!ptrInitialization.MatchLdloc(pinnedVar))
+ return false;
+
+ ILCondition ifStmt = body[pos + 1] as ILCondition;
+ if (!(ifStmt != null && ifStmt.TrueBlock != null && ifStmt.TrueBlock.Body.Count == 1 && (ifStmt.FalseBlock == null || ifStmt.FalseBlock.Body.Count == 0)))
+ return false;
+ if (!UnpackDoubleNegation(ifStmt.Condition).MatchLdloc(var1))
+ return false;
+ ILVariable assignedVar;
+ ILExpression assignedExpr;
+ if (!(ifStmt.TrueBlock.Body[0].Match(ILCode.Stloc, out assignedVar, out assignedExpr) && assignedVar == var2 && assignedExpr.Code == ILCode.Add))
+ return false;
+ MethodReference calledMethod;
+ if (!(assignedExpr.Arguments[0].MatchLdloc(var1)))
+ return false;
+ if (!(assignedExpr.Arguments[1].Match(ILCode.Call, out calledMethod) || assignedExpr.Arguments[1].Match(ILCode.CallGetter, out calledMethod)))
+ return false;
+ if (!(calledMethod.Name == "get_OffsetToStringData" && calledMethod.DeclaringType.FullName == "System.Runtime.CompilerServices.RuntimeHelpers"))
+ return false;
+
+ ILVariable pointerVar;
+ if (body[pos + 2].Match(ILCode.Stloc, out pointerVar, out assignedExpr) && assignedExpr.MatchLdloc(var2)) {
+ pos += 3;
+ fixedStmtInitializer.Operand = pointerVar;
+ return true;
+ }
+ return false;
+ }
+ #endregion
+
+ #region SimplifyLogicNot
+ static bool SimplifyLogicNot(List<ILNode> body, ILExpression expr, int pos)
+ {
+ bool modified = false;
+ expr = SimplifyLogicNot(expr, ref modified);
+ Debug.Assert(expr == null);
+ return modified;
+ }
+
+ static ILExpression SimplifyLogicNot(ILExpression expr, ref bool modified)
+ {
+ ILExpression a;
+ // "ceq(a, ldc.i4.0)" becomes "logicnot(a)" if the inferred type for expression "a" is boolean
+ if (expr.Code == ILCode.Ceq && TypeAnalysis.IsBoolean(expr.Arguments[0].InferredType) && (a = expr.Arguments[1]).Code == ILCode.Ldc_I4 && (int)a.Operand == 0) {
+ expr.Code = ILCode.LogicNot;
+ expr.ILRanges.AddRange(a.ILRanges);
+ expr.Arguments.RemoveAt(1);
+ modified = true;
+ }
+
+ ILExpression res = null;
+ while (expr.Code == ILCode.LogicNot) {
+ a = expr.Arguments[0];
+ // remove double negation
+ if (a.Code == ILCode.LogicNot) {
+ res = a.Arguments[0];
+ res.ILRanges.AddRange(expr.ILRanges);
+ res.ILRanges.AddRange(a.ILRanges);
+ expr = res;
+ } else {
+ if (SimplifyLogicNotArgument(expr)) res = expr = a;
+ break;
+ }
+ }
+
+ for (int i = 0; i < expr.Arguments.Count; i++) {
+ a = SimplifyLogicNot(expr.Arguments[i], ref modified);
+ if (a != null) {
+ expr.Arguments[i] = a;
+ modified = true;
+ }
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// If the argument is a binary comparison operation then the negation is pushed through it
+ /// </summary>
+ static bool SimplifyLogicNotArgument(ILExpression expr)
+ {
+ var a = expr.Arguments[0];
+ ILCode c;
+ switch (a.Code) {
+ case ILCode.Ceq: c = ILCode.Cne; break;
+ case ILCode.Cne: c = ILCode.Ceq; break;
+ case ILCode.Cgt: c = ILCode.Cle; break;
+ case ILCode.Cgt_Un: c = ILCode.Cle_Un; break;
+ case ILCode.Cge: c = ILCode.Clt; break;
+ case ILCode.Cge_Un: c = ILCode.Clt_Un; break;
+ case ILCode.Clt: c = ILCode.Cge; break;
+ case ILCode.Clt_Un: c = ILCode.Cge_Un; break;
+ case ILCode.Cle: c = ILCode.Cgt; break;
+ case ILCode.Cle_Un: c = ILCode.Cgt_Un; break;
+ default: return false;
+ }
+ a.Code = c;
+ a.ILRanges.AddRange(expr.ILRanges);
+ return true;
+ }
+ #endregion
+
+ #region SimplifyShiftOperators
+ static bool SimplifyShiftOperators(List<ILNode> body, ILExpression expr, int pos)
+ {
+ // C# compiles "a << b" to "a << (b & 31)", so we will remove the "& 31" if possible.
+ bool modified = false;
+ SimplifyShiftOperators(expr, ref modified);
+ return modified;
+ }
+
+ static void SimplifyShiftOperators(ILExpression expr, ref bool modified)
+ {
+ for (int i = 0; i < expr.Arguments.Count; i++)
+ SimplifyShiftOperators(expr.Arguments[i], ref modified);
+ if (expr.Code != ILCode.Shl && expr.Code != ILCode.Shr && expr.Code != ILCode.Shr_Un)
+ return;
+ var a = expr.Arguments[1];
+ if (a.Code != ILCode.And || a.Arguments[1].Code != ILCode.Ldc_I4 || expr.InferredType == null)
+ return;
+ int mask;
+ switch (expr.InferredType.MetadataType) {
+ case MetadataType.Int32:
+ case MetadataType.UInt32: mask = 31; break;
+ case MetadataType.Int64:
+ case MetadataType.UInt64: mask = 63; break;
+ default: return;
+ }
+ if ((int)a.Arguments[1].Operand != mask) return;
+ var res = a.Arguments[0];
+ res.ILRanges.AddRange(a.ILRanges);
+ res.ILRanges.AddRange(a.Arguments[1].ILRanges);
+ expr.Arguments[1] = res;
+ modified = true;
+ }
+ #endregion
+
+ #region InlineExpressionTreeParameterDeclarations
+ bool InlineExpressionTreeParameterDeclarations(List<ILNode> body, ILExpression expr, int pos)
+ {
+ // When there is a Expression.Lambda() call, and the parameters are declared in the
+ // IL statement immediately prior to the one containing the Lambda() call,
+ // using this code for the3 declaration:
+ // stloc(v, call(Expression::Parameter, call(Type::GetTypeFromHandle, ldtoken(...)), ldstr(...)))
+ // and the variables v are assigned only once (in that statements), and read only in a Expression::Lambda
+ // call that immediately follows the assignment statements, then we will inline those assignments
+ // into the Lambda call using ILCode.ExpressionTreeParameterDeclarations.
+
+ // This is sufficient to allow inlining over the expression tree construction. The remaining translation
+ // of expression trees into C# will be performed by a C# AST transformer.
+
+ for (int i = expr.Arguments.Count - 1; i >= 0; i--) {
+ if (InlineExpressionTreeParameterDeclarations(body, expr.Arguments[i], pos))
+ return true;
+ }
+
+ MethodReference mr;
+ ILExpression lambdaBodyExpr, parameterArray;
+ if (!(expr.Match(ILCode.Call, out mr, out lambdaBodyExpr, out parameterArray) && mr.Name == "Lambda"))
+ return false;
+ if (!(parameterArray.Code == ILCode.InitArray && mr.DeclaringType.FullName == "System.Linq.Expressions.Expression"))
+ return false;
+ int firstParameterPos = pos - parameterArray.Arguments.Count;
+ if (firstParameterPos < 0)
+ return false;
+
+ ILExpression[] parameterInitExpressions = new ILExpression[parameterArray.Arguments.Count + 1];
+ for (int i = 0; i < parameterArray.Arguments.Count; i++) {
+ parameterInitExpressions[i] = body[firstParameterPos + i] as ILExpression;
+ if (!MatchParameterVariableAssignment(parameterInitExpressions[i]))
+ return false;
+ ILVariable v = (ILVariable)parameterInitExpressions[i].Operand;
+ if (!parameterArray.Arguments[i].MatchLdloc(v))
+ return false;
+ // TODO: validate that the variable is only used here and within 'body'
+ }
+
+ parameterInitExpressions[parameterInitExpressions.Length - 1] = lambdaBodyExpr;
+ Debug.Assert(expr.Arguments[0] == lambdaBodyExpr);
+ expr.Arguments[0] = new ILExpression(ILCode.ExpressionTreeParameterDeclarations, null, parameterInitExpressions);
+
+ body.RemoveRange(firstParameterPos, parameterArray.Arguments.Count);
+
+ return true;
+ }
+
+ bool MatchParameterVariableAssignment(ILExpression expr)
+ {
+ // stloc(v, call(Expression::Parameter, call(Type::GetTypeFromHandle, ldtoken(...)), ldstr(...)))
+ ILVariable v;
+ ILExpression init;
+ if (!expr.Match(ILCode.Stloc, out v, out init))
+ return false;
+ if (v.IsGenerated || v.IsParameter || v.IsPinned)
+ return false;
+ if (v.Type == null || v.Type.FullName != "System.Linq.Expressions.ParameterExpression")
+ return false;
+ MethodReference parameterMethod;
+ ILExpression typeArg, nameArg;
+ if (!init.Match(ILCode.Call, out parameterMethod, out typeArg, out nameArg))
+ return false;
+ if (!(parameterMethod.Name == "Parameter" && parameterMethod.DeclaringType.FullName == "System.Linq.Expressions.Expression"))
+ return false;
+ MethodReference getTypeFromHandle;
+ ILExpression typeToken;
+ if (!typeArg.Match(ILCode.Call, out getTypeFromHandle, out typeToken))
+ return false;
+ if (!(getTypeFromHandle.Name == "GetTypeFromHandle" && getTypeFromHandle.DeclaringType.FullName == "System.Type"))
+ return false;
+ return typeToken.Code == ILCode.Ldtoken && nameArg.Code == ILCode.Ldstr;
+ }
+ #endregion
+ }
+}
diff --git a/ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs b/ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs
new file mode 100644
index 00000000..d3a74a37
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs
@@ -0,0 +1,376 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ public class SimpleControlFlow
+ {
+ Dictionary<ILLabel, int> labelGlobalRefCount = new Dictionary<ILLabel, int>();
+ Dictionary<ILLabel, ILBasicBlock> labelToBasicBlock = new Dictionary<ILLabel, ILBasicBlock>();
+
+ DecompilerContext context;
+ TypeSystem typeSystem;
+
+ public SimpleControlFlow(DecompilerContext context, ILBlock method)
+ {
+ this.context = context;
+ typeSystem = context.CurrentMethod.Module.TypeSystem;
+
+ foreach(ILLabel target in method.GetSelfAndChildrenRecursive<ILExpression>(e => e.IsBranch()).SelectMany(e => e.GetBranchTargets())) {
+ labelGlobalRefCount[target] = labelGlobalRefCount.GetOrDefault(target) + 1;
+ }
+ foreach(ILBasicBlock bb in method.GetSelfAndChildrenRecursive<ILBasicBlock>()) {
+ foreach(ILLabel label in bb.GetChildren().OfType<ILLabel>()) {
+ labelToBasicBlock[label] = bb;
+ }
+ }
+ }
+
+ public bool SimplifyTernaryOperator(List<ILNode> body, ILBasicBlock head, int pos)
+ {
+ Debug.Assert(body.Contains(head));
+
+ ILExpression condExpr;
+ ILLabel trueLabel;
+ ILLabel falseLabel;
+ ILVariable trueLocVar = null;
+ ILExpression trueExpr;
+ ILLabel trueFall;
+ ILVariable falseLocVar = null;
+ ILExpression falseExpr;
+ ILLabel falseFall;
+ object unused;
+
+ if (head.MatchLastAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel) &&
+ labelGlobalRefCount[trueLabel] == 1 &&
+ labelGlobalRefCount[falseLabel] == 1 &&
+ ((labelToBasicBlock[trueLabel].MatchSingleAndBr(ILCode.Stloc, out trueLocVar, out trueExpr, out trueFall) &&
+ labelToBasicBlock[falseLabel].MatchSingleAndBr(ILCode.Stloc, out falseLocVar, out falseExpr, out falseFall) &&
+ trueLocVar == falseLocVar && trueFall == falseFall) ||
+ (labelToBasicBlock[trueLabel].MatchSingle(ILCode.Ret, out unused, out trueExpr) &&
+ labelToBasicBlock[falseLabel].MatchSingle(ILCode.Ret, out unused, out falseExpr))) &&
+ body.Contains(labelToBasicBlock[trueLabel]) &&
+ body.Contains(labelToBasicBlock[falseLabel])
+ )
+ {
+ bool isStloc = trueLocVar != null;
+ ILCode opCode = isStloc ? ILCode.Stloc : ILCode.Ret;
+ TypeReference retType = isStloc ? trueLocVar.Type : context.CurrentMethod.ReturnType;
+ bool retTypeIsBoolean = TypeAnalysis.IsBoolean(retType);
+ int leftBoolVal;
+ int rightBoolVal;
+ ILExpression newExpr;
+ // a ? true:false is equivalent to a
+ // a ? false:true is equivalent to !a
+ // a ? true : b is equivalent to a || b
+ // a ? b : true is equivalent to !a || b
+ // a ? b : false is equivalent to a && b
+ // a ? false : b is equivalent to !a && b
+ if (retTypeIsBoolean &&
+ trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal) &&
+ falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal) &&
+ ((leftBoolVal != 0 && rightBoolVal == 0) || (leftBoolVal == 0 && rightBoolVal != 0))
+ )
+ {
+ // It can be expressed as trivilal expression
+ if (leftBoolVal != 0) {
+ newExpr = condExpr;
+ } else {
+ newExpr = new ILExpression(ILCode.LogicNot, null, condExpr) { InferredType = typeSystem.Boolean };
+ }
+ } else if ((retTypeIsBoolean || TypeAnalysis.IsBoolean(falseExpr.InferredType)) && trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal) && (leftBoolVal == 0 || leftBoolVal == 1)) {
+ // It can be expressed as logical expression
+ if (leftBoolVal != 0) {
+ newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, condExpr, falseExpr);
+ } else {
+ newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, new ILExpression(ILCode.LogicNot, null, condExpr), falseExpr);
+ }
+ } else if ((retTypeIsBoolean || TypeAnalysis.IsBoolean(trueExpr.InferredType)) && falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal) && (rightBoolVal == 0 || rightBoolVal == 1)) {
+ // It can be expressed as logical expression
+ if (rightBoolVal != 0) {
+ newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, new ILExpression(ILCode.LogicNot, null, condExpr), trueExpr);
+ } else {
+ newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, condExpr, trueExpr);
+ }
+ } else {
+ // Ternary operator tends to create long complicated return statements
+ if (opCode == ILCode.Ret)
+ return false;
+
+ // Only simplify generated variables
+ if (opCode == ILCode.Stloc && !trueLocVar.IsGenerated)
+ return false;
+
+ // Create ternary expression
+ newExpr = new ILExpression(ILCode.TernaryOp, null, condExpr, trueExpr, falseExpr);
+ }
+
+ head.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
+ head.Body.Add(new ILExpression(opCode, trueLocVar, newExpr));
+ if (isStloc)
+ head.Body.Add(new ILExpression(ILCode.Br, trueFall));
+
+ // Remove the old basic blocks
+ body.RemoveOrThrow(labelToBasicBlock[trueLabel]);
+ body.RemoveOrThrow(labelToBasicBlock[falseLabel]);
+
+ return true;
+ }
+ return false;
+ }
+
+ public bool SimplifyNullCoalescing(List<ILNode> body, ILBasicBlock head, int pos)
+ {
+ // ...
+ // v = ldloc(leftVar)
+ // brtrue(endBBLabel, ldloc(leftVar))
+ // br(rightBBLabel)
+ //
+ // rightBBLabel:
+ // v = rightExpr
+ // br(endBBLabel)
+ // ...
+ // =>
+ // ...
+ // v = NullCoalescing(ldloc(leftVar), rightExpr)
+ // br(endBBLabel)
+
+ ILVariable v, v2;
+ ILExpression leftExpr, leftExpr2;
+ ILVariable leftVar;
+ ILLabel endBBLabel, endBBLabel2;
+ ILLabel rightBBLabel;
+ ILBasicBlock rightBB;
+ ILExpression rightExpr;
+ if (head.Body.Count >= 3 &&
+ head.Body[head.Body.Count - 3].Match(ILCode.Stloc, out v, out leftExpr) &&
+ leftExpr.Match(ILCode.Ldloc, out leftVar) &&
+ head.MatchLastAndBr(ILCode.Brtrue, out endBBLabel, out leftExpr2, out rightBBLabel) &&
+ leftExpr2.MatchLdloc(leftVar) &&
+ labelToBasicBlock.TryGetValue(rightBBLabel, out rightBB) &&
+ rightBB.MatchSingleAndBr(ILCode.Stloc, out v2, out rightExpr, out endBBLabel2) &&
+ v == v2 &&
+ endBBLabel == endBBLabel2 &&
+ labelGlobalRefCount.GetOrDefault(rightBBLabel) == 1 &&
+ body.Contains(rightBB)
+ )
+ {
+ head.Body.RemoveTail(ILCode.Stloc, ILCode.Brtrue, ILCode.Br);
+ head.Body.Add(new ILExpression(ILCode.Stloc, v, new ILExpression(ILCode.NullCoalescing, null, leftExpr, rightExpr)));
+ head.Body.Add(new ILExpression(ILCode.Br, endBBLabel));
+
+ body.RemoveOrThrow(labelToBasicBlock[rightBBLabel]);
+ return true;
+ }
+ return false;
+ }
+
+ public bool SimplifyShortCircuit(List<ILNode> body, ILBasicBlock head, int pos)
+ {
+ Debug.Assert(body.Contains(head));
+
+ ILExpression condExpr;
+ ILLabel trueLabel;
+ ILLabel falseLabel;
+ if(head.MatchLastAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel)) {
+ for (int pass = 0; pass < 2; pass++) {
+
+ // On the second pass, swap labels and negate expression of the first branch
+ // It is slightly ugly, but much better then copy-pasting this whole block
+ ILLabel nextLabel = (pass == 0) ? trueLabel : falseLabel;
+ ILLabel otherLablel = (pass == 0) ? falseLabel : trueLabel;
+ bool negate = (pass == 1);
+
+ ILBasicBlock nextBasicBlock = labelToBasicBlock[nextLabel];
+ ILExpression nextCondExpr;
+ ILLabel nextTrueLablel;
+ ILLabel nextFalseLabel;
+ if (body.Contains(nextBasicBlock) &&
+ nextBasicBlock != head &&
+ labelGlobalRefCount[(ILLabel)nextBasicBlock.Body.First()] == 1 &&
+ nextBasicBlock.MatchSingleAndBr(ILCode.Brtrue, out nextTrueLablel, out nextCondExpr, out nextFalseLabel) &&
+ (otherLablel == nextFalseLabel || otherLablel == nextTrueLablel))
+ {
+ // Create short cicuit branch
+ ILExpression logicExpr;
+ if (otherLablel == nextFalseLabel) {
+ logicExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, negate ? new ILExpression(ILCode.LogicNot, null, condExpr) : condExpr, nextCondExpr);
+ } else {
+ logicExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, negate ? condExpr : new ILExpression(ILCode.LogicNot, null, condExpr), nextCondExpr);
+ }
+ head.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
+ head.Body.Add(new ILExpression(ILCode.Brtrue, nextTrueLablel, logicExpr));
+ head.Body.Add(new ILExpression(ILCode.Br, nextFalseLabel));
+
+ // Remove the inlined branch from scope
+ body.RemoveOrThrow(nextBasicBlock);
+
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public bool SimplifyCustomShortCircuit(List<ILNode> body, ILBasicBlock head, int pos)
+ {
+ Debug.Assert(body.Contains(head));
+
+ // --- looking for the following pattern ---
+ // stloc(targetVar, leftVar)
+ // brtrue(exitLabel, call(op_False, leftVar)
+ // br(followingBlock)
+ //
+ // FollowingBlock:
+ // stloc(targetVar, call(op_BitwiseAnd, leftVar, rightExpression))
+ // br(exitLabel)
+ // ---
+
+ if (head.Body.Count < 3)
+ return false;
+
+ // looking for:
+ // stloc(targetVar, leftVar)
+ ILVariable targetVar;
+ ILExpression targetVarInitExpr;
+ if (!head.Body[head.Body.Count - 3].Match(ILCode.Stloc, out targetVar, out targetVarInitExpr))
+ return false;
+
+ ILVariable leftVar;
+ if (!targetVarInitExpr.Match(ILCode.Ldloc, out leftVar))
+ return false;
+
+ // looking for:
+ // brtrue(exitLabel, call(op_False, leftVar)
+ // br(followingBlock)
+ ILExpression callExpr;
+ ILLabel exitLabel;
+ ILLabel followingBlock;
+ if(!head.MatchLastAndBr(ILCode.Brtrue, out exitLabel, out callExpr, out followingBlock))
+ return false;
+
+ if (labelGlobalRefCount[followingBlock] > 1)
+ return false;
+
+ MethodReference opFalse;
+ ILExpression opFalseArg;
+ if (!callExpr.Match(ILCode.Call, out opFalse, out opFalseArg))
+ return false;
+
+ // ignore operators other than op_False and op_True
+ if (opFalse.Name != "op_False" && opFalse.Name != "op_True")
+ return false;
+
+ if (!opFalseArg.MatchLdloc(leftVar))
+ return false;
+
+ ILBasicBlock followingBasicBlock = labelToBasicBlock[followingBlock];
+
+ // FollowingBlock:
+ // stloc(targetVar, call(op_BitwiseAnd, leftVar, rightExpression))
+ // br(exitLabel)
+ ILVariable _targetVar;
+ ILExpression opBitwiseCallExpr;
+ ILLabel _exitLabel;
+ if (!followingBasicBlock.MatchSingleAndBr(ILCode.Stloc, out _targetVar, out opBitwiseCallExpr, out _exitLabel))
+ return false;
+
+ if (_targetVar != targetVar || exitLabel != _exitLabel)
+ return false;
+
+ MethodReference opBitwise;
+ ILExpression leftVarExpression;
+ ILExpression rightExpression;
+ if (!opBitwiseCallExpr.Match(ILCode.Call, out opBitwise, out leftVarExpression, out rightExpression))
+ return false;
+
+ if (!leftVarExpression.MatchLdloc(leftVar))
+ return false;
+
+ // ignore operators other than op_BitwiseAnd and op_BitwiseOr
+ if (opBitwise.Name != "op_BitwiseAnd" && opBitwise.Name != "op_BitwiseOr")
+ return false;
+
+ // insert:
+ // stloc(targetVar, LogicAnd(C::op_BitwiseAnd, leftVar, rightExpression)
+ // br(exitLabel)
+ ILCode op = opBitwise.Name == "op_BitwiseAnd" ? ILCode.LogicAnd : ILCode.LogicOr;
+
+ if (op == ILCode.LogicAnd && opFalse.Name != "op_False")
+ return false;
+
+ if (op == ILCode.LogicOr && opFalse.Name != "op_True")
+ return false;
+
+ ILExpression shortCircuitExpr = MakeLeftAssociativeShortCircuit(op, opFalseArg, rightExpression);
+ shortCircuitExpr.Operand = opBitwise;
+
+ head.Body.RemoveTail(ILCode.Stloc, ILCode.Brtrue, ILCode.Br);
+ head.Body.Add(new ILExpression(ILCode.Stloc, targetVar, shortCircuitExpr));
+ head.Body.Add(new ILExpression(ILCode.Br, exitLabel));
+ body.Remove(followingBasicBlock);
+
+ return true;
+ }
+
+ ILExpression MakeLeftAssociativeShortCircuit(ILCode code, ILExpression left, ILExpression right)
+ {
+ // Assuming that the inputs are already left associative
+ if (right.Match(code)) {
+ // Find the leftmost logical expression
+ ILExpression current = right;
+ while(current.Arguments[0].Match(code))
+ current = current.Arguments[0];
+ current.Arguments[0] = new ILExpression(code, null, left, current.Arguments[0]) { InferredType = typeSystem.Boolean };
+ return right;
+ } else {
+ return new ILExpression(code, null, left, right) { InferredType = typeSystem.Boolean };
+ }
+ }
+
+ public bool JoinBasicBlocks(List<ILNode> body, ILBasicBlock head, int pos)
+ {
+ ILLabel nextLabel;
+ ILBasicBlock nextBB;
+ if (!head.Body.ElementAtOrDefault(head.Body.Count - 2).IsConditionalControlFlow() &&
+ head.Body.Last().Match(ILCode.Br, out nextLabel) &&
+ labelGlobalRefCount[nextLabel] == 1 &&
+ labelToBasicBlock.TryGetValue(nextLabel, out nextBB) &&
+ body.Contains(nextBB) &&
+ nextBB.Body.First() == nextLabel &&
+ !nextBB.Body.OfType<ILTryCatchBlock>().Any()
+ )
+ {
+ head.Body.RemoveTail(ILCode.Br);
+ nextBB.Body.RemoveAt(0); // Remove label
+ head.Body.AddRange(nextBB.Body);
+
+ body.RemoveOrThrow(nextBB);
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/ILAst/StateRange.cs b/ICSharpCode.Decompiler/ILAst/StateRange.cs
new file mode 100644
index 00000000..ef27c498
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/StateRange.cs
@@ -0,0 +1,312 @@
+// Copyright (c) 2012 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ internal struct Interval
+ {
+ public readonly int Start, End;
+
+ public Interval(int start, int end)
+ {
+ Debug.Assert(start <= end || (start == 0 && end == -1));
+ Start = start;
+ End = end;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("({0} to {1})", Start, End);
+ }
+ }
+
+ internal class StateRange
+ {
+ readonly List<Interval> data = new List<Interval>();
+
+ public StateRange()
+ {
+ }
+
+ public StateRange(int start, int end)
+ {
+ data.Add(new Interval(start, end));
+ }
+
+ public bool IsEmpty {
+ get { return data.Count == 0; }
+ }
+
+ public bool Contains(int val)
+ {
+ foreach (Interval v in data) {
+ if (v.Start <= val && val <= v.End)
+ return true;
+ }
+ return false;
+ }
+
+ public void UnionWith(StateRange other)
+ {
+ data.AddRange(other.data);
+ }
+
+ /// <summary>
+ /// Unions this state range with (other intersect (minVal to maxVal))
+ /// </summary>
+ public void UnionWith(StateRange other, int minVal, int maxVal)
+ {
+ foreach (Interval v in other.data) {
+ int start = Math.Max(v.Start, minVal);
+ int end = Math.Min(v.End, maxVal);
+ if (start <= end)
+ data.Add(new Interval(start, end));
+ }
+ }
+
+ /// <summary>
+ /// Merges overlapping interval ranges.
+ /// </summary>
+ public void Simplify()
+ {
+ if (data.Count < 2)
+ return;
+ data.Sort((a, b) => a.Start.CompareTo(b.Start));
+ Interval prev = data[0];
+ int prevIndex = 0;
+ for (int i = 1; i < data.Count; i++) {
+ Interval next = data[i];
+ Debug.Assert(prev.Start <= next.Start);
+ if (next.Start <= prev.End + 1) { // intervals overlapping or touching
+ prev = new Interval(prev.Start, Math.Max(prev.End, next.End));
+ data[prevIndex] = prev;
+ data[i] = new Interval(0, -1); // mark as deleted
+ } else {
+ prev = next;
+ prevIndex = i;
+ }
+ }
+ data.RemoveAll(i => i.Start > i.End); // remove all entries that were marked as deleted
+ }
+
+ public override string ToString()
+ {
+ return string.Join(",", data);
+ }
+
+ public Interval ToEnclosingInterval()
+ {
+ if (data.Count == 0)
+ throw new SymbolicAnalysisFailedException();
+ return new Interval(data[0].Start, data[data.Count - 1].End);
+ }
+ }
+
+ internal enum StateRangeAnalysisMode
+ {
+ IteratorMoveNext,
+ IteratorDispose,
+ AsyncMoveNext
+ }
+
+ internal class StateRangeAnalysis
+ {
+ readonly StateRangeAnalysisMode mode;
+ readonly FieldDefinition stateField;
+ internal DefaultDictionary<ILNode, StateRange> ranges;
+ SymbolicEvaluationContext evalContext;
+
+ internal Dictionary<MethodDefinition, StateRange> finallyMethodToStateRange; // used only for IteratorDispose
+
+ /// <summary>
+ /// Initializes the state range logic:
+ /// Clears 'ranges' and sets 'ranges[entryPoint]' to the full range (int.MinValue to int.MaxValue)
+ /// </summary>
+ public StateRangeAnalysis(ILNode entryPoint, StateRangeAnalysisMode mode, FieldDefinition stateField, ILVariable cachedStateVar = null)
+ {
+ this.mode = mode;
+ this.stateField = stateField;
+ if (mode == StateRangeAnalysisMode.IteratorDispose) {
+ finallyMethodToStateRange = new Dictionary<MethodDefinition, StateRange>();
+ }
+
+ ranges = new DefaultDictionary<ILNode, StateRange>(n => new StateRange());
+ ranges[entryPoint] = new StateRange(int.MinValue, int.MaxValue);
+ evalContext = new SymbolicEvaluationContext(stateField);
+ if (cachedStateVar != null)
+ evalContext.AddStateVariable(cachedStateVar);
+ }
+
+ public int AssignStateRanges(List<ILNode> body, int bodyLength)
+ {
+ if (bodyLength == 0)
+ return 0;
+ for (int i = 0; i < bodyLength; i++) {
+ StateRange nodeRange = ranges[body[i]];
+ nodeRange.Simplify();
+
+ ILLabel label = body[i] as ILLabel;
+ if (label != null) {
+ ranges[body[i + 1]].UnionWith(nodeRange);
+ continue;
+ }
+
+ ILTryCatchBlock tryFinally = body[i] as ILTryCatchBlock;
+ if (tryFinally != null) {
+ if (mode == StateRangeAnalysisMode.IteratorDispose) {
+ if (tryFinally.CatchBlocks.Count != 0 || tryFinally.FaultBlock != null || tryFinally.FinallyBlock == null)
+ throw new SymbolicAnalysisFailedException();
+ ranges[tryFinally.TryBlock].UnionWith(nodeRange);
+ if (tryFinally.TryBlock.Body.Count != 0) {
+ ranges[tryFinally.TryBlock.Body[0]].UnionWith(nodeRange);
+ AssignStateRanges(tryFinally.TryBlock.Body, tryFinally.TryBlock.Body.Count);
+ }
+ continue;
+ } else if (mode == StateRangeAnalysisMode.AsyncMoveNext) {
+ return i;
+ } else {
+ throw new SymbolicAnalysisFailedException();
+ }
+ }
+
+ ILExpression expr = body[i] as ILExpression;
+ if (expr == null)
+ throw new SymbolicAnalysisFailedException();
+ switch (expr.Code) {
+ case ILCode.Switch:
+ {
+ SymbolicValue val = evalContext.Eval(expr.Arguments[0]);
+ if (val.Type != SymbolicValueType.State)
+ goto default;
+ ILLabel[] targetLabels = (ILLabel[])expr.Operand;
+ for (int j = 0; j < targetLabels.Length; j++) {
+ int state = j - val.Constant;
+ ranges[targetLabels[j]].UnionWith(nodeRange, state, state);
+ }
+ StateRange nextRange = ranges[body[i + 1]];
+ nextRange.UnionWith(nodeRange, int.MinValue, -1 - val.Constant);
+ nextRange.UnionWith(nodeRange, targetLabels.Length - val.Constant, int.MaxValue);
+ break;
+ }
+ case ILCode.Br:
+ case ILCode.Leave:
+ ranges[(ILLabel)expr.Operand].UnionWith(nodeRange);
+ break;
+ case ILCode.Brtrue:
+ {
+ SymbolicValue val = evalContext.Eval(expr.Arguments[0]).AsBool();
+ if (val.Type == SymbolicValueType.StateEquals) {
+ ranges[(ILLabel)expr.Operand].UnionWith(nodeRange, val.Constant, val.Constant);
+ StateRange nextRange = ranges[body[i + 1]];
+ nextRange.UnionWith(nodeRange, int.MinValue, val.Constant - 1);
+ nextRange.UnionWith(nodeRange, val.Constant + 1, int.MaxValue);
+ break;
+ } else if (val.Type == SymbolicValueType.StateInEquals) {
+ ranges[body[i + 1]].UnionWith(nodeRange, val.Constant, val.Constant);
+ StateRange targetRange = ranges[(ILLabel)expr.Operand];
+ targetRange.UnionWith(nodeRange, int.MinValue, val.Constant - 1);
+ targetRange.UnionWith(nodeRange, val.Constant + 1, int.MaxValue);
+ break;
+ } else {
+ goto default;
+ }
+ }
+ case ILCode.Nop:
+ ranges[body[i + 1]].UnionWith(nodeRange);
+ break;
+ case ILCode.Ret:
+ break;
+ case ILCode.Stloc:
+ {
+ SymbolicValue val = evalContext.Eval(expr.Arguments[0]);
+ if (val.Type == SymbolicValueType.State && val.Constant == 0) {
+ evalContext.AddStateVariable((ILVariable)expr.Operand);
+ goto case ILCode.Nop;
+ } else {
+ goto default;
+ }
+ }
+ case ILCode.Call:
+ // in some cases (e.g. foreach over array) the C# compiler produces a finally method outside of try-finally blocks
+ if (mode == StateRangeAnalysisMode.IteratorDispose) {
+ MethodDefinition mdef = (expr.Operand as MethodReference).ResolveWithinSameModule();
+ if (mdef == null || finallyMethodToStateRange.ContainsKey(mdef))
+ throw new SymbolicAnalysisFailedException();
+ finallyMethodToStateRange.Add(mdef, nodeRange);
+ break;
+ } else {
+ goto default;
+ }
+ default:
+ if (mode == StateRangeAnalysisMode.IteratorDispose) {
+ throw new SymbolicAnalysisFailedException();
+ } else {
+ return i;
+ }
+ }
+ }
+ return bodyLength;
+ }
+
+ public void EnsureLabelAtPos(List<ILNode> body, ref int pos, ref int bodyLength)
+ {
+ if (pos > 0 && body[pos - 1] is ILLabel) {
+ pos--;
+ } else {
+ // ensure that the first element at body[pos] is a label:
+ ILLabel newLabel = new ILLabel();
+ newLabel.Name = "YieldReturnEntryPoint";
+ ranges[newLabel] = ranges[body[pos]]; // give the label the range of the instruction at body[pos]
+ body.Insert(pos, newLabel);
+ bodyLength++;
+ }
+ }
+
+ public LabelRangeMapping CreateLabelRangeMapping(List<ILNode> body, int pos, int bodyLength)
+ {
+ LabelRangeMapping result = new LabelRangeMapping();
+ CreateLabelRangeMapping(body, pos, bodyLength, result, false);
+ return result;
+ }
+
+ void CreateLabelRangeMapping(List<ILNode> body, int pos, int bodyLength, LabelRangeMapping result, bool onlyInitialLabels)
+ {
+ for (int i = pos; i < bodyLength; i++) {
+ ILLabel label = body[i] as ILLabel;
+ if (label != null) {
+ result.Add(new KeyValuePair<ILLabel, StateRange>(label, ranges[label]));
+ } else {
+ ILTryCatchBlock tryCatchBlock = body[i] as ILTryCatchBlock;
+ if (tryCatchBlock != null) {
+ CreateLabelRangeMapping(tryCatchBlock.TryBlock.Body, 0, tryCatchBlock.TryBlock.Body.Count, result, true);
+ } else if (onlyInitialLabels) {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ internal class LabelRangeMapping : List<KeyValuePair<ILLabel, StateRange>> {}
+}
diff --git a/ICSharpCode.Decompiler/ILAst/SymbolicExecution.cs b/ICSharpCode.Decompiler/ILAst/SymbolicExecution.cs
new file mode 100644
index 00000000..76c57eb0
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/SymbolicExecution.cs
@@ -0,0 +1,157 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ /// <summary>
+ /// This exception is thrown when we find something else than we expect from the C# compiler.
+ /// This aborts the analysis and makes the whole transform fail.
+ /// </summary>
+ internal class SymbolicAnalysisFailedException : Exception {}
+
+ internal enum SymbolicValueType
+ {
+ /// <summary>
+ /// Unknown value
+ /// </summary>
+ Unknown,
+ /// <summary>
+ /// int: Constant (result of ldc.i4)
+ /// </summary>
+ IntegerConstant,
+ /// <summary>
+ /// int: State + Constant
+ /// </summary>
+ State,
+ /// <summary>
+ /// This pointer (result of ldarg.0)
+ /// </summary>
+ This,
+ /// <summary>
+ /// bool: State == Constant
+ /// </summary>
+ StateEquals,
+ /// <summary>
+ /// bool: State != Constant
+ /// </summary>
+ StateInEquals
+ }
+
+ internal struct SymbolicValue
+ {
+ public readonly int Constant;
+ public readonly SymbolicValueType Type;
+
+ public SymbolicValue(SymbolicValueType type, int constant = 0)
+ {
+ Type = type;
+ Constant = constant;
+ }
+
+ public SymbolicValue AsBool()
+ {
+ if (Type == SymbolicValueType.State) {
+ // convert state integer to bool:
+ // if (state + c) = if (state + c != 0) = if (state != -c)
+ return new SymbolicValue(SymbolicValueType.StateInEquals, unchecked(-Constant));
+ }
+ return this;
+ }
+ public override string ToString()
+ {
+ return string.Format("[SymbolicValue {0}: {1}]", Type, Constant);
+ }
+ }
+
+ internal class SymbolicEvaluationContext
+ {
+ readonly FieldDefinition stateField;
+ readonly List<ILVariable> stateVariables = new List<ILVariable>();
+
+ public SymbolicEvaluationContext(FieldDefinition stateField)
+ {
+ this.stateField = stateField;
+ }
+
+ public void AddStateVariable(ILVariable v)
+ {
+ if (!stateVariables.Contains(v))
+ stateVariables.Add(v);
+ }
+
+ SymbolicValue Failed()
+ {
+ return new SymbolicValue(SymbolicValueType.Unknown);
+ }
+
+ public SymbolicValue Eval(ILExpression expr)
+ {
+ SymbolicValue left, right;
+ switch (expr.Code) {
+ case ILCode.Sub:
+ left = Eval(expr.Arguments[0]);
+ right = Eval(expr.Arguments[1]);
+ if (left.Type != SymbolicValueType.State && left.Type != SymbolicValueType.IntegerConstant)
+ return Failed();
+ if (right.Type != SymbolicValueType.IntegerConstant)
+ return Failed();
+ return new SymbolicValue(left.Type, unchecked ( left.Constant - right.Constant ));
+ case ILCode.Ldfld:
+ if (Eval(expr.Arguments[0]).Type != SymbolicValueType.This)
+ return Failed();
+ if (CecilExtensions.ResolveWithinSameModule(expr.Operand as FieldReference) != stateField)
+ return Failed();
+ return new SymbolicValue(SymbolicValueType.State);
+ case ILCode.Ldloc:
+ ILVariable loadedVariable = (ILVariable)expr.Operand;
+ if (stateVariables.Contains(loadedVariable))
+ return new SymbolicValue(SymbolicValueType.State);
+ else if (loadedVariable.IsParameter && loadedVariable.OriginalParameter.Index < 0)
+ return new SymbolicValue(SymbolicValueType.This);
+ else
+ return Failed();
+ case ILCode.Ldc_I4:
+ return new SymbolicValue(SymbolicValueType.IntegerConstant, (int)expr.Operand);
+ case ILCode.Ceq:
+ case ILCode.Cne:
+ left = Eval(expr.Arguments[0]);
+ right = Eval(expr.Arguments[1]);
+ if (left.Type != SymbolicValueType.State || right.Type != SymbolicValueType.IntegerConstant)
+ return Failed();
+ // bool: (state + left.Constant == right.Constant)
+ // bool: (state == right.Constant - left.Constant)
+ return new SymbolicValue(expr.Code == ILCode.Ceq ? SymbolicValueType.StateEquals : SymbolicValueType.StateInEquals, unchecked(right.Constant - left.Constant));
+ case ILCode.LogicNot:
+ SymbolicValue val = Eval(expr.Arguments[0]).AsBool();
+ if (val.Type == SymbolicValueType.StateEquals)
+ return new SymbolicValue(SymbolicValueType.StateInEquals, val.Constant);
+ else if (val.Type == SymbolicValueType.StateInEquals)
+ return new SymbolicValue(SymbolicValueType.StateEquals, val.Constant);
+ else
+ return Failed();
+ default:
+ return Failed();
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
new file mode 100644
index 00000000..1931d390
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
@@ -0,0 +1,1294 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ /// <summary>
+ /// Assigns C# types to IL expressions.
+ /// </summary>
+ /// <remarks>
+ /// Types are inferred in a bidirectional manner:
+ /// The expected type flows from the outside to the inside, the actual inferred type flows from the inside to the outside.
+ /// </remarks>
+ public class TypeAnalysis
+ {
+ public static void Run(DecompilerContext context, ILBlock method)
+ {
+ TypeAnalysis ta = new TypeAnalysis();
+ ta.context = context;
+ ta.module = context.CurrentMethod.Module;
+ ta.typeSystem = ta.module.TypeSystem;
+ ta.method = method;
+ ta.CreateDependencyGraph(method);
+ ta.IdentifySingleLoadVariables();
+ ta.RunInference();
+ }
+
+ sealed class ExpressionToInfer
+ {
+ public ILExpression Expression;
+
+ public bool Done;
+
+ /// <summary>
+ /// Set for assignment expressions that should wait until the variable type is available
+ /// from the context where the variable is used.
+ /// </summary>
+ public ILVariable DependsOnSingleLoad;
+
+ /// <summary>
+ /// The list variables that are read by this expression.
+ /// </summary>
+ public List<ILVariable> Dependencies = new List<ILVariable>();
+
+ public override string ToString()
+ {
+ if (Done)
+ return "[Done] " + Expression.ToString();
+ else
+ return Expression.ToString();
+ }
+
+ }
+
+ DecompilerContext context;
+ TypeSystem typeSystem;
+ ILBlock method;
+ ModuleDefinition module;
+ List<ExpressionToInfer> allExpressions = new List<ExpressionToInfer>();
+ DefaultDictionary<ILVariable, List<ExpressionToInfer>> assignmentExpressions = new DefaultDictionary<ILVariable, List<ExpressionToInfer>>(_ => new List<ExpressionToInfer>());
+ HashSet<ILVariable> singleLoadVariables = new HashSet<ILVariable>();
+
+ #region CreateDependencyGraph
+ /// <summary>
+ /// Creates the "ExpressionToInfer" instances (=nodes in dependency graph)
+ /// </summary>
+ /// <remarks>
+ /// We are using a dependency graph to ensure that expressions are analyzed in the correct order.
+ /// </remarks>
+ void CreateDependencyGraph(ILNode node)
+ {
+ ILCondition cond = node as ILCondition;
+ if (cond != null) {
+ cond.Condition.ExpectedType = typeSystem.Boolean;
+ }
+ ILWhileLoop loop = node as ILWhileLoop;
+ if (loop != null && loop.Condition != null) {
+ loop.Condition.ExpectedType = typeSystem.Boolean;
+ }
+ ILTryCatchBlock.CatchBlock catchBlock = node as ILTryCatchBlock.CatchBlock;
+ if (catchBlock != null && catchBlock.ExceptionVariable != null && catchBlock.ExceptionType != null && catchBlock.ExceptionVariable.Type == null) {
+ catchBlock.ExceptionVariable.Type = catchBlock.ExceptionType;
+ }
+ ILExpression expr = node as ILExpression;
+ if (expr != null) {
+ ExpressionToInfer expressionToInfer = new ExpressionToInfer();
+ expressionToInfer.Expression = expr;
+ allExpressions.Add(expressionToInfer);
+ FindNestedAssignments(expr, expressionToInfer);
+
+ if (expr.Code == ILCode.Stloc && ((ILVariable)expr.Operand).Type == null)
+ assignmentExpressions[(ILVariable)expr.Operand].Add(expressionToInfer);
+ return;
+ }
+ foreach (ILNode child in node.GetChildren()) {
+ CreateDependencyGraph(child);
+ }
+ }
+
+ void FindNestedAssignments(ILExpression expr, ExpressionToInfer parent)
+ {
+ foreach (ILExpression arg in expr.Arguments) {
+ if (arg.Code == ILCode.Stloc) {
+ ExpressionToInfer expressionToInfer = new ExpressionToInfer();
+ expressionToInfer.Expression = arg;
+ allExpressions.Add(expressionToInfer);
+ FindNestedAssignments(arg, expressionToInfer);
+ ILVariable v = (ILVariable)arg.Operand;
+ if (v.Type == null) {
+ assignmentExpressions[v].Add(expressionToInfer);
+ // the instruction that consumes the stloc result is handled as if it was reading the variable
+ parent.Dependencies.Add(v);
+ }
+ } else {
+ ILVariable v;
+ if (arg.Match(ILCode.Ldloc, out v) && v.Type == null) {
+ parent.Dependencies.Add(v);
+ }
+ FindNestedAssignments(arg, parent);
+ }
+ }
+ }
+ #endregion
+
+ void IdentifySingleLoadVariables()
+ {
+ // Find all variables that are assigned to exactly a single time:
+ var q = from expr in allExpressions
+ from v in expr.Dependencies
+ group expr by v;
+ foreach (var g in q.ToArray()) {
+ ILVariable v = g.Key;
+ if (g.Count() == 1 && g.Single().Expression.GetSelfAndChildrenRecursive<ILExpression>().Count(e => e.Operand == v) == 1) {
+ singleLoadVariables.Add(v);
+ // Mark the assignments as dependent on the type from the single load:
+ foreach (var assignment in assignmentExpressions[v]) {
+ assignment.DependsOnSingleLoad = v;
+ }
+ }
+ }
+ }
+
+ void RunInference()
+ {
+ int numberOfExpressionsAlreadyInferred = 0;
+ // Two flags that allow resolving cycles:
+ bool ignoreSingleLoadDependencies = false;
+ bool assignVariableTypesBasedOnPartialInformation = false;
+ while (numberOfExpressionsAlreadyInferred < allExpressions.Count) {
+ int oldCount = numberOfExpressionsAlreadyInferred;
+ foreach (ExpressionToInfer expr in allExpressions) {
+ if (!expr.Done && expr.Dependencies.TrueForAll(v => v.Type != null || singleLoadVariables.Contains(v))
+ && (expr.DependsOnSingleLoad == null || expr.DependsOnSingleLoad.Type != null || ignoreSingleLoadDependencies))
+ {
+ RunInference(expr.Expression);
+ expr.Done = true;
+ numberOfExpressionsAlreadyInferred++;
+ }
+ }
+ if (numberOfExpressionsAlreadyInferred == oldCount) {
+ if (ignoreSingleLoadDependencies) {
+ if (assignVariableTypesBasedOnPartialInformation)
+ throw new InvalidOperationException("Could not infer any expression");
+ else
+ assignVariableTypesBasedOnPartialInformation = true;
+ } else {
+ // We have a cyclic dependency; we'll try if we can resolve it by ignoring single-load dependencies.
+ // This can happen if the variable was not actually assigned an expected type by the single-load instruction.
+ ignoreSingleLoadDependencies = true;
+ continue;
+ }
+ } else {
+ assignVariableTypesBasedOnPartialInformation = false;
+ ignoreSingleLoadDependencies = false;
+ }
+ // Now infer types for variables:
+ foreach (var pair in assignmentExpressions) {
+ ILVariable v = pair.Key;
+ if (v.Type == null && (assignVariableTypesBasedOnPartialInformation ? pair.Value.Any(e => e.Done) : pair.Value.All(e => e.Done))) {
+ TypeReference inferredType = null;
+ foreach (ExpressionToInfer expr in pair.Value) {
+ Debug.Assert(expr.Expression.Code == ILCode.Stloc);
+ ILExpression assignedValue = expr.Expression.Arguments.Single();
+ if (assignedValue.InferredType != null) {
+ if (inferredType == null) {
+ inferredType = assignedValue.InferredType;
+ } else {
+ // pick the common base type
+ inferredType = TypeWithMoreInformation(inferredType, assignedValue.InferredType);
+ }
+ }
+ }
+ if (inferredType == null)
+ inferredType = typeSystem.Object;
+ v.Type = inferredType;
+ // Assign inferred type to all the assignments (in case they used different inferred types):
+ foreach (ExpressionToInfer expr in pair.Value) {
+ expr.Expression.InferredType = inferredType;
+ // re-infer if the expected type has changed
+ InferTypeForExpression(expr.Expression.Arguments.Single(), inferredType);
+ }
+ }
+ }
+ }
+ }
+
+ void RunInference(ILExpression expr)
+ {
+ bool anyArgumentIsMissingExpectedType = expr.Arguments.Any(a => a.ExpectedType == null);
+ if (expr.InferredType == null || anyArgumentIsMissingExpectedType)
+ InferTypeForExpression(expr, expr.ExpectedType, forceInferChildren: anyArgumentIsMissingExpectedType);
+ foreach (var arg in expr.Arguments) {
+ if (arg.Code != ILCode.Stloc) {
+ RunInference(arg);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Infers the C# type of <paramref name="expr"/>.
+ /// </summary>
+ /// <param name="expr">The expression</param>
+ /// <param name="expectedType">The expected type of the expression</param>
+ /// <param name="forceInferChildren">Whether direct children should be inferred even if its not necessary. (does not apply to nested children!)</param>
+ /// <returns>The inferred type</returns>
+ TypeReference InferTypeForExpression(ILExpression expr, TypeReference expectedType, bool forceInferChildren = false)
+ {
+ if (expectedType != null && !IsSameType(expr.ExpectedType, expectedType)) {
+ expr.ExpectedType = expectedType;
+ if (expr.Code != ILCode.Stloc) // stloc is special case and never gets re-evaluated
+ forceInferChildren = true;
+ }
+ if (forceInferChildren || expr.InferredType == null)
+ expr.InferredType = DoInferTypeForExpression(expr, expectedType, forceInferChildren);
+ return expr.InferredType;
+ }
+
+ TypeReference DoInferTypeForExpression(ILExpression expr, TypeReference expectedType, bool forceInferChildren = false)
+ {
+ switch (expr.Code) {
+ #region Logical operators
+ case ILCode.LogicNot:
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments.Single(), typeSystem.Boolean);
+ }
+ return typeSystem.Boolean;
+ case ILCode.LogicAnd:
+ case ILCode.LogicOr:
+ // if Operand is set the logic and/or expression is a custom operator
+ // we can deal with it the same as a normal invocation.
+ if (expr.Operand != null)
+ goto case ILCode.Call;
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments[0], typeSystem.Boolean);
+ InferTypeForExpression(expr.Arguments[1], typeSystem.Boolean);
+ }
+ return typeSystem.Boolean;
+ case ILCode.TernaryOp:
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments[0], typeSystem.Boolean);
+ }
+ return InferBinaryArguments(expr.Arguments[1], expr.Arguments[2], expectedType, forceInferChildren);
+ case ILCode.NullCoalescing:
+ return InferBinaryArguments(expr.Arguments[0], expr.Arguments[1], expectedType, forceInferChildren);
+ #endregion
+ #region Variable load/store
+ case ILCode.Stloc:
+ {
+ ILVariable v = (ILVariable)expr.Operand;
+ if (forceInferChildren) {
+ // do not use 'expectedType' in here!
+ InferTypeForExpression(expr.Arguments.Single(), v.Type);
+ }
+ return v.Type;
+ }
+ case ILCode.Ldloc:
+ {
+ ILVariable v = (ILVariable)expr.Operand;
+ if (v.Type == null && singleLoadVariables.Contains(v)) {
+ v.Type = expectedType;
+ }
+ return v.Type;
+ }
+ case ILCode.Ldloca:
+ {
+ ILVariable v = (ILVariable)expr.Operand;
+ if (v.Type != null)
+ return new ByReferenceType(v.Type);
+ else
+ return null;
+ }
+ #endregion
+ #region Call / NewObj
+ case ILCode.Call:
+ case ILCode.Callvirt:
+ case ILCode.CallGetter:
+ case ILCode.CallvirtGetter:
+ case ILCode.CallSetter:
+ case ILCode.CallvirtSetter:
+ {
+ MethodReference method = (MethodReference)expr.Operand;
+ if (forceInferChildren) {
+ for (int i = 0; i < expr.Arguments.Count; i++) {
+ if (i == 0 && method.HasThis) {
+ InferTypeForExpression(expr.Arguments[0], MakeRefIfValueType(method.DeclaringType, expr.GetPrefix(ILCode.Constrained)));
+ } else {
+ InferTypeForExpression(expr.Arguments[i], SubstituteTypeArgs(method.Parameters[method.HasThis ? i - 1 : i].ParameterType, method));
+ }
+ }
+ }
+ if (expr.Code == ILCode.CallSetter || expr.Code == ILCode.CallvirtSetter) {
+ return SubstituteTypeArgs(method.Parameters.Last().ParameterType, method);
+ } else {
+ return SubstituteTypeArgs(method.ReturnType, method);
+ }
+ }
+ case ILCode.Newobj:
+ {
+ MethodReference ctor = (MethodReference)expr.Operand;
+ if (forceInferChildren) {
+ for (int i = 0; i < ctor.Parameters.Count; i++) {
+ InferTypeForExpression(expr.Arguments[i], SubstituteTypeArgs(ctor.Parameters[i].ParameterType, ctor));
+ }
+ }
+ return ctor.DeclaringType;
+ }
+ case ILCode.InitObject:
+ case ILCode.InitCollection:
+ return InferTypeForExpression(expr.Arguments[0], expectedType);
+ case ILCode.InitializedObject:
+ // expectedType should always be known due to the parent method call / property setter
+ Debug.Assert(expectedType != null);
+ return expectedType;
+ #endregion
+ #region Load/Store Fields
+ case ILCode.Ldfld:
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments[0], MakeRefIfValueType(((FieldReference)expr.Operand).DeclaringType, expr.GetPrefix(ILCode.Constrained)));
+ }
+ return GetFieldType((FieldReference)expr.Operand);
+ case ILCode.Ldsfld:
+ return GetFieldType((FieldReference)expr.Operand);
+ case ILCode.Ldflda:
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments[0], MakeRefIfValueType(((FieldReference)expr.Operand).DeclaringType, expr.GetPrefix(ILCode.Constrained)));
+ }
+ return new ByReferenceType(GetFieldType((FieldReference)expr.Operand));
+ case ILCode.Ldsflda:
+ return new ByReferenceType(GetFieldType((FieldReference)expr.Operand));
+ case ILCode.Stfld:
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments[0], MakeRefIfValueType(((FieldReference)expr.Operand).DeclaringType, expr.GetPrefix(ILCode.Constrained)));
+ InferTypeForExpression(expr.Arguments[1], GetFieldType((FieldReference)expr.Operand));
+ }
+ return GetFieldType((FieldReference)expr.Operand);
+ case ILCode.Stsfld:
+ if (forceInferChildren)
+ InferTypeForExpression(expr.Arguments[0], GetFieldType((FieldReference)expr.Operand));
+ return GetFieldType((FieldReference)expr.Operand);
+ #endregion
+ #region Reference/Pointer instructions
+ case ILCode.Ldind_Ref:
+ return UnpackPointer(InferTypeForExpression(expr.Arguments[0], null));
+ case ILCode.Stind_Ref:
+ if (forceInferChildren) {
+ TypeReference elementType = UnpackPointer(InferTypeForExpression(expr.Arguments[0], null));
+ InferTypeForExpression(expr.Arguments[1], elementType);
+ }
+ return null;
+ case ILCode.Ldobj:
+ {
+ TypeReference type = (TypeReference)expr.Operand;
+ var argType = InferTypeForExpression(expr.Arguments[0], null);
+ if (argType is PointerType || argType is ByReferenceType) {
+ var elementType = ((TypeSpecification)argType).ElementType;
+ int infoAmount = GetInformationAmount(elementType);
+ if (infoAmount == 1 && GetInformationAmount(type) == 8) {
+ // A bool can be loaded from both bytes and sbytes.
+ type = elementType;
+ }
+ if (infoAmount >= 8 && infoAmount <= 64 && infoAmount == GetInformationAmount(type)) {
+ // An integer can be loaded as another integer of the same size.
+ // For integers smaller than 32 bit, the signs must match (as loading performs sign extension)
+ bool? elementTypeIsSigned = IsSigned(elementType);
+ bool? typeIsSigned = IsSigned(type);
+ if (elementTypeIsSigned != null && typeIsSigned != null) {
+ if (infoAmount >= 32 || elementTypeIsSigned == typeIsSigned)
+ type = elementType;
+ }
+ }
+ }
+ if (argType is PointerType)
+ InferTypeForExpression(expr.Arguments[0], new PointerType(type));
+ else
+ InferTypeForExpression(expr.Arguments[0], new ByReferenceType(type));
+ return type;
+ }
+ case ILCode.Stobj:
+ {
+ TypeReference operandType = (TypeReference)expr.Operand;
+ TypeReference pointerType = InferTypeForExpression(expr.Arguments[0], new ByReferenceType(operandType));
+ TypeReference elementType;
+ if (pointerType is PointerType)
+ elementType = ((PointerType)pointerType).ElementType;
+ else if (pointerType is ByReferenceType)
+ elementType = ((ByReferenceType)pointerType).ElementType;
+ else
+ elementType = null;
+ if (elementType != null) {
+ // An integer can be stored in any other integer of the same size.
+ int infoAmount = GetInformationAmount(elementType);
+ if (infoAmount == 1 && GetInformationAmount(operandType) == 8)
+ operandType = elementType;
+ else if (infoAmount == GetInformationAmount(operandType) && IsSigned(elementType) != null && IsSigned(operandType) != null)
+ operandType = elementType;
+ }
+ if (forceInferChildren) {
+ if (pointerType is PointerType)
+ InferTypeForExpression(expr.Arguments[0], new PointerType(operandType));
+ else if (!IsSameType(operandType, expr.Operand as TypeReference))
+ InferTypeForExpression(expr.Arguments[0], new ByReferenceType(operandType));
+ InferTypeForExpression(expr.Arguments[1], operandType);
+ }
+ return operandType;
+ }
+ case ILCode.Initobj:
+ return null;
+ case ILCode.DefaultValue:
+ return (TypeReference)expr.Operand;
+ case ILCode.Localloc:
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments[0], null);
+ }
+ if (expectedType is PointerType)
+ return expectedType;
+ else
+ return typeSystem.IntPtr;
+ case ILCode.Sizeof:
+ return typeSystem.Int32;
+ case ILCode.PostIncrement:
+ case ILCode.PostIncrement_Ovf:
+ case ILCode.PostIncrement_Ovf_Un:
+ {
+ TypeReference elementType = UnpackPointer(InferTypeForExpression(expr.Arguments[0], null));
+ if (forceInferChildren && elementType != null) {
+ // Assign expected type to the child expression
+ InferTypeForExpression(expr.Arguments[0], new ByReferenceType(elementType));
+ }
+ return elementType;
+ }
+ case ILCode.Mkrefany:
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments[0], (TypeReference)expr.Operand);
+ }
+ return typeSystem.TypedReference;
+ case ILCode.Refanytype:
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments[0], typeSystem.TypedReference);
+ }
+ return new TypeReference("System", "RuntimeTypeHandle", module, module.TypeSystem.Corlib, true);
+ case ILCode.Refanyval:
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments[0], typeSystem.TypedReference);
+ }
+ return new ByReferenceType((TypeReference)expr.Operand);
+ case ILCode.AddressOf:
+ {
+ TypeReference t = InferTypeForExpression(expr.Arguments[0], UnpackPointer(expectedType));
+ return t != null ? new ByReferenceType(t) : null;
+ }
+ case ILCode.ValueOf:
+ return GetNullableTypeArgument(InferTypeForExpression(expr.Arguments[0], CreateNullableType(expectedType)));
+ case ILCode.NullableOf:
+ return CreateNullableType(InferTypeForExpression(expr.Arguments[0], GetNullableTypeArgument(expectedType)));
+ #endregion
+ #region Arithmetic instructions
+ case ILCode.Not: // bitwise complement
+ case ILCode.Neg:
+ return InferTypeForExpression(expr.Arguments.Single(), expectedType);
+ case ILCode.Add:
+ return InferArgumentsInAddition(expr, null, expectedType);
+ case ILCode.Sub:
+ return InferArgumentsInSubtraction(expr, null, expectedType);
+ case ILCode.Mul:
+ case ILCode.Or:
+ case ILCode.And:
+ case ILCode.Xor:
+ return InferArgumentsInBinaryOperator(expr, null, expectedType);
+ case ILCode.Add_Ovf:
+ return InferArgumentsInAddition(expr, true, expectedType);
+ case ILCode.Sub_Ovf:
+ return InferArgumentsInSubtraction(expr, true, expectedType);
+ case ILCode.Mul_Ovf:
+ case ILCode.Div:
+ case ILCode.Rem:
+ return InferArgumentsInBinaryOperator(expr, true, expectedType);
+ case ILCode.Add_Ovf_Un:
+ return InferArgumentsInAddition(expr, false, expectedType);
+ case ILCode.Sub_Ovf_Un:
+ return InferArgumentsInSubtraction(expr, false, expectedType);
+ case ILCode.Mul_Ovf_Un:
+ case ILCode.Div_Un:
+ case ILCode.Rem_Un:
+ return InferArgumentsInBinaryOperator(expr, false, expectedType);
+ case ILCode.Shl:
+ if (forceInferChildren)
+ InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
+ if (expectedType != null && (
+ expectedType.MetadataType == MetadataType.Int32 || expectedType.MetadataType == MetadataType.UInt32 ||
+ expectedType.MetadataType == MetadataType.Int64 || expectedType.MetadataType == MetadataType.UInt64)
+ )
+ return NumericPromotion(InferTypeForExpression(expr.Arguments[0], expectedType));
+ else
+ return NumericPromotion(InferTypeForExpression(expr.Arguments[0], null));
+ case ILCode.Shr:
+ case ILCode.Shr_Un:
+ {
+ if (forceInferChildren)
+ InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
+ TypeReference type = NumericPromotion(InferTypeForExpression(expr.Arguments[0], null));
+ if (type == null)
+ return null;
+ TypeReference expectedInputType = null;
+ switch (type.MetadataType) {
+ case MetadataType.Int32:
+ if (expr.Code == ILCode.Shr_Un)
+ expectedInputType = typeSystem.UInt32;
+ break;
+ case MetadataType.UInt32:
+ if (expr.Code == ILCode.Shr)
+ expectedInputType = typeSystem.Int32;
+ break;
+ case MetadataType.Int64:
+ if (expr.Code == ILCode.Shr_Un)
+ expectedInputType = typeSystem.UInt64;
+ break;
+ case MetadataType.UInt64:
+ if (expr.Code == ILCode.Shr)
+ expectedInputType = typeSystem.UInt64;
+ break;
+ }
+ if (expectedInputType != null) {
+ InferTypeForExpression(expr.Arguments[0], expectedInputType);
+ return expectedInputType;
+ } else {
+ return type;
+ }
+ }
+ case ILCode.CompoundAssignment:
+ {
+ var op = expr.Arguments[0];
+ if (op.Code == ILCode.NullableOf) op = op.Arguments[0].Arguments[0];
+ var varType = InferTypeForExpression(op.Arguments[0], null);
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments[0], varType);
+ }
+ return varType;
+ }
+ #endregion
+ #region Constant loading instructions
+ case ILCode.Ldnull:
+ return typeSystem.Object;
+ case ILCode.Ldstr:
+ return typeSystem.String;
+ case ILCode.Ldftn:
+ case ILCode.Ldvirtftn:
+ return typeSystem.IntPtr;
+ case ILCode.Ldc_I4:
+ if (IsBoolean(expectedType) && ((int)expr.Operand == 0 || (int)expr.Operand == 1))
+ return typeSystem.Boolean;
+ if (expectedType is PointerType && (int)expr.Operand == 0)
+ return expectedType;
+ if (IsIntegerOrEnum(expectedType) && OperandFitsInType(expectedType, (int)expr.Operand))
+ return expectedType;
+ else
+ return typeSystem.Int32;
+ case ILCode.Ldc_I8:
+ if (expectedType is PointerType && (long)expr.Operand == 0)
+ return expectedType;
+ if (IsIntegerOrEnum(expectedType) && GetInformationAmount(expectedType) >= NativeInt)
+ return expectedType;
+ else
+ return typeSystem.Int64;
+ case ILCode.Ldc_R4:
+ return typeSystem.Single;
+ case ILCode.Ldc_R8:
+ return typeSystem.Double;
+ case ILCode.Ldc_Decimal:
+ return new TypeReference("System", "Decimal", module, module.TypeSystem.Corlib, true);
+ case ILCode.Ldtoken:
+ if (expr.Operand is TypeReference)
+ return new TypeReference("System", "RuntimeTypeHandle", module, module.TypeSystem.Corlib, true);
+ else if (expr.Operand is FieldReference)
+ return new TypeReference("System", "RuntimeFieldHandle", module, module.TypeSystem.Corlib, true);
+ else
+ return new TypeReference("System", "RuntimeMethodHandle", module, module.TypeSystem.Corlib, true);
+ case ILCode.Arglist:
+ return new TypeReference("System", "RuntimeArgumentHandle", module, module.TypeSystem.Corlib, true);
+ #endregion
+ #region Array instructions
+ case ILCode.Newarr:
+ if (forceInferChildren) {
+ var lengthType = InferTypeForExpression(expr.Arguments.Single(), null);
+ if (lengthType == typeSystem.IntPtr) {
+ lengthType = typeSystem.Int64;
+ } else if (lengthType == typeSystem.UIntPtr) {
+ lengthType = typeSystem.UInt64;
+ } else if (lengthType != typeSystem.UInt32 && lengthType != typeSystem.Int64 && lengthType != typeSystem.UInt64) {
+ lengthType = typeSystem.Int32;
+ }
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments.Single(), lengthType);
+ }
+ }
+ return new ArrayType((TypeReference)expr.Operand);
+ case ILCode.InitArray:
+ var operandAsArrayType = (ArrayType)expr.Operand;
+ if (forceInferChildren)
+ {
+ foreach (ILExpression arg in expr.Arguments)
+ InferTypeForExpression(arg, operandAsArrayType.ElementType);
+ }
+ return operandAsArrayType;
+ case ILCode.Ldlen:
+ return typeSystem.Int32;
+ case ILCode.Ldelem_U1:
+ case ILCode.Ldelem_U2:
+ case ILCode.Ldelem_U4:
+ case ILCode.Ldelem_I1:
+ case ILCode.Ldelem_I2:
+ case ILCode.Ldelem_I4:
+ case ILCode.Ldelem_I8:
+ case ILCode.Ldelem_R4:
+ case ILCode.Ldelem_R8:
+ case ILCode.Ldelem_I:
+ case ILCode.Ldelem_Ref:
+ {
+ ArrayType arrayType = InferTypeForExpression(expr.Arguments[0], null) as ArrayType;
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
+ }
+ return arrayType != null ? arrayType.ElementType : null;
+ }
+ case ILCode.Ldelem_Any:
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
+ }
+ return (TypeReference)expr.Operand;
+ case ILCode.Ldelema:
+ {
+ ArrayType arrayType = InferTypeForExpression(expr.Arguments[0], null) as ArrayType;
+ if (forceInferChildren)
+ InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
+ return arrayType != null ? new ByReferenceType(arrayType.ElementType) : null;
+ }
+ case ILCode.Stelem_I:
+ case ILCode.Stelem_I1:
+ case ILCode.Stelem_I2:
+ case ILCode.Stelem_I4:
+ case ILCode.Stelem_I8:
+ case ILCode.Stelem_R4:
+ case ILCode.Stelem_R8:
+ case ILCode.Stelem_Ref:
+ case ILCode.Stelem_Any:
+ {
+ ArrayType arrayType = InferTypeForExpression(expr.Arguments[0], null) as ArrayType;
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
+ if (arrayType != null) {
+ InferTypeForExpression(expr.Arguments[2], arrayType.ElementType);
+ }
+ }
+ return arrayType != null ? arrayType.ElementType : null;
+ }
+ #endregion
+ #region Conversion instructions
+ case ILCode.Conv_I1:
+ case ILCode.Conv_Ovf_I1:
+ case ILCode.Conv_Ovf_I1_Un:
+ return HandleConversion(8, true, expr.Arguments[0], expectedType, typeSystem.SByte);
+ case ILCode.Conv_I2:
+ case ILCode.Conv_Ovf_I2:
+ case ILCode.Conv_Ovf_I2_Un:
+ return HandleConversion(16, true, expr.Arguments[0], expectedType, typeSystem.Int16);
+ case ILCode.Conv_I4:
+ case ILCode.Conv_Ovf_I4:
+ case ILCode.Conv_Ovf_I4_Un:
+ return HandleConversion(32, true, expr.Arguments[0], expectedType, typeSystem.Int32);
+ case ILCode.Conv_I8:
+ case ILCode.Conv_Ovf_I8:
+ case ILCode.Conv_Ovf_I8_Un:
+ return HandleConversion(64, true, expr.Arguments[0], expectedType, typeSystem.Int64);
+ case ILCode.Conv_U1:
+ case ILCode.Conv_Ovf_U1:
+ case ILCode.Conv_Ovf_U1_Un:
+ return HandleConversion(8, false, expr.Arguments[0], expectedType, typeSystem.Byte);
+ case ILCode.Conv_U2:
+ case ILCode.Conv_Ovf_U2:
+ case ILCode.Conv_Ovf_U2_Un:
+ return HandleConversion(16, false, expr.Arguments[0], expectedType, typeSystem.UInt16);
+ case ILCode.Conv_U4:
+ case ILCode.Conv_Ovf_U4:
+ case ILCode.Conv_Ovf_U4_Un:
+ return HandleConversion(32, false, expr.Arguments[0], expectedType, typeSystem.UInt32);
+ case ILCode.Conv_U8:
+ case ILCode.Conv_Ovf_U8:
+ case ILCode.Conv_Ovf_U8_Un:
+ return HandleConversion(64, false, expr.Arguments[0], expectedType, typeSystem.UInt64);
+ case ILCode.Conv_I:
+ case ILCode.Conv_Ovf_I:
+ case ILCode.Conv_Ovf_I_Un:
+ return HandleConversion(NativeInt, true, expr.Arguments[0], expectedType, typeSystem.IntPtr);
+ case ILCode.Conv_U:
+ case ILCode.Conv_Ovf_U:
+ case ILCode.Conv_Ovf_U_Un:
+ return HandleConversion(NativeInt, false, expr.Arguments[0], expectedType, typeSystem.UIntPtr);
+ case ILCode.Conv_R4:
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments[0], typeSystem.Single);
+ }
+ return typeSystem.Single;
+ case ILCode.Conv_R8:
+ if (forceInferChildren) {
+ InferTypeForExpression(expr.Arguments[0], typeSystem.Double);
+ }
+ return typeSystem.Double;
+ case ILCode.Conv_R_Un:
+ return (expectedType != null && expectedType.MetadataType == MetadataType.Single) ? typeSystem.Single : typeSystem.Double;
+ case ILCode.Castclass:
+ case ILCode.Unbox_Any:
+ return (TypeReference)expr.Operand;
+ case ILCode.Unbox:
+ return new ByReferenceType((TypeReference)expr.Operand);
+ case ILCode.Isinst:
+ {
+ // isinst performs the equivalent of a cast only for reference types;
+ // value types still need to be unboxed after an isinst instruction
+ TypeReference tr = (TypeReference)expr.Operand;
+ return tr.IsValueType ? typeSystem.Object : tr;
+ }
+ case ILCode.Box:
+ {
+ var tr = (TypeReference)expr.Operand;
+ if (forceInferChildren)
+ InferTypeForExpression(expr.Arguments.Single(), tr);
+ return tr.IsValueType ? typeSystem.Object : tr;
+ }
+ #endregion
+ #region Comparison instructions
+ case ILCode.Ceq:
+ case ILCode.Cne:
+ if (forceInferChildren)
+ InferArgumentsInBinaryOperator(expr, null, null);
+ return typeSystem.Boolean;
+ case ILCode.Clt:
+ case ILCode.Cgt:
+ case ILCode.Cle:
+ case ILCode.Cge:
+ if (forceInferChildren)
+ InferArgumentsInBinaryOperator(expr, true, null);
+ return typeSystem.Boolean;
+ case ILCode.Clt_Un:
+ case ILCode.Cgt_Un:
+ case ILCode.Cle_Un:
+ case ILCode.Cge_Un:
+ if (forceInferChildren)
+ InferArgumentsInBinaryOperator(expr, false, null);
+ return typeSystem.Boolean;
+ #endregion
+ #region Branch instructions
+ case ILCode.Brtrue:
+ if (forceInferChildren)
+ InferTypeForExpression(expr.Arguments.Single(), typeSystem.Boolean);
+ return null;
+ case ILCode.Br:
+ case ILCode.Leave:
+ case ILCode.Endfinally:
+ case ILCode.Switch:
+ case ILCode.Throw:
+ case ILCode.Rethrow:
+ case ILCode.LoopOrSwitchBreak:
+ case ILCode.LoopContinue:
+ case ILCode.YieldBreak:
+ return null;
+ case ILCode.Ret:
+ if (forceInferChildren && expr.Arguments.Count == 1) {
+ TypeReference returnType = context.CurrentMethod.ReturnType;
+ if (context.CurrentMethodIsAsync && returnType != null && returnType.Namespace == "System.Threading.Tasks") {
+ if (returnType.Name == "Task") {
+ returnType = typeSystem.Void;
+ } else if (returnType.Name == "Task`1" && returnType.IsGenericInstance) {
+ returnType = ((GenericInstanceType)returnType).GenericArguments[0];
+ }
+ }
+ InferTypeForExpression(expr.Arguments[0], returnType);
+ }
+ return null;
+ case ILCode.YieldReturn:
+ if (forceInferChildren) {
+ GenericInstanceType genericType = context.CurrentMethod.ReturnType as GenericInstanceType;
+ if (genericType != null) { // IEnumerable<T> or IEnumerator<T>
+ InferTypeForExpression(expr.Arguments[0], genericType.GenericArguments[0]);
+ } else { // non-generic IEnumerable or IEnumerator
+ InferTypeForExpression(expr.Arguments[0], typeSystem.Object);
+ }
+ }
+ return null;
+ case ILCode.Await:
+ {
+ TypeReference taskType = InferTypeForExpression(expr.Arguments[0], null);
+ if (taskType != null && taskType.Name == "Task`1" && taskType.IsGenericInstance && taskType.Namespace == "System.Threading.Tasks") {
+ return ((GenericInstanceType)taskType).GenericArguments[0];
+ }
+ return null;
+ }
+ #endregion
+ case ILCode.Pop:
+ return null;
+ case ILCode.Wrap:
+ case ILCode.Dup:
+ {
+ var arg = expr.Arguments.Single();
+ return arg.ExpectedType = InferTypeForExpression(arg, expectedType);
+ }
+ default:
+ Debug.WriteLine("Type Inference: Can't handle " + expr.Code.GetName());
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Wraps 'type' in a ByReferenceType if it is a value type. If a constrained prefix is specified,
+ /// returns the constrained type wrapped in a ByReferenceType.
+ /// </summary>
+ TypeReference MakeRefIfValueType(TypeReference type, ILExpressionPrefix constrainedPrefix)
+ {
+ if (constrainedPrefix != null)
+ return new ByReferenceType((TypeReference)constrainedPrefix.Operand);
+ if (type.IsValueType)
+ return new ByReferenceType(type);
+ else
+ return type;
+ }
+
+ /// <summary>
+ /// Promotes primitive types smaller than int32 to int32.
+ /// </summary>
+ /// <remarks>
+ /// Always promotes to signed int32.
+ /// </remarks>
+ TypeReference NumericPromotion(TypeReference type)
+ {
+ if (type == null)
+ return null;
+ switch (type.MetadataType) {
+ case MetadataType.SByte:
+ case MetadataType.Int16:
+ case MetadataType.Byte:
+ case MetadataType.UInt16:
+ return typeSystem.Int32;
+ default:
+ return type;
+ }
+ }
+
+ TypeReference HandleConversion(int targetBitSize, bool targetSigned, ILExpression arg, TypeReference expectedType, TypeReference targetType)
+ {
+ if (targetBitSize >= NativeInt && expectedType is PointerType) {
+ InferTypeForExpression(arg, expectedType);
+ return expectedType;
+ }
+ TypeReference argType = InferTypeForExpression(arg, null);
+ if (targetBitSize >= NativeInt && argType is ByReferenceType) {
+ // conv instructions on managed references mean that the GC should stop tracking them, so they become pointers:
+ PointerType ptrType = new PointerType(((ByReferenceType)argType).ElementType);
+ InferTypeForExpression(arg, ptrType);
+ return ptrType;
+ } else if (targetBitSize >= NativeInt && argType is PointerType) {
+ return argType;
+ }
+ TypeReference resultType = (GetInformationAmount(expectedType) == targetBitSize && IsSigned(expectedType) == targetSigned) ? expectedType : targetType;
+ arg.ExpectedType = resultType; // store the expected type in the argument so that AstMethodBodyBuilder will insert a cast
+ return resultType;
+ }
+
+ public static TypeReference GetFieldType(FieldReference fieldReference)
+ {
+ return SubstituteTypeArgs(UnpackModifiers(fieldReference.FieldType), fieldReference);
+ }
+
+ public static TypeReference SubstituteTypeArgs(TypeReference type, MemberReference member)
+ {
+ if (type is TypeSpecification) {
+ ArrayType arrayType = type as ArrayType;
+ if (arrayType != null) {
+ TypeReference elementType = SubstituteTypeArgs(arrayType.ElementType, member);
+ if (elementType != arrayType.ElementType) {
+ ArrayType newArrayType = new ArrayType(elementType);
+ newArrayType.Dimensions.Clear(); // remove the single dimension that Cecil adds by default
+ foreach (ArrayDimension d in arrayType.Dimensions)
+ newArrayType.Dimensions.Add(d);
+ return newArrayType;
+ } else {
+ return type;
+ }
+ }
+ ByReferenceType refType = type as ByReferenceType;
+ if (refType != null) {
+ TypeReference elementType = SubstituteTypeArgs(refType.ElementType, member);
+ return elementType != refType.ElementType ? new ByReferenceType(elementType) : type;
+ }
+ GenericInstanceType giType = type as GenericInstanceType;
+ if (giType != null) {
+ GenericInstanceType newType = new GenericInstanceType(giType.ElementType);
+ bool isChanged = false;
+ for (int i = 0; i < giType.GenericArguments.Count; i++) {
+ newType.GenericArguments.Add(SubstituteTypeArgs(giType.GenericArguments[i], member));
+ isChanged |= newType.GenericArguments[i] != giType.GenericArguments[i];
+ }
+ return isChanged ? newType : type;
+ }
+ OptionalModifierType optmodType = type as OptionalModifierType;
+ if (optmodType != null) {
+ TypeReference elementType = SubstituteTypeArgs(optmodType.ElementType, member);
+ return elementType != optmodType.ElementType ? new OptionalModifierType(optmodType.ModifierType, elementType) : type;
+ }
+ RequiredModifierType reqmodType = type as RequiredModifierType;
+ if (reqmodType != null) {
+ TypeReference elementType = SubstituteTypeArgs(reqmodType.ElementType, member);
+ return elementType != reqmodType.ElementType ? new RequiredModifierType(reqmodType.ModifierType, elementType) : type;
+ }
+ PointerType ptrType = type as PointerType;
+ if (ptrType != null) {
+ TypeReference elementType = SubstituteTypeArgs(ptrType.ElementType, member);
+ return elementType != ptrType.ElementType ? new PointerType(elementType) : type;
+ }
+ }
+ GenericParameter gp = type as GenericParameter;
+ if (gp != null) {
+ if (member.DeclaringType is ArrayType) {
+ return ((ArrayType)member.DeclaringType).ElementType;
+ } else if (gp.Owner.GenericParameterType == GenericParameterType.Method) {
+ return ((GenericInstanceMethod)member).GenericArguments[gp.Position];
+ } else {
+ return ((GenericInstanceType)member.DeclaringType).GenericArguments[gp.Position];
+ }
+ }
+ return type;
+ }
+
+ static TypeReference UnpackPointer(TypeReference pointerOrManagedReference)
+ {
+ ByReferenceType refType = pointerOrManagedReference as ByReferenceType;
+ if (refType != null)
+ return refType.ElementType;
+ PointerType ptrType = pointerOrManagedReference as PointerType;
+ if (ptrType != null)
+ return ptrType.ElementType;
+ return null;
+ }
+
+ internal static TypeReference UnpackModifiers(TypeReference type)
+ {
+ while (type is OptionalModifierType || type is RequiredModifierType)
+ type = ((TypeSpecification)type).ElementType;
+ return type;
+ }
+
+ static TypeReference GetNullableTypeArgument(TypeReference type)
+ {
+ var t = type as GenericInstanceType;
+ return IsNullableType(t) ? t.GenericArguments[0] : type;
+ }
+
+ GenericInstanceType CreateNullableType(TypeReference type)
+ {
+ if (type == null) return null;
+ var t = new GenericInstanceType(new TypeReference("System", "Nullable`1", module, module.TypeSystem.Corlib, true));
+ t.GenericArguments.Add(type);
+ return t;
+ }
+
+ TypeReference InferArgumentsInBinaryOperator(ILExpression expr, bool? isSigned, TypeReference expectedType)
+ {
+ return InferBinaryArguments(expr.Arguments[0], expr.Arguments[1], expectedType);
+ }
+
+ TypeReference InferArgumentsInAddition(ILExpression expr, bool? isSigned, TypeReference expectedType)
+ {
+ ILExpression left = expr.Arguments[0];
+ ILExpression right = expr.Arguments[1];
+ TypeReference leftPreferred = DoInferTypeForExpression(left, expectedType);
+ if (leftPreferred is PointerType) {
+ left.InferredType = left.ExpectedType = leftPreferred;
+ InferTypeForExpression(right, null);
+ return leftPreferred;
+ }
+ if (IsEnum(leftPreferred)) {
+ //E+U=E
+ left.InferredType = left.ExpectedType = leftPreferred;
+ InferTypeForExpression(right, GetEnumUnderlyingType(leftPreferred));
+ return leftPreferred;
+ }
+ TypeReference rightPreferred = DoInferTypeForExpression(right, expectedType);
+ if (rightPreferred is PointerType) {
+ InferTypeForExpression(left, null);
+ right.InferredType = right.ExpectedType = rightPreferred;
+ return rightPreferred;
+ }
+ if (IsEnum(rightPreferred)) {
+ //U+E=E
+ right.InferredType = right.ExpectedType = rightPreferred;
+ InferTypeForExpression(left, GetEnumUnderlyingType(rightPreferred));
+ return rightPreferred;
+ }
+ return InferBinaryArguments(left, right, expectedType, leftPreferred: leftPreferred, rightPreferred: rightPreferred);
+ }
+
+ TypeReference InferArgumentsInSubtraction(ILExpression expr, bool? isSigned, TypeReference expectedType)
+ {
+ ILExpression left = expr.Arguments[0];
+ ILExpression right = expr.Arguments[1];
+ TypeReference leftPreferred = DoInferTypeForExpression(left, expectedType);
+ if (leftPreferred is PointerType) {
+ left.InferredType = left.ExpectedType = leftPreferred;
+ InferTypeForExpression(right, null);
+ return leftPreferred;
+ }
+ if (IsEnum(leftPreferred)) {
+ if (expectedType != null && IsEnum(expectedType)) {
+ // E-U=E
+ left.InferredType = left.ExpectedType = leftPreferred;
+ InferTypeForExpression(right, GetEnumUnderlyingType(leftPreferred));
+ return leftPreferred;
+ } else {
+ // E-E=U
+ left.InferredType = left.ExpectedType = leftPreferred;
+ InferTypeForExpression(right, leftPreferred);
+ return GetEnumUnderlyingType(leftPreferred);
+ }
+ }
+ return InferBinaryArguments(left, right, expectedType, leftPreferred: leftPreferred);
+ }
+
+ TypeReference InferBinaryArguments(ILExpression left, ILExpression right, TypeReference expectedType, bool forceInferChildren = false, TypeReference leftPreferred = null, TypeReference rightPreferred = null)
+ {
+ if (leftPreferred == null) leftPreferred = DoInferTypeForExpression(left, expectedType, forceInferChildren);
+ if (rightPreferred == null) rightPreferred = DoInferTypeForExpression(right, expectedType, forceInferChildren);
+ if (IsSameType(leftPreferred, rightPreferred)) {
+ return left.InferredType = right.InferredType = left.ExpectedType = right.ExpectedType = leftPreferred;
+ } else if (IsSameType(rightPreferred, DoInferTypeForExpression(left, rightPreferred, forceInferChildren))) {
+ return left.InferredType = right.InferredType = left.ExpectedType = right.ExpectedType = rightPreferred;
+ } else if (IsSameType(leftPreferred, DoInferTypeForExpression(right, leftPreferred, forceInferChildren))) {
+ // re-infer the left expression with the preferred type to reset any conflicts caused by the rightPreferred type
+ DoInferTypeForExpression(left, leftPreferred, forceInferChildren);
+ return left.InferredType = right.InferredType = left.ExpectedType = right.ExpectedType = leftPreferred;
+ } else {
+ left.ExpectedType = right.ExpectedType = TypeWithMoreInformation(leftPreferred, rightPreferred);
+ left.InferredType = DoInferTypeForExpression(left, left.ExpectedType, forceInferChildren);
+ right.InferredType = DoInferTypeForExpression(right, right.ExpectedType, forceInferChildren);
+ return left.ExpectedType;
+ }
+ }
+
+ TypeReference TypeWithMoreInformation(TypeReference leftPreferred, TypeReference rightPreferred)
+ {
+ int left = GetInformationAmount(leftPreferred);
+ int right = GetInformationAmount(rightPreferred);
+ if (left < right) {
+ return rightPreferred;
+ } else if (left > right) {
+ return leftPreferred;
+ } else {
+ // TODO
+ return leftPreferred;
+ }
+ }
+
+ /// <summary>
+ /// Information amount used for IntPtr.
+ /// </summary>
+ public const int NativeInt = 33; // treat native int as between int32 and int64
+
+ /// <summary>
+ /// Gets the underlying type, if the specified type is an enum.
+ /// Otherwise, returns null.
+ /// </summary>
+ public static TypeReference GetEnumUnderlyingType(TypeReference enumType)
+ {
+ // unfortunately we cannot rely on enumType.IsValueType here - it's not set when the instruction operand is a typeref (as opposed to a typespec)
+ if (enumType != null && !IsArrayPointerOrReference(enumType)) {
+ // value type might be an enum
+ TypeDefinition typeDef = enumType.Resolve() as TypeDefinition;
+ if (typeDef != null && typeDef.IsEnum) {
+ return typeDef.Fields.Single(f => !f.IsStatic).FieldType;
+ }
+ }
+ return null;
+ }
+
+ public static int GetInformationAmount(TypeReference type)
+ {
+ type = GetEnumUnderlyingType(type) ?? type;
+ if (type == null)
+ return 0;
+ switch (type.MetadataType) {
+ case MetadataType.Void:
+ return 0;
+ case MetadataType.Boolean:
+ return 1;
+ case MetadataType.SByte:
+ case MetadataType.Byte:
+ return 8;
+ case MetadataType.Char:
+ case MetadataType.Int16:
+ case MetadataType.UInt16:
+ return 16;
+ case MetadataType.Int32:
+ case MetadataType.UInt32:
+ case MetadataType.Single:
+ return 32;
+ case MetadataType.Int64:
+ case MetadataType.UInt64:
+ case MetadataType.Double:
+ return 64;
+ case MetadataType.IntPtr:
+ case MetadataType.UIntPtr:
+ return NativeInt;
+ default:
+ return 100; // we consider structs/objects to have more information than any primitives
+ }
+ }
+
+ public static bool IsBoolean(TypeReference type)
+ {
+ return type != null && type.MetadataType == MetadataType.Boolean;
+ }
+
+ public static bool IsIntegerOrEnum(TypeReference type)
+ {
+ return IsSigned(type) != null;
+ }
+
+ public static bool IsEnum(TypeReference type)
+ {
+ // Arrays/Pointers/ByReference resolve to their element type, but we don't want to consider those to be enums
+ // However, GenericInstanceTypes, ModOpts etc. should be considered enums.
+ if (type == null || IsArrayPointerOrReference(type))
+ return false;
+ // unfortunately we cannot rely on type.IsValueType here - it's not set when the instruction operand is a typeref (as opposed to a typespec)
+ TypeDefinition typeDef = type.Resolve() as TypeDefinition;
+ return typeDef != null && typeDef.IsEnum;
+ }
+
+ static bool? IsSigned(TypeReference type)
+ {
+ type = GetEnumUnderlyingType(type) ?? type;
+ if (type == null)
+ return null;
+ switch (type.MetadataType) {
+ case MetadataType.SByte:
+ case MetadataType.Int16:
+ case MetadataType.Int32:
+ case MetadataType.Int64:
+ case MetadataType.IntPtr:
+ return true;
+ case MetadataType.Byte:
+ case MetadataType.Char:
+ case MetadataType.UInt16:
+ case MetadataType.UInt32:
+ case MetadataType.UInt64:
+ case MetadataType.UIntPtr:
+ return false;
+ default:
+ return null;
+ }
+ }
+
+ static bool OperandFitsInType(TypeReference type, int num)
+ {
+ type = GetEnumUnderlyingType(type) ?? type;
+ switch (type.MetadataType) {
+ case MetadataType.SByte:
+ return sbyte.MinValue <= num && num <= sbyte.MaxValue;
+ case MetadataType.Int16:
+ return short.MinValue <= num && num <= short.MaxValue;
+ case MetadataType.Byte:
+ return byte.MinValue <= num && num <= byte.MaxValue;
+ case MetadataType.Char:
+ return char.MinValue <= num && num <= char.MaxValue;
+ case MetadataType.UInt16:
+ return ushort.MinValue <= num && num <= ushort.MaxValue;
+ default:
+ return true;
+ }
+ }
+
+ static bool IsArrayPointerOrReference(TypeReference type)
+ {
+ TypeSpecification typeSpec = type as TypeSpecification;
+ while (typeSpec != null) {
+ if (typeSpec is ArrayType || typeSpec is PointerType || typeSpec is ByReferenceType)
+ return true;
+ typeSpec = typeSpec.ElementType as TypeSpecification;
+ }
+ return false;
+ }
+
+ internal static bool IsNullableType(TypeReference type)
+ {
+ return type != null && type.Name == "Nullable`1" && type.Namespace == "System";
+ }
+
+ public static TypeCode GetTypeCode(TypeReference type)
+ {
+ if (type == null)
+ return TypeCode.Empty;
+ switch (type.MetadataType) {
+ case MetadataType.Boolean:
+ return TypeCode.Boolean;
+ case MetadataType.Char:
+ return TypeCode.Char;
+ case MetadataType.SByte:
+ return TypeCode.SByte;
+ case MetadataType.Byte:
+ return TypeCode.Byte;
+ case MetadataType.Int16:
+ return TypeCode.Int16;
+ case MetadataType.UInt16:
+ return TypeCode.UInt16;
+ case MetadataType.Int32:
+ return TypeCode.Int32;
+ case MetadataType.UInt32:
+ return TypeCode.UInt32;
+ case MetadataType.Int64:
+ return TypeCode.Int64;
+ case MetadataType.UInt64:
+ return TypeCode.UInt64;
+ case MetadataType.Single:
+ return TypeCode.Single;
+ case MetadataType.Double:
+ return TypeCode.Double;
+ case MetadataType.String:
+ return TypeCode.String;
+ default:
+ return TypeCode.Object;
+ }
+ }
+
+ /// <summary>
+ /// Clears the type inference data on the method.
+ /// </summary>
+ public static void Reset(ILBlock method)
+ {
+ foreach (ILExpression expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
+ expr.InferredType = null;
+ expr.ExpectedType = null;
+ ILVariable v = expr.Operand as ILVariable;
+ if (v != null && v.IsGenerated)
+ v.Type = null;
+ }
+ }
+
+ public static bool IsSameType(TypeReference type1, TypeReference type2)
+ {
+ if (type1 == type2)
+ return true;
+ if (type1 == null || type2 == null)
+ return false;
+ return type1.FullName == type2.FullName; // TODO: implement this more efficiently?
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs b/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs
new file mode 100644
index 00000000..7a9a09ed
--- /dev/null
+++ b/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs
@@ -0,0 +1,635 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler.ILAst
+{
+ internal class YieldReturnDecompiler
+ {
+ // For a description on the code generated by the C# compiler for yield return:
+ // http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx
+
+ // The idea here is:
+ // - Figure out whether the current method is instanciating an enumerator
+ // - Figure out which of the fields is the state field
+ // - Construct an exception table based on states. This allows us to determine, for each state, what the parent try block is.
+
+ // See http://community.sharpdevelop.net/blogs/danielgrunwald/archive/2011/03/06/ilspy-yield-return.aspx
+ // for a description of this step.
+
+ DecompilerContext context;
+ TypeDefinition enumeratorType;
+ MethodDefinition enumeratorCtor;
+ MethodDefinition disposeMethod;
+ FieldDefinition stateField;
+ FieldDefinition currentField;
+ Dictionary<FieldDefinition, ILVariable> fieldToParameterMap = new Dictionary<FieldDefinition, ILVariable>();
+ List<ILNode> newBody;
+
+ #region Run() method
+ public static void Run(DecompilerContext context, ILBlock method)
+ {
+ if (!context.Settings.YieldReturn)
+ return; // abort if enumerator decompilation is disabled
+ var yrd = new YieldReturnDecompiler();
+ yrd.context = context;
+ if (!yrd.MatchEnumeratorCreationPattern(method))
+ return;
+ yrd.enumeratorType = yrd.enumeratorCtor.DeclaringType;
+ #if DEBUG
+ if (Debugger.IsAttached) {
+ yrd.Run();
+ } else {
+ #endif
+ try {
+ yrd.Run();
+ } catch (SymbolicAnalysisFailedException) {
+ return;
+ }
+ #if DEBUG
+ }
+ #endif
+ method.Body.Clear();
+ method.EntryGoto = null;
+ method.Body.AddRange(yrd.newBody);
+
+ // Repeat the inlining/copy propagation optimization because the conversion of field access
+ // to local variables can open up additional inlining possibilities.
+ ILInlining inlining = new ILInlining(method);
+ inlining.InlineAllVariables();
+ inlining.CopyPropagation();
+ }
+
+ void Run()
+ {
+ AnalyzeCtor();
+ AnalyzeCurrentProperty();
+ ResolveIEnumerableIEnumeratorFieldMapping();
+ ConstructExceptionTable();
+ AnalyzeMoveNext();
+ TranslateFieldsToLocalAccess();
+ }
+ #endregion
+
+ #region Match the enumerator creation pattern
+ bool MatchEnumeratorCreationPattern(ILBlock method)
+ {
+ if (method.Body.Count == 0)
+ return false;
+ ILExpression newObj;
+ if (method.Body.Count == 1) {
+ // ret(newobj(...))
+ if (method.Body[0].Match(ILCode.Ret, out newObj))
+ return MatchEnumeratorCreationNewObj(newObj, out enumeratorCtor);
+ else
+ return false;
+ }
+ // stloc(var_1, newobj(..)
+ ILVariable var1;
+ if (!method.Body[0].Match(ILCode.Stloc, out var1, out newObj))
+ return false;
+ if (!MatchEnumeratorCreationNewObj(newObj, out enumeratorCtor))
+ return false;
+
+ int i;
+ for (i = 1; i < method.Body.Count; i++) {
+ // stfld(..., ldloc(var_1), ldloc(parameter))
+ FieldReference storedField;
+ ILExpression ldloc, loadParameter;
+ if (!method.Body[i].Match(ILCode.Stfld, out storedField, out ldloc, out loadParameter))
+ break;
+ ILVariable loadedVar, loadedArg;
+ if (!ldloc.Match(ILCode.Ldloc, out loadedVar) || !loadParameter.Match(ILCode.Ldloc, out loadedArg))
+ return false;
+ storedField = GetFieldDefinition(storedField);
+ if (loadedVar != var1 || storedField == null || !loadedArg.IsParameter)
+ return false;
+ fieldToParameterMap[(FieldDefinition)storedField] = loadedArg;
+ }
+ ILVariable var2;
+ ILExpression ldlocForStloc2;
+ if (i < method.Body.Count && method.Body[i].Match(ILCode.Stloc, out var2, out ldlocForStloc2)) {
+ // stloc(var_2, ldloc(var_1))
+ if (ldlocForStloc2.Code != ILCode.Ldloc || ldlocForStloc2.Operand != var1)
+ return false;
+ i++;
+ } else {
+ // the compiler might skip the above instruction in release builds; in that case, it directly returns stloc.Operand
+ var2 = var1;
+ }
+ ILExpression retArg;
+ if (i < method.Body.Count && method.Body[i].Match(ILCode.Ret, out retArg)) {
+ // ret(ldloc(var_2))
+ if (retArg.Code == ILCode.Ldloc && retArg.Operand == var2) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static FieldDefinition GetFieldDefinition(FieldReference field)
+ {
+ return CecilExtensions.ResolveWithinSameModule(field);
+ }
+
+ static MethodDefinition GetMethodDefinition(MethodReference method)
+ {
+ return CecilExtensions.ResolveWithinSameModule(method);
+ }
+
+ bool MatchEnumeratorCreationNewObj(ILExpression expr, out MethodDefinition ctor)
+ {
+ // newobj(CurrentType/...::.ctor, ldc.i4(-2))
+ ctor = null;
+ if (expr.Code != ILCode.Newobj || expr.Arguments.Count != 1)
+ return false;
+ if (expr.Arguments[0].Code != ILCode.Ldc_I4)
+ return false;
+ int initialState = (int)expr.Arguments[0].Operand;
+ if (!(initialState == -2 || initialState == 0))
+ return false;
+ ctor = GetMethodDefinition(expr.Operand as MethodReference);
+ if (ctor == null || ctor.DeclaringType.DeclaringType != context.CurrentType)
+ return false;
+ return IsCompilerGeneratorEnumerator(ctor.DeclaringType);
+ }
+
+ public static bool IsCompilerGeneratorEnumerator(TypeDefinition type)
+ {
+ if (!(type.DeclaringType != null && type.IsCompilerGenerated()))
+ return false;
+ foreach (TypeReference i in type.Interfaces) {
+ if (i.Namespace == "System.Collections" && i.Name == "IEnumerator")
+ return true;
+ }
+ return false;
+ }
+ #endregion
+
+ #region Figure out what the 'state' field is (analysis of .ctor())
+ /// <summary>
+ /// Looks at the enumerator's ctor and figures out which of the fields holds the state.
+ /// </summary>
+ void AnalyzeCtor()
+ {
+ ILBlock method = CreateILAst(enumeratorCtor);
+
+ foreach (ILNode node in method.Body) {
+ FieldReference field;
+ ILExpression instExpr;
+ ILExpression stExpr;
+ ILVariable arg;
+ if (node.Match(ILCode.Stfld, out field, out instExpr, out stExpr) &&
+ instExpr.MatchThis() &&
+ stExpr.Match(ILCode.Ldloc, out arg) &&
+ arg.IsParameter && arg.OriginalParameter.Index == 0)
+ {
+ stateField = GetFieldDefinition(field);
+ }
+ }
+ if (stateField == null)
+ throw new SymbolicAnalysisFailedException();
+ }
+
+ /// <summary>
+ /// Creates ILAst for the specified method, optimized up to before the 'YieldReturn' step.
+ /// </summary>
+ ILBlock CreateILAst(MethodDefinition method)
+ {
+ if (method == null || !method.HasBody)
+ throw new SymbolicAnalysisFailedException();
+
+ ILBlock ilMethod = new ILBlock();
+ ILAstBuilder astBuilder = new ILAstBuilder();
+ ilMethod.Body = astBuilder.Build(method, true, context);
+ ILAstOptimizer optimizer = new ILAstOptimizer();
+ optimizer.Optimize(context, ilMethod, ILAstOptimizationStep.YieldReturn);
+ return ilMethod;
+ }
+ #endregion
+
+ #region Figure out what the 'current' field is (analysis of get_Current())
+ /// <summary>
+ /// Looks at the enumerator's get_Current method and figures out which of the fields holds the current value.
+ /// </summary>
+ void AnalyzeCurrentProperty()
+ {
+ MethodDefinition getCurrentMethod = enumeratorType.Methods.FirstOrDefault(
+ m => m.Name.StartsWith("System.Collections.Generic.IEnumerator", StringComparison.Ordinal)
+ && m.Name.EndsWith(".get_Current", StringComparison.Ordinal));
+ ILBlock method = CreateILAst(getCurrentMethod);
+ if (method.Body.Count == 1) {
+ // release builds directly return the current field
+ ILExpression retExpr;
+ FieldReference field;
+ ILExpression ldFromObj;
+ if (method.Body[0].Match(ILCode.Ret, out retExpr) &&
+ retExpr.Match(ILCode.Ldfld, out field, out ldFromObj) &&
+ ldFromObj.MatchThis())
+ {
+ currentField = GetFieldDefinition(field);
+ }
+ } else if (method.Body.Count == 2) {
+ ILVariable v, v2;
+ ILExpression stExpr;
+ FieldReference field;
+ ILExpression ldFromObj;
+ ILExpression retExpr;
+ if (method.Body[0].Match(ILCode.Stloc, out v, out stExpr) &&
+ stExpr.Match(ILCode.Ldfld, out field, out ldFromObj) &&
+ ldFromObj.MatchThis() &&
+ method.Body[1].Match(ILCode.Ret, out retExpr) &&
+ retExpr.Match(ILCode.Ldloc, out v2) &&
+ v == v2)
+ {
+ currentField = GetFieldDefinition(field);
+ }
+ }
+ if (currentField == null)
+ throw new SymbolicAnalysisFailedException();
+ }
+ #endregion
+
+ #region Figure out the mapping of IEnumerable fields to IEnumerator fields (analysis of GetEnumerator())
+ void ResolveIEnumerableIEnumeratorFieldMapping()
+ {
+ MethodDefinition getEnumeratorMethod = enumeratorType.Methods.FirstOrDefault(
+ m => m.Name.StartsWith("System.Collections.Generic.IEnumerable", StringComparison.Ordinal)
+ && m.Name.EndsWith(".GetEnumerator", StringComparison.Ordinal));
+ if (getEnumeratorMethod == null)
+ return; // no mappings (maybe it's just an IEnumerator implementation?)
+
+ ILBlock method = CreateILAst(getEnumeratorMethod);
+ foreach (ILNode node in method.Body) {
+ FieldReference stField;
+ ILExpression stToObj;
+ ILExpression stExpr;
+ FieldReference ldField;
+ ILExpression ldFromObj;
+ if (node.Match(ILCode.Stfld, out stField, out stToObj, out stExpr) &&
+ stExpr.Match(ILCode.Ldfld, out ldField, out ldFromObj) &&
+ ldFromObj.MatchThis())
+ {
+ FieldDefinition storedField = GetFieldDefinition(stField);
+ FieldDefinition loadedField = GetFieldDefinition(ldField);
+ if (storedField != null && loadedField != null) {
+ ILVariable mappedParameter;
+ if (fieldToParameterMap.TryGetValue(loadedField, out mappedParameter))
+ fieldToParameterMap[storedField] = mappedParameter;
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region Construction of the exception table (analysis of Dispose())
+ // We construct the exception table by analyzing the enumerator's Dispose() method.
+
+ // Assumption: there are no loops/backward jumps
+ // We 'run' the code, with "state" being a symbolic variable
+ // so it can form expressions like "state + x" (when there's a sub instruction)
+ // For each instruction, we maintain a list of value ranges for state for which the instruction is reachable.
+ // This is (int.MinValue, int.MaxValue) for the first instruction.
+ // These ranges are propagated depending on the conditional jumps performed by the code.
+
+ Dictionary<MethodDefinition, StateRange> finallyMethodToStateRange;
+
+ void ConstructExceptionTable()
+ {
+ disposeMethod = enumeratorType.Methods.FirstOrDefault(m => m.Name == "System.IDisposable.Dispose");
+ ILBlock ilMethod = CreateILAst(disposeMethod);
+
+ var rangeAnalysis = new StateRangeAnalysis(ilMethod.Body[0], StateRangeAnalysisMode.IteratorDispose, stateField);
+ rangeAnalysis.AssignStateRanges(ilMethod.Body, ilMethod.Body.Count);
+ finallyMethodToStateRange = rangeAnalysis.finallyMethodToStateRange;
+
+ // Now look at the finally blocks:
+ foreach (var tryFinally in ilMethod.GetSelfAndChildrenRecursive<ILTryCatchBlock>()) {
+ var range = rangeAnalysis.ranges[tryFinally.TryBlock.Body[0]];
+ var finallyBody = tryFinally.FinallyBlock.Body;
+ if (finallyBody.Count != 2)
+ throw new SymbolicAnalysisFailedException();
+ ILExpression call = finallyBody[0] as ILExpression;
+ if (call == null || call.Code != ILCode.Call || call.Arguments.Count != 1)
+ throw new SymbolicAnalysisFailedException();
+ if (!call.Arguments[0].MatchThis())
+ throw new SymbolicAnalysisFailedException();
+ if (!finallyBody[1].Match(ILCode.Endfinally))
+ throw new SymbolicAnalysisFailedException();
+
+ MethodDefinition mdef = GetMethodDefinition(call.Operand as MethodReference);
+ if (mdef == null || finallyMethodToStateRange.ContainsKey(mdef))
+ throw new SymbolicAnalysisFailedException();
+ finallyMethodToStateRange.Add(mdef, range);
+ }
+ rangeAnalysis = null;
+ }
+ #endregion
+
+ #region Analysis of MoveNext()
+ ILVariable returnVariable;
+ ILLabel returnLabel;
+ ILLabel returnFalseLabel;
+
+ void AnalyzeMoveNext()
+ {
+ MethodDefinition moveNextMethod = enumeratorType.Methods.FirstOrDefault(m => m.Name == "MoveNext");
+ ILBlock ilMethod = CreateILAst(moveNextMethod);
+
+ if (ilMethod.Body.Count == 0)
+ throw new SymbolicAnalysisFailedException();
+ ILExpression lastReturnArg;
+ if (!ilMethod.Body.Last().Match(ILCode.Ret, out lastReturnArg))
+ throw new SymbolicAnalysisFailedException();
+
+ // There are two possibilities:
+ if (lastReturnArg.Code == ILCode.Ldloc) {
+ // a) the compiler uses a variable for returns (in debug builds, or when there are try-finally blocks)
+ returnVariable = (ILVariable)lastReturnArg.Operand;
+ returnLabel = ilMethod.Body.ElementAtOrDefault(ilMethod.Body.Count - 2) as ILLabel;
+ if (returnLabel == null)
+ throw new SymbolicAnalysisFailedException();
+ } else {
+ // b) the compiler directly returns constants
+ returnVariable = null;
+ returnLabel = null;
+ // In this case, the last return must return false.
+ if (lastReturnArg.Code != ILCode.Ldc_I4 || (int)lastReturnArg.Operand != 0)
+ throw new SymbolicAnalysisFailedException();
+ }
+
+ ILTryCatchBlock tryFaultBlock = ilMethod.Body[0] as ILTryCatchBlock;
+ List<ILNode> body;
+ int bodyLength;
+ if (tryFaultBlock != null) {
+ // there are try-finally blocks
+ if (returnVariable == null) // in this case, we must use a return variable
+ throw new SymbolicAnalysisFailedException();
+ // must be a try-fault block:
+ if (tryFaultBlock.CatchBlocks.Count != 0 || tryFaultBlock.FinallyBlock != null || tryFaultBlock.FaultBlock == null)
+ throw new SymbolicAnalysisFailedException();
+
+ ILBlock faultBlock = tryFaultBlock.FaultBlock;
+ // Ensure the fault block contains the call to Dispose().
+ if (faultBlock.Body.Count != 2)
+ throw new SymbolicAnalysisFailedException();
+ MethodReference disposeMethodRef;
+ ILExpression disposeArg;
+ if (!faultBlock.Body[0].Match(ILCode.Call, out disposeMethodRef, out disposeArg))
+ throw new SymbolicAnalysisFailedException();
+ if (GetMethodDefinition(disposeMethodRef) != disposeMethod || !disposeArg.MatchThis())
+ throw new SymbolicAnalysisFailedException();
+ if (!faultBlock.Body[1].Match(ILCode.Endfinally))
+ throw new SymbolicAnalysisFailedException();
+
+ body = tryFaultBlock.TryBlock.Body;
+ bodyLength = body.Count;
+ } else {
+ // no try-finally blocks
+ body = ilMethod.Body;
+ if (returnVariable == null)
+ bodyLength = body.Count - 1; // all except for the return statement
+ else
+ bodyLength = body.Count - 2; // all except for the return label and statement
+ }
+
+ // Now verify that the last instruction in the body is 'ret(false)'
+ if (returnVariable != null) {
+ // If we don't have a return variable, we already verified that above.
+ // If we do have one, check for 'stloc(returnVariable, ldc.i4(0))'
+
+ // Maybe might be a jump to the return label after the stloc:
+ ILExpression leave = body.ElementAtOrDefault(bodyLength - 1) as ILExpression;
+ if (leave != null && (leave.Code == ILCode.Br || leave.Code == ILCode.Leave) && leave.Operand == returnLabel)
+ bodyLength--;
+ ILExpression store0 = body.ElementAtOrDefault(bodyLength - 1) as ILExpression;
+ if (store0 == null || store0.Code != ILCode.Stloc || store0.Operand != returnVariable)
+ throw new SymbolicAnalysisFailedException();
+ if (store0.Arguments[0].Code != ILCode.Ldc_I4 || (int)store0.Arguments[0].Operand != 0)
+ throw new SymbolicAnalysisFailedException();
+
+ bodyLength--; // don't conside the stloc instruction to be part of the body
+ }
+ // The last element in the body usually is a label pointing to the 'ret(false)'
+ returnFalseLabel = body.ElementAtOrDefault(bodyLength - 1) as ILLabel;
+ // Note: in Roslyn-compiled code, returnFalseLabel may be null.
+
+ var rangeAnalysis = new StateRangeAnalysis(body[0], StateRangeAnalysisMode.IteratorMoveNext, stateField);
+ int pos = rangeAnalysis.AssignStateRanges(body, bodyLength);
+ rangeAnalysis.EnsureLabelAtPos(body, ref pos, ref bodyLength);
+
+ var labels = rangeAnalysis.CreateLabelRangeMapping(body, pos, bodyLength);
+ ConvertBody(body, pos, bodyLength, labels);
+ }
+ #endregion
+
+ #region ConvertBody
+ struct SetState
+ {
+ public readonly int NewBodyPos;
+ public readonly int NewState;
+
+ public SetState(int newBodyPos, int newState)
+ {
+ NewBodyPos = newBodyPos;
+ NewState = newState;
+ }
+ }
+
+ void ConvertBody(List<ILNode> body, int startPos, int bodyLength, List<KeyValuePair<ILLabel, StateRange>> labels)
+ {
+ newBody = new List<ILNode>();
+ newBody.Add(MakeGoTo(labels, 0));
+ List<SetState> stateChanges = new List<SetState>();
+ int currentState = -1;
+ // Copy all instructions from the old body to newBody.
+ for (int pos = startPos; pos < bodyLength; pos++) {
+ ILExpression expr = body[pos] as ILExpression;
+ if (expr != null && expr.Code == ILCode.Stfld && expr.Arguments[0].MatchThis()) {
+ // Handle stores to 'state' or 'current'
+ if (GetFieldDefinition(expr.Operand as FieldReference) == stateField) {
+ if (expr.Arguments[1].Code != ILCode.Ldc_I4)
+ throw new SymbolicAnalysisFailedException();
+ currentState = (int)expr.Arguments[1].Operand;
+ stateChanges.Add(new SetState(newBody.Count, currentState));
+ } else if (GetFieldDefinition(expr.Operand as FieldReference) == currentField) {
+ newBody.Add(new ILExpression(ILCode.YieldReturn, null, expr.Arguments[1]));
+ } else {
+ newBody.Add(body[pos]);
+ }
+ } else if (returnVariable != null && expr != null && expr.Code == ILCode.Stloc && expr.Operand == returnVariable) {
+ // handle store+branch to the returnVariable
+ ILExpression br = body.ElementAtOrDefault(++pos) as ILExpression;
+ if (br == null || !(br.Code == ILCode.Br || br.Code == ILCode.Leave) || br.Operand != returnLabel || expr.Arguments[0].Code != ILCode.Ldc_I4)
+ throw new SymbolicAnalysisFailedException();
+ int val = (int)expr.Arguments[0].Operand;
+ if (val == 0) {
+ newBody.Add(new ILExpression(ILCode.YieldBreak, null));
+ } else if (val == 1) {
+ newBody.Add(MakeGoTo(labels, currentState));
+ } else {
+ throw new SymbolicAnalysisFailedException();
+ }
+ } else if (expr != null && expr.Code == ILCode.Ret) {
+ if (expr.Arguments.Count != 1 || expr.Arguments[0].Code != ILCode.Ldc_I4)
+ throw new SymbolicAnalysisFailedException();
+ // handle direct return (e.g. in release builds)
+ int val = (int)expr.Arguments[0].Operand;
+ if (val == 0) {
+ newBody.Add(new ILExpression(ILCode.YieldBreak, null));
+ } else if (val == 1) {
+ newBody.Add(MakeGoTo(labels, currentState));
+ } else {
+ throw new SymbolicAnalysisFailedException();
+ }
+ } else if (expr != null && expr.Code == ILCode.Call && expr.Arguments.Count == 1 && expr.Arguments[0].MatchThis()) {
+ MethodDefinition method = GetMethodDefinition(expr.Operand as MethodReference);
+ if (method == null)
+ throw new SymbolicAnalysisFailedException();
+ StateRange stateRange;
+ if (method == disposeMethod) {
+ // Explicit call to dispose is used for "yield break;" within the method.
+ ILExpression br = body.ElementAtOrDefault(++pos) as ILExpression;
+ if (br == null || !(br.Code == ILCode.Br || br.Code == ILCode.Leave) || br.Operand != returnFalseLabel)
+ throw new SymbolicAnalysisFailedException();
+ newBody.Add(new ILExpression(ILCode.YieldBreak, null));
+ } else if (finallyMethodToStateRange.TryGetValue(method, out stateRange)) {
+ // Call to Finally-method
+ int index = stateChanges.FindIndex(ss => stateRange.Contains(ss.NewState));
+ if (index < 0)
+ throw new SymbolicAnalysisFailedException();
+
+ ILLabel label = new ILLabel();
+ label.Name = "JumpOutOfTryFinally" + stateChanges[index].NewState;
+ newBody.Add(new ILExpression(ILCode.Leave, label));
+
+ SetState stateChange = stateChanges[index];
+ // Move all instructions from stateChange.Pos to newBody.Count into a try-block
+ stateChanges.RemoveRange(index, stateChanges.Count - index); // remove all state changes up to the one we found
+ ILTryCatchBlock tryFinally = new ILTryCatchBlock();
+ tryFinally.TryBlock = new ILBlock(newBody.GetRange(stateChange.NewBodyPos, newBody.Count - stateChange.NewBodyPos));
+ newBody.RemoveRange(stateChange.NewBodyPos, newBody.Count - stateChange.NewBodyPos); // remove all nodes that we just moved into the try block
+ tryFinally.CatchBlocks = new List<ILTryCatchBlock.CatchBlock>();
+ tryFinally.FinallyBlock = ConvertFinallyBlock(method);
+ newBody.Add(tryFinally);
+ newBody.Add(label);
+ }
+ } else {
+ newBody.Add(body[pos]);
+ }
+ }
+ newBody.Add(new ILExpression(ILCode.YieldBreak, null));
+ }
+
+ ILExpression MakeGoTo(ILLabel targetLabel)
+ {
+ Debug.Assert(targetLabel != null);
+ if (targetLabel == returnFalseLabel)
+ return new ILExpression(ILCode.YieldBreak, null);
+ else
+ return new ILExpression(ILCode.Br, targetLabel);
+ }
+
+ ILExpression MakeGoTo(List<KeyValuePair<ILLabel, StateRange>> labels, int state)
+ {
+ foreach (var pair in labels) {
+ if (pair.Value.Contains(state))
+ return MakeGoTo(pair.Key);
+ }
+ throw new SymbolicAnalysisFailedException();
+ }
+
+ ILBlock ConvertFinallyBlock(MethodDefinition finallyMethod)
+ {
+ ILBlock block = CreateILAst(finallyMethod);
+ // Get rid of assignment to state
+ FieldReference stfld;
+ List<ILExpression> args;
+ if (block.Body.Count > 0 && block.Body[0].Match(ILCode.Stfld, out stfld, out args)) {
+ if (GetFieldDefinition(stfld) == stateField && args[0].MatchThis())
+ block.Body.RemoveAt(0);
+ }
+ // Convert ret to endfinally
+ foreach (ILExpression expr in block.GetSelfAndChildrenRecursive<ILExpression>()) {
+ if (expr.Code == ILCode.Ret)
+ expr.Code = ILCode.Endfinally;
+ }
+ return block;
+ }
+ #endregion
+
+ #region TranslateFieldsToLocalAccess
+ void TranslateFieldsToLocalAccess()
+ {
+ TranslateFieldsToLocalAccess(newBody, fieldToParameterMap);
+ }
+
+ internal static void TranslateFieldsToLocalAccess(List<ILNode> newBody, Dictionary<FieldDefinition, ILVariable> fieldToParameterMap)
+ {
+ var fieldToLocalMap = new DefaultDictionary<FieldDefinition, ILVariable>(f => new ILVariable { Name = f.Name, Type = f.FieldType });
+ foreach (ILNode node in newBody) {
+ foreach (ILExpression expr in node.GetSelfAndChildrenRecursive<ILExpression>()) {
+ FieldDefinition field = GetFieldDefinition(expr.Operand as FieldReference);
+ if (field != null) {
+ switch (expr.Code) {
+ case ILCode.Ldfld:
+ if (expr.Arguments[0].MatchThis()) {
+ expr.Code = ILCode.Ldloc;
+ if (fieldToParameterMap.ContainsKey(field)) {
+ expr.Operand = fieldToParameterMap[field];
+ } else {
+ expr.Operand = fieldToLocalMap[field];
+ }
+ expr.Arguments.Clear();
+ }
+ break;
+ case ILCode.Stfld:
+ if (expr.Arguments[0].MatchThis()) {
+ expr.Code = ILCode.Stloc;
+ if (fieldToParameterMap.ContainsKey(field)) {
+ expr.Operand = fieldToParameterMap[field];
+ } else {
+ expr.Operand = fieldToLocalMap[field];
+ }
+ expr.Arguments.RemoveAt(0);
+ }
+ break;
+ case ILCode.Ldflda:
+ if (expr.Arguments[0].MatchThis()) {
+ expr.Code = ILCode.Ldloca;
+ if (fieldToParameterMap.ContainsKey(field)) {
+ expr.Operand = fieldToParameterMap[field];
+ } else {
+ expr.Operand = fieldToLocalMap[field];
+ }
+ expr.Arguments.Clear();
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ #endregion
+ }
+}
diff --git a/ICSharpCode.Decompiler/ITextOutput.cs b/ICSharpCode.Decompiler/ITextOutput.cs
new file mode 100644
index 00000000..f13a55d6
--- /dev/null
+++ b/ICSharpCode.Decompiler/ITextOutput.cs
@@ -0,0 +1,62 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.IO;
+using ICSharpCode.NRefactory;
+using Mono.Cecil;
+
+namespace ICSharpCode.Decompiler
+{
+ public interface ITextOutput
+ {
+ TextLocation Location { get; }
+
+ void Indent();
+ void Unindent();
+ void Write(char ch);
+ void Write(string text);
+ void WriteLine();
+ void WriteDefinition(string text, object definition, bool isLocal = true);
+ void WriteReference(string text, object reference, bool isLocal = false);
+
+ void AddDebugSymbols(MethodDebugSymbols methodDebugSymbols);
+
+ void MarkFoldStart(string collapsedText = "...", bool defaultCollapsed = false);
+ void MarkFoldEnd();
+ }
+
+ public static class TextOutputExtensions
+ {
+ public static void Write(this ITextOutput output, string format, params object[] args)
+ {
+ output.Write(string.Format(format, args));
+ }
+
+ public static void WriteLine(this ITextOutput output, string text)
+ {
+ output.Write(text);
+ output.WriteLine();
+ }
+
+ public static void WriteLine(this ITextOutput output, string format, params object[] args)
+ {
+ output.WriteLine(string.Format(format, args));
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/PlainTextOutput.cs b/ICSharpCode.Decompiler/PlainTextOutput.cs
new file mode 100644
index 00000000..468096fa
--- /dev/null
+++ b/ICSharpCode.Decompiler/PlainTextOutput.cs
@@ -0,0 +1,122 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.IO;
+using ICSharpCode.NRefactory;
+
+namespace ICSharpCode.Decompiler
+{
+ public sealed class PlainTextOutput : ITextOutput
+ {
+ readonly TextWriter writer;
+ int indent;
+ bool needsIndent;
+
+ int line = 1;
+ int column = 1;
+
+ public PlainTextOutput(TextWriter writer)
+ {
+ if (writer == null)
+ throw new ArgumentNullException("writer");
+ this.writer = writer;
+ }
+
+ public PlainTextOutput()
+ {
+ writer = new StringWriter();
+ }
+
+ public TextLocation Location {
+ get {
+ return new TextLocation(line, column + (needsIndent ? indent : 0));
+ }
+ }
+
+ public override string ToString()
+ {
+ return writer.ToString();
+ }
+
+ public void Indent()
+ {
+ indent++;
+ }
+
+ public void Unindent()
+ {
+ indent--;
+ }
+
+ void WriteIndent()
+ {
+ if (needsIndent) {
+ needsIndent = false;
+ for (int i = 0; i < indent; i++) {
+ writer.Write('\t');
+ }
+ column += indent;
+ }
+ }
+
+ public void Write(char ch)
+ {
+ WriteIndent();
+ writer.Write(ch);
+ column++;
+ }
+
+ public void Write(string text)
+ {
+ WriteIndent();
+ writer.Write(text);
+ column += text.Length;
+ }
+
+ public void WriteLine()
+ {
+ writer.WriteLine();
+ needsIndent = true;
+ line++;
+ column = 1;
+ }
+
+ public void WriteDefinition(string text, object definition, bool isLocal)
+ {
+ Write(text);
+ }
+
+ public void WriteReference(string text, object reference, bool isLocal)
+ {
+ Write(text);
+ }
+
+ void ITextOutput.MarkFoldStart(string collapsedText, bool defaultCollapsed)
+ {
+ }
+
+ void ITextOutput.MarkFoldEnd()
+ {
+ }
+
+ void ITextOutput.AddDebugSymbols(MethodDebugSymbols methodDebugSymbols)
+ {
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs b/ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs
new file mode 100644
index 00000000..3dba481a
--- /dev/null
+++ b/ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs
@@ -0,0 +1,27 @@
+#region Using directives
+
+using System;
+using System.Resources;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+#endregion
+
+[assembly: AssemblyTitle("ICSharpCode.Decompiler")]
+[assembly: AssemblyDescription("IL decompiler engine")]
+[assembly: AssemblyCompany("ic#code")]
+[assembly: AssemblyProduct("ILSpy")]
+[assembly: AssemblyCopyright("Copyright 2011-2014 AlphaSierraPapa for the SharpDevelop Team")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// This sets the default COM visibility of types in the assembly to invisible.
+// If you need to expose a type to COM, use [ComVisible(true)] on that type.
+[assembly: ComVisible(false)]
+
+[assembly: AssemblyVersion("$INSERTVERSION$")]
+[assembly: AssemblyInformationalVersion("$INSERTVERSION$$INSERTBRANCHPOSTFIX$$INSERTVERSIONNAMEPOSTFIX$-$INSERTSHORTCOMMITHASH$")]
+[assembly: NeutralResourcesLanguage("en-US")]
+
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly",
+ Justification = "AssemblyInformationalVersion does not need to be a parsable version")]
diff --git a/ICSharpCode.Decompiler/ReferenceResolvingException.cs b/ICSharpCode.Decompiler/ReferenceResolvingException.cs
new file mode 100644
index 00000000..dbceb44b
--- /dev/null
+++ b/ICSharpCode.Decompiler/ReferenceResolvingException.cs
@@ -0,0 +1,68 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ICSharpCode.Decompiler
+{
+ /// <summary>
+ /// Represents an error while resolving a reference to a type or a member.
+ /// </summary>
+ [Serializable]
+ public class ReferenceResolvingException : Exception
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:ResolveException"/> class
+ /// </summary>
+ public ReferenceResolvingException()
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:ResolveException"/> class
+ /// </summary>
+ /// <param name="message">A <see cref="T:System.String"/> that describes the error. The content of message is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture.</param>
+ public ReferenceResolvingException(string message)
+ : base(message)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:ResolveException"/> class
+ /// </summary>
+ /// <param name="message">A <see cref="T:System.String"/> that describes the error. The content of message is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture.</param>
+ /// <param name="inner">The exception that is the cause of the current exception. If the innerException parameter is not a null reference, the current exception is raised in a catch block that handles the inner exception.</param>
+ public ReferenceResolvingException(string message, Exception inner)
+ : base(message, inner)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:ResolveException"/> class
+ /// </summary>
+ /// <param name="info">The object that holds the serialized object data.</param>
+ /// <param name="context">The contextual information about the source or destination.</param>
+ protected ReferenceResolvingException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
+ : base(info, context)
+ {
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Async.cs b/ICSharpCode.Decompiler/Tests/Async.cs
new file mode 100644
index 00000000..7629dd5e
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Async.cs
@@ -0,0 +1,155 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#pragma warning disable 1998
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+
+public class Async
+{
+ public async void SimpleVoidMethod()
+ {
+ Console.WriteLine("Before");
+ await Task.Delay(TimeSpan.FromSeconds(1.0));
+ Console.WriteLine("After");
+ }
+
+ public async void VoidMethodWithoutAwait()
+ {
+ Console.WriteLine("No Await");
+ }
+
+ public async void AwaitYield()
+ {
+ await Task.Yield();
+ }
+
+ public async void AwaitDefaultYieldAwaitable()
+ {
+ await default(YieldAwaitable);
+ }
+
+ public async Task SimpleVoidTaskMethod()
+ {
+ Console.WriteLine("Before");
+ await Task.Delay(TimeSpan.FromSeconds(1.0));
+ Console.WriteLine("After");
+ }
+
+ public async Task TaskMethodWithoutAwait()
+ {
+ Console.WriteLine("No Await");
+ }
+
+ public async Task<bool> SimpleBoolTaskMethod()
+ {
+ Console.WriteLine("Before");
+ await Task.Delay(TimeSpan.FromSeconds(1.0));
+ Console.WriteLine("After");
+ return true;
+ }
+
+ public async void TwoAwaitsWithDifferentAwaiterTypes()
+ {
+ Console.WriteLine("Before");
+ if (await this.SimpleBoolTaskMethod())
+ {
+ await Task.Delay(TimeSpan.FromSeconds(1.0));
+ }
+ Console.WriteLine("After");
+ }
+
+ public async void StreamCopyTo(Stream destination, int bufferSize)
+ {
+ byte[] array = new byte[bufferSize];
+ int count;
+ while ((count = await destination.ReadAsync(array, 0, array.Length)) != 0)
+ {
+ await destination.WriteAsync(array, 0, count);
+ }
+ }
+
+ public async void StreamCopyToWithConfigureAwait(Stream destination, int bufferSize)
+ {
+ byte[] array = new byte[bufferSize];
+ int count;
+ while ((count = await destination.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0)
+ {
+ await destination.WriteAsync(array, 0, count).ConfigureAwait(false);
+ }
+ }
+
+ public async void AwaitInLoopCondition()
+ {
+ while (await this.SimpleBoolTaskMethod())
+ {
+ Console.WriteLine("Body");
+ }
+ }
+
+ public async Task<int> AwaitInForEach(IEnumerable<Task<int>> elements)
+ {
+ int num = 0;
+ foreach (Task<int> current in elements)
+ {
+ num += await current;
+ }
+ return num;
+ }
+
+ public async Task TaskMethodWithoutAwaitButWithExceptionHandling()
+ {
+ try
+ {
+ using (new StringWriter())
+ {
+ Console.WriteLine("No Await");
+ }
+ }
+ catch (Exception)
+ {
+ Console.WriteLine("Crash");
+ }
+ }
+
+ public async Task<int> NestedAwait(Task<Task<int>> task)
+ {
+ return await(await task);
+ }
+
+ public async Task AwaitWithStack(Task<int> task)
+ {
+ Console.WriteLine("A", 1, await task);
+ }
+
+ public async Task AwaitWithStack2(Task<int> task)
+ {
+ if (await this.SimpleBoolTaskMethod())
+ {
+ Console.WriteLine("A", 1, await task);
+ }
+ else
+ {
+ int num = 1;
+ Console.WriteLine("A", 1, num);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il b/ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il
new file mode 100644
index 00000000..9e300027
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il
@@ -0,0 +1,59 @@
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
+ .ver 4:0:0:0
+}
+.assembly BooleanConsumedAsInteger
+{
+ .hash algorithm 0x00008004
+ .ver 1:0:0:0
+}
+.module BooleanConsumedAsInteger.exe
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000003 // ILONLY 32BITREQUIRED
+
+.class private auto ansi beforefieldinit BooleanConsumedAsInteger.Program extends [mscorlib]System.Object
+{
+ .method public hidebysig static void Main(string[] args) cil managed
+ {
+ .entrypoint
+ .maxstack 8
+
+ ret
+ }
+
+ .method public hidebysig static int32 ReturnBoolAsInt() cil managed
+ {
+ ldnull
+ ldnull
+ call bool [mscorlib] System.Object::Equals(object, object)
+ ret
+ }
+
+ .method public hidebysig static int32 BitwiseOperationOnBool() cil managed
+ {
+ ldnull
+ ldnull
+ call bool [mscorlib] System.Object::Equals(object, object)
+ ldc.i4 255
+ and
+ ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method Program::.ctor
+
+} // end of class StackTests.Program
+
+
+// =============================================================
diff --git a/ICSharpCode.Decompiler/Tests/CallOverloadedMethod.cs b/ICSharpCode.Decompiler/Tests/CallOverloadedMethod.cs
new file mode 100644
index 00000000..4f493ef2
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CallOverloadedMethod.cs
@@ -0,0 +1,52 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+
+public class CallOverloadedMethod
+{
+ public void OverloadedMethod(object a)
+ {
+ }
+
+ public void OverloadedMethod(int? a)
+ {
+ }
+
+ public void OverloadedMethod(string a)
+ {
+ }
+
+ public void Call()
+ {
+ this.OverloadedMethod("(string)");
+ this.OverloadedMethod((object)"(object)");
+ this.OverloadedMethod(5);
+ this.OverloadedMethod((object)5);
+ this.OverloadedMethod(5L);
+ this.OverloadedMethod((object)null);
+ this.OverloadedMethod((string)null);
+ this.OverloadedMethod((int?)null);
+ }
+
+ public void CallMethodUsingInterface(List<int> list)
+ {
+ ((ICollection<int>)list).Clear();
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/CheckedUnchecked.cs b/ICSharpCode.Decompiler/Tests/CheckedUnchecked.cs
new file mode 100644
index 00000000..fd1c4d89
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CheckedUnchecked.cs
@@ -0,0 +1,117 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class CheckedUnchecked
+{
+ public int Operators(int a, int b)
+ {
+ int num = checked(a + b);
+ int num2 = a + b;
+ int num3 = checked(a - b);
+ int num4 = a - b;
+ int num5 = checked(a * b);
+ int num6 = a * b;
+ int num7 = a / b;
+ int num8 = a % b;
+ // The division operators / and % only exist in one form (checked vs. unchecked doesn't matter for them)
+ return num * num2 * num3 * num4 * num5 * num6 * num7 * num8;
+ }
+
+ public int Cast(int a)
+ {
+ short num = checked((short)a);
+ short num2 = (short)a;
+ byte b = checked((byte)a);
+ byte b2 = (byte)a;
+ return num * num2 * b * b2;
+ }
+
+ public void ForWithCheckedIteratorAndUncheckedBody(int n)
+ {
+ checked
+ {
+ for (int i = n + 1; i < n + 1; i++)
+ {
+ n = unchecked(i * i);
+ }
+ }
+ }
+
+ public void ForWithCheckedInitializerAndUncheckedIterator(int n)
+ {
+ checked
+ {
+ int i = n;
+ for (i -= 10; i < n; i = unchecked(i + 1))
+ {
+ n--;
+ }
+ }
+ }
+ public void ObjectCreationInitializerChecked()
+ {
+ this.TestHelp(new
+ {
+ x = 0,
+ l = 0
+ }, n => checked(new
+ {
+ x = n.x + 1,
+ l = n.l + 1
+ }));
+ }
+
+ public void ObjectCreationWithOneFieldChecked()
+ {
+ this.TestHelp(new
+ {
+ x = 0,
+ l = 0
+ }, n => new
+ {
+ x = checked(n.x + 1),
+ l = n.l + 1
+ });
+ }
+
+
+ public void ArrayInitializerChecked()
+ {
+ this.TestHelp<int[]>(new int[]
+ {
+ 1,
+ 2
+ }, (int[] n) => checked(new int[]
+ {
+ n[0] + 1,
+ n[1] + 1
+ }));
+ }
+
+ public T TestHelp<T>(T t, Func<T, T> f)
+ {
+ return f(t);
+ }
+
+ public void CheckedInArrayCreationArgument(int a, int b)
+ {
+ Console.WriteLine(new int[checked(a + b)]);
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs b/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs
new file mode 100644
index 00000000..5cb49aad
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs
@@ -0,0 +1,133 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+
+namespace ICSharpCode.Decompiler.Tests
+{
+ static class CodeSampleFileParser
+ {
+ public static IEnumerable<string> ListSections(string s)
+ {
+ var query = from line in ToLines(s)
+ let sectionName = ReadSectionName(line)
+ where sectionName != null
+ select sectionName;
+ return query;
+ }
+
+ public static string GetSection(string sectionName, string s)
+ {
+ var lines = ToLines(s);
+
+ bool sectionFound = false;
+ var sectionText = new StringBuilder();
+
+ Action<string> parser = null;
+
+ Action<string> commonSectionReader = line =>
+ {
+ if (IsCommonSectionEnd(line))
+ parser = null;
+ else
+ sectionText.AppendLine(line);
+ };
+
+ Action<string> namedSectionReader = line =>
+ {
+ string name = ReadSectionName(line);
+ if (name == null)
+ sectionText.AppendLine(line);
+ else if (name != sectionName)
+ parser = null;
+ };
+
+ Action<string> defaultReader = line =>
+ {
+ if (IsCommonSectionStart(line))
+ parser = commonSectionReader;
+ else if (ReadSectionName(line) == sectionName)
+ {
+ parser = namedSectionReader;
+ sectionFound = true;
+ }
+ };
+
+ foreach(var line in lines)
+ {
+ (parser ?? defaultReader)(line);
+ }
+
+ if (sectionFound)
+ return sectionText.ToString();
+ else
+ return "";
+ }
+
+ public static bool IsCommentOrBlank(string s)
+ {
+ if(String.IsNullOrWhiteSpace(s))
+ return true;
+ s = s.Trim();
+ return s.StartsWith("//") || s.StartsWith("#"); // Also ignore #pragmas for warning suppression
+ }
+
+ public static string ConcatLines(IEnumerable<string> lines)
+ {
+ var buffer = new StringBuilder();
+ foreach (var line in lines)
+ {
+ buffer.AppendLine(line);
+ }
+ return buffer.ToString();
+ }
+
+ static string ReadSectionName(string line)
+ {
+ line = line.TrimStart();
+ if (line.StartsWith("//$$"))
+ return line.Substring(4).Trim();
+ else
+ return null;
+ }
+
+ static bool IsCommonSectionStart(string line)
+ {
+ return line.Trim() == "//$CS";
+ }
+
+ static bool IsCommonSectionEnd(string line)
+ {
+ return line.Trim() == "//$CE";
+ }
+
+ static IEnumerable<string> ToLines(string s)
+ {
+ var reader = new StringReader(s);
+ string line;
+ while ((line = reader.ReadLine()) != null)
+ {
+ yield return line;
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/ControlFlow.cs b/ICSharpCode.Decompiler/Tests/ControlFlow.cs
new file mode 100644
index 00000000..d83f04a2
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/ControlFlow.cs
@@ -0,0 +1,97 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+
+public static class ControlFlow
+{
+ public static void EmptyIf(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ }
+ _headers.Add(2, "result");
+ }
+
+ public static void NormalIf(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ else
+ {
+ _headers.Add(1, "else");
+ }
+ _headers.Add(2, "end");
+ }
+
+ public static void NormalIf2(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ _headers.Add(2, "end");
+ }
+
+ public static void NormalIf3(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ else
+ {
+ _headers.Add(1, "else");
+ }
+ }
+
+ public static void Test(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ foreach (string current in value)
+ {
+ _headers.Add(0, current);
+ }
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ else
+ {
+ _headers.Add(1, "else");
+ }
+ }
+
+ public static void CascadingIfElse(bool condition, string input, int index)
+ {
+ if (condition)
+ {
+ Console.WriteLine("condition");
+ }
+ else if (input == null)
+ {
+ Console.WriteLine("condition2");
+ }
+ else if (index > 1)
+ {
+ Console.WriteLine("condition3");
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs
new file mode 100644
index 00000000..4130b0b0
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs
@@ -0,0 +1,41 @@
+using System;
+namespace aa
+{
+ public static class CustomAtributes
+ {
+ [Flags]
+ public enum EnumWithFlag
+ {
+ All = 15,
+ None = 0,
+ Item1 = 1,
+ Item2 = 2,
+ Item3 = 4,
+ Item4 = 8
+ }
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttribute : Attribute
+ {
+ public MyAttribute(CustomAtributes.EnumWithFlag en)
+ {
+ }
+ }
+ [CustomAtributes.MyAttribute(CustomAtributes.EnumWithFlag.Item1 | CustomAtributes.EnumWithFlag.Item2)]
+ private static int field;
+ [CustomAtributes.MyAttribute(CustomAtributes.EnumWithFlag.All)]
+ public static string Property
+ {
+ get
+ {
+ return "aa";
+ }
+ }
+ [Obsolete("some message")]
+ public static void ObsoletedMethod()
+ {
+ Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, AttributeTargets.Property | AttributeTargets.Field);
+ AttributeTargets attributeTargets = AttributeTargets.Property | AttributeTargets.Field;
+ Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, attributeTargets);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs
new file mode 100644
index 00000000..892f33bf
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests.CustomAttributes
+{
+ [TestFixture]
+ public class CustomAttributeTests : DecompilerTestBase
+ {
+ [Test]
+ public void CustomAttributeSamples()
+ {
+ ValidateFileRoundtrip(@"CustomAttributes\S_CustomAttributeSamples.cs");
+ }
+
+ [Test]
+ public void CustomAttributesMultiTest()
+ {
+ ValidateFileRoundtrip(@"CustomAttributes\S_CustomAttributes.cs");
+ }
+
+ [Test]
+ public void AssemblyCustomAttributesMultiTest()
+ {
+ ValidateFileRoundtrip(@"CustomAttributes\S_AssemblyCustomAttribute.cs");
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/S_AssemblyCustomAttribute.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_AssemblyCustomAttribute.cs
new file mode 100644
index 00000000..feaa04a6
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_AssemblyCustomAttribute.cs
@@ -0,0 +1,21 @@
+// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+[assembly: CLSCompliant(false)]
diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs
new file mode 100644
index 00000000..7154b2c3
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs
@@ -0,0 +1,508 @@
+// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+//$CS
+using System;
+//$CE
+
+//$$ TargetModule (ignored)
+//[module: CLSCompliantAttribute(false)]
+//$$ ParameterlessAttributeUsage
+namespace ParameterLessAttributeUsage
+{
+ [Flags]
+ public enum EnumWithFlagsAttribute
+ {
+ None = 0
+ }
+}
+//$$ AttributeWithEnumArgument
+namespace AttributeWithEnumArgument
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+}
+//$$ AttributeWithEnumExpressionArgument
+namespace AttributeWithEnumExpressionArgument
+{
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Interface)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+}
+//$$ AttributeWithStringExpressionArgument
+namespace AttributeWithStringExpressionArgument
+{
+ [Obsolete("message")]
+ public class ObsoletedClass
+ {
+ }
+}
+//$$ AttributeWithTypeArgument
+namespace AttributeWithTypeArgument
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyTypeAttribute : Attribute
+ {
+ public MyTypeAttribute(Type t)
+ {
+ }
+ }
+
+ [MyType(typeof(Attribute))]
+ public class SomeClass
+ {
+ }
+}
+//$$ AppliedToEvent
+namespace AppliedToEvent
+{
+ [AttributeUsage(AttributeTargets.Event)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class TestClass
+ {
+ [MyAttribute]
+ public event EventHandler MyEvent;
+ }
+}
+//$$ AppliedToEventMethods
+namespace AppliedToEventMethods
+{
+ [AttributeUsage(AttributeTargets.Method)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class TestClass
+ {
+ [method: MyAttribute]
+ public event EventHandler MyEvent;
+ }
+}
+//$$ AppliedToField
+namespace AppliedToField
+{
+ [AttributeUsage(AttributeTargets.Field)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class TestClass
+ {
+ [MyAttribute]
+ public int Field;
+ }
+}
+//$$ AppliedToProperty
+namespace AppliedToProperty
+{
+ public class TestClass
+ {
+ [Obsolete("reason")]
+ public int Property
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ }
+}
+//$$ AppliedToPropertyGet
+namespace AppliedToPropertyGet
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class TestClass
+ {
+ public int Property
+ {
+ [MyAttribute]
+ get
+ {
+ return 0;
+ }
+ }
+ }
+}
+//$$ AppliedToPropertySet
+namespace AppliedToPropertySet
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class TestClass
+ {
+ public int Property
+ {
+ get
+ {
+ return 3;
+ }
+ [MyAttribute]
+ set
+ {
+ }
+ }
+ }
+}
+//$$ AppliedToIndexer
+namespace AppliedToIndexer
+{
+ public class TestClass
+ {
+ [Obsolete("reason")]
+ public int this[int i]
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ }
+}
+//$$ AppliedToDelegate
+[Obsolete("reason")]
+public delegate int AppliedToDelegate();
+//$$ AppliedToMethod
+namespace AppliedToMethod
+{
+ [AttributeUsage(AttributeTargets.Method)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class TestClass
+ {
+ [MyAttribute]
+ public void Method()
+ {
+ }
+ }
+}
+//$$ AppliedToInterface
+[Obsolete("reason")]
+public interface AppliedToInterface
+{
+}
+//$$ AppliedToStruct
+[Obsolete("reason")]
+public struct AppliedToStruct
+{
+ public int Field;
+}
+//$$ AppliedToParameter
+namespace AppliedToParameter
+{
+ [AttributeUsage(AttributeTargets.Parameter)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public void Method([MyAttribute] int val)
+ {
+ }
+ }
+}
+//$$ NamedInitializerProperty
+namespace NamedInitializerProperty
+{
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+}
+//$$ NamedInitializerPropertyString
+namespace NamedInitializerPropertyString
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ public string Prop
+ {
+ get
+ {
+ return "";
+ }
+ set
+ {
+ }
+ }
+ }
+ [MyAttribute(Prop = "value")]
+ public class MyClass
+ {
+ }
+}
+//$$ NamedInitializerPropertyType
+namespace NamedInitializerPropertyType
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ public Type Prop
+ {
+ get
+ {
+ return null;
+ }
+ set
+ {
+ }
+ }
+ }
+ [MyAttribute(Prop = typeof(Enum))]
+ public class MyClass
+ {
+ }
+}
+//$$ NamedInitializerPropertyEnum
+namespace NamedInitializerPropertyEnum
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ public AttributeTargets Prop
+ {
+ get
+ {
+ return AttributeTargets.All;
+ }
+ set
+ {
+ }
+ }
+ }
+ [MyAttribute(Prop = (AttributeTargets.Class | AttributeTargets.Method))]
+ public class MyClass
+ {
+ }
+}
+//$$ NamedInitializerFieldEnum
+namespace NamedInitializerFieldEnum
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ public AttributeTargets Field;
+ }
+ [MyAttribute(Field = (AttributeTargets.Class | AttributeTargets.Method))]
+ public class MyClass
+ {
+ }
+}
+//$$ TargetReturn
+namespace TargetReturn
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ [return: MyAttribute]
+ public int MyMethod()
+ {
+ return 5;
+ }
+ }
+}
+//$$ TargetPropertyGetReturn
+namespace TargetPropertyGetReturn
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public int Prop
+ {
+ [return: MyAttribute]
+ get
+ {
+ return 3;
+ }
+ }
+ }
+}
+//$$ TargetPropertySetParam
+namespace TargetPropertySetParam
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public int Prop
+ {
+ [param: MyAttribute]
+ set
+ {
+ }
+ }
+ }
+}
+//$$ TargetPropertySetReturn
+namespace TargetPropertySetReturn
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public int Prop
+ {
+ get
+ {
+ return 3;
+ }
+ [return: MyAttribute]
+ set
+ {
+ }
+ }
+ }
+}
+//$$ TargetPropertyIndexGetReturn
+namespace TargetPropertyIndexGetReturn
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public int this[string s]
+ {
+ [return: MyAttribute]
+ get
+ {
+ return 3;
+ }
+ }
+ }
+}
+//$$ TargetPropertyIndexParamOnlySet
+namespace TargetPropertyIndexParamOnlySet
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public int this[[MyAttribute] string s]
+ {
+ set
+ {
+ }
+ }
+ }
+}
+//$$ TargetPropertyIndexParamOnlyGet
+namespace TargetPropertyIndexParamOnlyGet
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public int this[[MyAttribute] string s]
+ {
+ get
+ {
+ return 3;
+ }
+ }
+ }
+}
+//$$ TargetPropertyIndexSetReturn
+namespace TargetPropertyIndexSetReturn
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass
+ {
+ public string this[int index]
+ {
+ get
+ {
+ return "";
+ }
+ [return: MyAttribute]
+ set
+ {
+ }
+ }
+ }
+}
+//$$ TargetPropertyIndexSetMultiParam
+namespace TargetPropertyIndexSetMultiParam
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ public int Field;
+ }
+ public class MyClass
+ {
+ public string this[[MyAttribute(Field = 2)] int index1, [MyAttribute(Field = 3)] int index2]
+ {
+ get
+ {
+ return "";
+ }
+ [param: MyAttribute]
+ set
+ {
+ }
+ }
+ }
+}
+//$$ ClassAttributeOnTypeParameter
+namespace ClassAttributeOnTypeParameter
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ public class MyClass<[MyAttribute] T>
+ {
+ }
+}
+//$$ AttributeOnReturnTypeOfDelegate
+namespace AttributeOnReturnTypeOfDelegate
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttributeAttribute : Attribute
+ {
+ }
+ [return: MyAttribute]
+ public delegate void Test();
+}
diff --git a/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs
new file mode 100644
index 00000000..37c1c0d7
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs
@@ -0,0 +1,79 @@
+// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+namespace aa
+{
+ public static class CustomAttributes
+ {
+ [Flags]
+ public enum EnumWithFlag
+ {
+ All = 15,
+ None = 0,
+ Item1 = 1,
+ Item2 = 2,
+ Item3 = 4,
+ Item4 = 8
+ }
+ [AttributeUsage(AttributeTargets.All)]
+ public class MyAttribute : Attribute
+ {
+ public MyAttribute(object val)
+ {
+ }
+ }
+ [CustomAttributes.MyAttribute(CustomAttributes.EnumWithFlag.Item1 | CustomAttributes.EnumWithFlag.Item2)]
+ private static int field;
+ [CustomAttributes.MyAttribute(CustomAttributes.EnumWithFlag.All)]
+ public static string Property
+ {
+ get
+ {
+ return "aa";
+ }
+ }
+ [Obsolete("some message")]
+ public static void ObsoletedMethod()
+ {
+ //Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, (AttributeTargets)(AttributeTargets.Property | AttributeTargets.Field));
+ Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, AttributeTargets.Property | AttributeTargets.Field);
+ AttributeTargets attributeTargets = AttributeTargets.Property | AttributeTargets.Field;
+ Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, attributeTargets);
+ }
+ // No Boxing
+ [CustomAttributes.MyAttribute(new StringComparison[]
+ {
+ StringComparison.Ordinal,
+ StringComparison.CurrentCulture
+ })]
+ public static void ArrayAsAttribute1()
+ {
+ }
+ // Boxing of each array element
+ [CustomAttributes.MyAttribute(new object[]
+ {
+ StringComparison.Ordinal,
+ StringComparison.CurrentCulture
+ })]
+ public static void ArrayAsAttribute2()
+ {
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs b/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs
new file mode 100644
index 00000000..5bd0ec51
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs
@@ -0,0 +1,88 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public static class CustomShortCircuitOperators
+{
+ // TODO: Restore base class after https://roslyn.codeplex.com/workitem/358 is fixed.
+ private class C
+ {
+ public static bool operator true(CustomShortCircuitOperators.C x)
+ {
+ return true;
+ }
+
+ public static bool operator false(CustomShortCircuitOperators.C x)
+ {
+ return false;
+ }
+
+ public static CustomShortCircuitOperators.C operator &(CustomShortCircuitOperators.C x, CustomShortCircuitOperators.C y)
+ {
+ return null;
+ }
+
+ public static CustomShortCircuitOperators.C operator |(CustomShortCircuitOperators.C x, CustomShortCircuitOperators.C y)
+ {
+ return null;
+ }
+
+ public static bool operator !(CustomShortCircuitOperators.C x)
+ {
+ return false;
+ }
+
+ private static void Main()
+ {
+ CustomShortCircuitOperators.C c = new CustomShortCircuitOperators.C();
+ CustomShortCircuitOperators.C c2 = new CustomShortCircuitOperators.C();
+ CustomShortCircuitOperators.C c3 = c && c2;
+ CustomShortCircuitOperators.C c4 = c || c2;
+ Console.WriteLine(c3.ToString());
+ Console.WriteLine(c4.ToString());
+ }
+
+ private static void Test2()
+ {
+ CustomShortCircuitOperators.C c = new CustomShortCircuitOperators.C();
+ if (c && c)
+ {
+ Console.WriteLine(c.ToString());
+ }
+
+ if (!(c && c))
+ {
+ Console.WriteLine(c.ToString());
+ }
+ }
+
+ private static void Test3()
+ {
+ CustomShortCircuitOperators.C c = new CustomShortCircuitOperators.C();
+ if (c)
+ {
+ Console.WriteLine(c.ToString());
+ }
+ if (!c)
+ {
+ Console.WriteLine(c.ToString());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs b/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs
new file mode 100644
index 00000000..659bb2be
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs
@@ -0,0 +1,89 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.CodeDom.Compiler;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+using ICSharpCode.Decompiler.Ast;
+using ICSharpCode.Decompiler.Tests.Helpers;
+using Microsoft.CSharp;
+using Mono.Cecil;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests
+{
+ public abstract class DecompilerTestBase
+ {
+ protected static void ValidateFileRoundtrip(string samplesFileName)
+ {
+ var fullPath = Path.Combine(@"..\..\Tests", samplesFileName);
+ AssertRoundtripCode(fullPath);
+ }
+
+ static string RemoveIgnorableLines(IEnumerable<string> lines)
+ {
+ return CodeSampleFileParser.ConcatLines(lines.Where(l => !CodeSampleFileParser.IsCommentOrBlank(l)));
+ }
+
+ protected static void AssertRoundtripCode(string fileName, bool optimize = false, bool useDebug = false, int compilerVersion = 4)
+ {
+ var code = RemoveIgnorableLines(File.ReadLines(fileName));
+ AssemblyDefinition assembly = CompileLegacy(code, optimize, useDebug, compilerVersion);
+
+ AstBuilder decompiler = new AstBuilder(new DecompilerContext(assembly.MainModule));
+ decompiler.AddAssembly(assembly);
+ new Helpers.RemoveCompilerAttribute().Run(decompiler.SyntaxTree);
+
+ StringWriter output = new StringWriter();
+ decompiler.GenerateCode(new PlainTextOutput(output));
+ CodeAssert.AreEqual(code, output.ToString());
+ }
+
+ protected static AssemblyDefinition CompileLegacy(string code, bool optimize, bool useDebug, int compilerVersion)
+ {
+ CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v" + new Version(compilerVersion, 0) } });
+ CompilerParameters options = new CompilerParameters();
+ options.CompilerOptions = "/unsafe /o" + (optimize ? "+" : "-") + (useDebug ? " /debug" : "");
+ if (compilerVersion >= 4)
+ options.ReferencedAssemblies.Add("System.Core.dll");
+ CompilerResults results = provider.CompileAssemblyFromSource(options, code);
+ try
+ {
+ if (results.Errors.Count > 0)
+ {
+ StringBuilder b = new StringBuilder("Compiler error:");
+ foreach (var error in results.Errors)
+ {
+ b.AppendLine(error.ToString());
+ }
+ throw new Exception(b.ToString());
+ }
+ return AssemblyDefinition.ReadAssembly(results.PathToAssembly);
+ }
+ finally
+ {
+ File.Delete(results.PathToAssembly);
+ results.TempFiles.Delete();
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs b/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs
new file mode 100644
index 00000000..70c00fc6
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs
@@ -0,0 +1,205 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+public static class DelegateConstruction
+{
+ class InstanceTests
+ {
+ public Action CaptureOfThis()
+ {
+ return delegate {
+ CaptureOfThis();
+ };
+ }
+
+ public Action CaptureOfThisAndParameter(int a)
+ {
+ return delegate {
+ CaptureOfThisAndParameter(a);
+ };
+ }
+
+ public Action CaptureOfThisAndParameterInForEach(int a)
+ {
+ foreach (int item in Enumerable.Empty<int>()) {
+ if (item > 0) {
+ return delegate {
+ CaptureOfThisAndParameter(item + a);
+ };
+ }
+ }
+ return null;
+ }
+
+ public Action CaptureOfThisAndParameterInForEachWithItemCopy(int a)
+ {
+ foreach (int item in Enumerable.Empty<int>()) {
+ int copyOfItem = item;
+ if (item > 0) {
+ return delegate {
+ CaptureOfThisAndParameter(item + a + copyOfItem);
+ };
+ }
+ }
+ return null;
+ }
+
+ public void LambdaInForLoop()
+ {
+ for (int i = 0; i < 100000; i++) {
+ Bar(() => Foo());
+ }
+ }
+
+ public int Foo()
+ {
+ return 0;
+ }
+
+ public void Bar(Func<int> f)
+ {
+ }
+ }
+
+ public static void Test(this string a)
+ {
+ }
+
+ public static Action<string> ExtensionMethodUnbound()
+ {
+ return new Action<string>(DelegateConstruction.Test);
+ }
+
+ public static Action ExtensionMethodBound()
+ {
+ return new Action("abc".Test);
+ }
+
+ public static Action ExtensionMethodBoundOnNull()
+ {
+ return new Action(((string)null).Test);
+ }
+
+ public static object StaticMethod()
+ {
+ return new Func<Action>(DelegateConstruction.ExtensionMethodBound);
+ }
+
+ public static object InstanceMethod()
+ {
+ return new Func<string>("hello".ToUpper);
+ }
+
+ public static object InstanceMethodOnNull()
+ {
+ return new Func<string>(((string)null).ToUpper);
+ }
+
+ public static List<Action<int>> AnonymousMethodStoreWithinLoop()
+ {
+ List<Action<int>> list = new List<Action<int>>();
+ for (int i = 0; i < 10; i++)
+ {
+ int counter;
+ list.Add(delegate(int x)
+ {
+ counter = x;
+ }
+ );
+ }
+ return list;
+ }
+
+ public static List<Action<int>> AnonymousMethodStoreOutsideLoop()
+ {
+ List<Action<int>> list = new List<Action<int>>();
+ int counter;
+ for (int i = 0; i < 10; i++)
+ {
+ list.Add(delegate(int x)
+ {
+ counter = x;
+ }
+ );
+ }
+ return list;
+ }
+
+ public static Action StaticAnonymousMethodNoClosure()
+ {
+ return delegate
+ {
+ Console.WriteLine();
+ };
+ }
+
+ public static void NameConflict()
+ {
+ // i is captured variable,
+ // j is parameter in anonymous method
+ // k is local in anonymous method,
+ // l is local in main method
+ // Ensure that the decompiler doesn't introduce name conflicts
+ List<Action<int>> list = new List<Action<int>>();
+ for (int l = 0; l < 10; l++) {
+ int i;
+ for (i = 0; i < 10; i++) {
+ list.Add(
+ delegate (int j) {
+ for (int k = 0; k < i; k += j) {
+ Console.WriteLine();
+ }
+ });
+ }
+ }
+ }
+
+ public static void NameConflict2(int j)
+ {
+ List<Action<int>> list = new List<Action<int>>();
+ for (int k = 0; k < 10; k++) {
+ list.Add(
+ delegate(int i) {
+ Console.WriteLine(i);
+ });
+ }
+ }
+
+ public static Action<int> NameConflict3(int i)
+ {
+ return delegate(int j) {
+ for (int k = 0; k < j; k++) {
+ Console.WriteLine(k);
+ }
+ };
+ }
+
+ public static Func<int, Func<int, int>> CurriedAddition(int a)
+ {
+ return b => c => a + b + c;
+ }
+
+ public static Func<int, Func<int, Func<int, int>>> CurriedAddition2(int a)
+ {
+ return b => c => d => a + b + c + d;
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/DoubleConstants.cs b/ICSharpCode.Decompiler/Tests/DoubleConstants.cs
new file mode 100644
index 00000000..2bc20a77
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/DoubleConstants.cs
@@ -0,0 +1,28 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class DoubleConstants
+{
+ public const double Zero = 0.0;
+ public const double MinusZero = -0.0;
+ public const double NaN = double.NaN;
+ public const double PositiveInfinity = double.PositiveInfinity;
+ public const double NegativeInfinity = double.NegativeInfinity;
+}
diff --git a/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs b/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs
new file mode 100644
index 00000000..0db35e35
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs
@@ -0,0 +1,128 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Threading;
+
+public class ExceptionHandling
+{
+ public void MethodEndingWithEndFinally()
+ {
+ try
+ {
+ throw null;
+ }
+ finally
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public void MethodEndingWithRethrow()
+ {
+ try
+ {
+ throw null;
+ }
+ catch
+ {
+ throw;
+ }
+ }
+
+ public void TryCatchFinally()
+ {
+ try
+ {
+ Console.WriteLine("Try");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ finally
+ {
+ Console.WriteLine("Finally");
+ }
+ }
+
+ public void TryCatchMultipleHandlers()
+ {
+ try
+ {
+ Console.WriteLine("Try");
+ }
+ catch (InvalidOperationException ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ catch (Exception ex2)
+ {
+ Console.WriteLine(ex2.Message);
+ }
+ catch
+ {
+ Console.WriteLine("other");
+ }
+ }
+
+ public void NoUsingStatementBecauseTheVariableIsAssignedTo()
+ {
+ CancellationTokenSource cancellationTokenSource = null;
+ try
+ {
+ cancellationTokenSource = new CancellationTokenSource();
+ }
+ finally
+ {
+ if (cancellationTokenSource != null)
+ {
+ cancellationTokenSource.Dispose();
+ }
+ }
+ }
+
+ public void UsingStatementThatChangesTheVariable()
+ {
+ CancellationTokenSource cancellationTokenSource = null;
+ using (cancellationTokenSource)
+ {
+ cancellationTokenSource = new CancellationTokenSource();
+ }
+ }
+
+ public void TwoCatchBlocksWithSameVariable()
+ {
+ try
+ {
+ Console.WriteLine("Try1");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ try
+ {
+ Console.WriteLine("Try2");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/ExpressionTrees.cs b/ICSharpCode.Decompiler/Tests/ExpressionTrees.cs
new file mode 100644
index 00000000..9d325e9e
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/ExpressionTrees.cs
@@ -0,0 +1,370 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Xml;
+
+public class ExpressionTrees
+{
+ class GenericClass<X>
+ {
+ public static X StaticField;
+ public X InstanceField;
+ public static X StaticProperty { get; set; }
+ public X InstanceProperty { get; set; }
+
+ public static bool GenericMethod<Y>()
+ {
+ return false;
+ }
+ }
+
+ int field;
+
+ static object ToCode<R>(object x, Expression<Func<R>> expr)
+ {
+ return expr;
+ }
+
+ static object ToCode<T, R>(object x, Expression<Func<T, R>> expr)
+ {
+ return expr;
+ }
+
+ static object X()
+ {
+ return null;
+ }
+
+ public void Parameter(bool a)
+ {
+ ToCode(X(), () => a);
+ }
+
+ public void LocalVariable()
+ {
+ bool a = true;
+ ToCode(X(), () => a);
+ }
+
+ public void LambdaParameter()
+ {
+ ToCode(X(), (bool a) => a);
+ }
+
+ public void AddOperator(int x)
+ {
+ ToCode(X(), () => 1 + x + 2);
+ }
+
+ public void AnonymousClasses()
+ {
+ ToCode(X(), () => new { X = 3, A = "a" });
+ }
+
+ public void ArrayIndex()
+ {
+ ToCode(X(), () => new[] { 3, 4, 5 }[0 + (int)(DateTime.Now.Ticks % 3)]);
+ }
+
+ public void ArrayLengthAndDoubles()
+ {
+ ToCode(X(), () => new[] { 1.0, 2.01, 3.5 }.Concat(new[] { 1.0, 2.0 }).ToArray().Length);
+ }
+
+ public void AsOperator()
+ {
+ ToCode(X(), () => new object() as string);
+ }
+
+ public void ComplexGenericName()
+ {
+ ToCode(X(), () => ((Func<int, bool>)(x => x > 0))(0));
+ }
+
+ public void DefaultValue()
+ {
+ ToCode(X(), () => new TimeSpan(1, 2, 3) == default(TimeSpan));
+ }
+
+ public void EnumConstant()
+ {
+ ToCode(X(), () => new object().Equals(MidpointRounding.ToEven));
+ }
+
+ public void IndexerAccess()
+ {
+ var dict = Enumerable.Range(1, 20).ToDictionary(n => n.ToString());
+ ToCode(X(), () => dict["3"] == 3);
+ }
+
+ public void IsOperator()
+ {
+ ToCode(X(), () => new object() is string);
+ }
+
+ public void ListInitializer()
+ {
+ ToCode(X(), () => new Dictionary<int, int> { { 1, 1 }, { 2, 2 }, { 3, 4 } }.Count == 3);
+ }
+
+ public void ListInitializer2()
+ {
+ ToCode(X(), () => new List<int>(50) { 1, 2, 3 }.Count == 3);
+ }
+
+ public void ListInitializer3()
+ {
+ ToCode(X(), () => new List<int> { 1, 2, 3 }.Count == 3);
+ }
+
+ public void LiteralCharAndProperty()
+ {
+ ToCode(X(), () => new string(' ', 3).Length == 1);
+ }
+
+ public void CharNoCast()
+ {
+ ToCode(X(), () => "abc"[1] == 'b');
+ }
+
+ public void StringsImplicitCast()
+ {
+ int i = 1;
+ string x = "X";
+ ToCode(X(), () => (("a\n\\b" ?? x) + x).Length == 2 ? false : true && (1m + -i > 0 || false));
+ }
+
+ public void NotImplicitCast()
+ {
+ byte z = 42;
+ ToCode(X(), () => ~z == 0);
+ }
+
+ public void MembersBuiltin()
+ {
+ ToCode(X(), () => 1.23m.ToString());
+ ToCode(X(), () => AttributeTargets.All.HasFlag((Enum)AttributeTargets.Assembly));
+ ToCode(X(), () => "abc".Length == 3);
+ ToCode(X(), () => 'a'.CompareTo('b') < 0);
+ }
+
+ public void MembersDefault()
+ {
+ ToCode(X(), () => default(DateTime).Ticks == 0);
+ ToCode(X(), () => default(int[]).Length == 0);
+ ToCode(X(), () => default(Type).IsLayoutSequential);
+ ToCode(X(), () => default(List<int>).Count);
+ ToCode(X(), () => default(int[]).Clone() == null);
+ ToCode(X(), () => default(Type).IsInstanceOfType(new object()));
+ ToCode(X(), () => default(List<int>).AsReadOnly());
+ }
+
+ public void DoAssert()
+ {
+ field = 37;
+ ToCode(X(), () => field != C());
+ ToCode(X(), () => !ReferenceEquals(this, new ExpressionTrees()));
+ ToCode(X(), () => MyEquals(this) && !MyEquals(default(ExpressionTrees)));
+ }
+
+ int C()
+ {
+ return field + 5;
+ }
+
+ bool MyEquals(ExpressionTrees other)
+ {
+ return other != null && field == other.field;
+ }
+
+ public void MethodGroupAsExtensionMethod()
+ {
+ ToCode(X(), () => (Func<bool>)new[] { 2000, 2004, 2008, 2012 }.Any);
+ }
+
+ public void MethodGroupConstant()
+ {
+ ToCode(X(), () => Array.TrueForAll(new[] { 2000, 2004, 2008, 2012 }, DateTime.IsLeapYear));
+
+ HashSet<int> set = new HashSet<int>();
+ ToCode(X(), () => new[] { 2000, 2004, 2008, 2012 }.All(set.Add));
+
+ Func<Func<object, object, bool>, bool> sink = f => f(null, null);
+ ToCode(X(), () => sink(int.Equals));
+ }
+
+ public void MultipleCasts()
+ {
+ ToCode(X(), () => 1 == (int)(object)1);
+ }
+
+ public void MultipleDots()
+ {
+ ToCode(X(), () => 3.ToString().ToString().Length > 0);
+ }
+
+ public void NestedLambda()
+ {
+ Func<Func<int>, int> call = f => f();
+ //no params
+ ToCode(X(), () => call(() => 42));
+ //one param
+ ToCode(X(), () => new[] { 37, 42 }.Select(x => x * 2));
+ //two params
+ ToCode(X(), () => new[] { 37, 42 }.Select((x, i) => x * 2));
+ }
+
+ public void CurriedLambda()
+ {
+ ToCode<int, Func<int, Func<int, int>>>(X(), a => b => c => a + b + c);
+ }
+
+ bool Fizz(Func<int, bool> a)
+ {
+ return a(42);
+ }
+
+ bool Buzz(Func<int, bool> a)
+ {
+ return a(42);
+ }
+
+ bool Fizz(Func<string, bool> a)
+ {
+ return a("42");
+ }
+
+ public void NestedLambda2()
+ {
+ ToCode(X(), () => Fizz(x => x == "a"));
+ ToCode(X(), () => Fizz(x => x == 37));
+
+ ToCode(X(), () => Fizz((int x) => true));
+ ToCode(X(), () => Buzz(x => true));
+ }
+
+ public void NewArrayAndExtensionMethod()
+ {
+ ToCode(X(), () => new[] { 1.0, 2.01, 3.5 }.SequenceEqual(new[] { 1.0, 2.01, 3.5 }));
+ }
+
+ public void NewMultiDimArray()
+ {
+ ToCode(X(), () => new int[3, 4].Length == 1);
+ }
+
+ public void NewObject()
+ {
+ ToCode(X(), () => new object() != new object());
+ }
+
+ public void NotOperator()
+ {
+ bool x = true;
+ int y = 3;
+ byte z = 42;
+ ToCode(X(), () => ~(int)z == 0);
+ ToCode(X(), () => ~y == 0);
+ ToCode(X(), () => !x);
+ }
+
+ public void ObjectInitializers()
+ {
+ XmlReaderSettings s = new XmlReaderSettings {
+ CloseInput = false,
+ CheckCharacters = false
+ };
+ ToCode(X(), () => new XmlReaderSettings { CloseInput = s.CloseInput, CheckCharacters = s.CheckCharacters }.Equals(s));
+ }
+
+ public void Quoted()
+ {
+ ToCode(X(), () => (Expression<Func<int, string, string>>)((n, s) => s + n.ToString()) != null);
+ }
+
+ public void Quoted2()
+ {
+ ToCode(X(), () => ToCode(X(), () => true).Equals(null));
+ }
+
+ public void QuotedWithAnonymous()
+ {
+ ToCode(X(), () => new[] { new { X = "a", Y = "b" } }.Select(o => o.X + o.Y).Single());
+ }
+
+ public void StaticCall()
+ {
+ ToCode(X(), () => Equals(3, 0));
+ }
+
+ public void ThisCall()
+ {
+ ToCode(X(), () => !Equals(3));
+ }
+
+ public void ThisExplicit()
+ {
+ ToCode(X(), () => object.Equals(this, 3));
+ }
+
+ public void TypedConstant()
+ {
+ ToCode(X(), () => new[] { typeof(int), typeof(string) });
+ }
+
+ public void StaticCallImplicitCast()
+ {
+ ToCode(X(), () => Equals(3, 0));
+ }
+
+ public void StaticMembers()
+ {
+ ToCode(X(), () => (DateTime.Now > DateTime.Now + TimeSpan.FromMilliseconds(10.001)).ToString() == "False");
+ }
+
+ public void Strings()
+ {
+ int i = 1;
+ string x = "X";
+ ToCode(X(), () => (("a\n\\b" ?? x) + x).Length == 2 ? false : true && (1m + (decimal)-i > 0m || false));
+ }
+
+ public void StringAccessor()
+ {
+ ToCode(X(), () => (int)"abc"[1] == 98);
+ }
+
+ public void GenericClassInstance()
+ {
+ ToCode(X(), () => new GenericClass<int>().InstanceField + new GenericClass<double>().InstanceProperty);
+ }
+
+ public void GenericClassStatic()
+ {
+ ToCode(X(), () => GenericClass<int>.StaticField + GenericClass<double>.StaticProperty);
+ }
+
+ public void InvokeGenericMethod()
+ {
+ ToCode(X(), () => GenericClass<int>.GenericMethod<double>());
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Generics.cs b/ICSharpCode.Decompiler/Tests/Generics.cs
new file mode 100644
index 00000000..9776d42f
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Generics.cs
@@ -0,0 +1,165 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+
+public static class Generics
+{
+ public class MyArray<T>
+ {
+ public class NestedClass<Y>
+ {
+ public T Item1;
+ public Y Item2;
+ }
+
+ public enum NestedEnum
+ {
+ A,
+ B
+ }
+
+ private T[] arr;
+
+ public MyArray(int capacity)
+ {
+ this.arr = new T[capacity];
+ }
+
+ public void Size(int capacity)
+ {
+ Array.Resize<T>(ref this.arr, capacity);
+ }
+
+ public void Grow(int capacity)
+ {
+ if (capacity >= this.arr.Length)
+ {
+ this.Size(capacity);
+ }
+ }
+ }
+
+ public interface IInterface
+ {
+ void Method1<T>() where T : class;
+ void Method2<T>() where T : class;
+ }
+
+ public abstract class Base : Generics.IInterface
+ {
+ // constraints must be repeated on implicit interface implementation
+ public abstract void Method1<T>() where T : class;
+
+ // constraints must not be specified on explicit interface implementation
+ void Generics.IInterface.Method2<T>()
+ {
+ }
+ }
+
+ public class Derived : Generics.Base
+ {
+ // constraints are inherited automatically and must not be specified
+ public override void Method1<T>()
+ {
+ }
+ }
+
+ private const Generics.MyArray<string>.NestedEnum enumVal = Generics.MyArray<string>.NestedEnum.A;
+ private static Type type1 = typeof(List<>);
+ private static Type type2 = typeof(Generics.MyArray<>);
+ private static Type type3 = typeof(List<>.Enumerator);
+ private static Type type4 = typeof(Generics.MyArray<>.NestedClass<>);
+ private static Type type5 = typeof(List<int>[]);
+ private static Type type6 = typeof(Generics.MyArray<>.NestedEnum);
+
+ public static void MethodWithConstraint<T, S>() where T : class, S where S : ICloneable, new()
+ {
+ }
+
+ public static void MethodWithStructConstraint<T>() where T : struct
+ {
+ }
+
+ private static void MultidimensionalArray<T>(T[,] array)
+ {
+ array[0, 0] = array[0, 1];
+ }
+
+ public static Dictionary<string, string>.KeyCollection.Enumerator GetEnumerator(Dictionary<string, string> d, Generics.MyArray<string>.NestedClass<int> nc)
+ {
+ // Tests references to inner classes in generic classes
+ return d.Keys.GetEnumerator();
+ }
+
+ public static bool IsString<T>(T input)
+ {
+ return input is string;
+ }
+
+ public static string AsString<T>(T input)
+ {
+ return input as string;
+ }
+
+ public static string CastToString<T>(T input)
+ {
+ return (string)((object)input);
+ }
+
+ public static T CastFromString<T>(string input)
+ {
+ return (T)((object)input);
+ }
+
+ public static bool IsInt<T>(T input)
+ {
+ return input is int;
+ }
+
+ public static int CastToInt<T>(T input)
+ {
+ return (int)((object)input);
+ }
+
+ public static T CastFromInt<T>(int input)
+ {
+ return (T)((object)input);
+ }
+
+ public static bool IsNullableInt<T>(T input)
+ {
+ return input is int?;
+ }
+
+ public static int? AsNullableInt<T>(T input)
+ {
+ return input as int?;
+ }
+
+ public static int? CastToNullableInt<T>(T input)
+ {
+ return (int?)((object)input);
+ }
+
+ public static T CastFromNullableInt<T>(int? input)
+ {
+ return (T)((object)input);
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs b/ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs
new file mode 100644
index 00000000..d06e2db2
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using DiffLib;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests.Helpers
+{
+ public class CodeAssert
+ {
+ public static void AreEqual(string input1, string input2)
+ {
+ var diff = new StringWriter();
+ if (!Compare(input1, input2, diff)) {
+ Assert.Fail(diff.ToString());
+ }
+ }
+
+ static bool Compare(string input1, string input2, StringWriter diff)
+ {
+ var differ = new AlignedDiff<string>(
+ NormalizeAndSplitCode(input1),
+ NormalizeAndSplitCode(input2),
+ new CodeLineEqualityComparer(),
+ new StringSimilarityComparer(),
+ new StringAlignmentFilter());
+
+ bool result = true, ignoreChange;
+
+ int line1 = 0, line2 = 0;
+
+ foreach (var change in differ.Generate()) {
+ switch (change.Change) {
+ case ChangeType.Same:
+ diff.Write("{0,4} {1,4} ", ++line1, ++line2);
+ diff.Write(" ");
+ diff.WriteLine(change.Element1);
+ break;
+ case ChangeType.Added:
+ diff.Write(" {1,4} ", line1, ++line2);
+ result &= ignoreChange = ShouldIgnoreChange(change.Element2);
+ diff.Write(ignoreChange ? " " : " + ");
+ diff.WriteLine(change.Element2);
+ break;
+ case ChangeType.Deleted:
+ diff.Write("{0,4} ", ++line1, line2);
+ result &= ignoreChange = ShouldIgnoreChange(change.Element1);
+ diff.Write(ignoreChange ? " " : " - ");
+ diff.WriteLine(change.Element1);
+ break;
+ case ChangeType.Changed:
+ diff.Write("{0,4} ", ++line1, line2);
+ result = false;
+ diff.Write("(-) ");
+ diff.WriteLine(change.Element1);
+ diff.Write(" {1,4} ", line1, ++line2);
+ diff.Write("(+) ");
+ diff.WriteLine(change.Element2);
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ class CodeLineEqualityComparer : IEqualityComparer<string>
+ {
+ private IEqualityComparer<string> baseComparer = EqualityComparer<string>.Default;
+
+ public bool Equals(string x, string y)
+ {
+ return baseComparer.Equals(
+ NormalizeLine(x),
+ NormalizeLine(y)
+ );
+ }
+
+ public int GetHashCode(string obj)
+ {
+ return baseComparer.GetHashCode(NormalizeLine(obj));
+ }
+ }
+
+ private static string NormalizeLine(string line)
+ {
+ line = line.Trim();
+ var index = line.IndexOf("//");
+ if (index >= 0) {
+ return line.Substring(0, index);
+ } else if (line.StartsWith("#")) {
+ return string.Empty;
+ } else {
+ return line;
+ }
+ }
+
+ private static bool ShouldIgnoreChange(string line)
+ {
+ // for the result, we should ignore blank lines and added comments
+ return NormalizeLine(line) == string.Empty;
+ }
+
+ private static IEnumerable<string> NormalizeAndSplitCode(string input)
+ {
+ return input.Split(new[] { "\r\n", "\n\r", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs b/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs
new file mode 100644
index 00000000..cb656202
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using ICSharpCode.Decompiler.Ast.Transforms;
+using ICSharpCode.NRefactory.CSharp;
+
+namespace ICSharpCode.Decompiler.Tests.Helpers
+{
+ class RemoveCompilerAttribute : DepthFirstAstVisitor<object, object>, IAstTransform
+ {
+ public override object VisitAttribute(NRefactory.CSharp.Attribute attribute, object data)
+ {
+ var section = (AttributeSection)attribute.Parent;
+ SimpleType type = attribute.Type as SimpleType;
+ if (section.AttributeTarget == "assembly" &&
+ (type.Identifier == "CompilationRelaxations" || type.Identifier == "RuntimeCompatibility" || type.Identifier == "SecurityPermission" || type.Identifier == "AssemblyVersion" || type.Identifier == "Debuggable"))
+ {
+ attribute.Remove();
+ if (section.Attributes.Count == 0)
+ section.Remove();
+ }
+ if (section.AttributeTarget == "module" && type.Identifier == "UnverifiableCode")
+ {
+ attribute.Remove();
+ if (section.Attributes.Count == 0)
+ section.Remove();
+ }
+ return null;
+ }
+
+ public void Run(AstNode node)
+ {
+ node.AcceptVisitor(this, null);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
new file mode 100644
index 00000000..808290a4
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <PropertyGroup>
+ <ProjectGuid>{FEC0DA52-C4A6-4710-BE36-B484A20C5E22}</ProjectGuid>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <OutputType>Library</OutputType>
+ <RootNamespace>ICSharpCode.Decompiler.Tests</RootNamespace>
+ <AssemblyName>ICSharpCode.Decompiler.Tests</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ <NoStdLib>False</NoStdLib>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+ <CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
+ <NoWarn>67,169,1058,728,1720,649</NoWarn>
+ <TargetFrameworkProfile />
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Platform)' == 'x86' ">
+ <PlatformTarget>x86</PlatformTarget>
+ <RegisterForComInterop>False</RegisterForComInterop>
+ <GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
+ <BaseAddress>4194304</BaseAddress>
+ <FileAlignment>4096</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <RegisterForComInterop>False</RegisterForComInterop>
+ <GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
+ <BaseAddress>4194304</BaseAddress>
+ <FileAlignment>4096</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <OutputPath>..\bin\Debug\</OutputPath>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>Full</DebugType>
+ <Optimize>False</Optimize>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
+ <OutputPath>..\bin\Release\</OutputPath>
+ <DebugSymbols>false</DebugSymbols>
+ <DebugType>None</DebugType>
+ <Optimize>True</Optimize>
+ <DefineConstants>TRACE</DefineConstants>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="DiffLib">
+ <HintPath>..\..\packages\DiffLib.1.0.0.55\lib\net35-Client\DiffLib.dll</HintPath>
+ </Reference>
+ <Reference Include="ICSharpCode.NRefactory">
+ <HintPath>..\..\packages\ICSharpCode.NRefactory.5.5.1\lib\Net40\ICSharpCode.NRefactory.dll</HintPath>
+ </Reference>
+ <Reference Include="ICSharpCode.NRefactory.CSharp">
+ <HintPath>..\..\packages\ICSharpCode.NRefactory.5.5.1\lib\Net40\ICSharpCode.NRefactory.CSharp.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.framework">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>.\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Async.cs" />
+ <Compile Include="CallOverloadedMethod.cs" />
+ <Compile Include="CheckedUnchecked.cs" />
+ <Compile Include="ControlFlow.cs" />
+ <Compile Include="DoubleConstants.cs" />
+ <Compile Include="ExpressionTrees.cs" />
+ <None Include="IL\SequenceOfNestedIfs.Output.cs" />
+ <Compile Include="IL\ILTests.cs" />
+ <Compile Include="LiftedOperators.cs" />
+ <Compile Include="CustomShortCircuitOperators.cs" />
+ <Compile Include="Helpers\CodeAssert.cs" />
+ <Compile Include="IncrementDecrement.cs" />
+ <Compile Include="Lock.cs" />
+ <Compile Include="PInvoke.cs" />
+ <Compile Include="QueryExpressions.cs" />
+ <Compile Include="Switch.cs" />
+ <Compile Include="TypeAnalysisTests.cs" />
+ <Compile Include="UndocumentedExpressions.cs" />
+ <Compile Include="UnsafeCode.cs" />
+ <Compile Include="Types\S_TypeDeclarations.cs" />
+ <Compile Include="YieldReturn.cs" />
+ <None Include="IL\SequenceOfNestedIfs.dll" />
+ <None Include="IL\SequenceOfNestedIfs.il" />
+ <None Include="IL\StackTests.exe" />
+ <None Include="IL\StackTests.il" />
+ <None Include="packages.config" />
+ <None Include="Types\S_EnumSamples.cs" />
+ <None Include="CustomAttributes\S_AssemblyCustomAttribute.cs" />
+ <Compile Include="Helpers\RemoveCompilerAttribute.cs" />
+ <Compile Include="Types\S_TypeMemberDeclarations.cs" />
+ <Compile Include="Types\EnumTests.cs" />
+ <Compile Include="Types\TypeTests.cs" />
+ <Compile Include="DelegateConstruction.cs" />
+ <None Include="CustomAttributes\S_CustomAttributes.cs" />
+ <Compile Include="Loops.cs" />
+ <Compile Include="PropertiesAndEvents.cs" />
+ <None Include="CustomAttributes\S_CustomAttributeSamples.cs" />
+ <Compile Include="CodeSampleFileParser.cs" />
+ <Compile Include="CustomAttributes\CustomAttributeTests.cs" />
+ <Compile Include="DecompilerTestBase.cs" />
+ <Compile Include="InitializerTests.cs" />
+ <Compile Include="ExceptionHandling.cs" />
+ <Compile Include="Generics.cs" />
+ <Compile Include="MultidimensionalArray.cs" />
+ <Compile Include="TestRunner.cs" />
+ <Compile Include="ValueTypes.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Mono.Cecil\Mono.Cecil.csproj">
+ <Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
+ <Name>Mono.Cecil</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ICSharpCode.Decompiler.csproj">
+ <Project>{984CC812-9470-4A13-AFF9-CC44068D666C}</Project>
+ <Name>ICSharpCode.Decompiler</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup />
+ <ItemGroup>
+ <None Include="BooleanConsumedAsInteger.il" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
+</Project> \ No newline at end of file
diff --git a/ICSharpCode.Decompiler/Tests/IL/ILTests.cs b/ICSharpCode.Decompiler/Tests/IL/ILTests.cs
new file mode 100644
index 00000000..f06f3108
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/IL/ILTests.cs
@@ -0,0 +1,51 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.IO;
+using ICSharpCode.Decompiler.Ast;
+using ICSharpCode.Decompiler.Tests.Helpers;
+using Mono.Cecil;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests
+{
+ [TestFixture]
+ public class ILTests
+ {
+ const string path = "../../Tests/IL";
+
+ [Test]
+ public void SequenceOfNestedIfs()
+ {
+ Run("SequenceOfNestedIfs.dll", "SequenceOfNestedIfs.Output.cs");
+ }
+
+ void Run(string compiledFile, string expectedOutputFile)
+ {
+ string expectedOutput = File.ReadAllText(Path.Combine(path, expectedOutputFile));
+ var assembly = AssemblyDefinition.ReadAssembly(Path.Combine(path, compiledFile));
+ AstBuilder decompiler = new AstBuilder(new DecompilerContext(assembly.MainModule));
+ decompiler.AddAssembly(assembly);
+ new Helpers.RemoveCompilerAttribute().Run(decompiler.SyntaxTree);
+ StringWriter output = new StringWriter();
+ decompiler.GenerateCode(new PlainTextOutput(output));
+ CodeAssert.AreEqual(expectedOutput, output.ToString());
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.Output.cs b/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.Output.cs
new file mode 100644
index 00000000..754d7daf
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.Output.cs
@@ -0,0 +1,53 @@
+using System;
+[Serializable]
+public class Material
+{
+ public static implicit operator bool(Material m)
+ {
+ return m == null;
+ }
+}
+[Serializable]
+public class SequenceOfNestedIfs
+{
+ public bool _clear;
+ public Material _material;
+ public override bool CheckShader()
+ {
+ return false;
+ }
+ public override void CreateMaterials()
+ {
+ if (!this._clear)
+ {
+ if (!this.CheckShader())
+ {
+ return;
+ }
+ this._material = new Material();
+ }
+ if (!this._material)
+ {
+ if (!this.CheckShader())
+ {
+ return;
+ }
+ this._material = new Material();
+ }
+ if (!this._material)
+ {
+ if (!this.CheckShader())
+ {
+ return;
+ }
+ this._material = new Material();
+ }
+ if (!this._material)
+ {
+ if (this.CheckShader())
+ {
+ this._material = new Material();
+ }
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.il b/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.il
new file mode 100644
index 00000000..9c9b749c
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.il
@@ -0,0 +1,140 @@
+// Metadata version: v2.0.50727
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 2:0:0:0
+}
+
+.assembly SequenceOfNestedIfs
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
+ 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module SequenceOfNestedIfs
+// MVID: {DCEC8A87-5679-4EBE-89A3-51274D8B5446}
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000001 // ILONLY
+// Image base: 0x01D60000
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class public auto ansi serializable beforefieldinit Material
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method Material::.ctor
+
+ .method public hidebysig specialname static
+ bool op_Implicit(class Material m) cil managed
+ {
+ // Code size 11 (0xb)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldnull
+ IL_0008: ceq
+ IL_000a: ret
+ } // end of method Material::op_Implicit
+
+} // end of class Material
+
+.class public auto ansi serializable beforefieldinit SequenceOfNestedIfs
+ extends [mscorlib]System.Object
+{
+ .field public bool _clear
+ .field public class Material _material
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method SequenceOfNestedIfs::.ctor
+
+ .method public hidebysig virtual instance bool
+ CheckShader() cil managed
+ {
+ // Code size 2 (0x2)
+ .maxstack 8
+ IL_0000: ldc.i4.0
+ IL_0001: ret
+ } // end of method SequenceOfNestedIfs::CheckShader
+
+ .method public hidebysig virtual instance void
+ CreateMaterials() cil managed
+ {
+ // Code size 168 (0xa8)
+ .maxstack 13
+ IL_0000: ldarg.0
+ IL_0001: ldfld bool SequenceOfNestedIfs::_clear
+ IL_0006: brtrue IL_0026
+
+ IL_000b: ldarg.0
+ IL_000c: callvirt instance bool SequenceOfNestedIfs::CheckShader()
+ IL_0011: brtrue IL_001b
+
+ IL_0016: br IL_00a7
+
+ IL_001b: ldarg.0
+ IL_001c: newobj instance void Material::.ctor()
+ IL_0021: stfld class Material SequenceOfNestedIfs::_material
+ IL_0026: ldarg.0
+ IL_0027: ldfld class Material SequenceOfNestedIfs::_material
+ IL_002c: call bool Material::op_Implicit(class Material)
+ IL_0031: brtrue IL_0051
+
+ IL_0036: ldarg.0
+ IL_0037: callvirt instance bool SequenceOfNestedIfs::CheckShader()
+ IL_003c: brtrue IL_0046
+
+ IL_0041: br IL_00a7
+
+ IL_0046: ldarg.0
+ IL_0047: newobj instance void Material::.ctor()
+ IL_004c: stfld class Material SequenceOfNestedIfs::_material
+ IL_0051: ldarg.0
+ IL_0052: ldfld class Material SequenceOfNestedIfs::_material
+ IL_0057: call bool Material::op_Implicit(class Material)
+ IL_005c: brtrue IL_007c
+
+ IL_0061: ldarg.0
+ IL_0062: callvirt instance bool SequenceOfNestedIfs::CheckShader()
+ IL_0067: brtrue IL_0071
+
+ IL_006c: br IL_00a7
+
+ IL_0071: ldarg.0
+ IL_0072: newobj instance void Material::.ctor()
+ IL_0077: stfld class Material SequenceOfNestedIfs::_material
+ IL_007c: ldarg.0
+ IL_007d: ldfld class Material SequenceOfNestedIfs::_material
+ IL_0082: call bool Material::op_Implicit(class Material)
+ IL_0087: brtrue IL_00a7
+
+ IL_008c: ldarg.0
+ IL_008d: callvirt instance bool SequenceOfNestedIfs::CheckShader()
+ IL_0092: brtrue IL_009c
+
+ IL_0097: br IL_00a7
+
+ IL_009c: ldarg.0
+ IL_009d: newobj instance void Material::.ctor()
+ IL_00a2: stfld class Material SequenceOfNestedIfs::_material
+ IL_00a7: ret
+ } // end of method SequenceOfNestedIfs::CreateMaterials
+
+} // end of class SequenceOfNestedIfs \ No newline at end of file
diff --git a/ICSharpCode.Decompiler/Tests/IL/StackTests.il b/ICSharpCode.Decompiler/Tests/IL/StackTests.il
new file mode 100644
index 00000000..51cee375
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/IL/StackTests.il
@@ -0,0 +1,132 @@
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
+ .ver 4:0:0:0
+}
+.assembly StackTests
+{
+ .hash algorithm 0x00008004
+ .ver 1:0:4059:39717
+}
+.module StackTests.exe
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000003 // ILONLY 32BITREQUIRED
+
+.class private auto ansi beforefieldinit StackTests.Program extends [mscorlib]System.Object
+{
+ .method public hidebysig static void Main(string[] args) cil managed
+ {
+ .entrypoint
+ .maxstack 8
+
+ ldc.i4.0
+ call string StackTests.Program::Test1(bool cond)
+ call void [mscorlib]System.Console::WriteLine(string) // false
+
+ ldc.i4.1
+ call string StackTests.Program::Test1(bool cond)
+ call void [mscorlib]System.Console::WriteLine(string) // true
+
+ ldc.i4.0
+ ldc.i4.0
+ ldc.i4.0
+ call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
+ call void [mscorlib]System.Console::WriteLine(int32) // 11
+
+ ldc.i4.0
+ ldc.i4.1
+ ldc.i4.0
+ call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
+ call void [mscorlib]System.Console::WriteLine(int32) // 21
+
+ ldc.i4.1
+ ldc.i4.1
+ ldc.i4.1
+ call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
+ call void [mscorlib]System.Console::WriteLine(int32) // 32
+
+ ldc.i4.2
+ ldc.i4.1
+ ldc.i4.0
+ call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
+ call void [mscorlib]System.Console::WriteLine(int32) // 23
+
+ ret
+ }
+
+ .method public hidebysig static string Test1(bool cond) cil managed
+ {
+ ldarg.0
+ brtrue TRUE
+
+ FALSE:
+ ldstr "false"
+ br EXIT
+
+ TRUE:
+ ldstr "true"
+
+ EXIT:
+ ret
+ }
+
+ .method public hidebysig static int32 Test2(int32 switch1, int32 br1, int32 br2) cil managed
+ {
+ ldarg.0
+ switch (ENTRY1, ENTRY2, ENTRY3)
+ ldc.i4.0
+ ret
+
+ ENTRY1:
+ ldc.i4.1
+ br BRANCH1
+
+ ENTRY2:
+ ldc.i4.2
+ br BRANCH1
+
+ ENTRY3:
+ ldc.i4.3
+ br BRANCH2
+
+ BRANCH1:
+ ldarg.1
+ brtrue BRANCH2
+
+ EXIT1:
+ ldc.i4 10
+ add
+ ret
+
+ BRANCH2:
+ ldarg.2
+ brtrue.s EXIT3
+
+ EXIT2:
+ ldc.i4 20
+ add
+ ret
+
+ EXIT3:
+ ldc.i4 30
+ add
+ ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method Program::.ctor
+
+} // end of class StackTests.Program
+
+
+// =============================================================
diff --git a/ICSharpCode.Decompiler/Tests/IncrementDecrement.cs b/ICSharpCode.Decompiler/Tests/IncrementDecrement.cs
new file mode 100644
index 00000000..e06b680d
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/IncrementDecrement.cs
@@ -0,0 +1,254 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class IncrementDecrement
+{
+ [Flags]
+ private enum MyEnum
+ {
+ None = 0,
+ One = 1,
+ Two = 2,
+ Four = 4
+ }
+
+ public class MutableClass
+ {
+ public int Field;
+
+ public int Property
+ {
+ get;
+ set;
+ }
+
+ public uint this[string name]
+ {
+ get
+ {
+ return 0u;
+ }
+ set
+ {
+ }
+ }
+ }
+
+ private IncrementDecrement.MyEnum enumField;
+ public static int StaticField;
+
+ public static int StaticProperty
+ {
+ get;
+ set;
+ }
+
+ private IncrementDecrement.MutableClass M()
+ {
+ return new IncrementDecrement.MutableClass();
+ }
+
+ private int[,] Array()
+ {
+ return null;
+ }
+
+ private unsafe int* GetPointer()
+ {
+ return null;
+ }
+
+ public int PreIncrementInAddition(int i, int j)
+ {
+ return i + ++j;
+ }
+
+ public int PreIncrementArrayElement(int[] array, int pos)
+ {
+ return --array[pos];
+ }
+
+ public int PreIncrementInstanceField()
+ {
+ return ++this.M().Field;
+ }
+
+ public int PreIncrementInstanceField2(IncrementDecrement.MutableClass m)
+ {
+ return ++m.Field;
+ }
+
+ public int PreIncrementInstanceProperty()
+ {
+ return ++this.M().Property;
+ }
+
+ public int PreIncrementStaticField()
+ {
+ return ++IncrementDecrement.StaticField;
+ }
+
+ public int PreIncrementStaticProperty()
+ {
+ return ++IncrementDecrement.StaticProperty;
+ }
+
+// public uint PreIncrementIndexer(string name)
+// {
+// return ++this.M()[name];
+// }
+
+ public int PreIncrementByRef(ref int i)
+ {
+ return ++i;
+ }
+
+ public unsafe int PreIncrementByPointer()
+ {
+ return ++(*this.GetPointer());
+ }
+
+ public int PreIncrement2DArray()
+ {
+ return ++this.Array()[1, 2];
+ }
+
+ public int CompoundAssignInstanceField()
+ {
+ return this.M().Field *= 10;
+ }
+
+ public int CompoundAssignInstanceProperty()
+ {
+ return this.M().Property *= 10;
+ }
+
+ public int CompoundAssignStaticField()
+ {
+ return IncrementDecrement.StaticField ^= 100;
+ }
+
+ public int CompoundAssignStaticProperty()
+ {
+ return IncrementDecrement.StaticProperty &= 10;
+ }
+
+ public int CompoundAssignArrayElement1(int[] array, int pos)
+ {
+ return array[pos] *= 10;
+ }
+
+ public int CompoundAssignArrayElement2(int[] array)
+ {
+ return array[Environment.TickCount] *= 10;
+ }
+
+// public uint CompoundAssignIndexer(string name)
+// {
+// return this.M()[name] -= 2;
+// }
+
+ public int CompoundAssignIncrement2DArray()
+ {
+ return this.Array()[1, 2] %= 10;
+ }
+
+ public int CompoundAssignByRef(ref int i)
+ {
+ return i <<= 2;
+ }
+
+ public unsafe double CompoundAssignByPointer(double* ptr)
+ {
+ return *ptr /= 1.5;
+ }
+
+ public void CompoundAssignEnum()
+ {
+ this.enumField |= IncrementDecrement.MyEnum.Two;
+ this.enumField &= ~IncrementDecrement.MyEnum.Four;
+ }
+
+ public int PostIncrementInAddition(int i, int j)
+ {
+ return i++ + j;
+ }
+
+ public void PostIncrementInlineLocalVariable(Func<int, int> f)
+ {
+ int num = 0;
+ f(num++);
+ }
+
+ public int PostIncrementArrayElement(int[] array, int pos)
+ {
+ return array[pos]--;
+ }
+
+ public int PostIncrementStaticField()
+ {
+ return IncrementDecrement.StaticField++;
+ }
+
+ public int PostIncrementStaticProperty()
+ {
+ return IncrementDecrement.StaticProperty++;
+ }
+
+ public int PostIncrementInstanceField(IncrementDecrement.MutableClass m)
+ {
+ return m.Field++;
+ }
+
+// public uint PostIncrementIndexer(string name)
+// {
+// return this.M()[name]++;
+// }
+
+// public unsafe int PostIncrementOfPointer(int* ptr)
+// {
+// return *(ptr++);
+// }
+
+ public int PostIncrementInstanceField()
+ {
+ return this.M().Field--;
+ }
+
+ public int PostIncrementInstanceProperty()
+ {
+ return this.M().Property--;
+ }
+
+ public int PostIncrement2DArray()
+ {
+ return this.Array()[IncrementDecrement.StaticField, IncrementDecrement.StaticProperty]++;
+ }
+
+ public int PostIncrementByRef(ref int i)
+ {
+ return i++;
+ }
+
+ public unsafe int PostIncrementByPointer()
+ {
+ return (*this.GetPointer())++;
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/InitializerTests.cs b/ICSharpCode.Decompiler/Tests/InitializerTests.cs
new file mode 100644
index 00000000..29e3d1d5
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/InitializerTests.cs
@@ -0,0 +1,885 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+
+public class InitializerTests
+{
+ private enum MyEnum
+ {
+ a,
+ b
+ }
+
+ private enum MyEnum2
+ {
+ c,
+ d
+ }
+
+ private class Data
+ {
+ public List<InitializerTests.MyEnum2> FieldList = new List<InitializerTests.MyEnum2>();
+ public InitializerTests.MyEnum a
+ {
+ get;
+ set;
+ }
+ public List<InitializerTests.MyEnum2> PropertyList
+ {
+ get;
+ set;
+ }
+
+ public InitializerTests.Data MoreData
+ {
+ get;
+ set;
+ }
+
+ public InitializerTests.StructData NestedStruct
+ {
+ get;
+ set;
+ }
+ }
+
+ private struct StructData
+ {
+ public int Field;
+ public int Property
+ {
+ get;
+ set;
+ }
+
+ public InitializerTests.Data MoreData
+ {
+ get;
+ set;
+ }
+
+ public StructData(int initialValue)
+ {
+ this = default(InitializerTests.StructData);
+ this.Field = initialValue;
+ this.Property = initialValue;
+ }
+ }
+
+ // Helper methods used to ensure initializers used within expressions work correctly
+ private static void X(object a, object b)
+ {
+ }
+
+ private static object Y()
+ {
+ return null;
+ }
+
+ #region Array Initializers
+ public static void Array1()
+ {
+ InitializerTests.X(InitializerTests.Y(), new int[]
+ {
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10
+ });
+ }
+
+ public static void Array2(int a, int b, int c)
+ {
+ InitializerTests.X(InitializerTests.Y(), new int[]
+ {
+ a,
+ 0,
+ b,
+ 0,
+ c
+ });
+ }
+
+ public static void NestedArray(int a, int b, int c)
+ {
+ InitializerTests.X(InitializerTests.Y(), new int[][]
+ {
+ new int[]
+ {
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10
+ },
+ new int[]
+ {
+ a,
+ b,
+ c
+ },
+ new int[]
+ {
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6
+ }
+ });
+ }
+
+ public static void ArrayBoolean()
+ {
+ InitializerTests.X(InitializerTests.Y(), new bool[]
+ {
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ true
+ });
+ }
+
+ public static void ArrayByte()
+ {
+ InitializerTests.X(InitializerTests.Y(), new byte[]
+ {
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 254,
+ 255
+ });
+ }
+
+ public static void ArraySByte()
+ {
+ InitializerTests.X(InitializerTests.Y(), new sbyte[]
+ {
+ -128,
+ -127,
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 127
+ });
+ }
+
+ public static void ArrayShort()
+ {
+ InitializerTests.X(InitializerTests.Y(), new short[]
+ {
+ -32768,
+ -1,
+ 0,
+ 1,
+ 32767
+ });
+ }
+
+ public static void ArrayUShort()
+ {
+ InitializerTests.X(InitializerTests.Y(), new ushort[]
+ {
+ 0,
+ 1,
+ 32767,
+ 32768,
+ 65534,
+ 65535
+ });
+ }
+
+ public static void ArrayInt()
+ {
+ InitializerTests.X(InitializerTests.Y(), new int[]
+ {
+ 1,
+ -2,
+ 2000000000,
+ 4,
+ 5,
+ -6,
+ 7,
+ 8,
+ 9,
+ 10
+ });
+ }
+
+ public static void ArrayUInt()
+ {
+ InitializerTests.X(InitializerTests.Y(), new uint[]
+ {
+ 1u,
+ 2000000000u,
+ 3000000000u,
+ 4u,
+ 5u,
+ 6u,
+ 7u,
+ 8u,
+ 9u,
+ 10u
+ });
+ }
+
+ public static void ArrayLong()
+ {
+ InitializerTests.X(InitializerTests.Y(), new long[]
+ {
+ -4999999999999999999L,
+ -1L,
+ 0L,
+ 1L,
+ 4999999999999999999L
+ });
+ }
+
+ public static void ArrayULong()
+ {
+ InitializerTests.X(InitializerTests.Y(), new ulong[]
+ {
+ 1uL,
+ 2000000000uL,
+ 3000000000uL,
+ 4uL,
+ 5uL,
+ 6uL,
+ 7uL,
+ 8uL,
+ 4999999999999999999uL,
+ 9999999999999999999uL
+ });
+ }
+
+ public static void ArrayFloat()
+ {
+ InitializerTests.X(InitializerTests.Y(), new float[]
+ {
+ -1.5f,
+ 0f,
+ 1.5f,
+ float.NegativeInfinity,
+ float.PositiveInfinity,
+ float.NaN
+ });
+ }
+
+ public static void ArrayDouble()
+ {
+ InitializerTests.X(InitializerTests.Y(), new double[]
+ {
+ -1.5,
+ 0.0,
+ 1.5,
+ double.NegativeInfinity,
+ double.PositiveInfinity,
+ double.NaN
+ });
+ }
+
+ public static void ArrayDecimal()
+ {
+ InitializerTests.X(InitializerTests.Y(), new decimal[]
+ {
+ -100m,
+ 0m,
+ 100m,
+ -79228162514264337593543950335m,
+ 79228162514264337593543950335m,
+ 0.0000001m
+ });
+ }
+
+ public static void ArrayString()
+ {
+ InitializerTests.X(InitializerTests.Y(), new string[]
+ {
+ "",
+ null,
+ "Hello",
+ "World"
+ });
+ }
+
+ public static void ArrayEnum()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.MyEnum[]
+ {
+ InitializerTests.MyEnum.a,
+ InitializerTests.MyEnum.b,
+ InitializerTests.MyEnum.a,
+ InitializerTests.MyEnum.b
+ });
+ }
+
+ public static void RecursiveArrayInitializer()
+ {
+ int[] array = new int[3];
+ array[0] = 1;
+ array[1] = 2;
+ array[2] = array[1] + 1;
+ array[0] = 0;
+ }
+ #endregion
+
+ public static void CollectionInitializerList()
+ {
+ InitializerTests.X(InitializerTests.Y(), new List<int>
+ {
+ 1,
+ 2,
+ 3
+ });
+ }
+
+ public static object RecursiveCollectionInitializer()
+ {
+ List<object> list = new List<object>();
+ list.Add(list);
+ return list;
+ }
+
+ public static void CollectionInitializerDictionary()
+ {
+ InitializerTests.X(InitializerTests.Y(), new Dictionary<string, int>
+ {
+ {
+ "First",
+ 1
+ },
+ {
+ "Second",
+ 2
+ },
+ {
+ "Third",
+ 3
+ }
+ });
+ }
+
+ public static void CollectionInitializerDictionaryWithEnumTypes()
+ {
+ InitializerTests.X(InitializerTests.Y(), new Dictionary<InitializerTests.MyEnum, InitializerTests.MyEnum2>
+ {
+ {
+ InitializerTests.MyEnum.a,
+ InitializerTests.MyEnum2.c
+ },
+ {
+ InitializerTests.MyEnum.b,
+ InitializerTests.MyEnum2.d
+ }
+ });
+ }
+
+ public static void NotACollectionInitializer()
+ {
+ List<int> list = new List<int>();
+ list.Add(1);
+ list.Add(2);
+ list.Add(3);
+ InitializerTests.X(InitializerTests.Y(), list);
+ }
+
+ public static void ObjectInitializer()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data
+ {
+ a = InitializerTests.MyEnum.a
+ });
+ }
+
+ public static void NotAObjectInitializer()
+ {
+ InitializerTests.Data data = new InitializerTests.Data();
+ data.a = InitializerTests.MyEnum.a;
+ InitializerTests.X(InitializerTests.Y(), data);
+ }
+
+ public static void ObjectInitializerAssignCollectionToField()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data
+ {
+ a = InitializerTests.MyEnum.a,
+ FieldList = new List<InitializerTests.MyEnum2>
+ {
+ InitializerTests.MyEnum2.c,
+ InitializerTests.MyEnum2.d
+ }
+ });
+ }
+
+ public static void ObjectInitializerAddToCollectionInField()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data
+ {
+ a = InitializerTests.MyEnum.a,
+ FieldList =
+ {
+ InitializerTests.MyEnum2.c,
+ InitializerTests.MyEnum2.d
+ }
+ });
+ }
+
+ public static void ObjectInitializerAssignCollectionToProperty()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data
+ {
+ a = InitializerTests.MyEnum.a,
+ PropertyList = new List<InitializerTests.MyEnum2>
+ {
+ InitializerTests.MyEnum2.c,
+ InitializerTests.MyEnum2.d
+ }
+ });
+ }
+
+ public static void ObjectInitializerAddToCollectionInProperty()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data
+ {
+ a = InitializerTests.MyEnum.a,
+ PropertyList =
+ {
+ InitializerTests.MyEnum2.c,
+ InitializerTests.MyEnum2.d
+ }
+ });
+ }
+
+ public static void ObjectInitializerWithInitializationOfNestedObjects()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data
+ {
+ MoreData =
+ {
+ a = InitializerTests.MyEnum.a
+ }
+ });
+ }
+
+ public static void StructInitializer_DefaultConstructor()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData
+ {
+ Field = 1,
+ Property = 2
+ });
+ }
+
+ public static void StructInitializer_ExplicitConstructor()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData(0)
+ {
+ Field = 1,
+ Property = 2
+ });
+ }
+
+ public static void StructInitializerWithInitializationOfNestedObjects()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.StructData
+ {
+ MoreData =
+ {
+ a = InitializerTests.MyEnum.a,
+ FieldList =
+ {
+ InitializerTests.MyEnum2.c,
+ InitializerTests.MyEnum2.d
+ }
+ }
+ });
+ }
+
+ public static void StructInitializerWithinObjectInitializer()
+ {
+ InitializerTests.X(InitializerTests.Y(), new InitializerTests.Data
+ {
+ NestedStruct = new InitializerTests.StructData(2)
+ {
+ Field = 1,
+ Property = 2
+ }
+ });
+ }
+
+ public int[,] MultidimensionalInit()
+ {
+ return new int[,]
+ {
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 1,
+ 1,
+ 1,
+ 1
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 1,
+ 1,
+ 1,
+ 1
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ }
+ };
+ }
+
+ public int[][,] MultidimensionalInit2()
+ {
+ return new int[][,]
+ {
+ new int[,]
+ {
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 1,
+ 1,
+ 1,
+ 1
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ }
+
+ },
+ new int[,]
+ {
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ }
+
+ },
+ new int[,]
+ {
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 1,
+ 1,
+ 1,
+ 1
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ }
+ },
+ new int[,]
+ {
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ },
+
+ {
+ 0,
+ 0,
+ 1,
+ 0
+ }
+
+ }
+ };
+ }
+
+ public int[][,,] ArrayOfArrayOfArrayInit()
+ {
+ return new int[][,,]
+ {
+ new int[,,]
+ {
+ {
+ {
+ 1,
+ 2,
+ 3
+ },
+ {
+ 4,
+ 5,
+ 6
+ },
+ {
+ 7,
+ 8,
+ 9
+ }
+ },
+ {
+ {
+ 11,
+ 12,
+ 13
+ },
+ {
+ 14,
+ 15,
+ 16
+ },
+ {
+ 17,
+ 18,
+ 19
+ }
+ }
+ },
+
+ new int[,,]
+ {
+ {
+ {
+ 21,
+ 22,
+ 23
+ },
+ {
+ 24,
+ 25,
+ 26
+ },
+ {
+ 27,
+ 28,
+ 29
+ }
+ },
+ {
+ {
+ 31,
+ 32,
+ 33
+ },
+ {
+ 34,
+ 35,
+ 36
+ },
+ {
+ 37,
+ 38,
+ 39
+ }
+ }
+ }
+ };
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/LiftedOperators.cs b/ICSharpCode.Decompiler/Tests/LiftedOperators.cs
new file mode 100644
index 00000000..426276ab
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/LiftedOperators.cs
@@ -0,0 +1,830 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Runtime.InteropServices;
+
+public static class LiftedOperators
+{
+ // C# uses 4 different patterns of IL for lifted operators: bool, other primitive types, decimal, other structs.
+ // Different patterns are used depending on whether both of the operands are nullable or only the left/right operand is nullable.
+ // Negation must not be pushed through such comparisons because it would change the semantics.
+ // A comparison used in a condition differs somewhat from a comparison used as a simple value.
+
+ public static void BoolBasic(bool? a, bool? b)
+ {
+ if (a == b)
+ {
+ Console.WriteLine();
+ }
+ if (a != b)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != b))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void BoolComplex(bool? a, Func<bool> x)
+ {
+ if (a == x())
+ {
+ Console.WriteLine();
+ }
+ if (a != x())
+ {
+ Console.WriteLine();
+ }
+
+ if (x() == a)
+ {
+ Console.WriteLine();
+ }
+ if (x() != a)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == x()))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != x()))
+ {
+ Console.WriteLine();
+ }
+ if (!(x() == a))
+ {
+ Console.WriteLine();
+ }
+ if (!(x() != a))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void BoolConst(bool? a)
+ {
+ if (a == true)
+ {
+ Console.WriteLine();
+ }
+ if (a != true)
+ {
+ Console.WriteLine();
+ }
+ if (a == false)
+ {
+ Console.WriteLine();
+ }
+ if (a != false)
+ {
+ Console.WriteLine();
+ }
+ if (a ?? true)
+ {
+ Console.WriteLine();
+ }
+ if (a ?? false)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void BoolValueBasic(bool? a, bool? b)
+ {
+ Console.WriteLine(a == b);
+ Console.WriteLine(a != b);
+
+ Console.WriteLine(!(a == b));
+ Console.WriteLine(!(a != b));
+
+ Console.WriteLine(a & b);
+ Console.WriteLine(a | b);
+ Console.WriteLine(a ^ b);
+ Console.WriteLine(a ?? b);
+ Console.WriteLine(!a);
+ a &= b;
+ a |= b;
+ a ^= b;
+ }
+
+ public static void BoolValueComplex(bool? a, Func<bool> x)
+ {
+ Console.WriteLine(a == x());
+ Console.WriteLine(a != x());
+
+ Console.WriteLine(x() == a);
+ Console.WriteLine(x() != a);
+
+ Console.WriteLine(!(a == x()));
+ Console.WriteLine(!(a != x()));
+
+ Console.WriteLine(a & x());
+ Console.WriteLine(a | x());
+ Console.WriteLine(a ^ x());
+ Console.WriteLine(a ?? x());
+ a &= x();
+ a |= x();
+ a ^= x();
+
+ Console.WriteLine(x() ^ a);
+ (new bool?[0])[0] ^= x();
+ }
+
+ public static void BoolValueConst(bool? a)
+ {
+ Console.WriteLine(a == true);
+ Console.WriteLine(a != true);
+ Console.WriteLine(a == false);
+ Console.WriteLine(a != false);
+ Console.WriteLine(a ?? true);
+ Console.WriteLine(a ?? false);
+ }
+
+ public static void IntBasic(int? a, int? b)
+ {
+ if (a == b)
+ {
+ Console.WriteLine();
+ }
+ if (a != b)
+ {
+ Console.WriteLine();
+ }
+ if (a > b)
+ {
+ Console.WriteLine();
+ }
+ if (a < b)
+ {
+ Console.WriteLine();
+ }
+ if (a >= b)
+ {
+ Console.WriteLine();
+ }
+ if (a <= b)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a > b))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void IntComplex(int? a, Func<int> x)
+ {
+ if (a == x())
+ {
+ Console.WriteLine();
+ }
+ if (a != x())
+ {
+ Console.WriteLine();
+ }
+ if (a > x())
+ {
+ Console.WriteLine();
+ }
+
+ if (x() == a)
+ {
+ Console.WriteLine();
+ }
+ if (x() != a)
+ {
+ Console.WriteLine();
+ }
+ if (x() > a)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == x()))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != x()))
+ {
+ Console.WriteLine();
+ }
+ if (!(a > x()))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void IntConst(int? a)
+ {
+ if (a == 2)
+ {
+ Console.WriteLine();
+ }
+ if (a != 2)
+ {
+ Console.WriteLine();
+ }
+ if (a > 2)
+ {
+ Console.WriteLine();
+ }
+
+ if (2 == a)
+ {
+ Console.WriteLine();
+ }
+ if (2 != a)
+ {
+ Console.WriteLine();
+ }
+ if (2 > a)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void IntValueBasic(int? a, int? b)
+ {
+ Console.WriteLine(a == b);
+ Console.WriteLine(a != b);
+ Console.WriteLine(a > b);
+
+ Console.WriteLine(!(a == b));
+ Console.WriteLine(!(a != b));
+ Console.WriteLine(!(a > b));
+
+ Console.WriteLine(a + b);
+ Console.WriteLine(a - b);
+ Console.WriteLine(a * b);
+ Console.WriteLine(a / b);
+ Console.WriteLine(a % b);
+ Console.WriteLine(a & b);
+ Console.WriteLine(a | b);
+ Console.WriteLine(a ^ b);
+ Console.WriteLine(a << b);
+ Console.WriteLine(a >> b);
+ Console.WriteLine(a ?? b);
+ Console.WriteLine(-a);
+ Console.WriteLine(~a);
+ // TODO:
+ //Console.WriteLine(a++);
+ //Console.WriteLine(a--);
+ Console.WriteLine(++a);
+ Console.WriteLine(--a);
+ a += b;
+ a -= b;
+ a *= b;
+ a /= b;
+ a %= b;
+ a &= b;
+ a |= b;
+ a ^= b;
+ a <<= b;
+ a >>= b;
+ }
+
+ public static void IntValueComplex(int? a, Func<int> x)
+ {
+ Console.WriteLine(a == x());
+ Console.WriteLine(a != x());
+ Console.WriteLine(a > x());
+
+ Console.WriteLine(x() == a);
+ Console.WriteLine(x() != a);
+ Console.WriteLine(x() > a);
+
+ Console.WriteLine(a + x());
+ Console.WriteLine(a - x());
+ Console.WriteLine(a * x());
+ Console.WriteLine(a / x());
+ Console.WriteLine(a % x());
+ Console.WriteLine(a & x());
+ Console.WriteLine(a | x());
+ Console.WriteLine(a ^ x());
+ Console.WriteLine(a << x());
+ Console.WriteLine(a >> x());
+ Console.WriteLine(a ?? x());
+ a += x();
+ a -= x();
+ a *= x();
+ a /= x();
+ a %= x();
+ a &= x();
+ a |= x();
+ a ^= x();
+ a <<= x();
+ a >>= x();
+
+ Console.WriteLine(x() + a);
+ (new int?[0])[0] += x();
+ }
+
+ public static void IntValueConst(int? a)
+ {
+ Console.WriteLine(a == 2);
+ Console.WriteLine(a != 2);
+ Console.WriteLine(a > 2);
+
+ Console.WriteLine(2 == a);
+ Console.WriteLine(2 != a);
+ Console.WriteLine(2 > a);
+
+ Console.WriteLine(a + 2);
+ Console.WriteLine(a - 2);
+ Console.WriteLine(a * 2);
+ Console.WriteLine(a / 2);
+ Console.WriteLine(a % 2);
+ Console.WriteLine(a & 2);
+ Console.WriteLine(a | 2);
+ Console.WriteLine(a ^ 2);
+ Console.WriteLine(a << 2);
+ Console.WriteLine(a >> 2);
+ Console.WriteLine(a ?? 2);
+ a += 2;
+ a -= 2;
+ a *= 2;
+ a /= 2;
+ a %= 2;
+ a &= 2;
+ a |= 2;
+ a ^= 2;
+ a <<= 2;
+ a >>= 2;
+
+ Console.WriteLine(2 + a);
+ }
+
+ public static void NumberBasic(decimal? a, decimal? b)
+ {
+ if (a == b)
+ {
+ Console.WriteLine();
+ }
+ if (a != b)
+ {
+ Console.WriteLine();
+ }
+ if (a > b)
+ {
+ Console.WriteLine();
+ }
+ if (a < b)
+ {
+ Console.WriteLine();
+ }
+ if (a >= b)
+ {
+ Console.WriteLine();
+ }
+ if (a <= b)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a > b))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void NumberComplex(decimal? a, Func<decimal> x)
+ {
+ if (a == x())
+ {
+ Console.WriteLine();
+ }
+ if (a != x())
+ {
+ Console.WriteLine();
+ }
+ if (a > x())
+ {
+ Console.WriteLine();
+ }
+
+ if (x() == a)
+ {
+ Console.WriteLine();
+ }
+ if (x() != a)
+ {
+ Console.WriteLine();
+ }
+ if (x() > a)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void NumberConst(decimal? a)
+ {
+ if (a == 2m)
+ {
+ Console.WriteLine();
+ }
+ if (a != 2m)
+ {
+ Console.WriteLine();
+ }
+ if (a > 2m)
+ {
+ Console.WriteLine();
+ }
+
+ if (2m == a)
+ {
+ Console.WriteLine();
+ }
+ if (2m != a)
+ {
+ Console.WriteLine();
+ }
+ if (2m > a)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void NumberValueBasic(decimal? a, decimal? b)
+ {
+ Console.WriteLine(a == b);
+ Console.WriteLine(a != b);
+ Console.WriteLine(a > b);
+
+ Console.WriteLine(!(a == b));
+ Console.WriteLine(!(a != b));
+ Console.WriteLine(!(a > b));
+
+ Console.WriteLine(a + b);
+ Console.WriteLine(a - b);
+ Console.WriteLine(a * b);
+ Console.WriteLine(a / b);
+ Console.WriteLine(a % b);
+ Console.WriteLine(a ?? b);
+ Console.WriteLine(-a);
+ // TODO:
+ //Console.WriteLine(a++);
+ //Console.WriteLine(a--);
+ //Console.WriteLine(++a);
+ //Console.WriteLine(--a);
+ a += b;
+ a -= b;
+ a *= b;
+ a /= b;
+ a %= b;
+ }
+
+ public static void NumberValueComplex(decimal? a, Func<decimal> x)
+ {
+ Console.WriteLine(a == x());
+ Console.WriteLine(a != x());
+ Console.WriteLine(a > x());
+
+ Console.WriteLine(x() == a);
+ Console.WriteLine(x() != a);
+ Console.WriteLine(x() > a);
+
+ Console.WriteLine(a + x());
+ Console.WriteLine(a - x());
+ Console.WriteLine(a * x());
+ Console.WriteLine(a / x());
+ Console.WriteLine(a % x());
+ Console.WriteLine(a ?? x());
+ a += x();
+ a -= x();
+ a *= x();
+ a /= x();
+ a %= x();
+
+ Console.WriteLine(x() + a);
+ (new decimal?[0])[0] += x();
+ }
+
+ public static void NumberValueConst(decimal? a)
+ {
+ Console.WriteLine(a == 2m);
+ Console.WriteLine(a != 2m);
+ Console.WriteLine(a > 2m);
+
+ Console.WriteLine(2m == a);
+ Console.WriteLine(2m != a);
+ Console.WriteLine(2m > a);
+
+ Console.WriteLine(a + 2m);
+ Console.WriteLine(a - 2m);
+ Console.WriteLine(a * 2m);
+ Console.WriteLine(a / 2m);
+ Console.WriteLine(a % 2m);
+ Console.WriteLine(a ?? 2m);
+ a += 2m;
+ a -= 2m;
+ a *= 2m;
+ a /= 2m;
+ a %= 2m;
+
+ Console.WriteLine(2m + a);
+ }
+
+ public static void StructBasic(TS? a, TS? b)
+ {
+ if (a == b)
+ {
+ Console.WriteLine();
+ }
+ if (a != b)
+ {
+ Console.WriteLine();
+ }
+ if (a > b)
+ {
+ Console.WriteLine();
+ }
+ if (a < b)
+ {
+ Console.WriteLine();
+ }
+ if (a >= b)
+ {
+ Console.WriteLine();
+ }
+ if (a <= b)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a > b))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void StructComplex(TS? a, Func<TS> x)
+ {
+ if (a == x())
+ {
+ Console.WriteLine();
+ }
+ if (a != x())
+ {
+ Console.WriteLine();
+ }
+ if (a > x())
+ {
+ Console.WriteLine();
+ }
+
+ if (x() == a)
+ {
+ Console.WriteLine();
+ }
+ if (x() != a)
+ {
+ Console.WriteLine();
+ }
+ if (x() > a)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void StructValueBasic(TS? a, TS? b, int? i)
+ {
+ Console.WriteLine(a == b);
+ Console.WriteLine(a != b);
+ Console.WriteLine(a > b);
+
+ Console.WriteLine(!(a == b));
+ Console.WriteLine(!(a != b));
+ Console.WriteLine(!(a > b));
+
+ Console.WriteLine(a + b);
+ Console.WriteLine(a - b);
+ Console.WriteLine(a * b);
+ Console.WriteLine(a / b);
+ Console.WriteLine(a % b);
+ Console.WriteLine(a & b);
+ Console.WriteLine(a | b);
+ Console.WriteLine(a ^ b);
+ Console.WriteLine(a << i);
+ Console.WriteLine(a >> i);
+ Console.WriteLine(a ?? b);
+ Console.WriteLine(+a);
+ Console.WriteLine(-a);
+ Console.WriteLine(!a);
+ Console.WriteLine(~a);
+ // TODO:
+ //Console.WriteLine(a++);
+ //Console.WriteLine(a--);
+ //Console.WriteLine(++a);
+ //Console.WriteLine(--a);
+ //Console.WriteLine((int?)a);
+ a += b;
+ a -= b;
+ a *= b;
+ a /= b;
+ a %= b;
+ a &= b;
+ a |= b;
+ a ^= b;
+ a <<= i;
+ a >>= i;
+ }
+
+ public static void StructValueComplex(TS? a, Func<TS> x, Func<int> i)
+ {
+ Console.WriteLine(a == x());
+ Console.WriteLine(a != x());
+ Console.WriteLine(a > x());
+
+ Console.WriteLine(x() == a);
+ Console.WriteLine(x() != a);
+ Console.WriteLine(x() > a);
+
+ Console.WriteLine(a + x());
+ Console.WriteLine(a - x());
+ Console.WriteLine(a * x());
+ Console.WriteLine(a / x());
+ Console.WriteLine(a % x());
+ Console.WriteLine(a & x());
+ Console.WriteLine(a | x());
+ Console.WriteLine(a ^ x());
+ Console.WriteLine(a << i());
+ Console.WriteLine(a >> i());
+ Console.WriteLine(a ?? x());
+ a += x();
+ a -= x();
+ a *= x();
+ a /= x();
+ a %= x();
+ a &= x();
+ a |= x();
+ a ^= x();
+ a <<= i();
+ a >>= i();
+
+ Console.WriteLine(x() + a);
+ (new TS?[0])[0] += x();
+ }
+}
+
+// dummy structure for testing custom operators
+[StructLayout(LayoutKind.Sequential, Size = 1)]
+public struct TS
+{
+ // unary
+ public static TS operator +(TS a)
+ {
+ throw null;
+ }
+ public static TS operator -(TS a)
+ {
+ throw null;
+ }
+ public static TS operator !(TS a)
+ {
+ throw null;
+ }
+ public static TS operator ~(TS a)
+ {
+ throw null;
+ }
+ public static TS operator ++(TS a)
+ {
+ throw null;
+ }
+ public static TS operator --(TS a)
+ {
+ throw null;
+ }
+
+ public static explicit operator int(TS a)
+ {
+ throw null;
+ }
+
+ // binary
+ public static TS operator +(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator -(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator *(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator /(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator %(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator &(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator |(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator ^(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator <<(TS a, int b)
+ {
+ throw null;
+ }
+ public static TS operator >>(TS a, int b)
+ {
+ throw null;
+ }
+
+ // comparisons
+ public static bool operator ==(TS a, TS b)
+ {
+ throw null;
+ }
+ public static bool operator !=(TS a, TS b)
+ {
+ throw null;
+ }
+ public static bool operator <(TS a, TS b)
+ {
+ throw null;
+ }
+ public static bool operator <=(TS a, TS b)
+ {
+ throw null;
+ }
+ public static bool operator >(TS a, TS b)
+ {
+ throw null;
+ }
+ public static bool operator >=(TS a, TS b)
+ {
+ throw null;
+ }
+
+ public override bool Equals(object obj)
+ {
+ throw null;
+ }
+ public override int GetHashCode()
+ {
+ throw null;
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Lock.cs b/ICSharpCode.Decompiler/Tests/Lock.cs
new file mode 100644
index 00000000..da5a59c7
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Lock.cs
@@ -0,0 +1,38 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class Lock
+{
+ public void LockThis()
+ {
+ lock (this)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public void LockOnType()
+ {
+ lock (typeof(Lock))
+ {
+ Console.WriteLine();
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Loops.cs b/ICSharpCode.Decompiler/Tests/Loops.cs
new file mode 100644
index 00000000..03427a8b
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Loops.cs
@@ -0,0 +1,74 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+public class Loops
+{
+ public void ForEach(IEnumerable<string> enumerable)
+ {
+ foreach (string current in enumerable)
+ {
+ current.ToLower();
+ }
+ }
+
+ public void ForEachOverList(List<string> list)
+ {
+ // List has a struct as enumerator, so produces quite different IL than foreach over the IEnumerable interface
+ foreach (string current in list)
+ {
+ current.ToLower();
+ }
+ }
+
+ public void ForEachOverNonGenericEnumerable(IEnumerable enumerable)
+ {
+ foreach (object current in enumerable)
+ {
+ current.ToString();
+ }
+ }
+
+ public void ForEachOverNonGenericEnumerableWithAutomaticCast(IEnumerable enumerable)
+ {
+ foreach (int num in enumerable)
+ {
+ num.ToString();
+ }
+ }
+
+// public void ForEachOverArray(string[] array)
+// {
+// foreach (string text in array)
+// {
+// text.ToLower();
+// }
+// }
+
+ public void ForOverArray(string[] array)
+ {
+ for (int i = 0; i < array.Length; i++)
+ {
+ array[i].ToLower();
+ }
+ }
+}
+
diff --git a/ICSharpCode.Decompiler/Tests/MultidimensionalArray.cs b/ICSharpCode.Decompiler/Tests/MultidimensionalArray.cs
new file mode 100644
index 00000000..c3557cee
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/MultidimensionalArray.cs
@@ -0,0 +1,58 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class MultidimensionalArray
+{
+ internal class Generic<T, S> where T : new()
+ {
+ private T[,] a = new T[20, 20];
+ private S[,][] b = new S[20, 20][];
+
+ public T this[int i, int j]
+ {
+ get
+ {
+ return this.a[i, j];
+ }
+ set
+ {
+ this.a[i, j] = value;
+ }
+ }
+
+ public void TestB(S x, ref S y)
+ {
+ this.b[5, 3] = new S[10];
+ this.b[5, 3][0] = default(S);
+ this.b[5, 3][1] = x;
+ this.b[5, 3][2] = y;
+ }
+
+ public void PassByReference(ref T arr)
+ {
+ this.PassByReference(ref this.a[10, 10]);
+ }
+ }
+
+ public int[][,] MakeArray()
+ {
+ return new int[10][,];
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/PInvoke.cs b/ICSharpCode.Decompiler/Tests/PInvoke.cs
new file mode 100644
index 00000000..0c828ac6
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/PInvoke.cs
@@ -0,0 +1,96 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Runtime.InteropServices;
+
+// P/Invoke and marshalling attribute tests
+public class PInvoke
+{
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 2)]
+ public struct MarshalAsTest
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+ public uint[] FixedArray;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.Bool)]
+ public int[] FixedBoolArray;
+
+ [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
+ public string[] SafeBStrArray;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
+ public string FixedString;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public struct Rect
+ {
+ [FieldOffset(0)]
+ public int left;
+ [FieldOffset(4)]
+ public int top;
+ [FieldOffset(8)]
+ public int right;
+ [FieldOffset(12)]
+ public int bottom;
+ }
+
+ public static decimal MarshalAttributesOnPropertyAccessors
+ {
+ [return: MarshalAs(UnmanagedType.Currency)]
+ get
+ {
+ return 0m;
+ }
+ [param: MarshalAs(UnmanagedType.Currency)]
+ set
+ {
+ }
+ }
+
+ [DllImport("xyz.dll", CharSet = CharSet.Auto)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool Method([MarshalAs(UnmanagedType.LPStr)] string input);
+
+ [DllImport("xyz.dll")]
+ private static extern void New1(int ElemCnt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] ar);
+
+ [DllImport("xyz.dll")]
+ private static extern void New2([MarshalAs(UnmanagedType.LPArray, SizeConst = 128)] int[] ar);
+
+ [DllImport("xyz.dll")]
+ private static extern void New3([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Bool, SizeConst = 64, SizeParamIndex = 1)] int[] ar);
+
+ public void CustomMarshal1([MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "MyCompany.MyMarshaler")] object o)
+ {
+ }
+
+ public void CustomMarshal2([MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "MyCompany.MyMarshaler", MarshalCookie = "Cookie")] object o)
+ {
+ }
+
+ [DllImport("ws2_32.dll", SetLastError = true)]
+ internal static extern IntPtr ioctlsocket([In] IntPtr socketHandle, [In] int cmd, [In] [Out] ref int argp);
+
+ public void CallMethodWithInOutParameter()
+ {
+ int num = 0;
+ PInvoke.ioctlsocket(IntPtr.Zero, 0, ref num);
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs b/ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs
new file mode 100644
index 00000000..9b3d1658
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs
@@ -0,0 +1,80 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Text;
+
+public class PropertiesAndEvents
+{
+ public event EventHandler AutomaticEvent;
+
+ [field: NonSerialized]
+ public event EventHandler AutomaticEventWithInitializer = delegate(object sender, EventArgs e)
+ {
+ };
+
+ public event EventHandler CustomEvent
+ {
+ add
+ {
+ this.AutomaticEvent += value;
+ }
+ remove
+ {
+ this.AutomaticEvent -= value;
+ }
+ }
+
+ public int AutomaticProperty
+ {
+ get;
+ set;
+ }
+
+ public int CustomProperty
+ {
+ get
+ {
+ return this.AutomaticProperty;
+ }
+ set
+ {
+ this.AutomaticProperty = value;
+ }
+ }
+
+ public int Getter(StringBuilder b)
+ {
+ return b.Length;
+ }
+
+ public void Setter(StringBuilder b)
+ {
+ b.Capacity = 100;
+ }
+
+ public char IndexerGetter(StringBuilder b)
+ {
+ return b[50];
+ }
+
+ public void IndexerSetter(StringBuilder b)
+ {
+ b[42] = 'b';
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/QueryExpressions.cs b/ICSharpCode.Decompiler/Tests/QueryExpressions.cs
new file mode 100644
index 00000000..d8b6e062
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/QueryExpressions.cs
@@ -0,0 +1,188 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+public class QueryExpressions
+{
+ public class Customer
+ {
+ public int CustomerID;
+ public IEnumerable<QueryExpressions.Order> Orders;
+ public string Name;
+ public string Country;
+ public string City;
+ }
+
+ public class Order
+ {
+ public int OrderID;
+ public DateTime OrderDate;
+ public QueryExpressions.Customer Customer;
+ public int CustomerID;
+ public decimal Total;
+ public IEnumerable<QueryExpressions.OrderDetail> Details;
+ }
+
+ public class OrderDetail
+ {
+ public decimal UnitPrice;
+ public int Quantity;
+ }
+
+ public IEnumerable<QueryExpressions.Customer> customers;
+ public IEnumerable<QueryExpressions.Order> orders;
+
+ public object MultipleWhere()
+ {
+ return from c in this.customers
+ where c.Orders.Count<QueryExpressions.Order>() > 10
+ where c.Country == "DE"
+ select c;
+ }
+
+ public object SelectManyFollowedBySelect()
+ {
+ return from c in this.customers
+ from o in c.Orders
+ select new
+ {
+ c.Name,
+ o.OrderID,
+ o.Total
+ };
+ }
+
+ public object SelectManyFollowedByOrderBy()
+ {
+ return from c in this.customers
+ from o in c.Orders
+ orderby o.Total descending
+ select new
+ {
+ c.Name,
+ o.OrderID,
+ o.Total
+ };
+ }
+
+ public object MultipleSelectManyFollowedBySelect()
+ {
+ return from c in this.customers
+ from o in c.Orders
+ from d in o.Details
+ select new
+ {
+ c.Name,
+ o.OrderID,
+ d.Quantity
+ };
+ }
+
+ public object MultipleSelectManyFollowedByLet()
+ {
+ return from c in this.customers
+ from o in c.Orders
+ from d in o.Details
+ let x = d.Quantity * d.UnitPrice
+ select new
+ {
+ c.Name,
+ o.OrderID,
+ x
+ };
+ }
+
+ public object FromLetWhereSelect()
+ {
+ return from o in this.orders
+ let t = o.Details.Sum((QueryExpressions.OrderDetail d) => d.UnitPrice * d.Quantity)
+ where t >= 1000m
+ select new
+ {
+ OrderID = o.OrderID,
+ Total = t
+ };
+ }
+
+ public object MultipleLet()
+ {
+ return from a in this.customers
+ let b = a.Country
+ let c = a.Name
+ select b + c;
+ }
+
+ public object Join()
+ {
+ return from c in this.customers
+ join o in this.orders on c.CustomerID equals o.CustomerID
+ select new
+ {
+ c.Name,
+ o.OrderDate,
+ o.Total
+ };
+ }
+
+ public object JoinInto()
+ {
+ return from c in this.customers
+ join o in this.orders on c.CustomerID equals o.CustomerID into co
+ let n = co.Count<QueryExpressions.Order>()
+ where n >= 10
+ select new
+ {
+ Name = c.Name,
+ OrderCount = n
+ };
+ }
+
+ public object OrderBy()
+ {
+ return from o in this.orders
+ orderby o.Customer.Name, o.Total descending
+ select o;
+ }
+
+ public object GroupBy()
+ {
+ return from c in this.customers
+ group c.Name by c.Country;
+ }
+
+ public object ExplicitType()
+ {
+ return from QueryExpressions.Customer c in this.customers
+ where c.City == "London"
+ select c;
+ }
+
+ public object QueryContinuation()
+ {
+ return from c in this.customers
+ group c by c.Country into g
+ select new
+ {
+ Country = g.Key,
+ CustCount = g.Count<QueryExpressions.Customer>()
+ };
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Switch.cs b/ICSharpCode.Decompiler/Tests/Switch.cs
new file mode 100644
index 00000000..4a20a639
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Switch.cs
@@ -0,0 +1,89 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public static class Switch
+{
+ public static string ShortSwitchOverString(string text)
+ {
+ switch (text) {
+ case "First case":
+ return "Text";
+ default:
+ return "Default";
+ }
+ }
+
+ public static string SwitchOverString1(string text)
+ {
+ switch (text)
+ {
+ case "First case":
+ return "Text1";
+ case "Second case":
+ case "2nd case":
+ return "Text2";
+ case "Third case":
+ return "Text3";
+ case "Fourth case":
+ return "Text4";
+ case "Fifth case":
+ return "Text5";
+ case "Sixth case":
+ return "Text6";
+ case null:
+ return null;
+ default:
+ return "Default";
+ }
+ }
+
+ public static string SwitchOverString2()
+ {
+ switch (Environment.UserName)
+ {
+ case "First case":
+ return "Text1";
+ case "Second case":
+ return "Text2";
+ case "Third case":
+ return "Text3";
+ case "Fourth case":
+ return "Text4";
+ case "Fifth case":
+ return "Text5";
+ case "Sixth case":
+ return "Text6";
+ default:
+ return "Default";
+ }
+ }
+
+ public static string SwitchOverBool(bool b)
+ {
+ switch (b) {
+ case true:
+ return bool.TrueString;
+ case false:
+ return bool.FalseString;
+ default:
+ return null;
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/TestRunner.cs b/ICSharpCode.Decompiler/Tests/TestRunner.cs
new file mode 100644
index 00000000..215725b0
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/TestRunner.cs
@@ -0,0 +1,198 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.CodeDom.Compiler;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using DiffLib;
+using ICSharpCode.Decompiler.Ast;
+using ICSharpCode.Decompiler.Tests.Helpers;
+using Microsoft.CSharp;
+using Mono.Cecil;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests
+{
+ [TestFixture]
+ public class TestRunner : DecompilerTestBase
+ {
+ [Test]
+ public void Async()
+ {
+ TestFile(@"..\..\Tests\Async.cs");
+ }
+
+ [Test, Ignore("disambiguating overloads is not yet implemented")]
+ public void CallOverloadedMethod()
+ {
+ TestFile(@"..\..\Tests\CallOverloadedMethod.cs");
+ }
+
+ [Test, Ignore("unncessary primitive casts")]
+ public void CheckedUnchecked()
+ {
+ TestFile(@"..\..\Tests\CheckedUnchecked.cs");
+ }
+
+ [Test, Ignore("Missing cast on null")]
+ public void DelegateConstruction()
+ {
+ TestFile(@"..\..\Tests\DelegateConstruction.cs");
+ }
+
+ [Test, Ignore("Not yet implemented")]
+ public void ExpressionTrees()
+ {
+ TestFile(@"..\..\Tests\ExpressionTrees.cs");
+ }
+
+ [Test]
+ public void ExceptionHandling()
+ {
+ AssertRoundtripCode(@"..\..\Tests\ExceptionHandling.cs", optimize: false);
+ AssertRoundtripCode(@"..\..\Tests\ExceptionHandling.cs", optimize: false);
+ }
+
+ [Test]
+ public void Generics()
+ {
+ TestFile(@"..\..\Tests\Generics.cs");
+ }
+
+ [Test]
+ public void CustomShortCircuitOperators()
+ {
+ TestFile(@"..\..\Tests\CustomShortCircuitOperators.cs");
+ }
+
+ [Test]
+ public void ControlFlowWithDebug()
+ {
+ AssertRoundtripCode(@"..\..\Tests\ControlFlow.cs", optimize: false, useDebug: true);
+ AssertRoundtripCode(@"..\..\Tests\ControlFlow.cs", optimize: false, useDebug: true);
+ }
+
+ [Test]
+ public void DoubleConstants()
+ {
+ TestFile(@"..\..\Tests\DoubleConstants.cs");
+ }
+
+ [Test]
+ public void IncrementDecrement()
+ {
+ TestFile(@"..\..\Tests\IncrementDecrement.cs");
+ }
+
+ [Test]
+ public void InitializerTests()
+ {
+ TestFile(@"..\..\Tests\InitializerTests.cs");
+ }
+
+ [Test]
+ public void LiftedOperators()
+ {
+ TestFile(@"..\..\Tests\LiftedOperators.cs");
+ }
+
+ [Test]
+ public void Lock()
+ {
+ //TestFile(@"..\..\Tests\Lock.cs", compilerVersion: 2);
+ TestFile(@"..\..\Tests\Lock.cs", compilerVersion: 4);
+ }
+
+ [Test]
+ public void Loops()
+ {
+ TestFile(@"..\..\Tests\Loops.cs");
+ }
+
+ [Test]
+ public void MultidimensionalArray()
+ {
+ TestFile(@"..\..\Tests\MultidimensionalArray.cs");
+ }
+
+ [Test]
+ public void PInvoke()
+ {
+ TestFile(@"..\..\Tests\PInvoke.cs");
+ }
+
+ [Test]
+ public void PropertiesAndEvents()
+ {
+ TestFile(@"..\..\Tests\PropertiesAndEvents.cs");
+ }
+
+ [Test]
+ public void QueryExpressions()
+ {
+ TestFile(@"..\..\Tests\QueryExpressions.cs");
+ }
+
+ [Test, Ignore("switch transform doesn't recreate the exact original switch")]
+ public void Switch()
+ {
+ TestFile(@"..\..\Tests\Switch.cs");
+ }
+
+ [Test]
+ public void UndocumentedExpressions()
+ {
+ TestFile(@"..\..\Tests\UndocumentedExpressions.cs");
+ }
+
+ [Test, Ignore("has incorrect casts to IntPtr")]
+ public void UnsafeCode()
+ {
+ TestFile(@"..\..\Tests\UnsafeCode.cs");
+ }
+
+ [Test]
+ public void ValueTypes()
+ {
+ TestFile(@"..\..\Tests\ValueTypes.cs");
+ }
+
+ [Test, Ignore("Redundant yield break; not removed")]
+ public void YieldReturn()
+ {
+ TestFile(@"..\..\Tests\YieldReturn.cs");
+ }
+
+ [Test]
+ public void TypeAnalysis()
+ {
+ TestFile(@"..\..\Tests\TypeAnalysisTests.cs");
+ }
+
+ static void TestFile(string fileName, bool useDebug = false, int compilerVersion = 4)
+ {
+ AssertRoundtripCode(fileName, optimize: false, useDebug: useDebug, compilerVersion: compilerVersion);
+ AssertRoundtripCode(fileName, optimize: true, useDebug: useDebug, compilerVersion: compilerVersion);
+ AssertRoundtripCode(fileName, optimize: false, useDebug: useDebug, compilerVersion: compilerVersion);
+ AssertRoundtripCode(fileName, optimize: true, useDebug: useDebug, compilerVersion: compilerVersion);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs b/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs
new file mode 100644
index 00000000..760bb862
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs
@@ -0,0 +1,153 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class TypeAnalysisTests
+{
+ public byte SubtractFrom256(byte b)
+ {
+ return (byte)(256 - (int)b);
+ }
+
+ #region Shift
+ public int LShiftInteger(int num1, int num2)
+ {
+ return num1 << num2;
+ }
+
+ public uint LShiftUnsignedInteger(uint num1, uint num2)
+ {
+ return num1 << (int)num2;
+ }
+
+ public long LShiftLong(long num1, long num2)
+ {
+ return num1 << (int)num2;
+ }
+
+ public ulong LShiftUnsignedLong(ulong num1, ulong num2)
+ {
+ return num1 << (int)num2;
+ }
+
+ public int RShiftInteger(int num1, int num2)
+ {
+ return num1 >> num2;
+ }
+
+ public uint RShiftUnsignedInteger(uint num1, int num2)
+ {
+ return num1 >> num2;
+ }
+
+ public long RShiftLong(long num1, long num2)
+ {
+ return num1 >> (int)num2;
+ }
+
+ public ulong RShiftUnsignedLong(ulong num1, ulong num2)
+ {
+ return num1 >> (int)num2;
+ }
+
+ public int ShiftByte(byte num)
+ {
+ return (int)num << 8;
+ }
+
+ public int RShiftByte(byte num)
+ {
+ return num >> 8;
+ }
+
+ public uint RShiftByteWithZeroExtension(byte num)
+ {
+ return (uint)num >> 8;
+ }
+
+ public int RShiftByteAsSByte(byte num)
+ {
+ return (sbyte)num >> 8;
+ }
+
+ public int RShiftSByte(sbyte num)
+ {
+ return num >> 8;
+ }
+
+ public uint RShiftSByteWithZeroExtension(sbyte num)
+ {
+ return (uint)num >> 8;
+ }
+
+ public int RShiftSByteAsByte(sbyte num)
+ {
+ return (byte)num >> 8;
+ }
+ #endregion
+
+ public int GetHashCode(long num)
+ {
+ return (int)num ^ (int)(num >> 32);
+ }
+
+ public void TernaryOp(Random a, Random b, bool c)
+ {
+ if ((c ? a : b) == null)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public void OperatorIs(object o)
+ {
+ Console.WriteLine(o is Random);
+ Console.WriteLine(!(o is Random));
+ }
+
+ public byte[] CreateArrayWithInt(int length)
+ {
+ return new byte[length];
+ }
+
+ public byte[] CreateArrayWithLong(long length)
+ {
+ return new byte[length];
+ }
+
+ public byte[] CreateArrayWithUInt(uint length)
+ {
+ return new byte[length];
+ }
+
+ public byte[] CreateArrayWithULong(ulong length)
+ {
+ return new byte[length];
+ }
+
+ public StringComparison EnumDiffNumber(StringComparison data)
+ {
+ return data - 1;
+ }
+
+ public int EnumDiff(StringComparison a, StringComparison b)
+ {
+ return Math.Abs(a - b);
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs b/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs
new file mode 100644
index 00000000..fb48d016
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Types/EnumTests.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests.Types
+{
+ [TestFixture]
+ public class EnumTests : DecompilerTestBase
+ {
+ [Test]
+ public void EnumSamples()
+ {
+ ValidateFileRoundtrip(@"Types\S_EnumSamples.cs");
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Types/S_EnumSamples.cs b/ICSharpCode.Decompiler/Tests/Types/S_EnumSamples.cs
new file mode 100644
index 00000000..3149f575
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Types/S_EnumSamples.cs
@@ -0,0 +1,129 @@
+// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+//$CS
+using System;
+//$CE
+
+//$$ SingleValue
+public class TS_SingleValue
+{
+ public AttributeTargets Method()
+ {
+ return AttributeTargets.Class;
+ }
+}
+//$$ TwoValuesOr
+public class TS_TwoValuesOr
+{
+ public AttributeTargets Method()
+ {
+ return AttributeTargets.Class | AttributeTargets.Method;
+ }
+}
+//$$ ThreeValuesOr
+public class TS_ThreeValuesOr
+{
+ public AttributeTargets Method()
+ {
+ return AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter;
+ }
+}
+//$$ UnknownNumericValue
+public class TS_UnknownNumericValue
+{
+ public AttributeTargets Method()
+ {
+ return (AttributeTargets)1000000;
+ }
+}
+//$$ AllValue
+public class TS_AllValue
+{
+ public AttributeTargets Method()
+ {
+ return AttributeTargets.All;
+ }
+}
+//$$ ZeroValue
+public class TS_ZeroValue
+{
+ public AttributeTargets Method()
+ {
+ return (AttributeTargets)0;
+ }
+}
+//$$ PreservingTypeWhenBoxed
+public class TS_PreservingTypeWhenBoxed
+{
+ public object Method()
+ {
+ return AttributeTargets.Delegate;
+ }
+}
+//$$ PreservingTypeWhenBoxedTwoEnum
+public class TS_PreservingTypeWhenBoxedTwoEnum
+{
+ public object Method()
+ {
+ return AttributeTargets.Class | AttributeTargets.Delegate;
+ }
+}
+//$$ DeclarationSimpleEnum
+public enum TS_DeclarationSimpleEnum
+{
+ Item1,
+ Item2
+}
+//$$ DeclarationLongBasedEnum
+public enum TS_DeclarationLongBasedEnum : long
+{
+ Item1,
+ Item2
+}
+//$$ DeclarationLongWithInitializers
+public enum TS_DeclarationLongWithInitializers : long
+{
+ Item1,
+ Item2 = 20L,
+ Item3
+}
+//$$ DeclarationShortWithInitializers
+public enum TS_DeclarationShortWithInitializers : short
+{
+ Item1,
+ Item2 = 20,
+ Item3
+}
+//$$ DeclarationByteWithInitializers
+public enum TS_DeclarationByteWithInitializers : byte
+{
+ Item1,
+ Item2 = 20,
+ Item3
+}
+//$$ DeclarationFlags
+[Flags]
+public enum TS_DeclarationFlags
+{
+ None = 0,
+ Item1 = 1,
+ Item2 = 2,
+ Item3 = 4,
+ All = 7
+}
diff --git a/ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs b/ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs
new file mode 100644
index 00000000..99bf4279
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace ClassMultiInterface
+{
+ public interface IA
+ {
+ }
+ public interface IA2 : IA
+ {
+ }
+ public interface IB
+ {
+ }
+ public class C : IA2, IB
+ {
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs b/ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs
new file mode 100644
index 00000000..4a85b9f8
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs
@@ -0,0 +1,1138 @@
+// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+//$CS
+using System;
+//$CE
+
+//$$ IndexerWithGetOnly
+namespace IndexerWithGetOnly
+{
+ public class MyClass
+ {
+ public int this[int i]
+ {
+ get
+ {
+ return i;
+ }
+ }
+ }
+}
+//$$ IndexerWithSetOnly
+namespace IndexerWithSetOnly
+{
+ public class MyClass
+ {
+ public int this[int i]
+ {
+ set
+ {
+ }
+ }
+ }
+}
+//$$ IndexerWithMoreParameters
+namespace IndexerWithMoreParameters
+{
+ public class MyClass
+ {
+ public int this[int i, string s, Type t]
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ }
+}
+//$$ IndexerInGenericClass
+namespace IndexerInGenericClass
+{
+ public class MyClass<T>
+ {
+ public int this[T t]
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ }
+}
+//$$ OverloadedIndexer
+namespace OverloadedIndexer
+{
+ public class MyClass
+ {
+ public int this[int t]
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ public int this[string s]
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ Console.WriteLine(value + " " + s);
+ }
+ }
+ }
+}
+//$$ IndexerInInterface
+namespace IndexerInInterface
+{
+ public interface IInterface
+ {
+ int this[string s, string s2]
+ {
+ set;
+ }
+ }
+}
+//$$ IndexerInterfaceExplicitImplementation
+namespace IndexerInterfaceExplicitImplementation
+{
+ public interface IMyInterface
+ {
+ int this[string s]
+ {
+ get;
+ }
+ }
+ public class MyClass : IMyInterface
+ {
+ int IMyInterface.this[string s]
+ {
+ get
+ {
+ return 3;
+ }
+ }
+ }
+}
+//$$ IndexerInterfaceImplementation
+namespace IndexerInterfaceImplementation
+{
+ public interface IMyInterface
+ {
+ int this[string s]
+ {
+ get;
+ }
+ }
+ public class MyClass : IMyInterface
+ {
+ public int this[string s]
+ {
+ get
+ {
+ return 3;
+ }
+ }
+ }
+}
+//$$ IndexerAbstract
+namespace IndexerAbstract
+{
+ public abstract class MyClass
+ {
+ public abstract int this[string s, string s2]
+ {
+ set;
+ }
+ protected abstract string this[int index]
+ {
+ get;
+ }
+ }
+}
+//$$ MethodExplicit
+namespace MethodExplicit
+{
+ public interface IMyInterface
+ {
+ void MyMethod();
+ }
+ public class MyClass : IMyInterface
+ {
+ void IMyInterface.MyMethod()
+ {
+ }
+ }
+}
+//$$ MethodFromInterfaceVirtual
+namespace MethodFromInterfaceVirtual
+{
+ public interface IMyInterface
+ {
+ void MyMethod();
+ }
+ public class MyClass : IMyInterface
+ {
+ public virtual void MyMethod()
+ {
+ }
+ }
+}
+//$$ MethodFromInterface
+namespace MethodFromInterface
+{
+ public interface IMyInterface
+ {
+ void MyMethod();
+ }
+ public class MyClass : IMyInterface
+ {
+ public void MyMethod()
+ {
+ }
+ }
+}
+//$$ MethodFromInterfaceAbstract
+namespace MethodFromInterfaceAbstract
+{
+ public interface IMyInterface
+ {
+ void MyMethod();
+ }
+ public abstract class MyClass : IMyInterface
+ {
+ public abstract void MyMethod();
+ }
+}
+//$$ PropertyInterface
+namespace PropertyInterface
+{
+ public interface IMyInterface
+ {
+ int MyProperty
+ {
+ get;
+ set;
+ }
+ }
+}
+//$$ PropertyInterfaceExplicitImplementation
+namespace PropertyInterfaceExplicitImplementation
+{
+ public interface IMyInterface
+ {
+ int MyProperty
+ {
+ get;
+ set;
+ }
+ }
+ public class MyClass : IMyInterface
+ {
+ int IMyInterface.MyProperty
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ }
+ }
+ }
+}
+//$$ PropertyInterfaceImplementation
+namespace PropertyInterfaceImplementation
+{
+ public interface IMyInterface
+ {
+ int MyProperty
+ {
+ get;
+ set;
+ }
+ }
+ public class MyClass : IMyInterface
+ {
+ public int MyProperty
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ }
+ }
+ }
+}
+//$$ PropertyPrivateGetPublicSet
+namespace PropertyPrivateGetPublicSet
+{
+ public class MyClass
+ {
+ public int MyProperty
+ {
+ private get
+ {
+ return 3;
+ }
+ set
+ {
+ }
+ }
+ }
+}
+//$$ PropertyPublicGetProtectedSet
+namespace PropertyPublicGetProtectedSet
+{
+ public class MyClass
+ {
+ public int MyProperty
+ {
+ get
+ {
+ return 3;
+ }
+ protected set
+ {
+ }
+ }
+ }
+}
+//$$ PropertyOverrideDefaultAccessorOnly
+namespace PropertyOverrideDefaultAccessorOnly
+{
+ public class MyClass
+ {
+ public virtual int MyProperty
+ {
+ get
+ {
+ return 3;
+ }
+ protected set
+ {
+ }
+ }
+ }
+ public class Derived : MyClass
+ {
+ public override int MyProperty
+ {
+ get
+ {
+ return 4;
+ }
+ }
+ }
+}
+//$$ PropertyOverrideRestrictedAccessorOnly
+namespace PropertyOverrideRestrictedAccessorOnly
+{
+ public class MyClass
+ {
+ public virtual int MyProperty
+ {
+ get
+ {
+ return 3;
+ }
+ protected set
+ {
+ }
+ }
+ }
+ public class Derived : MyClass
+ {
+ public override int MyProperty
+ {
+ protected set
+ {
+ }
+ }
+ }
+}
+//$$ PropertyOverrideOneAccessor
+namespace PropertyOverrideOneAccessor
+{
+ public class MyClass
+ {
+ protected internal virtual int MyProperty
+ {
+ get
+ {
+ return 3;
+ }
+ protected set
+ {
+ }
+ }
+ }
+ public class DerivedNew : MyClass
+ {
+ public new virtual int MyProperty
+ {
+ set
+ {
+ }
+ }
+ }
+ public class DerivedOverride : DerivedNew
+ {
+ public override int MyProperty
+ {
+ set
+ {
+ }
+ }
+ }
+}
+//$$ IndexerOverrideRestrictedAccessorOnly
+namespace IndexerOverrideRestrictedAccessorOnly
+{
+ public class MyClass
+ {
+ public virtual int this[string s]
+ {
+ get
+ {
+ return 3;
+ }
+ protected set
+ {
+ }
+ }
+ protected internal virtual int this[int i]
+ {
+ protected get
+ {
+ return 2;
+ }
+ set
+ {
+ }
+ }
+ }
+ public class Derived : MyClass
+ {
+ protected internal override int this[int i]
+ {
+ protected get
+ {
+ return 4;
+ }
+ }
+ }
+}
+//$$ HideProperty
+namespace HideProperty
+{
+ public class A
+ {
+ public virtual int P
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ }
+ }
+ }
+ public class B : A
+ {
+ private new int P
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ }
+ }
+ }
+ public class C : B
+ {
+ public override int P
+ {
+ set
+ {
+ }
+ }
+ }
+}
+//$$ HideMembers
+namespace HideMembers
+{
+ public class A
+ {
+ public int F;
+ public int Prop
+ {
+ get
+ {
+ return 3;
+ }
+ }
+ public int G
+ {
+ get
+ {
+ return 3;
+ }
+ }
+ }
+ public class B : A
+ {
+ public new int F
+ {
+ get
+ {
+ return 3;
+ }
+ }
+ public new string Prop
+ {
+ get
+ {
+ return "a";
+ }
+ }
+ }
+ public class C : A
+ {
+ public new int G;
+ }
+ public class D : A
+ {
+ public new void F()
+ {
+ }
+ }
+ public class D1 : D
+ {
+ public new int F;
+ }
+ public class E : A
+ {
+ private new class F
+ {
+ }
+ }
+}
+//$$ HideMembers2
+namespace HideMembers2
+{
+ public class G
+ {
+ public int Item
+ {
+ get
+ {
+ return 1;
+ }
+ }
+ }
+ public class G2 : G
+ {
+ public int this[int i]
+ {
+ get
+ {
+ return 2;
+ }
+ }
+ }
+ public class G3 : G2
+ {
+ public new int Item
+ {
+ get
+ {
+ return 4;
+ }
+ }
+ }
+ public class H
+ {
+ public int this[int j]
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ }
+ public class H2 : H
+ {
+ public int Item
+ {
+ get
+ {
+ return 2;
+ }
+ }
+ }
+ public class H3 : H2
+ {
+ public new string this[int j]
+ {
+ get
+ {
+ return null;
+ }
+ }
+ }
+}
+//$$ HideMembers2a
+namespace HideMembers2a
+{
+ public interface IA
+ {
+ int this[int i]
+ {
+ get;
+ }
+ }
+ public class A : IA
+ {
+ int IA.this[int i]
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+ }
+ public class A1 : A
+ {
+ public int this[int i]
+ {
+ get
+ {
+ return 3;
+ }
+ }
+ }
+}
+//$$ HideMembers3
+namespace HideMembers3
+{
+ public class G<T>
+ {
+ public void M1(T p)
+ {
+ }
+ public int M2(int t)
+ {
+ return 3;
+ }
+ }
+ public class G1<T> : G<int>
+ {
+ public new int M1(int i)
+ {
+ return 0;
+ }
+ public int M2(T i)
+ {
+ return 2;
+ }
+ }
+ public class G2<T> : G<int>
+ {
+ public int M1(T p)
+ {
+ return 4;
+ }
+ }
+ public class J
+ {
+ public int P
+ {
+ get
+ {
+ return 2;
+ }
+ }
+ }
+ public class J2 : J
+ {
+#pragma warning disable 0108 // Deliberate bad code for test case
+ public int get_P;
+#pragma warning restore 0108
+ }
+}
+//$$ HideMembers4
+namespace HideMembers4
+{
+ public class A
+ {
+ public void M<T>(T t)
+ {
+ }
+ }
+ public class A1 : A
+ {
+ public new void M<K>(K t)
+ {
+ }
+ public void M(int t)
+ {
+ }
+ }
+ public class B
+ {
+ public void M<T>()
+ {
+ }
+ public void M1<T>()
+ {
+ }
+ public void M2<T>(T t)
+ {
+ }
+ }
+ public class B1 : B
+ {
+ public void M<T1, T2>()
+ {
+ }
+ public new void M1<R>()
+ {
+ }
+ public new void M2<R>(R r)
+ {
+ }
+ }
+ public class C<T>
+ {
+ public void M<TT>(T t)
+ {
+ }
+ }
+ public class C1<K> : C<K>
+ {
+ public void M<TT>(TT t)
+ {
+ }
+ }
+}
+//$$ HideMembers5
+namespace HideMembers5
+{
+ public class A
+ {
+ public void M(int t)
+ {
+ }
+ }
+ public class A1 : A
+ {
+ public void M(ref int t)
+ {
+ }
+ }
+ public class B
+ {
+ public void M(ref int l)
+ {
+ }
+ }
+ public class B1 : B
+ {
+ public void M(out int l)
+ {
+ l = 2;
+ }
+ public void M(ref long l)
+ {
+ }
+ }
+}
+//$$ HideMemberSkipNotVisible
+namespace HideMemberSkipNotVisible
+{
+ public class A
+ {
+ protected int F;
+ protected string P
+ {
+ get
+ {
+ return null;
+ }
+ }
+ }
+ public class B : A
+ {
+ private new string F;
+ private new int P
+ {
+ set
+ {
+ }
+ }
+ }
+}
+//$$ HideNestedClass
+namespace HideNestedClass
+{
+ public class A
+ {
+ public class N1
+ {
+ }
+ protected class N2
+ {
+ }
+ private class N3
+ {
+ }
+ internal class N4
+ {
+ }
+ protected internal class N5
+ {
+ }
+ }
+ public class B : A
+ {
+ public new int N1;
+ public new int N2;
+ public int N3;
+ public new int N4;
+ public new int N5;
+ }
+}
+//$$ HidePropertyReservedMethod
+namespace HidePropertyReservedMethod
+{
+ public class A
+ {
+ public int P
+ {
+ get
+ {
+ return 1;
+ }
+ }
+ }
+ public class B : A
+ {
+ public int get_P()
+ {
+ return 2;
+ }
+ public void set_P(int value)
+ {
+ }
+ }
+}
+//$$ HideIndexerDiffAccessor
+namespace HideIndexerDiffAccessor
+{
+ public class A
+ {
+ public int this[int i]
+ {
+ get
+ {
+ return 2;
+ }
+ }
+ }
+ public class B : A
+ {
+ public new int this[int j]
+ {
+ set
+ {
+ }
+ }
+ }
+}
+//$$ HideIndexerGeneric
+namespace HideIndexerGeneric
+{
+ public class A<T>
+ {
+ public virtual int this[T r]
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ }
+ }
+ }
+ public class B : A<int>
+ {
+ private new int this[int k]
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ }
+ }
+ }
+ public class C<T> : A<T>
+ {
+ public override int this[T s]
+ {
+ set
+ {
+ }
+ }
+ }
+ public class D<T> : C<T>
+ {
+ public new virtual int this[T s]
+ {
+ set
+ {
+ }
+ }
+ }
+}
+//$$ HideMethod
+namespace HideMethod
+{
+ public class A
+ {
+ public virtual void F()
+ {
+ }
+ }
+ public class B : A
+ {
+ private new void F()
+ {
+ base.F();
+ }
+ }
+ public class C : B
+ {
+ public override void F()
+ {
+ base.F();
+ }
+ }
+}
+//$$ HideMethodGeneric
+namespace HideMethodGeneric
+{
+ public class A<T>
+ {
+ public virtual void F(T s)
+ {
+ }
+ public new static bool Equals(object o1, object o2)
+ {
+ return true;
+ }
+ }
+ public class B : A<string>
+ {
+ private new void F(string k)
+ {
+ }
+ public void F(int i)
+ {
+ }
+ }
+ public class C<T> : A<T>
+ {
+ public override void F(T r)
+ {
+ }
+ public void G(T t)
+ {
+ }
+ }
+ public class D<T1> : C<T1>
+ {
+ public new virtual void F(T1 k)
+ {
+ }
+ public virtual void F<T2>(T2 k)
+ {
+ }
+ public virtual void G<T2>(T2 t)
+ {
+ }
+ }
+}
+//$$ HideMethodGenericSkipPrivate
+namespace HideMethodGenericSkipPrivate
+{
+ public class A<T>
+ {
+ public virtual void F(T t)
+ {
+ }
+ }
+ public class B<T> : A<T>
+ {
+ private new void F(T t)
+ {
+ }
+ private void K()
+ {
+ }
+ }
+ public class C<T> : B<T>
+ {
+ public override void F(T tt)
+ {
+ }
+ public void K()
+ {
+ }
+ }
+ public class D : B<int>
+ {
+ public override void F(int t)
+ {
+ }
+ }
+}
+//$$ HideMethodGeneric2
+namespace HideMethodGeneric2
+{
+ public class A
+ {
+ public virtual void F(int i)
+ {
+ }
+ public void K()
+ {
+ }
+ }
+ public class B<T> : A
+ {
+ protected virtual void F(T t)
+ {
+ }
+ public void K<T2>()
+ {
+ }
+ }
+ public class C : B<int>
+ {
+ protected override void F(int k)
+ {
+ }
+ public new void K<T3>()
+ {
+ }
+ }
+ public class D : B<string>
+ {
+ public override void F(int k)
+ {
+ }
+ public void L<T4>()
+ {
+ }
+ }
+ public class E<T>
+ {
+ public void M<T2>(T t, T2 t2)
+ {
+ }
+ }
+ public class F<T> : E<T>
+ {
+ public void M(T t1, T t2)
+ {
+ }
+ }
+}
+//$$ HideMethodDiffSignatures
+namespace HideMethodDiffSignatures
+{
+ public class C1<T>
+ {
+ public virtual void M(T arg)
+ {
+ }
+ }
+ public class C2<T1, T2> : C1<T2>
+ {
+ public new virtual void M(T2 arg)
+ {
+ }
+ }
+ public class C3 : C2<int, bool>
+ {
+ public new virtual void M(bool arg)
+ {
+ }
+ }
+}
+//$$ HideMethodStatic
+namespace HideMethodStatic
+{
+ public class A
+ {
+ public int N
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ }
+ public class B
+ {
+ public int N()
+ {
+ return 0;
+ }
+ }
+}
+//$$ HideEvent
+namespace HideEvent
+{
+ public class A
+ {
+ public virtual event EventHandler E;
+ public event EventHandler F;
+ }
+ public class B : A
+ {
+ public new virtual event EventHandler E;
+ public new event EventHandler F;
+ }
+ public class C : B
+ {
+ public override event EventHandler E;
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs b/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs
new file mode 100644
index 00000000..3bb80ed8
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/Types/TypeTests.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests.Types
+{
+ [TestFixture]
+ public class TypeTests : DecompilerTestBase
+ {
+ [Test]
+ public void TypeMemberDeclarations()
+ {
+ ValidateFileRoundtrip(@"Types\S_TypeMemberDeclarations.cs");
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs b/ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs
new file mode 100644
index 00000000..80f5b037
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs
@@ -0,0 +1,41 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class UndocumentedExpressions
+{
+ public static int GetArgCount(__arglist)
+ {
+ ArgIterator argIterator = new ArgIterator(__arglist);
+ return argIterator.GetRemainingCount();
+ }
+
+ public static void MakeTypedRef(object o)
+ {
+ TypedReference tr = __makeref(o);
+ UndocumentedExpressions.AcceptTypedRef(tr);
+ }
+
+ private static void AcceptTypedRef(TypedReference tr)
+ {
+ Console.WriteLine("Value is: " + __refvalue(tr, object).ToString());
+ Console.WriteLine("Type is: " + __reftype(tr).Name);
+ __refvalue(tr, object) = 1;
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/UnsafeCode.cs b/ICSharpCode.Decompiler/Tests/UnsafeCode.cs
new file mode 100644
index 00000000..1a3bd6a0
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/UnsafeCode.cs
@@ -0,0 +1,145 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public class UnsafeCode
+{
+ public unsafe int* NullPointer
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ public unsafe long ConvertDoubleToLong(double d)
+ {
+ return *(long*)(&d);
+ }
+
+ public unsafe double ConvertLongToDouble(long d)
+ {
+ return *(double*)(&d);
+ }
+
+ public unsafe int ConvertFloatToInt(float d)
+ {
+ return *(int*)(&d);
+ }
+
+ public unsafe float ConvertIntToFloat(int d)
+ {
+ return *(float*)(&d);
+ }
+
+ public unsafe void PassRefParameterAsPointer(ref int p)
+ {
+ fixed (int* ptr = &p)
+ {
+ this.PassPointerAsRefParameter(ptr);
+ }
+ }
+
+ public unsafe void PassPointerAsRefParameter(int* p)
+ {
+ this.PassRefParameterAsPointer(ref *p);
+ }
+
+ public unsafe void AddressInMultiDimensionalArray(double[,] matrix)
+ {
+ fixed (double* ptr = &matrix[1, 2])
+ {
+ this.PointerReferenceExpression(ptr);
+ }
+ }
+
+ public unsafe void FixedStringAccess(string text)
+ {
+ fixed (char* ptr = text)
+ {
+ char* ptr2 = ptr;
+ while (*ptr2 != '\0')
+ {
+ *ptr2 = 'A';
+ ptr2++;
+ }
+ }
+ }
+
+ public unsafe void PutDoubleIntoLongArray1(long[] array, int index, double val)
+ {
+ fixed (long* ptr = array)
+ {
+ ((double*)ptr)[index] = val;
+ }
+ }
+
+ public unsafe void PutDoubleIntoLongArray2(long[] array, int index, double val)
+ {
+ fixed (long* ptr = &array[index])
+ {
+ *(double*)ptr = val;
+ }
+ }
+
+ public unsafe string PointerReferenceExpression(double* d)
+ {
+ return d->ToString();
+ }
+
+ public unsafe void FixMultipleStrings(string text)
+ {
+ fixed (char* ptr = text, userName = Environment.UserName, ptr2 = text)
+ {
+ *ptr = 'c';
+ *userName = 'd';
+ *ptr2 = 'e';
+ }
+ }
+
+ public unsafe string StackAlloc(int count)
+ {
+ char* ptr = stackalloc char[count];
+ for (int i = 0; i < count; i++)
+ {
+ ptr[i] = (char)i;
+ }
+ return this.PointerReferenceExpression((double*)ptr);
+ }
+
+ public unsafe int* PointerArithmetic(int* p)
+ {
+ return p + 2;
+ }
+
+ public unsafe byte* PointerArithmetic2(long* p, int y, int x)
+ {
+ return (byte*)p + (y * x);
+ }
+
+ public unsafe long* PointerArithmetic3(long* p)
+ {
+ return (long*)((byte*)p + 3);
+ }
+
+ unsafe ~UnsafeCode()
+ {
+ this.PassPointerAsRefParameter(this.NullPointer);
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/ValueTypes.cs b/ICSharpCode.Decompiler/Tests/ValueTypes.cs
new file mode 100644
index 00000000..1493cff4
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/ValueTypes.cs
@@ -0,0 +1,188 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+
+public static class ValueTypes
+{
+ public struct S
+ {
+ public int Field;
+
+ public S(int field)
+ {
+ this.Field = field;
+ }
+
+ public void SetField()
+ {
+ this.Field = 5;
+ }
+
+ public void MethodCalls()
+ {
+ this.SetField();
+ ValueTypes.S.Test(this);
+ ValueTypes.S.Test(ref this);
+ }
+
+ private static void Test(ValueTypes.S byVal)
+ {
+ }
+
+ private static void Test(ref ValueTypes.S byRef)
+ {
+ }
+ }
+
+ private static readonly ValueTypes.S ReadOnlyS = default(ValueTypes.S);
+ private static ValueTypes.S MutableS = default(ValueTypes.S);
+ private static volatile int VolatileInt;
+
+ public static void CallMethodViaField()
+ {
+ ValueTypes.ReadOnlyS.SetField();
+ ValueTypes.MutableS.SetField();
+ ValueTypes.S mutableS = ValueTypes.MutableS;
+ mutableS.SetField();
+ }
+
+ public static ValueTypes.S InitObj1()
+ {
+ ValueTypes.S result = default(ValueTypes.S);
+ ValueTypes.MakeArray();
+ return result;
+ }
+
+ public static ValueTypes.S InitObj2()
+ {
+ return default(ValueTypes.S);
+ }
+
+ public static void InitObj3(out ValueTypes.S p)
+ {
+ p = default(ValueTypes.S);
+ }
+
+ public static ValueTypes.S CallValueTypeCtor1()
+ {
+ return new ValueTypes.S(10);
+ }
+
+ public static ValueTypes.S CallValueTypeCtor2()
+ {
+ ValueTypes.S result = new ValueTypes.S(10);
+ return result;
+ }
+
+ public static ValueTypes.S Copy1(ValueTypes.S p)
+ {
+ return p;
+ }
+
+ public static ValueTypes.S Copy2(ref ValueTypes.S p)
+ {
+ return p;
+ }
+
+ public static void Copy3(ValueTypes.S p, out ValueTypes.S o)
+ {
+ o = p;
+ }
+
+ public static void Copy4(ref ValueTypes.S p, out ValueTypes.S o)
+ {
+ o = p;
+ }
+
+ public static void Copy4b(ref ValueTypes.S p, out ValueTypes.S o)
+ {
+ // test passing through by-ref arguments
+ ValueTypes.Copy4(ref p, out o);
+ }
+
+ public static void Issue56(int i, out string str)
+ {
+ str = "qq";
+ str += i.ToString();
+ }
+
+ public static void CopyAroundAndModifyField(ValueTypes.S s)
+ {
+ ValueTypes.S s2 = s;
+ s2.Field += 10;
+ s = s2;
+ }
+
+ private static int[] MakeArray()
+ {
+ return null;
+ }
+
+ public static void IncrementArrayLocation()
+ {
+ ValueTypes.MakeArray()[Environment.TickCount]++;
+ }
+
+ public static bool Is(object obj)
+ {
+ return obj is ValueTypes.S;
+ }
+
+ public static bool IsNullable(object obj)
+ {
+ return obj is ValueTypes.S?;
+ }
+
+ public static ValueTypes.S? As(object obj)
+ {
+ return obj as ValueTypes.S?;
+ }
+
+ public static ValueTypes.S OnlyChangeTheCopy(ValueTypes.S p)
+ {
+ ValueTypes.S s = p;
+ s.SetField();
+ return p;
+ }
+
+ public static void UseRefBoolInCondition(ref bool x)
+ {
+ if (x)
+ {
+ Console.WriteLine("true");
+ }
+ }
+
+ public static void CompareNotEqual0IsReallyNotEqual(IComparable<int> a)
+ {
+ if (a.CompareTo(0) != 0)
+ {
+ Console.WriteLine("true");
+ }
+ }
+
+ public static void CompareEqual0IsReallyEqual(IComparable<int> a)
+ {
+ if (a.CompareTo(0) == 0)
+ {
+ Console.WriteLine("true");
+ }
+ }
+
+}
diff --git a/ICSharpCode.Decompiler/Tests/YieldReturn.cs b/ICSharpCode.Decompiler/Tests/YieldReturn.cs
new file mode 100644
index 00000000..7546b194
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/YieldReturn.cs
@@ -0,0 +1,148 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+
+public static class YieldReturn
+{
+ public static IEnumerable<string> SimpleYieldReturn()
+ {
+ yield return "A";
+ yield return "B";
+ yield return "C";
+ }
+
+ public static IEnumerable<int> YieldReturnInLoop()
+ {
+ for (int i = 0; i < 100; i++) {
+ yield return i;
+ }
+ }
+
+ public static IEnumerable<int> YieldReturnWithTryFinally()
+ {
+ yield return 0;
+ try {
+ yield return 1;
+ } finally {
+ Console.WriteLine("Finally!");
+ }
+ yield return 2;
+ }
+
+ public static IEnumerable<int> YieldReturnInLock1(object o)
+ {
+ lock (o) {
+ yield return 1;
+ }
+ }
+
+ public static IEnumerable<int> YieldReturnInLock2(object o)
+ {
+ lock (o) {
+ yield return 1;
+ o = null;
+ yield return 2;
+ }
+ }
+
+ public static IEnumerable<string> YieldReturnWithNestedTryFinally(bool breakInMiddle)
+ {
+ Console.WriteLine("Start of method - 1");
+ yield return "Start of method";
+ Console.WriteLine("Start of method - 2");
+ try {
+ Console.WriteLine("Within outer try - 1");
+ yield return "Within outer try";
+ Console.WriteLine("Within outer try - 2");
+ try {
+ Console.WriteLine("Within inner try - 1");
+ yield return "Within inner try";
+ Console.WriteLine("Within inner try - 2");
+ if (breakInMiddle)
+ yield break;
+ Console.WriteLine("End of inner try - 1");
+ yield return "End of inner try";
+ Console.WriteLine("End of inner try - 2");
+ } finally {
+ Console.WriteLine("Inner Finally");
+ }
+ Console.WriteLine("End of outer try - 1");
+ yield return "End of outer try";
+ Console.WriteLine("End of outer try - 2");
+ } finally {
+ Console.WriteLine("Outer Finally");
+ }
+ Console.WriteLine("End of method - 1");
+ yield return "End of method";
+ Console.WriteLine("End of method - 2");
+ }
+
+ public static IEnumerable<string> YieldReturnWithTwoNonNestedFinallyBlocks(IEnumerable<string> input)
+ {
+ // outer try-finally block
+ foreach (string line in input) {
+ // nested try-finally block
+ try {
+ yield return line;
+ } finally {
+ Console.WriteLine("Processed " + line);
+ }
+ }
+ yield return "A";
+ yield return "B";
+ yield return "C";
+ yield return "D";
+ yield return "E";
+ yield return "F";
+ // outer try-finally block
+ foreach (string line in input)
+ yield return line.ToUpper();
+ }
+
+ public static IEnumerable<Func<string>> YieldReturnWithAnonymousMethods1(IEnumerable<string> input)
+ {
+ foreach (string line in input) {
+ yield return () => line;
+ }
+ }
+
+ public static IEnumerable<Func<string>> YieldReturnWithAnonymousMethods2(IEnumerable<string> input)
+ {
+ foreach (string line in input) {
+ string copy = line;
+ yield return () => copy;
+ }
+ }
+
+ public static IEnumerable<int> GetEvenNumbers(int n)
+ {
+ for (int i = 0; i < n; i++) {
+ if (i % 2 == 0)
+ yield return i;
+ }
+ }
+
+ public static IEnumerable<char> YieldChars()
+ {
+ yield return 'a';
+ yield return 'b';
+ yield return 'c';
+ }
+}
diff --git a/ICSharpCode.Decompiler/Tests/packages.config b/ICSharpCode.Decompiler/Tests/packages.config
new file mode 100644
index 00000000..b6522ccd
--- /dev/null
+++ b/ICSharpCode.Decompiler/Tests/packages.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="DiffLib" version="1.0.0.55" />
+ <package id="ICSharpCode.NRefactory" version="5.5.1" targetFramework="net45" />
+ <package id="Mono.Cecil" version="0.9.5.4" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/ICSharpCode.Decompiler/TextOutputWriter.cs b/ICSharpCode.Decompiler/TextOutputWriter.cs
new file mode 100644
index 00000000..964187a3
--- /dev/null
+++ b/ICSharpCode.Decompiler/TextOutputWriter.cs
@@ -0,0 +1,55 @@
+// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.IO;
+using System.Text;
+
+namespace ICSharpCode.Decompiler
+{
+ public class TextOutputWriter : TextWriter
+ {
+ readonly ITextOutput output;
+
+ public TextOutputWriter(ITextOutput output)
+ {
+ if (output == null)
+ throw new ArgumentNullException("output");
+ this.output = output;
+ }
+
+ public override Encoding Encoding {
+ get { return Encoding.UTF8; }
+ }
+
+ public override void Write(char value)
+ {
+ output.Write(value);
+ }
+
+ public override void Write(string value)
+ {
+ output.Write(value);
+ }
+
+ public override void WriteLine()
+ {
+ output.WriteLine();
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/packages.config b/ICSharpCode.Decompiler/packages.config
new file mode 100644
index 00000000..11cc9f06
--- /dev/null
+++ b/ICSharpCode.Decompiler/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="ICSharpCode.NRefactory" version="5.5.1" targetFramework="net45" />
+ <package id="Mono.Cecil" version="0.9.6.1" targetFramework="net451" />
+</packages>
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..ee588a5b
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,40 @@
+CORE=Xamarin.Forms.Core
+COREASSEMBLY=$(CORE)/bin/Release/$(CORE).dll
+XAML=Xamarin.Forms.Xaml
+XAMLASSEMBLY=$(XAML)/bin/Release/$(XAML).dll
+MAPS=Xamarin.Forms.Maps
+MAPSASSEMBLY=$(MAPS)/bin/Release/$(MAPS).dll
+# MDOC=/Library/Frameworks/Mono.framework/Versions/2.10.12/bin/mdoc
+MDOC=mdoc
+
+docs: $(CORE).docs $(MAPS).docs $(XAML).docs
+
+$(CORE).docs: $(COREASSEMBLY)
+ $(MDOC) update --delete -o docs/$(CORE) $(COREASSEMBLY) -L /Library/Frameworks/Mono.framework/Libraries/mono/xbuild-frameworks/.NETPortable/v4.5/Profile/Profile259/
+
+$(XAML).docs: $(XAMLASSEMBLY)
+ $(MDOC) update --delete -o docs/$(XAML) $(XAMLASSEMBLY) -L /Library/Frameworks/Mono.framework/Libraries/mono/xbuild-frameworks/.NETPortable/v4.5/Profile/Profile259/
+
+$(MAPS).docs: $(MAPSASSEMBLY)
+ $(MDOC) update --delete -o docs/$(MAPS) $(MAPSASSEMBLY) -L /Library/Frameworks/Mono.framework/Libraries/mono/xbuild-frameworks/.NETPortable/v4.5/Profile/Profile259/
+
+$(COREASSEMBLY): .FORCE
+ xbuild /property:Configuration=Release Xamarin.Forms.Core/Xamarin.Forms.Core.csproj
+
+$(XAMLASSEMBLY): .FORCE
+ xbuild /property:Configuration=Release Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.csproj
+
+$(MAPSASSEMBLY): .FORCE
+ xbuild /property:Configuration=Release Xamarin.Forms.Maps/Xamarin.Forms.Maps.csproj
+
+htmldocs: docs
+ $(MDOC) export-html -o htmldocs docs/*
+
+
+xmldocs: docs
+ $(MDOC) export-msxdoc -o docs/$(CORE).xml docs/$(CORE)
+ $(MDOC) export-msxdoc -o docs/$(XAML).xml docs/$(XAML)
+ $(MDOC) export-msxdoc -o docs/$(MAPS).xml docs/$(MAPS)
+.FORCE:
+
+.PHONY: .FORCE $(CORE).docs $(MAPS).docs $(XAML).docs htmldocs xmldocs
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..3acf95cd
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+Xamarin.Forms
diff --git a/Stubs/Xamarin.Forms.Platform.Android/Properties/AssemblyInfo.cs b/Stubs/Xamarin.Forms.Platform.Android/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..e30743a6
--- /dev/null
+++ b/Stubs/Xamarin.Forms.Platform.Android/Properties/AssemblyInfo.cs
@@ -0,0 +1,31 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Android.App;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle ("Xamarin.Forms.Platform.Android")]
+[assembly: AssemblyDescription ("")]
+[assembly: AssemblyConfiguration ("")]
+[assembly: AssemblyCompany ("")]
+[assembly: AssemblyProduct ("Xamarin.Forms.Platform.Android")]
+[assembly: AssemblyCopyright ("Copyright © 2015")]
+[assembly: AssemblyTrademark ("")]
+[assembly: AssemblyCulture ("")]
+[assembly: InternalsVisibleTo ("Xamarin.Forms.Core")]
+[assembly: ComVisible (false)]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion ("1.0.0.0")]
+[assembly: AssemblyFileVersion ("1.0.0.0")]
diff --git a/Stubs/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android (Forwarders).csproj b/Stubs/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android (Forwarders).csproj
new file mode 100644
index 00000000..0ef06973
--- /dev/null
+++ b/Stubs/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android (Forwarders).csproj
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{6E53FEB1-1100-46AE-8013-17BBA35CC197}</ProjectGuid>
+ <ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Platform</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Platform</AssemblyName>
+ <FileAlignment>512</FileAlignment>
+ <AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+ <AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
+ <DevInstrumentationEnabled>True</DevInstrumentationEnabled>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ <TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;__ANDROID__</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Mono.Android" />
+ <Reference Include="mscorlib" />
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Xml" />
+ <Reference Include="Xamarin.Android.Support.v4, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\Xamarin.Android.Support.v4.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.Android.Support.v7.RecyclerView, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\Xamarin.Android.Support.v7.RecyclerView.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.v7.RecyclerView.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Platform.cs">
+ <Link>Xamarin.Forms.Platform.cs</Link>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Xamarin.Forms.Platform.Android.FormsViewGroup\Xamarin.Forms.Platform.Android.FormsViewGroup.csproj">
+ <Project>{3b72465b-acae-43ae-9327-10f372fe5f80}</Project>
+ <Name>Xamarin.Forms.Platform.Android.FormsViewGroup</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Xamarin.Forms.Platform.Android\Xamarin.Forms.Platform.Android.csproj">
+ <Project>{0e16e70a-d6dd-4323-ad5d-363abff42d6a}</Project>
+ <Name>Xamarin.Forms.Platform.Android</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+ </Target>
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/Stubs/Xamarin.Forms.Platform.Android/packages.config b/Stubs/Xamarin.Forms.Platform.Android/packages.config
new file mode 100644
index 00000000..0dceb44c
--- /dev/null
+++ b/Stubs/Xamarin.Forms.Platform.Android/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Xamarin.Android.Support.v4" version="23.1.1.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.Android.Support.v7.RecyclerView" version="23.1.1.1" targetFramework="monoandroid60" />
+</packages>
diff --git a/Stubs/Xamarin.Forms.Platform.WP8/Properties/AssemblyInfo.cs b/Stubs/Xamarin.Forms.Platform.WP8/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..cb633c9a
--- /dev/null
+++ b/Stubs/Xamarin.Forms.Platform.WP8/Properties/AssemblyInfo.cs
@@ -0,0 +1,30 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Xamarin.Forms.Platform.WP8")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Forms.Platform.WP8")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: InternalsVisibleTo ("Xamarin.Forms.Core")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)] \ No newline at end of file
diff --git a/Stubs/Xamarin.Forms.Platform.WP8/Xamarin.Forms.Platform.WP8 (Forwarders).csproj b/Stubs/Xamarin.Forms.Platform.WP8/Xamarin.Forms.Platform.WP8 (Forwarders).csproj
new file mode 100644
index 00000000..adf6b997
--- /dev/null
+++ b/Stubs/Xamarin.Forms.Platform.WP8/Xamarin.Forms.Platform.WP8 (Forwarders).csproj
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>10.0.20506</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{483CDAE7-4353-4AB2-9C20-145A9F148FAD}</ProjectGuid>
+ <ProjectTypeGuids>{C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Platform</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Platform</AssemblyName>
+ <TargetFrameworkIdentifier>WindowsPhone</TargetFrameworkIdentifier>
+ <TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
+ <SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
+ <SilverlightApplication>false</SilverlightApplication>
+ <ValidateXaml>true</ValidateXaml>
+ <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+ <ThrowErrorsInValidation>true</ThrowErrorsInValidation>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;NETFX_CORE;WINDOWS_PHONE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\ARM\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+ <OutputPath>bin\ARM\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
+ <ProjectReference Include="..\..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Xamarin.Forms.Platform.WP8\Xamarin.Forms.Platform.WP8.csproj">
+ <Project>{517b6ae0-792b-4665-9376-5ca33e539181}</Project>
+ <Name>Xamarin.Forms.Platform.WP8</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Platform.cs">
+ <Link>Xamarin.Forms.Platform.cs</Link>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '12.0' ">
+ <VisualStudioVersion>12.0</VisualStudioVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(TargetPlatformIdentifier)' == '' ">
+ <TargetPlatformIdentifier>WindowsPhoneApp</TargetPlatformIdentifier>
+ </PropertyGroup>
+ <!--<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />-->
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).$(TargetFrameworkVersion).Overrides.targets" />
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Stubs/Xamarin.Forms.Platform.cs b/Stubs/Xamarin.Forms.Platform.cs
new file mode 100644
index 00000000..5f3de257
--- /dev/null
+++ b/Stubs/Xamarin.Forms.Platform.cs
@@ -0,0 +1,141 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Xamarin.Forms;
+
+#if __ANDROID__
+using Xamarin.Forms.Platform.Android;
+#elif WINDOWS_PHONE || WINDOWS_PHONE_APP
+using Xamarin.Forms.Platform.WinPhone;
+#elif __IOS__
+using Xamarin.Forms.Platform.iOS;
+#endif
+
+namespace Xamarin.Forms.Platform
+{
+ internal static class Loader
+ {
+ internal static void Load ()
+ {
+ }
+ }
+
+#if !WINDOWS_PHONE && !WINDOWS_PHONE_APP
+ [RenderWith(typeof(BoxRenderer))]
+#else
+ [RenderWith (typeof(BoxViewRenderer))]
+#endif
+ internal class _BoxViewRenderer { }
+
+ [RenderWith(typeof(EntryRenderer))]
+ internal class _EntryRenderer { }
+
+ [RenderWith (typeof (EditorRenderer))]
+ internal class _EditorRenderer { }
+
+ [RenderWith (typeof (LabelRenderer))]
+ internal class _LabelRenderer { }
+
+ [RenderWith (typeof (ImageRenderer))]
+ internal class _ImageRenderer { }
+
+ [RenderWith (typeof (ButtonRenderer))]
+ internal class _ButtonRenderer { }
+
+ [RenderWith (typeof (TableViewRenderer))]
+ internal class _TableViewRenderer { }
+
+ [RenderWith (typeof (ListViewRenderer))]
+ internal class _ListViewRenderer { }
+
+ [RenderWith (typeof (CarouselViewRenderer))]
+ internal class _CarouselViewRenderer { }
+
+ [RenderWith (typeof (SliderRenderer))]
+ internal class _SliderRenderer { }
+
+ [RenderWith (typeof (WebViewRenderer))]
+ internal class _WebViewRenderer { }
+
+ [RenderWith (typeof (SearchBarRenderer))]
+ internal class _SearchBarRenderer { }
+
+ [RenderWith (typeof (SwitchRenderer))]
+ internal class _SwitchRenderer { }
+
+ [RenderWith (typeof (DatePickerRenderer))]
+ internal class _DatePickerRenderer { }
+
+ [RenderWith (typeof (TimePickerRenderer))]
+ internal class _TimePickerRenderer { }
+
+ [RenderWith (typeof (PickerRenderer))]
+ internal class _PickerRenderer { }
+
+ [RenderWith (typeof (StepperRenderer))]
+ internal class _StepperRenderer { }
+
+ [RenderWith (typeof (ProgressBarRenderer))]
+ internal class _ProgressBarRenderer { }
+
+ [RenderWith (typeof (ScrollViewRenderer))]
+ internal class _ScrollViewRenderer { }
+
+#if !WINDOWS_PHONE && !WINDOWS_PHONE_APP
+ [RenderWith (typeof (ToolbarRenderer))]
+#else
+ [RenderWith (null)]
+#endif
+ internal class _ToolbarRenderer { }
+
+ [RenderWith (typeof (ActivityIndicatorRenderer))]
+ internal class _ActivityIndicatorRenderer { }
+
+ [RenderWith (typeof (FrameRenderer))]
+ internal class _FrameRenderer { }
+
+#if !WINDOWS_PHONE && !WINDOWS_PHONE_APP
+ [RenderWith (typeof (NavigationMenuRenderer))]
+ internal class _NavigationMenuRenderer { }
+
+ [RenderWith (typeof (OpenGLViewRenderer))]
+#else
+ [RenderWith (null)]
+#endif
+
+ internal class _OpenGLViewRenderer { }
+
+#if !WINDOWS_PHONE && !WINDOWS_PHONE_APP
+ [RenderWith (typeof (TabbedRenderer))]
+#else
+ [RenderWith (typeof (TabbedPageRenderer))]
+#endif
+ internal class _TabbedPageRenderer { }
+
+#if !WINDOWS_PHONE && !WINDOWS_PHONE_APP
+ [RenderWith (typeof (NavigationRenderer))]
+#else
+ [RenderWith (typeof (NavigationPageRenderer))]
+#endif
+ internal class _NavigationPageRenderer { }
+
+ [RenderWith (typeof (CarouselPageRenderer))]
+ internal class _CarouselPageRenderer { }
+
+ [RenderWith (typeof (PageRenderer))]
+ internal class _PageRenderer { }
+
+#if !__IOS__
+ [RenderWith (typeof (MasterDetailRenderer))]
+#else
+ [RenderWith (typeof (PhoneMasterDetailRenderer))]
+#endif
+ internal class _MasterDetailPageRenderer { }
+}
+
+
+
+
+
diff --git a/Stubs/Xamarin.Forms.Platform.iOS.Classic/Properties/AssemblyInfo.cs b/Stubs/Xamarin.Forms.Platform.iOS.Classic/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..43f81582
--- /dev/null
+++ b/Stubs/Xamarin.Forms.Platform.iOS.Classic/Properties/AssemblyInfo.cs
@@ -0,0 +1,37 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle ("Xamarin.Forms.Platform.iOS.Classic")]
+[assembly: AssemblyDescription ("")]
+[assembly: AssemblyConfiguration ("")]
+[assembly: AssemblyCompany ("")]
+[assembly: AssemblyProduct ("Xamarin.Forms.Platform.iOS.Classic")]
+[assembly: AssemblyCopyright ("Copyright © 2015")]
+[assembly: AssemblyTrademark ("")]
+[assembly: AssemblyCulture ("")]
+[assembly: InternalsVisibleTo ("Xamarin.Forms.Core")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible (false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid ("fa4af8a0-f4f1-41b4-a463-a8b5b8fc5b8b")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion ("1.0.0.0")]
+[assembly: AssemblyFileVersion ("1.0.0.0")]
diff --git a/Stubs/Xamarin.Forms.Platform.iOS.Classic/Xamarin.Forms.Platform.iOS.Classic (Forwarders).csproj b/Stubs/Xamarin.Forms.Platform.iOS.Classic/Xamarin.Forms.Platform.iOS.Classic (Forwarders).csproj
new file mode 100644
index 00000000..9f496376
--- /dev/null
+++ b/Stubs/Xamarin.Forms.Platform.iOS.Classic/Xamarin.Forms.Platform.iOS.Classic (Forwarders).csproj
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{3E443AEF-3EC0-48C4-A524-7C6996339E1B}</ProjectGuid>
+ <ProjectTypeGuids>{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <RootNamespace>Xamarin.Forms.Platform</RootNamespace>
+ <IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
+ <AssemblyName>Xamarin.Forms.Platform</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\iPhone\Debug</OutputPath>
+ <DefineConstants>DEBUG</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <MtouchDebug>true</MtouchDebug>
+ <CodesignKey>iPhone Developer</CodesignKey>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\iPhone\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <CodesignKey>iPhone Developer</CodesignKey>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Platform.cs">
+ <Link>Xamarin.Forms.Platform.cs</Link>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Xamarin.Forms.Platform.iOS\Xamarin.Forms.Platform.iOS.Classic.csproj">
+ <Project>{4a47b5df-ddfc-476b-ac41-5105ff3b9b8b}</Project>
+ <Name>Xamarin.Forms.Platform.iOS.Classic</Name>
+ <IsAppExtension>false</IsAppExtension>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Core" />
+ <Reference Include="monotouch" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.MonoTouch.CSharp.targets" />
+</Project> \ No newline at end of file
diff --git a/Stubs/Xamarin.Forms.Platform.iOS/Properties/AssemblyInfo.cs b/Stubs/Xamarin.Forms.Platform.iOS/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..047b72b9
--- /dev/null
+++ b/Stubs/Xamarin.Forms.Platform.iOS/Properties/AssemblyInfo.cs
@@ -0,0 +1,37 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle ("Xamarin.Forms.Platform.iOS")]
+[assembly: AssemblyDescription ("")]
+[assembly: AssemblyConfiguration ("")]
+[assembly: AssemblyCompany ("")]
+[assembly: AssemblyProduct ("Xamarin.Forms.Platform.iOS")]
+[assembly: AssemblyCopyright ("Copyright © 2015")]
+[assembly: AssemblyTrademark ("")]
+[assembly: AssemblyCulture ("")]
+[assembly: InternalsVisibleTo ("Xamarin.Forms.Core")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible (false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid ("d3f9fea6-cce8-4c30-b0d2-197b40c50756")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion ("1.0.0.0")]
+[assembly: AssemblyFileVersion ("1.0.0.0")]
diff --git a/Stubs/Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS (Forwarders).csproj b/Stubs/Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS (Forwarders).csproj
new file mode 100644
index 00000000..7278b40c
--- /dev/null
+++ b/Stubs/Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS (Forwarders).csproj
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{39B3457F-01D8-43D0-8E84-D8C4F73CF48D}</ProjectGuid>
+ <ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <RootNamespace>Xamarin.Forms.Platform</RootNamespace>
+ <IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
+ <AssemblyName>Xamarin.Forms.Platform</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\iPhone\Debug</OutputPath>
+ <DefineConstants>DEBUG</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <MtouchDebug>true</MtouchDebug>
+ <CodesignKey>iPhone Developer</CodesignKey>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\iPhone\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <CodesignKey>iPhone Developer</CodesignKey>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Platform.cs">
+ <Link>Xamarin.Forms.Platform.cs</Link>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Xamarin.Forms.Platform.iOS\Xamarin.Forms.Platform.iOS.csproj">
+ <Project>{271193c1-6e7c-429c-a36d-3f1be5267231}</Project>
+ <Name>Xamarin.Forms.Platform.iOS</Name>
+ <IsAppExtension>false</IsAppExtension>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Core" />
+ <Reference Include="Xamarin.iOS" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Android.UITests/BaseTestFixture.cs b/Xamarin.Forms.Android.UITests/BaseTestFixture.cs
new file mode 100644
index 00000000..6e38f356
--- /dev/null
+++ b/Xamarin.Forms.Android.UITests/BaseTestFixture.cs
@@ -0,0 +1,108 @@
+using System;
+using Xamarin.UITest;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using NUnit.Framework;
+using System.Threading;
+
+namespace Xamarin.Forms.UITests
+{
+ public class BaseTestFixture
+ {
+ string idiomEnvVar;
+ string IPEnvVar;
+
+ public AndroidApp App { get; private set; }
+ public Device Device { get; set; }
+
+ public BaseTestFixture ()
+ {
+ idiomEnvVar = Environment.GetEnvironmentVariable ("DEVICE_IDIOM");
+ IPEnvVar = Environment.GetEnvironmentVariable ("DEVICE_IP");
+
+ Console.WriteLine (string.Format ("****** Connecting to {0} with IP: {1} ********", idiomEnvVar, IPEnvVar));
+
+ Device = SetupDevice (idiomEnvVar, IPEnvVar);
+ }
+
+ [SetUp]
+ public void Setup ()
+ {
+
+ if (string.IsNullOrEmpty (idiomEnvVar) &&
+ string.IsNullOrEmpty (IPEnvVar)) {
+ // Use IDE Configuration
+ App = ConfigureApp
+ .Android
+ .Debug ()
+ .ApkFile ("../../../Xamarin.Forms.ControlGallery.Android/bin/Debug/AndroidControlGallery.AndroidControlGallery-Signed.apk")
+ .StartApp ();
+ } else {
+ // Use CI Configuration
+ App = ConfigureApp
+ .Android
+ .DeviceIp (Device.IP)
+ .ApkFile ("../../../Xamarin.Forms.ControlGallery.Android/bin/Debug/AndroidControlGallery.AndroidControlGallery-Signed.apk")
+ .StartApp ();
+ }
+
+ FixtureSetup ();
+ }
+
+ protected virtual void FixtureSetup ()
+ {
+ App.SetOrientationPortrait ();
+ App.Screenshot ("Begin test");
+ }
+
+ Device SetupDevice (string idiomEnvVar, string IPEnvVar)
+ {
+ Device device;
+
+ if (idiomEnvVar == "PHONE") {
+
+ // default phone
+ device = new Device (DeviceType.Phone, "10.0.1.161");
+
+ if (!string.IsNullOrEmpty (IPEnvVar))
+ device.IP = IPEnvVar;
+
+ } else if (idiomEnvVar == "TABLET") {
+
+ // default tablet
+ device = new Device (DeviceType.Tablet, "10.0.1.42");
+
+ if (!string.IsNullOrEmpty (IPEnvVar))
+ device.IP = IPEnvVar;
+
+ } else {
+
+ // default phone
+ device = new Device (DeviceType.Phone, "10.0.1.161");
+
+ }
+
+ return device;
+ }
+
+ }
+
+ public static class PlatformStrings
+ {
+ public static string Button = "Button";
+ public static string Cell = "xamarin.forms.platform.android.ViewCellRenderer_ViewCellContainer";
+ public static string HomePageTitle = "Android Controls";
+ public static string Label = "TextView";
+ public static string Entry = "EditText";
+ public static string Placeholder = "hint";
+ public static string Text = "text";
+ }
+
+ public static class PlatformValues
+ {
+ public static int BoxViewScreenNumber = 4;
+ public static int KeyboardDismissY = 500;
+ public static int OffsetForScrollView = -5;
+ }
+}
+
diff --git a/Xamarin.Forms.Android.UITests/Makefile b/Xamarin.Forms.Android.UITests/Makefile
new file mode 100644
index 00000000..87c3be60
--- /dev/null
+++ b/Xamarin.Forms.Android.UITests/Makefile
@@ -0,0 +1,15 @@
+console:
+ calabash-android console ../Xamarin.Forms.ControlGallery.Android/bin/Debug/AndroidControlGallery.AndroidControlGallery-Signed.apk
+
+testcloud:
+ mono xut-console.exe submit --assembly-dir ../Xamarin.Forms.Android.UITests/bin/debug ../Xamarin.Forms.ControlGallery.Android/bin/Release/AndroidControlGallery.AndroidControlGallery-Signed.apk 1a02b2e1ee5a2895e47da095cc895a49 7a47b813
+
+run-phone-android:
+ DEVICE_IDIOM=PHONE DEVICE_ID=9adaaf78 DEVICE_IP=192.168.1.144 mono ../packages/NUnit.Runners.2.6.3/tools/nunit-console-x86.exe -result=galaxy-results.xml bin/Debug/Xamarin.Forms.Android.UITests.dll
+
+run-parallel-android:
+ DEVICE_IDIOM=TABLET mono ../packages/NUnit.Runners.2.6.3/tools/nunit-console-x86.exe -result=nexus-results.xml bin/Debug/Xamarin.Forms.Android.UITests.dll --include "CITest" &
+ DEVICE_IDIOM=PHONE mono ../packages/NUnit.Runners.2.6.3/tools/nunit-console-x86.exe -result=galaxy-results.xml bin/Debug/Xamarin.Forms.Android.UITests.dll --include "CITest"
+
+clean:
+ rm -rf screenshot_* test_servers/ .irb-history nexus-results.xml galaxy-results.xml
diff --git a/Xamarin.Forms.Android.UITests/PlatformHelpers.cs b/Xamarin.Forms.Android.UITests/PlatformHelpers.cs
new file mode 100644
index 00000000..6021f2a2
--- /dev/null
+++ b/Xamarin.Forms.Android.UITests/PlatformHelpers.cs
@@ -0,0 +1,132 @@
+using System;
+using Xamarin.UITest;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using NUnit.Framework;
+using System.Threading;
+
+namespace Xamarin.Forms.UITests
+{
+
+ public static class PlatformHelpers
+ {
+
+ public static string GetTextForQuery (this IApp app, Func<AppQuery, AppQuery> query)
+ {
+ AppResult[] elements = app.Query (query);
+ if (elements.Length > 1) {
+ // Test cloud doesn't support Assert.Fail
+ Assert.False (true, "Query returned more than one result");
+ }
+ return elements [0].Text;
+ }
+
+ public static bool ScrollDownForElement (this IApp app, Func<AppQuery, AppQuery> query, int scrollNumberLimit)
+ {
+ // Check if element exists before scrolling
+ if (app.Query (query).Length > 0)
+ return true;
+
+ int scrollNumber = 0;
+ while (app.Query (query).Length == 0) {
+ app.ScrollDown ();
+ scrollNumber++;
+ if (scrollNumber > scrollNumberLimit)
+ return false;
+ }
+
+ return true;
+ }
+
+ public static bool ScrollUpForElement (this IApp app, Func<AppQuery, AppQuery> query, int scrollNumberLimit)
+ {
+ int scrollNumber = 0;
+ while (app.Query (query).Length == 0) {
+ app.ScrollUp ();
+ scrollNumber++;
+ if (scrollNumber > scrollNumberLimit)
+ return false;
+ }
+
+ return true;
+ }
+
+ public static bool DragFromToForElement (this AndroidApp app, int scrollNumberLimit, Func<AppQuery, AppQuery> query, float xStart, float yStart, float xEnd, float yEnd)
+ {
+ int numberOfScrolls = 0;
+ // Element exists
+ if (app.Query (query).Length > 0)
+ return true;
+
+ while (app.Query (query).Length == 0) {
+ DragFromTo (app, xStart, yStart, xEnd, yEnd);
+ if (numberOfScrolls > scrollNumberLimit) {
+ return false;
+ }
+ numberOfScrolls++;
+ }
+ // Element found
+ return true;
+ }
+
+ public static void SwipeBackNavigation (this AndroidApp app)
+ {
+ // Do nothing on Android
+ }
+
+ public static void DragFromTo (this AndroidApp app, float xStart, float yStart, float xEnd, float yEnd, Speed speed = Speed.Fast)
+ {
+ // No effect on Android
+ app.DragCoordinates (xStart, yStart, xEnd, yEnd);
+ }
+
+ public static void KeyboardIsPresent (this AndroidApp app)
+ {
+ // TODO : Add keyboard detection
+// Thread.Sleep (1000);
+//
+// AppRect screenSize = app.MainScreenBounds ();
+// AppRect contentBounds = app.Query (q => q.Raw ("*").Id ("content"))[0].Rect;
+//
+// bool keyboardIsShown = false;
+// if ((screenSize.Height - contentBounds.Height) > (screenSize.Height / 4)) {
+// // Determine if keyboard is showing by seeing if content size is shrunk by over 1/4 of screens size
+// keyboardIsShown = true;
+// }
+//
+// Assert.IsTrue (keyboardIsShown, "Keyboard should be shown");
+ Assert.Inconclusive ("Keyboard should be shown");
+ }
+
+ public static void KeyboardIsDismissed (this AndroidApp app)
+ {
+ // TODO : Add keyboard detection
+// AppRect screenSize = app.MainScreenBounds ();
+// AppRect contentBounds = app.Query (q => q.Raw ("*").Id ("content"))[0].Rect;
+//
+// bool keyboardIsShown = false;
+// if ((screenSize.Height - contentBounds.Height) > (screenSize.Height / 4)) {
+// // Determine if keyboard is showing by seeing if content size is shrunk by over 1/4 of screens size
+// keyboardIsShown = true;
+// }
+//
+// Assert.IsFalse (keyboardIsShown, "Keyboard should be dismissed");
+ Assert.Inconclusive ("Keyboard should be dismissed");
+ }
+
+ public static int IndexForElementWithText (this AndroidApp app, Func<AppQuery, AppQuery> query, string text)
+ {
+ var elements = app.Query (query);
+ int index = 0;
+ for (int i = 0; i < elements.Length; i++) {
+ string labelText = elements[i].Text;
+ if (labelText == (text)) {
+ index = i;
+ break;
+ }
+ index++;
+ }
+ return index == elements.Length ? -1 : index;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Android.UITests/PlatformQueries.cs b/Xamarin.Forms.Android.UITests/PlatformQueries.cs
new file mode 100644
index 00000000..0b826949
--- /dev/null
+++ b/Xamarin.Forms.Android.UITests/PlatformQueries.cs
@@ -0,0 +1,111 @@
+using System;
+using Xamarin.UITest;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using NUnit.Framework;
+using System.Threading;
+
+namespace Xamarin.Forms.UITests
+{
+ public class iOSUiTestType
+ {
+ public iOSUiTestType ()
+ {
+
+ }
+ }
+
+ public static class PlatformQueries
+ {
+ public static Func<AppQuery, AppQuery> AbsoluteGalleryBackground = q => q.Raw ("xamarin.forms.platform.android.BoxRenderer parent xamarin.forms.platform.android.RendererFactory_DefaultRenderer index:0");
+ public static Func<AppQuery, AppQuery> ActivityIndicators = q => q.Raw ("ProgressBar");
+ public static Func<AppQuery, AppQuery> Back = q => q.Id ("up");
+ public static Func<AppQuery, AppQuery> BoxRendererQuery = q => q.Raw ("xamarin.forms.platform.android.BoxRenderer");
+ public static Func<AppQuery, AppQuery> Cells = q => q.Raw ("xamarin.forms.platform.android.ViewCellRenderer_ViewCellContainer");
+ public static Func<AppQuery, AppQuery> DismissPickerCustom = q => q.Marked ("OK");
+ public static Func<AppQuery, AppQuery> DismissPickerNormal = q => q.Marked ("Done");
+ public static Func<AppQuery, AppQuery> Entrys = q => q.Raw ("EntryEditText");
+ public static Func<AppQuery, AppQuery> EntryCells = q => q.Raw ("EntryCellEditText");
+ public static Func<AppQuery, AppQuery> Editors = q => q.Raw ("EditorEditText");
+ public static Func<AppQuery, AppQuery> Frames = q => q.Raw ("FrameRenderer");
+ public static Func<AppQuery, AppQuery> Images = q => q.Raw ("xamarin.forms.platform.android.ImageRenderer");
+ public static Func<AppQuery, AppQuery> ImageView = q => q.Raw("ImageView");
+ public static Func<AppQuery, AppQuery> LabelRenderers = q => q.Raw ("LabelRenderer");
+ public static Func<AppQuery, AppQuery> List = q => q.Raw ("ListView");
+ public static Func<AppQuery, AppQuery> Labels = q => q.Raw ("TextView");
+ public static Func<AppQuery, AppQuery> Map = q => q.Raw ("MapView");
+ public static Func<AppQuery, AppQuery> NumberPicker = q => q.Raw ("NumberPicker");
+ public static Func<AppQuery, AppQuery> ProgressBar = q => q.Raw ("ProgressBar");
+ public static Func<AppQuery, AppQuery> Tables = q => q.Raw ("ListView");
+ public static Func<AppQuery, AppQuery> SearchBars = q => q.Raw ("SearchView");
+ public static Func<AppQuery, AppQuery> Sliders = q => q.Raw ("SeekBar");
+ public static Func<AppQuery, AppQuery> SpanningThreeRows = q => q.Marked ("Spanning 3 rows");
+ public static Func<AppQuery, AppQuery> Steppers = q => q.Raw ("button marked:'+'");
+ public static Func<AppQuery, AppQuery> Switch = q => q.Raw("Switch");
+ public static Func<AppQuery, AppQuery> ThreeXThreeGridCell = q => q.Marked ("a block 3x3");
+
+ public static Func<AppQuery, AppQuery> EntryWithPlaceholder (string text) {
+ return q => q.Raw (string.Format ("EntryEditText hint:'{0}'", text));
+ }
+ public static Func<AppQuery, AppQuery> EntryCellWithPlaceholder (string text) {
+ return q => q.Raw (string.Format ("EntryCellEditText hint:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryWithText (string text) {
+ return q => q.Raw (string.Format ("EntryEditText text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryCellWithText (string text) {
+ return q => q.Raw (string.Format ("EntryCellEditText text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EditorsWithText (string text) {
+ return q => q.Raw (string.Format ("EditorEditText text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryWithIndex (int index) {
+ return q => q.Raw (string.Format ("EntryEditText index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> SearchBarWithIndex (int index) {
+ return q => q.Raw (string.Format ("SearchView index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> LabelWithIndex (int index) {
+ return q => q.Raw (string.Format ("TextView index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> LabelWithText (string text) {
+ return q => q.Raw (string.Format ("TextView text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> LabelWithId (string id) {
+ return q => q.Raw (string.Format ("TextView id:'{0}'", id));
+ }
+
+ public static Func<AppQuery, AppQuery> PickerEntryWithIndex (int index) {
+ return q => q.Raw (string.Format ("EditText index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> PickerEntryWithPlaceholder (string placeholder) {
+ return q => q.Raw (string.Format ("EditText hint:'{0}'", placeholder));
+ }
+
+ public static Func<AppQuery, AppQuery> PickerEntryWithText (string text) {
+ return q => q.Raw (string.Format ("EditText text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> SwitchWithIndex (int index) {
+ return q => q.Raw (string.Format ("Switch index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> StepperWithIndex (int index) {
+ return q => q.Raw (string.Format ("button marked:'+' index:{0}", index));
+ }
+
+ public static AppResult DetailPage (this AndroidApp app)
+ {
+ return app.Query (q => q.Raw ("*"))[0];
+ }
+ }
+}
diff --git a/Xamarin.Forms.Android.UITests/Properties/AssemblyInfo.cs b/Xamarin.Forms.Android.UITests/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..99b6aa63
--- /dev/null
+++ b/Xamarin.Forms.Android.UITests/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Xamarin.Forms.Android.UITest")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Forms.Android.UITest")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("fd80e73b-7225-40ce-b38d-350c5487a0df")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Xamarin.Forms.Android.UITests/Xamarin.Forms.Android.UITests.csproj b/Xamarin.Forms.Android.UITests/Xamarin.Forms.Android.UITests.csproj
new file mode 100644
index 00000000..5c1b991b
--- /dev/null
+++ b/Xamarin.Forms.Android.UITests/Xamarin.Forms.Android.UITests.csproj
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{D290FCBE-3196-452B-B84C-B62BF9B54F2A}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Android.UITest</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Android.UITests</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="nunit.framework">
+ <HintPath>..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ <Reference Include="Xamarin.UITest">
+ <HintPath>..\packages\Xamarin.UITest.0.4.1\lib\Xamarin.UITest.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="BaseTestFixture.cs" />
+ <Compile Include="..\Xamarin.Forms.iOS.UITests\TestHelpers.cs">
+ <Link>TestHelpers.cs</Link>
+ </Compile>
+ <Compile Include="PlatformQueries.cs" />
+ <Compile Include="PlatformHelpers.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ <Compile Include="..\Xamarin.Forms.iOS.UITests\Device.cs">
+ <Link>Device.cs</Link>
+ </Compile>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+ </Target>
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Android.UITests/packages.config b/Xamarin.Forms.Android.UITests/packages.config
new file mode 100644
index 00000000..cd848561
--- /dev/null
+++ b/Xamarin.Forms.Android.UITests/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit" version="2.6.3" targetFramework="net45" />
+ <package id="Xamarin.UITest" version="0.4.1" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.Android.UITests/testcloudupload.bat b/Xamarin.Forms.Android.UITests/testcloudupload.bat
new file mode 100644
index 00000000..1afa4cff
--- /dev/null
+++ b/Xamarin.Forms.Android.UITests/testcloudupload.bat
@@ -0,0 +1 @@
+xut-console.exe submit --assembly-dir ..\Xamarin.Forms.Android.UITests\bin\debug ..\Xamarin.Forms.ControlGallery.Android\bin\Release\AndroidControlGallery.AndroidControlGallery-Signed.apk 1a02b2e1ee5a2895e47da095cc895a49 6bbba6ec
diff --git a/Xamarin.Forms.Build.Tasks/CreateObjectVisitor.cs b/Xamarin.Forms.Build.Tasks/CreateObjectVisitor.cs
new file mode 100644
index 00000000..0dabb5d9
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/CreateObjectVisitor.cs
@@ -0,0 +1,544 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ class CreateObjectVisitor : IXamlNodeVisitor
+ {
+ public CreateObjectVisitor(ILContext context)
+ {
+ Context = context;
+ Module = context.Body.Method.Module;
+ }
+
+ public ILContext Context { get; }
+
+ ModuleDefinition Module { get; }
+
+ public bool VisitChildrenFirst
+ {
+ get { return true; }
+ }
+
+ public bool StopOnDataTemplate
+ {
+ get { return true; }
+ }
+
+ public bool StopOnResourceDictionary
+ {
+ get { return false; }
+ }
+
+ public void Visit(ValueNode node, INode parentNode)
+ {
+ Context.Values[node] = node.Value;
+
+ XmlName propertyName;
+ if (SetPropertiesVisitor.TryGetPropertyName(node, parentNode, out propertyName))
+ {
+ if (propertyName.NamespaceURI == "http://schemas.openxmlformats.org/markup-compatibility/2006" &&
+ propertyName.LocalName == "Ignorable")
+ {
+ (parentNode.IgnorablePrefixes ?? (parentNode.IgnorablePrefixes = new List<string>())).AddRange(
+ (node.Value as string).Split(','));
+ }
+ }
+ }
+
+ public void Visit(MarkupNode node, INode parentNode)
+ {
+ //At this point, all MarkupNodes are expanded to ElementNodes
+ }
+
+ public void Visit(ElementNode node, INode parentNode)
+ {
+ if (node.SkipPrefix((node.NamespaceResolver ?? parentNode.NamespaceResolver).LookupPrefix(node.NamespaceURI)))
+ return;
+
+ var typeref = node.XmlType.GetTypeReference(Module, node);
+ TypeDefinition typedef = typeref.Resolve();
+
+ if (IsXaml2009LanguagePrimitive(node))
+ {
+ var vardef = new VariableDefinition(typeref);
+ Context.Variables[node] = vardef;
+ Context.Body.Variables.Add(vardef);
+
+ Context.IL.Append(PushValueFromLanguagePrimitive(typedef, node));
+ Context.IL.Emit(OpCodes.Stloc, vardef);
+ }
+ else
+ {
+ MethodDefinition factoryCtorInfo = null;
+ MethodDefinition factoryMethodInfo = null;
+ MethodDefinition parameterizedCtorInfo = null;
+ MethodDefinition ctorInfo = null;
+
+ if (node.Properties.ContainsKey(XmlName.xArguments) && !node.Properties.ContainsKey(XmlName.xFactoryMethod))
+ {
+ factoryCtorInfo = typedef.AllMethods().FirstOrDefault(md => md.IsConstructor &&
+ !md.IsStatic &&
+ md.HasParameters &&
+ md.MatchXArguments(node, Module));
+ if (factoryCtorInfo == null)
+ {
+ throw new XamlParseException(
+ string.Format("No constructors found for {0} with matching x:Arguments", typedef.FullName), node);
+ }
+ ctorInfo = factoryCtorInfo;
+ if (!typedef.IsValueType) //for ctor'ing typedefs, we first have to ldloca before the params
+ Context.IL.Append(PushCtorXArguments(factoryCtorInfo, node));
+ }
+ else if (node.Properties.ContainsKey(XmlName.xFactoryMethod))
+ {
+ var factoryMethod = (string)(node.Properties[XmlName.xFactoryMethod] as ValueNode).Value;
+ factoryMethodInfo = typedef.AllMethods().FirstOrDefault(md => !md.IsConstructor &&
+ md.Name == factoryMethod &&
+ md.IsStatic &&
+ md.MatchXArguments(node, Module));
+ if (factoryMethodInfo == null)
+ {
+ throw new XamlParseException(
+ String.Format("No static method found for {0}::{1} ({2})", typedef.FullName, factoryMethod, null), node);
+ }
+ Context.IL.Append(PushCtorXArguments(factoryMethodInfo, node));
+ }
+ if (ctorInfo == null && factoryMethodInfo == null)
+ {
+ parameterizedCtorInfo = typedef.Methods.FirstOrDefault(md => md.IsConstructor &&
+ !md.IsStatic &&
+ md.HasParameters &&
+ md.Parameters.All(
+ pd =>
+ pd.CustomAttributes.Any(
+ ca =>
+ ca.AttributeType.FullName ==
+ "Xamarin.Forms.ParameterAttribute")));
+ }
+ if (parameterizedCtorInfo != null && ValidateCtorArguments(parameterizedCtorInfo, node))
+ {
+ ctorInfo = parameterizedCtorInfo;
+ // IL_0000: ldstr "foo"
+ Context.IL.Append(PushCtorArguments(parameterizedCtorInfo, node));
+ }
+ ctorInfo = ctorInfo ?? typedef.Methods.FirstOrDefault(md => md.IsConstructor && !md.HasParameters && !md.IsStatic);
+
+ var ctorinforef = ctorInfo?.ResolveGenericParameters(typeref, Module);
+ var factorymethodinforef = factoryMethodInfo?.ResolveGenericParameters(typeref, Module);
+ var implicitOperatorref = typedef.Methods.FirstOrDefault(md =>
+ md.IsPublic &&
+ md.IsStatic &&
+ md.IsSpecialName &&
+ md.Name == "op_Implicit" && md.Parameters[0].ParameterType.FullName == "System.String");
+
+ if (ctorinforef != null || factorymethodinforef != null || typedef.IsValueType)
+ {
+ VariableDefinition vardef = new VariableDefinition(typeref);
+ Context.Variables[node] = vardef;
+ Context.Body.Variables.Add(vardef);
+
+ ValueNode vnode = null;
+ if (node.CollectionItems.Count == 1 && (vnode = node.CollectionItems.First() as ValueNode) != null &&
+ vardef.VariableType.IsValueType)
+ {
+ //<Color>Purple</Color>
+ Context.IL.Append(vnode.PushConvertedValue(Context, typeref, new ICustomAttributeProvider[] { typedef },
+ node.PushServiceProvider(Context), false, true));
+ Context.IL.Emit(OpCodes.Stloc, vardef);
+ }
+ else if (node.CollectionItems.Count == 1 && (vnode = node.CollectionItems.First() as ValueNode) != null &&
+ implicitOperatorref != null)
+ {
+ //<FileImageSource>path.png</FileImageSource>
+ var implicitOperator = Module.Import(implicitOperatorref);
+ Context.IL.Emit(OpCodes.Ldstr, ((ValueNode)(node.CollectionItems.First())).Value as string);
+ Context.IL.Emit(OpCodes.Call, implicitOperator);
+ Context.IL.Emit(OpCodes.Stloc, vardef);
+ }
+ else if (factorymethodinforef != null)
+ {
+ var factory = Module.Import(factorymethodinforef);
+ Context.IL.Emit(OpCodes.Call, factory);
+ Context.IL.Emit(OpCodes.Stloc, vardef);
+ }
+ else if (!typedef.IsValueType)
+ {
+ var ctor = Module.Import(ctorinforef);
+ // IL_0001: newobj instance void class [Xamarin.Forms.Core]Xamarin.Forms.Button::'.ctor'()
+ // IL_0006: stloc.0
+ Context.IL.Emit(OpCodes.Newobj, ctor);
+ Context.IL.Emit(OpCodes.Stloc, vardef);
+ }
+ else if (ctorInfo != null && node.Properties.ContainsKey(XmlName.xArguments) &&
+ !node.Properties.ContainsKey(XmlName.xFactoryMethod) && ctorInfo.MatchXArguments(node, Module))
+ {
+ // IL_0008: ldloca.s 1
+ // IL_000a: ldc.i4.1
+ // IL_000b: call instance void valuetype Test/Foo::'.ctor'(bool)
+
+ var ctor = Module.Import(ctorinforef);
+ Context.IL.Emit(OpCodes.Ldloca, vardef);
+ Context.IL.Append(PushCtorXArguments(factoryCtorInfo, node));
+ Context.IL.Emit(OpCodes.Call, ctor);
+ }
+ else
+ {
+ // IL_0000: ldloca.s 0
+ // IL_0002: initobj Test/Foo
+ Context.IL.Emit(OpCodes.Ldloca, vardef);
+ Context.IL.Emit(OpCodes.Initobj, Module.Import(typedef));
+ }
+
+ if (typeref.FullName == "Xamarin.Forms.Xaml.TypeExtension")
+ {
+ var visitor = new SetPropertiesVisitor(Context);
+ foreach (var cnode in node.Properties.Values.ToList())
+ cnode.Accept(visitor, node);
+ foreach (var cnode in node.CollectionItems)
+ cnode.Accept(visitor, node);
+
+ //As we're stripping the TypeExtension bare, keep the type if we need it later (hint: we do need it)
+ INode ntype;
+ if (!node.Properties.TryGetValue(new XmlName("", "TypeName"), out ntype))
+ ntype = node.CollectionItems[0];
+
+ var type = ((ValueNode)ntype).Value as string;
+ var namespaceuri = type.Contains(":") ? node.NamespaceResolver.LookupNamespace(type.Split(':')[0].Trim()) : "";
+ type = type.Contains(":") ? type.Split(':')[1].Trim() : type;
+ Context.TypeExtensions[node] = new XmlType(namespaceuri, type, null).GetTypeReference(Module, node);
+
+ node.Properties.Clear();
+ node.CollectionItems.Clear();
+
+ var vardefref = new VariableDefinitionReference(vardef);
+ Context.IL.Append(SetPropertiesVisitor.ProvideValue(vardefref, Context, Module, node));
+ if (vardef != vardefref.VariableDefinition)
+ {
+ Context.Variables[node] = vardefref.VariableDefinition;
+ Context.Body.Variables.Add(vardefref.VariableDefinition);
+ }
+ }
+ }
+ }
+ }
+
+ public void Visit(RootNode node, INode parentNode)
+ {
+ // IL_0013: ldarg.0
+ // IL_0014: stloc.3
+
+ var ilnode = (ILRootNode)node;
+ var typeref = ilnode.TypeReference;
+ var vardef = new VariableDefinition(typeref);
+ Context.Variables[node] = vardef;
+ Context.Root = vardef;
+ Context.Body.Variables.Add(vardef);
+ Context.IL.Emit(OpCodes.Ldarg_0);
+ Context.IL.Emit(OpCodes.Stloc, vardef);
+ }
+
+ public void Visit(ListNode node, INode parentNode)
+ {
+ XmlName name;
+ if (SetPropertiesVisitor.TryGetPropertyName(node, parentNode, out name))
+ node.XmlName = name;
+ }
+
+ bool ValidateCtorArguments(MethodDefinition ctorinfo, ElementNode enode)
+ {
+ foreach (var parameter in ctorinfo.Parameters)
+ {
+ var propname =
+ parameter.CustomAttributes.First(ca => ca.AttributeType.FullName == "Xamarin.Forms.ParameterAttribute")
+ .ConstructorArguments.First()
+ .Value as string;
+ if (!enode.Properties.ContainsKey(new XmlName("", propname)))
+ return false;
+ }
+ return true;
+ }
+
+ IEnumerable<Instruction> PushCtorArguments(MethodDefinition ctorinfo, ElementNode enode)
+ {
+ foreach (var parameter in ctorinfo.Parameters)
+ {
+ var propname =
+ parameter.CustomAttributes.First(ca => ca.AttributeType.FullName == "Xamarin.Forms.ParameterAttribute")
+ .ConstructorArguments.First()
+ .Value as string;
+ var node = enode.Properties[new XmlName("", propname)];
+ enode.Properties.Remove(new XmlName("", propname));
+ VariableDefinition vardef;
+ ValueNode vnode = null;
+
+ if (node is IElementNode && (vardef = Context.Variables[node as IElementNode]) != null)
+ yield return Instruction.Create(OpCodes.Ldloc, vardef);
+ else if ((vnode = node as ValueNode) != null)
+ {
+ foreach (var instruction in vnode.PushConvertedValue(Context,
+ parameter.ParameterType,
+ new ICustomAttributeProvider[] { parameter, parameter.ParameterType.Resolve() },
+ enode.PushServiceProvider(Context), false, true))
+ yield return instruction;
+ }
+ }
+ }
+
+ IEnumerable<Instruction> PushCtorXArguments(MethodDefinition factoryCtorInfo, ElementNode enode)
+ {
+ if (!enode.Properties.ContainsKey(XmlName.xArguments))
+ yield break;
+
+ var arguments = new List<INode>();
+ var node = enode.Properties[XmlName.xArguments] as ElementNode;
+ if (node != null)
+ arguments.Add(node);
+ var list = enode.Properties[XmlName.xArguments] as ListNode;
+ if (list != null)
+ {
+ foreach (var n in list.CollectionItems)
+ arguments.Add(n);
+ }
+
+ for (var i = 0; i < factoryCtorInfo.Parameters.Count; i++)
+ {
+ var parameter = factoryCtorInfo.Parameters[i];
+ var arg = arguments[i];
+ VariableDefinition vardef;
+ ValueNode vnode = null;
+
+ if (arg is IElementNode && (vardef = Context.Variables[arg as IElementNode]) != null)
+ yield return Instruction.Create(OpCodes.Ldloc, vardef);
+ else if ((vnode = arg as ValueNode) != null)
+ {
+ foreach (var instruction in vnode.PushConvertedValue(Context,
+ parameter.ParameterType,
+ new ICustomAttributeProvider[] { parameter, parameter.ParameterType.Resolve() },
+ enode.PushServiceProvider(Context), false, true))
+ yield return instruction;
+ }
+ }
+ }
+
+ static bool IsXaml2009LanguagePrimitive(IElementNode node)
+ {
+ if (node.NamespaceURI == "http://schemas.microsoft.com/winfx/2009/xaml")
+ return true;
+ if (node.NamespaceURI != "clr-namespace:System;assembly=mscorlib")
+ return false;
+ var name = node.XmlType.Name.Split(':')[1];
+ if (name == "Boolean" ||
+ name == "String" ||
+ name == "Char" ||
+ name == "Decimal" ||
+ name == "Single" ||
+ name == "Double" ||
+ name == "Byte" ||
+ name == "Int16" ||
+ name == "Int32" ||
+ name == "Int64" ||
+ name == "TimeSpan" ||
+ name == "Uri")
+ return true;
+ return false;
+ }
+
+ IEnumerable<Instruction> PushValueFromLanguagePrimitive(TypeDefinition typedef, ElementNode node)
+ {
+ var hasValue = node.CollectionItems.Count == 1 && node.CollectionItems[0] is ValueNode &&
+ ((ValueNode)node.CollectionItems[0]).Value is string;
+ var valueString = hasValue ? ((ValueNode)node.CollectionItems[0]).Value as string : string.Empty;
+ switch (typedef.FullName)
+ {
+ case "System.Boolean":
+ bool outbool;
+ if (hasValue && bool.TryParse(valueString, out outbool))
+ yield return Instruction.Create(outbool ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
+ else
+ yield return Instruction.Create(OpCodes.Ldc_I4_0);
+ break;
+ case "System.String":
+ yield return Instruction.Create(OpCodes.Ldstr, valueString);
+ break;
+ case "System.Object":
+ var ctorinfo =
+ Context.Body.Method.Module.TypeSystem.Object.Resolve()
+ .Methods.FirstOrDefault(md => md.IsConstructor && !md.HasParameters);
+ var ctor = Context.Body.Method.Module.Import(ctorinfo);
+ yield return Instruction.Create(OpCodes.Newobj, ctor);
+ break;
+ case "System.Char":
+ char outchar;
+ if (hasValue && char.TryParse(valueString, out outchar))
+ yield return Instruction.Create(OpCodes.Ldc_I4, outchar);
+ else
+ yield return Instruction.Create(OpCodes.Ldc_I4, 0x00);
+ break;
+ case "System.Decimal":
+ decimal outdecimal;
+ if (hasValue && decimal.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outdecimal))
+ {
+ var vardef = new VariableDefinition(Context.Body.Method.Module.Import(typeof (decimal)));
+ Context.Body.Variables.Add(vardef);
+ //Use an extra temp var so we can push the value to the stack, just like other cases
+ // IL_0003: ldstr "adecimal"
+ // IL_0008: ldc.i4.s 0x6f
+ // IL_000a: call class [mscorlib]System.Globalization.CultureInfo class [mscorlib]System.Globalization.CultureInfo::get_InvariantCulture()
+ // IL_000f: ldloca.s 0
+ // IL_0011: call bool valuetype [mscorlib]System.Decimal::TryParse(string, valuetype [mscorlib]System.Globalization.NumberStyles, class [mscorlib]System.IFormatProvider, [out] valuetype [mscorlib]System.Decimal&)
+ // IL_0016: pop
+ yield return Instruction.Create(OpCodes.Ldstr, valueString);
+ yield return Instruction.Create(OpCodes.Ldc_I4, 0x6f); //NumberStyles.Number
+ var getInvariantInfo =
+ Context.Body.Method.Module.Import(typeof (CultureInfo))
+ .Resolve()
+ .Properties.FirstOrDefault(pd => pd.Name == "InvariantCulture")
+ .GetMethod;
+ var getInvariant = Context.Body.Method.Module.Import(getInvariantInfo);
+ yield return Instruction.Create(OpCodes.Call, getInvariant);
+ yield return Instruction.Create(OpCodes.Ldloca, vardef);
+ var tryParseInfo =
+ Context.Body.Method.Module.Import(typeof (decimal))
+ .Resolve()
+ .Methods.FirstOrDefault(md => md.Name == "TryParse" && md.Parameters.Count == 4);
+ var tryParse = Context.Body.Method.Module.Import(tryParseInfo);
+ yield return Instruction.Create(OpCodes.Call, tryParse);
+ yield return Instruction.Create(OpCodes.Pop);
+ yield return Instruction.Create(OpCodes.Ldloc, vardef);
+ }
+ else
+ {
+ yield return Instruction.Create(OpCodes.Ldc_I4_0);
+ var decimalctorinfo =
+ Context.Body.Method.Module.Import(typeof (decimal))
+ .Resolve()
+ .Methods.FirstOrDefault(
+ md => md.IsConstructor && md.Parameters.Count == 1 && md.Parameters[0].ParameterType.FullName == "System.Int32");
+ var decimalctor = Context.Body.Method.Module.Import(decimalctorinfo);
+ yield return Instruction.Create(OpCodes.Newobj, decimalctor);
+ }
+ break;
+ case "System.Single":
+ float outfloat;
+ if (hasValue && float.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outfloat))
+ yield return Instruction.Create(OpCodes.Ldc_R4, outfloat);
+ else
+ yield return Instruction.Create(OpCodes.Ldc_R4, 0f);
+ break;
+ case "System.Double":
+ double outdouble;
+ if (hasValue && double.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outdouble))
+ yield return Instruction.Create(OpCodes.Ldc_R8, outdouble);
+ else
+ yield return Instruction.Create(OpCodes.Ldc_R8, 0d);
+ break;
+ case "System.Byte":
+ byte outbyte;
+ if (hasValue && byte.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outbyte))
+ yield return Instruction.Create(OpCodes.Ldc_I4, (int)outbyte);
+ else
+ yield return Instruction.Create(OpCodes.Ldc_I4, 0x00);
+ break;
+ case "System.Int16":
+ short outshort;
+ if (hasValue && short.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outshort))
+ yield return Instruction.Create(OpCodes.Ldc_I4, outshort);
+ else
+ yield return Instruction.Create(OpCodes.Ldc_I4, 0x00);
+ break;
+ case "System.Int32":
+ int outint;
+ if (hasValue && int.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outint))
+ yield return Instruction.Create(OpCodes.Ldc_I4, outint);
+ else
+ yield return Instruction.Create(OpCodes.Ldc_I4, 0x00);
+ break;
+ case "System.Int64":
+ long outlong;
+ if (hasValue && long.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outlong))
+ yield return Instruction.Create(OpCodes.Ldc_I8, outlong);
+ else
+ yield return Instruction.Create(OpCodes.Ldc_I8, 0L);
+ break;
+ case "System.TimeSpan":
+ TimeSpan outspan;
+ if (hasValue && TimeSpan.TryParse(valueString, CultureInfo.InvariantCulture, out outspan))
+ {
+ var vardef = new VariableDefinition(Context.Body.Method.Module.Import(typeof (TimeSpan)));
+ Context.Body.Variables.Add(vardef);
+ //Use an extra temp var so we can push the value to the stack, just like other cases
+ yield return Instruction.Create(OpCodes.Ldstr, valueString);
+ var getInvariantInfo =
+ Context.Body.Method.Module.Import(typeof (CultureInfo))
+ .Resolve()
+ .Properties.FirstOrDefault(pd => pd.Name == "InvariantCulture")
+ .GetMethod;
+ var getInvariant = Context.Body.Method.Module.Import(getInvariantInfo);
+ yield return Instruction.Create(OpCodes.Call, getInvariant);
+ yield return Instruction.Create(OpCodes.Ldloca, vardef);
+ var tryParseInfo =
+ Context.Body.Method.Module.Import(typeof (TimeSpan))
+ .Resolve()
+ .Methods.FirstOrDefault(md => md.Name == "TryParse" && md.Parameters.Count == 3);
+ var tryParse = Context.Body.Method.Module.Import(tryParseInfo);
+ yield return Instruction.Create(OpCodes.Call, tryParse);
+ yield return Instruction.Create(OpCodes.Pop);
+ yield return Instruction.Create(OpCodes.Ldloc, vardef);
+ }
+ else
+ {
+ yield return Instruction.Create(OpCodes.Ldc_I8, 0L);
+ var timespanctorinfo =
+ Context.Body.Method.Module.Import(typeof (TimeSpan))
+ .Resolve()
+ .Methods.FirstOrDefault(
+ md => md.IsConstructor && md.Parameters.Count == 1 && md.Parameters[0].ParameterType.FullName == "System.Int64");
+ var timespanctor = Context.Body.Method.Module.Import(timespanctorinfo);
+ yield return Instruction.Create(OpCodes.Newobj, timespanctor);
+ }
+ break;
+ case "System.Uri":
+ Uri outuri;
+ if (hasValue && Uri.TryCreate(valueString, UriKind.RelativeOrAbsolute, out outuri))
+ {
+ var vardef = new VariableDefinition(Context.Body.Method.Module.Import(typeof (Uri)));
+ Context.Body.Variables.Add(vardef);
+ //Use an extra temp var so we can push the value to the stack, just like other cases
+ yield return Instruction.Create(OpCodes.Ldstr, valueString);
+ yield return Instruction.Create(OpCodes.Ldc_I4, (int)UriKind.RelativeOrAbsolute);
+ yield return Instruction.Create(OpCodes.Ldloca, vardef);
+ var tryCreateInfo =
+ Context.Body.Method.Module.Import(typeof (Uri))
+ .Resolve()
+ .Methods.FirstOrDefault(md => md.Name == "TryCreate" && md.Parameters.Count == 3);
+ var tryCreate = Context.Body.Method.Module.Import(tryCreateInfo);
+ yield return Instruction.Create(OpCodes.Call, tryCreate);
+ yield return Instruction.Create(OpCodes.Pop);
+ yield return Instruction.Create(OpCodes.Ldloc, vardef);
+ }
+ else
+ yield return Instruction.Create(OpCodes.Ldnull);
+ break;
+ default:
+ var defaultctorinfo = typedef.Methods.FirstOrDefault(md => md.IsConstructor && !md.HasParameters);
+ if (defaultctorinfo != null)
+ {
+ var defaultctor = Context.Body.Method.Module.Import(defaultctorinfo);
+ yield return Instruction.Create(OpCodes.Newobj, defaultctor);
+ }
+ else
+ {
+ //should never happen. but if it does, this prevents corrupting the IL stack
+ yield return Instruction.Create(OpCodes.Ldnull);
+ }
+ break;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/DebugXamlCTask.cs b/Xamarin.Forms.Build.Tasks/DebugXamlCTask.cs
new file mode 100644
index 00000000..f4b2f52c
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/DebugXamlCTask.cs
@@ -0,0 +1,152 @@
+using System;
+using System.IO;
+using System.Linq;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Mono.Cecil.Rocks;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ public class DebugXamlCTask : XamlCTask
+ {
+ public override bool Execute()
+ {
+ InMsBuild = true;
+ Verbosity = Int32.MaxValue;
+ LogLine(1, "Preparing debug code for xamlc");
+ LogLine(1, "\nAssembly: {0}", Assembly);
+
+ var resolver = new DefaultAssemblyResolver();
+ if (!string.IsNullOrEmpty(DependencyPaths))
+ {
+ foreach (var dep in DependencyPaths.Split(';'))
+ {
+ LogLine(3, "Adding searchpath {0}", dep);
+ resolver.AddSearchDirectory(dep);
+ }
+ }
+ if (!string.IsNullOrEmpty(ReferencePath))
+ {
+ var paths = ReferencePath.Replace("//", "/").Split(';');
+ foreach (var p in paths)
+ {
+ var searchpath = Path.GetDirectoryName(p);
+ LogLine(3, "Adding searchpath {0}", searchpath);
+ resolver.AddSearchDirectory(searchpath);
+ // LogLine (3, "Referencing {0}", p);
+ // resolver.AddAssembly (p);
+ }
+ }
+ var assemblyDefinition = AssemblyDefinition.ReadAssembly(Assembly, new ReaderParameters
+ {
+ //ReadSymbols = DebugSymbols,
+ AssemblyResolver = resolver
+ });
+
+ foreach (var module in assemblyDefinition.Modules)
+ {
+ LogLine(2, " Module: {0}", module.Name);
+ foreach (var resource in module.Resources.OfType<EmbeddedResource>())
+ {
+ Log(2, " Resource: {0}... ", resource.Name);
+ string classname;
+ if (!resource.IsXaml(out classname))
+ {
+ LogLine(2, "skipped.");
+ continue;
+ }
+ TypeDefinition typeDef = module.GetType(classname);
+ if (typeDef == null)
+ {
+ LogLine(2, "no type found... skipped.");
+ continue;
+ }
+ var initComp = typeDef.Methods.FirstOrDefault(md => md.Name == "InitializeComponent");
+ if (initComp == null)
+ {
+ LogLine(2, "no InitializeComponent found... skipped.");
+ continue;
+ }
+ if (typeDef.Methods.FirstOrDefault(md => md.Name == "InitCompRuntime") != null)
+ {
+ LogLine(2, "InitCompRuntime already exists... skipped");
+ continue;
+ }
+ LogLine(2, "");
+
+ Log(2, " Duplicating {0}.InitializeComponent () into {0}.InitCompRuntime ... ", typeDef.Name);
+ var initCompRuntime = new MethodDefinition("InitCompRuntime", initComp.Attributes, initComp.ReturnType);
+ initCompRuntime.Body = initComp.Body;
+ typeDef.Methods.Add(initCompRuntime);
+ LogLine(2, "done.");
+
+ // IL_0000: ldarg.0
+ // IL_0001: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.ContentPage::'.ctor'()
+ //
+ // IL_0006: nop
+ // IL_0007: ldarg.1
+ // IL_0008: brfalse IL_0018
+ //
+ // IL_000d: ldarg.0
+ // IL_000e: callvirt instance void class Xamarin.Forms.Xaml.XamlcTests.MyPage::InitializeComponent()
+ // IL_0013: br IL_001e
+ //
+ // IL_0018: ldarg.0
+ // IL_0019: callvirt instance void class Xamarin.Forms.Xaml.XamlcTests.MyPage::InitCompRuntime()
+ // IL_001e: ret
+
+ var altCtor =
+ typeDef.Methods.Where(
+ md => md.IsConstructor && md.Parameters.Count == 1 && md.Parameters[0].ParameterType == module.TypeSystem.Boolean)
+ .FirstOrDefault();
+ if (altCtor != null)
+ Log(2, " Replacing body of {0}.{0} (bool {1}) ... ", typeDef.Name, altCtor.Parameters[0].Name);
+ else
+ {
+ Log(2, " Adding {0}.{0} (bool useCompiledXaml) ... ", typeDef.Name);
+ altCtor = new MethodDefinition(".ctor",
+ MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName |
+ MethodAttributes.RTSpecialName, module.TypeSystem.Void);
+ altCtor.Parameters.Add(new ParameterDefinition("useCompiledXaml", ParameterAttributes.None,
+ module.TypeSystem.Boolean));
+ }
+
+ var body = new MethodBody(altCtor);
+ var il = body.GetILProcessor();
+ var br2 = Instruction.Create(OpCodes.Ldarg_0);
+ var ret = Instruction.Create(OpCodes.Ret);
+ il.Emit(OpCodes.Ldarg_0);
+ il.Emit(OpCodes.Callvirt,
+ module.Import(typeDef.BaseType.Resolve().GetConstructors().First(c => c.HasParameters == false)));
+
+ il.Emit(OpCodes.Nop);
+ il.Emit(OpCodes.Ldarg_1);
+ il.Emit(OpCodes.Brfalse, br2);
+
+ il.Emit(OpCodes.Ldarg_0);
+ il.Emit(OpCodes.Callvirt, initComp);
+ il.Emit(OpCodes.Br, ret);
+
+ il.Append(br2);
+ il.Emit(OpCodes.Callvirt, initCompRuntime);
+ il.Append(ret);
+
+ altCtor.Body = body;
+ if (!typeDef.Methods.Contains(altCtor))
+ typeDef.Methods.Add(altCtor);
+ LogLine(2, "done.");
+ }
+
+ LogLine(2, "");
+ }
+ Log(1, "Writing the assembly... ");
+ assemblyDefinition.Write(Assembly, new WriterParameters
+ {
+ WriteSymbols = DebugSymbols
+ });
+ LogLine(1, "done.");
+
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/ExpandMarkupsVisitor.cs b/Xamarin.Forms.Build.Tasks/ExpandMarkupsVisitor.cs
new file mode 100644
index 00000000..e63ae426
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/ExpandMarkupsVisitor.cs
@@ -0,0 +1,207 @@
+using System;
+using System.Collections.Generic;
+using System.Xml;
+using Xamarin.Forms.Xaml;
+using Xamarin.Forms.Xaml.Internals;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ class ExpandMarkupsVisitor : IXamlNodeVisitor
+ {
+ readonly IList<XmlName> skips = new List<XmlName>
+ {
+ XmlName.xKey,
+ XmlName.xTypeArguments,
+ XmlName.xArguments,
+ XmlName.xFactoryMethod,
+ XmlName.xName
+ };
+
+ public ExpandMarkupsVisitor(ILContext context)
+ {
+ Context = context;
+ }
+
+ ILContext Context { get; }
+
+ public bool VisitChildrenFirst
+ {
+ get { return true; }
+ }
+
+ public bool StopOnDataTemplate
+ {
+ get { return false; }
+ }
+
+ public bool StopOnResourceDictionary
+ {
+ get { return false; }
+ }
+
+ public void Visit(ValueNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(MarkupNode markupnode, INode parentNode)
+ {
+ XmlName propertyName;
+ if (!TryGetProperyName(markupnode, parentNode, out propertyName))
+ return;
+ if (skips.Contains(propertyName))
+ return;
+ var markupString = markupnode.MarkupString;
+ var node = ParseExpression(ref markupString, Context, markupnode.NamespaceResolver, markupnode) as IElementNode;
+ if (node != null)
+ {
+ ((IElementNode)parentNode).Properties[propertyName] = node;
+ node.Accept(new XamlNodeVisitor((n, parent) => n.Parent = parent), parentNode);
+ }
+ }
+
+ public void Visit(ElementNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(RootNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(ListNode node, INode parentNode)
+ {
+ }
+
+ public static bool TryGetProperyName(INode node, INode parentNode, out XmlName name)
+ {
+ name = default(XmlName);
+ var parentElement = parentNode as IElementNode;
+ if (parentElement == null)
+ return false;
+ foreach (var kvp in parentElement.Properties)
+ {
+ if (kvp.Value != node)
+ continue;
+ name = kvp.Key;
+ return true;
+ }
+ return false;
+ }
+
+ static INode ParseExpression(ref string expression, ILContext context, IXmlNamespaceResolver nsResolver,
+ IXmlLineInfo xmlLineInfo)
+ {
+ if (expression.StartsWith("{}", StringComparison.Ordinal))
+ return new ValueNode(expression.Substring(2), null);
+
+ if (expression[expression.Length - 1] != '}')
+ throw new XamlParseException("Markup expression missing its closing tag", xmlLineInfo);
+
+ int len;
+ string match;
+ if (!MarkupExpressionParser.MatchMarkup(out match, expression, out len))
+ throw new XamlParseException("Error while parsing markup expression", xmlLineInfo);
+ expression = expression.Substring(len).TrimStart();
+ if (expression.Length == 0)
+ throw new XamlParseException("Markup expression not closed", xmlLineInfo);
+
+ var provider = new XamlServiceProvider(null, null);
+ provider.Add(typeof (ILContextProvider), new ILContextProvider(context));
+ provider.Add(typeof (IXmlNamespaceResolver), nsResolver);
+ provider.Add(typeof (IXmlLineInfoProvider), new XmlLineInfoProvider(xmlLineInfo));
+
+ return new MarkupExpansionParser().Parse(match, ref expression, provider);
+ }
+
+ class ILContextProvider
+ {
+ public ILContextProvider(ILContext context)
+ {
+ Context = context;
+ }
+
+ public ILContext Context { get; }
+ }
+
+ class MarkupExpansionParser : MarkupExpressionParser, IExpressionParser<INode>
+ {
+ IElementNode node;
+
+ object IExpressionParser.Parse(string match, ref string remaining, IServiceProvider serviceProvider)
+ {
+ return Parse(match, ref remaining, serviceProvider);
+ }
+
+ public INode Parse(string match, ref string remaining, IServiceProvider serviceProvider)
+ {
+ var nsResolver = serviceProvider.GetService(typeof (IXmlNamespaceResolver)) as IXmlNamespaceResolver;
+ if (nsResolver == null)
+ throw new ArgumentException();
+ IXmlLineInfo xmlLineInfo = null;
+ var xmlLineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
+ if (xmlLineInfoProvider != null)
+ xmlLineInfo = xmlLineInfoProvider.XmlLineInfo;
+ var contextProvider = serviceProvider.GetService(typeof (ILContextProvider)) as ILContextProvider;
+
+ var split = match.Split(':');
+ if (split.Length > 2)
+ throw new ArgumentException();
+
+ string prefix, name;
+ if (split.Length == 2)
+ {
+ prefix = split[0];
+ name = split[1];
+ }
+ else
+ {
+ prefix = "";
+ name = split[0];
+ }
+
+ var namespaceuri = nsResolver.LookupNamespace(prefix) ?? "";
+ //The order of lookup is to look for the Extension-suffixed class name first and then look for the class name without the Extension suffix.
+ XmlType type;
+ try
+ {
+ type = new XmlType(namespaceuri, name + "Extension", null);
+ var typeref = type.GetTypeReference(contextProvider.Context.Body.Method.Module, null);
+ }
+ catch (XamlParseException)
+ {
+ type = new XmlType(namespaceuri, name, null);
+ }
+
+ if (type == null)
+ throw new NotSupportedException();
+
+ node = xmlLineInfo == null
+ ? new ElementNode(type, null, nsResolver)
+ : new ElementNode(type, null, nsResolver, xmlLineInfo.LineNumber, xmlLineInfo.LinePosition);
+
+ if (remaining.StartsWith("}", StringComparison.Ordinal))
+ {
+ remaining = remaining.Substring(1);
+ return node;
+ }
+
+ char next;
+ string piece;
+ while ((piece = GetNextPiece(ref remaining, out next)) != null)
+ HandleProperty(piece, serviceProvider, ref remaining, next != '=');
+
+ return node;
+ }
+
+ protected override void SetPropertyValue(string prop, string strValue, object value, IServiceProvider serviceProvider)
+ {
+ if (prop != null)
+ {
+ var name = new XmlName(node.NamespaceURI, prop);
+ node.Properties[name] = value as INode ?? new ValueNode(strValue, null);
+ }
+ else //ContentProperty
+ node.CollectionItems.Add(value as INode ?? new ValueNode(strValue, null));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/FieldReferenceExtensions.cs b/Xamarin.Forms.Build.Tasks/FieldReferenceExtensions.cs
new file mode 100644
index 00000000..3876b9c8
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/FieldReferenceExtensions.cs
@@ -0,0 +1,22 @@
+using Mono.Cecil;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ static class FieldReferenceExtensions
+ {
+ public static FieldReference ResolveGenericParameters(this FieldReference self, TypeReference declaringTypeRef)
+ {
+ var fieldType = self.FieldType;
+ if (fieldType.IsGenericParameter)
+ {
+ var genericParameter = (GenericParameter)fieldType;
+ fieldType = ((GenericInstanceType)declaringTypeRef).GenericArguments[genericParameter.Position];
+ }
+ var fieldReference = new FieldReference(self.Name, fieldType)
+ {
+ DeclaringType = declaringTypeRef
+ };
+ return fieldReference;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/FixedCreateCSharpManifestResourceName.cs b/Xamarin.Forms.Build.Tasks/FixedCreateCSharpManifestResourceName.cs
new file mode 100644
index 00000000..a508a558
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/FixedCreateCSharpManifestResourceName.cs
@@ -0,0 +1,27 @@
+using Microsoft.Build.Framework;
+using Microsoft.Build.Tasks;
+using Microsoft.Build.Utilities;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ public class FixedCreateCSharpManifestResourceName : CreateCSharpManifestResourceName
+ {
+ [Output]
+ public ITaskItem[] ResourceFilesWithManifestResourceNames { get; set; }
+
+ public override bool Execute()
+ {
+ var ret = base.Execute();
+
+ ResourceFilesWithManifestResourceNames = new TaskItem[ResourceFiles.Length];
+
+ for (var i = 0; i < ResourceFiles.Length; i++)
+ {
+ var copy = new TaskItem(ResourceFiles[i]);
+ copy.SetMetadata("ManifestResourceName", ManifestResourceNames[i].ItemSpec);
+ ResourceFilesWithManifestResourceNames[i] = copy;
+ }
+ return ret;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/ILContext.cs b/Xamarin.Forms.Build.Tasks/ILContext.cs
new file mode 100644
index 00000000..14ade391
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/ILContext.cs
@@ -0,0 +1,37 @@
+using System.Collections.Generic;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ class ILContext
+ {
+ public ILContext(ILProcessor il, MethodBody body, FieldDefinition parentContextValues = null)
+ {
+ IL = il;
+ Body = body;
+ Values = new Dictionary<IValueNode, object>();
+ Variables = new Dictionary<IElementNode, VariableDefinition>();
+ Scopes = new Dictionary<INode, VariableDefinition>();
+ TypeExtensions = new Dictionary<INode, TypeReference>();
+ ParentContextValues = parentContextValues;
+ }
+
+ public Dictionary<IValueNode, object> Values { get; private set; }
+
+ public Dictionary<IElementNode, VariableDefinition> Variables { get; private set; }
+
+ public Dictionary<INode, VariableDefinition> Scopes { get; private set; }
+
+ public Dictionary<INode, TypeReference> TypeExtensions { get; }
+
+ public FieldDefinition ParentContextValues { get; private set; }
+
+ public object Root { get; set; } //FieldDefinition or VariableDefinition
+
+ public ILProcessor IL { get; private set; }
+
+ public MethodBody Body { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/ILProcessorExtensions.cs b/Xamarin.Forms.Build.Tasks/ILProcessorExtensions.cs
new file mode 100644
index 00000000..6bcedc78
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/ILProcessorExtensions.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+using Mono.Cecil.Cil;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ static class ILProcessorExtensions
+ {
+ public static void Append(this ILProcessor processor, IEnumerable<Instruction> instructions)
+ {
+ foreach (var instruction in instructions)
+ processor.Append(instruction);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/ILRootNode.cs b/Xamarin.Forms.Build.Tasks/ILRootNode.cs
new file mode 100644
index 00000000..b50d6204
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/ILRootNode.cs
@@ -0,0 +1,15 @@
+using Mono.Cecil;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ class ILRootNode : RootNode
+ {
+ public ILRootNode(XmlType xmlType, TypeReference typeReference) : base(xmlType)
+ {
+ TypeReference = typeReference;
+ }
+
+ public TypeReference TypeReference { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/MethodDefinitionExtensions.cs b/Xamarin.Forms.Build.Tasks/MethodDefinitionExtensions.cs
new file mode 100644
index 00000000..41d7cb20
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/MethodDefinitionExtensions.cs
@@ -0,0 +1,38 @@
+using System.Collections.Generic;
+using Mono.Cecil;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ static class MethodDefinitionExtensions
+ {
+ public static bool MatchXArguments(this MethodDefinition methodDefinition, ElementNode enode, ModuleDefinition module)
+ {
+ if (!enode.Properties.ContainsKey(XmlName.xArguments))
+ return !methodDefinition.HasParameters;
+
+ var arguments = new List<INode>();
+ var node = enode.Properties[XmlName.xArguments] as ElementNode;
+ if (node != null)
+ arguments.Add(node);
+ var list = enode.Properties[XmlName.xArguments] as ListNode;
+ if (list != null)
+ {
+ foreach (var n in list.CollectionItems)
+ arguments.Add(n);
+ }
+
+ if (methodDefinition.Parameters.Count != arguments.Count)
+ return false;
+
+ for (var i = 0; i < methodDefinition.Parameters.Count; i++)
+ {
+ var paramType = methodDefinition.Parameters[i].ParameterType;
+ var argType = ((IElementNode)arguments[i]).XmlType.GetTypeReference(module, null);
+ if (!argType.InheritsFromOrImplements(paramType))
+ return false;
+ }
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/MethodReferenceExtensions.cs b/Xamarin.Forms.Build.Tasks/MethodReferenceExtensions.cs
new file mode 100644
index 00000000..e377a0c6
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/MethodReferenceExtensions.cs
@@ -0,0 +1,63 @@
+using System;
+using Mono.Cecil;
+using Mono.Cecil.Rocks;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ static class MethodReferenceExtensions
+ {
+ [Obsolete]
+ public static MethodReference MakeGeneric(this MethodReference self, params TypeReference[] arguments)
+ {
+ var reference = new MethodReference(self.Name, self.ReturnType)
+ {
+ DeclaringType = self.DeclaringType.MakeGenericInstanceType(arguments),
+ HasThis = self.HasThis,
+ ExplicitThis = self.ExplicitThis,
+ CallingConvention = self.CallingConvention
+ };
+
+ foreach (var parameter in self.Parameters)
+ reference.Parameters.Add(new ParameterDefinition(parameter.ParameterType));
+
+ foreach (var generic_parameter in self.GenericParameters)
+ reference.GenericParameters.Add(new GenericParameter(generic_parameter.Name, reference));
+
+ return reference;
+ }
+
+ public static MethodReference ResolveGenericParameters(this MethodReference self, TypeReference declaringTypeRef,
+ ModuleDefinition module)
+ {
+ if (self == null)
+ throw new ArgumentNullException("self");
+ if (declaringTypeRef == null)
+ throw new ArgumentNullException("declaringTypeRef");
+
+ var reference = new MethodReference(self.Name, self.ReturnType)
+ {
+ DeclaringType = declaringTypeRef,
+ HasThis = self.HasThis,
+ ExplicitThis = self.ExplicitThis,
+ CallingConvention = self.CallingConvention
+ };
+
+ foreach (var parameter in self.Parameters)
+ reference.Parameters.Add(new ParameterDefinition(module.Import(parameter.ParameterType)));
+
+ foreach (var generic_parameter in self.GenericParameters)
+ reference.GenericParameters.Add(new GenericParameter(generic_parameter.Name, reference));
+
+ return reference;
+ }
+
+ public static void ImportTypes(this MethodReference self, ModuleDefinition module)
+ {
+ if (self.HasParameters)
+ {
+ for (var i = 0; i < self.Parameters.Count; i++)
+ self.Parameters[i].ParameterType = module.Import(self.Parameters[i].ParameterType);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/NodeILExtensions.cs b/Xamarin.Forms.Build.Tasks/NodeILExtensions.cs
new file mode 100644
index 00000000..30b01061
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/NodeILExtensions.cs
@@ -0,0 +1,480 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Xml;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Xamarin.Forms.Xaml;
+using Xamarin.Forms.Xaml.Internals;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ static class NodeILExtensions
+ {
+ public static IEnumerable<Instruction> PushConvertedValue(this ValueNode node, ILContext context,
+ TypeReference targetTypeRef, IEnumerable<ICustomAttributeProvider> attributeProviders,
+ IEnumerable<Instruction> pushServiceProvider, bool boxValueTypes, bool unboxValueTypes)
+ {
+ TypeReference typeConverter = null;
+ foreach (var attributeProvider in attributeProviders)
+ {
+ CustomAttribute typeConverterAttribute;
+ if (
+ (typeConverterAttribute =
+ attributeProvider.CustomAttributes.FirstOrDefault(
+ cad => TypeConverterAttribute.TypeConvertersType.Contains(cad.AttributeType.FullName))) != null)
+ {
+ typeConverter = typeConverterAttribute.ConstructorArguments[0].Value as TypeReference;
+ break;
+ }
+ }
+ return node.PushConvertedValue(context, targetTypeRef, typeConverter, pushServiceProvider, boxValueTypes,
+ unboxValueTypes);
+ }
+
+ public static IEnumerable<Instruction> PushConvertedValue(this ValueNode node, ILContext context, FieldReference bpRef,
+ IEnumerable<Instruction> pushServiceProvider, bool boxValueTypes, bool unboxValueTypes)
+ {
+ var module = context.Body.Method.Module;
+ var targetTypeRef = GetBPReturnType(context, bpRef, node);
+
+ TypeReference typeConverter;
+ bpRef.HasTypeConverter(module, out typeConverter);
+
+ return node.PushConvertedValue(context, targetTypeRef, typeConverter, pushServiceProvider, boxValueTypes,
+ unboxValueTypes);
+ }
+
+ public static IEnumerable<Instruction> PushConvertedValue(this ValueNode node, ILContext context,
+ TypeReference targetTypeRef, TypeReference typeConverter, IEnumerable<Instruction> pushServiceProvider,
+ bool boxValueTypes, bool unboxValueTypes)
+ {
+ var module = context.Body.Method.Module;
+ var str = (string)node.Value;
+
+ //If there's a [TypeConverter], use it
+ if (typeConverter != null)
+ {
+ var isExtendedConverter = typeConverter.ImplementsInterface(module.Import(typeof (IExtendedTypeConverter)));
+ var typeConverterCtor = typeConverter.Resolve().Methods.Single(md => md.IsConstructor && md.Parameters.Count == 0);
+ var typeConverterCtorRef = module.Import(typeConverterCtor);
+ var convertFromInvariantStringDefinition = isExtendedConverter
+ ? module.Import(typeof (IExtendedTypeConverter))
+ .Resolve()
+ .Methods.FirstOrDefault(md => md.Name == "ConvertFromInvariantString" && md.Parameters.Count == 2)
+ : typeConverter.Resolve()
+ .AllMethods()
+ .FirstOrDefault(md => md.Name == "ConvertFromInvariantString" && md.Parameters.Count == 1);
+ var convertFromInvariantStringReference = module.Import(convertFromInvariantStringDefinition);
+
+ yield return Instruction.Create(OpCodes.Newobj, typeConverterCtorRef);
+ yield return Instruction.Create(OpCodes.Ldstr, node.Value as string);
+
+ if (isExtendedConverter)
+ {
+ foreach (var instruction in pushServiceProvider)
+ yield return instruction;
+ }
+
+ yield return Instruction.Create(OpCodes.Callvirt, convertFromInvariantStringReference);
+
+ if (targetTypeRef.IsValueType && unboxValueTypes)
+ yield return Instruction.Create(OpCodes.Unbox_Any, module.Import(targetTypeRef));
+
+ //ConvertFrom returns an object, no need to Box
+ yield break;
+ }
+ var originalTypeRef = targetTypeRef;
+ var isNullable = false;
+ MethodReference nullableCtor = null;
+ if (targetTypeRef.Resolve().FullName == "System.Nullable`1")
+ {
+ targetTypeRef = ((GenericInstanceType)targetTypeRef).GenericArguments[0];
+ isNullable = true;
+ nullableCtor = originalTypeRef.GetMethods(md => md.IsConstructor && md.Parameters.Count == 1, module).Single().Item1;
+ nullableCtor = nullableCtor.MakeGeneric(targetTypeRef);
+ }
+ //Obvious Built-in conversions
+ if (targetTypeRef.Resolve().BaseType != null && targetTypeRef.Resolve().BaseType.FullName == "System.Enum")
+ yield return Instruction.Create(OpCodes.Ldc_I4, ParseEnum(targetTypeRef, str, node));
+ else if (targetTypeRef.FullName == "System.Char")
+ yield return Instruction.Create(OpCodes.Ldc_I4, Char.Parse(str));
+ else if (targetTypeRef.FullName == "System.Byte")
+ yield return Instruction.Create(OpCodes.Ldc_I4, Byte.Parse(str, CultureInfo.InvariantCulture));
+ else if (targetTypeRef.FullName == "System.Int16")
+ yield return Instruction.Create(OpCodes.Ldc_I4, Int16.Parse(str, CultureInfo.InvariantCulture));
+ else if (targetTypeRef.FullName == "System.Int32")
+ yield return Instruction.Create(OpCodes.Ldc_I4, Int32.Parse(str, CultureInfo.InvariantCulture));
+ else if (targetTypeRef.FullName == "System.Int64")
+ yield return Instruction.Create(OpCodes.Ldc_I8, Int64.Parse(str, CultureInfo.InvariantCulture));
+ else if (targetTypeRef.FullName == "System.Single")
+ yield return Instruction.Create(OpCodes.Ldc_R4, Single.Parse(str, CultureInfo.InvariantCulture));
+ else if (targetTypeRef.FullName == "System.Double")
+ yield return Instruction.Create(OpCodes.Ldc_R8, Double.Parse(str, CultureInfo.InvariantCulture));
+ else if (targetTypeRef.FullName == "System.Boolean")
+ {
+ if (Boolean.Parse(str))
+ yield return Instruction.Create(OpCodes.Ldc_I4_1);
+ else
+ yield return Instruction.Create(OpCodes.Ldc_I4_0);
+ }
+ else if (targetTypeRef.FullName == "System.TimeSpan")
+ {
+ var ts = TimeSpan.Parse(str, CultureInfo.InvariantCulture);
+ var ticks = ts.Ticks;
+ var timeSpanCtor =
+ module.Import(typeof (TimeSpan))
+ .Resolve()
+ .Methods.FirstOrDefault(md => md.IsConstructor && md.Parameters.Count == 1);
+ var timeSpanCtorRef = module.Import(timeSpanCtor);
+
+ yield return Instruction.Create(OpCodes.Ldc_I8, ticks);
+ yield return Instruction.Create(OpCodes.Newobj, timeSpanCtorRef);
+ }
+ else if (targetTypeRef.FullName == "System.DateTime")
+ {
+ var dt = DateTime.Parse(str, CultureInfo.InvariantCulture);
+ var ticks = dt.Ticks;
+ var dateTimeCtor =
+ module.Import(typeof (DateTime))
+ .Resolve()
+ .Methods.FirstOrDefault(md => md.IsConstructor && md.Parameters.Count == 1);
+ var dateTimeCtorRef = module.Import(dateTimeCtor);
+
+ yield return Instruction.Create(OpCodes.Ldc_I8, ticks);
+ yield return Instruction.Create(OpCodes.Newobj, dateTimeCtorRef);
+ }
+ else if (targetTypeRef.FullName == "System.String" && str.StartsWith("{}", StringComparison.Ordinal))
+ yield return Instruction.Create(OpCodes.Ldstr, str.Substring(2));
+ else if (targetTypeRef.FullName == "System.String")
+ yield return Instruction.Create(OpCodes.Ldstr, str);
+ else if (targetTypeRef.FullName == "System.Object")
+ yield return Instruction.Create(OpCodes.Ldstr, str);
+ else
+ yield return Instruction.Create(OpCodes.Ldnull);
+
+ if (isNullable)
+ yield return Instruction.Create(OpCodes.Newobj, module.Import(nullableCtor));
+ if (originalTypeRef.IsValueType && boxValueTypes)
+ yield return Instruction.Create(OpCodes.Box, module.Import(originalTypeRef));
+ }
+
+ static int ParseEnum(TypeReference enumRef, string value, IXmlLineInfo lineInfo)
+ {
+ var enumDef = enumRef.Resolve();
+ if (!enumDef.IsEnum)
+ throw new InvalidOperationException();
+
+ int? result = null;
+
+ foreach (var v in value.Split(','))
+ {
+ foreach (var field in enumDef.Fields)
+ {
+ if (field.Name == "value__")
+ continue;
+ if (field.Name == v.Trim())
+ result = (result ?? 0) | (int)field.Constant;
+ }
+ }
+
+ if (result.HasValue)
+ return result.Value;
+
+ throw new XamlParseException(string.Format("Enum value not found for {0}", value), lineInfo);
+ }
+
+ static bool HasTypeConverter(this FieldReference bpRef, ModuleDefinition module,
+ out TypeReference typeConverterReference)
+ {
+ typeConverterReference = null;
+
+ var declaringType = bpRef.DeclaringType;
+ var bpName = bpRef.Name;
+ var pName = bpName.EndsWith("Property", StringComparison.Ordinal) ? bpName.Substring(0, bpName.Length - 8) : bpName;
+ var property = declaringType.Resolve().Properties.FirstOrDefault(p => p.Name == pName);
+ CustomAttribute attr = null;
+
+ if (property != null)
+ {
+ if (property.HasCustomAttributes)
+ {
+ attr =
+ property.CustomAttributes.FirstOrDefault(
+ cad => TypeConverterAttribute.TypeConvertersType.Contains(cad.AttributeType.FullName));
+ }
+ if (attr == null && property.PropertyType.Resolve().HasCustomAttributes)
+ {
+ attr =
+ property.PropertyType.Resolve()
+ .CustomAttributes.FirstOrDefault(
+ cad => TypeConverterAttribute.TypeConvertersType.Contains(cad.AttributeType.FullName));
+ }
+
+ if (attr == null)
+ return false;
+
+ typeConverterReference = attr.ConstructorArguments[0].Value as TypeReference;
+ return true;
+ }
+
+ var getters = bpRef.DeclaringType.GetMethods(md => md.Name == "Get" + pName && md.IsStatic, module).SingleOrDefault();
+ if (getters != null)
+ {
+ if (getters.Item1.HasCustomAttributes)
+ {
+ attr =
+ getters.Item1.CustomAttributes.FirstOrDefault(
+ cad => TypeConverterAttribute.TypeConvertersType.Contains(cad.AttributeType.FullName));
+ }
+ else if (getters.Item1.ReturnType.Resolve().HasCustomAttributes)
+ {
+ attr =
+ getters.Item1.ReturnType.Resolve()
+ .CustomAttributes.FirstOrDefault(
+ cad => TypeConverterAttribute.TypeConvertersType.Contains(cad.AttributeType.FullName));
+ }
+
+ if (attr == null)
+ return false;
+
+ typeConverterReference = attr.ConstructorArguments[0].Value as TypeReference;
+ return true;
+ }
+
+ return false;
+ }
+
+ static TypeReference GetBPReturnType(ILContext context, FieldReference bpRef, IXmlLineInfo lineInfo)
+ {
+ //Find a property with a matching name
+ var name = bpRef.Name;
+ if (!name.EndsWith("Property", StringComparison.Ordinal))
+ return context.Body.Method.Module.TypeSystem.Object;
+ name = name.Substring(0, name.Length - 8);
+
+ //First, check for a property
+ TypeReference declaringTypeRef;
+ var property = bpRef.DeclaringType.GetProperty(pd => pd.Name == name, out declaringTypeRef);
+ if (property != null)
+ return property.PropertyType;
+
+ //Then check for getter or setter (attached BPs)
+ var getters =
+ bpRef.DeclaringType.GetMethods(md => md.Name == "Get" + name && md.IsStatic, context.Body.Method.Module)
+ .SingleOrDefault();
+ if (getters != null)
+ return getters.Item1.ReturnType;
+
+ //throws
+ throw new XamlParseException(
+ string.Format(
+ "Can not find a Property named \"{0}\" or a static method named \"Get{0}\" for BindableProperty \"{1}\"", name,
+ bpRef.Name), lineInfo);
+ }
+
+ public static IEnumerable<Instruction> PushXmlLineInfo(this INode node, ILContext context)
+ {
+ var module = context.Body.Method.Module;
+
+ var xmlLineInfo = node as IXmlLineInfo;
+ if (xmlLineInfo == null)
+ {
+ yield return Instruction.Create(OpCodes.Ldnull);
+ yield break;
+ }
+ MethodReference ctor;
+ if (xmlLineInfo.HasLineInfo())
+ {
+ yield return Instruction.Create(OpCodes.Ldc_I4, xmlLineInfo.LineNumber);
+ yield return Instruction.Create(OpCodes.Ldc_I4, xmlLineInfo.LinePosition);
+ ctor = module.Import(typeof (XmlLineInfo).GetConstructor(new[] { typeof (int), typeof (int) }));
+ }
+ else
+ ctor = module.Import(typeof (XmlLineInfo).GetConstructor(new Type[] { }));
+ yield return Instruction.Create(OpCodes.Newobj, ctor);
+ }
+
+ public static IEnumerable<Instruction> PushParentObjectsArray(this INode node, ILContext context)
+ {
+ var module = context.Body.Method.Module;
+
+ var nodes = new List<IElementNode>();
+ INode n = node.Parent;
+ while (n != null)
+ {
+ var en = n as IElementNode;
+ if (en != null && context.Variables.ContainsKey(en))
+ nodes.Add(en);
+ n = n.Parent;
+ }
+
+ if (nodes.Count == 0 && context.ParentContextValues == null)
+ {
+ yield return Instruction.Create(OpCodes.Ldnull);
+ yield break;
+ }
+
+ if (nodes.Count == 0)
+ {
+ yield return Instruction.Create(OpCodes.Ldarg_0);
+ yield return Instruction.Create(OpCodes.Ldfld, context.ParentContextValues);
+ yield break;
+ }
+
+ //Compute parent object length
+ if (context.ParentContextValues != null)
+ {
+ yield return Instruction.Create(OpCodes.Ldarg_0);
+ yield return Instruction.Create(OpCodes.Ldfld, context.ParentContextValues);
+ yield return Instruction.Create(OpCodes.Ldlen);
+ yield return Instruction.Create(OpCodes.Conv_I4);
+ }
+ else
+ yield return Instruction.Create(OpCodes.Ldc_I4_0);
+ var parentObjectLength = new VariableDefinition(module.TypeSystem.Int32);
+ context.Body.Variables.Add(parentObjectLength);
+ yield return Instruction.Create(OpCodes.Stloc, parentObjectLength);
+
+ //Create the final array
+ yield return Instruction.Create(OpCodes.Ldloc, parentObjectLength);
+ yield return Instruction.Create(OpCodes.Ldc_I4, nodes.Count);
+ yield return Instruction.Create(OpCodes.Add);
+ yield return Instruction.Create(OpCodes.Newarr, module.TypeSystem.Object);
+ var finalArray = new VariableDefinition(module.Import(typeof (object[])));
+ context.Body.Variables.Add(finalArray);
+ yield return Instruction.Create(OpCodes.Stloc, finalArray);
+
+ //Copy original array to final
+ if (context.ParentContextValues != null)
+ {
+ yield return Instruction.Create(OpCodes.Ldarg_0);
+ yield return Instruction.Create(OpCodes.Ldfld, context.ParentContextValues); //sourceArray
+ yield return Instruction.Create(OpCodes.Ldc_I4_0); //sourceIndex
+ yield return Instruction.Create(OpCodes.Ldloc, finalArray); //destinationArray
+ yield return Instruction.Create(OpCodes.Ldc_I4, nodes.Count); //destinationIndex
+ yield return Instruction.Create(OpCodes.Ldloc, parentObjectLength); //length
+ var arrayCopy =
+ module.Import(typeof (Array))
+ .Resolve()
+ .Methods.First(
+ md =>
+ md.Name == "Copy" && md.Parameters.Count == 5 &&
+ md.Parameters[1].ParameterType.FullName == module.TypeSystem.Int32.FullName);
+ yield return Instruction.Create(OpCodes.Call, module.Import(arrayCopy));
+ }
+
+ //Add nodes to array
+ yield return Instruction.Create(OpCodes.Ldloc, finalArray);
+ if (nodes.Count > 0)
+ {
+ for (var i = 0; i < nodes.Count; i++)
+ {
+ var en = nodes[i];
+ yield return Instruction.Create(OpCodes.Dup);
+ yield return Instruction.Create(OpCodes.Ldc_I4, i);
+ yield return Instruction.Create(OpCodes.Ldloc, context.Variables[en]);
+ if (context.Variables[en].VariableType.IsValueType)
+ yield return Instruction.Create(OpCodes.Box, module.Import(context.Variables[en].VariableType));
+ yield return Instruction.Create(OpCodes.Stelem_Ref);
+ }
+ }
+ }
+
+ public static IEnumerable<Instruction> PushServiceProvider(this INode node, ILContext context)
+ {
+ var module = context.Body.Method.Module;
+
+#if NOSERVICEPROVIDER
+ yield return Instruction.Create (OpCodes.Ldnull);
+ yield break;
+ #endif
+
+ var ctorinfo = typeof (XamlServiceProvider).GetConstructor(new Type[] { });
+ var ctor = module.Import(ctorinfo);
+
+ var addServiceInfo = typeof (XamlServiceProvider).GetMethod("Add", new[] { typeof (Type), typeof (object) });
+ var addService = module.Import(addServiceInfo);
+
+ var getTypeFromHandle =
+ module.Import(typeof (Type).GetMethod("GetTypeFromHandle", new[] { typeof (RuntimeTypeHandle) }));
+ var getAssembly = module.Import(typeof (Type).GetProperty("Assembly").GetMethod);
+
+ yield return Instruction.Create(OpCodes.Newobj, ctor);
+
+ //Add a SimpleValueTargetProvider
+ var pushParentIl = node.PushParentObjectsArray(context).ToList();
+ if (pushParentIl[pushParentIl.Count - 1].OpCode != OpCodes.Ldnull)
+ {
+ yield return Instruction.Create(OpCodes.Dup); //Keep the serviceProvider on the stack
+ yield return Instruction.Create(OpCodes.Ldtoken, module.Import(typeof (IProvideValueTarget)));
+ yield return Instruction.Create(OpCodes.Call, module.Import(getTypeFromHandle));
+
+ foreach (var instruction in pushParentIl)
+ yield return instruction;
+
+ var targetProviderCtor =
+ module.Import(typeof (SimpleValueTargetProvider).GetConstructor(new[] { typeof (object[]) }));
+ yield return Instruction.Create(OpCodes.Newobj, targetProviderCtor);
+ yield return Instruction.Create(OpCodes.Callvirt, addService);
+ }
+
+ //Add a NamescopeProvider
+ if (context.Scopes.ContainsKey(node))
+ {
+ yield return Instruction.Create(OpCodes.Dup); //Dupicate the serviceProvider
+ yield return Instruction.Create(OpCodes.Ldtoken, module.Import(typeof (INameScopeProvider)));
+ yield return Instruction.Create(OpCodes.Call, module.Import(getTypeFromHandle));
+ var namescopeProviderCtor = module.Import(typeof (NameScopeProvider).GetConstructor(new Type[] { }));
+ yield return Instruction.Create(OpCodes.Newobj, namescopeProviderCtor);
+ yield return Instruction.Create(OpCodes.Dup); //Duplicate the namescopeProvider
+ var setNamescope = module.Import(typeof (NameScopeProvider).GetProperty("NameScope").GetSetMethod());
+
+ yield return Instruction.Create(OpCodes.Ldloc, context.Scopes[node]);
+ yield return Instruction.Create(OpCodes.Callvirt, setNamescope);
+ yield return Instruction.Create(OpCodes.Callvirt, addService);
+ }
+
+ //Add a XamlTypeResolver
+ if (node.NamespaceResolver != null)
+ {
+ yield return Instruction.Create(OpCodes.Dup); //Dupicate the serviceProvider
+ yield return Instruction.Create(OpCodes.Ldtoken, module.Import(typeof (IXamlTypeResolver)));
+ yield return Instruction.Create(OpCodes.Call, module.Import(getTypeFromHandle));
+ var xmlNamespaceResolverCtor = module.Import(typeof (XmlNamespaceResolver).GetConstructor(new Type[] { }));
+ var addNamespace = module.Import(typeof (XmlNamespaceResolver).GetMethod("Add"));
+ yield return Instruction.Create(OpCodes.Newobj, xmlNamespaceResolverCtor);
+ foreach (var kvp in node.NamespaceResolver.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml))
+ {
+ yield return Instruction.Create(OpCodes.Dup); //dup the resolver
+ yield return Instruction.Create(OpCodes.Ldstr, kvp.Key);
+ yield return Instruction.Create(OpCodes.Ldstr, kvp.Value);
+ yield return Instruction.Create(OpCodes.Callvirt, addNamespace);
+ }
+ yield return Instruction.Create(OpCodes.Ldtoken, context.Body.Method.DeclaringType);
+ yield return Instruction.Create(OpCodes.Call, module.Import(getTypeFromHandle));
+ yield return Instruction.Create(OpCodes.Callvirt, getAssembly);
+ var xtr = module.Import(typeof (XamlTypeResolver)).Resolve();
+ var xamlTypeResolverCtor = module.Import(xtr.Methods.First(md => md.IsConstructor && md.Parameters.Count == 2));
+ yield return Instruction.Create(OpCodes.Newobj, xamlTypeResolverCtor);
+ yield return Instruction.Create(OpCodes.Callvirt, addService);
+ }
+
+ if (node is IXmlLineInfo)
+ {
+ yield return Instruction.Create(OpCodes.Dup); //Dupicate the serviceProvider
+ yield return Instruction.Create(OpCodes.Ldtoken, module.Import(typeof (IXmlLineInfoProvider)));
+ yield return Instruction.Create(OpCodes.Call, module.Import(getTypeFromHandle));
+
+ foreach (var instruction in node.PushXmlLineInfo(context))
+ yield return instruction;
+
+ var lip = module.Import(typeof (XmlLineInfoProvider)).Resolve();
+ var lineInfoProviderCtor = module.Import(lip.Methods.First(md => md.IsConstructor && md.Parameters.Count == 1));
+ yield return Instruction.Create(OpCodes.Newobj, lineInfoProviderCtor);
+ yield return Instruction.Create(OpCodes.Callvirt, addService);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/Properties/AssemblyInfo.cs b/Xamarin.Forms.Build.Tasks/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..ea4bda34
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/Properties/AssemblyInfo.cs
@@ -0,0 +1,30 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+//
+
+[assembly: AssemblyTitle("Xamarin.Forms.Build.Tasks")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Xamarin Inc.")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Xamarin Inc.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The Page "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+//[assembly: AssemblyVersion("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
+[assembly: InternalsVisibleTo("xamlg")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Xaml.UnitTests")] \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/PropertyDefinitionExtensions.cs b/Xamarin.Forms.Build.Tasks/PropertyDefinitionExtensions.cs
new file mode 100644
index 00000000..472a5658
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/PropertyDefinitionExtensions.cs
@@ -0,0 +1,33 @@
+using Mono.Cecil;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ static class PropertyDefinitionExtensions
+ {
+ // public static PropertyDefinition MakeGeneric (this PropertyDefinition self, GenericInstanceType declaringTypeReference)
+ // {
+ // if (declaringTypeReference == null)
+ // throw new ArgumentNullException ("declaringTypeReference");
+ // if (self == null)
+ // throw new ArgumentNullException ("self");
+ //
+ // var propertyType = declaringTypeReference.GenericArguments[((GenericParameter)self.PropertyType).Position];
+ // self.PropertyType = propertyType;
+ // self.SetMethod = self.SetMethod.MakeGeneric (propertyType).Resolve ();
+ // self.GetMethod.ReturnType = propertyType;
+ //
+ // return self;
+ // }
+
+ public static TypeReference ResolveGenericPropertyType(this PropertyDefinition self,
+ TypeReference declaringTypeReference)
+ {
+ if (self.PropertyType.IsGenericParameter)
+ {
+ return
+ ((GenericInstanceType)declaringTypeReference).GenericArguments[((GenericParameter)self.PropertyType).Position];
+ }
+ return self.PropertyType;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/SetFieldVisitor.cs b/Xamarin.Forms.Build.Tasks/SetFieldVisitor.cs
new file mode 100644
index 00000000..1839cf7b
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/SetFieldVisitor.cs
@@ -0,0 +1,72 @@
+using System.Linq;
+using Mono.Cecil.Cil;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ class SetFieldVisitor : IXamlNodeVisitor
+ {
+ public SetFieldVisitor(ILContext context)
+ {
+ Context = context;
+ }
+
+ public ILContext Context { get; }
+
+ public bool VisitChildrenFirst
+ {
+ get { return false; }
+ }
+
+ public bool StopOnDataTemplate
+ {
+ get { return true; }
+ }
+
+ public bool StopOnResourceDictionary
+ {
+ get { return false; }
+ }
+
+ public void Visit(ValueNode node, INode parentNode)
+ {
+ if (!IsXNameProperty(node, parentNode))
+ return;
+ if (!(parentNode is RootNode))
+ {
+ //no variable assigned for root
+ var field = Context.Body.Method.DeclaringType.Fields.SingleOrDefault(fd => fd.Name == (string)node.Value);
+ if (field == null)
+ return;
+ Context.IL.Emit(OpCodes.Ldarg_0);
+ Context.IL.Emit(OpCodes.Ldloc, Context.Variables[(IElementNode)parentNode]);
+ Context.IL.Emit(OpCodes.Stfld, field);
+ }
+ }
+
+ public void Visit(MarkupNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(ElementNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(RootNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(ListNode node, INode parentNode)
+ {
+ }
+
+ static bool IsXNameProperty(ValueNode node, INode parentNode)
+ {
+ var parentElement = parentNode as IElementNode;
+ INode xNameNode;
+ if (parentElement != null && parentElement.Properties.TryGetValue(XmlName.xName, out xNameNode) && xNameNode == node)
+ return true;
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/SetNamescopesAndRegisterNamesVisitor.cs b/Xamarin.Forms.Build.Tasks/SetNamescopesAndRegisterNamesVisitor.cs
new file mode 100644
index 00000000..477328e2
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/SetNamescopesAndRegisterNamesVisitor.cs
@@ -0,0 +1,142 @@
+using System.Linq;
+using Mono.Cecil.Cil;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ class SetNamescopesAndRegisterNamesVisitor : IXamlNodeVisitor
+ {
+ public SetNamescopesAndRegisterNamesVisitor(ILContext context)
+ {
+ Context = context;
+ }
+
+ ILContext Context { get; }
+
+ public bool VisitChildrenFirst
+ {
+ get { return false; }
+ }
+
+ public bool StopOnDataTemplate
+ {
+ get { return true; }
+ }
+
+ public bool StopOnResourceDictionary
+ {
+ get { return false; }
+ }
+
+ public void Visit(ValueNode node, INode parentNode)
+ {
+ Context.Scopes[node] = Context.Scopes[parentNode];
+ if (IsXNameProperty(node, parentNode))
+ RegisterName((string)node.Value, Context.Scopes[node], Context.Variables[(IElementNode)parentNode], node);
+ }
+
+ public void Visit(MarkupNode node, INode parentNode)
+ {
+ Context.Scopes[node] = Context.Scopes[parentNode];
+ }
+
+ public void Visit(ElementNode node, INode parentNode)
+ {
+ if (node.SkipPrefix((node.NamespaceResolver ?? parentNode.NamespaceResolver).LookupPrefix(node.NamespaceURI)))
+ return;
+
+ VariableDefinition ns;
+ if (parentNode == null || IsDataTemplate(node, parentNode) || IsStyle(node, parentNode))
+ ns = CreateNamescope();
+ else
+ ns = Context.Scopes[parentNode];
+ if (
+ Context.Variables[node].VariableType.InheritsFromOrImplements(
+ Context.Body.Method.Module.Import(typeof (BindableObject))))
+ SetNameScope(node, ns);
+ Context.Scopes[node] = ns;
+ }
+
+ public void Visit(RootNode node, INode parentNode)
+ {
+ var ns = CreateNamescope();
+ if (
+ Context.Variables[node].VariableType.InheritsFromOrImplements(
+ Context.Body.Method.Module.Import(typeof (BindableObject))))
+ SetNameScope(node, ns);
+ Context.Scopes[node] = ns;
+ }
+
+ public void Visit(ListNode node, INode parentNode)
+ {
+ Context.Scopes[node] = Context.Scopes[parentNode];
+ }
+
+ static bool IsDataTemplate(INode node, INode parentNode)
+ {
+ var parentElement = parentNode as IElementNode;
+ INode createContent;
+ if (parentElement != null && parentElement.Properties.TryGetValue(XmlName._CreateContent, out createContent) &&
+ createContent == node)
+ return true;
+ return false;
+ }
+
+ static bool IsStyle(INode node, INode parentNode)
+ {
+ var pnode = parentNode as ElementNode;
+ return pnode != null && pnode.XmlType.Name == "Style";
+ }
+
+ static bool IsXNameProperty(ValueNode node, INode parentNode)
+ {
+ var parentElement = parentNode as IElementNode;
+ INode xNameNode;
+ if (parentElement != null && parentElement.Properties.TryGetValue(XmlName.xName, out xNameNode) && xNameNode == node)
+ return true;
+ return false;
+ }
+
+ VariableDefinition CreateNamescope()
+ {
+ var module = Context.Body.Method.Module;
+ var nsRef = module.Import(typeof (NameScope));
+ var vardef = new VariableDefinition(nsRef);
+ Context.Body.Variables.Add(vardef);
+ var nsDef = nsRef.Resolve();
+ var ctorinfo = nsDef.Methods.First(md => md.IsConstructor && !md.HasParameters);
+ var ctor = module.Import(ctorinfo);
+ Context.IL.Emit(OpCodes.Newobj, ctor);
+ Context.IL.Emit(OpCodes.Stloc, vardef);
+ return vardef;
+ }
+
+ void SetNameScope(ElementNode node, VariableDefinition ns)
+ {
+ var module = Context.Body.Method.Module;
+ var nsRef = module.Import(typeof (NameScope));
+ var nsDef = nsRef.Resolve();
+ var setNSInfo = nsDef.Methods.First(md => md.Name == "SetNameScope" && md.IsStatic);
+ var setNS = module.Import(setNSInfo);
+ Context.IL.Emit(OpCodes.Ldloc, Context.Variables[node]);
+ Context.IL.Emit(OpCodes.Ldloc, ns);
+ Context.IL.Emit(OpCodes.Call, setNS);
+ }
+
+ void RegisterName(string str, VariableDefinition scope, VariableDefinition element, INode node)
+ {
+ var module = Context.Body.Method.Module;
+ var nsRef = module.Import(typeof (INameScope));
+ var nsDef = nsRef.Resolve();
+ var registerInfo = nsDef.Methods.First(md => md.Name == "RegisterName" && md.Parameters.Count == 3);
+ var register = module.Import(registerInfo);
+
+ Context.IL.Emit(OpCodes.Ldloc, scope);
+ Context.IL.Emit(OpCodes.Ldstr, str);
+ Context.IL.Emit(OpCodes.Ldloc, element);
+ Context.IL.Append(node.PushXmlLineInfo(Context));
+ Context.IL.Emit(OpCodes.Callvirt, register);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
new file mode 100644
index 00000000..5470a3c8
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
@@ -0,0 +1,681 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Mono.Cecil.Rocks;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ class SetPropertiesVisitor : IXamlNodeVisitor
+ {
+ static int dtcount;
+
+ readonly IList<XmlName> skips = new List<XmlName>
+ {
+ XmlName.xKey,
+ XmlName.xTypeArguments,
+ XmlName.xArguments,
+ XmlName.xFactoryMethod,
+ XmlName.xName
+ };
+
+ public SetPropertiesVisitor(ILContext context, bool stopOnResourceDictionary = false)
+ {
+ Context = context;
+ Module = context.Body.Method.Module;
+ StopOnResourceDictionary = stopOnResourceDictionary;
+ }
+
+ public ILContext Context { get; }
+
+ ModuleDefinition Module { get; }
+
+ public bool VisitChildrenFirst
+ {
+ get { return true; }
+ }
+
+ public bool StopOnDataTemplate
+ {
+ get { return true; }
+ }
+
+ public bool StopOnResourceDictionary { get; }
+
+ public void Visit(ValueNode node, INode parentNode)
+ {
+ //TODO support Label text as element
+ XmlName propertyName;
+ if (!TryGetPropertyName(node, parentNode, out propertyName))
+ {
+ if (!IsCollectionItem(node, parentNode))
+ return;
+ string contentProperty;
+ if (!Context.Variables.ContainsKey((IElementNode)parentNode))
+ return;
+ var parentVar = Context.Variables[(IElementNode)parentNode];
+ if ((contentProperty = GetContentProperty(parentVar.VariableType)) != null)
+ propertyName = new XmlName(((IElementNode)parentNode).NamespaceURI, contentProperty);
+ else
+ return;
+ }
+
+ if (skips.Contains(propertyName))
+ return;
+ if (node.SkipPrefix((node.NamespaceResolver ?? parentNode.NamespaceResolver)?.LookupPrefix(propertyName.NamespaceURI)))
+ return;
+ if (propertyName.NamespaceURI == "http://schemas.openxmlformats.org/markup-compatibility/2006" &&
+ propertyName.LocalName == "Ignorable")
+ {
+ (parentNode.IgnorablePrefixes ?? (parentNode.IgnorablePrefixes = new List<string>())).AddRange(
+ (node.Value as string).Split(','));
+ return;
+ }
+ SetPropertyValue(Context.Variables[(IElementNode)parentNode], propertyName, node, Context, node);
+ }
+
+ public void Visit(MarkupNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(ElementNode node, INode parentNode)
+ {
+ if (node.SkipPrefix((node.NamespaceResolver ?? parentNode.NamespaceResolver)?.LookupPrefix(node.NamespaceURI)))
+ return;
+
+ //if this node is an IMarkupExtension, invoke ProvideValue() and replace the variable
+ var vardef = Context.Variables[node];
+ var vardefref = new VariableDefinitionReference(vardef);
+ Context.IL.Append(ProvideValue(vardefref, Context, Module, node));
+ if (vardef != vardefref.VariableDefinition)
+ {
+ vardef = vardefref.VariableDefinition;
+ Context.Body.Variables.Add(vardef);
+ Context.Variables[node] = vardef;
+ }
+
+ XmlName propertyName;
+ if (TryGetPropertyName(node, parentNode, out propertyName))
+ {
+ if (skips.Contains(propertyName))
+ return;
+
+ if (propertyName == XmlName._CreateContent)
+ SetDataTemplate((IElementNode)parentNode, node, Context, node);
+ else
+ SetPropertyValue(Context.Variables[(IElementNode)parentNode], propertyName, node, Context, node);
+ }
+ else if (IsCollectionItem(node, parentNode) && parentNode is IElementNode)
+ {
+ // Collection element, implicit content, or implicit collection element.
+ string contentProperty;
+ var parentVar = Context.Variables[(IElementNode)parentNode];
+ if (parentVar.VariableType.ImplementsInterface(Module.Import(typeof (IEnumerable))))
+ {
+ var elementType = parentVar.VariableType;
+ if (elementType.FullName != "Xamarin.Forms.ResourceDictionary")
+ {
+ var adderTuple = elementType.GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, Module).First();
+ var adderRef = Module.Import(adderTuple.Item1);
+ adderRef = Module.Import(adderRef.ResolveGenericParameters(adderTuple.Item2, Module));
+
+ Context.IL.Emit(OpCodes.Ldloc, parentVar);
+ Context.IL.Emit(OpCodes.Ldloc, vardef);
+ Context.IL.Emit(OpCodes.Callvirt, adderRef);
+ if (adderRef.ReturnType.FullName != "System.Void")
+ Context.IL.Emit(OpCodes.Pop);
+ }
+ }
+ else if ((contentProperty = GetContentProperty(parentVar.VariableType)) != null)
+ {
+ var name = new XmlName(node.NamespaceURI, contentProperty);
+ if (skips.Contains(name))
+ return;
+ SetPropertyValue(Context.Variables[(IElementNode)parentNode], name, node, Context, node);
+ }
+ }
+ else if (IsCollectionItem(node, parentNode) && parentNode is ListNode)
+ {
+ // IL_000d: ldloc.2
+ // IL_000e: callvirt instance class [mscorlib]System.Collections.Generic.IList`1<!0> class [Xamarin.Forms.Core]Xamarin.Forms.Layout`1<class [Xamarin.Forms.Core]Xamarin.Forms.View>::get_Children()
+ // IL_0013: ldloc.0
+ // IL_0014: callvirt instance void class [mscorlib]System.Collections.Generic.ICollection`1<class [Xamarin.Forms.Core]Xamarin.Forms.View>::Add(!0)
+
+ var parentList = (ListNode)parentNode;
+ var parent = Context.Variables[((IElementNode)parentNode.Parent)];
+
+ if (skips.Contains(parentList.XmlName))
+ return;
+
+ var elementType = parent.VariableType;
+ var localname = parentList.XmlName.LocalName;
+
+ GetNameAndTypeRef(ref elementType, parentList.XmlName.NamespaceURI, ref localname, Context, node);
+
+ TypeReference propertyDeclaringType;
+ var property = elementType.GetProperty(pd => pd.Name == localname, out propertyDeclaringType);
+ MethodDefinition propertyGetter;
+
+ if (property != null && (propertyGetter = property.GetMethod) != null && propertyGetter.IsPublic)
+ {
+ var propertyGetterRef = Module.Import(propertyGetter);
+ propertyGetterRef = Module.Import(propertyGetterRef.ResolveGenericParameters(propertyDeclaringType, Module));
+ var propertyType = propertyGetterRef.ReturnType.ResolveGenericParameters(propertyDeclaringType);
+
+ var adderTuple = propertyType.GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, Module).First();
+ var adderRef = Module.Import(adderTuple.Item1);
+ adderRef = Module.Import(adderRef.ResolveGenericParameters(adderTuple.Item2, Module));
+
+ Context.IL.Emit(OpCodes.Ldloc, parent);
+ Context.IL.Emit(OpCodes.Callvirt, propertyGetterRef);
+ Context.IL.Emit(OpCodes.Ldloc, vardef);
+ Context.IL.Emit(OpCodes.Callvirt, adderRef);
+ if (adderRef.ReturnType.FullName != "System.Void")
+ Context.IL.Emit(OpCodes.Pop);
+ }
+ }
+ }
+
+ public void Visit(RootNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(ListNode node, INode parentNode)
+ {
+ }
+
+ public static bool TryGetPropertyName(INode node, INode parentNode, out XmlName name)
+ {
+ name = default(XmlName);
+ var parentElement = parentNode as IElementNode;
+ if (parentElement == null)
+ return false;
+ foreach (var kvp in parentElement.Properties)
+ {
+ if (kvp.Value != node)
+ continue;
+ name = kvp.Key;
+ return true;
+ }
+ return false;
+ }
+
+ static bool IsCollectionItem(INode node, INode parentNode)
+ {
+ var parentList = parentNode as IListNode;
+ if (parentList == null)
+ return false;
+ return parentList.CollectionItems.Contains(node);
+ }
+
+ static string GetContentProperty(TypeReference typeRef)
+ {
+ var typeDef = typeRef.Resolve();
+ var attributes = typeDef.CustomAttributes;
+ var attr =
+ attributes.FirstOrDefault(cad => ContentPropertyAttribute.ContentPropertyTypes.Contains(cad.AttributeType.FullName));
+ if (attr != null)
+ return attr.ConstructorArguments[0].Value as string;
+ if (typeDef.BaseType == null)
+ return null;
+ return GetContentProperty(typeDef.BaseType);
+ }
+
+ public static IEnumerable<Instruction> ProvideValue(VariableDefinitionReference vardefref, ILContext context,
+ ModuleDefinition module, ElementNode node)
+ {
+ GenericInstanceType markupExtension;
+ IList<TypeReference> genericArguments;
+ if (vardefref.VariableDefinition.VariableType.FullName == "Xamarin.Forms.Xaml.ArrayExtension" &&
+ vardefref.VariableDefinition.VariableType.ImplementsGenericInterface("Xamarin.Forms.Xaml.IMarkupExtension`1",
+ out markupExtension, out genericArguments))
+ {
+ var markExt = markupExtension.Resolve();
+ var provideValueInfo = markExt.Methods.First(md => md.Name == "ProvideValue");
+ var provideValue = module.Import(provideValueInfo);
+ provideValue =
+ module.Import(provideValue.MakeGeneric(markupExtension.GenericArguments.Select(tr => module.Import(tr)).ToArray()));
+
+ var typeNode = node.Properties[new XmlName("", "Type")];
+ TypeReference arrayTypeRef;
+ if (context.TypeExtensions.TryGetValue(typeNode, out arrayTypeRef))
+ vardefref.VariableDefinition = new VariableDefinition(module.Import(arrayTypeRef.MakeArrayType()));
+ else
+ vardefref.VariableDefinition = new VariableDefinition(module.Import(genericArguments.First()));
+ yield return Instruction.Create(OpCodes.Ldloc, context.Variables[node]);
+ foreach (var instruction in node.PushServiceProvider(context))
+ yield return instruction;
+ yield return Instruction.Create(OpCodes.Callvirt, provideValue);
+
+ if (arrayTypeRef != null)
+ yield return Instruction.Create(OpCodes.Castclass, module.Import(arrayTypeRef.MakeArrayType()));
+ yield return Instruction.Create(OpCodes.Stloc, vardefref.VariableDefinition);
+ }
+ else if (vardefref.VariableDefinition.VariableType.ImplementsGenericInterface("Xamarin.Forms.Xaml.IMarkupExtension`1",
+ out markupExtension, out genericArguments))
+ {
+ var markExt = markupExtension.Resolve();
+ var provideValueInfo = markExt.Methods.First(md => md.Name == "ProvideValue");
+ var provideValue = module.Import(provideValueInfo);
+ provideValue =
+ module.Import(provideValue.MakeGeneric(markupExtension.GenericArguments.Select(tr => module.Import(tr)).ToArray()));
+
+ vardefref.VariableDefinition = new VariableDefinition(module.Import(genericArguments.First()));
+ yield return Instruction.Create(OpCodes.Ldloc, context.Variables[node]);
+ foreach (var instruction in node.PushServiceProvider(context))
+ yield return instruction;
+ yield return Instruction.Create(OpCodes.Callvirt, provideValue);
+ yield return Instruction.Create(OpCodes.Stloc, vardefref.VariableDefinition);
+ }
+ else if (context.Variables[node].VariableType.ImplementsInterface(module.Import(typeof (IMarkupExtension))))
+ {
+ var markExt = module.Import(typeof (IMarkupExtension)).Resolve();
+ var provideValueInfo = markExt.Methods.First(md => md.Name == "ProvideValue");
+ var provideValue = module.Import(provideValueInfo);
+
+ vardefref.VariableDefinition = new VariableDefinition(module.TypeSystem.Object);
+ yield return Instruction.Create(OpCodes.Ldloc, context.Variables[node]);
+ foreach (var instruction in node.PushServiceProvider(context))
+ yield return instruction;
+ yield return Instruction.Create(OpCodes.Callvirt, provideValue);
+ yield return Instruction.Create(OpCodes.Stloc, vardefref.VariableDefinition);
+ }
+ else if (context.Variables[node].VariableType.ImplementsInterface(module.Import(typeof (IValueProvider))))
+ {
+ var markExt = module.Import(typeof (IValueProvider)).Resolve();
+ var provideValueInfo = markExt.Methods.First(md => md.Name == "ProvideValue");
+ var provideValue = module.Import(provideValueInfo);
+
+ vardefref.VariableDefinition = new VariableDefinition(module.TypeSystem.Object);
+ yield return Instruction.Create(OpCodes.Ldloc, context.Variables[node]);
+ foreach (var instruction in node.PushServiceProvider(context))
+ yield return instruction;
+ yield return Instruction.Create(OpCodes.Callvirt, provideValue);
+ yield return Instruction.Create(OpCodes.Stloc, vardefref.VariableDefinition);
+ }
+ }
+
+ public static void SetPropertyValue(VariableDefinition parent, XmlName propertyName, INode valueNode,
+ ILContext context, IXmlLineInfo iXmlLineInfo)
+ {
+ var elementType = parent.VariableType;
+ var localName = propertyName.LocalName;
+ var module = context.Body.Method.Module;
+ var br = Instruction.Create(OpCodes.Nop);
+ TypeReference declaringTypeReference;
+ var handled = false;
+
+ //If it's an attached BP, update elementType and propertyName
+ var attached = GetNameAndTypeRef(ref elementType, propertyName.NamespaceURI, ref localName, context, iXmlLineInfo);
+
+ //If the target is an event, connect
+ // IL_0007: ldloc.0
+ // IL_0008: ldarg.0
+ // IL_0009: ldftn instance void class Xamarin.Forms.Xaml.XamlcTests.MyPage::OnButtonClicked(object, class [mscorlib]System.EventArgs)
+ // IL_000f: newobj instance void class [mscorlib]System.EventHandler::'.ctor'(object, native int)
+ // IL_0014: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.Button::add_Clicked(class [mscorlib]System.EventHandler)
+
+ var eventinfo = elementType.GetEvent(ed => ed.Name == localName);
+ if (eventinfo != null)
+ {
+ var value = ((ValueNode)valueNode).Value;
+
+ context.IL.Emit(OpCodes.Ldloc, parent);
+ if (context.Root is VariableDefinition)
+ context.IL.Emit(OpCodes.Ldloc, context.Root as VariableDefinition);
+ else if (context.Root is FieldDefinition)
+ {
+ context.IL.Emit(OpCodes.Ldarg_0);
+ context.IL.Emit(OpCodes.Ldfld, context.Root as FieldDefinition);
+ }
+ else
+ throw new InvalidProgramException();
+ var declaringType = context.Body.Method.DeclaringType;
+ if (declaringType.IsNested)
+ declaringType = declaringType.DeclaringType;
+ var handler = declaringType.AllMethods().FirstOrDefault(md => md.Name == value as string);
+ if (handler == null)
+ {
+ throw new XamlParseException(
+ string.Format("EventHandler \"{0}\" not found in type \"{1}\"", value, context.Body.Method.DeclaringType.FullName),
+ iXmlLineInfo);
+ }
+ context.IL.Emit(OpCodes.Ldftn, handler);
+ //FIXME: eventually get the right ctor instead fo the First() one, just in case another one could exists (not even sure it's possible).
+ var ctor = module.Import(eventinfo.EventType.Resolve().GetConstructors().First());
+ ctor = ctor.ResolveGenericParameters(eventinfo.EventType, module);
+ context.IL.Emit(OpCodes.Newobj, module.Import(ctor));
+ context.IL.Emit(OpCodes.Callvirt, module.Import(eventinfo.AddMethod));
+ return;
+ }
+
+ FieldReference bpRef = elementType.GetField(fd => fd.Name == localName + "Property" && fd.IsStatic && fd.IsPublic,
+ out declaringTypeReference);
+ if (bpRef != null)
+ {
+ bpRef = module.Import(bpRef.ResolveGenericParameters(declaringTypeReference));
+ bpRef.FieldType = module.Import(bpRef.FieldType);
+ }
+
+ //If Value is DynamicResource, SetDynamicResource
+ VariableDefinition varValue;
+ if (bpRef != null && valueNode is IElementNode &&
+ context.Variables.TryGetValue(valueNode as IElementNode, out varValue) &&
+ varValue.VariableType.FullName == typeof (DynamicResource).FullName)
+ {
+ var setDynamicResource =
+ module.Import(typeof (IDynamicResourceHandler)).Resolve().Methods.First(m => m.Name == "SetDynamicResource");
+ var getKey = typeof (DynamicResource).GetProperty("Key").GetMethod;
+
+ context.IL.Emit(OpCodes.Ldloc, parent);
+ context.IL.Emit(OpCodes.Ldsfld, bpRef);
+ context.IL.Emit(OpCodes.Ldloc, varValue);
+ context.IL.Emit(OpCodes.Callvirt, module.Import(getKey));
+ context.IL.Emit(OpCodes.Callvirt, module.Import(setDynamicResource));
+ return;
+ }
+
+ //If Value is a BindingBase and target is a BP, SetBinding
+ if (bpRef != null && valueNode is IElementNode &&
+ context.Variables.TryGetValue(valueNode as IElementNode, out varValue) &&
+ varValue.VariableType.InheritsFromOrImplements(module.Import(typeof (BindingBase))))
+ {
+ //TODO: check if parent is a BP
+ var setBinding = typeof (BindableObject).GetMethod("SetBinding",
+ new[] { typeof (BindableProperty), typeof (BindingBase) });
+
+ context.IL.Emit(OpCodes.Ldloc, parent);
+ context.IL.Emit(OpCodes.Ldsfld, bpRef);
+ context.IL.Emit(OpCodes.Ldloc, varValue);
+ context.IL.Emit(OpCodes.Callvirt, module.Import(setBinding));
+ return;
+ }
+
+ //If it's a BP, SetValue ()
+ // IL_0007: ldloc.0
+ // IL_0008: ldsfld class [Xamarin.Forms.Core]Xamarin.Forms.BindableProperty [Xamarin.Forms.Core]Xamarin.Forms.Label::TextProperty
+ // IL_000d: ldstr "foo"
+ // IL_0012: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.BindableObject::SetValue(class [Xamarin.Forms.Core]Xamarin.Forms.BindableProperty, object)
+ if (bpRef != null)
+ {
+ //TODO: check if parent is a BP
+ var setValue = typeof (BindableObject).GetMethod("SetValue", new[] { typeof (BindableProperty), typeof (object) });
+
+ if (valueNode is ValueNode)
+ {
+ context.IL.Emit(OpCodes.Ldloc, parent);
+ context.IL.Emit(OpCodes.Ldsfld, bpRef);
+ context.IL.Append(((ValueNode)valueNode).PushConvertedValue(context, bpRef, valueNode.PushServiceProvider(context),
+ true, false));
+ context.IL.Emit(OpCodes.Callvirt, module.Import(setValue));
+ return;
+ }
+ if (valueNode is IElementNode)
+ {
+ var getPropertyReturnType = module.Import(typeof (BindableProperty).GetProperty("ReturnType").GetGetMethod());
+ //FIXME: this should check for inheritance too
+ var isInstanceOfType = module.Import(typeof (Type).GetMethod("IsInstanceOfType", new[] { typeof (object) }));
+ var brfalse = Instruction.Create(OpCodes.Nop);
+
+ context.IL.Emit(OpCodes.Ldsfld, bpRef);
+ context.IL.Emit(OpCodes.Call, getPropertyReturnType);
+ context.IL.Emit(OpCodes.Ldloc, context.Variables[valueNode as IElementNode]);
+ if (context.Variables[valueNode as IElementNode].VariableType.IsValueType)
+ context.IL.Emit(OpCodes.Box, context.Variables[valueNode as IElementNode].VariableType);
+ context.IL.Emit(OpCodes.Callvirt, isInstanceOfType);
+ context.IL.Emit(OpCodes.Brfalse, brfalse);
+ context.IL.Emit(OpCodes.Ldloc, parent);
+ context.IL.Emit(OpCodes.Ldsfld, bpRef);
+ context.IL.Emit(OpCodes.Ldloc, context.Variables[(IElementNode)valueNode]);
+ if (context.Variables[valueNode as IElementNode].VariableType.IsValueType)
+ context.IL.Emit(OpCodes.Box, context.Variables[valueNode as IElementNode].VariableType);
+ context.IL.Emit(OpCodes.Callvirt, module.Import(setValue));
+ context.IL.Emit(OpCodes.Br, br);
+ context.IL.Append(brfalse);
+ handled = true;
+ }
+ }
+
+ //If it's a property, set it
+ // IL_0007: ldloc.0
+ // IL_0008: ldstr "foo"
+ // IL_000d: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.Label::set_Text(string)
+ PropertyDefinition property = elementType.GetProperty(pd => pd.Name == localName, out declaringTypeReference);
+ MethodDefinition propertySetter;
+ if (property != null && (propertySetter = property.SetMethod) != null && propertySetter.IsPublic)
+ {
+ module.Import(elementType.Resolve());
+ var propertySetterRef =
+ module.Import(module.Import(propertySetter).ResolveGenericParameters(declaringTypeReference, module));
+ propertySetterRef.ImportTypes(module);
+ var propertyType = property.ResolveGenericPropertyType(declaringTypeReference);
+ ValueNode vnode = null;
+
+ if ((vnode = valueNode as ValueNode) != null)
+ {
+ context.IL.Emit(OpCodes.Ldloc, parent);
+ context.IL.Append(vnode.PushConvertedValue(context,
+ propertyType,
+ new ICustomAttributeProvider[] { propertyType.Resolve() },
+ valueNode.PushServiceProvider(context), false, true));
+ context.IL.Emit(OpCodes.Callvirt, propertySetterRef);
+
+ context.IL.Append(br);
+ return;
+ }
+ if (valueNode is IElementNode)
+ {
+ var vardef = context.Variables[(ElementNode)valueNode];
+ var implicitOperators =
+ vardef.VariableType.GetMethods(md => md.IsPublic && md.IsStatic && md.IsSpecialName && md.Name == "op_Implicit",
+ module).ToList();
+ MethodReference implicitOperator = null;
+ if (implicitOperators.Any())
+ {
+ foreach (var op in implicitOperators)
+ {
+ var cast = op.Item1;
+ var opDeclTypeRef = op.Item2;
+ var castDef = module.Import(cast).ResolveGenericParameters(opDeclTypeRef, module);
+ var returnType = castDef.ReturnType;
+ if (returnType.IsGenericParameter)
+ returnType = ((GenericInstanceType)opDeclTypeRef).GenericArguments[((GenericParameter)returnType).Position];
+ if (returnType.FullName == propertyType.FullName &&
+ cast.Parameters[0].ParameterType.Name == vardef.VariableType.Name)
+ {
+ implicitOperator = castDef;
+ break;
+ }
+ }
+ }
+
+ //TODO replace latest check by a runtime type check
+ if (implicitOperator != null || vardef.VariableType.InheritsFromOrImplements(propertyType) ||
+ propertyType.FullName == "System.Object" || vardef.VariableType.FullName == "System.Object")
+ {
+ context.IL.Emit(OpCodes.Ldloc, parent);
+ context.IL.Emit(OpCodes.Ldloc, vardef);
+ if (implicitOperator != null)
+ {
+ // IL_000f: call !0 class [Xamarin.Forms.Core]Xamarin.Forms.OnPlatform`1<bool>::op_Implicit(class [Xamarin.Forms.Core]Xamarin.Forms.OnPlatform`1<!0>)
+ context.IL.Emit(OpCodes.Call, module.Import(implicitOperator));
+ }
+ else if (!vardef.VariableType.IsValueType && propertyType.IsValueType)
+ context.IL.Emit(OpCodes.Unbox_Any, module.Import(propertyType));
+ else if (vardef.VariableType.IsValueType && propertyType.FullName == "System.Object")
+ context.IL.Emit(OpCodes.Box, vardef.VariableType);
+ context.IL.Emit(OpCodes.Callvirt, propertySetterRef);
+ context.IL.Append(br);
+ return;
+ }
+ handled = true;
+ }
+ }
+
+ //If it's an already initialized property, add to it
+ MethodDefinition propertyGetter;
+ //TODO: check if property is assigned
+ if (property != null && (propertyGetter = property.GetMethod) != null && propertyGetter.IsPublic)
+ {
+ var propertyGetterRef = module.Import(propertyGetter);
+ propertyGetterRef = module.Import(propertyGetterRef.ResolveGenericParameters(declaringTypeReference, module));
+ var propertyType = propertyGetterRef.ReturnType.ResolveGenericParameters(declaringTypeReference);
+
+ //TODO check md.Parameters[0] type
+ var adderTuple =
+ propertyType.GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, module).FirstOrDefault();
+ if (adderTuple != null)
+ {
+ var adderRef = module.Import(adderTuple.Item1);
+ adderRef = module.Import(adderRef.ResolveGenericParameters(adderTuple.Item2, module));
+
+ if (valueNode is IElementNode)
+ {
+ context.IL.Emit(OpCodes.Ldloc, parent);
+ context.IL.Emit(OpCodes.Callvirt, propertyGetterRef);
+ context.IL.Emit(OpCodes.Ldloc, context.Variables[(ElementNode)valueNode]);
+ context.IL.Emit(OpCodes.Callvirt, adderRef);
+ if (adderRef.ReturnType.FullName != "System.Void")
+ context.IL.Emit(OpCodes.Pop);
+ context.IL.Append(br);
+ return;
+ }
+ }
+ }
+ if (!handled)
+ {
+ throw new XamlParseException(string.Format("No property, bindable property, or event found for '{0}'", localName),
+ iXmlLineInfo);
+ }
+ context.IL.Append(br);
+ }
+
+ static bool GetNameAndTypeRef(ref TypeReference elementType, string namespaceURI, ref string localname,
+ ILContext context, IXmlLineInfo lineInfo)
+ {
+ var dotIdx = localname.IndexOf('.');
+ if (dotIdx > 0)
+ {
+ var typename = localname.Substring(0, dotIdx);
+ localname = localname.Substring(dotIdx + 1);
+ elementType = new XmlType(namespaceURI, typename, null).GetTypeReference(context.Body.Method.Module, lineInfo);
+ return true;
+ }
+ return false;
+ }
+
+ static void SetDataTemplate(IElementNode parentNode, ElementNode node, ILContext parentContext,
+ IXmlLineInfo xmlLineInfo)
+ {
+ var parentVar = parentContext.Variables[parentNode];
+ //Push the DataTemplate to the stack, for setting the template
+ parentContext.IL.Emit(OpCodes.Ldloc, parentVar);
+
+ //Create nested class
+ // .class nested private auto ansi sealed beforefieldinit '<Main>c__AnonStorey0'
+ // extends [mscorlib]System.Object
+
+ var module = parentContext.Body.Method.Module;
+ var anonType = new TypeDefinition(
+ null,
+ "<" + parentContext.Body.Method.Name + ">_anonXamlCDataTemplate_" + dtcount++,
+ TypeAttributes.BeforeFieldInit |
+ TypeAttributes.Sealed |
+ TypeAttributes.NestedPrivate)
+ {
+ BaseType = module.TypeSystem.Object
+ };
+
+ parentContext.Body.Method.DeclaringType.NestedTypes.Add(anonType);
+ var ctor = anonType.AddDefaultConstructor();
+
+ var loadTemplate = new MethodDefinition("LoadDataTemplate",
+ MethodAttributes.Assembly | MethodAttributes.HideBySig,
+ module.TypeSystem.Object);
+ anonType.Methods.Add(loadTemplate);
+
+ var parentValues = new FieldDefinition("parentValues", FieldAttributes.Assembly, module.Import(typeof (object[])));
+ anonType.Fields.Add(parentValues);
+
+ TypeReference rootType = null;
+ var vdefRoot = parentContext.Root as VariableDefinition;
+ if (vdefRoot != null)
+ rootType = vdefRoot.VariableType;
+ var fdefRoot = parentContext.Root as FieldDefinition;
+ if (fdefRoot != null)
+ rootType = fdefRoot.FieldType;
+
+ var root = new FieldDefinition("root", FieldAttributes.Assembly, rootType);
+ anonType.Fields.Add(root);
+
+ //Fill the loadTemplate Body
+ var templateIl = loadTemplate.Body.GetILProcessor();
+ templateIl.Emit(OpCodes.Nop);
+ var templateContext = new ILContext(templateIl, loadTemplate.Body, parentValues)
+ {
+ Root = root
+ };
+ node.Accept(new CreateObjectVisitor(templateContext), null);
+ node.Accept(new SetNamescopesAndRegisterNamesVisitor(templateContext), null);
+ node.Accept(new SetFieldVisitor(templateContext), null);
+ node.Accept(new SetResourcesVisitor(templateContext), null);
+ node.Accept(new SetPropertiesVisitor(templateContext), null);
+ templateIl.Emit(OpCodes.Ldloc, templateContext.Variables[node]);
+ templateIl.Emit(OpCodes.Ret);
+
+ //Instanciate nested class
+ var parentIl = parentContext.IL;
+ parentIl.Emit(OpCodes.Newobj, ctor);
+
+ //Copy required local vars
+ parentIl.Emit(OpCodes.Dup); //Duplicate the nestedclass instance
+ parentIl.Append(node.PushParentObjectsArray(parentContext));
+ parentIl.Emit(OpCodes.Stfld, parentValues);
+ parentIl.Emit(OpCodes.Dup); //Duplicate the nestedclass instance
+ if (parentContext.Root is VariableDefinition)
+ parentIl.Emit(OpCodes.Ldloc, parentContext.Root as VariableDefinition);
+ else if (parentContext.Root is FieldDefinition)
+ {
+ parentIl.Emit(OpCodes.Ldarg_0);
+ parentIl.Emit(OpCodes.Ldfld, parentContext.Root as FieldDefinition);
+ }
+ else
+ throw new InvalidProgramException();
+ parentIl.Emit(OpCodes.Stfld, root);
+
+ //SetDataTemplate
+ parentIl.Emit(OpCodes.Ldftn, loadTemplate);
+ var funcCtor =
+ module.Import(typeof (Func<>))
+ .MakeGenericInstanceType(module.TypeSystem.Object)
+ .Resolve()
+ .Methods.First(md => md.IsConstructor && md.Parameters.Count == 2)
+ .MakeGeneric(module.TypeSystem.Object);
+ parentIl.Emit(OpCodes.Newobj, module.Import(funcCtor));
+
+ var propertySetter =
+ module.Import(typeof (IDataTemplate)).Resolve().Properties.First(p => p.Name == "LoadTemplate").SetMethod;
+ parentContext.IL.Emit(OpCodes.Callvirt, module.Import(propertySetter));
+ }
+ }
+
+ class VariableDefinitionReference
+ {
+ public VariableDefinitionReference(VariableDefinition vardef)
+ {
+ VariableDefinition = vardef;
+ }
+
+ public VariableDefinition VariableDefinition { get; set; }
+
+ public static implicit operator VariableDefinition(VariableDefinitionReference vardefref)
+ {
+ return vardefref.VariableDefinition;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/SetResourcesVisitor.cs b/Xamarin.Forms.Build.Tasks/SetResourcesVisitor.cs
new file mode 100644
index 00000000..c054117c
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/SetResourcesVisitor.cs
@@ -0,0 +1,141 @@
+using System;
+using System.Collections;
+using System.Linq;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ class SetResourcesVisitor : IXamlNodeVisitor
+ {
+ public SetResourcesVisitor(ILContext context)
+ {
+ Context = context;
+ Module = context.Body.Method.Module;
+ }
+
+ public ILContext Context { get; }
+
+ ModuleDefinition Module { get; }
+
+ public bool VisitChildrenFirst
+ {
+ get { return false; }
+ }
+
+ public bool StopOnDataTemplate
+ {
+ get { return true; }
+ }
+
+ public bool StopOnResourceDictionary
+ {
+ get { return false; }
+ }
+
+ public void Visit(ValueNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(MarkupNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(ElementNode node, INode parentNode)
+ {
+ //Set Resources in ResourcesDictionaries
+ if (IsCollectionItem(node, parentNode) && parentNode is IElementNode)
+ {
+ // Collection element, implicit content, or implicit collection element.
+ CustomAttribute cpAttr;
+ var parentVar = Context.Variables[(IElementNode)parentNode];
+ if (parentVar.VariableType.ImplementsInterface(Module.Import(typeof (IEnumerable))))
+ {
+ if (parentVar.VariableType.FullName == "Xamarin.Forms.ResourceDictionary" &&
+ !node.Properties.ContainsKey(XmlName.xKey))
+ {
+ node.Accept(new SetPropertiesVisitor(Context), parentNode);
+
+ if (node.XmlType.Name != "Style")
+ throw new XamlParseException("resources in ResourceDictionary require a x:Key attribute", node);
+
+ //if this node is an IMarkupExtension, invoke ProvideValue() and replace the variable
+ var vardef = Context.Variables[node];
+ var vardefref = new VariableDefinitionReference(vardef);
+ Context.IL.Append(SetPropertiesVisitor.ProvideValue(vardefref, Context, Module, node));
+ if (vardef != vardefref.VariableDefinition)
+ {
+ vardef = vardefref.VariableDefinition;
+ Context.Body.Variables.Add(vardef);
+ Context.Variables[node] = vardef;
+ }
+
+ Context.IL.Emit(OpCodes.Ldloc, parentVar);
+ Context.IL.Emit(OpCodes.Ldloc, Context.Variables[node]);
+ Context.IL.Emit(OpCodes.Callvirt,
+ Module.Import(
+ Module.Import(typeof (ResourceDictionary))
+ .Resolve()
+ .Methods.Single(md => md.Name == "Add" && md.Parameters.Count == 1)));
+ }
+ else if (parentVar.VariableType.FullName == "Xamarin.Forms.ResourceDictionary" &&
+ node.Properties.ContainsKey(XmlName.xKey))
+ {
+ node.Accept(new SetPropertiesVisitor(Context), parentNode);
+
+ //if this node is an IMarkupExtension, invoke ProvideValue() and replace the variable
+ var vardef = Context.Variables[node];
+ var vardefref = new VariableDefinitionReference(vardef);
+ Context.IL.Append(SetPropertiesVisitor.ProvideValue(vardefref, Context, Module, node));
+ if (vardef != vardefref.VariableDefinition)
+ {
+ vardef = vardefref.VariableDefinition;
+ Context.Body.Variables.Add(vardef);
+ Context.Variables[node] = vardef;
+ }
+
+ // IL_0013: ldloc.0
+ // IL_0014: ldstr "key"
+ // IL_0019: ldstr "foo"
+ // IL_001e: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.ResourceDictionary::Add(string, object)
+ Context.IL.Emit(OpCodes.Ldloc, parentVar);
+ Context.IL.Emit(OpCodes.Ldstr, (node.Properties[XmlName.xKey] as ValueNode).Value as string);
+ var varDef = Context.Variables[node];
+ Context.IL.Emit(OpCodes.Ldloc, varDef);
+ if (varDef.VariableType.IsValueType)
+ Context.IL.Emit(OpCodes.Box, Module.Import(varDef.VariableType));
+ Context.IL.Emit(OpCodes.Callvirt,
+ Module.Import(
+ Module.Import(typeof (ResourceDictionary))
+ .Resolve()
+ .Methods.Single(md => md.Name == "Add" && md.Parameters.Count == 2)));
+ }
+ }
+ }
+
+ //Set ResourcesDictionaries to their parents
+ XmlName propertyName;
+ if (SetPropertiesVisitor.TryGetPropertyName(node, parentNode, out propertyName) &&
+ (propertyName.LocalName == "Resources" || propertyName.LocalName.EndsWith(".Resources", StringComparison.Ordinal)) &&
+ Context.Variables[node].VariableType.FullName == "Xamarin.Forms.ResourceDictionary")
+ SetPropertiesVisitor.SetPropertyValue(Context.Variables[(IElementNode)parentNode], propertyName, node, Context, node);
+ }
+
+ public void Visit(RootNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(ListNode node, INode parentNode)
+ {
+ }
+
+ static bool IsCollectionItem(INode node, INode parentNode)
+ {
+ var parentList = parentNode as IListNode;
+ if (parentList == null)
+ return false;
+ return parentList.CollectionItems.Contains(node);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/TypeDefinitionExtensions.cs b/Xamarin.Forms.Build.Tasks/TypeDefinitionExtensions.cs
new file mode 100644
index 00000000..51b3fdbf
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/TypeDefinitionExtensions.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using MethodAttributes = Mono.Cecil.MethodAttributes;
+using MethodImplAttributes = Mono.Cecil.MethodImplAttributes;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ static class TypeDefinitionExtensions
+ {
+ public static MethodDefinition AddDefaultConstructor(this TypeDefinition targetType)
+ {
+ var parentType = typeof (object);
+
+ return AddDefaultConstructor(targetType, parentType);
+ }
+
+ public static MethodDefinition AddDefaultConstructor(this TypeDefinition targetType, Type parentType)
+ {
+ var module = targetType.Module;
+ var voidType = module.Import(typeof (void));
+ var methodAttributes = MethodAttributes.Public |
+ MethodAttributes.HideBySig |
+ MethodAttributes.SpecialName |
+ MethodAttributes.RTSpecialName;
+
+ var flags = BindingFlags.Public |
+ BindingFlags.NonPublic |
+ BindingFlags.Instance;
+
+ var objectConstructor = parentType.GetConstructor(flags, null, new Type[0], null);
+
+ if (objectConstructor == null)
+ objectConstructor = typeof (object).GetConstructor(new Type[0]);
+
+ var baseConstructor = module.Import(objectConstructor);
+
+ var ctor = new MethodDefinition(".ctor", methodAttributes, voidType)
+ {
+ CallingConvention = MethodCallingConvention.Default,
+ ImplAttributes = (MethodImplAttributes.IL | MethodImplAttributes.Managed)
+ };
+
+ var IL = ctor.Body.GetILProcessor();
+
+ IL.Emit(OpCodes.Ldarg_0);
+ IL.Emit(OpCodes.Call, baseConstructor);
+ IL.Emit(OpCodes.Ret);
+
+ targetType.Methods.Add(ctor);
+ return ctor;
+ }
+
+ public static IEnumerable<MethodDefinition> AllMethods(this TypeDefinition self)
+ {
+ while (self != null)
+ {
+ foreach (var md in self.Methods)
+ yield return md;
+ self = self.BaseType == null ? null : self.BaseType.Resolve();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs b/Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs
new file mode 100644
index 00000000..89a31765
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs
@@ -0,0 +1,222 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Mono.Cecil;
+using Mono.Cecil.Rocks;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ static class TypeReferenceExtensions
+ {
+ public static PropertyDefinition GetProperty(this TypeReference typeRef, Func<PropertyDefinition, bool> predicate,
+ out TypeReference declaringTypeRef)
+ {
+ declaringTypeRef = typeRef;
+ var typeDef = typeRef.Resolve();
+ var properties = typeDef.Properties.Where(predicate);
+ if (properties.Any())
+ return properties.Single();
+ if (typeDef.BaseType == null || typeDef.BaseType.FullName == "System.Object")
+ return null;
+ return typeDef.BaseType.GetProperty(predicate, out declaringTypeRef);
+ }
+
+ public static EventDefinition GetEvent(this TypeReference typeRef, Func<EventDefinition, bool> predicate)
+ {
+ var typeDef = typeRef.Resolve();
+ var events = typeDef.Events.Where(predicate);
+ if (events.Any())
+ return events.Single();
+ if (typeDef.BaseType == null || typeDef.BaseType.FullName == "System.Object")
+ return null;
+ return typeDef.BaseType.GetEvent(predicate);
+ }
+
+ public static FieldDefinition GetField(this TypeReference typeRef, Func<FieldDefinition, bool> predicate,
+ out TypeReference declaringTypeRef)
+ {
+ declaringTypeRef = typeRef;
+ var typeDef = typeRef.Resolve();
+ var bp = typeDef.Fields.Where
+ (predicate);
+ if (bp.Any())
+ return bp.Single();
+ if (typeDef.BaseType == null || typeDef.BaseType.FullName == "System.Object")
+ return null;
+ var basetype = typeDef.BaseType.ResolveGenericParameters(typeRef);
+ return basetype.GetField(predicate, out declaringTypeRef);
+ }
+
+ public static bool ImplementsInterface(this TypeReference typeRef, TypeReference @interface)
+ {
+ var typeDef = typeRef.Resolve();
+ if (typeDef.Interfaces.Any(tr => tr.FullName == @interface.FullName))
+ return true;
+ var baseTypeRef = typeDef.BaseType;
+ if (baseTypeRef != null && baseTypeRef.FullName != "System.Object")
+ return baseTypeRef.ImplementsInterface(@interface);
+ return false;
+ }
+
+ public static bool ImplementsGenericInterface(this TypeReference typeRef, string @interface,
+ out GenericInstanceType interfaceReference, out IList<TypeReference> genericArguments)
+ {
+ interfaceReference = null;
+ genericArguments = null;
+ var typeDef = typeRef.Resolve();
+ TypeReference iface;
+ if (
+ (iface =
+ typeDef.Interfaces.FirstOrDefault(
+ tr =>
+ tr.FullName.StartsWith(@interface) && tr.IsGenericInstance && (tr as GenericInstanceType).HasGenericArguments)) !=
+ null)
+ {
+ interfaceReference = iface as GenericInstanceType;
+ genericArguments = (iface as GenericInstanceType).GenericArguments;
+ return true;
+ }
+ var baseTypeRef = typeDef.BaseType;
+ if (baseTypeRef != null && baseTypeRef.FullName != "System.Object")
+ return baseTypeRef.ImplementsGenericInterface(@interface, out interfaceReference, out genericArguments);
+ return false;
+ }
+
+ public static bool InheritsFromOrImplements(this TypeReference typeRef, TypeReference baseClass)
+ {
+ var arrayInterfaces = new[]
+ {
+ "System.IEnumerable",
+ "System.Collections.IList",
+ "System.Collections.Collection"
+ };
+
+ var arrayGenericInterfaces = new[]
+ {
+ "System.IEnumerable`1",
+ "System.Collections.Generic.IList`1",
+ "System.Collections.Generic.IReadOnlyCollection<T>",
+ "System.Collections.Generic.IReadOnlyList<T>",
+ "System.Collections.Generic.Collection<T>"
+ };
+
+ if (typeRef.IsArray)
+ {
+ var arrayType = typeRef.Resolve();
+ if (arrayInterfaces.Contains(baseClass.FullName))
+ return true;
+ if (arrayGenericInterfaces.Contains(baseClass.Resolve().FullName) &&
+ baseClass.IsGenericInstance &&
+ (baseClass as GenericInstanceType).GenericArguments[0].FullName == arrayType.FullName)
+ return true;
+ }
+ var typeDef = typeRef.Resolve();
+ if (typeDef.FullName == baseClass.FullName)
+ return true;
+ if (typeDef.Interfaces.Any(ir => ir.FullName == baseClass.FullName))
+ return true;
+ if (typeDef.FullName == "System.Object")
+ return false;
+ if (typeDef.BaseType == null)
+ return false;
+ return typeDef.BaseType.InheritsFromOrImplements(baseClass);
+ }
+
+ public static CustomAttribute GetCustomAttribute(this TypeReference typeRef, TypeReference attribute)
+ {
+ var typeDef = typeRef.Resolve();
+ //FIXME: avoid string comparison. make sure the attribute TypeRef is the same one
+ var attr = typeDef.CustomAttributes.SingleOrDefault(ca => ca.AttributeType.FullName == attribute.FullName);
+ if (attr != null)
+ return attr;
+ var baseTypeRef = typeDef.BaseType;
+ if (baseTypeRef != null && baseTypeRef.FullName != "System.Object")
+ return baseTypeRef.GetCustomAttribute(attribute);
+ return null;
+ }
+
+ [Obsolete]
+ public static MethodDefinition GetMethod(this TypeReference typeRef, Func<MethodDefinition, bool> predicate)
+ {
+ TypeReference declaringTypeReference;
+ return typeRef.GetMethod(predicate, out declaringTypeReference);
+ }
+
+ [Obsolete]
+ public static MethodDefinition GetMethod(this TypeReference typeRef, Func<MethodDefinition, bool> predicate,
+ out TypeReference declaringTypeRef)
+ {
+ declaringTypeRef = typeRef;
+ var typeDef = typeRef.Resolve();
+ var methods = typeDef.Methods.Where(predicate);
+ if (methods.Any())
+ return methods.Single();
+ if (typeDef.BaseType != null && typeDef.BaseType.FullName == "System.Object")
+ return null;
+ if (typeDef.IsInterface)
+ {
+ foreach (var face in typeDef.Interfaces)
+ {
+ var m = face.GetMethod(predicate);
+ if (m != null)
+ return m;
+ }
+ return null;
+ }
+ return typeDef.BaseType.GetMethod(predicate, out declaringTypeRef);
+ }
+
+ public static IEnumerable<Tuple<MethodDefinition, TypeReference>> GetMethods(this TypeReference typeRef,
+ Func<MethodDefinition, bool> predicate, ModuleDefinition module)
+ {
+ return typeRef.GetMethods((md, tr) => predicate(md), module);
+ }
+
+ public static IEnumerable<Tuple<MethodDefinition, TypeReference>> GetMethods(this TypeReference typeRef,
+ Func<MethodDefinition, TypeReference, bool> predicate, ModuleDefinition module)
+ {
+ var typeDef = typeRef.Resolve();
+ foreach (var method in typeDef.Methods.Where(md => predicate(md, typeRef)))
+ yield return new Tuple<MethodDefinition, TypeReference>(method, typeRef);
+ if (typeDef.IsInterface)
+ {
+ foreach (var face in typeDef.Interfaces)
+ {
+ if (face.IsGenericInstance && typeRef is GenericInstanceType)
+ {
+ int i = 0;
+ foreach (var arg in ((GenericInstanceType)typeRef).GenericArguments)
+ ((GenericInstanceType)face).GenericArguments[i++] = module.Import(arg);
+ }
+ foreach (var tuple in face.GetMethods(predicate, module))
+ yield return tuple;
+ }
+ yield break;
+ }
+ if (typeDef.BaseType == null || typeDef.BaseType.FullName == "System.Object")
+ yield break;
+ var baseType = typeDef.BaseType.ResolveGenericParameters(typeRef);
+ foreach (var tuple in baseType.GetMethods(predicate, module))
+ yield return tuple;
+ }
+
+ public static TypeReference ResolveGenericParameters(this TypeReference self, TypeReference declaringTypeReference)
+ {
+ var genericself = self as GenericInstanceType;
+ if (genericself == null)
+ return self;
+
+ var genericdeclType = declaringTypeReference as GenericInstanceType;
+ if (genericdeclType == null)
+ return self;
+
+ if (!genericself.GenericArguments.Any(arg => arg.IsGenericParameter))
+ return self;
+
+ List<TypeReference> args = new List<TypeReference>();
+ for (var i = 0; i < genericself.GenericArguments.Count; i++)
+ args.Add(genericdeclType.GenericArguments[(genericself.GenericArguments[i] as GenericParameter).Position]);
+ return self.GetElementType().MakeGenericInstanceType(args.ToArray());
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/Xamarin.Forms.Build.Tasks.csproj b/Xamarin.Forms.Build.Tasks/Xamarin.Forms.Build.Tasks.csproj
new file mode 100644
index 00000000..0808dfdf
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/Xamarin.Forms.Build.Tasks.csproj
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <RootNamespace>Xamarin.Forms.Build.Tasks</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Build.Tasks</AssemblyName>
+ <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>full</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="Microsoft.Build.Framework" />
+ <Reference Include="Microsoft.Build.Utilities.v4.0" />
+ <Reference Include="Microsoft.Build" />
+ <Reference Include="System.Xml" />
+ <Reference Include="Microsoft.Build.Tasks.v4.0" />
+ <Reference Include="Mono.Cecil">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.dll</HintPath>
+ </Reference>
+ <Reference Include="Mono.Cecil.Mdb">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Mdb.dll</HintPath>
+ </Reference>
+ <Reference Include="Mono.Cecil.Pdb">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Pdb.dll</HintPath>
+ </Reference>
+ <Reference Include="Mono.Cecil.Rocks">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="..\Xamarin.Forms.Xaml\XmlnsHelper.cs">
+ <Link>XmlnsHelper.cs</Link>
+ </Compile>
+ <Compile Include="XamlGTask.cs" />
+ <Compile Include="ILContext.cs" />
+ <Compile Include="CreateObjectVisitor.cs" />
+ <Compile Include="SetPropertiesVisitor.cs" />
+ <Compile Include="SetFieldVisitor.cs" />
+ <Compile Include="TypeReferenceExtensions.cs" />
+ <Compile Include="NodeILExtensions.cs" />
+ <Compile Include="ILProcessorExtensions.cs" />
+ <Compile Include="ExpandMarkupsVisitor.cs" />
+ <Compile Include="SetNamescopesAndRegisterNamesVisitor.cs" />
+ <Compile Include="MethodReferenceExtensions.cs" />
+ <Compile Include="XamlCTask.cs" />
+ <Compile Include="DebugXamlCTask.cs" />
+ <Compile Include="ILRootNode.cs" />
+ <Compile Include="XmlTypeExtensions.cs" />
+ <Compile Include="SetResourcesVisitor.cs" />
+ <Compile Include="TypeDefinitionExtensions.cs" />
+ <Compile Include="FieldReferenceExtensions.cs" />
+ <Compile Include="PropertyDefinitionExtensions.cs" />
+ <Compile Include="XamlCAssemblyResolver.cs" />
+ <Compile Include="FixedCreateCSharpManifestResourceName.cs" />
+ <Compile Include="MethodDefinitionExtensions.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <Target Name="AfterBuild">
+ <ItemGroup>
+ <_CopyItems Include="$(TargetDir)*.dll" />
+ </ItemGroup>
+ <Copy SourceFiles="@(_CopyItems)" DestinationFolder="..\.nuspec\" ContinueOnError="true" />
+ </Target>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Xaml\Xamarin.Forms.Xaml.csproj">
+ <Project>{9DB2F292-8034-4E06-89AD-98BBDA4306B9}</Project>
+ <Name>Xamarin.Forms.Xaml</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj">
+ <Project>{984CC812-9470-4A13-AFF9-CC44068D666C}</Project>
+ <Name>ICSharpCode.Decompiler</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+ </Target>
+</Project>
diff --git a/Xamarin.Forms.Build.Tasks/XamlCAssemblyResolver.cs b/Xamarin.Forms.Build.Tasks/XamlCAssemblyResolver.cs
new file mode 100644
index 00000000..04f72c12
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/XamlCAssemblyResolver.cs
@@ -0,0 +1,15 @@
+using Mono.Cecil;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ class XamlCAssemblyResolver : DefaultAssemblyResolver
+ {
+ public void AddAssembly(string p)
+ {
+ RegisterAssembly(AssemblyDefinition.ReadAssembly(p, new ReaderParameters
+ {
+ AssemblyResolver = this
+ }));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/XamlCTask.cs b/Xamarin.Forms.Build.Tasks/XamlCTask.cs
new file mode 100644
index 00000000..81f06427
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/XamlCTask.cs
@@ -0,0 +1,417 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using ICSharpCode.Decompiler;
+using ICSharpCode.Decompiler.Ast;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Mono.Cecil.Rocks;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ public class XamlCTask : AppDomainIsolatedTask
+ {
+ string buffer = "";
+
+ bool hasCompiledXamlResources;
+
+ [Required]
+ public string Assembly { get; set; }
+
+ public string DependencyPaths { get; set; }
+
+ public string ReferencePath { get; set; }
+
+ public int Verbosity { get; set; }
+
+ public bool KeepXamlResources { get; set; }
+
+ public bool OptimizeIL { get; set; }
+
+ public bool DebugSymbols { get; set; }
+
+ public bool OutputGeneratedILAsCode { get; set; }
+
+ protected bool InMsBuild { get; set; }
+
+ public override bool Execute()
+ {
+ InMsBuild = true;
+ return Compile();
+ }
+
+ protected void LogError(string subcategory, string errorCode, string helpKeyword, string file, int lineNumber,
+ int columnNumber, int endLineNumber, int endColumnNumber, string message, params object[] messageArgs)
+ {
+ if (!string.IsNullOrEmpty(buffer))
+ LogLine(-1, null, null);
+ if (InMsBuild)
+ {
+ base.Log.LogError(subcategory, errorCode, helpKeyword, file, lineNumber, columnNumber, endLineNumber,
+ endColumnNumber, message, messageArgs);
+ }
+ else
+ Console.Error.WriteLine("{0} ({1}:{2}) : {3}", file, lineNumber, columnNumber, message);
+ }
+
+ protected void LogLine(int level, string format, params object[] arg)
+ {
+ if (!string.IsNullOrEmpty(buffer))
+ {
+ format = buffer + format;
+ buffer = "";
+ }
+
+ if (level < 0)
+ {
+ if (InMsBuild)
+ base.Log.LogError(format, arg);
+ else
+ Console.Error.WriteLine(format, arg);
+ }
+ else if (level <= Verbosity)
+ {
+ if (InMsBuild)
+ base.Log.LogMessage(format, arg);
+ else
+ Console.WriteLine(format, arg);
+ }
+ }
+
+ protected void Log(int level, string format, params object[] arg)
+ {
+ if (level <= 0)
+ Console.Error.Write(format, arg);
+ else if (level <= Verbosity)
+ {
+ if (InMsBuild)
+ buffer += String.Format(format, arg);
+ else
+ Console.Write(format, arg);
+ }
+ }
+
+ public static void Compile(string assemblyFileName, int verbosity = 0, bool keep = false, bool optimize = false,
+ string dependencyPaths = null, string referencePath = null, bool outputCSharp = false)
+ {
+ var xamlc = new XamlCTask
+ {
+ Assembly = assemblyFileName,
+ Verbosity = verbosity,
+ KeepXamlResources = keep,
+ OptimizeIL = optimize,
+ InMsBuild = false,
+ DependencyPaths = dependencyPaths,
+ ReferencePath = referencePath,
+ OutputGeneratedILAsCode = outputCSharp
+ };
+ xamlc.Compile();
+ }
+
+ public bool Compile()
+ {
+ LogLine(1, "Compiling Xaml");
+ LogLine(1, "\nAssembly: {0}", Assembly);
+ if (!string.IsNullOrEmpty(DependencyPaths))
+ LogLine(1, "DependencyPaths: \t{0}", DependencyPaths);
+ if (!string.IsNullOrEmpty(ReferencePath))
+ LogLine(1, "ReferencePath: \t{0}", ReferencePath.Replace("//", "/"));
+ LogLine(3, "DebugSymbols:\"{0}\"", DebugSymbols);
+ var skipassembly = true; //change this to false to enable XamlC by default
+ bool success = true;
+
+ if (!File.Exists(Assembly))
+ {
+ LogLine(1, "Assembly file not found. Skipping XamlC.");
+ return true;
+ }
+
+ var resolver = new XamlCAssemblyResolver();
+ if (!string.IsNullOrEmpty(DependencyPaths))
+ {
+ foreach (var dep in DependencyPaths.Split(';'))
+ {
+ LogLine(3, "Adding searchpath {0}", dep);
+ resolver.AddSearchDirectory(dep);
+ }
+ }
+
+ if (!string.IsNullOrEmpty(ReferencePath))
+ {
+ var paths = ReferencePath.Replace("//", "/").Split(';');
+ foreach (var p in paths)
+ {
+ var searchpath = Path.GetDirectoryName(p);
+ LogLine(3, "Adding searchpath {0}", searchpath);
+ resolver.AddSearchDirectory(searchpath);
+ // LogLine (3, "Referencing {0}", p);
+ // resolver.AddAssembly (p);
+ }
+ }
+
+ var assemblyDefinition = AssemblyDefinition.ReadAssembly(Path.GetFullPath(Assembly), new ReaderParameters
+ {
+ AssemblyResolver = resolver,
+ ReadSymbols = DebugSymbols
+ });
+
+ CustomAttribute xamlcAttr;
+ if (assemblyDefinition.HasCustomAttributes &&
+ (xamlcAttr =
+ assemblyDefinition.CustomAttributes.FirstOrDefault(
+ ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null)
+ {
+ var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value;
+ if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip)
+ skipassembly = true;
+ if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile)
+ skipassembly = false;
+ }
+
+ foreach (var module in assemblyDefinition.Modules)
+ {
+ var skipmodule = skipassembly;
+ if (module.HasCustomAttributes &&
+ (xamlcAttr =
+ module.CustomAttributes.FirstOrDefault(
+ ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null)
+ {
+ var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value;
+ if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip)
+ skipmodule = true;
+ if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile)
+ skipmodule = false;
+ }
+
+ LogLine(2, " Module: {0}", module.Name);
+ var resourcesToPrune = new List<EmbeddedResource>();
+ foreach (var resource in module.Resources.OfType<EmbeddedResource>())
+ {
+ Log(2, " Resource: {0}... ", resource.Name);
+ string classname;
+ if (!resource.IsXaml(out classname))
+ {
+ LogLine(2, "skipped.");
+ continue;
+ }
+ TypeDefinition typeDef = module.GetType(classname);
+ if (typeDef == null)
+ {
+ LogLine(2, "no type found... skipped.");
+ continue;
+ }
+ var skiptype = skipmodule;
+ if (typeDef.HasCustomAttributes &&
+ (xamlcAttr =
+ typeDef.CustomAttributes.FirstOrDefault(
+ ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null)
+ {
+ var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value;
+ if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip)
+ skiptype = true;
+ if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile)
+ skiptype = false;
+ }
+ if (skiptype)
+ {
+ LogLine(2, "Has XamlCompilationAttribute set to Skip and not Compile... skipped");
+ continue;
+ }
+
+ var initComp = typeDef.Methods.FirstOrDefault(md => md.Name == "InitializeComponent");
+ if (initComp == null)
+ {
+ LogLine(2, "no InitializeComponent found... skipped.");
+ continue;
+ }
+ LogLine(2, "");
+
+ Log(2, " Parsing Xaml... ");
+ var rootnode = ParseXaml(resource.GetResourceStream(), typeDef);
+ if (rootnode == null)
+ {
+ LogLine(2, "failed.");
+ continue;
+ }
+ LogLine(2, "done.");
+
+ hasCompiledXamlResources = true;
+
+ try
+ {
+ Log(2, " Replacing {0}.InitializeComponent ()... ", typeDef.Name);
+ var body = new MethodBody(initComp);
+ var il = body.GetILProcessor();
+ il.Emit(OpCodes.Nop);
+ var visitorContext = new ILContext(il, body);
+
+ rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null);
+ rootnode.Accept(new ExpandMarkupsVisitor(visitorContext), null);
+ rootnode.Accept(new CreateObjectVisitor(visitorContext), null);
+ rootnode.Accept(new SetNamescopesAndRegisterNamesVisitor(visitorContext), null);
+ rootnode.Accept(new SetFieldVisitor(visitorContext), null);
+ rootnode.Accept(new SetResourcesVisitor(visitorContext), null);
+ rootnode.Accept(new SetPropertiesVisitor(visitorContext, true), null);
+
+ il.Emit(OpCodes.Ret);
+ initComp.Body = body;
+ }
+ catch (XamlParseException xpe)
+ {
+ LogLine(2, "failed.");
+ LogError(null, null, null, resource.Name, xpe.XmlInfo.LineNumber, xpe.XmlInfo.LinePosition, 0, 0, xpe.Message,
+ xpe.HelpLink, xpe.Source);
+ LogLine(4, xpe.StackTrace);
+ success = false;
+ continue;
+ }
+ catch (XmlException xe)
+ {
+ LogLine(2, "failed.");
+ LogError(null, null, null, resource.Name, xe.LineNumber, xe.LinePosition, 0, 0, xe.Message, xe.HelpLink, xe.Source);
+ LogLine(4, xe.StackTrace);
+ success = false;
+ continue;
+ }
+ catch (Exception e)
+ {
+ LogLine(2, "failed.");
+ LogError(null, null, null, resource.Name, 0, 0, 0, 0, e.Message, e.HelpLink, e.Source);
+ LogLine(4, e.StackTrace);
+ success = false;
+ continue;
+ }
+ LogLine(2, "done.");
+
+ if (OptimizeIL)
+ {
+ Log(2, " Optimizing IL... ");
+ initComp.Body.OptimizeMacros();
+ LogLine(2, "done");
+ }
+
+ if (OutputGeneratedILAsCode)
+ {
+ var filepath = Path.Combine(Path.GetDirectoryName(Assembly), typeDef.FullName + ".decompiled.cs");
+ Log(2, " Decompiling {0} into {1}...", typeDef.FullName, filepath);
+ var decompilerContext = new DecompilerContext(module);
+ using(var writer = new StreamWriter(filepath))
+ {
+ var output = new PlainTextOutput(writer);
+
+ var codeDomBuilder = new AstBuilder(decompilerContext);
+ codeDomBuilder.AddType(typeDef);
+ codeDomBuilder.GenerateCode(output);
+ }
+
+ LogLine(2, "done");
+ }
+ resourcesToPrune.Add(resource);
+ }
+ if (!KeepXamlResources)
+ {
+ if (resourcesToPrune.Any())
+ LogLine(2, " Removing compiled xaml resources");
+ foreach (var resource in resourcesToPrune)
+ {
+ Log(2, " Removing {0}... ", resource.Name);
+ module.Resources.Remove(resource);
+ LogLine(2, "done");
+ }
+ }
+
+ LogLine(2, "");
+ }
+
+ if (!hasCompiledXamlResources)
+ {
+ LogLine(1, "No compiled resources. Skipping writing assembly.");
+ return success;
+ }
+
+ Log(1, "Writing the assembly... ");
+ try
+ {
+ assemblyDefinition.Write(Assembly, new WriterParameters
+ {
+ WriteSymbols = DebugSymbols
+ });
+ LogLine(1, "done.");
+ }
+ catch (Exception e)
+ {
+ LogLine(1, "failed.");
+ LogError(null, null, null, null, 0, 0, 0, 0, e.Message, e.HelpLink, e.Source);
+ LogLine(4, e.StackTrace);
+ success = false;
+ }
+
+ return success;
+ }
+
+ static ILRootNode ParseXaml(Stream stream, TypeReference typeReference)
+ {
+ ILRootNode rootnode = null;
+ using(var reader = XmlReader.Create(stream))
+ {
+ while (reader.Read())
+ {
+ //Skip until element
+ if (reader.NodeType == XmlNodeType.Whitespace)
+ continue;
+ if (reader.NodeType != XmlNodeType.Element)
+ {
+ Debug.WriteLine("Unhandled node {0} {1} {2}", reader.NodeType, reader.Name, reader.Value);
+ continue;
+ }
+
+ XamlParser.ParseXaml(
+ rootnode = new ILRootNode(new XmlType(reader.NamespaceURI, reader.Name, null), typeReference), reader);
+ break;
+ }
+ }
+ return rootnode;
+ }
+ }
+
+ static class CecilExtensions
+ {
+ public static bool IsXaml(this EmbeddedResource resource, out string classname)
+ {
+ classname = null;
+ if (!resource.Name.EndsWith(".xaml", StringComparison.InvariantCulture))
+ return false;
+
+ using(var resourceStream = resource.GetResourceStream())
+ {
+ var xmlDoc = new XmlDocument();
+ xmlDoc.Load(resourceStream);
+
+ var nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
+
+ var root = xmlDoc.SelectSingleNode("/*", nsmgr);
+ if (root == null)
+ {
+ // Log (2, "No root found... ");
+ return false;
+ }
+
+ var rootClass = root.Attributes["Class", "http://schemas.microsoft.com/winfx/2006/xaml"] ??
+ root.Attributes["Class", "http://schemas.microsoft.com/winfx/2009/xaml"];
+ if (rootClass == null)
+ {
+ // Log (2, "no x:Class found... ");
+ return false;
+ }
+ classname = rootClass.Value;
+ return true;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/XamlGTask.cs b/Xamarin.Forms.Build.Tasks/XamlGTask.cs
new file mode 100644
index 00000000..28158e6b
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/XamlGTask.cs
@@ -0,0 +1,261 @@
+using System;
+using System.CodeDom;
+using System.CodeDom.Compiler;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using Microsoft.CSharp;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ public class XamlGTask : Task
+ {
+ internal static CodeDomProvider Provider = new CSharpCodeProvider();
+
+ [Required]
+ public string Source { get; set; }
+
+ public string Language { get; set; }
+
+ public string AssemblyName { get; set; }
+
+ [Output]
+ public string OutputFile { get; set; }
+
+ public override bool Execute()
+ {
+ if (Source == null || OutputFile == null)
+ {
+ Log.LogMessage("Skipping XamlG");
+ return true;
+ }
+
+ Log.LogMessage("Source: {0}", Source);
+ Log.LogMessage("Language: {0}", Language);
+ Log.LogMessage("AssemblyName: {0}", AssemblyName);
+ Log.LogMessage("OutputFile {0}", OutputFile);
+
+ try
+ {
+ GenerateFile(Source, OutputFile);
+ return true;
+ }
+ catch (XmlException xe)
+ {
+ Log.LogError(null, null, null, Source, xe.LineNumber, xe.LinePosition, 0, 0, xe.Message, xe.HelpLink, xe.Source);
+
+ return false;
+ }
+ catch (Exception e)
+ {
+ Log.LogError(null, null, null, Source, 0, 0, 0, 0, e.Message, e.HelpLink, e.Source);
+ return false;
+ }
+ }
+
+ internal static void ParseXaml(TextReader xaml, out string rootType, out string rootNs, out CodeTypeReference baseType,
+ out IDictionary<string, CodeTypeReference> namesAndTypes)
+ {
+ var xmlDoc = new XmlDocument();
+ xmlDoc.Load(xaml);
+
+ var nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
+ nsmgr.AddNamespace("x", "http://schemas.microsoft.com/winfx/2006/xaml");
+ nsmgr.AddNamespace("x2009", "http://schemas.microsoft.com/winfx/2009/xaml");
+ nsmgr.AddNamespace("f", "http://xamarin.com/schemas/2014/forms");
+
+ var root = xmlDoc.SelectSingleNode("/*", nsmgr);
+ if (root == null)
+ {
+ Console.Error.WriteLine("{0}: No root node found");
+ rootType = null;
+ rootNs = null;
+ baseType = null;
+ namesAndTypes = null;
+ return;
+ }
+
+ var rootClass = root.Attributes["Class", "http://schemas.microsoft.com/winfx/2006/xaml"] ??
+ root.Attributes["Class", "http://schemas.microsoft.com/winfx/2009/xaml"];
+ if (rootClass == null)
+ {
+ rootType = null;
+ rootNs = null;
+ baseType = null;
+ namesAndTypes = null;
+ return;
+ }
+
+ string rootAsm;
+ XmlnsHelper.ParseXmlns(rootClass.Value, out rootType, out rootNs, out rootAsm);
+ namesAndTypes = GetNamesAndTypes(root, nsmgr);
+
+ var typeArguments = root.Attributes["TypeArguments", "http://schemas.microsoft.com/winfx/2009/xaml"];
+
+ baseType = GetType(root.NamespaceURI, root.LocalName, typeArguments == null ? null : typeArguments.Value.Split(','),
+ root.GetNamespaceOfPrefix);
+ }
+
+ internal static void GenerateCode(string rootType, string rootNs, CodeTypeReference baseType,
+ IDictionary<string, CodeTypeReference> namesAndTypes, string outFile)
+ {
+ if (rootType == null)
+ {
+ File.WriteAllText(outFile, "");
+ return;
+ }
+
+ var ccu = new CodeCompileUnit();
+ var declNs = new CodeNamespace(rootNs);
+ ccu.Namespaces.Add(declNs);
+
+ declNs.Imports.Add(new CodeNamespaceImport("System"));
+ declNs.Imports.Add(new CodeNamespaceImport("Xamarin.Forms"));
+ declNs.Imports.Add(new CodeNamespaceImport("Xamarin.Forms.Xaml"));
+
+ var declType = new CodeTypeDeclaration(rootType);
+ declType.IsPartial = true;
+ declType.BaseTypes.Add(baseType);
+
+ declNs.Types.Add(declType);
+
+ var initcomp = new CodeMemberMethod
+ {
+ Name = "InitializeComponent",
+ CustomAttributes =
+ {
+ new CodeAttributeDeclaration(new CodeTypeReference(typeof (GeneratedCodeAttribute)),
+ new CodeAttributeArgument(new CodePrimitiveExpression("Xamarin.Forms.Build.Tasks.XamlG")),
+ new CodeAttributeArgument(new CodePrimitiveExpression("0.0.0.0")))
+ }
+ };
+ declType.Members.Add(initcomp);
+
+ initcomp.Statements.Add(new CodeMethodInvokeExpression(
+ new CodeThisReferenceExpression(),
+ "LoadFromXaml", new CodeTypeOfExpression(declType.Name)));
+
+ foreach (var entry in namesAndTypes)
+ {
+ string name = entry.Key;
+ var type = entry.Value;
+
+ var field = new CodeMemberField
+ {
+ Name = name,
+ Type = type,
+ CustomAttributes =
+ {
+ new CodeAttributeDeclaration(new CodeTypeReference(typeof (GeneratedCodeAttribute)),
+ new CodeAttributeArgument(new CodePrimitiveExpression("Xamarin.Forms.Build.Tasks.XamlG")),
+ new CodeAttributeArgument(new CodePrimitiveExpression("0.0.0.0")))
+ }
+ };
+
+ declType.Members.Add(field);
+
+ var find_invoke = new CodeMethodInvokeExpression(
+ new CodeMethodReferenceExpression(
+ new CodeThisReferenceExpression(),
+ "FindByName", type), new CodePrimitiveExpression(name));
+
+ //CodeCastExpression cast = new CodeCastExpression (type, find_invoke);
+
+ CodeAssignStatement assign = new CodeAssignStatement(
+ new CodeVariableReferenceExpression(name), find_invoke);
+
+ initcomp.Statements.Add(assign);
+ }
+
+ using(var writer = new StreamWriter(outFile))
+ Provider.GenerateCodeFromCompileUnit(ccu, writer, new CodeGeneratorOptions());
+ }
+
+ internal static void GenerateFile(string xamlFile, string outFile)
+ {
+ string rootType, rootNs;
+ CodeTypeReference baseType;
+ IDictionary<string, CodeTypeReference> namesAndTypes;
+ using(StreamReader reader = File.OpenText(xamlFile))
+ ParseXaml(reader, out rootType, out rootNs, out baseType, out namesAndTypes);
+ GenerateCode(rootType, rootNs, baseType, namesAndTypes, outFile);
+ }
+
+ static Dictionary<string, CodeTypeReference> GetNamesAndTypes(XmlNode root, XmlNamespaceManager nsmgr)
+ {
+ var res = new Dictionary<string, CodeTypeReference>();
+
+ foreach (string attrib in new[] { "x:Name", "x2009:Name" })
+ {
+ XmlNodeList names =
+ root.SelectNodes(
+ "//*[@" + attrib +
+ "][not(ancestor:: f:DataTemplate) and not(ancestor:: f:ControlTemplate) and not(ancestor:: f:Style)]", nsmgr);
+ foreach (XmlNode node in names)
+ {
+ // Don't take the root canvas
+ if (node == root)
+ continue;
+
+ XmlAttribute attr = node.Attributes["Name", "http://schemas.microsoft.com/winfx/2006/xaml"] ??
+ node.Attributes["Name", "http://schemas.microsoft.com/winfx/2009/xaml"];
+ XmlAttribute typeArgsAttr = node.Attributes["x:TypeArguments"];
+ var typeArgsList = typeArgsAttr == null ? null : typeArgsAttr.Value.Split(',').ToList();
+ string name = attr.Value;
+
+ res[name] = GetType(node.NamespaceURI, node.LocalName, typeArgsList, node.GetNamespaceOfPrefix);
+ }
+ }
+
+ return res;
+ }
+
+ static CodeTypeReference GetType(string nsuri, string type, IList<string> typeArguments = null,
+ Func<string, string> getNamespaceOfPrefix = null)
+ {
+ var ns = GetNamespace(nsuri);
+ if (ns != null)
+ type = String.Concat(ns, ".", type);
+
+ if (typeArguments != null)
+ type = String.Concat(type, "`", typeArguments.Count);
+
+ var returnType = new CodeTypeReference(type);
+ if (ns != null)
+ returnType.Options |= CodeTypeReferenceOptions.GlobalReference;
+
+ if (typeArguments != null)
+ {
+ foreach (var typeArg in typeArguments)
+ {
+ var ns_uri = "";
+ var _type = typeArg;
+ if (typeArg.Contains(":"))
+ {
+ var prefix = typeArg.Split(':')[0].Trim();
+ ns_uri = getNamespaceOfPrefix(prefix);
+ _type = typeArg.Split(':')[1].Trim();
+ }
+ returnType.TypeArguments.Add(GetType(ns_uri, _type, null, getNamespaceOfPrefix));
+ }
+ }
+
+ return returnType;
+ }
+
+ static string GetNamespace(string namespaceuri)
+ {
+ if (!XmlnsHelper.IsCustom(namespaceuri))
+ return "Xamarin.Forms";
+ if (namespaceuri == "http://schemas.microsoft.com/winfx/2009/xaml")
+ return "System";
+ if (namespaceuri != "http://schemas.microsoft.com/winfx/2006/xaml" && !namespaceuri.Contains("clr-namespace"))
+ throw new Exception(String.Format("Can't load types from xmlns {0}", namespaceuri));
+ return XmlnsHelper.ParseNamespaceFromXmlns(namespaceuri);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/XmlTypeExtensions.cs b/Xamarin.Forms.Build.Tasks/XmlTypeExtensions.cs
new file mode 100644
index 00000000..e0810633
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/XmlTypeExtensions.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml;
+using Mono.Cecil;
+using Mono.Cecil.Rocks;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Build.Tasks
+{
+ static class XmlTypeExtensions
+ {
+ public static TypeReference GetTypeReference(this XmlType xmlType, ModuleDefinition module, IXmlLineInfo xmlInfo)
+ {
+ var namespaceURI = xmlType.NamespaceUri;
+ var elementName = xmlType.Name;
+ var typeArguments = xmlType.TypeArguments;
+
+ List<Tuple<string, string>> lookupAssemblies = new List<Tuple<string, string>>(); //assembly, namespace
+ List<string> lookupNames = new List<string>();
+
+ if (!XmlnsHelper.IsCustom(namespaceURI))
+ {
+ lookupAssemblies.Add(new Tuple<string, string>("Xamarin.Forms.Core", "Xamarin.Forms"));
+ lookupAssemblies.Add(new Tuple<string, string>("Xamarin.Forms.Xaml", "Xamarin.Forms.Xaml"));
+ }
+ else if (namespaceURI == "http://schemas.microsoft.com/winfx/2009/xaml" ||
+ namespaceURI == "http://schemas.microsoft.com/winfx/2006/xaml")
+ {
+ lookupAssemblies.Add(new Tuple<string, string>("Xamarin.Forms.Xaml", "Xamarin.Forms.Xaml"));
+ lookupAssemblies.Add(new Tuple<string, string>("mscorlib", "System"));
+ lookupAssemblies.Add(new Tuple<string, string>("System", "System"));
+ }
+ else
+ {
+ string ns;
+ string typename;
+ string asmstring;
+
+ XmlnsHelper.ParseXmlns(namespaceURI, out typename, out ns, out asmstring);
+ asmstring = asmstring ?? module.Assembly.Name.Name;
+ lookupAssemblies.Add(new Tuple<string, string>(asmstring, ns));
+ }
+
+ lookupNames.Add(elementName);
+ if (namespaceURI == "http://schemas.microsoft.com/winfx/2009/xaml")
+ lookupNames.Add(elementName + "Extension");
+ for (var i = 0; i < lookupNames.Count; i++)
+ {
+ var name = lookupNames[i];
+ if (name.Contains(":"))
+ name = name.Substring(name.LastIndexOf(':') + 1);
+ if (typeArguments != null)
+ name += "`" + typeArguments.Count; //this will return an open generic Type
+ lookupNames[i] = name;
+ }
+
+ TypeReference type = null;
+ foreach (var asm in lookupAssemblies)
+ {
+ if (type != null)
+ break;
+ foreach (var name in lookupNames)
+ {
+ if (type != null)
+ break;
+
+ var assemblydefinition = module.Assembly.Name.Name == asm.Item1
+ ? module.Assembly
+ : module.AssemblyResolver.Resolve(asm.Item1);
+ type = assemblydefinition.MainModule.GetType(asm.Item2, name);
+ if (type == null)
+ {
+ var exportedtype =
+ assemblydefinition.MainModule.ExportedTypes.FirstOrDefault(
+ (ExportedType arg) => arg.IsForwarder && arg.Namespace == asm.Item2 && arg.Name == name);
+ if (exportedtype != null)
+ type = exportedtype.Resolve();
+ }
+ }
+ }
+
+ if (type != null && typeArguments != null && type.HasGenericParameters)
+ {
+ type =
+ module.Import(type)
+ .MakeGenericInstanceType(typeArguments.Select(x => GetTypeReference(x, module, xmlInfo)).ToArray());
+ }
+
+ if (type == null)
+ throw new XamlParseException(string.Format("Type {0} not found in xmlns {1}", elementName, namespaceURI), xmlInfo);
+
+ return module.Import(type);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Build.Tasks/packages.config b/Xamarin.Forms.Build.Tasks/packages.config
new file mode 100644
index 00000000..2821c6e5
--- /dev/null
+++ b/Xamarin.Forms.Build.Tasks/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Mono.Cecil" version="0.9.6.1" targetFramework="net451" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Android/Activity1.cs b/Xamarin.Forms.ControlGallery.Android/Activity1.cs
new file mode 100644
index 00000000..3426ce21
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Activity1.cs
@@ -0,0 +1,412 @@
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Reflection;
+
+using Android.App;
+using Android.Content;
+using Android.Content.PM;
+using Android.Runtime;
+using Android.Views;
+using Android.Widget;
+using Android.OS;
+using Xamarin.Forms;
+using Xamarin.Forms.ControlGallery.Android;
+using Xamarin.Forms.Controls;
+using Xamarin.Forms.Maps.Android;
+using Xamarin.Forms.Platform.Android;
+using System.IO;
+using System.IO.IsolatedStorage;
+
+using Droid = Android;
+
+
+[assembly: Dependency (typeof (CacheService))]
+[assembly: Dependency (typeof (TestCloudService))]
+[assembly: Dependency (typeof (StringProvider))]
+[assembly: ExportRenderer (typeof (DisposePage), typeof (DisposePageRenderer))]
+[assembly: ExportRenderer (typeof (DisposeLabel), typeof (DisposeLabelRenderer))]
+[assembly: ExportRenderer (typeof (CustomButton), typeof (CustomButtonRenderer))]
+[assembly: ExportEffect (typeof (BorderEffect), "BorderEffect")]
+
+namespace Xamarin.Forms.ControlGallery.Android
+{
+ public class BorderEffect : PlatformEffect
+ {
+ protected override void OnAttached ()
+ {
+ Control.SetBackgroundColor (global::Android.Graphics.Color.Aqua);
+ }
+
+ protected override void OnDetached ()
+ {
+ }
+
+ protected override void OnElementPropertyChanged (PropertyChangedEventArgs args)
+ {
+ base.OnElementPropertyChanged (args);
+ }
+ }
+
+ public class CacheService : ICacheService
+ {
+ public void ClearImageCache ()
+ {
+ DeleteFilesInDirectory ("ImageLoaderCache");
+ }
+
+ static void DeleteFilesInDirectory (string directory)
+ {
+ using (IsolatedStorageFile isolatedStorage = IsolatedStorageFile.GetUserStoreForApplication ()) {
+ if (isolatedStorage.DirectoryExists (directory)) {
+ var files = isolatedStorage.GetFileNames (Path.Combine (directory, "*"));
+ foreach (string file in files) {
+ isolatedStorage.DeleteFile (Path.Combine (directory, file));
+ }
+ }
+ }
+ }
+ }
+
+ public class DisposePageRenderer : PageRenderer
+ {
+ protected override void Dispose (bool disposing)
+ {
+ if (disposing) {
+ ((DisposePage) Element).SendRendererDisposed ();
+ }
+ base.Dispose (disposing);
+
+ }
+ }
+
+ public class DisposeLabelRenderer : LabelRenderer
+ {
+ protected override void Dispose (bool disposing)
+ {
+
+ if (disposing) {
+ ((DisposeLabel) Element).SendRendererDisposed ();
+ }
+ base.Dispose (disposing);
+ }
+ }
+
+ public class StringProvider : IStringProvider
+ {
+ public string CoreGalleryTitle
+ {
+ get
+ {
+ return "Android CoreGallery";
+ }
+ }
+ }
+
+ public class TestCloudService : ITestCloudService
+ {
+ public bool IsOnTestCloud ()
+ {
+ var isInTestCloud = System.Environment.GetEnvironmentVariable ("XAMARIN_TEST_CLOUD");
+
+ return isInTestCloud != null && isInTestCloud.Equals ("1");
+ }
+
+ public string GetTestCloudDeviceName ()
+ {
+ return System.Environment.GetEnvironmentVariable ("XTC_DEVICE_NAME");
+ }
+
+ public string GetTestCloudDevice ()
+ {
+ return System.Environment.GetEnvironmentVariable ("XTC_DEVICE");
+ }
+ }
+
+#if PRE_APPLICATION_CLASS
+ [Activity (Label = "Control Gallery",
+ Icon = "@drawable/icon",
+ MainLauncher = true,
+ HardwareAccelerated = true,
+ ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
+ public class Activity1 : AndroidActivity
+ {
+
+
+ protected override void OnCreate (Bundle bundle)
+ {
+ base.OnCreate (bundle);
+
+ Forms.Init (this, bundle);
+ FormsMaps.Init (this, bundle);
+
+ SetPage (FormsApp.GetFormsApp ());
+
+ MessagingCenter.Subscribe<RootPagesGallery, Type> (this, Messages.ChangeRoot, (sender, pageType) => {
+ var page = ((Page)Activator.CreateInstance (pageType));
+ SetPage (page);
+ });
+
+ MessagingCenter.Subscribe<RootPagesGallery, Type> (this, Messages.ChangeRoot, (sender, pageType) => {
+ var page = ((Page)Activator.CreateInstance (pageType));
+ SetPage (page);
+ });
+
+ MessagingCenter.Subscribe<HomeButton> (this, Messages.GoHome, (sender) => {
+ var screen = FormsApp.GetFormsApp ();
+ SetPage (screen);
+ });
+ }
+
+ public override void OnConfigurationChanged (global::Android.Content.Res.Configuration newConfig)
+ {
+ // we're good
+ base.OnConfigurationChanged (newConfig);
+ }
+
+ protected override void OnDestroy ()
+ {
+ base.OnDestroy ();
+ }
+ }
+
+#elif FORMS_APPLICATION_ACTIVITY
+ [Activity(Label = "Control Gallery",
+ Icon = "@drawable/icon",
+ // Theme="@style/TestStyle",
+ MainLauncher = true,
+ HardwareAccelerated = true,
+ ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
+
+ public class Activity1 : FormsApplicationActivity
+ {
+ protected override void OnCreate(Bundle bundle)
+ {
+ //ToolbarResource = Resource.Layout.Toolbar;
+ //TabLayoutResource = Resource.Layout.Tabbar;
+
+ base.OnCreate(bundle);
+
+ if (!Debugger.IsAttached)
+ Insights.Initialize(App.InsightsApiKey, this.ApplicationContext);
+
+ Forms.Init(this, bundle);
+ FormsMaps.Init(this, bundle);
+ Xamarin.Forms.Forms.ViewInitialized += (object sender, Xamarin.Forms.ViewInitializedEventArgs e) => {
+ if (!string.IsNullOrWhiteSpace(e.View.StyleId))
+ {
+ e.NativeView.ContentDescription = e.View.StyleId;
+ }
+ };
+ // uncomment to verify turning off title bar works. This is not intended to be dynamic really.
+ //Forms.SetTitleBarVisibility (AndroidTitleBarVisibility.Never);
+
+ var app = new App ();
+
+ var mdp = app.MainPage as MasterDetailPage;
+ var detail = mdp?.Detail as NavigationPage;
+ if (detail != null) {
+ detail.Pushed += (sender, args) => {
+ var nncgPage = args.Page as NestedNativeControlGalleryPage;
+
+ if (nncgPage != null) {
+ AddNativeControls (nncgPage);
+ }
+ };
+ }
+
+ LoadApplication (app);
+ }
+
+ private void AddNativeControls (NestedNativeControlGalleryPage page)
+ {
+ if (page.NativeControlsAdded) {
+ return;
+ }
+
+ StackLayout sl = page.Layout;
+
+ // Create and add a native TextView
+ var textView = new TextView (this) { Text = "I am a native TextView", TextSize = 14 };
+ sl?.Children.Add (textView);
+
+ // Create and add a native Button
+ var button = new global::Android.Widget.Button (this) { Text = "Click to change TextView font size" };
+ float originalSize = textView.TextSize;
+ button.Click += (sender, args) => { textView.TextSize = textView.TextSize == originalSize ? 24 : 14; };
+
+ sl?.Children.Add (button.ToView ());
+
+ // Create a control which we know doesn't behave correctly with regard to measurement
+ var difficultControl0 = new BrokenNativeControl (this) {
+ Text = "This native control doesn't play nice with sizing, which is why it's all squished to one side."
+ };
+ var difficultControl1 = new BrokenNativeControl (this) {
+ Text = "Same control, but with a custom GetDesiredSize delegate to accomodate it's sizing problems."
+ };
+
+ // Add a misbehaving control
+ sl?.Children.Add (difficultControl0);
+
+ // Add a misbehaving control with a custom delegate for GetDesiredSize
+ sl?.Children.Add (difficultControl1, SizeBrokenControl);
+
+ page.NativeControlsAdded = true;
+ }
+
+ private static SizeRequest? SizeBrokenControl (NativeViewWrapperRenderer renderer,
+ int widthConstraint, int heightConstraint)
+ {
+ global::Android.Views.View nativeView = renderer.Control;
+
+ if ((widthConstraint == 0 && heightConstraint == 0) || nativeView == null) {
+ return null;
+ }
+
+ int width = global::Android.Views.View.MeasureSpec.GetSize (widthConstraint);
+ int widthSpec = global::Android.Views.View.MeasureSpec.MakeMeasureSpec (width * 2,
+ global::Android.Views.View.MeasureSpec.GetMode (widthConstraint));
+ nativeView.Measure (widthSpec, heightConstraint);
+ var size = new Size (nativeView.MeasuredWidth, nativeView.MeasuredHeight);
+ return new SizeRequest (size);
+ }
+
+ public override void OnConfigurationChanged(global::Android.Content.Res.Configuration newConfig)
+ {
+ // we're good
+ base.OnConfigurationChanged(newConfig);
+ }
+
+ protected override void OnDestroy()
+ {
+ base.OnDestroy();
+ }
+ }
+#else
+
+ [Activity (Label = "Control Gallery",
+ Icon = "@drawable/icon",
+ Theme = "@style/MyTheme",
+ MainLauncher = true,
+ HardwareAccelerated = true,
+ ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
+ [IntentFilter (new[] { Intent.ActionView },
+ Categories = new[]
+ {
+ Intent.ActionView,
+ Intent.CategoryDefault,
+ Intent.CategoryBrowsable
+ },
+ DataScheme = "http",
+ DataHost = App.AppName,
+ DataPathPrefix = "/gallery/"
+ )
+ ]
+ public class Activity1 : FormsAppCompatActivity
+ {
+ protected override void OnCreate (Bundle bundle)
+ {
+ ToolbarResource = Resource.Layout.Toolbar;
+ TabLayoutResource = Resource.Layout.Tabbar;
+
+ base.OnCreate (bundle);
+
+ if (!Debugger.IsAttached)
+ Insights.Initialize (App.Secrets["InsightsApiKey"], ApplicationContext);
+
+ Forms.Init (this, bundle);
+ FormsMaps.Init (this, bundle);
+ Forms.ViewInitialized += (sender, e) => {
+// if (!string.IsNullOrWhiteSpace(e.View.StyleId)) {
+// e.NativeView.ContentDescription = e.View.StyleId;
+// }
+ };
+ // uncomment to verify turning off title bar works. This is not intended to be dynamic really.
+ //Forms.SetTitleBarVisibility (AndroidTitleBarVisibility.Never);
+
+ var app = new App ();
+
+ var mdp = app.MainPage as MasterDetailPage;
+ var detail = mdp?.Detail as NavigationPage;
+ if (detail != null) {
+ detail.Pushed += (sender, args) => {
+ var nncgPage = args.Page as NestedNativeControlGalleryPage;
+
+ if (nncgPage != null) {
+ AddNativeControls (nncgPage);
+ }
+ };
+ }
+
+ LoadApplication (app);
+ }
+
+ public override void OnConfigurationChanged (global::Android.Content.Res.Configuration newConfig)
+ {
+ // we're good
+ base.OnConfigurationChanged (newConfig);
+ }
+
+ protected override void OnDestroy ()
+ {
+ base.OnDestroy ();
+ }
+
+ void AddNativeControls (NestedNativeControlGalleryPage page)
+ {
+ if (page.NativeControlsAdded) {
+ return;
+ }
+
+ StackLayout sl = page.Layout;
+
+ // Create and add a native TextView
+ var textView = new TextView (this) { Text = "I am a native TextView", TextSize = 14 };
+ sl?.Children.Add (textView);
+
+ // Create and add a native Button
+ var button = new global::Android.Widget.Button (this) { Text = "Click to change TextView font size" };
+ float originalSize = textView.TextSize;
+ button.Click += (sender, args) => {
+ textView.TextSize = textView.TextSize == originalSize ? 24 : 14;
+ };
+
+ sl?.Children.Add (button.ToView ());
+
+ // Create a control which we know doesn't behave correctly with regard to measurement
+ var difficultControl0 = new BrokenNativeControl (this) {
+ Text = "This native control doesn't play nice with sizing, which is why it's all squished to one side."
+ };
+ var difficultControl1 = new BrokenNativeControl (this) {
+ Text = "Same control, but with a custom GetDesiredSize delegate to accomodate it's sizing problems."
+ };
+
+ // Add a misbehaving control
+ sl?.Children.Add (difficultControl0);
+
+ // Add a misbehaving control with a custom delegate for GetDesiredSize
+ sl?.Children.Add (difficultControl1, SizeBrokenControl);
+
+ page.NativeControlsAdded = true;
+ }
+
+ static SizeRequest? SizeBrokenControl (NativeViewWrapperRenderer renderer,
+ int widthConstraint, int heightConstraint)
+ {
+ global::Android.Views.View nativeView = renderer.Control;
+
+ if ((widthConstraint == 0 && heightConstraint == 0) || nativeView == null) {
+ return null;
+ }
+
+ int width = global::Android.Views.View.MeasureSpec.GetSize (widthConstraint);
+ int widthSpec = global::Android.Views.View.MeasureSpec.MakeMeasureSpec (width * 2,
+ global::Android.Views.View.MeasureSpec.GetMode (widthConstraint));
+ nativeView.Measure (widthSpec, heightConstraint);
+ var size = new Size (nativeView.MeasuredWidth, nativeView.MeasuredHeight);
+ return new SizeRequest (size);
+ }
+ }
+#endif
+}
+
diff --git a/Xamarin.Forms.ControlGallery.Android/Assets/WebImages/XamarinLogo.png b/Xamarin.Forms.ControlGallery.Android/Assets/WebImages/XamarinLogo.png
new file mode 100644
index 00000000..361e2782
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Assets/WebImages/XamarinLogo.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Assets/default.css b/Xamarin.Forms.ControlGallery.Android/Assets/default.css
new file mode 100644
index 00000000..9e32b419
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Assets/default.css
@@ -0,0 +1,2 @@
+html,body{margin:0;padding:10}
+body,p,h1{font-family:Chalkduster;font-style: italic;} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Android/Assets/local.html b/Xamarin.Forms.ControlGallery.Android/Assets/local.html
new file mode 100644
index 00000000..ccc9bec3
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Assets/local.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<link rel="stylesheet" href="default.css">
+</head>
+<body>
+<h1 id="#LocalHtmlPage">Xamarin.Forms</h1>
+<p>This is a local iOS Html page</p>
+<a href="https://www.google.com">Go to Google</a>
+</body>
+</html> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Android/BrokenNativeControl.cs b/Xamarin.Forms.ControlGallery.Android/BrokenNativeControl.cs
new file mode 100644
index 00000000..c75e7ca9
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/BrokenNativeControl.cs
@@ -0,0 +1,60 @@
+using System;
+using Android.Content;
+using Android.Graphics;
+using Android.Runtime;
+using Android.Util;
+using Android.Views;
+using Android.Widget;
+
+namespace Xamarin.Forms.ControlGallery.Android
+{
+ /// <summary>
+ /// This is a custom Android control which deliberately does some incorrect measuring
+ /// </summary>
+ internal class BrokenNativeControl : TextView
+ {
+ bool _on;
+
+ public BrokenNativeControl (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer)
+ {
+ }
+
+ public BrokenNativeControl (Context context) : base (context)
+ {
+ }
+
+ public BrokenNativeControl (Context context, IAttributeSet attrs) : base (context, attrs)
+ {
+ }
+
+ public BrokenNativeControl (Context context, IAttributeSet attrs, int defStyleAttr)
+ : base (context, attrs, defStyleAttr)
+ {
+ }
+
+ public BrokenNativeControl (Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes)
+ : base (context, attrs, defStyleAttr, defStyleRes)
+ {
+ }
+
+ public override bool OnTouchEvent (MotionEvent e)
+ {
+ _on = !_on;
+
+ SetTypeface (null, _on ? TypefaceStyle.Bold : TypefaceStyle.Normal);
+
+ return base.OnTouchEvent (e);
+ }
+
+ protected override void OnMeasure (int widthMeasureSpec, int heightMeasureSpec)
+ {
+ int width = MeasureSpec.GetSize (widthMeasureSpec);
+
+ // Force the width to 1/2 of what's being requested. This is deliberately wrong so we can demo
+ // giving the LayoutExtensions an override to fix it with
+ int widthSpec = MeasureSpec.MakeMeasureSpec (width / 2, MeasureSpec.GetMode (widthMeasureSpec));
+
+ base.OnMeasure (widthSpec, heightMeasureSpec);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Android/CustomRenderers.cs b/Xamarin.Forms.ControlGallery.Android/CustomRenderers.cs
new file mode 100644
index 00000000..c8bfa1a4
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/CustomRenderers.cs
@@ -0,0 +1,344 @@
+using System;
+using Android.Widget;
+using Android.App;
+using System.Collections.Generic;
+using Android.Views;
+using System.Collections;
+using System.Linq;
+using Xamarin.Forms.Controls;
+using Xamarin.Forms.Platform.Android;
+using Xamarin.Forms;
+using Xamarin.Forms.ControlGallery.Android;
+using Android.Graphics.Drawables;
+using System.Threading.Tasks;
+using Android.Content;
+using Android.Runtime;
+using Android.Util;
+using AButton = Android.Widget.Button;
+
+[assembly: ExportRenderer (typeof (Bugzilla31395.CustomContentView), typeof (CustomContentRenderer))]
+[assembly: ExportRenderer (typeof (NativeListView), typeof (NativeListViewRenderer))]
+[assembly: ExportRenderer (typeof (NativeListView2), typeof (NativeAndroidListViewRenderer))]
+[assembly: ExportRenderer (typeof (NativeCell), typeof (NativeAndroidCellRenderer))]
+
+namespace Xamarin.Forms.ControlGallery.Android
+{
+ public class NativeListViewRenderer : ViewRenderer<NativeListView, global::Android.Widget.ListView>
+ {
+ public NativeListViewRenderer ()
+ {
+ }
+
+ protected override void OnElementChanged (ElementChangedEventArgs<NativeListView> e)
+ {
+ base.OnElementChanged (e);
+
+ if (Control == null) {
+ SetNativeControl (new global::Android.Widget.ListView (Forms.Context));
+ }
+
+ if (e.OldElement != null) {
+ // unsubscribe
+ Control.ItemClick -= Clicked;
+ }
+
+ if (e.NewElement != null) {
+ // subscribe
+
+ Control.Adapter = new NativeListViewAdapter (Forms.Context as Activity, e.NewElement);
+ Control.ItemClick += Clicked;
+ }
+ }
+
+ void Clicked (object sender, AdapterView.ItemClickEventArgs e) {
+ Element.NotifyItemSelected (Element.Items.ToList()[e.Position]);
+ }
+
+ protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged (sender, e);
+ if (e.PropertyName == NativeListView.ItemsProperty.PropertyName) {
+ // update the Items list in the UITableViewSource
+
+ Control.Adapter = new NativeListViewAdapter (Forms.Context as Activity, Element);
+ }
+ }
+ }
+
+ public class NativeListViewAdapter: BaseAdapter<string> {
+ readonly Activity _context;
+ IList<string> _tableItems = new List<string>();
+
+ public IEnumerable<string> Items {
+ set {
+ _tableItems = value.ToList();
+ }
+ }
+
+ public NativeListViewAdapter(Activity context, NativeListView view)
+ {
+ _context = context;
+ _tableItems = view.Items.ToList();
+ }
+
+ public override string this[int position]
+ {
+ get
+ {
+ return _tableItems[position];
+ }
+ }
+
+ public override long GetItemId(int position)
+ {
+ return position;
+ }
+
+ public override int Count
+ {
+ get { return _tableItems.Count; }
+ }
+
+ public override global::Android.Views.View GetView(int position, global::Android.Views.View convertView, ViewGroup parent)
+ {
+ // Get our object for this position
+ var item = _tableItems[position];
+
+ var view = convertView;
+ if (view == null) { // no view to re-use, create new
+ view = _context.LayoutInflater.Inflate(global::Android.Resource.Layout.SimpleListItem1, null);
+ }
+
+ view.FindViewById<TextView> (global::Android.Resource.Id.Text1).Text = item;
+
+ return view;
+ }
+ }
+
+ /// <summary>
+ /// This renderer uses a view defined in /Resources/Layout/NativeAndroidCell.axml
+ /// as the cell layout
+ /// </summary>
+ public class NativeAndroidCellRenderer : ViewCellRenderer
+ {
+ public NativeAndroidCellRenderer ()
+ {
+ }
+
+ protected override global::Android.Views.View GetCellCore (Cell item, global::Android.Views.View convertView, ViewGroup parent, Context context)
+ {
+ var x = (NativeCell)item;
+
+ var view = convertView;
+
+ if (view == null) {// no view to re-use, create new
+ view = (context as Activity).LayoutInflater.Inflate (Resource.Layout.NativeAndroidCell, null);
+ } else { // re-use, clear image
+ // doesn't seem to help
+ //view.FindViewById<ImageView> (Resource.Id.Image).Drawable.Dispose ();
+ }
+
+ view.FindViewById<TextView>(Resource.Id.Text1).Text = x.Name;
+ view.FindViewById<TextView>(Resource.Id.Text2).Text = x.Category;
+
+ // grab the old image and dispose of it
+ // TODO: optimize if the image is the *same* and we want to just keep it
+ if (view.FindViewById<ImageView> (Resource.Id.Image).Drawable != null) {
+ using (var image = view.FindViewById<ImageView> (Resource.Id.Image).Drawable as BitmapDrawable) {
+ if (image != null) {
+ if (image.Bitmap != null) {
+ //image.Bitmap.Recycle ();
+ image.Bitmap.Dispose ();
+ }
+ }
+ }
+ }
+
+ // If a new image is required, display it
+ if (!string.IsNullOrWhiteSpace (x.ImageFilename)) {
+ context.Resources.GetBitmapAsync (x.ImageFilename).ContinueWith ((t) => {
+ var bitmap = t.Result;
+ if (bitmap != null) {
+ view.FindViewById<ImageView> (Resource.Id.Image).SetImageBitmap (bitmap);
+ bitmap.Dispose ();
+ }
+ }, TaskScheduler.FromCurrentSynchronizationContext() );
+
+ } else {
+ // clear the image
+ view.FindViewById<ImageView> (Resource.Id.Image).SetImageBitmap (null);
+ }
+
+ return view;
+ }
+ }
+
+ public class NativeAndroidListViewRenderer : ViewRenderer<NativeListView2, global::Android.Widget.ListView>
+ {
+ public NativeAndroidListViewRenderer ()
+ {
+ }
+
+ protected override void OnElementChanged (ElementChangedEventArgs<NativeListView2> e)
+ {
+ base.OnElementChanged (e);
+
+ if (Control == null) {
+ SetNativeControl (new global::Android.Widget.ListView (Forms.Context));
+ }
+
+ if (e.OldElement != null) {
+ // unsubscribe
+ Control.ItemClick -= Clicked;
+ }
+
+ if (e.NewElement != null) {
+ // subscribe
+ Control.Adapter = new NativeAndroidListViewAdapter (Forms.Context as Activity, e.NewElement);
+ Control.ItemClick += Clicked;
+ }
+ }
+
+ // public override void Layout (int l, int t, int r, int b)
+ // {
+ // base.Layout (l, t, r, b);
+ // }
+
+ void Clicked (object sender, AdapterView.ItemClickEventArgs e) {
+ Element.NotifyItemSelected (Element.Items.ToList()[e.Position]);
+ }
+
+ protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged (sender, e);
+ if (e.PropertyName == NativeListView.ItemsProperty.PropertyName) {
+ // update the Items list in the UITableViewSource
+
+ Control.Adapter = new NativeAndroidListViewAdapter (Forms.Context as Activity, Element);
+ }
+ }
+ }
+
+ /// <summary>
+ /// This adapter uses a view defined in /Resources/Layout/NativeAndroidListViewCell.axml
+ /// as the cell layout
+ /// </summary>
+ public class NativeAndroidListViewAdapter : BaseAdapter<DataSource> {
+ readonly Activity _context;
+ IList<DataSource> _tableItems = new List<DataSource>();
+
+ public IEnumerable<DataSource> Items {
+ set {
+ _tableItems = value.ToList();
+ }
+ }
+
+ public NativeAndroidListViewAdapter(Activity context, NativeListView2 view)
+ {
+ _context = context;
+ _tableItems = view.Items.ToList();
+ }
+
+ public override DataSource this[int position]
+ {
+ get
+ {
+ return _tableItems[position];
+ }
+ }
+
+ public override long GetItemId(int position)
+ {
+ return position;
+ }
+
+ public override int Count
+ {
+ get { return _tableItems.Count; }
+ }
+
+ public override global::Android.Views.View GetView(int position, global::Android.Views.View convertView, ViewGroup parent)
+ {
+ var item = _tableItems[position];
+
+ var view = convertView;
+ if (view == null) {// no view to re-use, create new
+ view = _context.LayoutInflater.Inflate (Resource.Layout.NativeAndroidListViewCell, null);
+ } else { // re-use, clear image
+ // doesn't seem to help
+ //view.FindViewById<ImageView> (Resource.Id.Image).Drawable.Dispose ();
+ }
+ view.FindViewById<TextView>(Resource.Id.Text1).Text = item.Name;
+ view.FindViewById<TextView>(Resource.Id.Text2).Text = item.Category;
+
+ // grab the old image and dispose of it
+ // TODO: optimize if the image is the *same* and we want to just keep it
+ if (view.FindViewById<ImageView> (Resource.Id.Image).Drawable != null) {
+ using (var image = view.FindViewById<ImageView> (Resource.Id.Image).Drawable as BitmapDrawable) {
+ if (image != null) {
+ if (image.Bitmap != null) {
+ //image.Bitmap.Recycle ();
+ image.Bitmap.Dispose ();
+ }
+ }
+ }
+ }
+
+ // If a new image is required, display it
+ if (!string.IsNullOrWhiteSpace (item.ImageFilename)) {
+ _context.Resources.GetBitmapAsync (item.ImageFilename).ContinueWith ((t) => {
+ var bitmap = t.Result;
+ if (bitmap != null) {
+ view.FindViewById<ImageView> (Resource.Id.Image).SetImageBitmap (bitmap);
+ bitmap.Dispose ();
+ }
+ }, TaskScheduler.FromCurrentSynchronizationContext());
+ } else {
+ // clear the image
+ view.FindViewById<ImageView> (Resource.Id.Image).SetImageBitmap (null);
+ }
+
+ return view;
+ }
+ }
+ public class CustomContentRenderer : ViewRenderer
+ {
+ }
+
+ public class CustomNativeButton : AButton
+ {
+ public CustomNativeButton (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer)
+ {
+ }
+
+ public CustomNativeButton (Context context) : base (context)
+ {
+ }
+
+ public CustomNativeButton (Context context, IAttributeSet attrs) : base (context, attrs)
+ {
+ }
+
+ public CustomNativeButton (Context context, IAttributeSet attrs, int defStyleAttr) : base (context, attrs, defStyleAttr)
+ {
+ }
+
+ public CustomNativeButton (Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base (context, attrs, defStyleAttr, defStyleRes)
+ {
+ }
+ }
+
+ public class CustomButtonRenderer : ButtonRenderer
+ {
+ protected override void OnElementChanged (ElementChangedEventArgs<Button> e)
+ {
+ if(Control == null) {
+ CustomNativeButton b = new CustomNativeButton (Context);
+ SetNativeControl (b);
+ }
+
+ base.OnElementChanged (e);
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.ControlGallery.Android/Properties/AndroidManifest.xml b/Xamarin.Forms.ControlGallery.Android/Properties/AndroidManifest.xml
new file mode 100644
index 00000000..9bbcafdf
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Properties/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="AndroidControlGallery.AndroidControlGallery" android:installLocation="auto">
+ <uses-sdk android:minSdkVersion="15" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
+ <!-- The following two permissions are not required to use
+ Google Maps Android API v2, but are recommended. -->
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.BATTERY_STATS" />
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.READ_LOGS" />
+ <uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" />
+ <uses-feature android:glEsVersion="0x00020000" android:required="true" />
+ <application android:label="AndroidControlGallery">
+ <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
+ </application>
+</manifest> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Android/Properties/AssemblyInfo.cs b/Xamarin.Forms.ControlGallery.Android/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..61a74f21
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Properties/AssemblyInfo.cs
@@ -0,0 +1,37 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Android.App;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle ("Xamarin.Forms.ControlGallery.Android")]
+[assembly: AssemblyDescription ("")]
+[assembly: AssemblyConfiguration ("")]
+[assembly: AssemblyCompany ("")]
+[assembly: AssemblyProduct ("Xamarin.Forms.ControlGallery.Android")]
+[assembly: AssemblyCopyright ("Copyright © 2013")]
+[assembly: AssemblyTrademark ("")]
+[assembly: AssemblyCulture ("")]
+[assembly: ComVisible (false)]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion ("1.0.0.0")]
+[assembly: AssemblyFileVersion ("1.0.0.0")]
+
+// Add some common permissions, these can be removed if not needed
+[assembly: UsesPermission (Android.Manifest.Permission.Internet)]
+[assembly: UsesPermission (Android.Manifest.Permission.WriteExternalStorage)]
+
+[assembly: Android.App.MetaData("com.google.android.maps.v2.API_KEY", Value = "AIzaSyAdstcJQswxEjzX5YjLaMcu2aRVEBJw39Y")]
+[assembly: Xamarin.Forms.ResolutionGroupName ("XamControl")]
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/AboutResources.txt b/Xamarin.Forms.ControlGallery.Android/Resources/AboutResources.txt
new file mode 100644
index 00000000..10f52d46
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/AboutResources.txt
@@ -0,0 +1,44 @@
+Images, layout descriptions, binary blobs and string dictionaries can be included
+in your application as resource files. Various Android APIs are designed to
+operate on the resource IDs instead of dealing with images, strings or binary blobs
+directly.
+
+For example, a sample Android app that contains a user interface layout (main.axml),
+an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
+would keep its resources in the "Resources" directory of the application:
+
+Resources/
+ drawable/
+ icon.png
+
+ layout/
+ main.axml
+
+ values/
+ strings.xml
+
+In order to get the build system to recognize Android resources, set the build action to
+"AndroidResource". The native Android APIs do not operate directly with filenames, but
+instead operate on resource IDs. When you compile an Android application that uses resources,
+the build system will package the resources for distribution and generate a class called "R"
+(this is an Android convention) that contains the tokens for each one of the resources
+included. For example, for the above Resources layout, this is what the R class would expose:
+
+public class R {
+ public class drawable {
+ public const int icon = 0x123;
+ }
+
+ public class layout {
+ public const int main = 0x456;
+ }
+
+ public class strings {
+ public const int first_string = 0xabc;
+ public const int second_string = 0xbcd;
+ }
+}
+
+You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
+to reference the layout/main.axml file, or R.strings.first_string to reference the first
+string in the dictionary file values/strings.xml.
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/CustomSelector.xml b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/CustomSelector.xml
new file mode 100644
index 00000000..973f9480
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/CustomSelector.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="false"
+ android:state_selected="false"
+ android:drawable="@color/cellback" />
+ <item android:state_pressed="true" >
+ <shape>
+ <gradient
+ android:startColor="#E77A26"
+ android:endColor="#E77A26"
+ android:angle="270" />
+ </shape>
+ </item>
+
+ <item android:state_selected="true"
+ android:state_pressed="false"
+ android:drawable="@color/cellback" />
+</selector> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/CustomSelector2.xml b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/CustomSelector2.xml
new file mode 100644
index 00000000..efe02fa8
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/CustomSelector2.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="false"
+ android:state_selected="false"
+ android:drawable="@color/cellback2" />
+ <item android:state_pressed="true" >
+ <shape>
+ <gradient
+ android:startColor="#E77A26"
+ android:endColor="#E77A26"
+ android:angle="270" />
+ </shape>
+ </item>
+
+ <item android:state_selected="true"
+ android:state_pressed="false"
+ android:drawable="@color/cellback2" />
+</selector> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/FlowerBuds.jpg b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/FlowerBuds.jpg
new file mode 100644
index 00000000..023797cc
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/FlowerBuds.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/Fruits.jpg b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/Fruits.jpg
new file mode 100644
index 00000000..6c4ea3d9
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/Fruits.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/Icon.png b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/Icon.png
new file mode 100644
index 00000000..a07c69fa
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/Icon.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/Legumes.jpg b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/Legumes.jpg
new file mode 100644
index 00000000..5f299b41
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/Legumes.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/Vegetables.jpg b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/Vegetables.jpg
new file mode 100644
index 00000000..297964d7
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/Vegetables.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/bank.png b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/bank.png
new file mode 100644
index 00000000..fbf2947e
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/bank.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/calculator.png b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/calculator.png
new file mode 100644
index 00000000..339cab59
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/calculator.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/coffee.png b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/coffee.png
new file mode 100644
index 00000000..350257c0
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/coffee.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/cover1.jpg b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/cover1.jpg
new file mode 100644
index 00000000..f2cea334
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/cover1.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/cover1small.jpg b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/cover1small.jpg
new file mode 100644
index 00000000..c820c471
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/cover1small.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/crimson.jpg b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/crimson.jpg
new file mode 100644
index 00000000..3db7bb21
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/crimson.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/crimsonsmall.jpg b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/crimsonsmall.jpg
new file mode 100644
index 00000000..426c5e07
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/crimsonsmall.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/menuIcon.png b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/menuIcon.png
new file mode 100644
index 00000000..0793dc7b
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/menuIcon.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/oasis.jpg b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/oasis.jpg
new file mode 100644
index 00000000..078a6e09
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/oasis.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/oasissmall.jpg b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/oasissmall.jpg
new file mode 100644
index 00000000..f8d43821
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/oasissmall.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/photo.jpg b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/photo.jpg
new file mode 100644
index 00000000..07fd4b0a
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/photo.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/seth.png b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/seth.png
new file mode 100644
index 00000000..568360e8
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/seth.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/drawable/toolbar_close.png b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/toolbar_close.png
new file mode 100644
index 00000000..12f82abb
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/drawable/toolbar_close.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/layout/NativeAndroidCell.axml b/Xamarin.Forms.ControlGallery.Android/Resources/layout/NativeAndroidCell.axml
new file mode 100644
index 00000000..541dc07b
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/layout/NativeAndroidCell.axml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:background="@drawable/CustomSelector">
+ <LinearLayout
+ android:id="@+id/Text"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="10dip">
+ <TextView
+ android:id="@+id/Text1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="#FF7F3300"
+ android:textSize="20dip"
+ android:textStyle="italic" />
+ <TextView
+ android:id="@+id/Text2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="14dip"
+ android:textColor="#FF267F00"
+ android:paddingLeft="100dip" />
+ </LinearLayout>
+ <ImageView
+ android:id="@+id/Image"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:padding="5dp"
+ android:src="@drawable/icon"
+ android:layout_alignParentRight="true" />
+</RelativeLayout> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/layout/NativeAndroidListViewCell.axml b/Xamarin.Forms.ControlGallery.Android/Resources/layout/NativeAndroidListViewCell.axml
new file mode 100644
index 00000000..4c79bea8
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/layout/NativeAndroidListViewCell.axml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:background="@drawable/CustomSelector2">
+ <LinearLayout
+ android:id="@+id/Text"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="10dip">
+ <TextView
+ android:id="@+id/Text1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="#FF7F3300"
+ android:textSize="20dip"
+ android:textStyle="italic" />
+ <TextView
+ android:id="@+id/Text2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="14dip"
+ android:textColor="#FF267F00"
+ android:paddingLeft="100dip" />
+ </LinearLayout>
+ <ImageView
+ android:id="@+id/Image"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:padding="5dp"
+ android:src="@drawable/icon"
+ android:layout_alignParentRight="true" />
+</RelativeLayout> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/layout/Tabbar.axml b/Xamarin.Forms.ControlGallery.Android/Resources/layout/Tabbar.axml
new file mode 100644
index 00000000..97cb27ad
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/layout/Tabbar.axml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.design.widget.TabLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/sliding_tabs"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?attr/colorPrimary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
+ app:tabIndicatorColor="@android:color/white"
+ app:tabGravity="fill"
+ app:tabMode="fixed" /> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/layout/Toolbar.axml b/Xamarin.Forms.ControlGallery.Android/Resources/layout/Toolbar.axml
new file mode 100644
index 00000000..3a1989a8
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/layout/Toolbar.axml
@@ -0,0 +1,8 @@
+<android.support.v7.widget.Toolbar
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?attr/colorPrimary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
+ android:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/values/Colors.xml b/Xamarin.Forms.ControlGallery.Android/Resources/values/Colors.xml
new file mode 100644
index 00000000..8b96fc81
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/values/Colors.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="cellback">#FFFFFFE0</color>
+ <color name="cellback2">#FFDAFF7F</color>
+</resources> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Android/Resources/values/styles.xml b/Xamarin.Forms.ControlGallery.Android/Resources/values/styles.xml
new file mode 100644
index 00000000..971153df
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Resources/values/styles.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<resources>
+ <color name="custom_theme_color">#FF0000</color>
+ <style name="FormsTheme" parent="android:Theme.Holo.Light">
+ <item name="android:windowActionBar">true</item>
+ <item name="android:windowBackground">@color/custom_theme_color</item>
+ </style>
+
+ <style name="MyTheme" parent="MyTheme.Base">
+ </style>
+ <!-- Base theme applied no matter what API -->
+ <style name="MyTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
+ <!--If you are using revision 22.1 please use just windowNoTitle. Without android:-->
+ <item name="windowNoTitle">true</item>
+ <!--We will be using the toolbar so no need to show ActionBar-->
+ <item name="windowActionBar">false</item>
+ <!-- Set theme colors from http://www.google.com/design/spec/style/color.html#color-color-palette-->
+ <!-- colorPrimary is used for the default action bar background -->
+ <item name="colorPrimary">#2196F3</item>
+ <!-- colorPrimaryDark is used for the status bar -->
+ <item name="colorPrimaryDark">#1976D2</item>
+ <!-- colorAccent is used as the default value for colorControlActivated
+ which is used to tint widgets -->
+ <item name="colorAccent">#FF4081</item>
+ <!-- You can also set colorControlNormal, colorControlActivated
+ colorControlHighlight and colorSwitchThumbNormal. -->
+ <item name="windowActionModeOverlay">true</item>
+
+ <item name="android:datePickerDialogTheme">@style/AppCompatDialogStyle</item>
+ </style>
+
+ <style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
+ <item name="colorAccent">#FF4081</item>
+ </style>
+
+ <style name="TestStyle" parent="@android:style/Theme.Holo.Light.DarkActionBar">
+ </style>
+</resources> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Android/Xamarin.Forms.ControlGallery.Android.csproj b/Xamarin.Forms.ControlGallery.Android/Xamarin.Forms.ControlGallery.Android.csproj
new file mode 100644
index 00000000..ff23e911
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/Xamarin.Forms.ControlGallery.Android.csproj
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{1346A7F1-4457-4BB4-A371-2C8E28BBD53E}</ProjectGuid>
+ <ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.ControlGallery.Android</RootNamespace>
+ <AssemblyName>Xamarin.Forms.ControlGallery.Android</AssemblyName>
+ <FileAlignment>512</FileAlignment>
+ <AndroidApplication>true</AndroidApplication>
+ <AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+ <TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
+ <AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
+ <AndroidSupportedAbis>armeabi-v7a,x86</AndroidSupportedAbis>
+ <AndroidStoreUncompressedFileExtensions />
+ <MandroidI18n />
+ <JavaOptions />
+ <AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)' == 'Debug'">
+ <AndroidKeyStore>True</AndroidKeyStore>
+ <AndroidSigningKeyStore>$(SolutionDir)debug.keystore</AndroidSigningKeyStore>
+ <AndroidSigningStorePass>android</AndroidSigningStorePass>
+ <AndroidSigningKeyAlias>androiddebugkey</AndroidSigningKeyAlias>
+ <AndroidSigningKeyPass>android</AndroidSigningKeyPass>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>True</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
+ <AndroidLinkMode>Full</AndroidLinkMode>
+ <JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
+ <AndroidLinkSkip />
+ <EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
+ <BundleAssemblies>False</BundleAssemblies>
+ <CustomCommands>
+ <CustomCommands>
+ <Command type="AfterBuild" command="xbuild /t:SignAndroidPackage Xamarin.Forms.ControlGallery.Android/Xamarin.Forms.ControlGallery.Android.csproj" workingdir="${SolutionDir}" />
+ </CustomCommands>
+ </CustomCommands>
+ <AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
+ <AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>
+ <AndroidStoreUncompressedFileExtensions />
+ <MandroidI18n />
+ <Debugger>Xamarin</Debugger>
+ <AndroidEnableMultiDex>False</AndroidEnableMultiDex>
+ <DevInstrumentationEnabled>True</DevInstrumentationEnabled>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
+ <AndroidLinkMode>SdkOnly</AndroidLinkMode>
+ <JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
+ <AndroidLinkSkip />
+ <EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
+ <BundleAssemblies>False</BundleAssemblies>
+ <AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
+ <AndroidSupportedAbis>armeabi-v7a,x86</AndroidSupportedAbis>
+ <AndroidStoreUncompressedFileExtensions />
+ <MandroidI18n />
+ <JavaOptions />
+ <MonoDroidExtraArgs />
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
+ <AndroidLinkSkip />
+ <AndroidLinkMode>SdkOnly</AndroidLinkMode>
+ <EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
+ <BundleAssemblies>False</BundleAssemblies>
+ <AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
+ <AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>
+ <AndroidStoreUncompressedFileExtensions />
+ <MandroidI18n />
+ <JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
+ <Debugger>Xamarin</Debugger>
+ <AndroidEnableMultiDex>False</AndroidEnableMultiDex>
+ <DevInstrumentationEnabled>True</DevInstrumentationEnabled>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Mono.Android" />
+ <Reference Include="mscorlib" />
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Xml" />
+ <Reference Include="Xamarin.Android.Support.Design, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.Android.Support.Design.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.Design.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.Android.Support.v4, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.Android.Support.v4.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.Android.Support.v7.AppCompat, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.Android.Support.v7.AppCompat.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.v7.AppCompat.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.Android.Support.v7.CardView, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.Android.Support.v7.CardView.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.v7.CardView.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.Android.Support.v7.MediaRouter, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.Android.Support.v7.MediaRouter.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.v7.MediaRouter.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.Android.Support.v7.RecyclerView, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.Android.Support.v7.RecyclerView.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.v7.RecyclerView.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.GooglePlayServices.AppIndexing, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.GooglePlayServices.AppIndexing.29.0.0.1\lib\MonoAndroid41\Xamarin.GooglePlayServices.AppIndexing.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.GooglePlayServices.Base, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.GooglePlayServices.Base.29.0.0.1\lib\MonoAndroid41\Xamarin.GooglePlayServices.Base.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.GooglePlayServices.Basement, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.GooglePlayServices.Basement.29.0.0.1\lib\MonoAndroid41\Xamarin.GooglePlayServices.Basement.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.GooglePlayServices.Maps, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.GooglePlayServices.Maps.29.0.0.1\lib\MonoAndroid41\Xamarin.GooglePlayServices.Maps.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.Insights, Version=1.11.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.Insights.1.11.4\lib\MonoAndroid10\Xamarin.Insights.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Activity1.cs" />
+ <Compile Include="BrokenNativeControl.cs" />
+ <Compile Include="Properties\MapsKey.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Resources\Resource.Designer.cs" />
+ <Compile Include="CustomRenderers.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <AndroidAsset Include="Assets\default.css" />
+ <AndroidResource Include="Resources\drawable\bank.png" />
+ <AndroidResource Include="Resources\drawable\crimson.jpg" />
+ <AndroidResource Include="Resources\drawable\oasis.jpg" />
+ <AndroidResource Include="Resources\drawable\cover1small.jpg" />
+ <AndroidResource Include="Resources\drawable\crimsonsmall.jpg" />
+ <AndroidResource Include="Resources\drawable\oasissmall.jpg" />
+ <AndroidResource Include="Resources\drawable\calculator.png" />
+ <AndroidResource Include="Resources\drawable\seth.png" />
+ <AndroidResource Include="Resources\drawable\menuIcon.png" />
+ <AndroidResource Include="Resources\drawable\photo.jpg" />
+ <AndroidAsset Include="Assets\WebImages\XamarinLogo.png" />
+ <AndroidAsset Include="Assets\local.html" />
+ <AndroidResource Include="Resources\values\Colors.xml" />
+ <AndroidResource Include="Resources\layout\NativeAndroidCell.axml" />
+ <AndroidResource Include="Resources\layout\NativeAndroidListViewCell.axml" />
+ <AndroidResource Include="Resources\drawable\CustomSelector.xml" />
+ <AndroidResource Include="Resources\drawable\CustomSelector2.xml" />
+ <AndroidResource Include="Resources\drawable\FlowerBuds.jpg" />
+ <AndroidResource Include="Resources\drawable\Fruits.jpg" />
+ <AndroidResource Include="Resources\drawable\Legumes.jpg" />
+ <AndroidResource Include="Resources\drawable\Vegetables.jpg" />
+ <AndroidResource Include="Resources\values\styles.xml" />
+ <AndroidResource Include="Resources\drawable\coffee.png" />
+ <AndroidResource Include="Resources\drawable\toolbar_close.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <AndroidResource Include="Resources\drawable\Icon.png" />
+ <AndroidResource Include="Resources\drawable\cover1.jpg" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Stubs\Xamarin.Forms.Platform.Android\Xamarin.Forms.Platform.Android %28Forwarders%29.csproj">
+ <Project>{6e53feb1-1100-46ae-8013-17bba35cc197}</Project>
+ <Name>Xamarin.Forms.Platform.Android %28Forwarders%29</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Controls\Xamarin.Forms.Controls.csproj">
+ <Project>{cb9c96ce-125c-4a68-b6a1-c3ff1fbf93e1}</Project>
+ <Name>Xamarin.Forms.Controls</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.CustomAttributes\Xamarin.Forms.CustomAttributes.csproj">
+ <Project>{4dcd0420-1168-4b77-86db-6196ee4bd491}</Project>
+ <Name>Xamarin.Forms.CustomAttributes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps.Android\Xamarin.Forms.Maps.Android.csproj">
+ <Project>{bd50b39a-ebc5-408f-9c5e-923a8ebae473}</Project>
+ <Name>Xamarin.Forms.Maps.Android</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7d13bac2-c6a4-416a-b07e-c169b199e52b}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.Android.FormsViewGroup\Xamarin.Forms.Platform.Android.FormsViewGroup.csproj">
+ <Project>{3b72465b-acae-43ae-9327-10f372fe5f80}</Project>
+ <Name>Xamarin.Forms.Platform.Android.FormsViewGroup</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.Android\Xamarin.Forms.Platform.Android.csproj">
+ <Project>{0e16e70a-d6dd-4323-ad5d-363abff42d6a}</Project>
+ <Name>Xamarin.Forms.Platform.Android</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.config" />
+ <None Include="packages.config" />
+ <AndroidResource Include="Resources\layout\Toolbar.axml">
+ <SubType>Designer</SubType>
+ </AndroidResource>
+ <AndroidResource Include="Resources\layout\Tabbar.axml">
+ <SubType>Designer</SubType>
+ </AndroidResource>
+ </ItemGroup>
+ <ItemGroup>
+ <TransformFile Include="Properties\AndroidManifest.xml" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Import Project="..\packages\Xamarin.Insights.1.11.4\build\MonoAndroid10\Xamarin.Insights.targets" Condition="Exists('..\packages\Xamarin.Insights.1.11.4\build\MonoAndroid10\Xamarin.Insights.targets')" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <Import Project="..\packages\Xamarin.Insights.1.11.4\build\MonoAndroid10\Xamarin.Insights.targets" Condition="Exists('..\packages\Xamarin.Insights.1.11.4\build\MonoAndroid10\Xamarin.Insights.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('..\packages\Xamarin.Insights.1.11.4\build\MonoAndroid10\Xamarin.Insights.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Insights.1.11.4\build\MonoAndroid10\Xamarin.Insights.targets'))" />
+ </Target>
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Android/app.config b/Xamarin.Forms.ControlGallery.Android/app.config
new file mode 100644
index 00000000..b1d2a5a3
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/app.config
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="Mono.Cecil" publicKeyToken="0738eb9f132ed756" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-0.9.6.0" newVersion="0.9.6.0" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Android/packages.config b/Xamarin.Forms.ControlGallery.Android/packages.config
new file mode 100644
index 00000000..f900edac
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Android/packages.config
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Xamarin.Android.Support.Design" version="23.1.1.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.Android.Support.v4" version="23.1.1.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.Android.Support.v7.AppCompat" version="23.1.1.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.Android.Support.v7.CardView" version="23.1.1.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.Android.Support.v7.MediaRouter" version="23.1.1.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.Android.Support.v7.RecyclerView" version="23.1.1.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.GooglePlayServices.AppIndexing" version="29.0.0.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.GooglePlayServices.Base" version="29.0.0.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.GooglePlayServices.Basement" version="29.0.0.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.GooglePlayServices.Maps" version="29.0.0.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.Insights" version="1.11.4" targetFramework="MonoAndroid60" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WP8/App.xaml b/Xamarin.Forms.ControlGallery.WP8/App.xaml
new file mode 100644
index 00000000..f1554d73
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/App.xaml
@@ -0,0 +1,20 @@
+<Application
+ x:Class="Xamarin.Forms.ControlGallery.WP8.App"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
+ xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">
+
+ <!--Application Resources-->
+ <Application.Resources>
+ <local:LocalizedStrings xmlns:local="clr-namespace:Xamarin.Forms.ControlGallery.WP8" x:Key="LocalizedStrings"/>
+ </Application.Resources>
+
+ <Application.ApplicationLifetimeObjects>
+ <!--Required object that handles lifetime events for the application-->
+ <shell:PhoneApplicationService
+ Launching="Application_Launching" Closing="Application_Closing"
+ Activated="Application_Activated" Deactivated="Application_Deactivated"/>
+ </Application.ApplicationLifetimeObjects>
+
+</Application>
diff --git a/Xamarin.Forms.ControlGallery.WP8/App.xaml.cs b/Xamarin.Forms.ControlGallery.WP8/App.xaml.cs
new file mode 100644
index 00000000..6b43e3b7
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/App.xaml.cs
@@ -0,0 +1,234 @@
+using System;
+using System.Diagnostics;
+using System.Resources;
+using System.Windows;
+using System.Windows.Markup;
+using System.Windows.Navigation;
+using Microsoft.Phone.Controls;
+using Microsoft.Phone.Shell;
+using Xamarin.Forms.ControlGallery.WP8.Resources;
+
+using Application = Xamarin.Forms.Application;
+
+namespace Xamarin.Forms.ControlGallery.WP8
+{
+ public partial class App : System.Windows.Application
+ {
+ /// <summary>
+ /// Provides easy access to the root frame of the Phone Application.
+ /// </summary>
+ /// <returns>The root frame of the Phone Application.</returns>
+ public static PhoneApplicationFrame RootFrame { get; private set; }
+
+ /// <summary>
+ /// Constructor for the Application object.
+ /// </summary>
+ public App()
+ {
+ if (!Debugger.IsAttached)
+ Insights.Initialize (Controls.App.Secrets["InsightsApiKey"]);
+
+ FormsMaps.Init (Controls.App.Secrets["WP8AppId"], Controls.App.Secrets["WP8AuthToken"]);
+
+ // Global handler for uncaught exceptions.
+ UnhandledException += Application_UnhandledException;
+
+ // Standard XAML initialization
+ InitializeComponent();
+
+ // Phone-specific initialization
+ InitializePhoneApplication();
+
+ // Language display initialization
+ InitializeLanguage();
+
+ // Show graphics profiling information while debugging.
+ if (Debugger.IsAttached)
+ {
+ // Display the current frame rate counters.
+ Current.Host.Settings.EnableFrameRateCounter = true;
+
+ // Show the areas of the app that are being redrawn in each frame.
+ //Application.Current.Host.Settings.EnableRedrawRegions = true;
+
+ // Enable non-production analysis visualization mode,
+ // which shows areas of a page that are handed off to GPU with a colored overlay.
+ //Application.Current.Host.Settings.EnableCacheVisualization = true;
+
+ // Prevent the screen from turning off while under the debugger by disabling
+ // the application's idle detection.
+ // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run
+ // and consume battery power when the user is not using the phone.
+ PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
+ }
+
+ }
+
+ // Code to execute when the application is launching (eg, from Start)
+ // This code will not execute when the application is reactivated
+ void Application_Launching(object sender, LaunchingEventArgs e)
+ {
+ Debug.WriteLine ("Launching");
+ }
+
+ // Code to execute when the application is activated (brought to foreground)
+ // This code will not execute when the application is first launched
+ void Application_Activated(object sender, ActivatedEventArgs e)
+ {
+ Debug.WriteLine ("Closing");
+ }
+
+ // Code to execute when the application is deactivated (sent to background)
+ // This code will not execute when the application is closing
+ void Application_Deactivated(object sender, DeactivatedEventArgs e)
+ {
+ Debug.WriteLine ("Deactivated");
+ }
+
+ // Code to execute when the application is closing (eg, user hit Back)
+ // This code will not execute when the application is deactivated
+ void Application_Closing(object sender, ClosingEventArgs e)
+ {
+ Debug.WriteLine ("Closing");
+ }
+
+ // Code to execute if a navigation fails
+ void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
+ {
+ if (Debugger.IsAttached)
+ {
+ // A navigation has failed; break into the debugger
+ Debugger.Break();
+ }
+ }
+
+ // Code to execute on Unhandled Exceptions
+ void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
+ {
+ if (Debugger.IsAttached)
+ {
+ // An unhandled exception has occurred; break into the debugger
+ Debugger.Break();
+ }
+ }
+
+ #region Phone application initialization
+
+ // Avoid double-initialization
+ bool _phoneApplicationInitialized = false;
+
+ // Do not add any additional code to this method
+ void InitializePhoneApplication()
+ {
+ if (_phoneApplicationInitialized)
+ return;
+
+ // Create the frame but don't set it as RootVisual yet; this allows the splash
+ // screen to remain active until the application is ready to render.
+ RootFrame = new PhoneApplicationFrame();
+ RootFrame.Navigated += CompleteInitializePhoneApplication;
+
+ // Handle navigation failures
+ RootFrame.NavigationFailed += RootFrame_NavigationFailed;
+
+ // Handle reset requests for clearing the backstack
+ RootFrame.Navigated += CheckForResetNavigation;
+
+ // Ensure we don't initialize again
+ _phoneApplicationInitialized = true;
+ }
+
+ // Do not add any additional code to this method
+ void CompleteInitializePhoneApplication(object sender, System.Windows.Navigation.NavigationEventArgs e)
+ {
+ // Set the root visual to allow the application to render
+ if (RootVisual != RootFrame)
+ RootVisual = RootFrame;
+
+ // Remove this handler since it is no longer needed
+ RootFrame.Navigated -= CompleteInitializePhoneApplication;
+ }
+
+ void CheckForResetNavigation(object sender, System.Windows.Navigation.NavigationEventArgs e)
+ {
+ // If the app has received a 'reset' navigation, then we need to check
+ // on the next navigation to see if the page stack should be reset
+ if (e.NavigationMode == NavigationMode.Reset)
+ RootFrame.Navigated += ClearBackStackAfterReset;
+ }
+
+ void ClearBackStackAfterReset(object sender, System.Windows.Navigation.NavigationEventArgs e)
+ {
+ // Unregister the event so it doesn't get called again
+ RootFrame.Navigated -= ClearBackStackAfterReset;
+
+ // Only clear the stack for 'new' (forward) and 'refresh' navigations
+ if (e.NavigationMode != NavigationMode.New && e.NavigationMode != NavigationMode.Refresh)
+ return;
+
+ // For UI consistency, clear the entire page stack
+ while (RootFrame.RemoveBackEntry() != null)
+ {
+ ; // do nothing
+ }
+ }
+
+ #endregion
+
+ // Initialize the app's font and flow direction as defined in its localized resource strings.
+ //
+ // To ensure that the font of your application is aligned with its supported languages and that the
+ // FlowDirection for each of those languages follows its traditional direction, ResourceLanguage
+ // and ResourceFlowDirection should be initialized in each resx file to match these values with that
+ // file's culture. For example:
+ //
+ // AppResources.es-ES.resx
+ // ResourceLanguage's value should be "es-ES"
+ // ResourceFlowDirection's value should be "LeftToRight"
+ //
+ // AppResources.ar-SA.resx
+ // ResourceLanguage's value should be "ar-SA"
+ // ResourceFlowDirection's value should be "RightToLeft"
+ //
+ // For more info on localizing Windows Phone apps see http://go.microsoft.com/fwlink/?LinkId=262072.
+ //
+ void InitializeLanguage()
+ {
+ try
+ {
+ // Set the font to match the display language defined by the
+ // ResourceLanguage resource string for each supported language.
+ //
+ // Fall back to the font of the neutral language if the Display
+ // language of the phone is not supported.
+ //
+ // If a compiler error is hit then ResourceLanguage is missing from
+ // the resource file.
+ RootFrame.Language = XmlLanguage.GetLanguage(AppResources.ResourceLanguage);
+
+ // Set the FlowDirection of all elements under the root frame based
+ // on the ResourceFlowDirection resource string for each
+ // supported language.
+ //
+ // If a compiler error is hit then ResourceFlowDirection is missing from
+ // the resource file.
+ FlowDirection flow = (FlowDirection)Enum.Parse(typeof(FlowDirection), AppResources.ResourceFlowDirection);
+ RootFrame.FlowDirection = flow;
+ }
+ catch
+ {
+ // If an exception is caught here it is most likely due to either
+ // ResourceLangauge not being correctly set to a supported language
+ // code or ResourceFlowDirection is set to a value other than LeftToRight
+ // or RightToLeft.
+
+ if (Debugger.IsAttached)
+ {
+ Debugger.Break();
+ }
+
+ throw;
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.ControlGallery.WP8/Assets/AlignmentGrid.png b/Xamarin.Forms.ControlGallery.WP8/Assets/AlignmentGrid.png
new file mode 100644
index 00000000..f7d2e978
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/Assets/AlignmentGrid.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/Assets/ApplicationIcon.png b/Xamarin.Forms.ControlGallery.WP8/Assets/ApplicationIcon.png
new file mode 100644
index 00000000..7d95d4e0
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/Assets/ApplicationIcon.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/FlipCycleTileLarge.png b/Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/FlipCycleTileLarge.png
new file mode 100644
index 00000000..e0c59ac0
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/FlipCycleTileLarge.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/FlipCycleTileMedium.png b/Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/FlipCycleTileMedium.png
new file mode 100644
index 00000000..e93b89d6
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/FlipCycleTileMedium.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/FlipCycleTileSmall.png b/Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/FlipCycleTileSmall.png
new file mode 100644
index 00000000..550b1b5e
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/FlipCycleTileSmall.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/IconicTileMediumLarge.png b/Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/IconicTileMediumLarge.png
new file mode 100644
index 00000000..686e6b53
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/IconicTileMediumLarge.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/IconicTileSmall.png b/Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/IconicTileSmall.png
new file mode 100644
index 00000000..d4b5ede1
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/Assets/Tiles/IconicTileSmall.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/BrokenNativeControl.cs b/Xamarin.Forms.ControlGallery.WP8/BrokenNativeControl.cs
new file mode 100644
index 00000000..b05c12cb
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/BrokenNativeControl.cs
@@ -0,0 +1,56 @@
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Xamarin.Forms.ControlGallery.WP8
+{
+ internal class BrokenNativeControl : Panel
+ {
+ public BrokenNativeControl ()
+ {
+ _textBlock = new TextBlock {
+ MinHeight = 0,
+ MaxHeight = double.PositiveInfinity,
+ MinWidth = 0,
+ MaxWidth = double.PositiveInfinity,
+ FontSize = 24,
+ HorizontalAlignment = HorizontalAlignment.Center
+ };
+
+ Children.Add (_textBlock);
+
+ Background = new RadialGradientBrush (Colors.Green, Colors.Blue);
+ }
+
+ public static readonly DependencyProperty TextProperty = DependencyProperty.Register (
+ "Text", typeof(string), typeof(BrokenNativeControl), new PropertyMetadata (default(string), PropertyChangedCallback));
+
+ static void PropertyChangedCallback (DependencyObject dependencyObject,
+ DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
+ {
+ ((BrokenNativeControl)dependencyObject)._textBlock.Text = (string)dependencyPropertyChangedEventArgs.NewValue;
+ }
+
+ public string Text
+ {
+ get { return (string)GetValue (TextProperty); }
+ set { SetValue (TextProperty, value); }
+ }
+
+ readonly TextBlock _textBlock;
+
+ protected override System.Windows.Size ArrangeOverride (System.Windows.Size finalSize)
+ {
+ _textBlock.Arrange (new Rect (0, 0, finalSize.Width, finalSize.Height));
+ return finalSize;
+ }
+
+ protected override System.Windows.Size MeasureOverride (System.Windows.Size availableSize)
+ {
+ _textBlock.Measure (availableSize);
+
+ // This deliberately does something wrong so we can demo fixing it
+ return new System.Windows.Size (600, _textBlock.DesiredSize.Height);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WP8/LocalizedStrings.cs b/Xamarin.Forms.ControlGallery.WP8/LocalizedStrings.cs
new file mode 100644
index 00000000..174957b7
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/LocalizedStrings.cs
@@ -0,0 +1,14 @@
+using Xamarin.Forms.ControlGallery.WP8.Resources;
+
+namespace Xamarin.Forms.ControlGallery.WP8
+{
+ /// <summary>
+ /// Provides access to string resources.
+ /// </summary>
+ public class LocalizedStrings
+ {
+ static AppResources _localizedResources = new AppResources();
+
+ public AppResources LocalizedResources { get { return _localizedResources; } }
+ }
+}
diff --git a/Xamarin.Forms.ControlGallery.WP8/MainPage.xaml b/Xamarin.Forms.ControlGallery.WP8/MainPage.xaml
new file mode 100644
index 00000000..03e8f09b
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/MainPage.xaml
@@ -0,0 +1,63 @@
+<winPhone:FormsApplicationPage
+ x:Class="Xamarin.Forms.ControlGallery.WP8.MainPage"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
+ xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:winPhone="clr-namespace:Xamarin.Forms.Platform.WinPhone;assembly=Xamarin.Forms.Platform.WP8"
+ mc:Ignorable="d"
+ FontFamily="{StaticResource PhoneFontFamilyNormal}"
+ FontSize="{StaticResource PhoneFontSizeNormal}"
+ Foreground="{StaticResource PhoneForegroundBrush}"
+ SupportedOrientations="PortraitOrLandscape" Orientation="Portrait"
+ shell:SystemTray.IsVisible="True">
+
+ <!--LayoutRoot is the root grid where all page content is placed-->
+ <Grid x:Name="LayoutRoot" Background="Transparent">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+
+ <!-- LOCALIZATION NOTE:
+ To localize the displayed strings copy their values to appropriately named
+ keys in the app's neutral language resource file (AppResources.resx) then
+ replace the hard-coded text value between the attributes' quotation marks
+ with the binding clause whose path points to that string name.
+
+ For example:
+
+ Text="{Binding Path=LocalizedResources.ApplicationTitle, Source={StaticResource LocalizedStrings}}"
+
+ This binding points to the template's string resource named "ApplicationTitle".
+
+ Adding supported languages in the Project Properties tab will create a
+ new resx file per language that can carry the translated values of your
+ UI strings. The binding in these examples will cause the value of the
+ attributes to be drawn from the .resx file that matches the
+ CurrentUICulture of the app at run time.
+ -->
+
+ <!--TitlePanel contains the name of the application and page title-->
+ <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
+ <TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
+ <TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
+ </StackPanel>
+
+ <!--ContentPanel - place additional content here-->
+ <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
+
+ </Grid>
+
+ <!--Uncomment to see an alignment grid to help ensure your controls are
+ aligned on common boundaries. The image has a top margin of -32px to
+ account for the System Tray. Set this to 0 (or remove the margin altogether)
+ if the System Tray is hidden.
+
+ Before shipping remove this XAML and the image itself.-->
+ <!--<Image Source="/Assets/AlignmentGrid.png" VerticalAlignment="Top" Height="800" Width="480" Margin="0,-32,0,0" Grid.Row="0" Grid.RowSpan="2" IsHitTestVisible="False" />-->
+ </Grid>
+
+</winPhone:FormsApplicationPage>
diff --git a/Xamarin.Forms.ControlGallery.WP8/MainPage.xaml.cs b/Xamarin.Forms.ControlGallery.WP8/MainPage.xaml.cs
new file mode 100644
index 00000000..e1ddb60f
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/MainPage.xaml.cs
@@ -0,0 +1,143 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Windows;
+using System.Windows.Automation.Peers;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Navigation;
+using Microsoft.Phone.Controls;
+using Microsoft.Phone.Shell;
+using Xamarin.Forms.ControlGallery.WP8.Resources;
+using Xamarin.Forms;
+using Xamarin.Forms.ControlGallery.WP8;
+using Xamarin.Forms.Controls;
+using Xamarin.Forms.Maps.WP8;
+using Xamarin.Forms.Platform.WinPhone;
+
+[assembly: Dependency (typeof (StringProvider))]
+namespace Xamarin.Forms.ControlGallery.WP8
+{
+ public class StringProvider : IStringProvider
+ {
+ public string CoreGalleryTitle { get { return "WP8 Core Gallery"; } }
+ }
+
+#if PRE_APPLICATION_CLASS
+ public partial class MainPage : PhoneApplicationPage
+ {
+ public MainPage ()
+ {
+ InitializeComponent();
+
+ Forms.Init ();
+ FormsMaps.Init ();
+
+ Content = CoreGallery.GetMainPage ().ConvertPageToUIElement (this);
+
+ MessagingCenter.Subscribe<RootPagesGallery, Type>(this, Messages.ChangeRoot, (sender, pagetype) =>
+ {
+ var page = ((Page) Activator.CreateInstance(pagetype));
+ app.MainPage = page;
+ });
+
+ MessagingCenter.Subscribe<HomeButton>(this, Messages.GoHome, (sender) => {
+ var page = FormsApp.GetFormsApp ();
+ app.MainPage = page;
+ });
+ }
+ }
+
+#else
+ public partial class MainPage : FormsApplicationPage
+ {
+ // Constructor
+ public MainPage()
+ {
+ InitializeComponent();
+
+ Forms.Init ();
+ FormsMaps.Init ();
+
+ var app = new Controls.App ();
+
+ var mdp = app.MainPage as MasterDetailPage;
+
+ var detail = mdp?.Detail as NavigationPage;
+ if (detail != null) {
+ detail.Pushed += (sender, args) => {
+ var nncgPage = args.Page as NestedNativeControlGalleryPage;
+
+ if (nncgPage != null) {
+ AddNativeControls (nncgPage);
+ }
+ };
+ }
+
+ LoadApplication (app);
+ }
+
+ void AddNativeControls (NestedNativeControlGalleryPage page)
+ {
+ if (page.NativeControlsAdded) {
+ return;
+ }
+
+ StackLayout sl = page.Layout;
+
+ // Create and add a native TextBlock
+ var originalText = "I am a native TextBlock";
+ var textBlock = new TextBlock {
+ Text = originalText,
+ FontSize = 14,
+ FontFamily = new FontFamily ("HelveticaNeue")
+ };
+
+ sl?.Children.Add (textBlock);
+
+ // Create and add a native Button
+ var button = new System.Windows.Controls.Button { Content = "Click to toggle font size", Height = 80 };
+ button.Click += (sender, args) => { textBlock.FontSize = textBlock.FontSize == 14 ? 24 : 14; };
+
+ sl?.Children.Add (button.ToView ());
+
+ // Create a control which we know doesn't behave correctly with regard to measurement
+ var difficultControl = new BrokenNativeControl {
+ Text = "Not Sized/Arranged Properly"
+ };
+
+ var difficultControl2 = new BrokenNativeControl {
+ Text = "Fixed"
+ };
+
+ // Add the misbehaving controls, one with a custom delegate for ArrangeOverride
+ sl?.Children.Add (difficultControl);
+ sl?.Children.Add (difficultControl2,
+ arrangeOverrideDelegate: (renderer, finalSize) => {
+ if (finalSize.Width <= 0 || double.IsInfinity (finalSize.Width)) {
+ return null;
+ }
+
+ FrameworkElement frameworkElement = renderer.Control;
+
+ frameworkElement.Measure (finalSize);
+
+ // The broken control always sizes itself to be 600 wide
+ // We can re-center it by offsetting it during the Arrange call
+ double diff = (finalSize.Width - 600) / 2;
+ frameworkElement.Arrange (new Rect (diff, 0, finalSize.Width - diff, finalSize.Height));
+
+ // Arranging the control to the left will make it show up past the edge of the stack layout
+ // We can fix that by clipping it manually
+ var clip = new RectangleGeometry { Rect = new Rect (-diff, 0, finalSize.Width, finalSize.Height) };
+ frameworkElement.Clip = clip;
+
+ return finalSize;
+ }
+ );
+
+ page.NativeControlsAdded = true;
+ }
+ }
+#endif
+}
diff --git a/Xamarin.Forms.ControlGallery.WP8/Properties/AppManifest.xml b/Xamarin.Forms.ControlGallery.WP8/Properties/AppManifest.xml
new file mode 100644
index 00000000..6712a117
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/Properties/AppManifest.xml
@@ -0,0 +1,6 @@
+<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+>
+ <Deployment.Parts>
+ </Deployment.Parts>
+</Deployment>
diff --git a/Xamarin.Forms.ControlGallery.WP8/Properties/AssemblyInfo.cs b/Xamarin.Forms.ControlGallery.WP8/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..61dd07a6
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/Properties/AssemblyInfo.cs
@@ -0,0 +1,37 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Resources;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Xamarin.Forms.ControlGallery.WP8")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Forms.ControlGallery.WP8")]
+[assembly: AssemblyCopyright("Copyright © 2013")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("07d20f12-3e95-48a2-b6af-dd223a0a4d3b")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: NeutralResourcesLanguageAttribute("en-US")]
diff --git a/Xamarin.Forms.ControlGallery.WP8/Properties/WMAppManifest.xml b/Xamarin.Forms.ControlGallery.WP8/Properties/WMAppManifest.xml
new file mode 100644
index 00000000..f19e02c3
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/Properties/WMAppManifest.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2012/deployment" AppPlatformVersion="8.0">
+ <DefaultLanguage xmlns="" code="en-US" />
+ <App xmlns="" ProductID="{67f3837c-c663-4668-9cd3-5e6c5abd59b8}" Title="Xamarin.Forms.ControlGallery.WP8" RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal" Author="Xamarin.Forms.ControlGallery.WP8 author" Description="Sample description" Publisher="Xamarin.Forms.ControlGallery.WP8" PublisherID="{9e07f47c-403b-44af-8078-487f1d249780}">
+ <IconPath IsRelative="true" IsResource="false">Assets\ApplicationIcon.png</IconPath>
+ <Capabilities>
+ <Capability Name="ID_CAP_NETWORKING" />
+ <Capability Name="ID_CAP_MEDIALIB_AUDIO" />
+ <Capability Name="ID_CAP_MEDIALIB_PLAYBACK" />
+ <Capability Name="ID_CAP_SENSORS" />
+ <Capability Name="ID_CAP_WEBBROWSERCOMPONENT" />
+ <Capability Name="ID_CAP_MAP" />
+ <Capability Name="ID_CAP_LOCATION" />
+ <Capability Name="ID_CAP_IDENTITY_DEVICE" />
+ <Capability Name="ID_CAP_IDENTITY_USER" />
+ </Capabilities>
+ <Tasks>
+ <DefaultTask Name="_default" NavigationPage="MainPage.xaml" />
+ </Tasks>
+ <Tokens>
+ <PrimaryToken TokenID="Xamarin.Forms.ControlGallery.WP8Token" TaskName="_default">
+ <TemplateFlip>
+ <SmallImageURI IsRelative="true" IsResource="false">Assets\Tiles\FlipCycleTileSmall.png</SmallImageURI>
+ <Count>0</Count>
+ <BackgroundImageURI IsRelative="true" IsResource="false">Assets\Tiles\FlipCycleTileMedium.png</BackgroundImageURI>
+ <Title>Xamarin.Forms.ControlGallery.WP8</Title>
+ <BackContent>
+ </BackContent>
+ <BackBackgroundImageURI>
+ </BackBackgroundImageURI>
+ <BackTitle>
+ </BackTitle>
+ <DeviceLockImageURI>
+ </DeviceLockImageURI>
+ <HasLarge>
+ </HasLarge>
+ </TemplateFlip>
+ </PrimaryToken>
+ </Tokens>
+ <ScreenResolutions>
+ <ScreenResolution Name="ID_RESOLUTION_WVGA" />
+ <ScreenResolution Name="ID_RESOLUTION_WXGA" />
+ <ScreenResolution Name="ID_RESOLUTION_HD720P" />
+ </ScreenResolutions>
+ </App>
+</Deployment> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WP8/Resources/AppResources.Designer.cs b/Xamarin.Forms.ControlGallery.WP8/Resources/AppResources.Designer.cs
new file mode 100644
index 00000000..59435e99
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/Resources/AppResources.Designer.cs
@@ -0,0 +1,127 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.17626
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Xamarin.Forms.ControlGallery.WP8.Resources
+{
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ public class AppResources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal AppResources()
+ {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ public static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if (object.ReferenceEquals(resourceMan, null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Xamarin.Forms.ControlGallery.WP8.Resources.AppResources", typeof(AppResources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ public static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to LeftToRight.
+ /// </summary>
+ public static string ResourceFlowDirection
+ {
+ get
+ {
+ return ResourceManager.GetString("ResourceFlowDirection", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to us-EN.
+ /// </summary>
+ public static string ResourceLanguage
+ {
+ get
+ {
+ return ResourceManager.GetString("ResourceLanguage", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to MY APPLICATION.
+ /// </summary>
+ public static string ApplicationTitle
+ {
+ get
+ {
+ return ResourceManager.GetString("ApplicationTitle", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to button.
+ /// </summary>
+ public static string AppBarButtonText
+ {
+ get
+ {
+ return ResourceManager.GetString("AppBarButtonText", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to menu item.
+ /// </summary>
+ public static string AppBarMenuItemText
+ {
+ get
+ {
+ return ResourceManager.GetString("AppBarMenuItemText", resourceCulture);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WP8/Resources/AppResources.resx b/Xamarin.Forms.ControlGallery.WP8/Resources/AppResources.resx
new file mode 100644
index 00000000..569bf520
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/Resources/AppResources.resx
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="ResourceFlowDirection" xml:space="preserve">
+ <value>LeftToRight</value>
+ <comment>Controls the FlowDirection for all elements in the RootFrame. Set to the traditional direction of this resource file's language</comment>
+ </data>
+ <data name="ResourceLanguage" xml:space="preserve">
+ <value>en-US</value>
+ <comment>Controls the Language and ensures that the font for all elements in the RootFrame aligns with the app's language. Set to the language code of this resource file's language.</comment>
+ </data>
+ <data name="ApplicationTitle" xml:space="preserve">
+ <value>MY APPLICATION</value>
+ </data>
+ <data name="AppBarButtonText" xml:space="preserve">
+ <value>add</value>
+ </data>
+ <data name="AppBarMenuItemText" xml:space="preserve">
+ <value>Menu Item</value>
+ </data>
+</root>
diff --git a/Xamarin.Forms.ControlGallery.WP8/WebImages/XamarinLogo.png b/Xamarin.Forms.ControlGallery.WP8/WebImages/XamarinLogo.png
new file mode 100644
index 00000000..361e2782
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/WebImages/XamarinLogo.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/Xamarin.Forms.ControlGallery.WP8.csproj b/Xamarin.Forms.ControlGallery.WP8/Xamarin.Forms.ControlGallery.WP8.csproj
new file mode 100644
index 00000000..f6728fa2
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/Xamarin.Forms.ControlGallery.WP8.csproj
@@ -0,0 +1,258 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>10.0.20506</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}</ProjectGuid>
+ <ProjectTypeGuids>{C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.ControlGallery.WP8</RootNamespace>
+ <AssemblyName>Xamarin.Forms.ControlGallery.WP8</AssemblyName>
+ <TargetFrameworkIdentifier>WindowsPhone</TargetFrameworkIdentifier>
+ <TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
+ <SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
+ <SilverlightApplication>true</SilverlightApplication>
+ <SupportedCultures>
+ </SupportedCultures>
+ <XapOutputs>true</XapOutputs>
+ <GenerateSilverlightManifest>true</GenerateSilverlightManifest>
+ <XapFilename>Xamarin.Forms.ControlGallery.WP8_$(Configuration)_$(Platform).xap</XapFilename>
+ <SilverlightManifestTemplate>Properties\AppManifest.xml</SilverlightManifestTemplate>
+ <SilverlightAppEntry>Xamarin.Forms.ControlGallery.WP8.App</SilverlightAppEntry>
+ <ValidateXaml>true</ValidateXaml>
+ <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+ <ThrowErrorsInValidation>true</ThrowErrorsInValidation>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ <NuGetPackageImportStamp>
+ </NuGetPackageImportStamp>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>Bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>Bin\Release</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>Bin\x86\Debug</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>Bin\x86\Release</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>Bin\ARM\Debug</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|ARM' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>Bin\ARM\Release</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|ARM'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\ARM\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="App.xaml.cs">
+ <DependentUpon>App.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="BrokenNativeControl.cs" />
+ <Compile Include="LocalizedStrings.cs" />
+ <Compile Include="MainPage.xaml.cs">
+ <DependentUpon>MainPage.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Resources\AppResources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>AppResources.resx</DependentUpon>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <ApplicationDefinition Include="App.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </ApplicationDefinition>
+ <Page Include="MainPage.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.config" />
+ <None Include="packages.config" />
+ <None Include="Properties\AppManifest.xml" />
+ <None Include="Properties\WMAppManifest.xml">
+ <SubType>Designer</SubType>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="Assets\AlignmentGrid.png" />
+ <Content Include="Assets\ApplicationIcon.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="Assets\Tiles\FlipCycleTileLarge.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="Assets\Tiles\FlipCycleTileMedium.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="Assets\Tiles\FlipCycleTileSmall.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="Assets\Tiles\IconicTileMediumLarge.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="Assets\Tiles\IconicTileSmall.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="bank.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="cover1.jpg">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="cover1small.jpg" />
+ <Content Include="crimson.jpg" />
+ <Content Include="crimsonsmall.jpg" />
+ <Content Include="default.css" />
+ <Content Include="local.html" />
+ <Content Include="oasis.jpg" />
+ <Content Include="oasissmall.jpg" />
+ <Content Include="menuIcon.png" />
+ <Content Include="photo.jpg">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="seth.png" />
+ <Content Include="toolbar_close.png" />
+ <Content Include="WebImages\XamarinLogo.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\AppResources.resx">
+ <Generator>PublicResXFileCodeGenerator</Generator>
+ <LastGenOutput>AppResources.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Stubs\Xamarin.Forms.Platform.WP8\Xamarin.Forms.Platform.WP8 %28Forwarders%29.csproj">
+ <Project>{483cdae7-4353-4ab2-9c20-145a9f148fad}</Project>
+ <Name>Xamarin.Forms.Platform.WP8 %28Forwarders%29</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Controls\Xamarin.Forms.Controls.csproj">
+ <Project>{CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}</Project>
+ <Name>Xamarin.Forms.Controls</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps.WP8\Xamarin.Forms.Maps.WP8.csproj">
+ <Project>{9222D2B8-63A4-4A36-A80E-BC34F27E0951}</Project>
+ <Name>Xamarin.Forms.Maps.WP8</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7D13BAC2-C6A4-416A-B07E-C169B199E52B}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.WP8\Xamarin.Forms.Platform.WP8.csproj">
+ <Project>{517B6AE0-792B-4665-9376-5CA33E539181}</Project>
+ <Name>Xamarin.Forms.Platform.WP8</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="Xamarin.Insights, Version=1.11.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.Insights.1.11.4\lib\WP80\Xamarin.Insights.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).$(TargetFrameworkVersion).Overrides.targets" />
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ProjectExtensions />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+ <Error Condition="!Exists('..\packages\Xamarin.Insights.1.11.4\build\WP80\Xamarin.Insights.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Insights.1.11.4\build\WP80\Xamarin.Insights.targets'))" />
+ </Target>
+ <Import Project="..\packages\Xamarin.Insights.1.11.4\build\WP80\Xamarin.Insights.targets" Condition="Exists('..\packages\Xamarin.Insights.1.11.4\build\WP80\Xamarin.Insights.targets')" />
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WP8/app.config b/Xamarin.Forms.ControlGallery.WP8/app.config
new file mode 100644
index 00000000..b1d2a5a3
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/app.config
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="Mono.Cecil" publicKeyToken="0738eb9f132ed756" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-0.9.6.0" newVersion="0.9.6.0" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WP8/bank.png b/Xamarin.Forms.ControlGallery.WP8/bank.png
new file mode 100644
index 00000000..fbf2947e
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/bank.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/cover1.jpg b/Xamarin.Forms.ControlGallery.WP8/cover1.jpg
new file mode 100644
index 00000000..f2cea334
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/cover1.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/cover1small.jpg b/Xamarin.Forms.ControlGallery.WP8/cover1small.jpg
new file mode 100644
index 00000000..c820c471
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/cover1small.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/crimson.jpg b/Xamarin.Forms.ControlGallery.WP8/crimson.jpg
new file mode 100644
index 00000000..3db7bb21
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/crimson.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/crimsonsmall.jpg b/Xamarin.Forms.ControlGallery.WP8/crimsonsmall.jpg
new file mode 100644
index 00000000..426c5e07
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/crimsonsmall.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/default.css b/Xamarin.Forms.ControlGallery.WP8/default.css
new file mode 100644
index 00000000..9e32b419
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/default.css
@@ -0,0 +1,2 @@
+html,body{margin:0;padding:10}
+body,p,h1{font-family:Chalkduster;font-style: italic;} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WP8/local.html b/Xamarin.Forms.ControlGallery.WP8/local.html
new file mode 100644
index 00000000..b1998a12
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/local.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<link rel="stylesheet" href="default.css">
+</head>
+<body>
+<h1>Xamarin.Forms</h1>
+<p>This is a local iOS Html page</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WP8/menuIcon.png b/Xamarin.Forms.ControlGallery.WP8/menuIcon.png
new file mode 100644
index 00000000..0793dc7b
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/menuIcon.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/oasis.jpg b/Xamarin.Forms.ControlGallery.WP8/oasis.jpg
new file mode 100644
index 00000000..e0c15afc
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/oasis.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/oasissmall.jpg b/Xamarin.Forms.ControlGallery.WP8/oasissmall.jpg
new file mode 100644
index 00000000..f8d43821
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/oasissmall.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/packages.config b/Xamarin.Forms.ControlGallery.WP8/packages.config
new file mode 100644
index 00000000..aa654dda
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Xamarin.Insights" version="1.11.4" targetFramework="wp8" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WP8/photo.jpg b/Xamarin.Forms.ControlGallery.WP8/photo.jpg
new file mode 100644
index 00000000..07fd4b0a
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/photo.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/seth.png b/Xamarin.Forms.ControlGallery.WP8/seth.png
new file mode 100644
index 00000000..568360e8
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/seth.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WP8/toolbar_close.png b/Xamarin.Forms.ControlGallery.WP8/toolbar_close.png
new file mode 100644
index 00000000..12f82abb
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WP8/toolbar_close.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Windows/App.xaml b/Xamarin.Forms.ControlGallery.Windows/App.xaml
new file mode 100644
index 00000000..fd5f15d9
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/App.xaml
@@ -0,0 +1,7 @@
+<Application
+ x:Class="Xamarin.Forms.ControlGallery.Windows.App"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="using:Xamarin.Forms.ControlGallery.Windows">
+
+</Application>
diff --git a/Xamarin.Forms.ControlGallery.Windows/App.xaml.cs b/Xamarin.Forms.ControlGallery.Windows/App.xaml.cs
new file mode 100644
index 00000000..a20e2ce0
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/App.xaml.cs
@@ -0,0 +1,67 @@
+using System;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Activation;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Navigation;
+
+namespace Xamarin.Forms.ControlGallery.Windows
+{
+ public sealed partial class App
+ {
+ public App()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnLaunched(LaunchActivatedEventArgs e)
+ {
+
+#if DEBUG
+ if (System.Diagnostics.Debugger.IsAttached)
+ {
+ DebugSettings.EnableFrameRateCounter = true;
+ }
+#endif
+
+ var rootFrame = Window.Current.Content as global::Windows.UI.Xaml.Controls.Frame;
+
+ // Do not repeat app initialization when the Window already has content,
+ // just ensure that the window is active
+ if (rootFrame == null)
+ {
+ // Create a Frame to act as the navigation context and navigate to the first page
+ rootFrame = new global::Windows.UI.Xaml.Controls.Frame();
+ // Set the default language
+ rootFrame.Language = global::Windows.Globalization.ApplicationLanguages.Languages[0];
+
+ rootFrame.NavigationFailed += OnNavigationFailed;
+
+ Forms.Init (e);
+ FormsMaps.Init (Controls.App.Secrets["Win8MapsAuthKey"]);
+
+ // Place the frame in the current Window
+ Window.Current.Content = rootFrame;
+ }
+
+ if (rootFrame.Content == null)
+ {
+ // When the navigation stack isn't restored navigate to the first page,
+ // configuring the new page by passing required information as a navigation
+ // parameter
+ rootFrame.Navigate(typeof(MainPage), e.Arguments);
+ }
+ // Ensure the current window is active
+ Window.Current.Activate();
+ }
+
+ /// <summary>
+ /// Invoked when Navigation to a certain page fails
+ /// </summary>
+ /// <param name="sender">The Frame which failed navigation</param>
+ /// <param name="e">Details about the navigation failure</param>
+ void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
+ {
+ throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Windows/Assets/Logo.scale-100.png b/Xamarin.Forms.ControlGallery.Windows/Assets/Logo.scale-100.png
new file mode 100644
index 00000000..e26771cb
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/Assets/Logo.scale-100.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Windows/Assets/SmallLogo.scale-100.png b/Xamarin.Forms.ControlGallery.Windows/Assets/SmallLogo.scale-100.png
new file mode 100644
index 00000000..1eb0d9d5
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/Assets/SmallLogo.scale-100.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Windows/Assets/SplashScreen.scale-100.png b/Xamarin.Forms.ControlGallery.Windows/Assets/SplashScreen.scale-100.png
new file mode 100644
index 00000000..c951e031
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/Assets/SplashScreen.scale-100.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Windows/Assets/StoreLogo.scale-100.png b/Xamarin.Forms.ControlGallery.Windows/Assets/StoreLogo.scale-100.png
new file mode 100644
index 00000000..dcb67271
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/Assets/StoreLogo.scale-100.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Windows/BrokenNativeControl.cs b/Xamarin.Forms.ControlGallery.Windows/BrokenNativeControl.cs
new file mode 100644
index 00000000..02536301
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/BrokenNativeControl.cs
@@ -0,0 +1,64 @@
+using Windows.Foundation;
+using Windows.Graphics.Display;
+using Windows.UI;
+using Windows.UI.ViewManagement;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+
+namespace Xamarin.Forms.ControlGallery.Windows
+{
+ internal class BrokenNativeControl : Panel
+ {
+ public BrokenNativeControl ()
+ {
+ _textBlock = new TextBlock {
+ MinHeight = 0,
+ MaxHeight = double.PositiveInfinity,
+ MinWidth = 0,
+ MaxWidth = double.PositiveInfinity,
+ FontSize = 24,
+ HorizontalAlignment = HorizontalAlignment.Center
+ };
+
+ Children.Add (_textBlock);
+
+ Background =
+ new LinearGradientBrush (
+ new GradientStopCollection { new GradientStop { Color = Colors.Green, Offset = 0.5}, new GradientStop { Color = Colors.Blue, Offset = 1} }, 0);
+ }
+
+ public static readonly DependencyProperty TextProperty = DependencyProperty.Register (
+ "Text", typeof(string), typeof(BrokenNativeControl), new PropertyMetadata (default(string), PropertyChangedCallback));
+
+ static void PropertyChangedCallback (DependencyObject dependencyObject,
+ DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
+ {
+ ((BrokenNativeControl)dependencyObject)._textBlock.Text = (string)dependencyPropertyChangedEventArgs.NewValue;
+ }
+
+ public string Text
+ {
+ get { return (string)GetValue (TextProperty); }
+ set { SetValue (TextProperty, value); }
+ }
+
+ readonly TextBlock _textBlock;
+
+ protected override global::Windows.Foundation.Size ArrangeOverride(global::Windows.Foundation.Size finalSize)
+ {
+ _textBlock.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
+ return finalSize;
+ }
+
+ protected override global::Windows.Foundation.Size MeasureOverride (global::Windows.Foundation.Size availableSize)
+ {
+ _textBlock.Measure (availableSize);
+
+ // This deliberately does something wrong so we can demo fixing it
+ var width = Window.Current.Bounds.Width * (int)DisplayProperties.ResolutionScale / 100;
+
+ return new global::Windows.Foundation.Size (width, _textBlock.DesiredSize.Height);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Windows/MainPage.xaml b/Xamarin.Forms.ControlGallery.Windows/MainPage.xaml
new file mode 100644
index 00000000..b6c68bc2
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/MainPage.xaml
@@ -0,0 +1,11 @@
+<forms:WindowsPage
+ x:Class="Xamarin.Forms.ControlGallery.Windows.MainPage"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="using:Xamarin.Forms.ControlGallery.Windows"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:forms="using:Xamarin.Forms.Platform.WinRT"
+ mc:Ignorable="d">
+
+</forms:WindowsPage> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Windows/MainPage.xaml.cs b/Xamarin.Forms.ControlGallery.Windows/MainPage.xaml.cs
new file mode 100644
index 00000000..d02dda0e
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/MainPage.xaml.cs
@@ -0,0 +1,100 @@
+using System;
+using Windows.Foundation;
+using Windows.Graphics.Display;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+using Xamarin.Forms.Controls;
+using Xamarin.Forms.Platform.WinRT;
+
+namespace Xamarin.Forms.ControlGallery.Windows
+{
+ public sealed partial class MainPage
+ {
+ public MainPage ()
+ {
+ InitializeComponent ();
+
+ var app = new Controls.App ();
+
+ var mdp = app.MainPage as MasterDetailPage;
+
+ var detail = mdp?.Detail as NavigationPage;
+ if (detail != null) {
+ detail.Pushed += (sender, args) => {
+ var nncgPage = args.Page as NestedNativeControlGalleryPage;
+
+ if (nncgPage != null) {
+ AddNativeControls (nncgPage);
+ }
+ };
+ }
+
+ LoadApplication (app);
+ }
+
+ static void AddNativeControls (NestedNativeControlGalleryPage page)
+ {
+ if (page.NativeControlsAdded) {
+ return;
+ }
+
+ StackLayout sl = page.Layout;
+
+ // Create and add a native TextBlock
+ var originalText = "I am a native TextBlock";
+ var textBlock = new TextBlock {
+ Text = originalText,
+ FontSize = 14,
+ FontFamily = new FontFamily ("HelveticaNeue")
+ };
+
+ sl?.Children.Add (textBlock);
+
+ // Create and add a native Button
+ var button = new global::Windows.UI.Xaml.Controls.Button { Content = "Click to toggle font size", Height = 80 };
+ button.Click += (sender, args) => { textBlock.FontSize = textBlock.FontSize == 14 ? 24 : 14; };
+
+ sl?.Children.Add (button.ToView ());
+
+ // Create a control which we know doesn't behave correctly with regard to measurement
+ var difficultControl = new BrokenNativeControl {
+ Text = "Not Sized/Arranged Properly"
+ };
+
+ var difficultControl2 = new BrokenNativeControl {
+ Text = "Fixed"
+ };
+
+ // Add the misbehaving controls, one with a custom delegate for ArrangeOverrideDelegate
+ sl?.Children.Add (difficultControl);
+ sl?.Children.Add (difficultControl2,
+ arrangeOverrideDelegate: (renderer, finalSize) => {
+ if (finalSize.Width <= 0 || double.IsInfinity (finalSize.Width)) {
+ return null;
+ }
+
+ FrameworkElement frameworkElement = renderer.Control;
+
+ frameworkElement.Measure (finalSize);
+
+ // The broken control tries sizes itself to be the width of the screen
+ var wrongSize = Window.Current.Bounds.Width * (int)DisplayProperties.ResolutionScale / 100;
+
+ // We can re-center it by offsetting it during the Arrange call
+ double diff = Math.Abs(finalSize.Width - wrongSize) / -2;
+ frameworkElement.Arrange (new Rect (diff, 0, finalSize.Width - diff, finalSize.Height));
+
+ // Arranging the control to the left will make it show up past the edge of the stack layout
+ // We can fix that by clipping it manually
+ var clip = new RectangleGeometry { Rect = new Rect (-diff, 0, finalSize.Width, finalSize.Height) };
+ frameworkElement.Clip = clip;
+
+ return finalSize;
+ }
+ );
+
+ page.NativeControlsAdded = true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Windows/Package.appxmanifest b/Xamarin.Forms.ControlGallery.Windows/Package.appxmanifest
new file mode 100644
index 00000000..643facd6
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/Package.appxmanifest
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest">
+ <Identity Name="a4530307-5452-466a-8944-7925f27ddc21" Publisher="CN=Eric" Version="1.0.0.0" />
+ <Properties>
+ <DisplayName>Xamarin.Forms.ControlGallery.Windows</DisplayName>
+ <PublisherDisplayName>Xamarin Inc</PublisherDisplayName>
+ <Logo>Assets\StoreLogo.png</Logo>
+ </Properties>
+ <Prerequisites>
+ <OSMinVersion>6.3.0</OSMinVersion>
+ <OSMaxVersionTested>6.3.0</OSMaxVersionTested>
+ </Prerequisites>
+ <Resources>
+ <Resource Language="x-generate" />
+ </Resources>
+ <Applications>
+ <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="Xamarin.Forms.ControlGallery.Windows.App">
+ <m2:VisualElements DisplayName="Xamarin.Forms.ControlGallery.Windows" Square150x150Logo="Assets\Logo.png" Square30x30Logo="Assets\SmallLogo.png" Description="Xamarin.Forms.ControlGallery.Windows" ForegroundText="light" BackgroundColor="#464646">
+ <m2:SplashScreen Image="Assets\SplashScreen.png" />
+ </m2:VisualElements>
+ </Application>
+ </Applications>
+ <Capabilities>
+ <Capability Name="internetClient" />
+ <Capability Name="internetClientServer" />
+ <Capability Name="privateNetworkClientServer" />
+ <DeviceCapability Name="location" />
+ </Capabilities>
+</Package> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Windows/Properties/AssemblyInfo.cs b/Xamarin.Forms.ControlGallery.Windows/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..89577935
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Xamarin.Forms.ControlGallery.Windows")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Forms.ControlGallery.Windows")]
+[assembly: AssemblyCopyright("Copyright © Xamarin Inc 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)] \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Windows/StringProvider.cs b/Xamarin.Forms.ControlGallery.Windows/StringProvider.cs
new file mode 100644
index 00000000..68da57e7
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/StringProvider.cs
@@ -0,0 +1,15 @@
+using Xamarin.Forms;
+using Xamarin.Forms.ControlGallery.WinRT;
+using Xamarin.Forms.Controls;
+
+[assembly: Dependency (typeof (StringProvider))]
+
+namespace Xamarin.Forms.ControlGallery.WinRT
+{
+ public class StringProvider : IStringProvider
+ {
+ public string CoreGalleryTitle {
+ get { return "Windows Core Gallery"; }
+ }
+ }
+}
diff --git a/Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows.csproj b/Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows.csproj
new file mode 100644
index 00000000..c5f558b5
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows.csproj
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="..\nuspec\Xamarin.Forms.Maps.props" Condition="Exists('..\nuspec\Xamarin.Forms.Maps.props')" />
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{1251646E-7FC6-425C-9464-A35DF1FC8E4D}</ProjectGuid>
+ <OutputType>AppContainerExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.ControlGallery.Windows</RootNamespace>
+ <AssemblyName>Xamarin.Forms.ControlGallery.Windows</AssemblyName>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <TargetPlatformVersion>8.1</TargetPlatformVersion>
+ <MinimumVisualStudioVersion>12</MinimumVisualStudioVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <PackageCertificateKeyFile>Xamarin.Forms.ControlGallery.Windows_TemporaryKey.pfx</PackageCertificateKeyFile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\ARM\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+ <OutputPath>bin\ARM\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x64\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ <OutputPath>bin\x64\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
+ <ProjectReference Include="..\Xamarin.Forms.Controls\Xamarin.Forms.Controls.csproj">
+ <Project>{cb9c96ce-125c-4a68-b6a1-c3ff1fbf93e1}</Project>
+ <Name>Xamarin.Forms.Controls</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps.WinRT.Tablet\Xamarin.Forms.Maps.WinRT.Tablet.csproj">
+ <Project>{e5c4698d-fb57-4eec-98c0-89e620f6920a}</Project>
+ <Name>Xamarin.Forms.Maps.WinRT.Tablet</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.WinRT.Tablet\Xamarin.Forms.Platform.WinRT.Tablet.csproj">
+ <Project>{d3f9265a-30ac-43e8-a3eb-59bb76d2d0bf}</Project>
+ <Name>Xamarin.Forms.Platform.WinRT.Tablet</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.WinRT\Xamarin.Forms.Platform.WinRT.csproj">
+ <Project>{f3fdd7ac-8899-4e41-bfd7-ec83403e736d}</Project>
+ <Name>Xamarin.Forms.Platform.WinRT</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="App.xaml.cs">
+ <DependentUpon>App.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="BrokenNativeControl.cs" />
+ <Compile Include="MainPage.xaml.cs">
+ <DependentUpon>MainPage.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="StringProvider.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <AppxManifest Include="Package.appxmanifest">
+ <SubType>Designer</SubType>
+ </AppxManifest>
+ <None Include="Xamarin.Forms.ControlGallery.Windows_TemporaryKey.pfx" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\bank.png">
+ <Link>bank.png</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\cover1.jpg">
+ <Link>cover1.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\cover1small.jpg">
+ <Link>cover1small.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\crimson.jpg">
+ <Link>crimson.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\crimsonsmall.jpg">
+ <Link>crimsonsmall.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\menuIcon.png">
+ <Link>menuIcon.png</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\oasis.jpg">
+ <Link>oasis.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\oasissmall.jpg">
+ <Link>oasissmall.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\photo.jpg">
+ <Link>photo.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\seth.png">
+ <Link>seth.png</Link>
+ </Content>
+ <Content Include="Assets\Logo.scale-100.png" />
+ <Content Include="Assets\SmallLogo.scale-100.png" />
+ <Content Include="Assets\SplashScreen.scale-100.png" />
+ <Content Include="Assets\StoreLogo.scale-100.png" />
+ <Content Include="toolbar_close.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <ApplicationDefinition Include="App.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </ApplicationDefinition>
+ </ItemGroup>
+ <ItemGroup>
+ <Page Include="MainPage.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ </ItemGroup>
+ <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '12.0' ">
+ <VisualStudioVersion>12.0</VisualStudioVersion>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
+ <Import Project="$(XamlSpyInstallPath)MSBuild\FirstFloor.XamlSpy.WinRT.targets" Condition="'$(XamlSpyInstallPath)' != '' and '$(Configuration)' == 'DEBUG'" />
+ <Import Project="..\nuspec\Xamarin.Forms.Maps.targets" Condition="Exists('..\nuspec\Xamarin.Forms.Maps.targets')" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows_TemporaryKey.pfx b/Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows_TemporaryKey.pfx
new file mode 100644
index 00000000..c4de2da1
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows_TemporaryKey.pfx
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Windows/toolbar_close.png b/Xamarin.Forms.ControlGallery.Windows/toolbar_close.png
new file mode 100644
index 00000000..12f82abb
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/toolbar_close.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/App.xaml b/Xamarin.Forms.ControlGallery.WindowsPhone/App.xaml
new file mode 100644
index 00000000..7be404c7
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/App.xaml
@@ -0,0 +1,7 @@
+<Application
+ x:Class="Xamarin.Forms.ControlGallery.WindowsPhone.App"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="using:Xamarin.Forms.ControlGallery.WindowsPhone">
+
+</Application> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/App.xaml.cs b/Xamarin.Forms.ControlGallery.WindowsPhone/App.xaml.cs
new file mode 100644
index 00000000..1842bb86
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/App.xaml.cs
@@ -0,0 +1,134 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Activation;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Media.Animation;
+using Windows.UI.Xaml.Navigation;
+
+// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=391641
+
+namespace Xamarin.Forms.ControlGallery.WindowsPhone
+{
+ /// <summary>
+ /// Provides application-specific behavior to supplement the default Application class.
+ /// </summary>
+ public sealed partial class App
+ {
+ TransitionCollection _transitions;
+
+ /// <summary>
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ /// </summary>
+ public App()
+ {
+ InitializeComponent();
+ Suspending += OnSuspending;
+ }
+
+ /// <summary>
+ /// Invoked when the application is launched normally by the end user. Other entry points
+ /// will be used when the application is launched to open a specific file, to display
+ /// search results, and so forth.
+ /// </summary>
+ /// <param name="e">Details about the launch request and process.</param>
+ protected override void OnLaunched(LaunchActivatedEventArgs e)
+ {
+#if DEBUG
+ if (System.Diagnostics.Debugger.IsAttached)
+ {
+ DebugSettings.EnableFrameRateCounter = true;
+ }
+#endif
+
+ var rootFrame = Window.Current.Content as global::Windows.UI.Xaml.Controls.Frame;
+
+ // Do not repeat app initialization when the Window already has content,
+ // just ensure that the window is active
+ if (rootFrame == null)
+ {
+ // Create a Frame to act as the navigation context and navigate to the first page
+ rootFrame = new global::Windows.UI.Xaml.Controls.Frame();
+
+ // TODO: change this value to a cache size that is appropriate for your application
+ rootFrame.CacheSize = 1;
+
+ Forms.Init (e);
+ FormsMaps.Init (Controls.App.Secrets["WinPhoneMapsAuthKey"]);
+
+ if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
+ {
+ // TODO: Load state from previously suspended application
+ }
+
+ // Place the frame in the current Window
+ Window.Current.Content = rootFrame;
+ }
+
+ if (rootFrame.Content == null)
+ {
+ // Removes the turnstile navigation for startup.
+ if (rootFrame.ContentTransitions != null)
+ {
+ _transitions = new TransitionCollection();
+ foreach (var c in rootFrame.ContentTransitions)
+ {
+ _transitions.Add(c);
+ }
+ }
+
+ rootFrame.ContentTransitions = null;
+ rootFrame.Navigated += RootFrame_FirstNavigated;
+
+ // When the navigation stack isn't restored navigate to the first page,
+ // configuring the new page by passing required information as a navigation
+ // parameter
+ if (!rootFrame.Navigate(typeof(MainPage), e.Arguments))
+ {
+ throw new Exception("Failed to create initial page");
+ }
+ }
+
+ // Ensure the current window is active
+ Window.Current.Activate();
+ }
+
+ /// <summary>
+ /// Restores the content transitions after the app has launched.
+ /// </summary>
+ /// <param name="sender">The object where the handler is attached.</param>
+ /// <param name="e">Details about the navigation event.</param>
+ void RootFrame_FirstNavigated(object sender, global::Windows.UI.Xaml.Navigation.NavigationEventArgs e)
+ {
+ var rootFrame = sender as global::Windows.UI.Xaml.Controls.Frame;
+ rootFrame.ContentTransitions = _transitions ?? new TransitionCollection() { new NavigationThemeTransition() };
+ rootFrame.Navigated -= RootFrame_FirstNavigated;
+ }
+
+ /// <summary>
+ /// Invoked when application execution is being suspended. Application state is saved
+ /// without knowing whether the application will be terminated or resumed with the contents
+ /// of memory still intact.
+ /// </summary>
+ /// <param name="sender">The source of the suspend request.</param>
+ /// <param name="e">Details about the suspend request.</param>
+ void OnSuspending(object sender, SuspendingEventArgs e)
+ {
+ var deferral = e.SuspendingOperation.GetDeferral();
+
+ // TODO: Save application state and stop any background activity
+ deferral.Complete();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/Logo.scale-240.png b/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/Logo.scale-240.png
new file mode 100644
index 00000000..76921ca9
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/Logo.scale-240.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/SmallLogo.scale-240.png b/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/SmallLogo.scale-240.png
new file mode 100644
index 00000000..31663012
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/SmallLogo.scale-240.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/SplashScreen.scale-240.png b/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/SplashScreen.scale-240.png
new file mode 100644
index 00000000..33f26b33
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/SplashScreen.scale-240.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/Square71x71Logo.scale-240.png b/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/Square71x71Logo.scale-240.png
new file mode 100644
index 00000000..cfa54bee
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/Square71x71Logo.scale-240.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/StoreLogo.scale-240.png b/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/StoreLogo.scale-240.png
new file mode 100644
index 00000000..47e084b5
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/StoreLogo.scale-240.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/WideLogo.scale-240.png b/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/WideLogo.scale-240.png
new file mode 100644
index 00000000..6249d29d
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/Assets/WideLogo.scale-240.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/BrokenNativeControl.cs b/Xamarin.Forms.ControlGallery.WindowsPhone/BrokenNativeControl.cs
new file mode 100644
index 00000000..5be6db25
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/BrokenNativeControl.cs
@@ -0,0 +1,65 @@
+using Windows.Foundation;
+using Windows.Graphics.Display;
+using Windows.UI;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+using WSize = Windows.Foundation.Size;
+
+namespace Xamarin.Forms.ControlGallery.WindowsPhone
+{
+ internal class BrokenNativeControl : Panel
+ {
+ public BrokenNativeControl ()
+ {
+ _textBlock = new TextBlock {
+ MinHeight = 0,
+ MaxHeight = double.PositiveInfinity,
+ MinWidth = 0,
+ MaxWidth = double.PositiveInfinity,
+ FontSize = 24,
+ HorizontalAlignment = HorizontalAlignment.Center
+ };
+
+ Children.Add (_textBlock);
+
+ Background =
+ new LinearGradientBrush (
+ new GradientStopCollection { new GradientStop { Color = Colors.Green, Offset = 0.5}, new GradientStop { Color = Colors.Blue, Offset = 1} }, 0);
+ }
+
+ public static readonly DependencyProperty TextProperty = DependencyProperty.Register (
+ "Text", typeof(string), typeof(BrokenNativeControl), new PropertyMetadata (default(string), PropertyChangedCallback));
+
+ static void PropertyChangedCallback (DependencyObject dependencyObject,
+ DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
+ {
+ ((BrokenNativeControl)dependencyObject)._textBlock.Text = (string)dependencyPropertyChangedEventArgs.NewValue;
+ }
+
+ public string Text
+ {
+ get { return (string)GetValue (TextProperty); }
+ set { SetValue (TextProperty, value); }
+ }
+
+ readonly TextBlock _textBlock;
+
+ protected override WSize ArrangeOverride(WSize finalSize)
+ {
+ _textBlock.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
+ return finalSize;
+ }
+
+ protected override WSize MeasureOverride (WSize availableSize)
+ {
+ _textBlock.Measure (availableSize);
+
+ // This deliberately does something wrong so we can demo fixing it
+ var width = Window.Current.Bounds.Width * (int)DisplayProperties.ResolutionScale / 100;
+
+ // This deliberately does something wrong so we can demo fixing it
+ return new WSize (width, _textBlock.DesiredSize.Height);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/MainPage.xaml b/Xamarin.Forms.ControlGallery.WindowsPhone/MainPage.xaml
new file mode 100644
index 00000000..0ce7c4aa
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/MainPage.xaml
@@ -0,0 +1,11 @@
+<winRt:WindowsPhonePage
+ x:Class="Xamarin.Forms.ControlGallery.WindowsPhone.MainPage"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="using:Xamarin.Forms.ControlGallery.WindowsPhone"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:winRt="using:Xamarin.Forms.Platform.WinRT"
+ mc:Ignorable="d">
+
+</winRt:WindowsPhonePage>
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/MainPage.xaml.cs b/Xamarin.Forms.ControlGallery.WindowsPhone/MainPage.xaml.cs
new file mode 100644
index 00000000..1c34efd6
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/MainPage.xaml.cs
@@ -0,0 +1,108 @@
+using System;
+using Windows.Foundation;
+using Windows.Graphics.Display;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+using Xamarin.Forms.Controls;
+using WControls = Windows.UI.Xaml.Controls;
+using Xamarin.Forms.Platform.WinRT;
+
+// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=391641
+
+namespace Xamarin.Forms.ControlGallery.WindowsPhone
+{
+ /// <summary>
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ /// </summary>
+ public sealed partial class MainPage
+ {
+ public MainPage ()
+ {
+ InitializeComponent ();
+
+ var app = new Controls.App ();
+
+ var mdp = app.MainPage as MasterDetailPage;
+
+ var detail = mdp?.Detail as NavigationPage;
+ if (detail != null) {
+ detail.Pushed += (sender, args) => {
+ var nncgPage = args.Page as NestedNativeControlGalleryPage;
+
+ if (nncgPage != null) {
+ AddNativeControls (nncgPage);
+ }
+ };
+ }
+
+ LoadApplication (app);
+ }
+
+ void AddNativeControls (NestedNativeControlGalleryPage page)
+ {
+ if (page.NativeControlsAdded) {
+ return;
+ }
+
+ StackLayout sl = page.Layout;
+
+ // Create and add a native TextBlock
+ var originalText = "I am a native TextBlock";
+ var textBlock = new TextBlock {
+ Text = originalText,
+ FontSize = 14,
+ FontFamily = new FontFamily ("HelveticaNeue")
+ };
+
+ sl?.Children.Add (textBlock);
+
+ // Create and add a native Button
+ var button = new WControls.Button { Content = "Click to toggle font size", Height = 80 };
+ button.Click += (sender, args) => { textBlock.FontSize = textBlock.FontSize == 14 ? 24 : 14; };
+
+ sl?.Children.Add (button.ToView ());
+
+ // Create a control which we know doesn't behave correctly with regard to measurement
+ var difficultControl = new BrokenNativeControl {
+ Text = "Not Sized/Arranged Properly"
+ };
+
+ var difficultControl2 = new BrokenNativeControl {
+ Text = "Fixed"
+ };
+
+ // Add the misbehaving controls, one with a custom delegate for ArrangeOverrideDelegate
+ sl?.Children.Add (difficultControl);
+ sl?.Children.Add (difficultControl2,
+ arrangeOverrideDelegate: (renderer, finalSize) => {
+ if (finalSize.Width <= 0 || double.IsInfinity (finalSize.Width)) {
+ return null;
+ }
+
+ FrameworkElement frameworkElement = renderer.Control;
+
+ frameworkElement.Measure (finalSize);
+
+ // The broken control tries sizes itself to be the width of the screen
+ var wrongSize = Window.Current.Bounds.Width * (int)DisplayProperties.ResolutionScale / 100;
+
+ // The broken control always sizes itself to be 600 wide
+ // We can re-center it by offsetting it during the Arrange call
+ double diff = Math.Abs(finalSize.Width - wrongSize) / -2;
+ frameworkElement.Arrange (new Rect (diff, 0, finalSize.Width - diff, finalSize.Height));
+
+ // Arranging the control to the left will make it show up past the edge of the master page
+ // We can fix that by clipping it manually
+ var clip = new RectangleGeometry { Rect = new Rect (-diff, 0, finalSize.Width, finalSize.Height) };
+ frameworkElement.Clip = clip;
+
+ return finalSize;
+ }
+ );
+
+ page.NativeControlsAdded = true;
+ }
+
+ }
+}
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/Package.appxmanifest b/Xamarin.Forms.ControlGallery.WindowsPhone/Package.appxmanifest
new file mode 100644
index 00000000..b47c1316
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/Package.appxmanifest
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest" xmlns:m3="http://schemas.microsoft.com/appx/2014/manifest" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest">
+ <Identity Name="7d1da7bc-9b18-4581-9184-6b674b7a3dbe" Publisher="CN=Eric" Version="1.0.0.0" />
+ <mp:PhoneIdentity PhoneProductId="7d1da7bc-9b18-4581-9184-6b674b7a3dbe" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
+ <Properties>
+ <DisplayName>Xamarin.Forms.ControlGallery.WindowsPhone</DisplayName>
+ <PublisherDisplayName>Eric</PublisherDisplayName>
+ <Logo>Assets\StoreLogo.png</Logo>
+ </Properties>
+ <Prerequisites>
+ <OSMinVersion>6.3.1</OSMinVersion>
+ <OSMaxVersionTested>6.3.1</OSMaxVersionTested>
+ </Prerequisites>
+ <Resources>
+ <Resource Language="x-generate" />
+ </Resources>
+ <Applications>
+ <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="Xamarin.Forms.ControlGallery.WindowsPhone.App">
+ <m3:VisualElements DisplayName="Xamarin.Forms.ControlGallery.WindowsPhone" Square150x150Logo="Assets\Logo.png" Square44x44Logo="Assets\SmallLogo.png" Description="Xamarin.Forms.ControlGallery.WindowsPhone" ForegroundText="light" BackgroundColor="transparent">
+ <m3:DefaultTile Wide310x150Logo="Assets\WideLogo.png" Square71x71Logo="Assets\Square71x71Logo.png">
+ </m3:DefaultTile>
+ <m3:SplashScreen Image="Assets\SplashScreen.png" />
+ <m3:InitialRotationPreference>
+ <m3:Rotation Preference="portrait" />
+ <m3:Rotation Preference="landscape" />
+ <m3:Rotation Preference="landscapeFlipped" />
+ </m3:InitialRotationPreference>
+ </m3:VisualElements>
+ </Application>
+ </Applications>
+ <Capabilities>
+ <Capability Name="internetClientServer" />
+ </Capabilities>
+</Package> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/Properties/AssemblyInfo.cs b/Xamarin.Forms.ControlGallery.WindowsPhone/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..7be28e92
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Xamarin.Forms.ControlGallery.WindowsPhone")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Forms.ControlGallery.WindowsPhone")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)] \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/StringProvider.cs b/Xamarin.Forms.ControlGallery.WindowsPhone/StringProvider.cs
new file mode 100644
index 00000000..f6baddfa
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/StringProvider.cs
@@ -0,0 +1,15 @@
+using Xamarin.Forms;
+using Xamarin.Forms.ControlGallery.Windows;
+using Xamarin.Forms.Controls;
+
+[assembly: Dependency (typeof (StringProvider))]
+
+namespace Xamarin.Forms.ControlGallery.Windows
+{
+ public class StringProvider : IStringProvider
+ {
+ public string CoreGalleryTitle {
+ get { return "Windows Core Gallery"; }
+ }
+ }
+}
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/Xamarin.Forms.ControlGallery.WindowsPhone.csproj b/Xamarin.Forms.ControlGallery.WindowsPhone/Xamarin.Forms.ControlGallery.WindowsPhone.csproj
new file mode 100644
index 00000000..50c990ce
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/Xamarin.Forms.ControlGallery.WindowsPhone.csproj
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{8CDEC974-E6BE-4424-BC77-0B87400A08AF}</ProjectGuid>
+ <OutputType>AppContainerExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.ControlGallery.WindowsPhone</RootNamespace>
+ <AssemblyName>Xamarin.Forms.ControlGallery.WindowsPhone</AssemblyName>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <TargetPlatformVersion>8.1</TargetPlatformVersion>
+ <MinimumVisualStudioVersion>12</MinimumVisualStudioVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{76F1466A-8B6D-4E39-A767-685A06062A39};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\ARM\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+ <OutputPath>bin\ARM\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
+ <ProjectReference Include="..\Xamarin.Forms.Controls\Xamarin.Forms.Controls.csproj">
+ <Project>{cb9c96ce-125c-4a68-b6a1-c3ff1fbf93e1}</Project>
+ <Name>Xamarin.Forms.Controls</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps.WinRT.Phone\Xamarin.Forms.Maps.WinRT.Phone.csproj">
+ <Project>{2633af57-f2cb-442a-ac19-f97bd8a06571}</Project>
+ <Name>Xamarin.Forms.Maps.WinRT.Phone</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.WinRT.Phone\Xamarin.Forms.Platform.WinRT.Phone.csproj">
+ <Project>{3361d52c-2e74-433e-8285-9c9a5c485977}</Project>
+ <Name>Xamarin.Forms.Platform.WinRT.Phone</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.WinRT\Xamarin.Forms.Platform.WinRT.csproj">
+ <Project>{f3fdd7ac-8899-4e41-bfd7-ec83403e736d}</Project>
+ <Name>Xamarin.Forms.Platform.WinRT</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="App.xaml.cs">
+ <DependentUpon>App.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="BrokenNativeControl.cs" />
+ <Compile Include="MainPage.xaml.cs">
+ <DependentUpon>MainPage.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="StringProvider.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <AppxManifest Include="Package.appxmanifest">
+ <SubType>Designer</SubType>
+ </AppxManifest>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\bank.png">
+ <Link>bank.png</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\cover1.jpg">
+ <Link>cover1.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\cover1small.jpg">
+ <Link>cover1small.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\crimson.jpg">
+ <Link>crimson.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\crimsonsmall.jpg">
+ <Link>crimsonsmall.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\menuIcon.png">
+ <Link>menuIcon.png</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\oasis.jpg">
+ <Link>oasis.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\oasissmall.jpg">
+ <Link>oasissmall.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\photo.jpg">
+ <Link>photo.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\seth.png">
+ <Link>seth.png</Link>
+ </Content>
+ <Content Include="Assets\Logo.scale-240.png" />
+ <Content Include="Assets\SmallLogo.scale-240.png" />
+ <Content Include="Assets\SplashScreen.scale-240.png" />
+ <Content Include="Assets\Square71x71Logo.scale-240.png" />
+ <Content Include="Assets\StoreLogo.scale-240.png" />
+ <Content Include="Assets\WideLogo.scale-240.png" />
+ <Content Include="toolbar_close.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <ApplicationDefinition Include="App.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </ApplicationDefinition>
+ <Page Include="MainPage.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.config" />
+ </ItemGroup>
+ <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '12.0' ">
+ <VisualStudioVersion>12.0</VisualStudioVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(TargetPlatformIdentifier)' == '' ">
+ <TargetPlatformIdentifier>WindowsPhoneApp</TargetPlatformIdentifier>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
+ <Import Project="$(XamlSpyInstallPath)MSBuild\FirstFloor.XamlSpy.WindowsPhone.targets" Condition="'$(XamlSpyInstallPath)' != '' and '$(Configuration)' == 'DEBUG'" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/app.config b/Xamarin.Forms.ControlGallery.WindowsPhone/app.config
new file mode 100644
index 00000000..b1d2a5a3
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/app.config
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="Mono.Cecil" publicKeyToken="0738eb9f132ed756" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-0.9.6.0" newVersion="0.9.6.0" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/toolbar_close.png b/Xamarin.Forms.ControlGallery.WindowsPhone/toolbar_close.png
new file mode 100644
index 00000000..12f82abb
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/toolbar_close.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/App.xaml b/Xamarin.Forms.ControlGallery.WindowsUniversal/App.xaml
new file mode 100644
index 00000000..89b2c563
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/App.xaml
@@ -0,0 +1,8 @@
+<Application
+ x:Class="Xamarin.Forms.ControlGallery.WindowsUniversal.App"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="using:Xamarin.Forms.ControlGallery.WindowsUniversal">
+
+
+</Application>
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/App.xaml.cs b/Xamarin.Forms.ControlGallery.WindowsUniversal/App.xaml.cs
new file mode 100644
index 00000000..ff21e8fc
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/App.xaml.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Activation;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Navigation;
+
+// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=402347&clcid=0x409
+
+namespace Xamarin.Forms.ControlGallery.WindowsUniversal
+{
+ /// <summary>
+ /// Provides application-specific behavior to supplement the default Application class.
+ /// </summary>
+ sealed partial class App
+ {
+ /// <summary>
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ /// </summary>
+ public App()
+ {
+ InitializeComponent();
+ Suspending += OnSuspending;
+ }
+
+ /// <summary>
+ /// Invoked when the application is launched normally by the end user. Other entry points
+ /// will be used such as when the application is launched to open a specific file.
+ /// </summary>
+ /// <param name="e">Details about the launch request and process.</param>
+ protected override void OnLaunched(LaunchActivatedEventArgs e)
+ {
+
+#if DEBUG
+ if (System.Diagnostics.Debugger.IsAttached)
+ {
+ DebugSettings.EnableFrameRateCounter = true;
+ }
+#endif
+
+ var rootFrame = Window.Current.Content as Windows.UI.Xaml.Controls.Frame;
+
+ // Do not repeat app initialization when the Window already has content,
+ // just ensure that the window is active
+ if (rootFrame == null)
+ {
+ // Create a Frame to act as the navigation context and navigate to the first page
+ rootFrame = new Windows.UI.Xaml.Controls.Frame();
+ // Set the default language
+ rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];
+
+ rootFrame.NavigationFailed += OnNavigationFailed;
+
+ Forms.Init (e);
+ FormsMaps.Init (Controls.App.Secrets["UWPMapsAuthKey"]);
+
+ // Place the frame in the current Window
+ Window.Current.Content = rootFrame;
+ }
+
+ if (rootFrame.Content == null)
+ {
+ // When the navigation stack isn't restored navigate to the first page,
+ // configuring the new page by passing required information as a navigation
+ // parameter
+ rootFrame.Navigate(typeof(MainPage), e.Arguments);
+ }
+ // Ensure the current window is active
+ Window.Current.Activate();
+ }
+
+ /// <summary>
+ /// Invoked when Navigation to a certain page fails
+ /// </summary>
+ /// <param name="sender">The Frame which failed navigation</param>
+ /// <param name="e">Details about the navigation failure</param>
+ void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
+ {
+ throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
+ }
+
+ /// <summary>
+ /// Invoked when application execution is being suspended. Application state is saved
+ /// without knowing whether the application will be terminated or resumed with the contents
+ /// of memory still intact.
+ /// </summary>
+ /// <param name="sender">The source of the suspend request.</param>
+ /// <param name="e">Details about the suspend request.</param>
+ void OnSuspending(object sender, SuspendingEventArgs e)
+ {
+ var deferral = e.SuspendingOperation.GetDeferral();
+ //TODO: Save application state and stop any background activity
+ deferral.Complete();
+ }
+ }
+}
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/Logo.scale-100.png b/Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/Logo.scale-100.png
new file mode 100644
index 00000000..e26771cb
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/Logo.scale-100.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/SmallLogo.scale-100.png b/Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/SmallLogo.scale-100.png
new file mode 100644
index 00000000..a91554b5
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/SmallLogo.scale-100.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/SplashScreen.scale-100.png b/Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/SplashScreen.scale-100.png
new file mode 100644
index 00000000..c951e031
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/SplashScreen.scale-100.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/StoreLogo.scale-100.png b/Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/StoreLogo.scale-100.png
new file mode 100644
index 00000000..dcb67271
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/StoreLogo.scale-100.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/WideLogo.scale-100.png b/Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/WideLogo.scale-100.png
new file mode 100644
index 00000000..9dd94b62
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/Assets/WideLogo.scale-100.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/BrokenNativeControl.cs b/Xamarin.Forms.ControlGallery.WindowsUniversal/BrokenNativeControl.cs
new file mode 100644
index 00000000..6d98aefc
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/BrokenNativeControl.cs
@@ -0,0 +1,67 @@
+using Windows.Foundation;
+using Windows.Graphics.Display;
+using Windows.UI;
+using Windows.UI.ViewManagement;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+
+namespace Xamarin.Forms.ControlGallery.WindowsUniversal
+{
+ internal class BrokenNativeControl : Panel
+ {
+ public BrokenNativeControl ()
+ {
+ _textBlock = new TextBlock {
+ MinHeight = 0,
+ MaxHeight = double.PositiveInfinity,
+ MinWidth = 0,
+ MaxWidth = double.PositiveInfinity,
+ FontSize = 24,
+ HorizontalAlignment = HorizontalAlignment.Center
+ };
+
+ Children.Add (_textBlock);
+
+ Background =
+ new LinearGradientBrush (
+ new GradientStopCollection { new GradientStop { Color = Colors.Green, Offset = 0.5}, new GradientStop { Color = Colors.Blue, Offset = 1} }, 0);
+ }
+
+ public static readonly DependencyProperty TextProperty = DependencyProperty.Register (
+ "Text", typeof(string), typeof(BrokenNativeControl), new PropertyMetadata (default(string), PropertyChangedCallback));
+
+ static void PropertyChangedCallback (DependencyObject dependencyObject,
+ DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
+ {
+ ((BrokenNativeControl)dependencyObject)._textBlock.Text = (string)dependencyPropertyChangedEventArgs.NewValue;
+ }
+
+ public string Text
+ {
+ get { return (string)GetValue (TextProperty); }
+ set { SetValue (TextProperty, value); }
+ }
+
+ readonly TextBlock _textBlock;
+
+ protected override Windows.Foundation.Size ArrangeOverride(Windows.Foundation.Size finalSize)
+ {
+ _textBlock.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
+ return finalSize;
+ }
+
+
+ protected override Windows.Foundation.Size MeasureOverride (Windows.Foundation.Size availableSize)
+ {
+ _textBlock.Measure (availableSize);
+
+ // This deliberately does something wrong so we can demo fixing it
+ Rect bounds = ApplicationView.GetForCurrentView ().VisibleBounds;
+ double scaleFactor = DisplayInformation.GetForCurrentView ().RawPixelsPerViewPixel;
+ var size = new Size (bounds.Width * scaleFactor, bounds.Height * scaleFactor);
+
+ return new Windows.Foundation.Size (size.Width, _textBlock.DesiredSize.Height);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/MainPage.xaml b/Xamarin.Forms.ControlGallery.WindowsUniversal/MainPage.xaml
new file mode 100644
index 00000000..1fd0e45d
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/MainPage.xaml
@@ -0,0 +1,10 @@
+<forms:WindowsPage
+ x:Class="Xamarin.Forms.ControlGallery.WindowsUniversal.MainPage"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="using:Xamarin.Forms.ControlGallery.WindowsUniversal"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:forms="using:Xamarin.Forms.Platform.UWP"
+ mc:Ignorable="d">
+</forms:WindowsPage> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/MainPage.xaml.cs b/Xamarin.Forms.ControlGallery.WindowsUniversal/MainPage.xaml.cs
new file mode 100644
index 00000000..7e16e83c
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/MainPage.xaml.cs
@@ -0,0 +1,109 @@
+// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
+
+using System;
+using Windows.Foundation;
+using Windows.Graphics.Display;
+using Windows.UI.ViewManagement;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+using Xamarin.Forms.Controls;
+using Xamarin.Forms.Platform.UWP;
+
+namespace Xamarin.Forms.ControlGallery.WindowsUniversal
+{
+ /// <summary>
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ /// </summary>
+ public sealed partial class MainPage
+ {
+ public MainPage()
+ {
+ InitializeComponent();
+
+ var app = new Controls.App ();
+
+ var mdp = app.MainPage as MasterDetailPage;
+
+ var detail = mdp?.Detail as NavigationPage;
+ if (detail != null) {
+ detail.Pushed += (sender, args) => {
+ var nncgPage = args.Page as NestedNativeControlGalleryPage;
+
+ if (nncgPage != null) {
+ AddNativeControls (nncgPage);
+ }
+ };
+ }
+
+ LoadApplication (app);
+ }
+
+ void AddNativeControls (NestedNativeControlGalleryPage page)
+ {
+ if (page.NativeControlsAdded) {
+ return;
+ }
+
+ StackLayout sl = page.Layout;
+
+ // Create and add a native TextBlock
+ var originalText = "I am a native TextBlock";
+ var textBlock = new TextBlock {
+ Text = originalText,
+ FontSize = 14,
+ FontFamily = new FontFamily ("HelveticaNeue")
+ };
+
+ sl?.Children.Add (textBlock);
+
+ // Create and add a native Button
+ var button = new Windows.UI.Xaml.Controls.Button { Content = "Toggle Font Size", Height = 80 };
+ button.Click += (sender, args) => { textBlock.FontSize = textBlock.FontSize == 14 ? 24 : 14; };
+
+ sl?.Children.Add (button.ToView ());
+
+ // Create a control which we know doesn't behave correctly with regard to measurement
+ var difficultControl = new BrokenNativeControl {
+ Text = "Not Sized/Arranged Properly"
+ };
+
+ var difficultControl2 = new BrokenNativeControl {
+ Text = "Fixed"
+ };
+
+ // Add the misbehaving controls, one with a custom delegate for ArrangeOverrideDelegate
+ sl?.Children.Add (difficultControl);
+ sl?.Children.Add (difficultControl2,
+ arrangeOverrideDelegate: (renderer, finalSize) => {
+ if (finalSize.Width <= 0 || double.IsInfinity (finalSize.Width)) {
+ return null;
+ }
+
+ FrameworkElement frameworkElement = renderer.Control;
+
+ frameworkElement.Measure (finalSize);
+
+ // The broken control always tries to size itself to the screen width
+ // So figure that out and we'll know how far off it's laying itself out
+ Rect bounds = ApplicationView.GetForCurrentView ().VisibleBounds;
+ double scaleFactor = DisplayInformation.GetForCurrentView ().RawPixelsPerViewPixel;
+ var screenWidth = new Size (bounds.Width * scaleFactor, bounds.Height * scaleFactor);
+
+ // We can re-center it by offsetting it during the Arrange call
+ double diff = Math.Abs(screenWidth.Width - finalSize.Width) / -2;
+ frameworkElement.Arrange (new Rect (diff, 0, finalSize.Width - diff, finalSize.Height));
+
+ // Arranging the control to the left will make it show up past the edge of the stack layout
+ // We can fix that by clipping it manually
+ var clip = new RectangleGeometry { Rect = new Rect (-diff, 0, finalSize.Width, finalSize.Height) };
+ frameworkElement.Clip = clip;
+
+ return finalSize;
+ }
+ );
+
+ page.NativeControlsAdded = true;
+ }
+ }
+}
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/Package.appxmanifest b/Xamarin.Forms.ControlGallery.WindowsUniversal/Package.appxmanifest
new file mode 100644
index 00000000..b1c816a5
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/Package.appxmanifest
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
+ <Identity Name="0d4424f6-1e29-4476-ac00-ba22c3789cb6" Publisher="CN=xamarin" Version="1.0.0.0" />
+ <mp:PhoneIdentity PhoneProductId="0d4424f6-1e29-4476-ac00-ba22c3789cb6" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
+ <Properties>
+ <DisplayName>Xamarin.Forms.ControlGallery.WindowsUniversal</DisplayName>
+ <PublisherDisplayName>Eric</PublisherDisplayName>
+ <Logo>Assets\StoreLogo.png</Logo>
+ </Properties>
+ <Dependencies>
+ <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
+ </Dependencies>
+ <Resources>
+ <Resource Language="x-generate" />
+ </Resources>
+ <Applications>
+ <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="Xamarin.Forms.ControlGallery.WindowsUniversal.App">
+ <uap:VisualElements DisplayName="Xamarin.Forms.ControlGallery.WindowsUniversal" Square150x150Logo="Assets\Logo.png" Square44x44Logo="Assets\SmallLogo.png" Description="Xamarin.Forms.ControlGallery.WindowsUniversal" BackgroundColor="#464646">
+ <uap:SplashScreen Image="Assets\SplashScreen.png" />
+ </uap:VisualElements>
+ </Application>
+ </Applications>
+ <Capabilities>
+ <Capability Name="internetClient" />
+ <DeviceCapability Name="location" />
+ </Capabilities>
+</Package> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/Properties/AssemblyInfo.cs b/Xamarin.Forms.ControlGallery.WindowsUniversal/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..405b6c6f
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Xamarin.Forms.ControlGallery.WindowsUniversal")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Forms.ControlGallery.WindowsUniversal")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)] \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/Properties/default.rd.xml b/Xamarin.Forms.ControlGallery.WindowsUniversal/Properties/default.rd.xml
new file mode 100644
index 00000000..f1f67899
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/Properties/default.rd.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!-- This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most developers. However, you can modify these parameters to modify the behavior of the .NET Native optimizer. Runtime Directives are documented at http://go.microsoft.com/fwlink/?LinkID=391919 To fully enable reflection for App1.MyClass and all of its public/private members <Type Name="App1.MyClass" Dynamic="Required All"/> To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32 <TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" /> Using the Namespace directive to apply reflection policy to all the types in a particular namespace <Namespace Name="DataClasses.ViewModels" Seralize="All" /> -->
+<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata"><Application>
+<!-- An Assembly element with Name="*Application*" applies to all assemblies in the application package. The asterisks are not wildcards. -->
+<Assembly Dynamic="Required All" Name="Xamarin.Forms.ControlGallery.WindowsUniversal"/>
+<Assembly Dynamic="Required All" Name="*Application*" />
+<!-- Add your application specific runtime directives here. -->
+</Application></Directives> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj b/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj
new file mode 100644
index 00000000..00616897
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{AC257966-9368-478A-9DF4-F0D28E320FE3}</ProjectGuid>
+ <OutputType>AppContainerExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <OutputPath>bin\Debug\</OutputPath>
+ <RootNamespace>Xamarin.Forms.ControlGallery.WindowsUniversal</RootNamespace>
+ <AssemblyName>Xamarin.Forms.ControlGallery.WindowsUniversal</AssemblyName>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
+ <TargetPlatformVersion>10.0.10240.0</TargetPlatformVersion>
+ <TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
+ <MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
+ <EnableDotNetNativeCompatibleProfile>true</EnableDotNetNativeCompatibleProfile>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <PackageCertificateKeyFile>Xamarin.Forms.ControlGallery.WindowsUniversal_TemporaryKey.pfx</PackageCertificateKeyFile>
+ <PackageCertificateThumbprint>F7C761F7D1B63747976309D8A82A7F21D82E8161</PackageCertificateThumbprint>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\ARM\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+ <OutputPath>bin\ARM\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x64\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ <OutputPath>bin\x64\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
+ <ProjectReference Include="..\Xamarin.Forms.Controls\Xamarin.Forms.Controls.csproj">
+ <Project>{cb9c96ce-125c-4a68-b6a1-c3ff1fbf93e1}</Project>
+ <Name>Xamarin.Forms.Controls</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps.UWP\Xamarin.Forms.Maps.UWP.csproj">
+ <Project>{04d89a60-78ef-4a32-ae17-87e47e0233a5}</Project>
+ <Name>Xamarin.Forms.Maps.UWP</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.UAP\Xamarin.Forms.Platform.UAP.csproj">
+ <Project>{00d8d049-ffaa-4759-8fc9-1eca30777f72}</Project>
+ <Name>Xamarin.Forms.Platform.UAP</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="toolbar_close.png" />
+ <None Include="project.json" />
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\bank.png">
+ <Link>bank.png</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\cover1.jpg">
+ <Link>cover1.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\cover1small.jpg">
+ <Link>cover1small.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\crimson.jpg">
+ <Link>crimson.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\crimsonsmall.jpg">
+ <Link>crimsonsmall.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\menuIcon.png">
+ <Link>menuIcon.png</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\oasis.jpg">
+ <Link>oasis.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\oasissmall.jpg">
+ <Link>oasissmall.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\photo.jpg">
+ <Link>photo.jpg</Link>
+ </Content>
+ <Content Include="..\Xamarin.Forms.ControlGallery.WP8\seth.png">
+ <Link>seth.png</Link>
+ </Content>
+ <Content Include="Properties\default.rd.xml" />
+ <Compile Include="..\Xamarin.Forms.ControlGallery.Windows\StringProvider.cs">
+ <Link>StringProvider.cs</Link>
+ </Compile>
+ <Compile Include="App.xaml.cs">
+ <DependentUpon>App.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="BrokenNativeControl.cs" />
+ <Compile Include="MainPage.xaml.cs">
+ <DependentUpon>MainPage.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <AppxManifest Include="Package.appxmanifest">
+ <SubType>Designer</SubType>
+ </AppxManifest>
+ <None Include="Xamarin.Forms.ControlGallery.WindowsUniversal_TemporaryKey.pfx" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="Assets\Logo.scale-100.png" />
+ <Content Include="Assets\SmallLogo.scale-100.png" />
+ <Content Include="Assets\SplashScreen.scale-100.png" />
+ <Content Include="Assets\StoreLogo.scale-100.png" />
+ <Content Include="Assets\WideLogo.scale-100.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <ApplicationDefinition Include="App.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </ApplicationDefinition>
+ <Page Include="MainPage.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ </ItemGroup>
+ <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
+ <VisualStudioVersion>14.0</VisualStudioVersion>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal_TemporaryKey.pfx b/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal_TemporaryKey.pfx
new file mode 100644
index 00000000..ad2edaaa
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal_TemporaryKey.pfx
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/project.json b/Xamarin.Forms.ControlGallery.WindowsUniversal/project.json
new file mode 100644
index 00000000..5cfed231
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/project.json
@@ -0,0 +1,16 @@
+{
+ "dependencies": {
+ "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
+ },
+ "frameworks": {
+ "uap10.0": {}
+ },
+ "runtimes": {
+ "win10-arm": {},
+ "win10-arm-aot": {},
+ "win10-x86": {},
+ "win10-x86-aot": {},
+ "win10-x64": {},
+ "win10-x64-aot": {}
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/toolbar_close.png b/Xamarin.Forms.ControlGallery.WindowsUniversal/toolbar_close.png
new file mode 100644
index 00000000..12f82abb
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/toolbar_close.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs b/Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs
new file mode 100644
index 00000000..8f064d34
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/AppDelegate.cs
@@ -0,0 +1,276 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Runtime.Remoting.Lifetime;
+using System.IO;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+using CoreGraphics;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+using Xamarin.Forms;
+using Xamarin.Forms.ControlGallery.iOS;
+using Xamarin.Forms.Controls;
+using Xamarin.Forms.Maps.iOS;
+using Xamarin.Forms.Platform.iOS;
+
+[assembly: Dependency (typeof (TestCloudService))]
+[assembly: Dependency (typeof (StringProvider))]
+[assembly: Dependency (typeof (CacheService))]
+[assembly: ExportRenderer (typeof (DisposePage), typeof(DisposePageRenderer))]
+[assembly: ExportRenderer (typeof (DisposeLabel), typeof(DisposeLabelRenderer))]
+namespace Xamarin.Forms.ControlGallery.iOS
+{
+ public class CacheService : ICacheService
+ {
+ public void ClearImageCache ()
+ {
+ var documents = Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments);
+ var cache = Path.Combine (documents, ".config", ".isolated-storage", "ImageLoaderCache");
+ foreach (var file in Directory.GetFiles (cache)) {
+ File.Delete (file);
+ }
+ }
+ }
+
+ public class DisposePageRenderer : PageRenderer
+ {
+ protected override void Dispose (bool disposing)
+ {
+ if (disposing) {
+ ((DisposePage) Element).SendRendererDisposed ();
+ }
+ base.Dispose (disposing);
+
+ }
+ }
+
+ public class DisposeLabelRenderer : LabelRenderer
+ {
+ protected override void Dispose (bool disposing)
+ {
+
+ if (disposing) {
+ ((DisposeLabel) Element).SendRendererDisposed ();
+ }
+ base.Dispose (disposing);
+ }
+ }
+
+ public class StringProvider : IStringProvider
+ {
+ public string CoreGalleryTitle {
+ get { return "iOS Core Gallery"; }
+ }
+ }
+
+ public class TestCloudService : ITestCloudService
+ {
+ public bool IsOnTestCloud ()
+ {
+ var isInTestCloud = Environment.GetEnvironmentVariable ("XAMARIN_TEST_CLOUD");
+
+ return isInTestCloud != null && isInTestCloud.Equals("1");
+ }
+
+ public string GetTestCloudDeviceName ()
+ {
+ return Environment.GetEnvironmentVariable ("XTC_DEVICE_NAME");
+ }
+
+ public string GetTestCloudDevice()
+ {
+ return Environment.GetEnvironmentVariable ("XTC_DEVICE");
+ }
+ }
+
+#if PRE_APPLICATION_CLASS
+ [Register ("AppDelegate")]
+ public partial class AppDelegate : UIApplicationDelegate
+ {
+ UIWindow window;
+
+ public override bool FinishedLaunching (UIApplication app, NSDictionary options)
+ {
+ // create a new window instance based on the screen size
+ window = new UIWindow (UIScreen.MainScreen.Bounds);
+
+ UINavigationBar.Appearance.TintColor = Color.Yellow.ToUIColor ();
+ UINavigationBar.Appearance.BarTintColor = Color.Green.ToUIColor ();
+
+ //override navigation bar title with text attributes
+ UINavigationBar.Appearance.SetTitleTextAttributes(new UITextAttributes () {
+ TextColor = Color.Pink.ToUIColor ()
+ });
+
+ Xamarin.Calabash.Start ();
+ Forms.Init ();
+ FormsMaps.Init ();
+ window.RootViewController = FormsApp.GetFormsApp ().CreateViewController ();
+
+ MessagingCenter.Subscribe<RootPagesGallery, Type> (this, Messages.ChangeRoot, (sender, pagetype) => {
+ window = new UIWindow (UIScreen.MainScreen.Bounds);
+ window.RootViewController = ((Page) Activator.CreateInstance(pagetype)).CreateViewController();
+ window.MakeKeyAndVisible ();
+ });
+
+ MessagingCenter.Subscribe<HomeButton> (this, Messages.GoHome, (sender) => {
+ window = new UIWindow (UIScreen.MainScreen.Bounds);
+ window.RootViewController = FormsApp.GetFormsApp ().CreateViewController ();
+ window.MakeKeyAndVisible ();
+ });
+
+ // make the window visible
+ window.MakeKeyAndVisible ();
+
+ return true;
+ }
+ }
+
+#else
+ [Register ("AppDelegate")]
+ public partial class AppDelegate : FormsApplicationDelegate
+ {
+
+ public override bool FinishedLaunching (UIApplication uiApplication, NSDictionary launchOptions)
+ {
+ App.IOSVersion = int.Parse (UIDevice.CurrentDevice.SystemVersion.Substring (0, 1));
+
+ #if !_CLASSIC_
+ Xamarin.Calabash.Start ();
+ #endif
+ Forms.Init ();
+ FormsMaps.Init ();
+ Forms.ViewInitialized += (object sender, ViewInitializedEventArgs e) => {
+ // http://developer.xamarin.com/recipes/testcloud/set-accessibilityidentifier-ios/
+ if (null != e.View.AutomationId && null != e.NativeView) {
+ // e.NativeView.AccessibilityIdentifier = e.View.StyleId;
+ }
+ };
+
+ var app = new App ();
+
+ var mdp = app.MainPage as MasterDetailPage;
+ var detail = mdp?.Detail as NavigationPage;
+ if (detail != null) {
+ detail.Pushed += (sender, args) => {
+ var nncgPage = args.Page as NestedNativeControlGalleryPage;
+
+ if (nncgPage != null) {
+ AddNativeControls (nncgPage);
+ }
+ };
+ }
+
+ LoadApplication (app);
+ return base.FinishedLaunching (uiApplication, launchOptions);
+ }
+
+ void AddNativeControls (NestedNativeControlGalleryPage page)
+ {
+ if (page.NativeControlsAdded) {
+ return;
+ }
+
+ StackLayout sl = page.Layout;
+
+ // Create and add a native UILabel
+ var originalText = "I am a native UILabel";
+ var longerText =
+ "I am a native UILabel with considerably more text. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
+
+ var uilabel = new UILabel {
+ MinimumFontSize = 14f,
+ Text = originalText,
+ Lines = 0,
+ LineBreakMode = UILineBreakMode.WordWrap,
+ Font = UIFont.FromName ("Helvetica", 24f)
+ };
+
+ sl?.Children.Add (uilabel);
+
+ // Create and add a native Button
+ var uibutton = new UIButton (UIButtonType.RoundedRect);
+ uibutton.SetTitle ("Toggle Text Amount", UIControlState.Normal);
+ uibutton.Font = UIFont.FromName ("Helvetica", 14f);
+
+
+ uibutton.TouchUpInside += (sender, args) => {
+ uilabel.Text = uilabel.Text == originalText ? longerText : originalText;
+ uilabel.SizeToFit ();
+ };
+
+ sl?.Children.Add (uibutton.ToView ());
+
+ // Create some control which we know don't behave correctly with regard to measurement
+ var difficultControl0 = new BrokenNativeControl {
+ MinimumFontSize = 14f,
+ Font = UIFont.FromName ("Helvetica", 14f),
+ Lines = 0,
+ LineBreakMode = UILineBreakMode.WordWrap,
+ Text = "Doesn't play nice with sizing. That's why there's a big gap around it."
+ };
+
+ var difficultControl1 = new BrokenNativeControl {
+ MinimumFontSize = 14f,
+ Font = UIFont.FromName ("Helvetica", 14f),
+ Lines = 0,
+ LineBreakMode = UILineBreakMode.WordWrap,
+ Text = "Custom size fix specified. No gaps."
+ };
+
+ var explanation0 = new UILabel {
+ MinimumFontSize = 14f,
+ Text = "The next control is a customized label with a bad SizeThatFits implementation.",
+ Lines = 0,
+ LineBreakMode = UILineBreakMode.WordWrap,
+ Font = UIFont.FromName ("Helvetica", 24f)
+ };
+
+ var explanation1 = new UILabel {
+ MinimumFontSize = 14f,
+ Text = "The next control is the same broken class as above, but we pass in an override to the GetDesiredSize method.",
+ Lines = 0,
+ LineBreakMode = UILineBreakMode.WordWrap,
+ Font = UIFont.FromName ("Helvetica", 24f)
+ };
+
+ // Add a misbehaving control
+ sl?.Children.Add (explanation0);
+ sl?.Children.Add (difficultControl0);
+
+ // Add the misbehaving control with a custom delegate for FixSize
+ sl?.Children.Add (explanation1);
+ sl?.Children.Add (difficultControl1, FixSize);
+
+ page.NativeControlsAdded = true;
+ }
+
+ SizeRequest? FixSize (NativeViewWrapperRenderer renderer, double width, double height)
+ {
+ var uiView = renderer.Control;
+ var view = renderer.Element;
+
+ if (uiView == null || view == null) {
+ return null;
+ }
+
+#if __UNIFIED__
+ var constraint = new CGSize (width, height);
+#else
+ var constraint = new SizeF ((float)width, (float)height);
+#endif
+
+ // Let the BrokenNativeControl determine its size (which we know will be wrong)
+ var badRect = uiView.SizeThatFits (constraint);
+
+ // And we'll use the width (which is fine) and substitute our own height
+ return new SizeRequest (new Size (badRect.Width, 20));
+ }
+ }
+#endif
+}
diff --git a/Xamarin.Forms.ControlGallery.iOS/BrokenNativeControl.cs b/Xamarin.Forms.ControlGallery.iOS/BrokenNativeControl.cs
new file mode 100644
index 00000000..37fe4c5f
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/BrokenNativeControl.cs
@@ -0,0 +1,34 @@
+#if __UNIFIED__
+using CoreGraphics;
+using UIKit;
+#else
+using System.Drawing;
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.ControlGallery.iOS
+{
+ /// <summary>
+ /// This is a custom Android control which deliberately does some incorrect measuring/layout
+ /// </summary>
+ public class BrokenNativeControl : UILabel
+ {
+ public override string Text
+ {
+ get { return base.Text; }
+ set { base.Text = value.ToUpper (); }
+ }
+
+#if __UNIFIED__
+ public override CGSize SizeThatFits (CGSize size)
+ {
+ return new CGSize(size.Width, 150);
+ }
+#else
+ public override SizeF SizeThatFits (SizeF size)
+ {
+ return new SizeF (size.Width, 150);
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.iOS/CustomRenderers.cs b/Xamarin.Forms.ControlGallery.iOS/CustomRenderers.cs
new file mode 100644
index 00000000..a932ead0
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/CustomRenderers.cs
@@ -0,0 +1,415 @@
+using System;
+using Xamarin.Forms.Controls;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.iOS;
+using Xamarin.Forms.ControlGallery.iOS;
+using System.Collections.Generic;
+using System.Linq;
+using System.Drawing;
+
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+using RectangleF=CoreGraphics.CGRect;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+
+[assembly: ExportRenderer (typeof (Bugzilla31395.CustomContentView), typeof (CustomContentRenderer))]
+[assembly: ExportRenderer (typeof (NativeCell), typeof (NativeiOSCellRenderer))]
+[assembly: ExportRenderer (typeof (NativeListView2), typeof (NativeiOSListViewRenderer))]
+[assembly: ExportRenderer (typeof (NativeListView), typeof (NativeListViewRenderer))]
+namespace Xamarin.Forms.ControlGallery.iOS
+{
+ public class NativeiOSCellRenderer : ViewCellRenderer
+ {
+ static NSString s_rid = new NSString("NativeCell");
+
+ public NativeiOSCellRenderer ()
+ {
+ }
+
+ public override UITableViewCell GetCell (Xamarin.Forms.Cell item, UITableViewCell reusableCell, UITableView tv)
+ {
+ var x = (NativeCell)item;
+ Console.WriteLine (x);
+
+ NativeiOSCell c = reusableCell as NativeiOSCell;
+
+ if (c == null) {
+ c = new NativeiOSCell (s_rid);
+ }
+
+ UIImage i = null;
+ if (!string.IsNullOrWhiteSpace (x.ImageFilename)) {
+ i = UIImage.FromFile ("Images/" + x.ImageFilename + ".jpg");
+ }
+
+ base.WireUpForceUpdateSizeRequested (item, c, tv);
+
+ c.UpdateCell (x.Name, x.Category, i);
+
+ return c;
+ }
+ }
+
+
+ /// <summary>
+ /// Sample of a custom cell layout, taken from the iOS docs at
+ /// http://developer.xamarin.com/guides/ios/user_interface/tables/part_3_-_customizing_a_table's_appearance/
+ /// </summary>
+ public class NativeiOSCell : UITableViewCell {
+ UILabel _headingLabel;
+ UILabel _subheadingLabel;
+ UIImageView _imageView;
+
+ public NativeiOSCell (NSString cellId) : base (UITableViewCellStyle.Default, cellId)
+ {
+ SelectionStyle = UITableViewCellSelectionStyle.Gray;
+
+ ContentView.BackgroundColor = UIColor.FromRGB (255,255,224);
+
+ _imageView = new UIImageView();
+
+ _headingLabel = new UILabel () {
+ Font = UIFont.FromName("Cochin-BoldItalic", 22f),
+ TextColor = UIColor.FromRGB (127, 51, 0),
+ BackgroundColor = UIColor.Clear
+ };
+
+ _subheadingLabel = new UILabel () {
+ Font = UIFont.FromName("AmericanTypewriter", 12f),
+ TextColor = UIColor.FromRGB (38, 127, 0),
+ TextAlignment = UITextAlignment.Center,
+ BackgroundColor = UIColor.Clear
+ };
+
+ ContentView.Add (_headingLabel);
+ ContentView.Add (_subheadingLabel);
+ ContentView.Add (_imageView);
+ }
+
+ public void UpdateCell (string caption, string subtitle, UIImage image)
+ {
+ _imageView.Image = image;
+ _headingLabel.Text = caption;
+ _subheadingLabel.Text = subtitle;
+ }
+
+ public override void LayoutSubviews ()
+ {
+ base.LayoutSubviews ();
+
+ _imageView.Frame = new RectangleF(ContentView.Bounds.Width - 63, 5, 33, 33);
+ _headingLabel.Frame = new RectangleF(5, 4, ContentView.Bounds.Width - 63, 25);
+ _subheadingLabel.Frame = new RectangleF(100, 18, 100, 20);
+ }
+ }
+
+ /// <summary>
+ /// Sample of a custom cell layout, taken from the iOS docs at
+ /// http://developer.xamarin.com/guides/ios/user_interface/tables/part_3_-_customizing_a_table's_appearance/
+ /// </summary>
+ public class NativeiOSListViewCell : UITableViewCell {
+ UILabel _headingLabel;
+ UILabel _subheadingLabel;
+ UIImageView _imageView;
+
+ public NativeiOSListViewCell (NSString cellId) : base (UITableViewCellStyle.Default, cellId)
+ {
+ SelectionStyle = UITableViewCellSelectionStyle.Gray;
+
+ ContentView.BackgroundColor = UIColor.FromRGB (218, 255, 127);
+
+ _imageView = new UIImageView();
+
+ _headingLabel = new UILabel () {
+ Font = UIFont.FromName("Cochin-BoldItalic", 22f),
+ TextColor = UIColor.FromRGB (127, 51, 0),
+ BackgroundColor = UIColor.Clear
+ };
+
+ _subheadingLabel = new UILabel () {
+ Font = UIFont.FromName("AmericanTypewriter", 12f),
+ TextColor = UIColor.FromRGB (38, 127, 0),
+ TextAlignment = UITextAlignment.Center,
+ BackgroundColor = UIColor.Clear
+ };
+
+ ContentView.Add (_headingLabel);
+ ContentView.Add (_subheadingLabel);
+ ContentView.Add (_imageView);
+ }
+
+ public void UpdateCell (string caption, string subtitle, UIImage image)
+ {
+ _imageView.Image = image;
+ _headingLabel.Text = caption;
+ _subheadingLabel.Text = subtitle;
+ }
+
+ public override void LayoutSubviews ()
+ {
+ base.LayoutSubviews ();
+
+ _imageView.Frame = new RectangleF(ContentView.Bounds.Width - 63, 5, 33, 33);
+ _headingLabel.Frame = new RectangleF(5, 4, ContentView.Bounds.Width - 63, 25);
+ _subheadingLabel.Frame = new RectangleF(100, 18, 100, 20);
+ }
+ }
+
+ public class NativeiOSListViewRenderer : ViewRenderer<NativeListView2, UITableView>
+ {
+ public NativeiOSListViewRenderer ()
+ {
+ }
+
+ protected override void OnElementChanged (ElementChangedEventArgs<NativeListView2> e)
+ {
+ base.OnElementChanged (e);
+
+ if (Control == null) {
+ SetNativeControl (new UITableView ());
+ }
+
+ if (e.OldElement != null) {
+ // unsubscribe
+ }
+
+ if (e.NewElement != null) {
+ // subscribe
+
+ var s = new NativeiOSListViewSource (e.NewElement);
+ Control.Source = s;
+ }
+ }
+ protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged (sender, e);
+
+ if (e.PropertyName == NativeListView.ItemsProperty.PropertyName) {
+ // update the Items list in the UITableViewSource
+ var s = new NativeiOSListViewSource (Element);
+
+ Control.Source = s;
+ }
+ }
+ public override SizeRequest GetDesiredSize (double widthConstraint, double heightConstraint)
+ {
+ return Control.GetSizeRequest (widthConstraint, heightConstraint, 44, 44);
+ }
+ }
+
+ public class NativeListViewRenderer : ViewRenderer<NativeListView, UITableView>
+ {
+ public NativeListViewRenderer ()
+ {
+ }
+
+ protected override void OnElementChanged (ElementChangedEventArgs<NativeListView> e)
+ {
+ base.OnElementChanged (e);
+
+ if (Control == null) {
+ SetNativeControl (new UITableView ());
+ }
+
+ if (e.OldElement != null) {
+ // unsubscribe
+ }
+
+ if (e.NewElement != null) {
+ // subscribe
+
+ var s = new NativeListViewSource (e.NewElement);
+ Control.Source = s;
+ }
+ }
+ protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged (sender, e);
+
+ if (e.PropertyName == NativeListView.ItemsProperty.PropertyName) {
+ // update the Items list in the UITableViewSource
+ var s = new NativeListViewSource (Element);
+ Control.Source = s;
+ }
+ }
+ public override SizeRequest GetDesiredSize (double widthConstraint, double heightConstraint)
+ {
+ return Control.GetSizeRequest (widthConstraint, heightConstraint, 44, 44);
+ }
+ }
+
+ public class NativeiOSListViewSource : UITableViewSource
+ {
+ // declare vars
+ IList<DataSource> _tableItems;
+ NativeListView2 _listView;
+ readonly NSString _cellIdentifier = new NSString("TableCell");
+
+ public IEnumerable<DataSource> Items {
+ //get{ }
+ set{
+ _tableItems = value.ToList();
+ }
+ }
+
+ public NativeiOSListViewSource (NativeListView2 view)
+ {
+ _tableItems = view.Items.ToList();
+ _listView = view;
+ }
+
+ /// <summary>
+ /// Called by the TableView to determine how many cells to create for that particular section.
+ /// </summary>
+
+ #if __UNIFIED__
+ public override nint RowsInSection (UITableView tableview, nint section)
+ {
+ return _tableItems.Count;
+ }
+ #else
+ public override int RowsInSection (UITableView tableview, int section)
+ {
+ return _tableItems.Count;
+ }
+
+ #endif
+
+
+ #region user interaction methods
+
+ public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
+ {
+ _listView.NotifyItemSelected (_tableItems [indexPath.Row]);
+ Console.WriteLine("Row " + indexPath.Row.ToString() + " selected");
+ tableView.DeselectRow (indexPath, true);
+ }
+
+ public override void RowDeselected (UITableView tableView, NSIndexPath indexPath)
+ {
+ Console.WriteLine("Row " + indexPath.Row.ToString() + " deselected");
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Called by the TableView to get the actual UITableViewCell to render for the particular section and row
+ /// </summary>
+ public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
+ {
+ // request a recycled cell to save memory
+ NativeiOSListViewCell cell = tableView.DequeueReusableCell (_cellIdentifier) as NativeiOSListViewCell;
+
+ // if there are no cells to reuse, create a new one
+ if (cell == null) {
+ cell = new NativeiOSListViewCell (_cellIdentifier);
+ }
+
+ if (string.IsNullOrWhiteSpace (_tableItems [indexPath.Row].ImageFilename)) {
+ cell.UpdateCell (_tableItems [indexPath.Row].Name
+ , _tableItems [indexPath.Row].Category
+ , null);
+ } else {
+ cell.UpdateCell (_tableItems[indexPath.Row].Name
+ , _tableItems[indexPath.Row].Category
+ , UIImage.FromFile ("Images/" +_tableItems[indexPath.Row].ImageFilename + ".jpg") );
+ }
+
+ return cell;
+ }
+ }
+
+ public class NativeListViewSource : UITableViewSource
+ {
+ // declare vars
+ IList<string> _tableItems;
+ string _cellIdentifier = "TableCell";
+ NativeListView _listView;
+
+ public IEnumerable<string> Items {
+ set{
+ _tableItems = value.ToList();
+ }
+ }
+
+ public NativeListViewSource (NativeListView view)
+ {
+ _tableItems = view.Items.ToList ();
+ _listView = view;
+ }
+
+ #if __UNIFIED__
+ public override nint RowsInSection (UITableView tableview, nint section)
+ {
+ return _tableItems.Count;
+ }
+ #else
+ public override int RowsInSection (UITableView tableview, int section)
+ {
+ return _tableItems.Count;
+ }
+ #endif
+ #region user interaction methods
+
+ public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
+ {
+ _listView.NotifyItemSelected (_tableItems [indexPath.Row]);
+
+ Console.WriteLine("Row " + indexPath.Row.ToString() + " selected");
+
+ tableView.DeselectRow (indexPath, true);
+ }
+
+ public override void RowDeselected (UITableView tableView, NSIndexPath indexPath)
+ {
+ Console.WriteLine("Row " + indexPath.Row.ToString() + " deselected");
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Called by the TableView to get the actual UITableViewCell to render for the particular section and row
+ /// </summary>
+ public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
+ {
+ // declare vars
+ UITableViewCell cell = tableView.DequeueReusableCell (_cellIdentifier);
+ //string item = tableItems [indexPath.Row]; //.Items[indexPath.Row];
+
+ // if there are no cells to reuse, create a new one
+ if (cell == null)
+ cell = new UITableViewCell (UITableViewCellStyle.Subtitle, _cellIdentifier);
+
+ // set the item text
+ cell.TextLabel.Text = _tableItems [indexPath.Row];//.Items[indexPath.Row].Heading;
+
+ // if it's a cell style that supports a subheading, set it
+ // if(item.CellStyle == UITableViewCellStyle.Subtitle
+ // || item.CellStyle == UITableViewCellStyle.Value1
+ // || item.CellStyle == UITableViewCellStyle.Value2)
+ // { cell.DetailTextLabel.Text = item.SubHeading; }
+
+ // if the item has a valid image, and it's not the contact style (doesn't support images)
+ // if(!string.IsNullOrEmpty(item.ImageName) && item.CellStyle != UITableViewCellStyle.Value2)
+ // {
+ // if(File.Exists(item.ImageName))
+ // cell.ImageView.Image = UIImage.FromBundle(item.ImageName);
+ // }
+
+ // set the accessory
+ cell.Accessory = UITableViewCellAccessory.DisclosureIndicator;
+
+ return cell;
+ }
+
+ }
+
+ public class CustomContentRenderer : ViewRenderer
+ {
+ }
+}
+
diff --git a/Xamarin.Forms.ControlGallery.iOS/Default-568h@2x.png b/Xamarin.Forms.ControlGallery.iOS/Default-568h@2x.png
new file mode 100644
index 00000000..ea433f8c
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Default-568h@2x.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/Default-667h@2x.png b/Xamarin.Forms.ControlGallery.iOS/Default-667h@2x.png
new file mode 100644
index 00000000..fa609d8f
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Default-667h@2x.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/Default@2x.png b/Xamarin.Forms.ControlGallery.iOS/Default@2x.png
new file mode 100644
index 00000000..619be8a4
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Default@2x.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/Entitlements.plist b/Xamarin.Forms.ControlGallery.iOS/Entitlements.plist
new file mode 100644
index 00000000..0c67376e
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Entitlements.plist
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict/>
+</plist>
diff --git a/Xamarin.Forms.ControlGallery.iOS/Goobuntu-icon.png b/Xamarin.Forms.ControlGallery.iOS/Goobuntu-icon.png
new file mode 100644
index 00000000..b0315d52
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Goobuntu-icon.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/Images/FlowerBuds.jpg b/Xamarin.Forms.ControlGallery.iOS/Images/FlowerBuds.jpg
new file mode 100644
index 00000000..84972501
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Images/FlowerBuds.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/Images/FlowerBuds@2x.jpg b/Xamarin.Forms.ControlGallery.iOS/Images/FlowerBuds@2x.jpg
new file mode 100644
index 00000000..023797cc
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Images/FlowerBuds@2x.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/Images/Fruits.jpg b/Xamarin.Forms.ControlGallery.iOS/Images/Fruits.jpg
new file mode 100644
index 00000000..6fd02226
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Images/Fruits.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/Images/Fruits@2x.jpg b/Xamarin.Forms.ControlGallery.iOS/Images/Fruits@2x.jpg
new file mode 100644
index 00000000..6c4ea3d9
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Images/Fruits@2x.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/Images/Legumes.jpg b/Xamarin.Forms.ControlGallery.iOS/Images/Legumes.jpg
new file mode 100644
index 00000000..d41d4376
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Images/Legumes.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/Images/Legumes@2x.jpg b/Xamarin.Forms.ControlGallery.iOS/Images/Legumes@2x.jpg
new file mode 100644
index 00000000..5f299b41
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Images/Legumes@2x.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/Images/Vegetables.jpg b/Xamarin.Forms.ControlGallery.iOS/Images/Vegetables.jpg
new file mode 100644
index 00000000..8f5572d4
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Images/Vegetables.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/Images/Vegetables@2x.jpg b/Xamarin.Forms.ControlGallery.iOS/Images/Vegetables@2x.jpg
new file mode 100644
index 00000000..297964d7
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Images/Vegetables@2x.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/Info.plist b/Xamarin.Forms.ControlGallery.iOS/Info.plist
new file mode 100644
index 00000000..1d9d4de3
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Info.plist
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>UIDeviceFamily</key>
+ <array>
+ <integer>1</integer>
+ <integer>2</integer>
+ </array>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array/>
+ <key>MinimumOSVersion</key>
+ <string>6.1</string>
+ <key>NSMainNibFile</key>
+ <string></string>
+ <key>CFBundleDisplayName</key>
+ <string>XamControl</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.xamarin.quickui.controlgallery</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>NSMainNibFile~ipad</key>
+ <string></string>
+ <key>CFBundleIconFiles</key>
+ <array>
+ <string>Default@2x.png</string>
+ <string>Default-568h@2x.png</string>
+ </array>
+ <key>UIViewControllerBasedStatusBarAppearance</key>
+ <false/>
+ <key>NSLocationWhenInUseUsageDescription</key>
+ <string>We are using your location</string>
+ <key>NSLocationAlwaysUsageDescription</key>
+ <string>Can we use your location</string>
+ <key>CFBundleShortVersionString</key>
+ <string></string>
+ <key>UILaunchImages</key>
+ <array>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>8.0</string>
+ <key>UILaunchImageName</key>
+ <string>Default-667h</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{375, 667}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>8.0</string>
+ <key>UILaunchImageName</key>
+ <string>Default-736h</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{414, 736}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>7.0</string>
+ <key>UILaunchImageName</key>
+ <string>Default-568h</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{320, 568}</string>
+ </dict>
+ <dict>
+ <key>UILaunchImageMinimumOSVersion</key>
+ <string>6.0</string>
+ <key>UILaunchImageName</key>
+ <string>Default</string>
+ <key>UILaunchImageOrientation</key>
+ <string>Portrait</string>
+ <key>UILaunchImageSize</key>
+ <string>{320, 480}</string>
+
+ </dict>
+ </array>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSAllowsArbitraryLoads </key>
+ <true/>
+ <key>NSExceptionDomains</key>
+ <dict>
+ <key>xamarin.com</key>
+ <dict>
+ <key>NSIncludesSubdomains</key>
+ <true/>
+ <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
+ <true/>
+ <key>NSTemporaryExceptionMinimumTLSVersion</key>
+ <string>TLSv1.1</string>
+ </dict>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/Xamarin.Forms.ControlGallery.iOS/Intranet-icon.png b/Xamarin.Forms.ControlGallery.iOS/Intranet-icon.png
new file mode 100644
index 00000000..fbfe084f
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Intranet-icon.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/Main.cs b/Xamarin.Forms.ControlGallery.iOS/Main.cs
new file mode 100644
index 00000000..cf4bfa12
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Main.cs
@@ -0,0 +1,30 @@
+using System.Diagnostics;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Xamarin.Forms.Controls;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+
+namespace Xamarin.Forms.ControlGallery.iOS
+{
+ public class Application
+ {
+ // This is the main entry point of the application.
+ static void Main (string [] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ #if __UNIFIED__
+ if (!Debugger.IsAttached)
+ Insights.Initialize (App.Secrets["InsightsApiKey"]);
+ #endif
+ UIApplication.Main (args, null, "AppDelegate");
+ }
+ }
+}
diff --git a/Xamarin.Forms.ControlGallery.iOS/Properties/AssemblyInfo.cs b/Xamarin.Forms.ControlGallery.iOS/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..bb8d76cb
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle ("Xamarin.Forms.ControlGallery.iOS")]
+[assembly: AssemblyDescription ("")]
+[assembly: AssemblyConfiguration ("")]
+[assembly: AssemblyCompany ("")]
+[assembly: AssemblyProduct ("Xamarin.Forms.ControlGallery.iOS")]
+[assembly: AssemblyCopyright ("Copyright © 2013")]
+[assembly: AssemblyTrademark ("")]
+[assembly: AssemblyCulture ("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible (false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid ("5098d081-687d-442c-9f92-77fa599779f9")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion ("1.0.0.0")]
+[assembly: AssemblyFileVersion ("1.0.0.0")]
diff --git a/Xamarin.Forms.ControlGallery.iOS/WebImages/XamarinLogo.png b/Xamarin.Forms.ControlGallery.iOS/WebImages/XamarinLogo.png
new file mode 100644
index 00000000..361e2782
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/WebImages/XamarinLogo.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/Xamarin.Forms.ControlGallery.iOS.Classic.csproj b/Xamarin.Forms.ControlGallery.iOS/Xamarin.Forms.ControlGallery.iOS.Classic.csproj
new file mode 100644
index 00000000..cfa3dcaf
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Xamarin.Forms.ControlGallery.iOS.Classic.csproj
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{DEEC5844-D609-4F35-BCF0-5B71C91C8133}</ProjectGuid>
+ <ProjectTypeGuids>{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <OutputType>Exe</OutputType>
+ <RootNamespace>Xamarin.Forms.ControlGallery.iOS</RootNamespace>
+ <IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
+ <AssemblyName>XamarinFormsControlGalleryiOS</AssemblyName>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ <UseMSBuildEngine>True</UseMSBuildEngine>
+ <DefineConstants>_CLASSIC_</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>classic_bin\iPhoneSimulator\Debug\</OutputPath>
+ <BaseIntermediateOutputPath>classic_obj\</BaseIntermediateOutputPath>
+ <DefineConstants>DEBUG;HAVE_OPENTK;_CLASSIC_</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <MtouchLink>SdkOnly</MtouchLink>
+ <MtouchDebug>True</MtouchDebug>
+ <MtouchSdkVersion>6.1</MtouchSdkVersion>
+ <MtouchProfiling>False</MtouchProfiling>
+ <MtouchExtraArgs />
+ <MtouchFastDev>False</MtouchFastDev>
+ <MtouchArch>Default, i386</MtouchArch>
+ <MtouchUseLlvm>False</MtouchUseLlvm>
+ <MtouchUseThumb>False</MtouchUseThumb>
+ <MtouchUseSGen>False</MtouchUseSGen>
+ <MtouchUseRefCounting>False</MtouchUseRefCounting>
+ <MtouchOptimizePNGs>False</MtouchOptimizePNGs>
+ <MtouchSdkVersion>7.0</MtouchSdkVersion>
+ <MtouchEnableGenericValueTypeSharing>True</MtouchEnableGenericValueTypeSharing>
+ <MtouchI18n />
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>classic_bin\iPhoneSimulator\Release</OutputPath>
+ <BaseIntermediateOutputPath>classic_obj\</BaseIntermediateOutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <MtouchLink>None</MtouchLink>
+ <DefineConstants>_CLASSIC_</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>classic_bin\iPhone\Debug</OutputPath>
+ <BaseIntermediateOutputPath>classic_obj\</BaseIntermediateOutputPath>
+ <DefineConstants>DEBUG;__MOBILE__;__IOS__;_CLASSIC_</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <MtouchDebug>True</MtouchDebug>
+ <CodesignKey>iPhone Developer</CodesignKey>
+ <MtouchSdkVersion>8.1</MtouchSdkVersion>
+ <IpaPackageName>
+ </IpaPackageName>
+ <MtouchLink>SdkOnly</MtouchLink>
+ <MtouchProfiling>False</MtouchProfiling>
+ <MtouchExtraArgs />
+ <MtouchFastDev>False</MtouchFastDev>
+ <MtouchEnableGenericValueTypeSharing>True</MtouchEnableGenericValueTypeSharing>
+ <MtouchArch>Default, ARMv7</MtouchArch>
+ <MtouchUseLlvm>False</MtouchUseLlvm>
+ <MtouchUseThumb>False</MtouchUseThumb>
+ <MtouchUseSGen>False</MtouchUseSGen>
+ <MtouchUseRefCounting>False</MtouchUseRefCounting>
+ <MtouchOptimizePNGs>True</MtouchOptimizePNGs>
+ <MtouchI18n />
+ <BuildIpa>true</BuildIpa>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>classic_bin\iPhone\Release</OutputPath>
+ <BaseIntermediateOutputPath>classic_obj\</BaseIntermediateOutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <CodesignKey>iPhone Developer</CodesignKey>
+ <DefineConstants>_CLASSIC_</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Ad-Hoc|iPhone' ">
+ <DebugType>none</DebugType>
+ <Optimize>True</Optimize>
+ <OutputPath>classic_bin\iPhone\Ad-Hoc</OutputPath>
+ <BaseIntermediateOutputPath>classic_obj\</BaseIntermediateOutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>False</ConsolePause>
+ <CodesignKey>iPhone Distribution</CodesignKey>
+ <DefineConstants>_CLASSIC_</DefineConstants>
+ <BuildIpa>True</BuildIpa>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'AppStore|iPhone' ">
+ <DebugType>none</DebugType>
+ <Optimize>True</Optimize>
+ <OutputPath>classic_bin\iPhone\AppStore</OutputPath>
+ <BaseIntermediateOutputPath>classic_obj\</BaseIntermediateOutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>False</ConsolePause>
+ <CodesignKey>iPhone Distribution</CodesignKey>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|iPhoneSimulator'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\iPhoneSimulator\Turkey\</OutputPath>
+ <DefineConstants>__MOBILE__;__IOS__;DEBUG;HAVE_OPENTK;_CLASSIC_</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|iPhone'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\iPhone\Turkey\</OutputPath>
+ <DefineConstants>__MOBILE__;__IOS__;DEBUG;__MOBILE__;__IOS__;_CLASSIC_</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="BrokenNativeControl.cs" />
+ <Compile Include="Main.cs" />
+ <Compile Include="AppDelegate.cs" />
+ <None Include="app.config" />
+ <None Include="Info.plist" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <None Include="packages.config" />
+ <Compile Include="CustomRenderers.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Stubs\Xamarin.Forms.Platform.iOS.Classic\Xamarin.Forms.Platform.iOS.Classic %28Forwarders%29.csproj">
+ <Project>{3e443aef-3ec0-48c4-a524-7c6996339e1b}</Project>
+ <Name>Xamarin.Forms.Platform.iOS.Classic %28Forwarders%29</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Controls\Xamarin.Forms.Controls.csproj">
+ <Project>{cb9c96ce-125c-4a68-b6a1-c3ff1fbf93e1}</Project>
+ <Name>Xamarin.Forms.Controls</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps.iOS\Xamarin.Forms.Maps.iOS.Classic.csproj">
+ <Project>{ca10facd-22ab-463f-a20e-379c212b0858}</Project>
+ <Name>Xamarin.Forms.Maps.iOS.Classic</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7d13bac2-c6a4-416a-b07e-c169b199e52b}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.iOS\Xamarin.Forms.Platform.iOS.Classic.csproj">
+ <Project>{4a47b5df-ddfc-476b-ac41-5105ff3b9b8b}</Project>
+ <Name>Xamarin.Forms.Platform.iOS.Classic</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="bank%402x.png" />
+ <Content Include="bank.png" />
+ <Content Include="calculator%402x.png" />
+ <Content Include="calculator.png" />
+ <Content Include="cover1.jpg" />
+ <Content Include="crimson.jpg" />
+ <Content Include="Default-568h%402x.png" />
+ <BundleResource Include="default.css" />
+ <Content Include="Entitlements.plist" />
+ <Content Include="Goobuntu-icon.png" />
+ <Content Include="Intranet-icon.png" />
+ <BundleResource Include="Default%402x.png" />
+ <BundleResource Include="local.html" />
+ <Content Include="oasis.jpg" />
+ <BundleResource Include="oasissmall.jpg" />
+ <Content Include="coffee%402x.png" />
+ <Content Include="settings%402x.png" />
+ <Content Include="menuIcon%402x.png" />
+ <Content Include="crimsonsmall.jpg" />
+ <Content Include="seth%402x.png" />
+ <Content Include="cover1small.jpg" />
+ <Content Include="menuIcon.png" />
+ <Content Include="seth.png" />
+ <BundleResource Include="photo.jpg" />
+ <BundleResource Include="WebImages\XamarinLogo.png" />
+ <BundleResource Include="Images\FlowerBuds.jpg" />
+ <BundleResource Include="Images\FlowerBuds%402x.jpg" />
+ <BundleResource Include="Images\Fruits.jpg" />
+ <BundleResource Include="Images\Fruits%402x.jpg" />
+ <BundleResource Include="Images\Legumes.jpg" />
+ <BundleResource Include="Images\Legumes%402x.jpg" />
+ <BundleResource Include="Images\Vegetables.jpg" />
+ <BundleResource Include="Images\Vegetables%402x.jpg" />
+ <BundleResource Include="toolbar_close.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Core" />
+ <Reference Include="monotouch" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.MonoTouch.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ </Project>
diff --git a/Xamarin.Forms.ControlGallery.iOS/Xamarin.Forms.ControlGallery.iOS.csproj b/Xamarin.Forms.ControlGallery.iOS/Xamarin.Forms.ControlGallery.iOS.csproj
new file mode 100644
index 00000000..225a3b39
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/Xamarin.Forms.ControlGallery.iOS.csproj
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{C7131F14-274F-4B55-ACA9-E81731AD012F}</ProjectGuid>
+ <ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <OutputType>Exe</OutputType>
+ <RootNamespace>Xamarin.Forms.ControlGallery.iOS</RootNamespace>
+ <IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
+ <AssemblyName>XamarinFormsControlGalleryiOS</AssemblyName>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ <NuGetPackageImportStamp>
+ </NuGetPackageImportStamp>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\iPhoneSimulator\Debug</OutputPath>
+ <DefineConstants>DEBUG</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <MtouchArch>Default, i386, x86_64</MtouchArch>
+ <MtouchLink>SdkOnly</MtouchLink>
+ <MtouchDebug>True</MtouchDebug>
+ <CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
+ <MtouchSdkVersion>7.0</MtouchSdkVersion>
+ <MtouchProfiling>False</MtouchProfiling>
+ <MtouchFastDev>False</MtouchFastDev>
+ <MtouchEnableGenericValueTypeSharing>True</MtouchEnableGenericValueTypeSharing>
+ <MtouchUseLlvm>False</MtouchUseLlvm>
+ <MtouchUseThumb>False</MtouchUseThumb>
+ <MtouchUseSGen>False</MtouchUseSGen>
+ <MtouchUseRefCounting>False</MtouchUseRefCounting>
+ <MtouchOptimizePNGs>False</MtouchOptimizePNGs>
+ <MtouchI18n />
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\iPhoneSimulator\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <MtouchLink>None</MtouchLink>
+ <MtouchArch>i386, x86_64</MtouchArch>
+ <ConsolePause>false</ConsolePause>
+ <CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\iPhone\Debug</OutputPath>
+ <DefineConstants>DEBUG</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <MtouchArch>ARMv7, ARM64</MtouchArch>
+ <CodesignKey>iPhone Developer</CodesignKey>
+ <MtouchDebug>True</MtouchDebug>
+ <CodesignEntitlements>
+ </CodesignEntitlements>
+ <MtouchSdkVersion>8.1</MtouchSdkVersion>
+ <MtouchLink>SdkOnly</MtouchLink>
+ <MtouchProfiling>False</MtouchProfiling>
+ <MtouchExtraArgs />
+ <MtouchFastDev>False</MtouchFastDev>
+ <MtouchEnableGenericValueTypeSharing>True</MtouchEnableGenericValueTypeSharing>
+ <MtouchUseLlvm>False</MtouchUseLlvm>
+ <MtouchUseThumb>False</MtouchUseThumb>
+ <MtouchUseSGen>False</MtouchUseSGen>
+ <MtouchUseRefCounting>False</MtouchUseRefCounting>
+ <MtouchOptimizePNGs>True</MtouchOptimizePNGs>
+ <MtouchI18n />
+ <BuildIpa>True</BuildIpa>
+ <IpaMetadata />
+ <IpaPackageName />
+ <CodesignProvision />
+ <CodesignResourceRules />
+ <CodesignExtraArgs />
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\iPhone\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <MtouchArch>ARMv7, ARM64</MtouchArch>
+ <ConsolePause>false</ConsolePause>
+ <CodesignKey>iPhone Developer</CodesignKey>
+ <CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Ad-Hoc|iPhone' ">
+ <DebugType>none</DebugType>
+ <Optimize>True</Optimize>
+ <OutputPath>bin\iPhone\Ad-Hoc</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>False</ConsolePause>
+ <MtouchArch>ARMv7, ARM64</MtouchArch>
+ <BuildIpa>True</BuildIpa>
+ <CodesignProvision>Automatic:AdHoc</CodesignProvision>
+ <CodesignKey>iPhone Distribution</CodesignKey>
+ <CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'AppStore|iPhone' ">
+ <DebugType>none</DebugType>
+ <Optimize>True</Optimize>
+ <OutputPath>bin\iPhone\AppStore</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>False</ConsolePause>
+ <MtouchArch>ARMv7, ARM64</MtouchArch>
+ <CodesignProvision>Automatic:AppStore</CodesignProvision>
+ <CodesignKey>iPhone Distribution</CodesignKey>
+ <CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|iPhoneSimulator'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\iPhoneSimulator\Turkey\</OutputPath>
+ <DefineConstants>__UNIFIED__;__MOBILE__;__IOS__;DEBUG</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|iPhone'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\iPhone\Turkey\</OutputPath>
+ <DefineConstants>__UNIFIED__;__MOBILE__;__IOS__;DEBUG</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="BrokenNativeControl.cs" />
+ <Compile Include="Main.cs" />
+ <Compile Include="AppDelegate.cs" />
+ <None Include="app.config" />
+ <None Include="Info.plist" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <None Include="packages.config" />
+ <Compile Include="CustomRenderers.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Stubs\Xamarin.Forms.Platform.iOS\Xamarin.Forms.Platform.iOS %28Forwarders%29.csproj">
+ <Project>{39b3457f-01d8-43d0-8e84-d8c4f73cf48d}</Project>
+ <Name>Xamarin.Forms.Platform.iOS %28Forwarders%29</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Controls\Xamarin.Forms.Controls.csproj">
+ <Project>{cb9c96ce-125c-4a68-b6a1-c3ff1fbf93e1}</Project>
+ <Name>Xamarin.Forms.Controls</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps.iOS\Xamarin.Forms.Maps.iOS.csproj">
+ <Project>{aba078c4-f9bb-4924-8b2b-10fe0d2f5491}</Project>
+ <Name>Xamarin.Forms.Maps.iOS</Name>
+ <IsAppExtension>false</IsAppExtension>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7d13bac2-c6a4-416a-b07e-c169b199e52b}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.iOS\Xamarin.Forms.Platform.iOS.csproj">
+ <Project>{271193c1-6e7c-429c-a36d-3f1be5267231}</Project>
+ <Name>Xamarin.Forms.Platform.iOS</Name>
+ <IsAppExtension>false</IsAppExtension>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="bank%402x.png" />
+ <Content Include="bank.png" />
+ <Content Include="calculator%402x.png" />
+ <Content Include="calculator.png" />
+ <Content Include="cover1.jpg" />
+ <Content Include="crimson.jpg" />
+ <Content Include="Default-568h%402x.png" />
+ <BundleResource Include="default.css" />
+ <BundleResource Include="Default-667h%402x.png" />
+ <Content Include="Entitlements.plist">
+ <SubType>Designer</SubType>
+ </Content>
+ <Content Include="Goobuntu-icon.png" />
+ <Content Include="Intranet-icon.png" />
+ <BundleResource Include="Default%402x.png" />
+ <BundleResource Include="local.html" />
+ <Content Include="oasis.jpg" />
+ <BundleResource Include="oasissmall.jpg" />
+ <Content Include="coffee%402x.png" />
+ <Content Include="settings%402x.png" />
+ <Content Include="menuIcon%402x.png" />
+ <Content Include="crimsonsmall.jpg" />
+ <Content Include="seth%402x.png" />
+ <Content Include="cover1small.jpg" />
+ <Content Include="menuIcon.png" />
+ <Content Include="seth.png" />
+ <BundleResource Include="photo.jpg" />
+ <BundleResource Include="WebImages\XamarinLogo.png" />
+ <BundleResource Include="Images\FlowerBuds.jpg" />
+ <BundleResource Include="Images\FlowerBuds%402x.jpg" />
+ <BundleResource Include="Images\Fruits.jpg" />
+ <BundleResource Include="Images\Fruits%402x.jpg" />
+ <BundleResource Include="Images\Legumes.jpg" />
+ <BundleResource Include="Images\Legumes%402x.jpg" />
+ <BundleResource Include="Images\Vegetables.jpg" />
+ <BundleResource Include="Images\Vegetables%402x.jpg" />
+ <BundleResource Include="toolbar_close.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="Calabash, Version=18.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.TestCloud.Agent.0.18.0\lib\Xamarin.iOS10\Calabash.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="PLCrashReporterUnifiedBinding, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.Insights.1.11.4\lib\Xamarin.iOS10\PLCrashReporterUnifiedBinding.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Core" />
+ <Reference Include="Xamarin.Insights, Version=1.11.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.Insights.1.11.4\lib\Xamarin.iOS10\Xamarin.Insights.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.iOS" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+ <Error Condition="!Exists('..\packages\Xamarin.Insights.1.11.4\build\Xamarin.iOS10\Xamarin.Insights.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Insights.1.11.4\build\Xamarin.iOS10\Xamarin.Insights.targets'))" />
+ </Target>
+ <ItemGroup />
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.iOS/app.config b/Xamarin.Forms.ControlGallery.iOS/app.config
new file mode 100644
index 00000000..b1d2a5a3
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/app.config
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="Mono.Cecil" publicKeyToken="0738eb9f132ed756" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-0.9.6.0" newVersion="0.9.6.0" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.iOS/bank.png b/Xamarin.Forms.ControlGallery.iOS/bank.png
new file mode 100644
index 00000000..fbf2947e
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/bank.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/bank@2x.png b/Xamarin.Forms.ControlGallery.iOS/bank@2x.png
new file mode 100644
index 00000000..cf795eae
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/bank@2x.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/calculator.png b/Xamarin.Forms.ControlGallery.iOS/calculator.png
new file mode 100644
index 00000000..339cab59
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/calculator.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/calculator@2x.png b/Xamarin.Forms.ControlGallery.iOS/calculator@2x.png
new file mode 100644
index 00000000..d63d49c2
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/calculator@2x.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/coffee@2x.png b/Xamarin.Forms.ControlGallery.iOS/coffee@2x.png
new file mode 100644
index 00000000..350257c0
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/coffee@2x.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/cover1.jpg b/Xamarin.Forms.ControlGallery.iOS/cover1.jpg
new file mode 100644
index 00000000..f2cea334
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/cover1.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/cover1small.jpg b/Xamarin.Forms.ControlGallery.iOS/cover1small.jpg
new file mode 100644
index 00000000..c820c471
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/cover1small.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/crimson.jpg b/Xamarin.Forms.ControlGallery.iOS/crimson.jpg
new file mode 100644
index 00000000..3db7bb21
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/crimson.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/crimsonsmall.jpg b/Xamarin.Forms.ControlGallery.iOS/crimsonsmall.jpg
new file mode 100644
index 00000000..426c5e07
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/crimsonsmall.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/default.css b/Xamarin.Forms.ControlGallery.iOS/default.css
new file mode 100644
index 00000000..54d8187a
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/default.css
@@ -0,0 +1,2 @@
+html,body{margin:0;padding:10}
+body,p,h1{font-family:Chalkduster; font-size:10;} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.iOS/local.html b/Xamarin.Forms.ControlGallery.iOS/local.html
new file mode 100644
index 00000000..ccc9bec3
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/local.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<link rel="stylesheet" href="default.css">
+</head>
+<body>
+<h1 id="#LocalHtmlPage">Xamarin.Forms</h1>
+<p>This is a local iOS Html page</p>
+<a href="https://www.google.com">Go to Google</a>
+</body>
+</html> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.iOS/menuIcon.png b/Xamarin.Forms.ControlGallery.iOS/menuIcon.png
new file mode 100644
index 00000000..e4d7f9b3
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/menuIcon.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/menuIcon@2x.png b/Xamarin.Forms.ControlGallery.iOS/menuIcon@2x.png
new file mode 100644
index 00000000..0793dc7b
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/menuIcon@2x.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/move_slider_one_right_ios6_iphone.base64 b/Xamarin.Forms.ControlGallery.iOS/move_slider_one_right_ios6_iphone.base64
new file mode 100644
index 00000000..c42b0955
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/move_slider_one_right_ios6_iphone.base64
@@ -0,0 +1,345 @@
+YnBsaXN0MDCvEGAAAQASABwAJQAuADcAQABJAFIAWwBkAG0AdgB/AIgAkQCaAKMA
+rAC1AL4AxwDQANkA4gDrAPQA/QEGAQ8BGAEhASoBMwE8AUUBTgFXAWABaQFyAXsB
+hAGNAZYBnwGoAbEBugHDAcwB1QHeAecB8AH5AgICCwIUAh0CJgIvAjgCQQJKAlMC
+XAJlAm4CdwKAAokCkgKbAqQCrQK2Ar8CyALRAtoC4wLsAvUC/gMHAxADGQMiAysD
+NAM9A0YDTwNYA2HVAAIAAwAEAAUABgAHAAgACQAOABFUVGltZVREYXRhXldpbmRv
+d0xvY2F0aW9uWExvY2F0aW9uVFR5cGUTAAAHWi1xayFPEEABAAAAAQABAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAApCAADCQhozPlsA
+AAAA0gAKAAsADAANUVhRWSNAQUAAAAAAACNAWEAAAAAAANIACgALAA8AECNAQUAA
+AAAAACNAWEAAAAAAABELudUAAgATAAQABQAGABQAFQAWABkAEVREYXRhEwAAB1o9
+C0yXTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAA
+AAAAAKBAAAAOQgAAwkIaMz5bAAAAANIACgALABcAGCNAQcAAAAAAACNAWEAAAAAA
+ANIACgALABoAGyNAQcAAAAAAACNAWEAAAAAAANUAAgATAAQABQAGAB0AHgAfACIA
+ERMAAAdaPwehdE8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB
+AAECAwAAAAAAAACgQAAAEkIAAMJCGjM+WwAAAADSAAoACwAgACEjQEJAAAAAAAAj
+QFhAAAAAAADSAAoACwAjACQjQEJAAAAAAAAjQFhAAAAAAADVAAIAEwAEAAUABgAm
+ACcAKAArABETAAAHWkAP4ExPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAQABAgMAAAAAAAAAoEAAABhCAADCQhozPlsAAAAA0gAKAAsAKQAqI0BD
+AAAAAAAAI0BYQAAAAAAA0gAKAAsALAAtI0BDAAAAAAAAI0BYQAAAAAAA1QACABMA
+BAAFAAYALwAwADEANAAREwAAB1pCDO7hTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAAAoQgAAwkIaMz5bAAAAANIACgAL
+ADIAMyNARQAAAAAAACNAWEAAAAAAANIACgALADUANiNARQAAAAAAACNAWEAAAAAA
+ANUAAgATAAQABQAGADgAOQA6AD0AERMAAAdaRAkmi08QQAIAAAABAAEAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAANEIAAMJCGjM+WwAA
+AADSAAoACwA7ADwjQEaAAAAAAAAjQFhAAAAAAADSAAoACwA+AD8jQEaAAAAAAAAj
+QFhAAAAAAADVAAIAEwAEAAUABgBBAEIAQwBGABETAAAHWkYF4o1PEEACAAAAAQAB
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAADhCAADA
+QhozPlsAAAAA0gAKAAsARABFI0BHAAAAAAAAI0BYAAAAAAAA0gAKAAsARwBII0BH
+AAAAAAAAI0BYAAAAAAAA1QACABMABAAFAAYASgBLAEwATwAREwAAB1pG+fddTxBA
+AgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBA
+AAA6QgAAwEIaMz5bAAAAANIACgALAE0ATiNAR0AAAAAAACNAWAAAAAAAANIACgAL
+AFAAUSNAR0AAAAAAACNAWAAAAAAAANUAAgATAAQABQAGAFMAVABVAFgAERMAAAda
+SAAvhk8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAA
+AAAAAACgQAAAQEIAAMBCGjM+WwAAAADSAAoACwBWAFcjQEgAAAAAAAAjQFgAAAAA
+AADSAAoACwBZAFojQEgAAAAAAAAjQFgAAAAAAADVAAIAEwAEAAUABgBcAF0AXgBh
+ABETAAAHWkj5ZsNPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AQABAgMAAAAAAAAAoEAAAERCAADAQhozPlsAAAAA0gAKAAsAXwBgI0BIgAAAAAAA
+I0BYAAAAAAAA0gAKAAsAYgBjI0BIgAAAAAAAI0BYAAAAAAAA1QACABMABAAFAAYA
+ZQBmAGcAagAREwAAB1pKAkKGTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAEAAQIDAAAAAAAAAKBAAABKQgAAwEIaMz5bAAAAANIACgALAGgAaSNA
+SUAAAAAAACNAWAAAAAAAANIACgALAGsAbCNASUAAAAAAACNAWAAAAAAAANUAAgAT
+AAQABQAGAG4AbwBwAHMAERMAAAdaSv2OjU8QQAIAAAABAAEAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAATEIAAMBCGjM+WwAAAADSAAoA
+CwBxAHIjQEmAAAAAAAAjQFgAAAAAAADSAAoACwB0AHUjQEmAAAAAAAAjQFgAAAAA
+AADVAAIAEwAEAAUABgB3AHgAeQB8ABETAAAHWkz95lFPEEACAAAAAQABAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAFBCAADAQhozPlsA
+AAAA0gAKAAsAegB7I0BKAAAAAAAAI0BYAAAAAAAA0gAKAAsAfQB+I0BKAAAAAAAA
+I0BYAAAAAAAA1QACABMABAAFAAYAgACBAIIAhQAREwAAB1pN97uxTxBAAgAAAAEA
+AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAABUQgAA
+wEIaMz5bAAAAANIACgALAIMAhCNASoAAAAAAACNAWAAAAAAAANIACgALAIYAhyNA
+SoAAAAAAACNAWAAAAAAAANUAAgATAAQABQAGAIkAigCLAI4AERMAAAdaTvMjek8Q
+QAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACg
+QAAAWkIAAMBCGjM+WwAAAADSAAoACwCMAI0jQEtAAAAAAAAjQFgAAAAAAADSAAoA
+CwCPAJAjQEtAAAAAAAAjQFgAAAAAAADVAAIAEwAEAAUABgCSAJMAlACXABETAAAH
+Wk/0pBFPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMA
+AAAAAAAAoEAAAFxCAADAQhozPlsAAAAA0gAKAAsAlQCWI0BLgAAAAAAAI0BYAAAA
+AAAA0gAKAAsAmACZI0BLgAAAAAAAI0BYAAAAAAAA1QACABMABAAFAAYAmwCcAJ0A
+oAAREwAAB1pQ+DMyTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAEAAQIDAAAAAAAAAKBAAABiQgAAwEIaMz5bAAAAANIACgALAJ4AnyNATEAAAAAA
+ACNAWAAAAAAAANIACgALAKEAoiNATEAAAAAAACNAWAAAAAAAANUAAgATAAQABQAG
+AKQApQCmAKkAERMAAAdaUe2xO08QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAABAAECAwAAAAAAAACgQAAAaEIAAMBCGjM+WwAAAADSAAoACwCnAKgj
+QE0AAAAAAAAjQFgAAAAAAADSAAoACwCqAKsjQE0AAAAAAAAjQFgAAAAAAADVAAIA
+EwAEAAUABgCtAK4ArwCyABETAAAHWlL0IohPEEACAAAAAQABAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAG5CAADAQhozPlsAAAAA0gAK
+AAsAsACxI0BNwAAAAAAAI0BYAAAAAAAA0gAKAAsAswC0I0BNwAAAAAAAI0BYAAAA
+AAAA1QACABMABAAFAAYAtgC3ALgAuwAREwAAB1pT7rRyTxBAAgAAAAEAAQAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAAB0QgAAwEIaMz5b
+AAAAANIACgALALkAuiNAToAAAAAAACNAWAAAAAAAANIACgALALwAvSNAToAAAAAA
+ACNAWAAAAAAAANUAAgATAAQABQAGAL8AwADBAMQAERMAAAdaVPQX4U8QQAIAAAAB
+AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAeEIA
+AMBCGjM+WwAAAADSAAoACwDCAMMjQE8AAAAAAAAjQFgAAAAAAADSAAoACwDFAMYj
+QE8AAAAAAAAjQFgAAAAAAADVAAIAEwAEAAUABgDIAMkAygDNABETAAAHWlXsp/hP
+EEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAA
+oEAAAIFCAADAQhozPlsAAAAA0gAKAAsAywDMI0BQIAAAAAAAI0BYAAAAAAAA0gAK
+AAsAzgDPI0BQIAAAAAAAI0BYAAAAAAAA1QACABMABAAFAAYA0QDSANMA1gAREwAA
+B1pW6wTBTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQID
+AAAAAAAAAKBAAACHQgAAv0IaMz5bAAAAANIACgALANQA1SNAUOAAAAAAACNAV+AA
+AAAAANIACgALANcA2CNAUOAAAAAAACNAV+AAAAAAANUAAgATAAQABQAGANoA2wDc
+AN8AERMAAAdaV+whH08QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAABAAECAwAAAAAAAACgQAAAkEIAAL9CGjM+WwAAAADSAAoACwDdAN4jQFIAAAAA
+AAAjQFfgAAAAAADSAAoACwDgAOEjQFIAAAAAAAAjQFfgAAAAAADVAAIAEwAEAAUA
+BgDjAOQA5QDoABETAAAHWljtsG9PEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAJZCAAC/QhozPlsAAAAA0gAKAAsA5gDn
+I0BSwAAAAAAAI0BX4AAAAAAA0gAKAAsA6QDqI0BSwAAAAAAAI0BX4AAAAAAA1QAC
+ABMABAAFAAYA7ADtAO4A8QAREwAAB1pZ7okzTxBAAgAAAAEAAQAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAACZQgAAv0IaMz5bAAAAANIA
+CgALAO8A8CNAUyAAAAAAACNAV+AAAAAAANIACgALAPIA8yNAUyAAAAAAACNAV+AA
+AAAAANUAAgATAAQABQAGAPUA9gD3APoAERMAAAdaWuXLgU8QQAIAAAABAAEAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAnEIAAL9CGjM+
+WwAAAADSAAoACwD4APkjQFOAAAAAAAAjQFfgAAAAAADSAAoACwD7APwjQFOAAAAA
+AAAjQFfgAAAAAADVAAIAEwAEAAUABgD+AP8BAAEDABETAAAHWlvzXedPEEACAAAA
+AQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAJ9C
+AAC/QhozPlsAAAAA0gAKAAsBAQECI0BT4AAAAAAAI0BX4AAAAAAA0gAKAAsBBAEF
+I0BT4AAAAAAAI0BX4AAAAAAA1QACABMABAAFAAYBBwEIAQkBDAAREwAAB1pc6yyE
+TxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAA
+AKBAAAChQgAAv0IaMz5bAAAAANIACgALAQoBCyNAVCAAAAAAACNAV+AAAAAAANIA
+CgALAQ0BDiNAVCAAAAAAACNAV+AAAAAAANUAAgATAAQABQAGARABEQESARUAERMA
+AAdaXeO0BE8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEC
+AwAAAAAAAACgQAAApEIAAL9CGjM+WwAAAADSAAoACwETARQjQFSAAAAAAAAjQFfg
+AAAAAADSAAoACwEWARcjQFSAAAAAAAAjQFfgAAAAAADVAAIAEwAEAAUABgEZARoB
+GwEeABETAAAHWl7pfMRPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAQABAgMAAAAAAAAAoEAAAKhCAAC/QhozPlsAAAAA0gAKAAsBHAEdI0BVAAAA
+AAAAI0BX4AAAAAAA0gAKAAsBHwEgI0BVAAAAAAAAI0BX4AAAAAAA1QACABMABAAF
+AAYBIgEjASQBJwAREwAAB1pf66a6TxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAACuQgAAv0IaMz5bAAAAANIACgALASUB
+JiNAVcAAAAAAACNAV+AAAAAAANIACgALASgBKSNAVcAAAAAAACNAV+AAAAAAANUA
+AgATAAQABQAGASsBLAEtATAAERMAAAdaYOOBS08QQAIAAAABAAEAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAskIAAL9CGjM+WwAAAADS
+AAoACwEuAS8jQFZAAAAAAAAjQFfgAAAAAADSAAoACwExATIjQFZAAAAAAAAjQFfg
+AAAAAADVAAIAEwAEAAUABgE0ATUBNgE5ABETAAAHWmHrOWZPEEACAAAAAQABAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAALhCAAC/Qhoz
+PlsAAAAA0gAKAAsBNwE4I0BXAAAAAAAAI0BX4AAAAAAA0gAKAAsBOgE7I0BXAAAA
+AAAAI0BX4AAAAAAA1QACABMABAAFAAYBPQE+AT8BQgAREwAAB1pi5g04TxBAAgAA
+AAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAADB
+QgAAv0IaMz5bAAAAANIACgALAUABQSNAWCAAAAAAACNAV+AAAAAAANIACgALAUMB
+RCNAWCAAAAAAACNAV+AAAAAAANUAAgATAAQABQAGAUYBRwFIAUsAERMAAAdaY+o3
+nk8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAA
+AACgQAAAykIAAL9CGjM+WwAAAADSAAoACwFJAUojQFlAAAAAAAAjQFfgAAAAAADS
+AAoACwFMAU0jQFlAAAAAAAAjQFfgAAAAAADVAAIAEwAEAAUABgFPAVABUQFUABET
+AAAHWmTggWVPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAB
+AgMAAAAAAAAAoEAAANBCAAC/QhozPlsAAAAA0gAKAAsBUgFTI0BaAAAAAAAAI0BX
+4AAAAAAA0gAKAAsBVQFWI0BaAAAAAAAAI0BX4AAAAAAA1QACABMABAAFAAYBWAFZ
+AVoBXQAREwAAB1pl3GUyTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAEAAQIDAAAAAAAAAKBAAADVQgAAv0IaMz5bAAAAANIACgALAVsBXCNAWqAA
+AAAAACNAV+AAAAAAANIACgALAV4BXyNAWqAAAAAAACNAV+AAAAAAANUAAgATAAQA
+BQAGAWEBYgFjAWYAERMAAAdaZtgm1E8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAA2EIAAL9CGjM+WwAAAADSAAoACwFk
+AWUjQFsAAAAAAAAjQFfgAAAAAADSAAoACwFnAWgjQFsAAAAAAAAjQFfgAAAAAADV
+AAIAEwAEAAUABgFqAWsBbAFvABETAAAHWmfYjdFPEEACAAAAAQABAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAANtCAAC/QhozPlsAAAAA
+0gAKAAsBbQFuI0BbYAAAAAAAI0BX4AAAAAAA0gAKAAsBcAFxI0BbYAAAAAAAI0BX
+4AAAAAAA1QACABMABAAFAAYBcwF0AXUBeAAREwAAB1po3urYTxBAAgAAAAEAAQAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAADeQgAAv0Ia
+Mz5bAAAAANIACgALAXYBdyNAW8AAAAAAACNAV+AAAAAAANIACgALAXkBeiNAW8AA
+AAAAACNAV+AAAAAAANUAAgATAAQABQAGAXwBfQF+AYEAERMAAAdaadwxn08QQAIA
+AAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAA
+40IAAL9CGjM+WwAAAADSAAoACwF/AYAjQFxgAAAAAAAjQFfgAAAAAADSAAoACwGC
+AYMjQFxgAAAAAAAjQFfgAAAAAADVAAIAEwAEAAUABgGFAYYBhwGKABETAAAHWmrd
+X/VPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAA
+AAAAoEAAAOlCAAC/QhozPlsAAAAA0gAKAAsBiAGJI0BdIAAAAAAAI0BX4AAAAAAA
+0gAKAAsBiwGMI0BdIAAAAAAAI0BX4AAAAAAA1QACABMABAAFAAYBjgGPAZABkwAR
+EwAAB1pr14tZTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA
+AQIDAAAAAAAAAKBAAADvQgAAv0IaMz5bAAAAANIACgALAZEBkiNAXeAAAAAAACNA
+V+AAAAAAANIACgALAZQBlSNAXeAAAAAAACNAV+AAAAAAANUAAgATAAQABQAGAZcB
+mAGZAZwAERMAAAdabNMRSE8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAABAAECAwAAAAAAAACgQAAA9UIAAL9CGjM+WwAAAADSAAoACwGaAZsjQF6g
+AAAAAAAjQFfgAAAAAADSAAoACwGdAZ4jQF6gAAAAAAAjQFfgAAAAAADVAAIAEwAE
+AAUABgGgAaEBogGlABETAAAHWm3VWmZPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAPpCAAC/QhozPlsAAAAA0gAKAAsB
+owGkI0BfQAAAAAAAI0BX4AAAAAAA0gAKAAsBpgGnI0BfQAAAAAAAI0BX4AAAAAAA
+1QACABMABAAFAAYBqQGqAasBrgAREwAAB1pu22T5TxBAAgAAAAEAAQAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAAD9QgAAv0IaMz5bAAAA
+ANIACgALAawBrSNAX6AAAAAAACNAV+AAAAAAANIACgALAa8BsCNAX6AAAAAAACNA
+V+AAAAAAANUAAgATAAQABQAGAbIBswG0AbcAERMAAAdab861YE8QQAIAAAABAAEA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAA0MAAL9C
+GjM+WwAAAADSAAoACwG1AbYjQGBgAAAAAAAjQFfgAAAAAADSAAoACwG4AbkjQGBg
+AAAAAAAjQFfgAAAAAADVAAIAEwAEAAUABgG7AbwBvQHAABETAAAHWnDQNe1PEEAC
+AAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAA
+gAhDAAC/QhozPlsAAAAA0gAKAAsBvgG/I0BhEAAAAAAAI0BX4AAAAAAA0gAKAAsB
+wQHCI0BhEAAAAAAAI0BX4AAAAAAA1QACABMABAAFAAYBxAHFAcYByQAREwAAB1px
+zII/TxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAA
+AAAAAKBAAAANQwAAvUIaMz5bAAAAANIACgALAccByCNAYaAAAAAAACNAV6AAAAAA
+ANIACgALAcoByyNAYaAAAAAAACNAV6AAAAAAANUAAgATAAQABQAGAc0BzgHPAdIA
+ERMAAAdacspKDE8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB
+AAECAwAAAAAAAACgQACADkMAAL1CGjM+WwAAAADSAAoACwHQAdEjQGHQAAAAAAAj
+QFegAAAAAADSAAoACwHTAdQjQGHQAAAAAAAjQFegAAAAAADVAAIAEwAEAAUABgHW
+AdcB2AHbABETAAAHWnPMAgBPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAQABAgMAAAAAAAAAoEAAABFDAAC9QhozPlsAAAAA0gAKAAsB2QHaI0Bi
+IAAAAAAAI0BXoAAAAAAA0gAKAAsB3AHdI0BiIAAAAAAAI0BXoAAAAAAA1QACABMA
+BAAFAAYB3wHgAeEB5AAREwAAB1p0xjPNTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAIAVQwAAvUIaMz5bAAAAANIACgAL
+AeIB4yNAYrAAAAAAACNAV6AAAAAAANIACgALAeUB5iNAYrAAAAAAACNAV6AAAAAA
+ANUAAgATAAQABQAGAegB6QHqAe0AERMAAAdadcgO608QQAIAAAABAAEAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAGUMAAL1CGjM+WwAA
+AADSAAoACwHrAewjQGMgAAAAAAAjQFegAAAAAADSAAoACwHuAe8jQGMgAAAAAAAj
+QFegAAAAAADVAAIAEwAEAAUABgHxAfIB8wH2ABETAAAHWnbawvdPEEACAAAAAQAB
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAgB1DAAC9
+QhozPlsAAAAA0gAKAAsB9AH1I0BjsAAAAAAAI0BXoAAAAAAA0gAKAAsB9wH4I0Bj
+sAAAAAAAI0BXoAAAAAAA1QACABMABAAFAAYB+gH7AfwB/wAREwAAB1p4xKe1TxBA
+AgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBA
+AAAkQwAAvUIaMz5bAAAAANIACgALAf0B/iNAZIAAAAAAACNAV6AAAAAAANIACgAL
+AgACASNAZIAAAAAAACNAV6AAAAAAANUAAgATAAQABQAGAgMCBAIFAggAERMAAAda
+ecX9NU8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAA
+AAAAAACgQACAKEMAAL1CGjM+WwAAAADSAAoACwIGAgcjQGUQAAAAAAAjQFegAAAA
+AADSAAoACwIJAgojQGUQAAAAAAAjQFegAAAAAADVAAIAEwAEAAUABgIMAg0CDgIR
+ABETAAAHWnrENIRPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AQABAgMAAAAAAAAAoEAAgC5DAAC9QhozPlsAAAAA0gAKAAsCDwIQI0Bl0AAAAAAA
+I0BXoAAAAAAA0gAKAAsCEgITI0Bl0AAAAAAAI0BXoAAAAAAA1QACABMABAAFAAYC
+FQIWAhcCGgAREwAAB1p7w8aPTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAEAAQIDAAAAAAAAAKBAAAA0QwAAvUIaMz5bAAAAANIACgALAhgCGSNA
+ZoAAAAAAACNAV6AAAAAAANIACgALAhsCHCNAZoAAAAAAACNAV6AAAAAAANUAAgAT
+AAQABQAGAh4CHwIgAiMAERMAAAdafMRmzE8QQAIAAAABAAEAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQACAOUMAAL1CGjM+WwAAAADSAAoA
+CwIhAiIjQGcwAAAAAAAjQFegAAAAAADSAAoACwIkAiUjQGcwAAAAAAAjQFegAAAA
+AADVAAIAEwAEAAUABgInAigCKQIsABETAAAHWn3DHSdPEEACAAAAAQABAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAgDxDAAC9QhozPlsA
+AAAA0gAKAAsCKgIrI0BnkAAAAAAAI0BXoAAAAAAA0gAKAAsCLQIuI0BnkAAAAAAA
+I0BXoAAAAAAA1QACABMABAAFAAYCMAIxAjICNQAREwAAB1p+vcFETxBAAgAAAAEA
+AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAABBQwAA
+vUIaMz5bAAAAANIACgALAjMCNCNAaCAAAAAAACNAV6AAAAAAANIACgALAjYCNyNA
+aCAAAAAAACNAV6AAAAAAANUAAgATAAQABQAGAjkCOgI7Aj4AERMAAAdaf8OUOE8Q
+QAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACg
+QACAQ0MAAL1CGjM+WwAAAADSAAoACwI8Aj0jQGhwAAAAAAAjQFegAAAAAADSAAoA
+CwI/AkAjQGhwAAAAAAAjQFegAAAAAADVAAIAEwAEAAUABgJCAkMCRAJHABETAAAH
+WoDBMUtPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMA
+AAAAAAAAoEAAgEZDAAC9QhozPlsAAAAA0gAKAAsCRQJGI0Bo0AAAAAAAI0BXoAAA
+AAAA0gAKAAsCSAJJI0Bo0AAAAAAAI0BXoAAAAAAA1QACABMABAAFAAYCSwJMAk0C
+UAAREwAAB1qBvf1UTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAEAAQIDAAAAAAAAAKBAAABLQwAAvUIaMz5bAAAAANIACgALAk4CTyNAaWAAAAAA
+ACNAV6AAAAAAANIACgALAlECUiNAaWAAAAAAACNAV6AAAAAAANUAAgATAAQABQAG
+AlQCVQJWAlkAERMAAAdagsJMmE8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAABAAECAwAAAAAAAACgQAAATkMAAL1CGjM+WwAAAADSAAoACwJXAlgj
+QGnAAAAAAAAjQFegAAAAAADSAAoACwJaAlsjQGnAAAAAAAAjQFegAAAAAADVAAIA
+EwAEAAUABgJdAl4CXwJiABETAAAHWoO6hJlPEEACAAAAAQABAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAgE9DAAC9QhozPlsAAAAA0gAK
+AAsCYAJhI0Bp8AAAAAAAI0BXoAAAAAAA0gAKAAsCYwJkI0Bp8AAAAAAAI0BXoAAA
+AAAA1QACABMABAAFAAYCZgJnAmgCawAREwAAB1qEv3VXTxBAAgAAAAEAAQAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAIBSQwAAvEIaMz5b
+AAAAANIACgALAmkCaiNAalAAAAAAACNAV4AAAAAAANIACgALAmwCbSNAalAAAAAA
+ACNAV4AAAAAAANUAAgATAAQABQAGAm8CcAJxAnQAERMAAAdahcDge08QQAIAAAAB
+AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAVUMA
+ALxCGjM+WwAAAADSAAoACwJyAnMjQGqgAAAAAAAjQFeAAAAAAADSAAoACwJ1AnYj
+QGqgAAAAAAAjQFeAAAAAAADVAAIAEwAEAAUABgJ4AnkCegJ9ABETAAAHWoa4i/NP
+EEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAA
+oEAAgFZDAAC8QhozPlsAAAAA0gAKAAsCewJ8I0Bq0AAAAAAAI0BXgAAAAAAA0gAK
+AAsCfgJ/I0Bq0AAAAAAAI0BXgAAAAAAA1QACABMABAAFAAYCgQKCAoMChgAREwAA
+B1qHu8y9TxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQID
+AAAAAAAAAKBAAABYQwAAvEIaMz5bAAAAANIACgALAoQChSNAawAAAAAAACNAV4AA
+AAAAANIACgALAocCiCNAawAAAAAAACNAV4AAAAAAANUAAgATAAQABQAGAooCiwKM
+Ao8AERMAAAdaiLLbg08QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAABAAECAwAAAAAAAACgQACAWkMAALxCGjM+WwAAAADSAAoACwKNAo4jQGtQAAAA
+AAAjQFeAAAAAAADSAAoACwKQApEjQGtQAAAAAAAjQFeAAAAAAADVAAIAEwAEAAUA
+BgKTApQClQKYABETAAAHWom5Rd9PEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAgF1DAAC8QhozPlsAAAAA0gAKAAsClgKX
+I0BrsAAAAAAAI0BXgAAAAAAA0gAKAAsCmQKaI0BrsAAAAAAAI0BXgAAAAAAA1QAC
+ABMABAAFAAYCnAKdAp4CoQAREwAAB1qKsJhTTxBAAgAAAAEAAQAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAABfQwAAvEIaMz5bAAAAANIA
+CgALAp8CoCNAa+AAAAAAACNAV4AAAAAAANIACgALAqICoyNAa+AAAAAAACNAV4AA
+AAAAANUAAgATAAQABQAGAqUCpgKnAqoAERMAAAdai664xk8QQAIAAAABAAEAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQACAYEMAALxCGjM+
+WwAAAADSAAoACwKoAqkjQGwQAAAAAAAjQFeAAAAAAADSAAoACwKrAqwjQGwQAAAA
+AAAjQFeAAAAAAADVAAIAEwAEAAUABgKuAq8CsAKzABETAAAHWoy0hO5PEEACAAAA
+AQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAGJD
+AAC8QhozPlsAAAAA0gAKAAsCsQKyI0BsQAAAAAAAI0BXgAAAAAAA0gAKAAsCtAK1
+I0BsQAAAAAAAI0BXgAAAAAAA1QACABMABAAFAAYCtwK4ArkCvAAREwAAB1qNtPE9
+TxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAA
+AKBAAIBjQwAAvEIaMz5bAAAAANIACgALAroCuyNAbHAAAAAAACNAV4AAAAAAANIA
+CgALAr0CviNAbHAAAAAAACNAV4AAAAAAANUAAgATAAQABQAGAsACwQLCAsUAERMA
+AAdajrTi1E8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEC
+AwAAAAAAAACgQACAZUMAALxCGjM+WwAAAADSAAoACwLDAsQjQGywAAAAAAAjQFeA
+AAAAAADSAAoACwLGAscjQGywAAAAAAAjQFeAAAAAAADVAAIAEwAEAAUABgLJAsoC
+ywLOABETAAAHWo+rCk1PEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAQABAgMAAAAAAAAAoEAAgGhDAAC8QhozPlsAAAAA0gAKAAsCzALNI0BtEAAA
+AAAAI0BXgAAAAAAA0gAKAAsCzwLQI0BtEAAAAAAAI0BXgAAAAAAA1QACABMABAAF
+AAYC0gLTAtQC1wAREwAAB1qQrrC3TxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAABqQwAAvEIaMz5bAAAAANIACgALAtUC
+1iNAbUAAAAAAACNAV4AAAAAAANIACgALAtgC2SNAbUAAAAAAACNAV4AAAAAAANUA
+AgATAAQABQAGAtsC3ALdAuAAERMAAAdakap6hU8QQAIAAAABAAEAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAbUMAALxCGjM+WwAAAADS
+AAoACwLeAt8jQG2gAAAAAAAjQFeAAAAAAADSAAoACwLhAuIjQG2gAAAAAAAjQFeA
+AAAAAADVAAIAEwAEAAUABgLkAuUC5gLpABETAAAHWpKuQ2hPEEACAAAAAQABAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAG9DAAC8Qhoz
+PlsAAAAA0gAKAAsC5wLoI0Bt4AAAAAAAI0BXgAAAAAAA0gAKAAsC6gLrI0Bt4AAA
+AAAAI0BXgAAAAAAA1QACABMABAAFAAYC7QLuAu8C8gAREwAAB1qTqpD8TxBAAgAA
+AAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAABy
+QwAAvEIaMz5bAAAAANIACgALAvAC8SNAbkAAAAAAACNAV4AAAAAAANIACgALAvMC
+9CNAbkAAAAAAACNAV4AAAAAAANUAAgATAAQABQAGAvYC9wL4AvsAERMAAAdalKay
+VE8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAA
+AACgQACAc0MAALxCGjM+WwAAAADSAAoACwL5AvojQG5wAAAAAAAjQFeAAAAAAADS
+AAoACwL8Av0jQG5wAAAAAAAjQFeAAAAAAADVAAIAEwAEAAUABgL/AwADAQMEABET
+AAAHWpWqwh9PEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAB
+AgMAAAAAAAAAoEAAAHVDAAC8QhozPlsAAAAA0gAKAAsDAgMDI0BuoAAAAAAAI0BX
+gAAAAAAA0gAKAAsDBQMGI0BuoAAAAAAAI0BXgAAAAAAA1QACABMABAAFAAYDCAMJ
+AwoDDQAREwAAB1qWpDgFTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAEAAQIDAAAAAAAAAKBAAIB3QwAAvEIaMz5bAAAAANIACgALAwsDDCNAbvAA
+AAAAACNAV4AAAAAAANIACgALAw4DDyNAbvAAAAAAACNAV4AAAAAAANUAAgATAAQA
+BQAGAxEDEgMTAxYAERMAAAdal6sly08QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAeUMAALxCGjM+WwAAAADSAAoACwMU
+AxUjQG8gAAAAAAAjQFeAAAAAAADSAAoACwMXAxgjQG8gAAAAAAAjQFeAAAAAAADV
+AAIAEwAEAAUABgMaAxsDHAMfABETAAAHWpip5X9PEEACAAAAAQABAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAgHxDAAC8QhozPlsAAAAA
+0gAKAAsDHQMeI0BvkAAAAAAAI0BXgAAAAAAA0gAKAAsDIAMhI0BvkAAAAAAAI0BX
+gAAAAAAA1QACABMABAAFAAYDIwMkAyUDKAAREwAAB1qZr5LYTxBAAgAAAAEAAQAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAAB+QwAAvEIa
+Mz5bAAAAANIACgALAyYDJyNAb8AAAAAAACNAV4AAAAAAANIACgALAykDKiNAb8AA
+AAAAACNAV4AAAAAAANUAAgATAAQABQAGAywDLQMuAzEAERMAAAdamqeZtk8QQAIA
+AAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQABA
+gEMAALxCGjM+WwAAAADSAAoACwMvAzAjQHAIAAAAAAAjQFeAAAAAAADSAAoACwMy
+AzMjQHAIAAAAAAAjQFeAAAAAAADVAAIAEwAEAAUABgM1AzYDNwM6ABETAAAHWpun
+hTZPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAA
+AAAAoEAAAIFDAAC8QhozPlsAAAAA0gAKAAsDOAM5I0BwIAAAAAAAI0BXgAAAAAAA
+0gAKAAsDOwM8I0BwIAAAAAAAI0BXgAAAAAAA1QACABMABAAFAAYDPgM/A0ADQwAR
+EwAAB1qcpJ1xTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA
+AQIDAAAAAAAAAKBAAMCBQwAAvEIaMz5bAAAAANIACgALA0EDQiNAcDgAAAAAACNA
+V4AAAAAAANIACgALA0QDRSNAcDgAAAAAACNAV4AAAAAAANUAAgATAAQABQAGA0cD
+SANJA0wAERMAAAdanaBddU8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAABAAECAwAAAAAAAACgQABAgkMAALxCGjM+WwAAAADSAAoACwNKA0sjQHBI
+AAAAAAAjQFeAAAAAAADSAAoACwNNA04jQHBIAAAAAAAjQFeAAAAAAADVAAIAEwAE
+AAUABgNQA1EDUgNVABETAAAHWp6hXSNPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAINDAAC8QhozPlsAAAAA0gAKAAsD
+UwNUI0BwYAAAAAAAI0BXgAAAAAAA0gAKAAsDVgNXI0BwYAAAAAAAI0BXgAAAAAAA
+1QACABMABAAFAAYDWQNaA1sDXgAREwAAB1qgnt1TTxBAAgAAAAEAAQAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAICDQwAAvEIaMz5bAAAA
+ANIACgALA1wDXSNAcHAAAAAAACNAV4AAAAAAANIACgALA18DYCNAcHAAAAAAACNA
+V4AAAAAAANUAAgATAAQABQAGA2IDYwNkA2cAERMAAAdaq6c4V08QQAYAAAABAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAAAAAAAAAACgQACAg0MAALxC
+GjM+WwAAAADSAAoACwNlA2YjQHBwAAAAAAAjQFeAAAAAAADSAAoACwNoA2kjQHBw
+AAAAAAAjQFeAAAAAAAAACADLAOAA5QDqAPkBAgEHARABUwFcAV4BYAFpAXIBewGE
+AY0BkAGlAaoBswH2Af8CCAIRAhoCIwIsAkECSgKNApYCnwKoArECugLDAtgC4QMk
+Ay0DNgM/A0gDUQNaA28DeAO7A8QDzQPWA98D6APxBAYEDwRSBFsEZARtBHYEfwSI
+BJ0EpgTpBPIE+wUEBQ0FFgUfBTQFPQWABYkFkgWbBaQFrQW2BcsF1AYXBiAGKQYy
+BjsGRAZNBmIGawauBrcGwAbJBtIG2wbkBvkHAgdFB04HVwdgB2kHcgd7B5AHmQfc
+B+UH7gf3CAAICQgSCCcIMAhzCHwIhQiOCJcIoAipCL4IxwkKCRMJHAklCS4JNwlA
+CVUJXgmhCaoJswm8CcUJzgnXCewJ9Qo4CkEKSgpTClwKZQpuCoMKjArPCtgK4Qrq
+CvMK/AsFCxoLIwtmC28LeAuBC4oLkwucC7ELugv9DAYMDwwYDCEMKgwzDEgMUQyU
+DJ0MpgyvDLgMwQzKDN8M6A0rDTQNPQ1GDU8NWA1hDXYNfw3CDcsN1A3dDeYN7w34
+Dg0OFg5ZDmIOaw50Dn0Ohg6PDqQOrQ7wDvkPAg8LDxQPHQ8mDzsPRA+HD5APmQ+i
+D6sPtA+9D9IP2xAeECcQMBA5EEIQSxBUEGkQchC1EL4QxxDQENkQ4hDrEQARCRFM
+EVURXhFnEXAReRGCEZcRoBHjEewR9RH+EgcSEBIZEi4SNxJ6EoMSjBKVEp4SpxKw
+EsUSzhMRExoTIxMsEzUTPhNHE1wTZROoE7ETuhPDE8wT1RPeE/MT/BQ/FEgUURRa
+FGMUbBR1FIoUkxTWFN8U6BTxFPoVAxUMFSEVKhVtFXYVfxWIFZEVmhWjFbgVwRYE
+Fg0WFhYfFigWMRY6Fk8WWBabFqQWrRa2Fr8WyBbRFuYW7xcyFzsXRBdNF1YXXxdo
+F30XhhfJF9IX2xfkF+0X9hf/GBQYHRhgGGkYchh7GIQYjRiWGKsYtBj3GQAZCRkS
+GRsZJBktGUIZSxmOGZcZoBmpGbIZuxnEGdkZ4holGi4aNxpAGkkaUhpbGnAaeRq8
+GsUazhrXGuAa6RryGwcbEBtTG1wbZRtuG3cbgBuJG54bpxvqG/Mb/BwFHA4cFxwg
+HDUcPhyBHIockxycHKUcrhy3HMwc1R0YHSEdKh0zHTwdRR1OHWMdbB2vHbgdwR3K
+HdMd3B3lHfoeAx5GHk8eWB5hHmoecx58HpEemh7dHuYe7x74HwEfCh8THygfMR90
+H30fhh+PH5gfoR+qH78fyCALIBQgHSAmIC8gOCBBIFYgXyCiIKsgtCC9IMYgzyDY
+IO0g9iE5IUIhSyFUIV0hZiFvIYQhjSHQIdkh4iHrIfQh/SIGIhsiJCJnInAieSKC
+IosilCKdIrIiuyL+IwcjECMZIyIjKyM0I0kjUiOVI54jpyOwI7kjwiPLI+Aj6SQs
+JDUkPiRHJFAkWSRiJHckgCTDJMwk1STeJOck8CT5JQ4lFyVaJWMlbCV1JX4lhyWQ
+JaUlriXxJfomAyYMJhUmHiYnJjwmRSaIJpEmmiajJqwmtSa+JtMm3CcfJygnMSc6
+J0MnTCdVJ2oncye2J78nyCfRJ9on4yfsKAEoCihNKFYoXyhoKHEoeiiDKJgooSjk
+KO0o9ij/KQgpESkaKS8pOCl7KYQpjSmWKZ8pqCmxKcYpzyoSKhsqJCotKjYqPypI
+Kl0qZiqpKrIquyrEKs0q1irfKvQq/StAK0krUitbK2QrbSt2K4srlCvXK+Ar6Svy
+K/ssBCwNLCIsKyxuLHcsgCyJLJIsmyykLLkswi0FLQ4tFy0gLSktMi07LVAtWS2c
+LaUtri23LcAtyS3SLect8C4zLjwuRS5OLlcuYC5pLn4uhy7KLtMu3C7lLu4u9y8A
+LxUvHi9hL2ovcy98L4Uvji+XL6wvtS/4MAEwCjATMBwwJTAuMEMwTDCPMJgwoTCq
+MLMwvDDFMNow4zEmMS8xODFBMUoxUzFcMXExejG9McYxzzHYMeEx6jHzMggyETJU
+Ml0yZjJvMngygTKKMp8yqDLrMvQy/TMGMw8zGDMhMzYzPzOCM4szlDOdM6YzrzO4
+M80z1jQZNCI0KzQ0ND00RjRPNGQ0bTSwNLk0wjTLNNQ03TTmNPs1BDVHNVA1WTVi
+NWs1dDV9NZI1mzXeNec18DX5NgI2CzYUNik2MjZ1Nn42hzaQNpk2ojarNsA2yTcM
+NxU3HjcnNzA3OTdCN1c3YDejN6w3tTe+N8c30DfZN+439zg6OEM4TDhVOF44Zzhw
+OIU4jjjRONo44zjsOPU4/jkHORw5JTloOXE5ejmDOYw5lQAAAAAAAAICAAAAAAAA
+A2oAAAAAAAAAAAAAAAAAADme
diff --git a/Xamarin.Forms.ControlGallery.iOS/move_slider_three_right_ios6_iphone.base64 b/Xamarin.Forms.ControlGallery.iOS/move_slider_three_right_ios6_iphone.base64
new file mode 100644
index 00000000..7c2216b1
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/move_slider_three_right_ios6_iphone.base64
@@ -0,0 +1,284 @@
+YnBsaXN0MDCvEE8AAQASABwAJQAuADcAQABJAFIAWwBkAG0AdgB/AIgAkQCaAKMA
+rAC1AL4AxwDQANkA4gDrAPQA/QEGAQ8BGAEhASoBMwE8AUUBTgFXAWABaQFyAXsB
+hAGNAZYBnwGoAbEBugHDAcwB1QHeAecB8AH5AgICCwIUAh0CJgIvAjgCQQJKAlMC
+XAJlAm4CdwKAAokCkgKbAqQCrQK2Ar8CyNUAAgADAAQABQAGAAcACAAJAA4AEVRU
+aW1lVERhdGFeV2luZG93TG9jYXRpb25YTG9jYXRpb25UVHlwZRMAAAdq4xBdV08Q
+QAEAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACg
+QAAAFEIAABtDGjM+WwAAAADSAAoACwAMAA1RWFFZI0BCgAAAAAAAI0BjYAAAAAAA
+0gAKAAsADwAQI0BCgAAAAAAAI0BjYAAAAAAAEQu51QACABMABAAFAAYAFAAVABYA
+GQARVERhdGETAAAHau5p0LFPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAQABAgMAAAAAAAAAoEAAABhCAAAbQxozPlsAAAAA0gAKAAsAFwAYI0BD
+AAAAAAAAI0BjYAAAAAAA0gAKAAsAGgAbI0BDAAAAAAAAI0BjYAAAAAAA1QACABMA
+BAAFAAYAHQAeAB8AIgAREwAAB2rvZUmGTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAAAeQgAAG0MaMz5bAAAAANIACgAL
+ACAAISNAQ8AAAAAAACNAY2AAAAAAANIACgALACMAJCNAQ8AAAAAAACNAY2AAAAAA
+ANUAAgATAAQABQAGACYAJwAoACsAERMAAAdq8WjXBk8QQAIAAAABAAEAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAJEIAABtDGjM+WwAA
+AADSAAoACwApACojQESAAAAAAAAjQGNgAAAAAADSAAoACwAsAC0jQESAAAAAAAAj
+QGNgAAAAAADVAAIAEwAEAAUABgAvADAAMQA0ABETAAAHavJmzRRPEEACAAAAAQAB
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAACpCAAAb
+QxozPlsAAAAA0gAKAAsAMgAzI0BFQAAAAAAAI0BjYAAAAAAA0gAKAAsANQA2I0BF
+QAAAAAAAI0BjYAAAAAAA1QACABMABAAFAAYAOAA5ADoAPQAREwAAB2rzZA1PTxBA
+AgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBA
+AAAwQgAAG0MaMz5bAAAAANIACgALADsAPCNARgAAAAAAACNAY2AAAAAAANIACgAL
+AD4APyNARgAAAAAAACNAY2AAAAAAANUAAgATAAQABQAGAEEAQgBDAEYAERMAAAdq
+9F978E8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAA
+AAAAAACgQAAAOkIAABpDGjM+WwAAAADSAAoACwBEAEUjQEdAAAAAAAAjQGNAAAAA
+AADSAAoACwBHAEgjQEdAAAAAAAAjQGNAAAAAAADVAAIAEwAEAAUABgBKAEsATABP
+ABETAAAHavVlCG9PEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AQABAgMAAAAAAAAAoEAAAExCAAAaQxozPlsAAAAA0gAKAAsATQBOI0BJgAAAAAAA
+I0BjQAAAAAAA0gAKAAsAUABRI0BJgAAAAAAAI0BjQAAAAAAA1QACABMABAAFAAYA
+UwBUAFUAWAAREwAAB2r2X/8RTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAEAAQIDAAAAAAAAAKBAAABaQgAAGkMaMz5bAAAAANIACgALAFYAVyNA
+S0AAAAAAACNAY0AAAAAAANIACgALAFkAWiNAS0AAAAAAACNAY0AAAAAAANUAAgAT
+AAQABQAGAFwAXQBeAGEAERMAAAdq91xT3E8QQAIAAAABAAEAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAiEIAABpDGjM+WwAAAADSAAoA
+CwBfAGAjQFEAAAAAAAAjQGNAAAAAAADSAAoACwBiAGMjQFEAAAAAAAAjQGNAAAAA
+AADVAAIAEwAEAAUABgBlAGYAZwBqABETAAAHavhfDLRPEEACAAAAAQABAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAKRCAIAZQxozPlsA
+AAAA0gAKAAsAaABpI0BUgAAAAAAAI0BjMAAAAAAA0gAKAAsAawBsI0BUgAAAAAAA
+I0BjMAAAAAAA1QACABMABAAFAAYAbgBvAHAAcwAREwAAB2r5XqClTxBAAgAAAAEA
+AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAAC/QgCA
+GUMaMz5bAAAAANIACgALAHEAciNAV+AAAAAAACNAYzAAAAAAANIACgALAHQAdSNA
+V+AAAAAAACNAYzAAAAAAANUAAgATAAQABQAGAHcAeAB5AHwAERMAAAdq+l7J7U8Q
+QAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACg
+QAAA4kIAgBhDGjM+WwAAAADSAAoACwB6AHsjQFxAAAAAAAAjQGMQAAAAAADSAAoA
+CwB9AH4jQFxAAAAAAAAjQGMQAAAAAADVAAIAEwAEAAUABgCAAIEAggCFABETAAAH
+avtdmM1PEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMA
+AAAAAAAAoEAAAP1CAIAYQxozPlsAAAAA0gAKAAsAgwCEI0BfoAAAAAAAI0BjEAAA
+AAAA0gAKAAsAhgCHI0BfoAAAAAAAI0BjEAAAAAAA1QACABMABAAFAAYAiQCKAIsA
+jgAREwAAB2r8XUpkTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAEAAQIDAAAAAAAAAKBAAAAFQwAAGEMaMz5bAAAAANIACgALAIwAjSNAYKAAAAAA
+ACNAYwAAAAAAANIACgALAI8AkCNAYKAAAAAAACNAYwAAAAAAANUAAgATAAQABQAG
+AJIAkwCUAJcAERMAAAdq/VxOLk8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAABAAECAwAAAAAAAACgQACACUMAABhDGjM+WwAAAADSAAoACwCVAJYj
+QGEwAAAAAAAjQGMAAAAAAADSAAoACwCYAJkjQGEwAAAAAAAjQGMAAAAAAADVAAIA
+EwAEAAUABgCbAJwAnQCgABETAAAHav5bAdFPEEACAAAAAQABAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAgAxDAAAYQxozPlsAAAAA0gAK
+AAsAngCfI0BhkAAAAAAAI0BjAAAAAAAA0gAKAAsAoQCiI0BhkAAAAAAAI0BjAAAA
+AAAA1QACABMABAAFAAYApAClAKYAqQAREwAAB2r/WYrITxBAAgAAAAEAAQAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAIAPQwAAGEMaMz5b
+AAAAANIACgALAKcAqCNAYfAAAAAAACNAYwAAAAAAANIACgALAKoAqyNAYfAAAAAA
+ACNAYwAAAAAAANUAAgATAAQABQAGAK0ArgCvALIAERMAAAdrAGJOeE8QQAIAAAAB
+AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAEUMA
+ABhDGjM+WwAAAADSAAoACwCwALEjQGIgAAAAAAAjQGMAAAAAAADSAAoACwCzALQj
+QGIgAAAAAAAjQGMAAAAAAADVAAIAEwAEAAUABgC2ALcAuAC7ABETAAAHawFYwudP
+EEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAA
+oEAAgBJDAIAWQxozPlsAAAAA0gAKAAsAuQC6I0BiUAAAAAAAI0Bi0AAAAAAA0gAK
+AAsAvAC9I0BiUAAAAAAAI0Bi0AAAAAAA1QACABMABAAFAAYAvwDAAMEAxAAREwAA
+B2sCW80ITxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQID
+AAAAAAAAAKBAAAAXQwCAFkMaMz5bAAAAANIACgALAMIAwyNAYuAAAAAAACNAYtAA
+AAAAANIACgALAMUAxiNAYuAAAAAAACNAYtAAAAAAANUAAgATAAQABQAGAMgAyQDK
+AM0AERMAAAdrA1fkmk8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAABAAECAwAAAAAAAACgQAAAG0MAgBZDGjM+WwAAAADSAAoACwDLAMwjQGNgAAAA
+AAAjQGLQAAAAAADSAAoACwDOAM8jQGNgAAAAAAAjQGLQAAAAAADVAAIAEwAEAAUA
+BgDRANIA0wDWABETAAAHawRTbT5PEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAgB1DAIAWQxozPlsAAAAA0gAKAAsA1ADV
+I0BjsAAAAAAAI0Bi0AAAAAAA0gAKAAsA1wDYI0BjsAAAAAAAI0Bi0AAAAAAA1QAC
+ABMABAAFAAYA2gDbANwA3wAREwAAB2sFU/5CTxBAAgAAAAEAAQAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAAAjQwAAFkMaMz5bAAAAANIA
+CgALAN0A3iNAZGAAAAAAACNAYsAAAAAAANIACgALAOAA4SNAZGAAAAAAACNAYsAA
+AAAAANUAAgATAAQABQAGAOMA5ADlAOgAERMAAAdrBk38XU8QQAIAAAABAAEAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAJkMAABZDGjM+
+WwAAAADSAAoACwDmAOcjQGTAAAAAAAAjQGLAAAAAAADSAAoACwDpAOojQGTAAAAA
+AAAjQGLAAAAAAADVAAIAEwAEAAUABgDsAO0A7gDxABETAAAHawdbdAxPEEACAAAA
+AQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAClD
+AAAWQxozPlsAAAAA0gAKAAsA7wDwI0BlIAAAAAAAI0BiwAAAAAAA0gAKAAsA8gDz
+I0BlIAAAAAAAI0BiwAAAAAAA1QACABMABAAFAAYA9QD2APcA+gAREwAAB2sIT8Mj
+TxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAA
+AKBAAAAsQwAAFkMaMz5bAAAAANIACgALAPgA+SNAZYAAAAAAACNAYsAAAAAAANIA
+CgALAPsA/CNAZYAAAAAAACNAYsAAAAAAANUAAgATAAQABQAGAP4A/wEAAQMAERMA
+AAdrCVOVU08QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEC
+AwAAAAAAAACgQAAAL0MAABVDGjM+WwAAAADSAAoACwEBAQIjQGXgAAAAAAAjQGKg
+AAAAAADSAAoACwEEAQUjQGXgAAAAAAAjQGKgAAAAAADVAAIAEwAEAAUABgEHAQgB
+CQEMABETAAAHawpNmUpPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAQABAgMAAAAAAAAAoEAAADJDAAAVQxozPlsAAAAA0gAKAAsBCgELI0BmQAAA
+AAAAI0BioAAAAAAA0gAKAAsBDQEOI0BmQAAAAAAAI0BioAAAAAAA1QACABMABAAF
+AAYBEAERARIBFQAREwAAB2sLSRJXTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAAA1QwAAFUMaMz5bAAAAANIACgALARMB
+FCNAZqAAAAAAACNAYqAAAAAAANIACgALARYBFyNAZqAAAAAAACNAYqAAAAAAANUA
+AgATAAQABQAGARkBGgEbAR4AERMAAAdrDE0l6E8QQAIAAAABAAEAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQACAN0MAABVDGjM+WwAAAADS
+AAoACwEcAR0jQGbwAAAAAAAjQGKgAAAAAADSAAoACwEfASAjQGbwAAAAAAAjQGKg
+AAAAAADVAAIAEwAEAAUABgEiASMBJAEnABETAAAHaw1EdQxPEEACAAAAAQABAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAADpDAAAVQxoz
+PlsAAAAA0gAKAAsBJQEmI0BnQAAAAAAAI0BioAAAAAAA0gAKAAsBKAEpI0BnQAAA
+AAAAI0BioAAAAAAA1QACABMABAAFAAYBKwEsAS0BMAAREwAAB2sOSR6OTxBAAgAA
+AAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAAA9
+QwAAFUMaMz5bAAAAANIACgALAS4BLyNAZ6AAAAAAACNAYqAAAAAAANIACgALATEB
+MiNAZ6AAAAAAACNAYqAAAAAAANUAAgATAAQABQAGATQBNQE2ATkAERMAAAdrD0Kr
+aU8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAA
+AACgQAAAP0MAABVDGjM+WwAAAADSAAoACwE3ATgjQGfgAAAAAAAjQGKgAAAAAADS
+AAoACwE6ATsjQGfgAAAAAAAjQGKgAAAAAADVAAIAEwAEAAUABgE9AT4BPwFCABET
+AAAHaxBG0FpPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAB
+AgMAAAAAAAAAoEAAgEBDAAAVQxozPlsAAAAA0gAKAAsBQAFBI0BoEAAAAAAAI0Bi
+oAAAAAAA0gAKAAsBQwFEI0BoEAAAAAAAI0BioAAAAAAA1QACABMABAAFAAYBRgFH
+AUgBSwAREwAAB2sRQvVOTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAEAAQIDAAAAAAAAAKBAAIBDQwAAFUMaMz5bAAAAANIACgALAUkBSiNAaHAA
+AAAAACNAYqAAAAAAANIACgALAUwBTSNAaHAAAAAAACNAYqAAAAAAANUAAgATAAQA
+BQAGAU8BUAFRAVQAERMAAAdrEkYCoU8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAABAAECAwAAAAAAAACgQACARkMAABVDGjM+WwAAAADSAAoACwFS
+AVMjQGjQAAAAAAAjQGKgAAAAAADSAAoACwFVAVYjQGjQAAAAAAAjQGKgAAAAAADV
+AAIAEwAEAAUABgFYAVkBWgFdABETAAAHaxND+UBPEEACAAAAAQABAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAElDAIAUQxozPlsAAAAA
+0gAKAAsBWwFcI0BpIAAAAAAAI0BikAAAAAAA0gAKAAsBXgFfI0BpIAAAAAAAI0Bi
+kAAAAAAA1QACABMABAAFAAYBYQFiAWMBZgAREwAAB2sUTdo9TxBAAgAAAAEAAQAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAIBKQwCAFEMa
+Mz5bAAAAANIACgALAWQBZSNAaVAAAAAAACNAYpAAAAAAANIACgALAWcBaCNAaVAA
+AAAAACNAYpAAAAAAANUAAgATAAQABQAGAWoBawFsAW8AERMAAAdrFU0iOU8QQAIA
+AAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAA
+TEMAgBRDGjM+WwAAAADSAAoACwFtAW4jQGmAAAAAAAAjQGKQAAAAAADSAAoACwFw
+AXEjQGmAAAAAAAAjQGKQAAAAAADVAAIAEwAEAAUABgFzAXQBdQF4ABETAAAHaxZJ
+Yp5PEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAA
+AAAAoEAAgE1DAIAUQxozPlsAAAAA0gAKAAsBdgF3I0BpsAAAAAAAI0BikAAAAAAA
+0gAKAAsBeQF6I0BpsAAAAAAAI0BikAAAAAAA1QACABMABAAFAAYBfAF9AX4BgQAR
+EwAAB2sXSS8BTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA
+AQIDAAAAAAAAAKBAAIBOQwCAFEMaMz5bAAAAANIACgALAX8BgCNAadAAAAAAACNA
+YpAAAAAAANIACgALAYIBgyNAadAAAAAAACNAYpAAAAAAANUAAgATAAQABQAGAYUB
+hgGHAYoAERMAAAdrGEybD08QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAABAAECAwAAAAAAAACgQACAUUMAgBRDGjM+WwAAAADSAAoACwGIAYkjQGow
+AAAAAAAjQGKQAAAAAADSAAoACwGLAYwjQGowAAAAAAAjQGKQAAAAAADVAAIAEwAE
+AAUABgGOAY8BkAGTABETAAAHaxlB/x5PEEACAAAAAQABAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAFRDAIAUQxozPlsAAAAA0gAKAAsB
+kQGSI0BqgAAAAAAAI0BikAAAAAAA0gAKAAsBlAGVI0BqgAAAAAAAI0BikAAAAAAA
+1QACABMABAAFAAYBlwGYAZkBnAAREwAAB2saQ62PTxBAAgAAAAEAAQAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAIBVQwCAFEMaMz5bAAAA
+ANIACgALAZoBmyNAarAAAAAAACNAYpAAAAAAANIACgALAZ0BniNAarAAAAAAACNA
+YpAAAAAAANUAAgATAAQABQAGAaABoQGiAaUAERMAAAdrGz8+c08QQAIAAAABAAEA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAVkMAgBRD
+GjM+WwAAAADSAAoACwGjAaQjQGrAAAAAAAAjQGKQAAAAAADSAAoACwGmAacjQGrA
+AAAAAAAjQGKQAAAAAADVAAIAEwAEAAUABgGpAaoBqwGuABETAAAHaxw+NSNPEEAC
+AAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAA
+gFdDAIAUQxozPlsAAAAA0gAKAAsBrAGtI0Bq8AAAAAAAI0BikAAAAAAA0gAKAAsB
+rwGwI0Bq8AAAAAAAI0BikAAAAAAA1QACABMABAAFAAYBsgGzAbQBtwAREwAAB2sd
+Pk4wTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAA
+AAAAAKBAAIBYQwCAFEMaMz5bAAAAANIACgALAbUBtiNAaxAAAAAAACNAYpAAAAAA
+ANIACgALAbgBuSNAaxAAAAAAACNAYpAAAAAAANUAAgATAAQABQAGAbsBvAG9AcAA
+ERMAAAdrHkUUk08QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB
+AAECAwAAAAAAAACgQAAAWkMAgBRDGjM+WwAAAADSAAoACwG+Ab8jQGtAAAAAAAAj
+QGKQAAAAAADSAAoACwHBAcIjQGtAAAAAAAAjQGKQAAAAAADVAAIAEwAEAAUABgHE
+AcUBxgHJABETAAAHayBHX/lPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAQABAgMAAAAAAAAAoEAAgF5DAIATQxozPlsAAAAA0gAKAAsBxwHII0Br
+0AAAAAAAI0BicAAAAAAA0gAKAAsBygHLI0Br0AAAAAAAI0BicAAAAAAA1QACABMA
+BAAFAAYBzQHOAc8B0gAREwAAB2siPAOGTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAABiQwCAE0MaMz5bAAAAANIACgAL
+AdAB0SNAbEAAAAAAACNAYnAAAAAAANIACgALAdMB1CNAbEAAAAAAACNAYnAAAAAA
+ANUAAgATAAQABQAGAdYB1wHYAdsAERMAAAdrIznzfE8QQAIAAAABAAEAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQACAY0MAgBNDGjM+WwAA
+AADSAAoACwHZAdojQGxwAAAAAAAjQGJwAAAAAADSAAoACwHcAd0jQGxwAAAAAAAj
+QGJwAAAAAADVAAIAEwAEAAUABgHfAeAB4QHkABETAAAHayQ6sLBPEEACAAAAAQAB
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAGVDAIAT
+QxozPlsAAAAA0gAKAAsB4gHjI0BsoAAAAAAAI0BicAAAAAAA0gAKAAsB5QHmI0Bs
+oAAAAAAAI0BicAAAAAAA1QACABMABAAFAAYB6AHpAeoB7QAREwAAB2slM/J3TxBA
+AgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBA
+AIBnQwCAE0MaMz5bAAAAANIACgALAesB7CNAbPAAAAAAACNAYnAAAAAAANIACgAL
+Ae4B7yNAbPAAAAAAACNAYnAAAAAAANUAAgATAAQABQAGAfEB8gHzAfYAERMAAAdr
+JjURmU8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAA
+AAAAAACgQACAa0MAgBNDGjM+WwAAAADSAAoACwH0AfUjQG1wAAAAAAAjQGJwAAAA
+AADSAAoACwH3AfgjQG1wAAAAAAAjQGJwAAAAAADVAAIAEwAEAAUABgH6AfsB/AH/
+ABETAAAHayc6eWdPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AQABAgMAAAAAAAAAoEAAgG5DAIATQxozPlsAAAAA0gAKAAsB/QH+I0Bt0AAAAAAA
+I0BicAAAAAAA0gAKAAsCAAIBI0Bt0AAAAAAAI0BicAAAAAAA1QACABMABAAFAAYC
+AwIEAgUCCAAREwAAB2soPjFYTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAEAAQIDAAAAAAAAAKBAAABwQwCAE0MaMz5bAAAAANIACgALAgYCByNA
+bgAAAAAAACNAYnAAAAAAANIACgALAgkCCiNAbgAAAAAAACNAYnAAAAAAANUAAgAT
+AAQABQAGAgwCDQIOAhEAERMAAAdrKTRvp08QQAIAAAABAAEAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQACAcUMAgBNDGjM+WwAAAADSAAoA
+CwIPAhAjQG4wAAAAAAAjQGJwAAAAAADSAAoACwISAhMjQG4wAAAAAAAjQGJwAAAA
+AADVAAIAEwAEAAUABgIVAhYCFwIaABETAAAHayowmJNPEEACAAAAAQABAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAgHJDAIATQxozPlsA
+AAAA0gAKAAsCGAIZI0BuUAAAAAAAI0BicAAAAAAA0gAKAAsCGwIcI0BuUAAAAAAA
+I0BicAAAAAAA1QACABMABAAFAAYCHgIfAiACIwAREwAAB2srMwmiTxBAAgAAAAEA
+AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAAB0QwCA
+E0MaMz5bAAAAANIACgALAiECIiNAboAAAAAAACNAYnAAAAAAANIACgALAiQCJSNA
+boAAAAAAACNAYnAAAAAAANUAAgATAAQABQAGAicCKAIpAiwAERMAAAdrLCyaBE8Q
+QAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACg
+QAAAdkMAABNDGjM+WwAAAADSAAoACwIqAisjQG7AAAAAAAAjQGJgAAAAAADSAAoA
+CwItAi4jQG7AAAAAAAAjQGJgAAAAAADVAAIAEwAEAAUABgIwAjECMgI1ABETAAAH
+ay0xLT5PEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMA
+AAAAAAAAoEAAAHlDAAATQxozPlsAAAAA0gAKAAsCMwI0I0BvIAAAAAAAI0BiYAAA
+AAAA0gAKAAsCNgI3I0BvIAAAAAAAI0BiYAAAAAAA1QACABMABAAFAAYCOQI6AjsC
+PgAREwAAB2suLuuNTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAEAAQIDAAAAAAAAAKBAAIB7QwAAE0MaMz5bAAAAANIACgALAjwCPSNAb3AAAAAA
+ACNAYmAAAAAAANIACgALAj8CQCNAb3AAAAAAACNAYmAAAAAAANUAAgATAAQABQAG
+AkICQwJEAkcAERMAAAdrLy+XLU8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAABAAECAwAAAAAAAACgQACAfkMAABNDGjM+WwAAAADSAAoACwJFAkYj
+QG/QAAAAAAAjQGJgAAAAAADSAAoACwJIAkkjQG/QAAAAAAAjQGJgAAAAAADVAAIA
+EwAEAAUABgJLAkwCTQJQABETAAAHazAvT/NPEEACAAAAAQABAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAIBDAAATQxozPlsAAAAA0gAK
+AAsCTgJPI0BwAAAAAAAAI0BiYAAAAAAA0gAKAAsCUQJSI0BwAAAAAAAAI0BiYAAA
+AAAA1QACABMABAAFAAYCVAJVAlYCWQAREwAAB2sxJwXLTxBAAgAAAAEAAQAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAECAQwAAE0MaMz5b
+AAAAANIACgALAlcCWCNAcAgAAAAAACNAYmAAAAAAANIACgALAloCWyNAcAgAAAAA
+ACNAYmAAAAAAANUAAgATAAQABQAGAl0CXgJfAmIAERMAAAdrMitgu08QQAIAAAAB
+AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAgUMA
+ABNDGjM+WwAAAADSAAoACwJgAmEjQHAgAAAAAAAjQGJgAAAAAADSAAoACwJjAmQj
+QHAgAAAAAAAjQGJgAAAAAADVAAIAEwAEAAUABgJmAmcCaAJrABETAAAHazMqBe1P
+EEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAA
+oEAAwIFDAAATQxozPlsAAAAA0gAKAAsCaQJqI0BwOAAAAAAAI0BiYAAAAAAA0gAK
+AAsCbAJtI0BwOAAAAAAAI0BiYAAAAAAA1QACABMABAAFAAYCbwJwAnECdAAREwAA
+B2s0K7CYTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQID
+AAAAAAAAAKBAAICCQwAAE0MaMz5bAAAAANIACgALAnICcyNAcFAAAAAAACNAYmAA
+AAAAANIACgALAnUCdiNAcFAAAAAAACNAYmAAAAAAANUAAgATAAQABQAGAngCeQJ6
+An0AERMAAAdrNyoIAk8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAABAAECAwAAAAAAAACgQAAAg0MAABJDGjM+WwAAAADSAAoACwJ7AnwjQHBgAAAA
+AAAjQGJAAAAAAADSAAoACwJ+An8jQHBgAAAAAAAjQGJAAAAAAADVAAIAEwAEAAUA
+BgKBAoICgwKGABETAAAHazkl7PxPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAgINDAAASQxozPlsAAAAA0gAKAAsChAKF
+I0BwcAAAAAAAI0BiQAAAAAAA0gAKAAsChwKII0BwcAAAAAAAI0BiQAAAAAAA1QAC
+ABMABAAFAAYCigKLAowCjwAREwAAB2s6JlicTxBAAgAAAAEAAQAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAECEQwAAEkMaMz5bAAAAANIA
+CgALAo0CjiNAcIgAAAAAACNAYkAAAAAAANIACgALApACkSNAcIgAAAAAACNAYkAA
+AAAAANUAAgATAAQABQAGApMClAKVApgAERMAAAdrPRquhE8QQAIAAAABAAEAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAhkMAABJDGjM+
+WwAAAADSAAoACwKWApcjQHDAAAAAAAAjQGJAAAAAAADSAAoACwKZApojQHDAAAAA
+AAAjQGJAAAAAAADVAAIAEwAEAAUABgKcAp0CngKhABETAAAHaz8WbgJPEEACAAAA
+AQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAQIZD
+AAASQxozPlsAAAAA0gAKAAsCnwKgI0BwyAAAAAAAI0BiQAAAAAAA0gAKAAsCogKj
+I0BwyAAAAAAAI0BiQAAAAAAA1QACABMABAAFAAYCpQKmAqcCqgAREwAAB2tAFgUH
+TxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAA
+AKBAAMCGQwAAEkMaMz5bAAAAANIACgALAqgCqSNAcNgAAAAAACNAYkAAAAAAANIA
+CgALAqsCrCNAcNgAAAAAACNAYkAAAAAAANUAAgATAAQABQAGAq4CrwKwArMAERMA
+AAdrQxGfo08QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEC
+AwAAAAAAAACgQABAh0MAABJDGjM+WwAAAADSAAoACwKxArIjQHDoAAAAAAAjQGJA
+AAAAAADSAAoACwK0ArUjQHDoAAAAAAAjQGJAAAAAAADVAAIAEwAEAAUABgK3ArgC
+uQK8ABETAAAHa0sPLKxPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAQABAgMAAAAAAAAAoEAAwIdDAAASQxozPlsAAAAA0gAKAAsCugK7I0Bw+AAA
+AAAAI0BiQAAAAAAA0gAKAAsCvQK+I0Bw+AAAAAAAI0BiQAAAAAAA1QACABMABAAF
+AAYCwALBAsICxQAREwAAB2tODSCBTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAECIQwAAEkMaMz5bAAAAANIACgALAsMC
+xCNAcQgAAAAAACNAYkAAAAAAANIACgALAsYCxyNAcQgAAAAAACNAYkAAAAAAANUA
+AgATAAQABQAGAskCygLLAs4AERMAAAdrUITiOE8QQAYAAAABAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAABAAECAAAAAAAAAACgQABAiEMAABJDGjM+WwAAAADS
+AAoACwLMAs0jQHEIAAAAAAAjQGJAAAAAAADSAAoACwLPAtAjQHEIAAAAAAAjQGJA
+AAAAAAAACACpAL4AwwDIANcA4ADlAO4BMQE6ATwBPgFHAVABWQFiAWsBbgGDAYgB
+kQHUAd0B5gHvAfgCAQIKAh8CKAJrAnQCfQKGAo8CmAKhArYCvwMCAwsDFAMdAyYD
+LwM4A00DVgOZA6IDqwO0A70DxgPPA+QD7QQwBDkEQgRLBFQEXQRmBHsEhATHBNAE
+2QTiBOsE9AT9BRIFGwVeBWcFcAV5BYIFiwWUBakFsgX1Bf4GBwYQBhkGIgYrBkAG
+SQaMBpUGnganBrAGuQbCBtcG4AcjBywHNQc+B0cHUAdZB24Hdwe6B8MHzAfVB94H
+5wfwCAUIDghRCFoIYwhsCHUIfgiHCJwIpQjoCPEI+gkDCQwJFQkeCTMJPAl/CYgJ
+kQmaCaMJrAm1CcoJ0woWCh8KKAoxCjoKQwpMCmEKagqtCrYKvwrICtEK2grjCvgL
+AQtEC00LVgtfC2gLcQt6C48LmAvbC+QL7Qv2C/8MCAwRDCYMLwxyDHsMhAyNDJYM
+nwyoDL0Mxg0JDRINGw0kDS0NNg0/DVQNXQ2gDakNsg27DcQNzQ3WDesN9A43DkAO
+SQ5SDlsOZA5tDoIOiw7ODtcO4A7pDvIO+w8EDxkPIg9lD24Pdw+AD4kPkg+bD7AP
+uQ/8EAUQDhAXECAQKRAyEEcQUBCTEJwQpRCuELcQwBDJEN4Q5xEqETMRPBFFEU4R
+VxFgEXURfhHBEcoR0xHcEeUR7hH3EgwSFRJYEmESahJzEnwShRKOEqMSrBLvEvgT
+ARMKExMTHBMlEzoTQxOGE48TmBOhE6oTsxO8E9ET2hQdFCYULxQ4FEEUShRTFGgU
+cRS0FL0UxhTPFNgU4RTqFP8VCBVLFVQVXRVmFW8VeBWBFZYVnxXiFesV9BX9FgYW
+DxYYFi0WNhZ5FoIWixaUFp0WphavFsQWzRcQFxkXIhcrFzQXPRdGF1sXZBenF7AX
+uRfCF8sX1BfdF/IX+xg+GEcYUBhZGGIYaxh0GIkYkhjVGN4Y5xjwGPkZAhkLGSAZ
+KRlsGXUZfhmHGZAZmRmiGbcZwBoDGgwaFRoeGicaMBo5Gk4aVxqaGqMarBq1Gr4a
+xxrQGuUa7hsxGzobQxtMG1UbXhtnG3wbhRvIG9Eb2hvjG+wb9Rv+HBMcHBxfHGgc
+cRx6HIMcjByVHKocsxz2HP8dCB0RHRodIx0sHUEdSh2NHZYdnx2oHbEduh3DHdgd
+4R4kHi0eNh4/HkgeUR5aHm8eeB67HsQezR7WHt8e6B7xHwYfDx9SH1sfZB9tH3Yf
+fx+IH50fph/pH/If+yAEIA0gFiAfIDQgPSCAIIkgkiCbIKQgrSC2IMsg1CEXISAh
+KSEyITshRCFNIWIhayGuIbchwCHJIdIh2yHkIfkiAiJFIk4iVyJgImkiciJ7IpAi
+mSLcIuUi7iL3IwAjCSMSIycjMCNzI3wjhSOOI5cjoCOpI74jxyQKJBMkHCQlJC4k
+NyRAJFUkXiShJKoksyS8JMUkziTXJOwk9SU4JUElSiVTJVwlZSVuJYMljCXPJdgl
+4SXqJfMl/CYFJhomIyZmJm8meCaBJoomkyacJrEmuib9JwYnDycYJyEnKiczJ0gn
+USeUJ50npievJ7gnwSfKJ98n6CgrKDQoPShGKE8oWChhKHYofyjCKMso1CjdKOYo
+7yj4KQ0pFilZKWIpayl0KX0phimPKaQprSnwKfkqAioLKhQqHSomKjsqRCqHKpAq
+mSqiKqsqtCq9KtIq2yseKycrMCs5K0IrSytUK2krciu1K74rxyvQK9kr4ivrLAAs
+CSxMLFUsXixnLHAseSyCLJcsoCzjLOws9Sz+LQctEC0ZLS4tNy16LYMtjC2VLZ4t
+py2wLcUtzi4RLhouIy4sLjUuPi5HLlwuZS6oLrEuui7DLswu1S7eLvMu/C8/L0gv
+US9aL2MvbAAAAAAAAAICAAAAAAAAAtEAAAAAAAAAAAAAAAAAAC91
diff --git a/Xamarin.Forms.ControlGallery.iOS/move_slider_two_right_ios6_iphone.base64 b/Xamarin.Forms.ControlGallery.iOS/move_slider_two_right_ios6_iphone.base64
new file mode 100644
index 00000000..5235dce8
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/move_slider_two_right_ios6_iphone.base64
@@ -0,0 +1,44 @@
+YnBsaXN0MDCtARIcJS43QElSW2RtdtUCAwQFBgcICQ4RVFRpbWVURGF0YV5XaW5k
+b3dMb2NhdGlvblhMb2NhdGlvblRUeXBlEwAAB2dt8Dn+TxBAAQAAAAEAAQAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAAAOQgAA/0IaMz5b
+AAAAANIKCwwNUVhRWSNAQcAAAAAAACNAX+AAAAAAANIKCw8QI0BBwAAAAAAAI0Bf
+4AAAAAAAEQu51QITBAUGFBUWGRFURGF0YRMAAAdndRBD9k8QQAIAAAABAAEAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAAAACgQAAAEkIAAP9CGjM+
+WwAAAADSCgsXGCNAQkAAAAAAACNAX+AAAAAAANIKCxobI0BCQAAAAAAAI0Bf4AAA
+AAAA1QITBAUGHR4fIhETAAAHZ3YQsV5PEEACAAAAAQABAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAACRCAAD/QhozPlsAAAAA0goLICEj
+QESAAAAAAAAjQF/gAAAAAADSCgsjJCNARIAAAAAAACNAX+AAAAAAANUCEwQFBiYn
+KCsREwAAB2d3GbewTxBAAgAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAEAAQIDAAAAAAAAAKBAAAA8QgAA/UIaMz5bAAAAANIKCykqI0BHgAAAAAAAI0Bf
+oAAAAAAA0goLLC0jQEeAAAAAAAAjQF+gAAAAAADVAhMEBQYvMDE0ERMAAAdneBDQ
+bE8QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAwAAAAAA
+AACgQAAAVEIAAP1CGjM+WwAAAADSCgsyMyNASoAAAAAAACNAX6AAAAAAANIKCzU2
+I0BKgAAAAAAAI0BfoAAAAAAA1QITBAUGODk6PRETAAAHZ3kTB7lPEEACAAAAAQAB
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAAHhCAAD6
+QhozPlsAAAAA0goLOzwjQE8AAAAAAAAjQF9AAAAAAADSCgs+PyNATwAAAAAAACNA
+X0AAAAAAANUCEwQFBkFCQ0YREwAAB2d6ByCaTxBAAgAAAAEAAQAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAACYQgAA+UIaMz5bAAAAANIK
+C0RFI0BTAAAAAAAAI0BfIAAAAAAA0goLR0gjQFMAAAAAAAAjQF8gAAAAAADVAhME
+BQZKS0xPERMAAAdnexkO/08QQAIAAAABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAABAAECAwAAAAAAAACgQAAAvkIAAPNCGjM+WwAAAADSCgtNTiNAV8AAAAAA
+ACNAXmAAAAAAANIKC1BRI0BXwAAAAAAAI0BeYAAAAAAA1QITBAUGU1RVWBETAAAH
+Z30RHChPEEACAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAgMA
+AAAAAAAAoEAAgENDAADtQhozPlsAAAAA0goLVlcjQGhwAAAAAAAjQF2gAAAAAADS
+CgtZWiNAaHAAAAAAACNAXaAAAAAAANUCEwQFBlxdXmEREwAAB2d+BrouTxBAAgAA
+AAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQIDAAAAAAAAAKBAAECY
+QwAA7UIaMz5bAAAAANIKC19gI0BzCAAAAAAAI0BdoAAAAAAA0goLYmMjQHMIAAAA
+AAAjQF2gAAAAAADVAhMEBQZlZmdqERMAAAdnfxBUHk8QQAYAAAABAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAABAAECAAAAAAAAAACgQADAn0MAAO1CGjM+WwAA
+AADSCgtoaSNAc/gAAAAAACNAXaAAAAAAANIKC2tsI0Bz+AAAAAAAI0BdoAAAAAAA
+1QITBAUGbm9wcxETAAAHZ+NsZe1PEEABAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAQABAgMAAAAAAAAAoEAAQJhDAABMQhozPlsAAAAA0goLcXIjQHMI
+AAAAAAAjQEmAAAAAAADSCgt0dSNAcwgAAAAAACNASYAAAAAAANUCEwQFBnd4eXwR
+EwAAB2fqw0JWTxBABgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA
+AQIAAAAAAAAAAKBAAECYQwAATEIaMz5bAAAAANIKC3p7I0BzCAAAAAAAI0BJgAAA
+AAAA0goLfX4jQHMIAAAAAAAjQEmAAAAAAAAACAAWACEAJgArADoAQwBIAFEAlACZ
+AJsAnQCmAK8AtAC9AMYAyQDUANkA4gElASoBMwE8AUEBSgFTAV4BZwGqAa8BuAHB
+AcYBzwHYAeMB7AIvAjQCPQJGAksCVAJdAmgCcQK0ArkCwgLLAtAC2QLiAu0C9gM5
+Az4DRwNQA1UDXgNnA3IDewO+A8MDzAPVA9oD4wPsA/cEAARDBEgEUQRaBF8EaARx
+BHwEhQTIBM0E1gTfBOQE7QT2BQEFCgVNBVIFWwVkBWkFcgV7BYYFjwXSBdcF4AXp
+Be4F9wYABgsGFAZXBlwGZQZuBnMGfAaFBpAGmQbcBuEG6gbzBvgHAQAAAAAAAAIB
+AAAAAAAAAH8AAAAAAAAAAAAAAAAAAAcK
diff --git a/Xamarin.Forms.ControlGallery.iOS/oasis.jpg b/Xamarin.Forms.ControlGallery.iOS/oasis.jpg
new file mode 100644
index 00000000..078a6e09
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/oasis.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/oasissmall.jpg b/Xamarin.Forms.ControlGallery.iOS/oasissmall.jpg
new file mode 100644
index 00000000..f8d43821
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/oasissmall.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/packages.config b/Xamarin.Forms.ControlGallery.iOS/packages.config
new file mode 100644
index 00000000..9749cf18
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Xamarin.Insights" version="1.11.4" targetFramework="xamarinios10" />
+ <package id="Xamarin.TestCloud.Agent" version="0.18.0" targetFramework="xamarinios10" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.iOS/photo.jpg b/Xamarin.Forms.ControlGallery.iOS/photo.jpg
new file mode 100644
index 00000000..07fd4b0a
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/photo.jpg
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/seth.png b/Xamarin.Forms.ControlGallery.iOS/seth.png
new file mode 100644
index 00000000..bd672139
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/seth.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/seth@2x.png b/Xamarin.Forms.ControlGallery.iOS/seth@2x.png
new file mode 100644
index 00000000..568360e8
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/seth@2x.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/settings@2x.png b/Xamarin.Forms.ControlGallery.iOS/settings@2x.png
new file mode 100644
index 00000000..3ba6a677
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/settings@2x.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.iOS/toolbar_close.png b/Xamarin.Forms.ControlGallery.iOS/toolbar_close.png
new file mode 100644
index 00000000..12f82abb
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.iOS/toolbar_close.png
Binary files differ
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/AddingMultipleItemsListView.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/AddingMultipleItemsListView.cs
new file mode 100644
index 00000000..1dbd3ada
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/AddingMultipleItemsListView.cs
@@ -0,0 +1,443 @@
+using System;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Diagnostics;
+using System.Windows.Input;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+
+ public class PropertyChangedBase : INotifyPropertyChanged
+ {
+ Dictionary<string, object> _properties = new Dictionary<string, object>();
+
+ protected T GetProperty<T>([CallerMemberName] string name = null)
+ {
+ object value = null;
+ if (_properties.TryGetValue(name, out value)) {
+ return value == null ? default(T) : (T)value;
+ }
+ return default(T);
+ }
+
+ protected void SetProperty<T>(T value, [CallerMemberName] string name = null)
+ {
+ if (Equals(value, GetProperty<T>(name))) {
+ return;
+ }
+ _properties[name] = value;
+ OnPropertyChanged(name);
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null) {
+ handler(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+ }
+
+ public class ViewModelError
+ {
+ public ViewModelError(string text)
+ {
+ Text = text;
+ }
+
+ public string Text { get; set; }
+
+ public override bool Equals(object obj)
+ {
+ var error = obj as ViewModelError;
+ if (error == null) {
+ return false;
+ }
+ return Text.Equals(error.Text);
+ }
+
+ public override int GetHashCode()
+ {
+ return Text.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return string.Format("ViewModelError: {0}", Text);
+ }
+ }
+
+ public class ViewModelBase : PropertyChangedBase
+ {
+ public ViewModelBase()
+ {
+ _errors = new List<ViewModelError>();
+ Validate();
+ }
+
+ readonly List<ViewModelError> _errors;
+
+ public virtual bool IsValid
+ {
+ get { return _errors.Count <= 0; }
+ }
+
+ protected IEnumerable<ViewModelError> Errors
+ {
+ get { return _errors; }
+ }
+
+ public event EventHandler IsValidChanged;
+
+ public event EventHandler IsBusyChanged;
+
+ protected virtual void Validate()
+ {
+ OnPropertyChanged("IsValid");
+ OnPropertyChanged("Errors");
+
+ var callback = IsValidChanged;
+ if (callback != null) {
+ callback(this, EventArgs.Empty);
+ }
+
+ // Spit out errors for easier debugging.
+ if (_errors != null && _errors.Count > 0) {
+ Debug.WriteLine("Errors:");
+ foreach (var error in _errors) {
+ Debug.WriteLine(error);
+ }
+ }
+ }
+
+ protected virtual void ValidateProperty(Func<bool> validate, ViewModelError error)
+ {
+ if (validate()) {
+ _errors.Remove(error);
+ } else if (!_errors.Contains(error)) {
+ _errors.Add(error);
+ }
+ }
+
+ public virtual bool IsBusy
+ {
+ get { return _isBusy; }
+ set
+ {
+ if (_isBusy != value) {
+ _isBusy = value;
+ OnPropertyChanged("IsBusy");
+ OnIsBusyChanged();
+ }
+ }
+ }
+
+ bool _isBusy = false;
+
+ protected virtual void OnIsBusyChanged()
+ {
+ // Some models might want to have a validation thet depends on the busy state.
+ Validate();
+ var method = IsBusyChanged;
+ if (method != null)
+ IsBusyChanged(this, EventArgs.Empty);
+ }
+ }
+
+ public class DelegateCommand : ICommand
+ {
+ readonly Predicate<object> _canExecute;
+ readonly Action<object> _execute;
+
+ public event EventHandler CanExecuteChanged;
+
+ public DelegateCommand(Action<object> execute)
+ : this(execute, null)
+ {
+ }
+
+ public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
+ {
+ _execute = execute;
+ _canExecute = canExecute;
+ }
+
+ public bool CanExecute(object parameter)
+ {
+ if (_canExecute == null) {
+ return true;
+ }
+
+ return _canExecute(parameter);
+ }
+
+ public void Execute(object parameter)
+ {
+ _execute(parameter);
+ }
+
+ public void RaiseCanExecuteChanged()
+ {
+ var handler = CanExecuteChanged;
+ if (handler != null) {
+ handler(this, EventArgs.Empty);
+ }
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class ExampleViewModel : ViewModelBase
+ {
+ [Preserve (AllMembers = true)]
+ public class Job : ViewModelBase
+ {
+
+ public string JobId
+ {
+ get { return GetProperty<string>(); }
+ set { SetProperty(value); }
+ }
+
+ public string JobName
+ {
+ get { return GetProperty<string>(); }
+ set { SetProperty(value); }
+ }
+
+ public double? Hours
+ {
+ get { return GetProperty<double?>(); }
+ set { SetProperty(value); }
+ }
+
+ public bool Locked
+ {
+ get { return GetProperty<bool>(); }
+ set { SetProperty(value); }
+ }
+ }
+
+ public ExampleViewModel()
+ {
+
+ Jobs = new ObservableCollection<Job>()
+ {
+ new Job() { JobId = "3672", JobName = "Big Job", Hours = 2},
+ new Job() { JobId = "6289", JobName = "Smaller Job", Hours = 2},
+ new Job() { JobId = "3672-41", JobName = "Add On Job", Hours = 23},
+ };
+ }
+
+ public ObservableCollection<Job> Jobs { get; set; }
+
+
+ public ICommand AddOneCommand
+ {
+ get
+ {
+ if (_addOneCommand == null) {
+ _addOneCommand = new DelegateCommand(obj => {
+ Jobs.Add(new Job(){JobId = "1234", JobName = "add one", Hours = 12});
+ }, obj => !IsBusy);
+ }
+ return _addOneCommand;
+ }
+ }
+
+ ICommand _addOneCommand;
+
+ public ICommand AddTwoCommand
+ {
+ get
+ {
+ if (_addTwoCommand == null) {
+ _addTwoCommand = new DelegateCommand(obj => {
+ Jobs.Add(new Job() { JobId = "9999", JobName = "add two", Hours = 12 });
+ Jobs.Add(new Job() { JobId = "8888", JobName = "add two", Hours = 12 });
+ }, obj => !IsBusy);
+ }
+ return _addTwoCommand;
+ }
+ }
+
+ ICommand _addTwoCommand;
+
+ public void GetHours()
+ {
+
+ var results = new ObservableCollection<Job>()
+ {
+ new Job() { JobId = "3672", JobName = "RADO", Hours = 2},
+ new Job() { JobId = "6289", JobName = "MGA Life Cycle Flexible Test System", Hours = 2},
+
+ };
+
+ foreach (var x in results)
+ Jobs.Add(x);
+
+ }
+ }
+
+ public class DoubleStringConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if (null == value || "0" == value.ToString())
+ return string.Empty;
+ return value.ToString();
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ double? returnValue = null;
+ double convertResult;
+ var strvalue = value as string;
+ if (double.TryParse(strvalue, out convertResult))
+ {
+ returnValue = convertResult;
+ }
+ return returnValue;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.None, 0, "Adding Multiple Items to a ListView", PlatformAffected.All)]
+ public class AddingMultipleItemsListView : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Title = "Hours";
+ var exampleViewModel = new ExampleViewModel();
+ BindingContext = exampleViewModel;
+
+ var listView = new ListView
+ {
+ ItemTemplate = new DataTemplate(typeof(CustomViewCell)),
+ HeightRequest = 400,
+ VerticalOptions = LayoutOptions.Start
+ };
+
+ listView.SetBinding(ListView.ItemsSourceProperty, new Binding("Jobs", BindingMode.TwoWay));
+
+ var addOneJobButton = new Button
+ {
+ Text = "Add One"
+ };
+ addOneJobButton.SetBinding(Button.CommandProperty, new Binding("AddOneCommand"));
+
+ var addTwoJobsButton = new Button
+ {
+ Text = "Add Two"
+ };
+ addTwoJobsButton.SetBinding(Button.CommandProperty, new Binding("AddTwoCommand"));
+
+ var layout = new StackLayout
+ {
+ Orientation = StackOrientation.Vertical,
+ VerticalOptions = LayoutOptions.StartAndExpand,
+ Spacing = 15,
+ Children = {
+ listView,
+ addOneJobButton,
+ addTwoJobsButton
+ }
+ };
+ Content = layout;
+ }
+
+ [Preserve (AllMembers = true)]
+ public class CustomViewCell : ViewCell
+ {
+ public CustomViewCell ()
+ {
+ var jobId = new Label {
+ Font = Font.SystemFontOfSize(20),
+ WidthRequest = 105,
+ VerticalOptions = LayoutOptions.Center,
+
+ HorizontalOptions = LayoutOptions.StartAndExpand
+ };
+ jobId.SetBinding(Label.TextProperty, "JobId");
+
+ var jobName = new Label {
+ VerticalOptions = LayoutOptions.Center,
+ WidthRequest = 175,
+ HorizontalOptions = LayoutOptions.CenterAndExpand,
+ };
+ jobName.SetBinding(Label.TextProperty, "JobName");
+
+ var hours = new Label {
+ WidthRequest = 45,
+ VerticalOptions = LayoutOptions.Center,
+ XAlign = TextAlignment.End,
+ HorizontalOptions = LayoutOptions.EndAndExpand,
+
+ };
+ hours.SetBinding(Label.TextProperty, new Binding("Hours", BindingMode.OneWay, new DoubleStringConverter()));
+
+ var hlayout = new StackLayout {
+ Children = {
+ jobId,
+ jobName,
+ hours
+ },
+ Orientation = StackOrientation.Horizontal,
+ };
+
+ View = hlayout;
+ }
+ }
+
+#if UITEST
+ [Test]
+ public void AddingMultipleListViewTests1AllElementsPresent ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Big Job"));
+ RunningApp.WaitForElement (q => q.Marked ("Smaller Job"));
+ RunningApp.WaitForElement (q => q.Marked ("Add On Job"));
+ RunningApp.WaitForElement (q => q.Marked ("Add One"));
+ RunningApp.WaitForElement (q => q.Marked ("Add Two"));
+ RunningApp.WaitForElement (q => q.Marked ("3672"));
+ RunningApp.WaitForElement (q => q.Marked ("6289"));
+ RunningApp.WaitForElement (q => q.Marked ("3672-41"));
+ RunningApp.WaitForElement (q => q.Marked ("2"));
+ RunningApp.WaitForElement (q => q.Marked ("2"));
+ RunningApp.WaitForElement (q => q.Marked ("23"));
+
+ RunningApp.Screenshot ("All elements are present");
+ }
+
+ [Test]
+ public void AddingMultipleListViewTests2AddOneElementToList ()
+ {
+ RunningApp.Tap (q => q.Marked ("Add One"));
+
+ RunningApp.WaitForElement (q => q.Marked ("1234"), timeout: TimeSpan.FromSeconds (2));
+ RunningApp.Screenshot ("One more element exists");
+ }
+
+ [Test]
+ public void AddingMultipleListViewTests3AddTwoElementToList ()
+ {
+ RunningApp.Screenshot ("Click 'Add Two'");
+ RunningApp.Tap (q => q.Marked ("Add Two"));
+
+ RunningApp.WaitForElement (q => q.Marked ("9999"), timeout: TimeSpan.FromSeconds (2));
+ RunningApp.WaitForElement (q => q.Marked ("8888"), timeout: TimeSpan.FromSeconds (2));
+ RunningApp.Screenshot ("Two more element exist");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/AppBarIconColors.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/AppBarIconColors.cs
new file mode 100644
index 00000000..fffe5ecf
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/AppBarIconColors.cs
@@ -0,0 +1,52 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve(AllMembers = true)]
+ [Issue(IssueTracker.None, 0, "[UWP] Modal NavigationPage ignores BarTextColor settings for icons", PlatformAffected.WinRT)]
+ public class AppBarIconColors : TestNavigationPage
+ {
+ protected override void Init()
+ {
+ var firstPage = new ContentPage() { Title = "Page One" };
+
+ var button = new Button { Text = "Push Modal Page" };
+
+ firstPage.Content = new StackLayout { Children = { new Label { Text = "Click the 'push modal page' button" }, button } };
+
+ var otherButton = new Button() { Text = "back" };
+ otherButton.Clicked += (sender, args) => Navigation.PopModalAsync();
+
+ var page = new ContentPage {
+ Title = "Page Two",
+ Content =
+ new StackLayout {
+ Children = {
+ new Label {
+ Text =
+ "This is a modal page. The 'X' icon, the 'Done' label below it, and the '...' in the toolbar should all be white on UWP. If any of them are not white, this test has failed."
+ },
+ otherButton
+ }
+ }
+ };
+ page.ToolbarItems.Add(new ToolbarItem("Done", "toolbar_close.png", () => { Navigation.PopModalAsync(); }));
+
+ button.Clicked += (sender, args) => Navigation.PushModalAsync(new NavigationPageWithAppBarColors(page));
+
+ PushAsync(new NavigationPageWithAppBarColors(firstPage));
+ }
+ }
+
+ [Preserve(AllMembers = true)]
+ public class NavigationPageWithAppBarColors : NavigationPage
+ {
+ public NavigationPageWithAppBarColors(Page root) : base(root)
+ {
+ BarBackgroundColor = Color.Purple;
+ BarTextColor = Color.White;
+ Title = root.Title;
+ Icon = root.Icon;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla21368.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla21368.cs
new file mode 100644
index 00000000..88d9d2ac
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla21368.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Bugzilla, 21368, "Button text alignment breaks if the buttons are in a stack layout inside another layout and the button is clicked", PlatformAffected.Android)]
+ public class Bugzilla21368 : ContentPage
+ {
+ ScrollView _scrollView;
+ StackLayout _buttonsStack;
+ Grid _buttonsGrid;
+
+ public Bugzilla21368 ()
+ {
+ _scrollView = new ScrollView {
+ Orientation = ScrollOrientation.Horizontal,
+ Content = new StackLayout {
+ Orientation = StackOrientation.Horizontal
+ },
+ HeightRequest = 100
+ };
+
+ _buttonsGrid = new Grid {
+ RowSpacing = 10
+ };
+
+ _buttonsGrid.Children.Add (_scrollView, 0, 0);
+ _buttonsGrid.Children.Add (new Button {
+ Text = "Add Control",
+ Command = new Command (OnAddControl),
+ WidthRequest=400
+ }, 0, 1);
+ _buttonsGrid.Children.Add (new Button {
+ Text = "Insert Control",
+ Command = new Command (OnInsertControl)
+ }, 0, 2);
+ _buttonsGrid.Children.Add (new Button {
+ Text = "Remove Control",
+ Command = new Command (OnRemoveControl)
+ }, 0, 3);
+ _buttonsStack = new StackLayout { Children = { _buttonsGrid } };
+
+ Content = new StackLayout {
+ Orientation = StackOrientation.Vertical,
+ Children =
+ {
+ _buttonsStack
+ }
+ };
+ }
+
+ StackLayout ScrollStackLayout
+ {
+ get { return (StackLayout) _scrollView.Content; }
+ }
+
+ void OnAddControl ()
+ {
+ ScrollStackLayout.Children.Add (new Button { Text = "hello" });
+ ForceRelayout ();
+ }
+
+ void OnInsertControl ()
+ {
+ ScrollStackLayout.Children.Insert (0, new Button {
+ Text = "hello"
+ });
+ ForceRelayout ();
+ }
+
+ void OnRemoveControl ()
+ {
+ if (ScrollStackLayout.Children.Count > 0) {
+ ScrollStackLayout.Children.RemoveAt (0);
+ ForceRelayout ();
+ }
+ }
+
+ void ForceRelayout ()
+ {
+ ScrollStackLayout.ForceLayout ();
+ _scrollView.ForceLayout ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla21501.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla21501.cs
new file mode 100644
index 00000000..a9b896a5
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla21501.cs
@@ -0,0 +1,47 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Bugzilla, 21501, "ListView: Button in ItemTemplate breaks SelectedItem",PlatformAffected.Android)]
+ public class Bugzilla21501 : ContentPage
+ {
+ public Bugzilla21501 ()
+ {
+ var stringList = new List<string> () { "abc", "xyz", "todo" };
+
+ var resultLabel = new Label () { Text = "A" };
+
+ var listView = new ListView ();
+ listView.ItemsSource = stringList;
+ listView.ItemTemplate = new DataTemplate (() => {
+ var label = new Label ();
+ label.SetBinding (Label.TextProperty, ".");
+
+ var button = new Button () { Text = "Test" };
+
+ return new ViewCell {
+ View = new StackLayout {
+ Padding = new Thickness (0, 5),
+ Orientation = StackOrientation.Horizontal,
+ Children = { label, button }
+ }
+ };
+ });
+
+ listView.ItemSelected += (sender, args) => {
+ resultLabel.Text = resultLabel.Text + "!";
+ };
+
+ var layout = new StackLayout () {
+ Orientation = StackOrientation.Vertical,
+ Children = { listView, resultLabel }
+ };
+
+ Content = layout;
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla21780.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla21780.cs
new file mode 100644
index 00000000..70283c45
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla21780.cs
@@ -0,0 +1,19 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Bugzilla, 21780, "Windows Phone Editor control has black background with black text, background turns to white when editing", PlatformAffected.WinPhone)]
+ public class Bugzilla21780 : ContentPage
+ {
+ public Bugzilla21780 ()
+ {
+ var label = new Label () { Text = "If text is visible in the editor below, this test has passed." };
+ var editor = new Editor () { Text = "This text should be visible even if the editor does not have focus" };
+
+ Content = new StackLayout() {
+ Children = { label, editor }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla22229.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla22229.xaml
new file mode 100644
index 00000000..1f4c96d4
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla22229.xaml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Bugzilla22229" CurrentPageChanged="OnCurrentPageChanged" Title="Test Page">
+ <TabbedPage.Children>
+ <ContentPage Title="Tab 1"/>
+ <ContentPage Title="Tab 2"/>
+ <ContentPage Title="Tab 3"/>
+ <ContentPage Title="Tab 4"/>
+ <ContentPage Title="Tab 5"/>
+ </TabbedPage.Children>
+</TabbedPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla22229.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla22229.xaml.cs
new file mode 100644
index 00000000..10b6e8ad
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla22229.xaml.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 22229, "ToolbarItems not clearing", PlatformAffected.iOS | PlatformAffected.WinPhone, NavigationBehavior.PushAsync)]
+ public partial class Bugzilla22229 : TabbedPage
+ {
+ string _prefix;
+
+ public Bugzilla22229()
+ {
+ InitializeComponent();
+ _prefix = Device.OnPlatform(
+ iOS: "Images/",
+ Android: "",
+ WinPhone: "Assets/"
+ );
+ InitializeActionBar();
+ }
+
+
+ public void OnCurrentPageChanged(object sender, EventArgs e)
+ {
+ InitializeActionBar();
+ }
+
+ void InitializeActionBar()
+ {
+ ToolbarItems.Clear();
+ if (CurrentPage == Children[0])
+ {
+ ToolbarItems.Add(new ToolbarItem("Action 1", null, () => { }, ToolbarItemOrder.Primary, 1));
+ ToolbarItems.Add(new ToolbarItem("Action 2", null, () => { }, ToolbarItemOrder.Primary, 2));
+
+ ToolbarItems.Add(new ToolbarItem("Action 3", null, () => { }, ToolbarItemOrder.Secondary, 3));
+ ToolbarItems.Add(new ToolbarItem("Action 4", null, () => { }, ToolbarItemOrder.Secondary, 4));
+ ToolbarItems.Add(new ToolbarItem("Action 5", null, () => { }, ToolbarItemOrder.Secondary, 5));
+ }
+
+ }
+ }
+#endif
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla22401.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla22401.cs
new file mode 100644
index 00000000..c19b3c92
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla22401.cs
@@ -0,0 +1,114 @@
+using System.Collections.Generic;
+using System.Linq;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Bugzilla, 22401, "MasterDetailPage detail width broken when landscape", PlatformAffected.iOS, NavigationBehavior.PushAsync)]
+ public class Bugzilla22401 : MasterDetailPage
+ {
+ public Bugzilla22401()
+ {
+ List<Person> people = GetDemoData ();
+
+ // Create the ListView.
+ var listView = new ListView {
+ // Source of data items.
+ ItemsSource = people,
+
+ // Define template for displaying each item.
+ // (Argument of DataTemplate constructor is called for
+ // each item; it must return a Cell derivative.)
+ ItemTemplate = new DataTemplate (() => {
+ // Create views with bindings for displaying each property.
+ Label nameLabel = new Label();
+ nameLabel.SetBinding (Label.TextProperty, "Name");
+
+ // Return an assembled ViewCell.
+ return new ViewCell {
+ View = new StackLayout {
+ Padding = new Thickness(0, 5),
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ new StackLayout {
+ VerticalOptions = LayoutOptions.Center,
+ Spacing = 0,
+ Children = {
+ nameLabel
+ }
+ }
+ }
+ }
+ };
+ })
+ };
+
+ Master = new ContentPage { Title = "master", Icon = "menuIcon.png", Content = listView };
+
+ listView.ItemSelected += (sender, e) => {
+ Detail = CreateDetailPage (string.Format("Page {0}", (e.SelectedItem as Person).Name));
+ IsPresented = false;
+ };
+ listView.SelectedItem = people.First ();
+ }
+
+ static List<Person> GetDemoData()
+ {
+ List<Person> people = new List<Person> {
+ new Person("Abigail"),
+ new Person("Bob"),
+ new Person("Cathy"),
+ new Person("David"),
+ new Person("Eugenie"),
+ new Person("Freddie"),
+ new Person("Greta"),
+ new Person("Harold"),
+ new Person("Irene"),
+ new Person("Jonathan"),
+ new Person("Kathy"),
+ new Person("Larry"),
+ new Person("Monica"),
+ new Person("Nick"),
+ new Person("Olive"),
+ new Person("Pendletonlow"),
+ new Person("Queenie"),
+ new Person("Rob"),
+ new Person("Sally"),
+ new Person("Timothy"),
+ new Person("Uma"),
+ new Person("Victor"),
+ new Person("Wendy"),
+ new Person("Xavier"),
+ new Person("Yvonne"),
+ new Person("Zachary"),
+ };
+ return people;
+ }
+
+ static Page CreateDetailPage(string text)
+ {
+ var page = new ContentPage {
+ Title = text,
+ Content = new StackLayout {
+ Children = {
+ new Label {
+ Text = text,
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ HorizontalOptions = LayoutOptions.CenterAndExpand,
+ }
+ }
+ }
+ };
+
+ var tbiBank = new ToolbarItem { Command = new Command (() => { }), Icon = "bank.png" };
+ var tbiCalc = new ToolbarItem { Command = new Command (() => { }), Icon = "calculator.png" };
+
+ page.ToolbarItems.Add (tbiBank);
+ page.ToolbarItems.Add (tbiCalc);
+
+ return new NavigationPage (page);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla24574.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla24574.cs
new file mode 100644
index 00000000..b6d3c508
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla24574.cs
@@ -0,0 +1,50 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 24574, "Tap Double Tap")]
+ public class Issue24574 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ var label = new Label {
+ AutomationId = "TapLabel",
+ Text = "123"
+ };
+
+ var rec = new TapGestureRecognizer () { NumberOfTapsRequired = 1 };
+ rec.Tapped += (s, e) => { label.Text = "Single"; };
+ label.GestureRecognizers.Add (rec);
+
+ rec = new TapGestureRecognizer () { NumberOfTapsRequired = 2 };
+ rec.Tapped += (s, e) => { label.Text = "Double"; };
+ label.GestureRecognizers.Add (rec);
+
+ Content = label;
+ }
+
+#if UITEST
+ [Test]
+ public void Issue1Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue 24574");
+
+ RunningApp.WaitForElement (q => q.Marked ("TapLabel"));
+
+ RunningApp.Tap (q => q.Marked ("TapLabel"));
+ RunningApp.WaitForElement (q => q.Marked ("Single"));
+
+ RunningApp.DoubleTap (q => q.Marked ("TapLabel"));
+ RunningApp.WaitForElement (q => q.Marked ("Double"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla24769.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla24769.cs
new file mode 100644
index 00000000..699887bf
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla24769.cs
@@ -0,0 +1,80 @@
+using System.Collections.Generic;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 24769, "Layout cycle when Progress Bar is in a ListView", PlatformAffected.WinPhone | PlatformAffected.WinRT)]
+ public class Bugzilla24769 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var instructions = new Label () {
+ Text = @"Click the button labeled 'Progress++' three times. Each time, all four ProgressBar controls should increment. If they do not increment, the test has failed."
+ };
+
+ var items = new List<ListItem> {
+ new ListItem { Name = "Item1" },
+ new ListItem { Name = "Item2" },
+ new ListItem { Name = "Item3" }
+ };
+
+ var btn = new Button {
+ Text = "Progress++"
+ };
+
+ var progressBar = new ProgressBar { Progress = 0.1 };
+
+ btn.Clicked += (sender, arg) => {
+ MessagingCenter.Send (this, "set_progress");
+ progressBar.Progress += 0.1;
+ };
+
+ var list = new ListView {
+ ItemsSource = items,
+ ItemTemplate = new DataTemplate (typeof(ListCell))
+ };
+
+ BackgroundColor = Color.Maroon;
+
+ Content = new StackLayout {
+ VerticalOptions = LayoutOptions.Fill,
+ HorizontalOptions = LayoutOptions.Fill,
+ Children = {
+ instructions,
+ btn,
+ progressBar,
+ list
+ }
+ };
+ }
+ }
+
+ internal class ListCell : ViewCell
+ {
+ public ListCell ()
+ {
+ var label = new Label ();
+ label.SetBinding (Label.TextProperty, "Name");
+
+ var progress = new ProgressBar { Progress = 0.1 };
+
+ MessagingCenter.Subscribe<Bugzilla24769> (this, "set_progress", sender => { progress.Progress += 0.1; });
+
+ View =
+ new StackLayout {
+ HorizontalOptions = LayoutOptions.Fill,
+ BackgroundColor = Color.Gray,
+ Children = {
+ label,
+ progress
+ }
+ };
+ }
+ }
+
+ internal class ListItem
+ {
+ public string Name { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla25662.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla25662.cs
new file mode 100644
index 00000000..6a34cdf7
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla25662.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 25662, "Setting IsEnabled does not disable SwitchCell")]
+ public class Bugzilla25662 : ContentPage
+ {
+ class MySwitch : SwitchCell
+ {
+ public MySwitch ()
+ {
+ IsEnabled = false;
+ }
+ }
+
+
+ public Bugzilla25662 ()
+ {
+ var list = new ListView {
+ ItemsSource = new[] {
+ "One", "Two", "Three"
+ },
+ ItemTemplate = new DataTemplate (typeof (MySwitch))
+ };
+
+ Content = list;
+ Title = "My page";
+
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla25979.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla25979.cs
new file mode 100644
index 00000000..277ac684
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla25979.cs
@@ -0,0 +1,133 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 25979, "https://bugzilla.xamarin.com/show_bug.cgi?id=25979")]
+ public class Bugzilla25979 : TestNavigationPage // or TestMasterDetailPage, etc ...
+ {
+ [Preserve (AllMembers = true)]
+ internal sealed class MyPage : ContentPage
+ {
+ public MyPage()
+ {
+ Title = "Page 1";
+ AutomationId = "PageOneId";
+
+ var b = new Button {
+ AutomationId = "PageOneButtonId",
+ Text = "Next"
+ };
+ b.Clicked += async (sender, e) => {
+ await Navigation.PushAsync (new MyPage2());
+ };
+
+ Content = new StackLayout {
+ BackgroundColor = Color.Red,
+ Children = {
+ new Label { Text = "Page 1", FontSize=Device.GetNamedSize(NamedSize.Large, typeof(Label)) },
+ b
+ }
+ };
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ internal sealed class MyPage2 : ContentPage
+ {
+ public MyPage2()
+ {
+ Title = "Page 2";
+ AutomationId = "PageTwoId";
+
+ var b = new Button {
+ AutomationId = "PageTwoButtonId",
+ Text = "Next"
+ };
+ b.Clicked += async (sender, e) => {
+ await Navigation.PushAsync (new MyPage3());
+ Navigation.NavigationStack[0].BindingContext = null;
+ Navigation.RemovePage(Navigation.NavigationStack[0]);
+ };
+
+ Content = new StackLayout {
+ BackgroundColor = Color.Red,
+ Children = {
+ new Label { Text = "Page 2", FontSize=Device.GetNamedSize(NamedSize.Large, typeof(Label)) },
+ b
+ }
+ };
+ }
+
+ protected override void OnAppearing ()
+ {
+ base.OnAppearing();
+ Navigation.NavigationStack[0].BindingContext = null;
+ Navigation.RemovePage(Navigation.NavigationStack[0]);
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ internal sealed class MyPage3 : ContentPage
+ {
+ public MyPage3 ()
+ {
+ AutomationId = "PageThreeId";
+ Title = "PageThreeId";
+
+ var label = new Label { Text = "Page 3" };
+
+ Content = new StackLayout {
+ Children = {
+ label,
+ new Button {
+ AutomationId = "PopButton",
+ Text = "Try to Pop",
+ Command = new Command(
+ async() => {
+ await Navigation.PopAsync();
+ label.Text = "PopAttempted";
+ }
+ )}
+ }
+ };
+ }
+ }
+
+ protected override void Init ()
+ {
+ // Initialize ui here instead of ctor
+ Navigation.PushAsync (new MyPage () { Title="Navigation Stack" });
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla25979Test ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("PageOneId"));
+ RunningApp.Screenshot ("At page one");
+ RunningApp.WaitForElement (q => q.Marked ("PageOneButtonId"));
+ RunningApp.Tap (q => q.Marked ("PageOneButtonId"));
+
+ RunningApp.WaitForElement (q => q.Marked ("PageTwoId"));
+ RunningApp.Screenshot ("At page two - I didn't crash");
+ RunningApp.WaitForElement (q => q.Marked ("PageTwoButtonId"));
+ RunningApp.Tap (q => q.Marked ("PageTwoButtonId"));
+
+ RunningApp.WaitForElement (q => q.Marked ("PageThreeId"));
+ RunningApp.Screenshot ("At page three - I didn't crash");
+
+ RunningApp.WaitForElement (q => q.Marked ("PopButton"));
+ RunningApp.Tap (q => q.Marked ("PopButton"));
+ RunningApp.WaitForElement (q => q.Marked ("PopAttempted"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26032.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26032.xaml
new file mode 100644
index 00000000..748942a5
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26032.xaml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<local:TestContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Controls"
+ x:Class="Xamarin.Forms.Controls.Bugzilla26032">
+ <RelativeLayout>
+ <ListView x:Name="List1"
+ RelativeLayout.XConstraint="{ConstraintExpression Type=Constant, Constant=0}"
+ RelativeLayout.YConstraint="{ConstraintExpression Type=Constant, Constant=0}"
+ RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.5}"
+ RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.7}"
+
+ ItemTapped="OnItemTapped"
+ ItemSelected="OnItemSelected"
+ >
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <TextCell Text="{Binding}" />
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+
+ <ListView x:Name="List2"
+ RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.5}"
+ RelativeLayout.YConstraint="{ConstraintExpression Type=Constant, Constant=0}"
+ RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.5}"
+ RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.7}"
+
+ ItemTapped="OnItemTapped"
+ ItemSelected="OnItemSelected"
+ >
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <TextCell Text="{Binding}">
+ <TextCell.ContextActions>
+ <MenuItem Text="Delete" IsDestructive="True" />
+ </TextCell.ContextActions>
+ </TextCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+
+ <ScrollView
+ RelativeLayout.XConstraint="{ConstraintExpression Type=Constant, Constant=0}"
+ RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.7}"
+ RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width}"
+ RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.3}">
+ <Label x:Name="Log" />
+ </ScrollView>
+ </RelativeLayout>
+</local:TestContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26032.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26032.xaml.cs
new file mode 100644
index 00000000..e45e6bb3
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26032.xaml.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 26032, " ListView ItemTapped doesn't get called for the selected item ", PlatformAffected.iOS)]
+ public partial class Bugzilla26032 : TestContentPage
+ {
+ #if APP
+ public Bugzilla26032 ()
+ {
+
+ InitializeComponent ();
+ var data = new[] { "1", "2", "3", "4", "5" };
+ var dataContext = new[] { "1 Context", "2 Context", "3 Context", "4 Context", "5 Context" };
+ List1.ItemsSource = data;
+ List2.ItemsSource = dataContext;
+ }
+
+
+ public void OnItemTapped(object sender, ItemTappedEventArgs e)
+ {
+ Log.Text = string.Format("Item '{0}' tapped\n{1}", e.Item, Log.Text);
+ }
+
+ public void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
+ {
+ Log.Text = string.Format("Item '{0}' selected\n{1}", e.SelectedItem, Log.Text);
+ }
+
+ #endif
+
+ protected override void Init ()
+ {
+ }
+
+
+ #if UITEST
+ [Test]
+ public void SelectedItemTap ()
+ {
+ var id = "1";
+ var idContext = "1 Context";
+ var initalLog = "Item '{0}' tapped\nItem '{0}' selected\n";
+
+ var forId1 = string.Format (initalLog, id);
+ RunningApp.WaitForElement (q => q.Marked (id));
+ RunningApp.Tap (q => q.Marked (id));
+ RunningApp.WaitForElement (q => q.Text (forId1));
+ RunningApp.Tap (q => q.Marked (id));
+ forId1 = string.Format ( "Item '{0}' tapped\n" + initalLog, id);
+ RunningApp.WaitForElement (q => q.Text (forId1));
+
+ var forIdContext = string.Format (initalLog, idContext);
+ RunningApp.WaitForElement (q => q.Marked (idContext));
+ RunningApp.Tap (q => q.Marked (idContext));
+ RunningApp.WaitForElement (q => q.Text (forIdContext + forId1));
+ RunningApp.Tap (q => q.Marked (idContext));
+ forIdContext = string.Format ( "Item '{0}' tapped\n" + initalLog, idContext);
+ RunningApp.WaitForElement (q => q.Text (forIdContext + forId1));
+ }
+ #endif
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26171.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26171.cs
new file mode 100644
index 00000000..6ad49179
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26171.cs
@@ -0,0 +1,98 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Maps;
+using System.Threading.Tasks;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 26171, "Xamarin.Forms.Maps is not updating VisibleRegion property when layout is changed")]
+ public class Bugzilla26171 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ var map = MakeMap ();
+
+ var label = new Label { AutomationId = "lblValue" };
+
+ var buttonLayout = new Button { Text = "Change layout" };
+ buttonLayout.Clicked += async (a, e) => {
+ map.VerticalOptions = LayoutOptions.Start;
+ await Print (map,label);
+ };
+
+ var stack = new StackLayout {
+ Spacing = 0,
+ Padding = new Thickness (30, 0)
+ };
+
+ stack.Children.Add (label);
+ stack.Children.Add (map);
+ stack.Children.Add (buttonLayout);
+
+ Content = new ScrollView { Content = stack };
+
+ Appearing += async (sender, e) => await Print (map, label);
+
+ }
+
+ static async Task Print (Map map, Label label)
+ {
+ await Task.Delay(500);
+ if (map.VisibleRegion != null) {
+ label.Text = map.VisibleRegion.Radius.Kilometers.ToString ();
+ }
+ }
+
+ public static Map MakeMap ()
+ {
+ Pin colosseum = null;
+ Pin pantheon = null;
+ Pin chapel = null;
+
+ var map = new Map {
+ IsShowingUser = false,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HeightRequest = 100,
+ Pins = {
+ (colosseum = new Pin {
+ Type = PinType.Place,
+ Position = new Position (41.890202, 12.492049),
+ Label = "Colosseum",
+ Address = "Piazza del Colosseo, 00184 Rome, Province of Rome, Italy"
+ }),
+ (pantheon = new Pin {
+ Type = PinType.Place,
+ Position = new Position (41.898652, 12.476831),
+ Label = "Pantheon",
+ Address = "Piazza della Rotunda, 00186 Rome, Province of Rome, Italy"
+ }),
+ (chapel = new Pin {
+ Type = PinType.Place,
+ Position = new Position (41.903209, 12.454545),
+ Label = "Sistine Chapel",
+ Address = "Piazza della Rotunda, 00186 Rome, Province of Rome, Italy"
+ })
+ }
+ };
+
+ return map;
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla26171Test ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("lblValue"));
+ var value = RunningApp.Query (q => q.Marked ("lblValue")) [0].Text;
+ RunningApp.Screenshot ("I see the Label");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26233.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26233.cs
new file mode 100644
index 00000000..0a9f3fdc
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26233.cs
@@ -0,0 +1,56 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 26233, "Windows phone crashing when going back to page containing listview with Frame inside ViewCell")]
+ public class Bugzilla26233 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var listview = new ListView ();
+ listview.ItemTemplate = new DataTemplate (typeof (ItemTemplate));
+ listview.ItemsSource = new string[] { "item", "item", "item", "item", "item" };
+ var btnBack = new Button { Text = "back", Command = new Command (() => Navigation.PopAsync ()) };
+ listview.ItemSelected += (s, e) => Navigation.PushAsync (new ContentPage { Content = btnBack });
+ var btnPush = new Button {
+ Text = "Next",
+ AutomationId = "btnPush",
+ Command = new Command (() => Navigation.PushAsync (new ContentPage { Content = btnBack }))
+ };
+
+ Content = new StackLayout { Children = { btnPush, listview } };
+ }
+
+ [Preserve (AllMembers = true)]
+ internal class ItemTemplate : ViewCell
+ {
+ public ItemTemplate ()
+ {
+ var frame = new Frame ();
+ frame.Content = new StackLayout { Children = { new Label { Text = "hello 1" } } };
+ View = frame;
+ }
+ }
+
+#if UITEST
+ [Test]
+ public void DoesntCrashOnNavigatingBackToThePage ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("btnPush"));
+ RunningApp.Tap (q => q.Marked ("btnPush"));
+ RunningApp.WaitForElement (q => q.Marked ("back"));
+ RunningApp.Screenshot ("I see the back button");
+ RunningApp.Tap (q => q.Marked ("back"));
+ RunningApp.WaitForElement (q => q.Marked ("btnPush"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26501.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26501.cs
new file mode 100644
index 00000000..2ab31f0a
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26501.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers = true)]
+ public class FamilyViewModel
+ {
+ public Guid ProfileId { get; set; }
+ public string DisplayName { get; set; }
+ public string ImageFilename { get; set; }
+ public string BonusBalance { get; set; }
+ public string MemberNo { get; set; }
+
+ public FamilyViewModel ()
+ {
+ ProfileId = Guid.Empty;
+ DisplayName = "";
+ BonusBalance = "";
+ MemberNo = "";
+ ImageFilename = "";
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class FamilyCell : ViewCell
+ {
+ public Label FamilyLabel;
+
+ public FamilyCell ()
+ {
+ FamilyLabel = new Label ();
+
+ var l1 = new RelativeLayout ();
+
+ l1.Children.Add (FamilyLabel,
+ Constraint.Constant (50),
+ Constraint.Constant (4),
+ Constraint.RelativeToParent (p => p.Width - 10 - 50 - 85)
+ );
+
+
+ View = l1;
+
+ FamilyLabel.SetBinding (Label.TextProperty, "DisplayName");
+
+ // COMMENT LINE BELOW OUT TO MAKE IT WORK!
+ AddContextActions ();
+ }
+
+ void AddContextActions ()
+ {
+ ContextActions.Add (new MenuItem () {
+ Text = "Delete",
+ IsDestructive = true,
+ Command = new Command (Delete)
+ });
+
+ ContextActions.Add (new MenuItem () {
+ Text = "More",
+ IsDestructive = false,
+ Command = new Command (More)
+ });
+ }
+
+ void Delete ()
+ {
+ }
+
+ void More ()
+ {
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Bugzilla, 26501, "BindingSource / Context action issue", PlatformAffected.iOS)]
+ public class Bugzilla26501 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ //TODO: Multilanguage
+ Title = "Context Action Bug";
+
+ _familyListView = new ListView () {
+ RowHeight = 50,
+ ItemTemplate = new DataTemplate (typeof (FamilyCell)),
+ HasUnevenRows = true
+ };
+
+ //TODO: Multilanguage
+ ToolbarItems.Add (new ToolbarItem ("Refresh", "", () => {
+ _familyListView.ItemsSource = _demoDataSource2;
+ }));
+
+
+ _familyListView.ItemSelected += (sender, e) => _familyListView.SelectedItem = null;
+
+ Content = _familyListView;
+
+ UpdateData ();
+ }
+
+ readonly FamilyViewModel[] _demoDataSource = new FamilyViewModel[] {
+ new FamilyViewModel {DisplayName = "ZOOMER robothund"},
+ new FamilyViewModel {DisplayName = "FROST sengetj"},
+ new FamilyViewModel {DisplayName = "BEADOS Quick Dry designstation"},
+ new FamilyViewModel {DisplayName = "Redningsstation i junglen"},
+ };
+
+ readonly FamilyViewModel[] _demoDataSource2 = new FamilyViewModel[] {
+ new FamilyViewModel {DisplayName = "ZOOMER robothund"},
+ new FamilyViewModel {DisplayName = "FROST sengetj"},
+ new FamilyViewModel {DisplayName = "BEADOS Quick Dry designstation"},
+ new FamilyViewModel {DisplayName = "Redningsstation i junglen"},
+ new FamilyViewModel {DisplayName = "CHAMPIONS LEAGUE 2014/15 boosterpakke"},
+ new FamilyViewModel {DisplayName = "NEW BORN BABY luksusske med dukke"},
+ new FamilyViewModel {DisplayName = "FURBY Boom Festive Sweater elektronisk plysdyr"},
+ new FamilyViewModel {DisplayName = "LEGO FRIENDS 41007 Heartlake hundesalon"},
+ new FamilyViewModel {DisplayName = "LEGO CITY 4204 Minen"}
+ };
+
+ ListView _familyListView;
+
+ List<FamilyViewModel> _itemSource;
+
+ void UpdateData ()
+ {
+ Device.BeginInvokeOnMainThread (() => _familyListView.ItemsSource = _demoDataSource);
+ }
+
+#if UITEST
+ [Test]
+ public void TestCellsShowAfterRefresh ()
+ {
+ RunningApp.Tap (q => q.Marked ("Refresh"));
+
+ // make sure the refresh has completed
+ System.Threading.Thread.Sleep (1);
+
+ RunningApp.WaitForElement (q => q.Marked ("ZOOMER robothund"));
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26868.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26868.cs
new file mode 100644
index 00000000..ca744500
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26868.cs
@@ -0,0 +1,105 @@
+using System.Collections.Generic;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 26868, "GroupHeaders do not extend on Windows Phone")]
+ public class Bugzilla26868 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ List<GroupedData> groups = new List<GroupedData> ();
+
+ var group1 = new GroupedData { GroupName = "Group #1" };
+ group1.Add (new GroupItem { DisplayText = "Text for ListView item 1.1" });
+ group1.Add (new GroupItem { DisplayText = "Text for ListView item 1.2" });
+ groups.Add (group1);
+
+ var group2 = new GroupedData { GroupName = "Group #2" };
+ group2.Add (new GroupItem { DisplayText = "Text for ListVIew item 2.1" });
+ group2.Add (new GroupItem { DisplayText = "Text for ListView item 2.2" });
+ groups.Add (group2);
+
+ var itemTemplate = new DataTemplate(typeof(GroupItemTemplate));
+ itemTemplate.CreateContent();
+
+ var groupHeaderTemplate = new DataTemplate(typeof(GroupHeaderTemplate));
+ groupHeaderTemplate.CreateContent();
+
+ var listView = new ListView {
+ IsGroupingEnabled = true,
+ GroupDisplayBinding = new Binding ("GroupName"),
+ GroupShortNameBinding = new Binding ("GroupName"),
+ HasUnevenRows = Device.OnPlatform (Android: true, WinPhone: false, iOS: false),
+
+ ItemTemplate = itemTemplate,
+ GroupHeaderTemplate = groupHeaderTemplate,
+
+ ItemsSource = groups
+ };
+
+ Content = new StackLayout {
+ VerticalOptions = LayoutOptions.Center,
+ Children = {
+ new Label {
+ Text = "The group headers below should extend to the width of the screen. If they aren't the width of the screen, this test has failed."
+ },
+ new ContentView {
+ Content = listView,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Padding = 0
+ }
+ }
+ };
+ }
+
+ [Preserve (AllMembers = true)]
+ public class GroupItem
+ {
+ public string DisplayText { get; set; }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class GroupedData : List<GroupItem>
+ {
+ public string GroupName { get; set; }
+ }
+
+ [Preserve (AllMembers=true)]
+ public class GroupItemTemplate : ViewCell
+ {
+ public GroupItemTemplate()
+ {
+ var title = new Label() { FontSize = 14 };
+ title.SetBinding(Label.TextProperty, new Binding("DisplayText", BindingMode.OneWay));
+
+ View = new StackLayout
+ {
+ Orientation = StackOrientation.Horizontal,
+ Padding = new Thickness(8),
+ Children = { title }
+ };
+ }
+ }
+
+ [Preserve(AllMembers = true)]
+ public class GroupHeaderTemplate : ViewCell
+ {
+ public GroupHeaderTemplate()
+ {
+ var title = new Label { TextColor = Color.White, FontSize = 16 };
+ title.SetBinding(Label.TextProperty, new Binding("GroupName", BindingMode.OneWay));
+
+ View = new StackLayout
+ {
+ Padding = new Thickness(8, 0),
+ VerticalOptions = LayoutOptions.StartAndExpand,
+ BackgroundColor = Color.FromHex("#6D91BA"),
+ Orientation = StackOrientation.Horizontal,
+ Children = { title },
+ };
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26993.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26993.cs
new file mode 100644
index 00000000..765fbb12
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla26993.cs
@@ -0,0 +1,105 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.Generic;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 26993, "https://bugzilla.xamarin.com/show_bug.cgi?id=26993")]
+ public class Bugzilla26993 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ [Preserve (AllMembers = true)]
+ public class Bz26993ViewCell : ViewCell
+ {
+ static int s_id = 0;
+
+ public Bz26993ViewCell ()
+ {
+ View = new WebView {
+ AutomationId = "AutomationId" + s_id,
+ HeightRequest = 300,
+ Source = new HtmlWebViewSource {
+ Html = "<html><head><link rel=\"stylesheet\" href=\"default.css\"></head><body><h1 id=\"CellID" + s_id + "\">Xamarin.Forms " + s_id + "</h1><p>The CSS and image are loaded from local files!</p><img src='WebImages/XamarinLogo.png'/><p><a id=\"LinkID" + s_id++ + "\" href=\"local.html\">next page</a></p></body></html>"
+ }
+ };
+ }
+ }
+
+ protected override void Init ()
+ {
+ var itemSource = new List<string> {
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ };
+
+ Content = new StackLayout {
+ Children = {
+ new ListView {
+ RowHeight = 300,
+ ItemsSource = itemSource,
+ ItemTemplate = new DataTemplate (typeof(Bz26993ViewCell))
+ }
+ }
+ };
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla26993Test ()
+ {
+ RunningApp.Screenshot ("I am at BZ26993");
+
+ RunningApp.WaitForElement (q=>q.WebView(0).Css("#CellID0"));
+ RunningApp.Tap (q=>q.WebView(0).Css("#LinkID0"));
+
+ RunningApp.Screenshot ("Load local HTML");
+
+ RunningApp.WaitForNoElement (q=>q.WebView(0).Css("#LinkID0"));
+ var newElem = RunningApp.Query (q => q.WebView (0).Css ("h1"));
+ Assert.AreEqual ("#LocalHtmlPage", newElem[0].Id);
+
+ RunningApp.Screenshot ("I see the Label");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27085.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27085.cs
new file mode 100644
index 00000000..875d83b5
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27085.cs
@@ -0,0 +1,36 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Issue (IssueTracker.Bugzilla, 27085, "EntryCell has no possibility to hide keyboard on iOS")]
+ public class Bugzilla27085 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ var tableview = new TableView ();
+
+ var section = new TableSection ("Settings");
+ section.Add (new TextCell { Text = "TextCell" });
+ section.Add (new TextCell { Text = "TextCell" });
+ section.Add (new EntryCell { Text = "EntryCell", Keyboard = Keyboard.Numeric });
+ section.Add (new EntryCell { Text = "EntryCell", Keyboard = Keyboard.Numeric });
+ var root = new TableRoot ("Main");
+ root.Add (section);
+
+ tableview.Root = root;
+
+ Content = tableview;
+ }
+
+#if UITEST
+
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27318.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27318.xaml
new file mode 100644
index 00000000..ae1e9ba7
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27318.xaml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Bugzilla27318">
+ <StackLayout>
+ <ListView x:Name="listView" BackgroundColor="Red">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <StackLayout Spacing="0">
+ <Label Text="Fontsize 30 text"
+ BackgroundColor="Green"
+ FontSize="30" />
+ <Label Text="Small text overwritten"
+ BackgroundColor="Yellow"
+ HorizontalOptions="End" />
+ </StackLayout>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27318.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27318.xaml.cs
new file mode 100644
index 00000000..8bd04d09
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27318.xaml.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms.CustomAttributes;
+
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 27318, "Labels overlapping", PlatformAffected.Android, NavigationBehavior.PushAsync)]
+ public partial class Bugzilla27318 : ContentPage
+ {
+ public Bugzilla27318 ()
+ {
+ InitializeComponent ();
+ listView.ItemsSource = new [] { "Foo", "Bar", "Baz" };
+ }
+ }
+#endif
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27350.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27350.cs
new file mode 100644
index 00000000..e4899358
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27350.cs
@@ -0,0 +1,151 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.ComponentModel;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 27350, "Binding throws Null Pointer Exception when Updating Tab")]
+ public class Bugzilla27350 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ var btn = new Button { Text = "next main" };
+ btn.Clicked += async (object sender, EventArgs e) => await Navigation.PushAsync (new MainPage1 ());
+ Content = btn;
+ }
+
+ class RecipeViewModel
+ {
+ public Recipe Recipe { get; set; }
+
+ public ObservableCollection<RecipeGroup> RecipeGroups { get; set; }
+
+ public async Task LoadRecipesAsync ()
+ {
+ var groups = new ObservableCollection<RecipeGroup> ();
+ groups.Add (new RecipeGroup { Title = "Teste 1" });
+ groups.Add (new RecipeGroup { Title = "Teste 2" });
+ groups.Add (new RecipeGroup { Title = "Teste 3" });
+ groups.Add (new RecipeGroup { Title = "Teste 4" });
+ groups.Add (new RecipeGroup { Title = "Teste 5" });
+ groups.Add (new RecipeGroup { Title = "Teste 6" });
+ groups.Add (new RecipeGroup { Title = "Teste 4" });
+ groups.Add (new RecipeGroup { Title = "Teste 5" });
+ groups.Add (new RecipeGroup { Title = "Teste 6" });
+
+ RecipeGroups = groups;
+ }
+ }
+
+ class Recipe
+ {
+ public string ID { get; set; }
+
+ public string Title { get; set; }
+
+ public string Subtitle { get; set; }
+
+ public string Description { get; set; }
+
+ public string ImagePath { get; set; }
+
+ public string TileImagePath { get; set; }
+
+ public int PrepTime { get; set; }
+
+ public string Directions { get; set; }
+
+ public List<string> Ingredients { get; set; }
+ }
+
+ class RecipeGroup : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ void OnPropertyChanged (string caller)
+ {
+ var handler = PropertyChanged;
+ if (handler != null) {
+ handler (this, new PropertyChangedEventArgs (caller));
+ }
+ }
+
+ public string ID { get; set; }
+
+ public string Title {
+ get{ return _title; }
+ set {
+ _title = value;
+ OnPropertyChanged ("Title");
+ }
+ }
+
+ string _title;
+
+ public string Subtitle { get; set; }
+
+ public string ImagePath { get; set; }
+
+ public string GroupImagePath { get; set; }
+
+ public string Description { get; set; }
+
+ public List<Recipe> Recipes { get; set; }
+ }
+
+ class MainPage1 : TabbedPage
+ {
+ public MainPage1 ()
+ {
+ ItemTemplate = new DataTemplate (() => {
+ var page = new ContentPage ();
+ page.SetBinding (TitleProperty, new Binding ("Title"));
+ var btn = new Button { Text = "change", Command = new Command (() => {
+ (page.BindingContext as RecipeGroup).Title = "we changed";
+ })
+ };
+ var btn1 = new Button { Text = "null", Command = new Command (() => {
+ (page.BindingContext as RecipeGroup).Title = null;
+ })
+ };
+ page.Content = new StackLayout { Children = { btn, btn1 } };
+ return page;
+ });
+ SetBinding (ItemsSourceProperty, new Binding ("RecipeGroups"));
+ }
+
+ protected override async void OnAppearing ()
+ {
+ base.OnAppearing ();
+
+ if (BindingContext == null)
+ BindingContext = await GetRecipeViewModelAsync ();
+ }
+
+ RecipeViewModel _rvm;
+
+ public async Task<RecipeViewModel> GetRecipeViewModelAsync ()
+ {
+ if (_rvm == null) {
+ _rvm = new RecipeViewModel ();
+ } else {
+ _rvm.RecipeGroups.Clear ();
+ }
+
+ await _rvm.LoadRecipesAsync ();
+
+ return _rvm;
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27378.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27378.cs
new file mode 100644
index 00000000..7d47e488
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27378.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 27378, "Navigation.InsertPageBefore causes AurgumentException only on Windows Phone", PlatformAffected.WinPhone, NavigationBehavior.PushModalAsync)]
+ public class Bugzilla27378
+ : NavigationPage
+ {
+ public Bugzilla27378()
+ {
+ ContentPage page = null;
+ page = new ContentPage {
+ Content = new Button {
+ Text = "Click",
+ Command = new Command (async () => {
+ Navigation.InsertPageBefore (new ContentPage {
+ Content = new Label {
+ Text = "Second page"
+ }
+ }, page);
+ await Navigation.PopAsync ();
+ })
+ }
+ };
+
+ PushAsync (page);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27581.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27581.cs
new file mode 100644
index 00000000..511e9860
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27581.cs
@@ -0,0 +1,29 @@
+using System;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Bugzilla, 27581, "WebView in ContentPage", PlatformAffected.Android)]
+ public class Bugzilla27581 : ContentPage
+ {
+ public Bugzilla27581 ()
+ {
+ Content = new StackLayout {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Children = {
+ new Label {
+ XAlign = TextAlignment.Center,
+ Text = "Tap input field, then try to scroll"
+ },
+ new WebView {
+ Source = "http://movinglabs.com/temp/xamarin/input.html",
+ VerticalOptions = LayoutOptions.FillAndExpand
+ }
+ }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27642.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27642.cs
new file mode 100644
index 00000000..ec2c203e
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27642.cs
@@ -0,0 +1,178 @@
+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 +++ ");
+
+ var label = new Label { Text = sb.ToString (), HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, XAlign = TextAlignment.Center, };
+
+ 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 +++++ ");
+
+ var label = new Label { Text = sb.ToString (), HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, XAlign = TextAlignment.Center, };
+
+ scrollView.Content = label;
+
+ Content = scrollView;
+
+ }
+ }
+
+ public class View2 : ExtendedContentView
+ {
+ public View2 ()
+ {
+ BackgroundColor = Color.Teal;
+ Content = new Label { Text = "View 2", HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, XAlign = TextAlignment.Center, };
+ }
+ }
+
+ [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);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27698.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27698.cs
new file mode 100644
index 00000000..08122826
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27698.cs
@@ -0,0 +1,53 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Issue (IssueTracker.Bugzilla, 27698, "[iOS] DisplayAlert and DisplayActionSheet are shown below master page ")]
+ public class Bugzilla27698 : TestMasterDetailPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+
+ var showAlertBtn = new Button { Text = "DisplayAlert" };
+ var showActionSheetBtn = new Button { Text = "DisplayActionSheet" };
+
+ var master = new ContentPage
+ {
+ Title = "Master",
+ Content = new StackLayout
+ {
+ VerticalOptions = LayoutOptions.Center,
+ Children = {
+ showAlertBtn,
+ showActionSheetBtn
+ }
+ }
+ };
+
+ Master = master;
+
+ MasterBehavior = MasterBehavior.Popover;
+
+ Detail = new ContentPage {
+ Content = new Label { Text = "Details", HorizontalOptions =
+ LayoutOptions.Center, VerticalOptions = LayoutOptions.Center
+ }
+ };
+
+ showAlertBtn.Clicked += (s, e) => DisplayAlert("Title","Message", "Cancel");
+ showActionSheetBtn.Clicked += (s, e) => DisplayActionSheet ("Title", "Cancel", null, "Button1", "Button2", "Button3");
+
+ }
+
+#if UITEST
+
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27779.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27779.cs
new file mode 100644
index 00000000..271c4b05
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla27779.cs
@@ -0,0 +1,83 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.Generic;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 27779, "Xamarin.Forms.ReadOnlyListAdapter.IndexOf throws NotImplementedExcpetion ")]
+ public class Bugzilla27779 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ ListView _listview;
+ IReadOnlyList<Person> _itemsSource;
+
+ public class Source : IReadOnlyList<Person>
+ {
+ List<Person> _items;
+ public Source ()
+ {
+ _items = new List<Person> ();
+
+ for (int i = 0; i < 100; i++) {
+ _items.Add (new Person ("Person #" + i));
+ }
+
+ }
+ #region IEnumerable implementation
+ public IEnumerator<Person> GetEnumerator ()
+ {
+ return _items.GetEnumerator ();
+ }
+ #endregion
+ #region IEnumerable implementation
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
+ {
+ return _items.GetEnumerator ();
+ }
+ #endregion
+ #region IReadOnlyList implementation
+ public Person this [int index] {
+ get {
+ return _items [index];
+ }
+ }
+ #endregion
+ #region IReadOnlyCollection implementation
+ public int Count {
+ get {
+ return _items.Count;
+ }
+ }
+ #endregion
+
+ }
+ protected override void Init ()
+ {
+
+ _itemsSource = new Source();
+
+ _listview = new ListView {
+ ItemsSource = _itemsSource
+ };
+
+ var btn = new Button { Text = "Set selected", AutomationId="btnSelect" };
+ btn.Clicked+= (object sender, EventArgs e) => {
+ _listview.SelectedItem = _itemsSource [0];
+ };
+
+ Content = new StackLayout { Children = { btn, _listview } };
+ }
+
+ protected override void OnAppearing ()
+ {
+ base.OnAppearing ();
+ }
+
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28001.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28001.cs
new file mode 100644
index 00000000..e73bc0dd
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28001.cs
@@ -0,0 +1,60 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 28001, "[Android] TabbedPage: invisible tabs are not Disposed", PlatformAffected.Android)]
+ public class Bugzilla28001 : TestContentPage
+ {
+ static int s_disposeCount;
+ static Label s_lbl;
+
+ void HandleDispose (object sender, EventArgs e)
+ {
+ s_disposeCount++;
+ s_lbl.Text = string.Format ("Dispose {0} pages", s_disposeCount);
+ }
+
+ protected override void Init ()
+ {
+ s_lbl = new Label { AutomationId = "lblDisposedCound" };
+ var tab1 = new DisposePage { Title = "Tab1" };
+ var tab2 = new DisposePage { Title = "Tab2" };
+ tab1.RendererDisposed += HandleDispose;
+ tab2.RendererDisposed += HandleDispose;
+
+ tab2.PopAction = tab1.PopAction = async () => await Navigation.PopAsync ();
+
+ var tabbedPage = new TabbedPage { Children = { tab1, tab2 } };
+ var btm = new Button { Text = "Push" };
+
+ btm.Clicked += async (object sender, EventArgs e) => {
+ await Navigation.PushAsync (tabbedPage);
+ };
+
+ Content = new StackLayout { Children = { btm, s_lbl } };
+ }
+
+
+ #if UITEST
+ [Test]
+ public void Bugzilla28001Test ()
+ {
+ RunningApp.Screenshot ("I am at Bugzilla 28001");
+ RunningApp.Tap (q => q.Marked ("Push"));
+ RunningApp.Tap (q => q.Marked ("Tab2"));
+ RunningApp.Tap (q => q.Marked ("Tab1"));
+ RunningApp.Tap (q => q.Marked ("Pop"));
+ RunningApp.WaitForElement (q => q.Marked (string.Format ("Dispose {0} pages", 2)));
+
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28240.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28240.cs
new file mode 100644
index 00000000..f2bf078a
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28240.cs
@@ -0,0 +1,38 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 28240, "Problems with a NavigationPage as Master+Detail of a MasterDetailPage", PlatformAffected.Android)]
+ public class Bugzilla28240 : TestMasterDetailPage
+ {
+ protected override void Init ()
+ {
+ Detail = new NavigationPage( new ContentPage { Title = "DetailPage", BackgroundColor = Color.Red });
+ Master = new NavigationPage( new ContentPage { Title = "MasterPage", BackgroundColor = Color.Blue }) { Title =" Master" };
+ }
+
+ protected override async void OnAppearing ()
+ {
+ var btn = new Button () { Text = "GO Back" };
+ btn.Clicked+= async (object sender, EventArgs e) => await (Master as NavigationPage).PopAsync ();
+
+ await (Master as NavigationPage).PushAsync (new ContentPage { Title = "New MasterPage", Content = btn , BackgroundColor = Color.Pink });
+ base.OnAppearing ();
+ }
+#if UITEST
+ [Test]
+ public void Bugzilla28240Test ()
+ {
+
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28498.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28498.cs
new file mode 100644
index 00000000..3f5f5abc
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28498.cs
@@ -0,0 +1,78 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 28498, "App crashes when switching between NavigationPages on a MasterDetailPage when In-Call Status Bar is visible")]
+ public class Bugzilla28498 : TestMasterDetailPage
+ {
+ protected override void Init ()
+ {
+
+
+ var carrouselChildPage = new ContentPage { Content = new StackLayout {
+ Orientation = StackOrientation.Vertical,
+ Children = {
+ new Label { Text = "Carousel Page" },
+ new Button { Text = "Open", AutomationId="btnOpen", Command = new Command (() => IsPresented = true) },
+ },
+ Padding = 10
+ }
+ };
+
+ var otherPage = new ContentPage { Content = new StackLayout {
+ Orientation = StackOrientation.Vertical,
+ Children = {
+ new Label { Text = "Other" },
+ new Button { Text = "Open", AutomationId="btnOpen", Command = new Command (() => IsPresented = true) },
+ },
+ Padding = 10
+ }
+ };
+
+ var carousel = new NavigationPage(new CarouselPage { Children = { carrouselChildPage } });
+ var other = new NavigationPage(otherPage);
+ Detail = carousel;
+
+ Master = new ContentPage
+ {
+ Title = "Menu",
+ Content = new StackLayout
+ {
+ Orientation = StackOrientation.Vertical,
+ Children = {
+ new Button { Text = "Page 1 (Carousel)", AutomationId="btnCarousel", Command = new Command(() => Detail = carousel) },
+ new Button { Text = "Page 2 (Other)", AutomationId="btnOther", Command = new Command(() => Detail = other) },
+ },
+ Padding = 10
+ }
+ };
+
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla28498Test ()
+ {
+ RunningApp.SetOrientationPortrait ();
+ RunningApp.Tap (q => q.Marked ("btnOpen"));
+ RunningApp.Tap (q => q.Marked ("btnOther"));
+ RunningApp.SetOrientationLandscape ();
+ RunningApp.Tap (q => q.Marked ("btnOpen"));
+ RunningApp.Screenshot ("Detail open");
+
+ if (RunningApp.Query (c => c.Marked ("btnCarousel")).Length > 0)
+ Assert.DoesNotThrow (() => RunningApp.Tap (q => q.Marked ("btnCarousel")));
+ else
+ Assert.Inconclusive ("Should be button here, but rotation could take some time on XTC");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28570.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28570.cs
new file mode 100644
index 00000000..5e9a8cb8
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28570.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Diagnostics;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest.Android;
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 28570, "https://bugzilla.xamarin.com/show_bug.cgi?id=28570")]
+ internal class Bugzilla28570 : TestContentPage
+ {
+ public ScrollView ScrollView;
+
+ protected override void Init ()
+ {
+ Label header = new Label {
+ Text = "ScrollView Bug",
+ FontSize = 50,
+ FontAttributes = FontAttributes.Bold,
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ Label lab1 = new Label ();
+ lab1.Text = "Sometimes page content fits entirely on " +
+ "the page. That's very convenient. But " +
+ "on many occasions, the content of the page " +
+ "is much too large for the page, or only " +
+ "becomes available at runtime." +
+ "\n\n" +
+ "For cases such as these, the ScrollView " +
+ "provides a solution. Simply set its " +
+ "Content property to your content \u2014 in this " +
+ "case a Label but in the general case very " +
+ "likely a Layout derivative with multiple " +
+ "children \u2014 and the ScrollView provides " +
+ "scrolling with the distinctive look and touch " +
+ "familiar to the user." +
+ "\n\n" +
+ "The ScrollView is also capable of " +
+ "horizontal scrolling, and while that's " +
+ "usually not as common as vertical scrolling, " +
+ "sometimes it comes in handy." +
+ "\n\n" +
+ "Most often, the content of a ScrollView is " +
+ "a StackLayout. Whenever you're using a " +
+ "StackLayout with a number of items determined " +
+ "only at runtime, you should probably put it in " +
+ "a StackLayout just to be sure your stuff doesn't " +
+ "go running off the bottom of the screen." +
+ "Most often, the content of a ScrollView is " +
+ "a StackLayout. Whenever you're using a " +
+ "StackLayout with a number of items determined " +
+ "only at runtime, you should probably put it in " +
+ "a StackLayout just to be sure your stuff doesn't " +
+ "go running off the bottom of the screen.";
+
+ var targetLabel = new Label {Text = "Find Me"};
+ targetLabel.AutomationId = "28570Target";
+
+ lab1.FontSize = Device.GetNamedSize (NamedSize.Small, typeof (Label));
+
+
+ ScrollView = new ScrollView {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Content = new StackLayout {
+ Children = {
+ lab1,
+ targetLabel
+ }
+ }
+ };
+
+ Button makeBig = new Button ();
+ makeBig.Text = "Tap";
+ //
+ // Clicking button first time does not scroll event though scrollView.Height is already set.
+ // Clicking a second time does correctly scroll to the end. scrollView.Height is unchanged.
+ //
+ // For this test to work you should make sure the text fits into the screen when the font is small
+ // and then becomes larger than the screeen when switching to the Large font.
+ //
+ makeBig.Clicked += (object sender, EventArgs e) => {
+ lab1.FontSize = Device.GetNamedSize (NamedSize.Large, typeof (Label));
+ Debug.WriteLine ("******** scrollView.Height= {0}", lab1.Height); // this shows the same updated size on all clicks, so this is not the problem.
+ ScrollView.ScrollToAsync (0, lab1.Bounds.Bottom, false);
+ };
+
+ // Build the page.
+ Content = new StackLayout {
+ Children = {
+ makeBig,
+ header,
+ ScrollView,
+ }
+ };
+ }
+
+#if UITEST
+ [Test]
+ [Ignore("Fails intermittently on TestCloud")]
+ public void Bugzilla28570Test ()
+ {
+ if (RunningApp is AndroidApp) {
+ RunningApp.WaitForElement (q => q.Marked ("Tap"));
+ RunningApp.Screenshot ("At test page");
+ RunningApp.Tap (q => q.Marked ("Tap"));
+
+ RunningApp.WaitForElement (q => q.Marked ("28570Target"));
+ }
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28575.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28575.cs
new file mode 100644
index 00000000..665dec2d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28575.cs
@@ -0,0 +1,53 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 28575, "listview header set to null")]
+ public class Bugzilla28575 : TestContentPage
+ {
+ readonly string _header = "Hello I am Header!!!!";
+
+ protected override void Init ()
+ {
+ var listview = new ListView ();
+ listview.Header = new Label () {
+ Text = _header,
+ TextColor = Color.Red,
+ XAlign = TextAlignment.Center
+ };
+
+ var b = new Button () {
+ Text = "Click",
+ AutomationId = "btnClick"
+
+ };
+ b.Clicked += (sender, e) => listview.Header = null;
+
+ Content = new StackLayout {
+ Children = {
+ b,
+ listview
+ }
+ };
+ }
+
+ #if UITEST
+ [Test]
+ public void Bugzilla28575Test ()
+ {
+ RunningApp.Screenshot ("I am at Bugzilla28575Test ");
+ RunningApp.WaitForElement (q => q.Marked (_header));
+ RunningApp.Tap (q => q.Marked ("Click"));
+ RunningApp.WaitForNoElement (q => q.Marked (_header));
+ }
+ #endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28709.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28709.cs
new file mode 100644
index 00000000..db67e935
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28709.cs
@@ -0,0 +1,94 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Threading.Tasks;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 28709, "Application.Properties saving crash ")]
+ public class Bugzilla28709 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+
+ var btn = new Button () {
+ Text = "Save Properties",
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.Center
+ };
+
+ var btn1 = new Button () {
+ Text = "Save Properties Multiple Threads",
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.Center
+ };
+ btn.Clicked += OnButtonClicked;
+ btn1.Clicked += (sender, e) => {
+ Task.Run(() => {System.Diagnostics.Debug.WriteLine ("thread 1"); OnButtonClicked1("thread1",new EventArgs());});
+ Task.Run(() => {System.Diagnostics.Debug.WriteLine ("thread 2"); OnButtonClicked1("thread2",new EventArgs());});
+ Task.Run(() => {System.Diagnostics.Debug.WriteLine ("thread 3"); OnButtonClicked1("thread3",new EventArgs());});
+
+ };
+ Content = new StackLayout { Children = { btn, btn1 }};
+ }
+
+ void OnButtonClicked (object sender, EventArgs e)
+ {
+ System.Diagnostics.Debug.WriteLine ($"OnButtonClicked {sender.ToString()}");
+
+ int j = -1;
+ var properties = Application.Current.Properties;
+ int seed = 13;
+ while (++j < 300) {
+ seed = ((seed * 257) + 41) % 65536;
+ int i = seed % 20;
+
+ int previousClickTotal = -1;
+ if (properties.ContainsKey ("PreviousClickTotal" + i.ToString ()))
+ previousClickTotal = (int)(Application.Current.Properties ["PreviousClickTotal" + i.ToString ()]);
+
+ string clickTotal = "0";
+ if (properties.ContainsKey ("ClickTotal" + i.ToString ()))
+ clickTotal = (string)Application.Current.Properties ["ClickTotal" + i.ToString ()];
+
+ double nextClickTotal = 1.0;
+ if (properties.ContainsKey ("NextClickTotal" + i.ToString ()))
+ nextClickTotal = (double)(Application.Current.Properties ["NextClickTotal" + i.ToString ()]);
+
+ Application.Current.Properties ["PreviousClickTotal" + i.ToString ()] = ++previousClickTotal;
+ Application.Current.Properties ["ClickTotal" + i.ToString ()] = previousClickTotal.ToString ();
+ Application.Current.Properties ["NextClickTotal" + i.ToString ()] = ++nextClickTotal;
+
+ SaveAllProperties ();
+ }
+ }
+
+ async void OnButtonClicked1 (object sender, EventArgs e)
+ {
+ System.Diagnostics.Debug.WriteLine ($"OnButtonClicked {sender.ToString()}");
+ //Application.Current.Properties[sender.ToString()] = 1;
+ await Application.Current.SavePropertiesAsync ();
+ System.Diagnostics.Debug.WriteLine ($"OnButtonClicked {sender.ToString()} done");
+ }
+
+ async void SaveAllProperties ()
+ {
+ await Application.Current.SavePropertiesAsync ();
+ }
+
+
+ #if UITEST
+ [Test]
+ public void Bugzilla28709Test ()
+ {
+ RunningApp.Tap (q => q.Marked ("Save Properties"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28796.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28796.cs
new file mode 100644
index 00000000..98938d77
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28796.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 28796, "Crash on Tab change", PlatformAffected.Android, NavigationBehavior.PushModalAsync)]
+ public class Bugzilla28796
+ : TabbedPage
+ {
+ public Bugzilla28796()
+ {
+ Children.Add (new ContentPage {
+ Title = "First",
+ Content = new Label {
+ Text = "Select the second tab. Click the button and before it finishes animating, select the first tab."
+ }
+ });
+
+ var button = new Button {
+ Text = "Navigate"
+ };
+ button.Clicked += (sender, args) => {
+ Navigation.PushModalAsync (new ContentPage());
+ };
+
+ Children.Add (new ContentPage {
+ Title = "Second",
+ Content = button
+ });
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28939.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28939.cs
new file mode 100644
index 00000000..c216f23d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla28939.cs
@@ -0,0 +1,21 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Issue (IssueTracker.Bugzilla, 28939, " Entry Control loses cursor position to either beginning or end of input ",
+ PlatformAffected.WinPhone)]
+ public class Bugzilla28939 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Content = new StackLayout {
+ Children = {
+ new Label {
+ Text = @"Enter the text ""testing"" in the Entry Control below. Move the cursor between the 'e' and the 's'. Type the letter 'a'. If the cursor is positioned after the 'a', the test has passed."
+ },
+ new Entry()
+ }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29017.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29017.cs
new file mode 100644
index 00000000..eea9295d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29017.cs
@@ -0,0 +1,82 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Maps;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Issue (IssueTracker.Bugzilla, 29017, "Pin clicked does not work on iOS maps")]
+ public class Issue29017 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ Label _lbl;
+
+ protected override void Init ()
+ {
+ var map = new Map {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand
+ };
+
+ _lbl = new Label {
+ Text = "Not Clicked"
+ };
+
+ Content = new StackLayout {
+ Children = {
+ new Button {
+ Text = "Add pins",
+ Command = new Command (() => {
+
+ foreach (var pin in map.Pins) {
+ pin.Clicked -= PinClicked;
+ }
+
+ map.Pins.Clear ();
+
+ for (int i = 0; i < 100; i++) {
+ var rnd = new Random ();
+ var lat = rnd.NextDouble () / 10;
+ var lng = rnd.NextDouble () / 10;
+
+ if (i % 2 == 0) {
+ lat = -lat;
+ lng = -lng;
+ }
+
+ var pin = new Pin {
+ Address = "address",
+ Label = "label",
+ Type = PinType.Place,
+ Position = new Position (map.VisibleRegion.Center.Latitude + lat, map.VisibleRegion.Center.Longitude + lng)
+ };
+
+ pin.Clicked += PinClicked;
+ map.Pins.Add (pin);
+ }
+ })
+ },
+ _lbl,
+ map
+ }
+ };
+ }
+
+ void PinClicked (object sender, EventArgs e)
+ {
+ _lbl.Text = "Click " + DateTime.Now.ToLocalTime ();
+ }
+
+#if UITEST
+ [Test]
+ public void Issue1Test ()
+ {
+
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29107.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29107.xaml
new file mode 100644
index 00000000..de0f96d7
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29107.xaml
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<local:TestContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Controls"
+ x:Class="Xamarin.Forms.Controls.Bugzilla29107">
+ <StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" Padding="20">
+ <Frame OutlineColor="Gray" Padding="5">
+ <Label Text="" VerticalOptions="End" HorizontalOptions="Start" />
+ </Frame>
+ <StackLayout HorizontalOptions="FillAndExpand" Orientation="Horizontal">
+ <Label Text=" State:" HorizontalOptions="Start">
+ <Label.Font>
+ Bold,Large
+ </Label.Font>
+ </Label>
+ <Label Text="Test State" HorizontalOptions="Start">
+ <Label.Font>
+ Bold,Large
+ </Label.Font>
+ </Label>
+ </StackLayout>
+ <StackLayout HorizontalOptions="FillAndExpand" Orientation="Horizontal">
+ <ScrollView Orientation="Vertical" IsClippedToBounds="true">
+ <StackLayout HorizontalOptions="FillAndExpand">
+ <Label Text="Parameter1" HorizontalOptions="FillAndExpand" />
+ <Picker x:Name="pickerParam1" Title="Prameter1">
+ </Picker>
+ <StackLayout x:Name="layoutParam1" HorizontalOptions="FillAndExpand">
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ </StackLayout>
+ </StackLayout>
+ </ScrollView>
+ <ScrollView Orientation="Vertical" IsClippedToBounds="true">
+ <StackLayout HorizontalOptions="FillAndExpand">
+ <Label Text="Parameter2" HorizontalOptions="FillAndExpand" />
+ <Picker x:Name="pickerParam2" Title="Parameter2">
+ </Picker>
+ <StackLayout x:Name="layoutParam2" HorizontalOptions="FillAndExpand">
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ <Label Text="Entry" HorizontalOptions="FillAndExpand">
+ </Label>
+ <Entry HorizontalOptions="FillAndExpand">
+ </Entry>
+ </StackLayout>
+ </StackLayout>
+ </ScrollView>
+ <Grid HorizontalOptions="Start" Padding="2" VerticalOptions="FillAndExpand">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="200" />
+ <ColumnDefinition Width="200" />
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="20">
+ </RowDefinition>
+ <RowDefinition Height="20">
+ </RowDefinition>
+ <RowDefinition Height="20">
+ </RowDefinition>
+ <RowDefinition Height="20">
+ </RowDefinition>
+ <RowDefinition Height="20">
+ </RowDefinition>
+ <RowDefinition Height="20">
+ </RowDefinition>
+ <RowDefinition Height="20">
+ </RowDefinition>
+ <RowDefinition Height="20">
+ </RowDefinition>
+ </Grid.RowDefinitions>
+ <Label Text="Field" Grid.Row="0" Grid.Column="0">
+ <Label.Font>
+ Bold,Large
+ </Label.Font>
+ </Label>
+ <Label Text="Field" Grid.Row="0" Grid.Column="1">
+ <Label.Font>
+ Bold,Large
+ </Label.Font>
+ </Label>
+ <Label Text="Field" Grid.Row="1" Grid.Column="0">
+ <Label.Font>
+ Bold,Medium
+ </Label.Font>
+ </Label>
+ <Label Text="Field" Grid.Row="1" Grid.Column="1">
+ </Label>
+ <Label Text="Field" Grid.Row="2" Grid.Column="0">
+ <Label.Font>
+ Bold,Medium
+ </Label.Font>
+ </Label>
+ <Label Text="Field" Grid.Row="2" Grid.Column="1">
+ </Label>
+ <Label Text="Field" Grid.Row="3" Grid.Column="0">
+ <Label.Font>
+ Bold,Medium
+ </Label.Font>
+ </Label>
+ <Label Text="Field" Grid.Row="3" Grid.Column="1">
+ </Label>
+ <Label Text="Field" Grid.Row="4" Grid.Column="0">
+ <Label.Font>
+ Bold,Medium
+ </Label.Font>
+ </Label>
+ <Label Text="Field" Grid.Row="4" Grid.Column="1">
+ </Label>
+ <Label Text="Field" Grid.Row="5" Grid.Column="0">
+ <Label.Font>
+ Bold,Medium
+ </Label.Font>
+ </Label>
+ <Label Text="Field" Grid.Row="5" Grid.Column="1">
+ </Label>
+ <Label Text="Field" Grid.Row="6" Grid.Column="0">
+ <Label.Font>
+ Bold,Medium
+ </Label.Font>
+ </Label>
+ <Label Text="Field" Grid.Row="6" Grid.Column="1">
+ </Label>
+ <Label Text="Field" Grid.Row="7" Grid.Column="0">
+ <Label.Font>
+ Bold,Medium
+ </Label.Font>
+ </Label>
+ <Label Text="Field" Grid.Row="7" Grid.Column="1">
+ </Label>
+ <Label Text="Field" Grid.Row="8" Grid.Column="0">
+ <Label.Font>
+ Bold,Medium
+ </Label.Font>
+ </Label>
+ <Label Text="Field" Grid.Row="8" Grid.Column="1">
+ </Label>
+ </Grid>
+ </StackLayout>
+ <StackLayout HorizontalOptions="FillAndExpand" Orientation="Horizontal">
+ <Button Text="Start">
+ </Button>
+ <Button Text="Cancel">
+ </Button>
+ <Button Text="End">
+ </Button>
+ </StackLayout>
+ </StackLayout>
+</local:TestContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29107.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29107.xaml.cs
new file mode 100644
index 00000000..d7a7ddca
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29107.xaml.cs
@@ -0,0 +1,22 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 29107, "Xamarin.Android ScrollView text overlaps", PlatformAffected.Android)]
+ public partial class Bugzilla29107 : TestContentPage
+ {
+ public Bugzilla29107 ()
+ {
+#if APP
+ InitializeComponent ();
+#endif
+ }
+
+ protected override void Init ()
+ {
+
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29128.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29128.cs
new file mode 100644
index 00000000..c414e49e
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29128.cs
@@ -0,0 +1,36 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 29128, "Slider background lays out wrong Android")]
+ public class Bugzilla29128 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Content = new Slider {
+ AutomationId = "SliderId",
+ BackgroundColor = Color.Blue,
+ Maximum = 255,
+ Minimum = 0,
+ };
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla29128Test ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("SliderId"));
+ RunningApp.Screenshot("Slider and button should be centered");
+ Assert.Inconclusive ("For visual review only");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29158.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29158.cs
new file mode 100644
index 00000000..f755348b
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29158.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 29158, "XF for WP8.1RT - BeginInvokeOnMainThread generates NullReferenceException", (PlatformAffected)(1<<3))]
+ public class Bugzilla29158
+ : ContentPage
+ {
+ protected override void OnAppearing()
+ {
+ base.OnAppearing();
+
+ System.Threading.Tasks.Task.Run (async () =>
+ {
+ await System.Threading.Tasks.Task.Delay (1000);
+ Device.BeginInvokeOnMainThread (() => DisplayAlert("Time's up", "", "OK"));
+ });
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29229.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29229.cs
new file mode 100644
index 00000000..059c2110
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29229.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+ [Issue (IssueTracker.Bugzilla, 29229, "ListView crash on Windows Phone", PlatformAffected.WinPhone, NavigationBehavior.PushModalAsync)]
+ public class Bugzilla29229
+ : NavigationPage
+ {
+ public Bugzilla29229()
+ {
+ var absLayout = new AbsoluteLayout();
+ absLayout.BackgroundColor = Color.Red;
+ absLayout.Scale = 1;
+
+ var cPx = new ListView ();
+ Point ptx = Point.Zero;
+ cPx.ItemTapped += delegate (object sender, ItemTappedEventArgs e) {
+ };
+ cPx.ClassId = "weather";
+ cPx.Layout (new Rectangle (0,0,480,768));
+ absLayout.Children.Add (cPx, new Rectangle (cPx.X, cPx.Y, cPx.Width, cPx.Height), AbsoluteLayoutFlags.None);
+ absLayout.LowerChild (cPx);
+ PushAsync (new ContentPage { Content = absLayout });
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29247.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29247.cs
new file mode 100644
index 00000000..74828e71
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29247.cs
@@ -0,0 +1,67 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 29247, "iOS Device.OpenUri breaks with encoded params", PlatformAffected.iOS )]
+ public class Bugzilla29247 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Content = new StackLayout {
+ VerticalOptions = LayoutOptions.Center,
+ Children = {
+ new Label {
+ XAlign = TextAlignment.Center,
+ Text = "Welcome to Xamarin Forms!"
+ },
+ new Button {
+ Text = "Without Params (Works)",
+ AutomationId = "btnOpenUri1",
+ Command = new Command (() => Device.OpenUri (new Uri ("http://www.bing.com")))
+ },
+ new Button {
+ Text = "With encoded Params (Breaks)",
+ AutomationId = "btnOpenUri2",
+ Command = new Command (() => Device.OpenUri (new Uri ("http://www.bing.com/search?q=xamarin%20bombs%20on%20this")))
+ },
+ new Button {
+ Text = "With decoded Params (Breaks)",
+ AutomationId = "btnOpenUri3",
+ Command = new Command (() => Device.OpenUri (new Uri ("http://www.bing.com/search?q=xamarin bombs on this")))
+ }
+ }
+ };
+ }
+
+ #if UITEST
+ [Test]
+ [Ignore("Fails on ios 7.1")]
+ public void Bugzilla29247Test ()
+ {
+ RunningApp.Tap (q => q.Marked ("btnOpenUri1"));
+ }
+
+ [Test]
+ [Ignore("Fails on ios 7.1")]
+ public void Bugzilla29247EncodedParamsTest ()
+ {
+ RunningApp.Tap (q => q.Marked ("btnOpenUri2"));
+ }
+
+ [Test]
+ [Ignore("Fails on ios 7.1")]
+ public void Bugzilla29247DecodeParamsTest ()
+ {
+ RunningApp.Tap (q => q.Marked ("btnOpenUri3"));
+ }
+ #endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29257.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29257.cs
new file mode 100644
index 00000000..012ed59e
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29257.cs
@@ -0,0 +1,100 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.Generic;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 29257, "CarouselPage.CurrentPage Does Not Work Properly When Used Inside a NavigationPage ")]
+ public class Bugzilla29257 : TestContentPage
+ {
+ List<string> _menuItems = new List<string> {
+ "Page 1", "Page 2", "Page 3", "Page 4", "Page 5"
+ };
+
+ ListView _menu;
+
+ protected override void Init ()
+ {
+ _menu = new ListView { ItemsSource = _menuItems };
+
+ _menu.ItemSelected += PageSelected;
+
+ Content = _menu;
+ }
+
+ async void PageSelected(object sender, SelectedItemChangedEventArgs e)
+ {
+ var selection = e.SelectedItem as string;
+
+ switch (selection)
+ {
+ case "Page 1":
+ await Navigation.PushAsync(new TestPage(0));
+ break;
+
+ case "Page 2":
+ await Navigation.PushAsync(new TestPage(1));
+ break;
+
+ case "Page 3":
+ await Navigation.PushAsync(new TestPage(2));
+ break;
+
+ case "Page 4":
+ await Navigation.PushAsync(new TestPage(3));
+ break;
+
+ case "Page 5":
+ await Navigation.PushAsync(new TestPage(4));
+ break;
+ }
+ _menu.SelectedItem = null;
+ }
+
+ public class TestPage : CarouselPage
+ {
+ public TestPage()
+ {
+ Children.Add(new ContentPage { Content = new Label { Text = "This is page 1" , BackgroundColor = Color.Red} });
+ Children.Add(new ContentPage { Content = new Label { Text = "This is page 2" , BackgroundColor = Color.Green} });
+ Children.Add(new ContentPage { Content = new Label { Text = "This is page 3" , BackgroundColor = Color.Blue} });
+ Children.Add(new ContentPage { Content = new Label { Text = "This is page 4" , BackgroundColor = Color.Pink} });
+ Children.Add(new ContentPage { Content = new Label { Text = "This is page 5" , BackgroundColor = Color.Yellow } });
+
+ }
+
+ public TestPage(int page) : this()
+ {
+ CurrentPage = Children[page];
+ }
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla29257Test ()
+ {
+ RunningApp.Tap (q => q.Marked ("Page 1"));
+ RunningApp.WaitForElement (q => q.Marked ("This is page 1"));
+ RunningApp.Back ();
+ RunningApp.Tap (q => q.Marked ("Page 2"));
+ RunningApp.WaitForElement (q => q.Marked ("This is page 2"));
+ RunningApp.Back ();
+ RunningApp.Tap (q => q.Marked ("Page 3"));
+ RunningApp.WaitForElement (q => q.Marked ("This is page 3"));
+ RunningApp.Back ();
+ RunningApp.Tap (q => q.Marked ("Page 4"));
+ RunningApp.WaitForElement (q => q.Marked ("This is page 4"));
+ RunningApp.Back ();
+ RunningApp.Tap (q => q.Marked ("Page 5"));
+ RunningApp.WaitForElement (q => q.Marked ("This is page 5"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29363.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29363.cs
new file mode 100644
index 00000000..fbacce89
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29363.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+#endif
+
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 29363, "PushModal followed immediate by PopModal crashes")]
+ public class Bugzilla29363 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var layout = new StackLayout () {HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand};
+
+ Button modal = new Button {
+ Text = "Modal Push Pop Test",
+ Font = Font.SystemFontOfSize (25, FontAttributes.Bold),
+ HorizontalOptions = LayoutOptions.Center
+ };
+ modal.Clicked += async (object sender, EventArgs e) => {
+ var page = new ContentPage () {BackgroundColor = Color.Red};
+
+ await Navigation.PushModalAsync (page);
+
+ await Navigation.PopModalAsync (true);
+ };
+
+ layout.Children.Add (modal);
+ Content = layout;
+ }
+
+#if UITEST
+ [Test]
+ public void PushButton ()
+ {
+ RunningApp.Tap (q => q.Marked ("Modal Push Pop Test"));
+ System.Threading.Thread.Sleep (5);
+ // if it didn't crash, yay
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29453.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29453.cs
new file mode 100644
index 00000000..ce6e5e12
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla29453.cs
@@ -0,0 +1,72 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 29453, "Navigation.PopAsync(false) in Entry.Completed handler => System.ArgumentException", PlatformAffected.Android)]
+ public class Bugzilla29453 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ var page1Layout = new StackLayout {
+ Children = {
+ new Label {
+ XAlign = TextAlignment.Center,
+ Text = "Page 1"
+ }
+ }
+ };
+
+ var page2Layout = new StackLayout {
+ Children = {
+ new Label {
+ XAlign = TextAlignment.Center,
+ Text = "Page 2"
+ }
+ }
+ };
+
+ var entry = new Entry { AutomationId = "entryText" };
+
+ entry.Completed += async (sender, args) => {
+ await Navigation.PopAsync (false);
+ };
+
+ page2Layout.Children.Add (entry);
+
+ var page2 = new ContentPage {
+ Content = page2Layout
+ };
+
+ var button = new Button {
+ Text = "Go to page 2",
+ AutomationId = "btnGotoPage2",
+ Command = new Command (async () => await Navigation.PushAsync (page2))
+ };
+
+ page1Layout.Children.Add (button);
+ Content = page1Layout;
+ }
+
+ #if UITEST
+ [Test]
+ public void Bugzilla29453Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue Bugzilla29453");
+ RunningApp.WaitForElement (q => q.Marked ("Page 1"));
+ RunningApp.Tap (q => q.Marked ("btnGotoPage2"));
+ RunningApp.Tap (q => q.Marked ("entryText"));
+ RunningApp.EnterText ("XF");
+ RunningApp.PressEnter ();
+ RunningApp.WaitForElement (q => q.Marked ("Page 1"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30317.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30317.cs
new file mode 100644
index 00000000..7cc07709
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30317.cs
@@ -0,0 +1,260 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+using Xamarin.UITest.Android;
+using System.Collections.Generic;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 30317, "https://bugzilla.xamarin.com/show_bug.cgi?id=30137")]
+ public class Bugzilla30317 : TestNavigationPage // or TestMasterDetailPage, etc ...
+ {
+ [Preserve (AllMembers = true)]
+ public class Bugzilla30317ListItem
+ {
+ public string Label { get; set; }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Bugzilla30317ListCell : ViewCell
+ {
+ public Bugzilla30317ListCell()
+ {
+ var label = new Label (); ;
+ label.SetBinding(Label.TextProperty, "Label");
+ View = label;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Bugzilla30317Page1 : ContentPage
+ {
+ ListView _listView;
+
+ public Bugzilla30317Page1 ()
+ {
+ AutomationId = "PageOne";
+ Title = "Set ItemSource On Appearing";
+
+ _listView = new ListView ();
+
+ _listView.ItemTemplate = new DataTemplate(typeof(Bugzilla30317ListCell));
+
+ var nextPageButton = new Button {
+ AutomationId = "GoToPageTwoButton",
+ Text = "Go Page 2",
+ Command = new Command (async () => {
+ await Navigation.PushAsync (new Bugzilla30317Page2 ());
+ })
+ };
+
+ Content = new StackLayout { Children = { nextPageButton, _listView } };
+ }
+
+ protected override void OnAppearing ()
+ {
+ base.OnAppearing ();
+
+ _listView.ItemsSource = new Bugzilla30317ListItem[] {
+ new Bugzilla30317ListItem { Label = "PageOneItem1" },
+ new Bugzilla30317ListItem { Label = "PageOneItem2" },
+ new Bugzilla30317ListItem { Label = "PageOneItem3" },
+ new Bugzilla30317ListItem { Label = "PageOneItem4" },
+ new Bugzilla30317ListItem { Label = "PageOneItem5" },
+ };
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Bugzilla30317Page2 : ContentPage
+ {
+ public Bugzilla30317Page2 ()
+ {
+ AutomationId = "PageTwo";
+ Title = "Set ItemSource in ctor";
+
+ var listView = new ListView ();
+
+ listView.ItemTemplate = new DataTemplate(typeof(Bugzilla30317ListCell));
+ listView.ItemsSource = new Bugzilla30317ListItem[] {
+ new Bugzilla30317ListItem { Label = "PageTwoItem1" },
+ new Bugzilla30317ListItem { Label = "PageTwoItem2" },
+ new Bugzilla30317ListItem { Label = "PageTwoItem3" },
+ new Bugzilla30317ListItem { Label = "PageTwoItem4" },
+ new Bugzilla30317ListItem { Label = "PageTwoItem5" },
+ };
+
+ var nextPageButton = new Button {
+ AutomationId = "GoToPageThreeButton",
+ Text = "Go Page 3",
+ Command = new Command (async () => {
+ await Navigation.PushModalAsync (new Bugzilla30317Page3 ());
+ })
+ };
+
+ Content = new StackLayout { Children = { nextPageButton, listView } };
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Bugzilla30317Page3TabOne : ContentPage
+ {
+ public Bugzilla30317Page3TabOne ()
+ {
+ AutomationId = "TabbedPageOne";
+ Title = "TabOneCtor";
+
+ var listView = new ListView ();
+
+ listView.ItemTemplate = new DataTemplate(typeof(Bugzilla30317ListCell));
+ listView.ItemsSource = new Bugzilla30317ListItem[] {
+ new Bugzilla30317ListItem { Label = "PageThreeTabOneItem1" },
+ new Bugzilla30317ListItem { Label = "PageThreeTabOneItem2" },
+ new Bugzilla30317ListItem { Label = "PageThreeTabOneItem3" },
+ new Bugzilla30317ListItem { Label = "PageThreeTabOneItem4" },
+ new Bugzilla30317ListItem { Label = "PageThreeTabOneItem5" },
+ };
+
+ Content = listView;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Bugzilla30317Page3TabTwo : ContentPage
+ {
+ ListView _listView;
+
+ public Bugzilla30317Page3TabTwo ()
+ {
+ AutomationId = "TabbedPageTwo";
+ Title = "TabTwoOnAppearing";
+
+ _listView = new ListView ();
+
+ _listView.ItemTemplate = new DataTemplate(typeof(Bugzilla30317ListCell));
+
+
+ Content = _listView;
+
+ }
+
+ protected override void OnAppearing ()
+ {
+ base.OnAppearing ();
+
+ _listView.ItemsSource = new Bugzilla30317ListItem[] {
+ new Bugzilla30317ListItem { Label = "PageThreeTabTwoItem1" },
+ new Bugzilla30317ListItem { Label = "PageThreeTabTwoItem2" },
+ new Bugzilla30317ListItem { Label = "PageThreeTabTwoItem3" },
+ new Bugzilla30317ListItem { Label = "PageThreeTabTwoItem4" },
+ new Bugzilla30317ListItem { Label = "PageThreeTabTwoItem5" },
+ };
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Bugzilla30317Page3 : TabbedPage
+ {
+ public Bugzilla30317Page3 ()
+ {
+ Children.Add (new Bugzilla30317Page3TabOne ());
+ Children.Add (new Bugzilla30317Page3TabTwo ());
+ }
+ }
+
+ protected override void Init ()
+ {
+ Navigation.PushAsync (new Bugzilla30317Page1 ());
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla30317ItemSourceOnAppearingContentPage ()
+ {
+ if (RunningApp is AndroidApp) {
+ RunningApp.Screenshot ("I am at Bugzilla30317");
+ RunningApp.WaitForElement (q => q.Marked ("PageOne"));
+ RunningApp.Screenshot ("I see Page 1");
+
+ RunningApp.WaitForElement (q => q.Marked ("PageOneItem1"));
+ RunningApp.TouchAndHold (q => q.Marked ("PageOneItem1"));
+
+ RunningApp.WaitForElement (q => q.Marked ("PageOneItem5"));
+ RunningApp.TouchAndHold (q => q.Marked ("PageOneItem5"));
+
+ RunningApp.Screenshot ("I did not crash");
+ } else {
+ Assert.Inconclusive ("Not run on iOS");
+ }
+ }
+
+ [Test]
+ public void Bugzilla30317ItemSourceCtorContentPage ()
+ {
+ if (RunningApp is AndroidApp) {
+ RunningApp.WaitForElement (q => q.Marked ("GoToPageTwoButton"));
+ RunningApp.Tap (q => q.Marked ("GoToPageTwoButton"));
+
+ RunningApp.WaitForElement (q => q.Marked ("PageTwo"));
+ RunningApp.Screenshot ("I see Page 2");
+
+ RunningApp.WaitForElement (q => q.Marked ("PageTwoItem1"));
+ RunningApp.TouchAndHold (q => q.Marked ("PageTwoItem1"));
+
+ RunningApp.WaitForElement (q => q.Marked ("PageTwoItem5"));
+ RunningApp.TouchAndHold (q => q.Marked ("PageTwoItem5"));
+
+ RunningApp.Screenshot ("I did not crash");
+ } else {
+ Assert.Inconclusive ("Not run on iOS");
+ }
+ }
+
+ [Test]
+ public void Bugzilla30317ItemSourceTabbedPage ()
+ {
+ if (RunningApp is AndroidApp) {
+ RunningApp.WaitForElement (q => q.Marked ("GoToPageTwoButton"));
+ RunningApp.Tap (q => q.Marked ("GoToPageTwoButton"));
+
+ RunningApp.Screenshot ("I see Page 2");
+ RunningApp.WaitForElement (q => q.Marked ("PageTwo"));
+
+ RunningApp.WaitForElement (q => q.Marked ("GoToPageThreeButton"));
+ RunningApp.Tap (q => q.Marked ("GoToPageThreeButton"));
+
+ RunningApp.Screenshot ("I see TabbedPage One");
+ RunningApp.WaitForElement (q => q.Marked ("TabOneCtor"));
+
+ RunningApp.WaitForElement (q => q.Marked ("PageThreeTabOneItem1"));
+ RunningApp.TouchAndHold (q => q.Marked ("PageThreeTabOneItem1"));
+ RunningApp.WaitForElement (q => q.Marked ("PageThreeTabOneItem1"));
+
+ RunningApp.WaitForElement (q => q.Marked ("PageThreeTabOneItem5"));
+ RunningApp.TouchAndHold (q => q.Marked ("PageThreeTabOneItem5"));
+ RunningApp.WaitForElement (q => q.Marked ("PageThreeTabOneItem5"));
+
+ RunningApp.Screenshot ("I see TabbedPage Two");
+ RunningApp.WaitForElement (q => q.Marked ("TabTwoOnAppearing"));
+ RunningApp.Tap (q => q.Marked ("TabTwoOnAppearing"));
+
+ RunningApp.WaitForElement (q => q.Marked ("PageThreeTabTwoItem1"));
+ RunningApp.TouchAndHold (q => q.Marked ("PageThreeTabTwoItem1"));
+ RunningApp.WaitForElement (q => q.Marked ("PageThreeTabTwoItem1"));
+
+ RunningApp.WaitForElement (q => q.Marked ("PageThreeTabTwoItem5"));
+ RunningApp.TouchAndHold (q => q.Marked ("PageThreeTabTwoItem5"));
+ RunningApp.WaitForElement (q => q.Marked ("PageThreeTabTwoItem5"));
+ } else {
+ Assert.Inconclusive ("Not run on iOS");
+ }
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30324.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30324.cs
new file mode 100644
index 00000000..1356ffa7
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30324.cs
@@ -0,0 +1,97 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 30324, "Detail view of MasterDetailPage does not get appearance events on Android when whole MasterDetailPage disappears/reappears")]
+ public class Bugzilla30324 : TestNavigationPage
+ {
+ Label _lbl;
+ int _count;
+
+ protected override void Init ()
+ {
+ MasterDetailPage page = new MasterDetailPage();
+ page.Master = new Page () { Title = "Master", BackgroundColor = Color.Red };
+ _lbl = new Label ();
+
+ var otherPage = new ContentPage () {
+ Title = "Other",
+ Content = new StackLayout { Children = {
+ new Button () {
+ Text = "navigate back",
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.Center,
+
+ Command = new Command (() => Navigation.PopAsync())
+ }
+ }
+ }
+ };
+
+ page.Detail = new ContentPage () {
+ Title = "Detail",
+ Content = new StackLayout { Children = {
+ _lbl,
+ new Button () {
+ Text = "navigate",
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.Center,
+
+ Command = new Command (() => Navigation.PushAsync (otherPage))
+ }
+ }
+ }
+ };
+
+ page.Appearing += (sender, e) =>
+ {
+ System.Diagnostics.Debug.WriteLine("Appear MDP");
+ };
+ page.Disappearing += (sender, e) =>
+ {
+ System.Diagnostics.Debug.WriteLine("Disappear MDP");
+ };
+ page.Detail.Appearing += (sender, args) =>
+ {
+ if(_count ==2)
+ _lbl.Text = "Appear detail";
+ System.Diagnostics.Debug.WriteLine("Appear detail");
+ };
+ page.Detail.Disappearing += (sender, args) => {
+ System.Diagnostics.Debug.WriteLine ("Disappear detail");
+ _lbl.Text = "Disappear detail";
+ page.Detail.BackgroundColor = Color.Green;
+ _count++;
+ };
+ page.Master.Appearing += (sender, e) =>
+ {
+ System.Diagnostics.Debug.WriteLine("Appear master");
+ };
+ Navigation.PushAsync (page);
+ }
+
+ #if UITEST
+ [Test]
+ public void Bugzilla30324Test ()
+ {
+ RunningApp.Tap (q => q.Marked ("navigate"));
+ RunningApp.Tap (q => q.Marked ("navigate back"));
+ RunningApp.WaitForElement (q => q.Marked ("Disappear detail"));
+ RunningApp.Tap (q => q.Marked ("navigate"));
+ RunningApp.Tap (q => q.Marked ("navigate back"));
+ RunningApp.WaitForElement (q => q.Marked ("Appear detail"));
+ }
+ #endif
+ }
+
+
+}
+
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30353.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30353.cs
new file mode 100644
index 00000000..56c5ef87
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30353.cs
@@ -0,0 +1,113 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest.iOS;
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 30353, "MasterDetailPage.IsPresentedChanged is not raised")]
+ public class Bugzilla30353 : TestMasterDetailPage
+ {
+ protected override void Init ()
+ {
+ var lbl = new Label {
+ HorizontalOptions = LayoutOptions.CenterAndExpand,
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ Text = "Detail"
+ };
+
+ #if !UITEST
+ if (App.IOSVersion == 7) {
+ lbl.Text = "Don't run";
+ }
+ #endif
+
+ var lblMaster = new Label {
+ HorizontalOptions = LayoutOptions.CenterAndExpand,
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ Text = "Master"
+ };
+ var btn = new Button () {
+ Text = "Toggle"
+ };
+ var btn1 = new Button () {
+ Text = "Toggle"
+ };
+
+ btn.Clicked += (object sender, EventArgs e) => IsPresented = !IsPresented;
+ btn1.Clicked += (object sender, EventArgs e) => IsPresented = !IsPresented;
+
+ var stacklayout = new StackLayout ();
+ stacklayout.Children.Add (lbl);
+ stacklayout.Children.Add (btn);
+
+ var stacklayout1 = new StackLayout ();
+ stacklayout1.Children.Add (lblMaster);
+ stacklayout1.Children.Add (btn1);
+
+ Master = new ContentPage {
+ Title = "IsPresentedChanged Test",
+ BackgroundColor = Color.Green,
+ Content = stacklayout1
+ };
+ Detail = new ContentPage {
+ BackgroundColor = Color.Gray,
+ Content = stacklayout
+ };
+ MasterBehavior = MasterBehavior.Popover;
+ IsPresentedChanged += (s, e) =>
+ lblMaster.Text = lbl.Text = string.Format ("The Master is now {0}", IsPresented ? "visible" : "invisible");
+ }
+
+ #if UITEST
+ [Test]
+ public void Bugzilla30353Test ()
+ {
+ var dontRun = RunningApp.Query (q => q.Marked ("Don't run"));
+ if (dontRun.Length > 0)
+ {
+ return;
+ }
+ RunningApp.SetOrientationPortrait ();
+ RunningApp.Screenshot ("Portrait");
+ RunningApp.Tap (q => q.Marked ("Toggle"));
+ RunningApp.Screenshot ("Portrait Visible");
+ RunningApp.WaitForElement (q => q.Marked ("The Master is now visible"));
+ if (RunningApp is iOSApp)
+ RunningApp.Tap (q => q.Marked ("Toggle"));
+ else
+ RunningApp.Back ();
+ RunningApp.Screenshot ("Portrait Invisible");
+ RunningApp.WaitForElement (q => q.Marked ("The Master is now invisible"));
+ RunningApp.SetOrientationLandscape ();
+ RunningApp.Screenshot ("Landscape Invisible");
+ RunningApp.WaitForElement (q => q.Marked ("The Master is now invisible"));
+ RunningApp.Tap (q => q.Marked ("Toggle"));
+ RunningApp.Screenshot ("Landscape Visible");
+ RunningApp.WaitForElement (q => q.Marked ("The Master is now visible"));
+ if (RunningApp is iOSApp)
+ RunningApp.Tap (q => q.Marked ("Toggle"));
+ else
+ RunningApp.Back ();
+ RunningApp.Screenshot ("Landscape InVisible");
+ RunningApp.WaitForElement (q => q.Marked ("The Master is now invisible"));
+ RunningApp.SetOrientationPortrait ();
+ RunningApp.Tap (q => q.Marked ("Toggle"));
+ RunningApp.Screenshot ("Portrait Visible");
+ RunningApp.WaitForElement (q => q.Marked ("The Master is now visible"));
+ if (RunningApp is iOSApp)
+ RunningApp.Tap (q => q.Marked ("Toggle"));
+ else
+ RunningApp.Back ();
+ RunningApp.Screenshot ("Portrait Invisible");
+ RunningApp.WaitForElement (q => q.Marked ("The Master is now invisible"));
+ RunningApp.SetOrientationLandscape ();
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30651.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30651.cs
new file mode 100644
index 00000000..a2466b98
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30651.cs
@@ -0,0 +1,101 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.ObjectModel;
+using System.Linq;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 30651, "ListView jumps around while scrolling after items are added to its source")]
+ public class Bugzilla30651: TestContentPage
+ {
+ ListViewModel _viewModel;
+ protected override void Init ()
+ {
+ _viewModel = new ListViewModel();
+ BindingContext = _viewModel;
+ var lv = new ListView ();
+ lv.SetBinding (ListView.ItemsSourceProperty, new Binding ("Items"));
+ lv.SeparatorVisibility = SeparatorVisibility.None;
+ lv.HasUnevenRows = true;
+ lv.ItemAppearing+= (object sender, ItemVisibilityEventArgs e) => {
+ _viewModel.OnItemAppearing(e.Item.ToString());
+ };
+ lv.ItemTemplate = new DataTemplate (typeof(TestCell));
+ Content = lv;
+ }
+
+ public class TestCell : ViewCell {
+ Label _myLabel;
+ public TestCell ()
+ {
+ View = _myLabel = new Label();
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ if (BindingContext == null)
+ return;
+
+ var i = BindingContext as string;
+ _myLabel.Text = i;
+ Height = 100;
+
+ base.OnBindingContextChanged();
+ }
+ }
+
+
+ public class ListViewModel : ViewModelBase
+ {
+ ObservableCollection<string> _items;
+ int _counter = 0;
+
+ public ObservableCollection<string> Items
+ {
+ get { return _items; }
+ set { _items = value; OnPropertyChanged ();}
+ }
+
+ public ListViewModel()
+ {
+ Items = new ObservableCollection<string>();
+ AddMoreData();
+ }
+
+ public void OnItemAppearing(string s)
+ {
+ if (Items.Last() == s)
+ AddMoreData();
+ }
+
+ void AddMoreData()
+ {
+ _counter++;
+ Items.Add(_counter.ToString());
+ _counter++;
+ Items.Add(_counter.ToString());
+ _counter++;
+ Items.Add(_counter.ToString());
+ _counter++;
+ Items.Add(_counter.ToString());
+ _counter++;
+ Items.Add(_counter.ToString());
+ _counter++;
+ Items.Add(_counter.ToString());
+ _counter++;
+ Items.Add(_counter.ToString());
+ _counter++;
+ Items.Add(_counter.ToString());
+ _counter++;
+ Items.Add(_counter.ToString());
+ _counter++;
+ Items.Add(_counter.ToString());
+ _counter++;
+ Items.Add(_counter.ToString());
+ _counter++;
+ Items.Add(_counter.ToString());
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30835.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30835.cs
new file mode 100644
index 00000000..c4af01d6
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30835.cs
@@ -0,0 +1,207 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.Generic;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 30835, "Navigating to and from the Carousel page with MasterDetail page creates an Out of memory exception")]
+ public class Bugzilla30835 : TestMasterDetailPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ var menuPage = new MenuPage ();
+
+ menuPage.Menu.ItemSelected += (sender, e) => NavigateTo (e.SelectedItem as MenuItem);
+
+ Master = menuPage;
+ Detail = new NavigationPage (new HolderCarouselPages ());
+ }
+
+ void NavigateTo (MenuItem menu)
+ {
+ var displayPage = (Page)Activator.CreateInstance (menu.TargetType);
+ Detail = new NavigationPage (displayPage);
+ IsPresented = false;
+ }
+
+ [Preserve (AllMembers = true)]
+ public class HolderCarouselPages : CarouselPage
+ {
+ public HolderCarouselPages ()
+ {
+ Device.BeginInvokeOnMainThread (() => {
+ ItemsSource = new HolderImage[] {
+ new HolderImage ("frog", "photo.jpg"),
+ new HolderImage ("history", "photo.jpg"),
+ new HolderImage ("Test", "photo.jpg"),
+ };
+ });
+
+ ItemTemplate = new DataTemplate (() => new DisplayContentPage ());
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class HolderImage
+ {
+ public HolderImage (string name, string images)
+ {
+ Name = name;
+ Homeimages = images;
+ }
+
+ public string Name { private set; get; }
+
+ public string Homeimages { private set; get; }
+
+ public override string ToString ()
+ {
+ return Name;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class DisplayContentPage : ContentPage
+ {
+ public DisplayContentPage ()
+ {
+ var imageView = new Image {
+ HorizontalOptions = LayoutOptions.Center,
+ };
+
+ Content = new StackLayout {
+ Children = {
+ new StackLayout {
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.StartAndExpand,
+ Children = {
+ imageView
+ }
+ },
+ }
+ };
+ imageView.SetBinding (Image.SourceProperty, "Homeimages");
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class MenuPage : ContentPage
+ {
+ public ListView Menu { get; set; }
+
+ public MenuPage ()
+ {
+ Icon = "bank.png";
+ Title = "Carsousel Memory Bug";
+ BackgroundColor = Color.FromHex ("#000000");
+
+ Menu = new MenuListView ();
+
+ var menuLabel = new ContentView {
+ Padding = new Thickness (10, 36, 0, 5),
+ Content = new Label {
+ TextColor = Color.FromHex ("#FFFFFF"),
+ Text = "Carsousel Memory Bug",
+ }
+ };
+
+ var layout = new StackLayout {
+ Spacing = 0,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ };
+ layout.Children.Add (menuLabel);
+ layout.Children.Add (Menu);
+
+ Content = layout;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class MenuListView : ListView
+ {
+ public MenuListView ()
+ {
+ List<MenuItem> data = new MenuListData ();
+
+ ItemsSource = data;
+ VerticalOptions = LayoutOptions.FillAndExpand;
+ BackgroundColor = Color.Black;
+
+ var cell = new DataTemplate (typeof(ImageCell));
+ cell.SetBinding (TextCell.TextColorProperty, "TextColor");
+ cell.SetBinding (TextCell.TextProperty, "Title");
+ cell.SetBinding (ImageCell.ImageSourceProperty, "IconSource");
+
+ ItemTemplate = cell;
+ SelectedItem = data [0];
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class MenuListData : List<MenuItem>
+ {
+ public MenuListData ()
+ {
+ Add (new MenuItem () {
+ Title = "Carousel",
+ IconSource = "icon.png",
+ TargetType = typeof(HolderCarouselPages),
+ TextColor = Color.White
+ });
+
+ Add (new MenuItem () {
+ Title = "Pic 1",
+ IconSource = "icon.png",
+ TargetType = typeof(Pic1),
+ TextColor = Color.White
+ });
+
+ Add (new MenuItem () {
+ Title = "Pic 2",
+ IconSource = "icon.png",
+ TargetType = typeof(Pic1),
+ TextColor = Color.White
+ });
+
+ Add (new MenuItem () {
+ Title = "Pic 3",
+ IconSource = "icon.png",
+ TargetType = typeof(Pic1),
+ TextColor = Color.White
+ });
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class MenuItem
+ {
+ public string Title { get; set; }
+
+ public string IconSource { get; set; }
+
+ public Type TargetType { get; set; }
+
+ public Color TextColor { get ; set; }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Pic1 : ContentPage
+ {
+ public Pic1 ()
+ {
+ Content = new StackLayout {
+ Children = {
+ new Image { Source = "photo.jpg" }
+ }
+ };
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30935.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30935.cs
new file mode 100644
index 00000000..3953f63d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla30935.cs
@@ -0,0 +1,44 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Issue (IssueTracker.Bugzilla, 30935, "NullReferenceException in ViewRenderer<TView, TNativeView> (Xamarin.Forms.Platform.Android)")]
+ public class Bugzilla30935 : TestContentPage
+ {
+ Entry _entry;
+ protected override void Init ()
+ {
+ _entry = new Entry { AutomationId = "entry" };
+ // Initialize ui here instead of ctor
+ Content = new StackLayout { Children = { new Label {
+ AutomationId = "IssuePageLabel",
+ Text = "See if I'm here"
+ },_entry
+ }
+ };
+ }
+
+ protected override void OnAppearing ()
+ {
+ _entry.Focus ();
+ Content = null;
+ base.OnAppearing ();
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla30935DoesntThrowException ()
+ {
+ RunningApp.WaitForNoElement (q => q.Marked ("IssuePageLabel"));
+ RunningApp.WaitForNoElement (q => q.Marked ("entry"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31029.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31029.cs
new file mode 100644
index 00000000..9f9594a2
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31029.cs
@@ -0,0 +1,126 @@
+using System;
+using System.IO;
+using System.Text;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 31029, "[Windows Phone 8.1]Generating an Image via MemoryStream does not appear")]
+ public class Bugzilla31029 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ var generatedImage = new Image { Aspect = Aspect.AspectFit };
+
+ var btn = new Button { Text="generate" };
+
+ btn.Clicked += (sender, e) => {
+ var source = GenerateBmp (60, 60, Color.Red);
+ generatedImage.Source = source;
+
+ };
+
+ Content = new StackLayout {
+ Children = {
+ btn,
+ new Label {Text = "GeneratedImage", Font=Font.BoldSystemFontOfSize(NamedSize.Medium)},
+ generatedImage
+ },
+ Padding = new Thickness (0, 20, 0, 0),
+ VerticalOptions = LayoutOptions.StartAndExpand,
+ HorizontalOptions = LayoutOptions.CenterAndExpand
+ };
+ }
+ public ImageSource GenerateBmp (int rows, int cols, Color color)
+ {
+ BmpMaker bmpMaker = new BmpMaker (rows, cols);
+ //background color to white
+ for (int i = 0; i < rows; i++) {
+ for (int j = 0; j < cols; j++) {
+ bmpMaker.SetPixel (i, j, Color.White);
+ }
+ }
+ //draw a square
+ int marginX = rows / 10;
+ int marginY = cols / 10;
+ for (int row = marginX; row < (rows - marginX); row++) {
+ for (int col = marginY; col < (cols - marginY); col++) {
+ bmpMaker.SetPixel (row, col, color);
+ }
+ }
+ ImageSource resultImage = bmpMaker.Generate ();
+ return resultImage;
+ }
+ }
+
+ public class BmpMaker
+ {
+ const int HeaderSize = 54;
+ readonly byte[] _buffer;
+ public BmpMaker (int width, int height)
+ {
+ Width = width;
+ Height = height;
+ int numPixels = Width * Height;
+ int numPixelBytes = 4 * numPixels;
+ int fileSize = HeaderSize + numPixelBytes;
+ _buffer = new byte[fileSize];
+ // Write headers in MemoryStream and hence the buffer.
+ using (MemoryStream memoryStream = new MemoryStream (_buffer)) {
+ using (BinaryWriter writer = new BinaryWriter (memoryStream, Encoding.UTF8)) {
+ // Construct BMP header (14 bytes).
+ writer.Write (new char[] { 'B', 'M' }); // Signature
+ writer.Write (fileSize); // File size
+ writer.Write ((short) 0); // Reserved
+ writer.Write ((short) 0); // Reserved
+ writer.Write (HeaderSize); // Offset to pixels
+ // Construct BitmapInfoHeader (40 bytes).
+ writer.Write (40); // Header size
+ writer.Write (Width); // Pixel width
+ writer.Write (Height); // Pixel height
+ writer.Write ((short) 1); // Planes
+ writer.Write ((short) 32); // Bits per pixel
+ writer.Write (0); // Compression
+ writer.Write (numPixelBytes); // Image size in bytes
+ writer.Write (0); // X pixels per meter
+ writer.Write (0); // Y pixels per meter
+ writer.Write (0); // Number colors in color table
+ writer.Write (0); // Important color count
+ }
+ }
+ }
+
+ public int Width { get; private set; }
+ public int Height { get; private set; }
+
+ public void SetPixel (int row, int col, Color color)
+ {
+ SetPixel (row, col, (int) (255 * color.R),
+ (int) (255 * color.G),
+ (int) (255 * color.B),
+ (int) (255 * color.A));
+ }
+
+ public void SetPixel (int row, int col, int r, int g, int b, int a = 255)
+ {
+ int index = (row * Width + col) * 4 + HeaderSize;
+ _buffer[index + 0] = (byte) b;
+ _buffer[index + 1] = (byte) g;
+ _buffer[index + 2] = (byte) r;
+ _buffer[index + 3] = (byte) a;
+ }
+
+ public ImageSource Generate ()
+ {
+ Stream memoryStream = new MemoryStream (_buffer);
+ ImageSource imageSource = ImageSource.FromStream (() => { return memoryStream; });
+ return imageSource;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31114.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31114.cs
new file mode 100644
index 00000000..e7f5be4d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31114.cs
@@ -0,0 +1,421 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.ObjectModel;
+
+#if UITEST
+using Xamarin.UITest.iOS;
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 31114, "iOS ContextAction leaves blank line after swiping in ListView")]
+ public class Bugzilla31114 : TestContentPage
+ {
+ ObservableCollection<ListItem> _items = new ObservableCollection<ListItem>();
+ ListView _listView;
+ Button _btbLoad;
+ public Command RefreshListCommand;
+ bool _isBusy = false;
+
+ protected override void Init ()
+ {
+
+ RefreshListCommand = new Command(LoadItemsFromCommand, CanRefreshList);
+ _listView = new ListView();
+ _listView.ItemsSource = _items;
+ _listView.ItemTemplate = new DataTemplate(typeof(TaskItemTemplate));
+ _listView.RowHeight = 64;
+ _listView.RefreshCommand = RefreshListCommand;
+ _listView.IsPullToRefreshEnabled = true;
+
+ _btbLoad = new Button { Text = "Load", AutomationId = "btnLoad", Command = RefreshListCommand };
+ TaskItemTemplate.RefreshFromQuickComplete += TaskListPageRefreshFromQuickComplete;
+
+ LoadItems();
+
+ Content = new StackLayout {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Children = {
+ _listView,_btbLoad
+ }
+ };
+ }
+
+ protected override void OnDisappearing ()
+ {
+ TaskItemTemplate.RefreshFromQuickComplete -= TaskListPageRefreshFromQuickComplete;
+ base.OnDisappearing ();
+ }
+
+ bool CanRefreshList()
+ {
+ return !isBusy;
+ }
+
+ void LoadItemsFromCommand()
+ {
+ LoadItems();
+ }
+
+ void TaskListPageRefreshFromQuickComplete(object sender, ListItemEventArgs e)
+ {
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ LoadItemsFromCommand();
+ });
+ }
+
+ void LoadItems()
+ {
+ isBusy = true;
+
+ Random random = new Random(DateTime.Now.Millisecond);
+
+ int count = random.Next(20, 30);
+
+ _items.Clear();
+
+ for (int i = 0; i < count - 1; i++)
+ {
+ var newItem = new ListItem()
+ {
+ Id = Guid.NewGuid().ToString(),
+ EntityTypeId = 1350,
+ BackgroundColor = "00aa00",
+ TextColor = "FFFFFF",
+ PrimaryText = "PIPE #"+(i+1000).ToString(),
+ CircleColor = "0000aa",
+ Icon = "",
+ OtherText = random.Next(100, 200).ToString() + " ft",
+ SecondaryText = "LENGTH " + i.ToString(),
+ SupportsQuickComplete = true,
+ };
+
+ //Debug.WriteLine(newItem.PrimaryText);
+
+ _items.Add(newItem);
+ }
+
+
+ isBusy = false;
+ }
+
+ bool isBusy
+ {
+ get { return _isBusy; }
+ set
+ {
+ _isBusy = value;
+ _listView.IsRefreshing = _isBusy;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class ListItem
+ {
+ public string Id { get; set; }
+
+ public string PrimaryText { get; set; }
+
+ public string SecondaryText { get; set; }
+
+ public string TertiaryText { get; set; }
+
+ public string OtherText { get; set; }
+
+ public string ListControl { get; set; }
+
+ public string Icon { get; set; }
+
+ public string Params { get; set; }
+
+ public string BackgroundColor { get; set; }
+
+ public string TextColor { get; set; }
+
+ public string CircleColor { get; set; }
+
+ public long EntityTypeId { get; set; }
+
+ public bool SupportsQuickComplete { get; set; }
+
+ public ListItem ()
+ {
+ }
+
+ public string BackgroundColorColor
+ {
+ get
+ {
+ return BackgroundColor;
+ }
+ set
+ {
+ if (BackgroundColor != value)
+ {
+ BackgroundColor = value;
+ }
+ }
+ }
+
+ public string PrimaryLabelText
+ {
+ get
+ {
+ return PrimaryText;
+ }
+ }
+
+ public string SecondaryLabelText
+ {
+ get
+ {
+ return SecondaryText;
+ }
+ }
+
+ public string OtherLabelText
+ {
+ get
+ {
+ return OtherText;
+ }
+ }
+ }
+
+ public class ListItemEventArgs : EventArgs
+ {
+ public ListItem ListItem { get; set; }
+
+ public ListItemEventArgs(ListItem item)
+ {
+ ListItem = item;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class TaskItemTemplate : ViewCell
+ {
+ Image _photo;
+ Label _mainLabel;
+ Label _secondaryLabel;
+ Label _distanceLabel;
+ Label _statusCircle;
+ StackLayout _stackLayout;
+ StackLayout _primaryContent;
+ StackLayout _secondaryContent;
+ AbsoluteLayout _masterLayout;
+
+ MenuItem _quickCompleteMenu;
+
+ public static event EventHandler<ListItemEventArgs> RefreshFromQuickComplete;
+
+ public TaskItemTemplate()
+ {
+ Init(true);
+ }
+
+ public TaskItemTemplate(bool fast = true)
+ {
+ Init(fast);
+ }
+
+ void Init(bool fast)
+ {
+ _photo = new Image
+ {
+ HeightRequest = 52,
+ WidthRequest = 52,
+ };
+
+
+ _mainLabel = new Label() { HeightRequest = 40, FontSize = 24, TranslationY = 5, LineBreakMode = LineBreakMode.TailTruncation };
+ _mainLabel.SetBinding(Label.TextProperty, "PrimaryLabelText");
+
+ _secondaryLabel = new Label() { HeightRequest = 40, FontSize = 16, TranslationY = -5, LineBreakMode = LineBreakMode.TailTruncation };
+ _secondaryLabel.SetBinding(Label.TextProperty, "SecondaryLabelText");
+
+ _distanceLabel = new Label() { XAlign = TextAlignment.End, HorizontalOptions = LayoutOptions.EndAndExpand, FontSize = 11, LineBreakMode = LineBreakMode.NoWrap };
+ _distanceLabel.SetBinding(Label.TextProperty, "OtherLabelText");
+
+ _statusCircle = new Label()
+ {
+ HorizontalOptions = LayoutOptions.EndAndExpand,
+ FontSize = 30,
+ TranslationY = 0,
+ };
+
+ _primaryContent = new StackLayout()
+ {
+ HorizontalOptions = LayoutOptions.StartAndExpand,
+ Orientation = StackOrientation.Vertical,
+ Children =
+ {
+ _mainLabel,
+ _secondaryLabel,
+ },
+ Padding = new Thickness(12, 0, 0, 0),
+ };
+
+ _secondaryContent = new StackLayout()
+ {
+ MinimumWidthRequest = 50,
+ HorizontalOptions = LayoutOptions.EndAndExpand,
+ Children =
+ {
+ _distanceLabel,
+ _statusCircle,
+ },
+ Padding = new Thickness(0, 5, 5, 0),
+ };
+
+ _stackLayout = new StackLayout
+ {
+ Orientation = StackOrientation.Horizontal,
+ Children =
+ {
+ _photo,
+ _primaryContent,
+ _secondaryContent,
+ },
+ Padding = new Thickness(5, 0, 0, 0)
+ };
+
+ if (!fast)
+ {
+ View = _stackLayout;
+ }
+ else
+ {
+ _quickCompleteMenu = new MenuItem { Text = "Complete", IsDestructive = false };
+ _quickCompleteMenu.SetBinding(MenuItem.CommandParameterProperty, new Binding("."));
+
+ // Delete context menu action
+ _quickCompleteMenu.Clicked += (sender, e) =>
+ {
+ FastCompleteForCmd(sender);
+ };
+
+ // Add this action to the cell
+ ContextActions.Add(_quickCompleteMenu);
+
+ _masterLayout = new AbsoluteLayout();
+
+ _masterLayout.Children.Add(_stackLayout);
+
+ AbsoluteLayout.SetLayoutFlags(_stackLayout, AbsoluteLayoutFlags.All);
+ AbsoluteLayout.SetLayoutBounds(_stackLayout, new Rectangle(0.0, 0.0, 1.0f, 1.0f));
+
+ View = _masterLayout;
+ }
+ }
+
+
+ protected override void OnPropertyChanged(string propertyName = null)
+ {
+ base.OnPropertyChanged(propertyName);
+ if (propertyName == "BackgroundColor")
+ {
+ var item = BindingContext as ListItem;
+ if (item != null && !string.IsNullOrEmpty(item.BackgroundColor))
+ View.BackgroundColor = Color.FromHex(item.BackgroundColor);
+ }
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ try
+ {
+ base.OnBindingContextChanged();
+ var item = BindingContext as ListItem;
+ if (item != null)
+ {
+ Color transformedColor;
+
+ if (!string.IsNullOrWhiteSpace(item.TextColor))
+ {
+ transformedColor = Color.FromHex(item.TextColor);
+
+ _mainLabel.TextColor = transformedColor;
+ _secondaryLabel.TextColor = transformedColor;
+ _distanceLabel.TextColor = transformedColor;
+ }
+
+ if (string.IsNullOrEmpty(item.Icon))
+ item.Icon = "https://beehive.blob.core.windows.net/staticimages/FeatureImages/MutantLizard01.png";
+
+ _photo.Source = new UriImageSource()
+ {
+ Uri = new Uri(item.Icon),
+ CachingEnabled = true,
+ CacheValidity = new TimeSpan(30, 0, 0, 0),
+ };
+
+ if (!string.IsNullOrWhiteSpace(item.BackgroundColor))
+ {
+ transformedColor = Color.FromHex(item.BackgroundColor);
+ View.BackgroundColor = transformedColor;
+ }
+
+ if (!string.IsNullOrWhiteSpace(item.CircleColor))
+ {
+ _statusCircle.Text = "\u25CF "; // ascii circle
+ _statusCircle.TextColor = Color.FromHex(item.CircleColor);
+ _statusCircle.FontSize = 30;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ }
+ }
+
+ async void FastCompleteForCmd(object sender)
+ {
+ try
+ {
+ {
+ var item = BindingContext as ListItem;
+ bool success = true; // await _taskListManager.FastComplete(item);
+
+ if (success)
+ RefreshFromQuickComplete(this, new ListItemEventArgs(item));
+ }
+ }
+ catch (Exception ex)
+ {
+
+ }
+ }
+
+ }
+
+#if UITEST
+ [Test]
+ [Ignore("Fails sometimes - needs a better test")]
+ public void Bugzilla31114Test ()
+ {
+ if (RunningApp is iOSApp) {
+ for (int i = 0; i < 5; i++) {
+ RunningApp.DragCoordinates (10, 300, 10, 10);
+ }
+ RunningApp.Tap (q => q.Marked ("btnLoad"));
+ RunningApp.DragCoordinates (10, 300, 10, 10);
+ RunningApp.WaitForElement (q => q.Marked ("PIPE #1007"));
+ RunningApp.WaitForElement (q => q.Marked ("PIPE #1008"));
+ RunningApp.WaitForElement (q => q.Marked ("PIPE #1009"));
+ RunningApp.DragCoordinates (10, 300, 10, 10);
+ RunningApp.WaitForElement (q => q.Marked ("PIPE #1010"));
+ RunningApp.WaitForElement (q => q.Marked ("PIPE #1011"));
+ RunningApp.WaitForElement (q => q.Marked ("PIPE #1012"));
+ RunningApp.WaitForElement (q => q.Marked ("PIPE #1013"));
+ }
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31145.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31145.cs
new file mode 100644
index 00000000..9e1d7916
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31145.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve(AllMembers = true)]
+ [Issue(IssueTracker.Bugzilla, 31145, "Picker cause memory leak holding entire Page in memory after it popped (WP8 SL only)", PlatformAffected.WinPhone)]
+ public class Bugzilla31145 : TestContentPage
+ {
+ WeakReference _page2Tracker;
+ Label _resultLabel;
+
+ protected override void Init()
+ {
+ var instructions = new Label () { Text = "The counter below should say 'Page2 IsAlive = false' after a short period of time. If the counter does not say that within 5 seconds, this test has failed." };
+ _resultLabel = new Label ();
+ Content = new StackLayout { Children = { instructions, _resultLabel } };
+ }
+
+ protected override async void OnAppearing()
+ {
+ base.OnAppearing();
+
+ if (_page2Tracker == null)
+ {
+ var page2 = new Bugzilla31145Page2();
+
+ _page2Tracker = new WeakReference(page2, false);
+
+ await Task.Yield();
+ await Navigation.PushModalAsync(page2);
+
+ StartTrackPage2();
+ }
+ }
+
+ async void StartTrackPage2()
+ {
+ var n = 0;
+ while (_page2Tracker.IsAlive)
+ {
+ _resultLabel.Text = $"Page2 IsAlive = {_page2Tracker.IsAlive} ({n++})";
+ await Task.Delay(1000);
+ GC.Collect();
+ }
+
+ _resultLabel.Text = $"Page2 IsAlive = {_page2Tracker.IsAlive}";
+ }
+ }
+
+ public class Bugzilla31145Page2 : ContentPage
+ {
+ public Bugzilla31145Page2()
+ {
+ Content = new Picker();
+ }
+
+ protected override async void OnAppearing()
+ {
+ base.OnAppearing();
+
+ await Task.Yield();
+ await Navigation.PopModalAsync();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31255.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31255.cs
new file mode 100644
index 00000000..378077e0
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31255.cs
@@ -0,0 +1,88 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Threading.Tasks;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 31255, "Master's page Icon cause memory leak after MasterDetailPage is popped out by holding on page")]
+ public class Bugzilla31255 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ var stack = new StackLayout () { VerticalOptions = LayoutOptions.Center };
+
+ stack.Children.Add (new Label () { VerticalOptions =
+ LayoutOptions.Center, XAlign = TextAlignment.Center, Text = "Page 1"
+ });
+
+ Content = stack;
+
+ }
+
+ WeakReference _page2Tracker;
+
+ protected override async void OnAppearing ()
+ {
+ base.OnAppearing ();
+
+ if (_page2Tracker == null) {
+ var page2 = new Page2 ();
+
+ _page2Tracker = new WeakReference (page2, false);
+
+ await Task.Delay (1000);
+ await Navigation.PushModalAsync (page2);
+
+ StartTrackPage2 ();
+ }
+ }
+
+ async void StartTrackPage2 ()
+ {
+ while (true) {
+ ((Label)((StackLayout)Content).Children [0]).Text =
+ string.Format ("Page1. But Page2 IsAlive = {0}", _page2Tracker.IsAlive);
+ await Task.Delay (1000);
+ GC.Collect ();
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Page2 : MasterDetailPage
+ {
+ public Page2 ()
+ {
+ Master = new Page () { Title = "Master",
+ Icon = "Icon.png"
+ };
+ Detail = new Page () { Title = "Detail" };
+ }
+
+ protected override async void OnAppearing ()
+ {
+ base.OnAppearing ();
+
+ await Task.Delay (1000);
+ await Navigation.PopModalAsync ();
+ }
+ }
+
+ #if UITEST
+ [Test]
+ [Ignore("Fails intermittently on TestCloud")]
+ public async void Bugzilla31255Test ()
+ {
+ RunningApp.Screenshot ("I am at Bugzilla 31255");
+ await Task.Delay (5000);
+ RunningApp.WaitForElement (q => q.Marked ("Page1. But Page2 IsAlive = False"));
+ }
+ #endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31330.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31330.cs
new file mode 100644
index 00000000..5f7e14ec
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31330.cs
@@ -0,0 +1,163 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.ObjectModel;
+using System.Windows.Input;
+
+
+#if UITEST
+using Xamarin.UITest.iOS;
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 31330, "Disabled context actions appear enabled")]
+ public class Bugzilla31330 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var vm = new ListViewModel ();
+ BindingContext = vm;
+ vm.Init ();
+ var listview = new ListView ();
+ listview.SetBinding (ListView.ItemsSourceProperty, new Binding ("Items"));
+ listview.ItemTemplate = new DataTemplate (typeof(CustomTextCell));
+ listview.ItemSelected += (object sender, SelectedItemChangedEventArgs e) => {
+ (e.SelectedItem as ListItemViewModel).CanExecute = true;
+ ((e.SelectedItem as ListItemViewModel).DeleteItemCommand as Command).ChangeCanExecute ();
+ };
+ // Initialize ui here instead of ctor
+ Content = listview;
+ }
+
+ [Preserve (AllMembers = true)]
+ public class CustomTextCell : TextCell
+ {
+ public CustomTextCell ()
+ {
+ SetBinding (TextProperty, new Binding ("Title"));
+ var deleteMenuItem = new MenuItem ();
+ deleteMenuItem.Text = "Delete";
+ deleteMenuItem.IsDestructive = true;
+ deleteMenuItem.SetBinding (MenuItem.CommandProperty, new Binding ("DeleteItemCommand"));
+ ContextActions.Add (deleteMenuItem);
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class ListViewModel : ViewModel
+ {
+ public void Init ()
+ {
+ Items.Add (new ListItemViewModel (this) { Title = string.Format ("Something {0}", Items.Count.ToString ()) });
+ Items.Add (new ListItemViewModel (this) { Title = string.Format ("Something {0}", Items.Count.ToString ()) });
+ Items.Add (new ListItemViewModel (this) { Title = string.Format ("Something {0}", Items.Count.ToString ()) });
+ }
+
+ public ObservableCollection<ListItemViewModel> Items { get; } = new ObservableCollection<ListItemViewModel>();
+
+ ICommand _disabledCommand;
+
+ public ICommand DisabledCommand {
+ get {
+ if (_disabledCommand == null) {
+ _disabledCommand = new Command (() => {
+ }, () => false);
+ }
+
+ return _disabledCommand;
+ }
+ }
+
+ ICommand _addItemCommand;
+
+ public ICommand AddItemCommand {
+ get {
+ if (_addItemCommand == null) {
+ _addItemCommand = new Command (() => Items.Add (new ListItemViewModel (this) { Title = string.Format ("Something {0}", Items.Count.ToString ()) }));
+ }
+
+ return _addItemCommand;
+ }
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class ListItemViewModel : ViewModel
+ {
+ public bool CanExecute = false;
+ readonly ListViewModel _listViewModel;
+
+ public ListItemViewModel (ListViewModel listViewModel)
+ {
+ if (listViewModel == null) {
+ throw new ArgumentNullException ("listViewModel");
+ }
+ _listViewModel = listViewModel;
+ }
+
+ public string Title { get; set; }
+
+ ICommand _deleteItemCommand;
+
+ public ICommand DeleteItemCommand {
+ get {
+ if (_deleteItemCommand == null) {
+ _deleteItemCommand = new Command (() => _listViewModel.Items.Remove (this), () => CanExecute);
+ }
+
+ return _deleteItemCommand;
+ }
+ }
+
+ ICommand _otherCommand;
+
+ public ICommand OtherCommand {
+ get {
+ if (_otherCommand == null) {
+ _otherCommand = new Command (() => {
+ }, () => false);
+ }
+
+ return _otherCommand;
+ }
+ }
+ }
+
+ #if UITEST
+ [Test]
+ public void Bugzilla31330Test ()
+ {
+ var screenBounds = RunningApp.Query (q => q.Raw ("* index:0"))[0].Rect;
+
+ var cell = RunningApp.Query (c => c.Marked ("Something 1")) [0];
+ var cell2 = RunningApp.Query (c => c.Marked ("Something 2")) [0];
+ if (RunningApp is iOSApp) {
+ RunningApp.DragCoordinates (screenBounds.Width - 10, cell.Rect.CenterY, 0, cell.Rect.CenterY);
+ RunningApp.WaitForElement (c => c.Marked ("Delete"));
+ RunningApp.Tap (c => c.Marked ("Delete"));
+ RunningApp.WaitForElement (c => c.Marked ("Something 1"));
+ RunningApp.Tap (c => c.Marked ("Something 2"));
+ RunningApp.DragCoordinates (screenBounds.Width - 10, cell2.Rect.CenterY, 0, cell2.Rect.CenterY);
+ RunningApp.Tap (c => c.Marked ("Delete"));
+ RunningApp.WaitForNoElement (c => c.Marked ("Something 2"));
+ }
+ else {
+ RunningApp.TouchAndHoldCoordinates (cell.Rect.CenterX, cell.Rect.CenterY);
+ RunningApp.WaitForElement (c => c.Marked ("Delete"));
+ RunningApp.Tap (c => c.Marked ("Delete"));
+ RunningApp.Back ();
+ RunningApp.WaitForElement (c => c.Marked ("Something 1"));
+ RunningApp.Tap (c => c.Marked ("Something 2"));
+ RunningApp.TouchAndHoldCoordinates (cell2.Rect.CenterX, cell2.Rect.CenterY);
+ RunningApp.Tap (c => c.Marked ("Delete"));
+ RunningApp.WaitForNoElement (c => c.Marked ("Something 2"));
+ }
+
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31333.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31333.cs
new file mode 100644
index 00000000..3d8f68d7
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31333.cs
@@ -0,0 +1,256 @@
+using System;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Xamarin.Forms.CustomAttributes;
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+
+#endif
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Bugzilla, 31333,
+ "Focus() on Entry in ViewCell brings up keyboard, but doesn't have cursor in EditText", PlatformAffected.Android)]
+ public class Bugzilla31333 : TestContentPage
+ {
+ [Preserve (AllMembers=true)]
+ public class Model31333 : INotifyPropertyChanged
+ {
+ public string Data
+ {
+ get { return _data; }
+ set
+ {
+ _data = value;
+ OnPropertyChanged ();
+ }
+ }
+
+ bool _isFocused = false;
+ string _data;
+
+ public bool IsFocused
+ {
+ get { return _isFocused; }
+ set
+ {
+ _isFocused = value;
+ OnPropertyChanged ();
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChanged?.Invoke (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ public interface IHaveControlFocusedProperty
+ {
+ void SetBinding ();
+ }
+
+ [Preserve (AllMembers=true)]
+ public class ExtendedEntry : Entry, IHaveControlFocusedProperty
+ {
+ public static readonly BindableProperty IsControlFocusedProperty =
+ BindableProperty.Create ("IsControlFocused", typeof(bool), typeof(ExtendedEntry), false);
+
+ public bool IsControlFocused
+ {
+ get { return (bool)GetValue (IsControlFocusedProperty); }
+ set { SetValue (IsControlFocusedProperty, value); }
+ }
+
+ protected override void OnPropertyChanged (string propertyName = null)
+ {
+ base.OnPropertyChanged (propertyName);
+ if (propertyName == IsControlFocusedProperty.PropertyName) {
+ if (IsControlFocused) {
+ Focus ();
+ } else {
+ Unfocus ();
+ }
+ }
+ }
+
+ public void SetBinding ()
+ {
+ this.SetBinding (IsControlFocusedProperty, "IsFocused");
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ public class ExtendedEditor : Editor, IHaveControlFocusedProperty
+ {
+ public static readonly BindableProperty IsControlFocusedProperty =
+ BindableProperty.Create ("IsControlFocused", typeof(bool), typeof(ExtendedEditor), false);
+
+ public bool IsControlFocused
+ {
+ get { return (bool)GetValue (IsControlFocusedProperty); }
+ set { SetValue (IsControlFocusedProperty, value); }
+ }
+
+ protected override void OnPropertyChanged (string propertyName = null)
+ {
+ base.OnPropertyChanged (propertyName);
+ if (propertyName == IsControlFocusedProperty.PropertyName) {
+ if (IsControlFocused) {
+ Focus ();
+ } else {
+ Unfocus ();
+ }
+ }
+ }
+
+ public void SetBinding ()
+ {
+ this.SetBinding (IsControlFocusedProperty, "IsFocused");
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ public class ExtendedCell<T> : ViewCell where T : View, IHaveControlFocusedProperty
+ {
+ public ExtendedCell ()
+ {
+ var control = (T)Activator.CreateInstance (typeof(T));
+ control.SetBinding ();
+ control.HorizontalOptions = LayoutOptions.FillAndExpand;
+
+ View = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ HorizontalOptions = LayoutOptions.StartAndExpand,
+ Children = {
+ control
+ }
+ };
+ }
+ }
+
+ StackLayout CreateListViewTestSection (Type controlType)
+ {
+ var name = controlType.GenericTypeArguments[0].Name;
+ name = name.Replace ("Extended", "");
+
+ var button = new Button () { Text = $"Focus {name} in ListView" };
+
+ var data = new ObservableCollection<Model31333> { new Model31333 () };
+
+ var listView = new ListView {
+ VerticalOptions = LayoutOptions.Start,
+ ItemsSource = data,
+ ItemTemplate = new DataTemplate (controlType)
+ };
+
+ button.Clicked += (sender, args) => {
+ var item = data[0];
+ if (item != null) {
+ item.IsFocused = !item.IsFocused;
+ }
+ };
+
+ return new StackLayout () { Children = { button, listView } };
+ }
+
+ StackLayout CreateTableViewTestSection<T> () where T : View, IHaveControlFocusedProperty
+ {
+ var name = typeof(T).Name;
+ name = name.Replace ("Extended", "");
+
+ var button = new Button () { Text = $"Focus {name} in Table" };
+
+ var data = new Model31333 ();
+
+ var tableView = new TableView {
+ VerticalOptions = LayoutOptions.Start
+ };
+
+ var tableRoot = new TableRoot();
+ var tableSection = new TableSection();
+
+ var cell = new ExtendedCell<T> ();
+
+ cell.BindingContext = data;
+
+ tableSection.Add(cell);
+ tableRoot.Add (tableSection);
+ tableView.Root = tableRoot;
+
+ button.Clicked += (sender, args) => {
+ var item = data;
+ if (item != null) {
+ item.IsFocused = !item.IsFocused;
+ }
+ };
+
+ return new StackLayout () { Children = { button, tableView } };
+ }
+
+ protected override void Init ()
+ {
+ var entrySection = CreateListViewTestSection (typeof(ExtendedCell<ExtendedEntry>));
+ var editorSection = CreateListViewTestSection (typeof(ExtendedCell<ExtendedEditor>));
+
+ var entryTableSection = CreateTableViewTestSection<ExtendedEntry> ();
+ var editorTableSection = CreateTableViewTestSection<ExtendedEditor> ();
+
+ Content = new StackLayout () { Children = { entrySection, editorSection, entryTableSection, editorTableSection } };
+ }
+
+#if UITEST
+ [Test]
+ [UiTest (typeof(NavigationPage))]
+ public void Issue31333FocusEntryInListViewCell ()
+ {
+ RunningApp.Tap (q => q.Marked ("Focus Entry in ListView"));
+ RunningApp.Screenshot ("Entry control in ListView cell is focused");
+ RunningApp.EnterText ("Entry in ListView Success");
+ Assert.True(RunningApp.Query(query => query.Text("Entry in ListView Success")).Length > 0);
+ RunningApp.Screenshot ("Entry in ListView Success");
+ }
+
+ [Test]
+ [UiTest (typeof(NavigationPage))]
+ public void Issue31333FocusEditorInListViewCell ()
+ {
+ RunningApp.Tap (q => q.Marked ("Focus Editor in ListView"));
+ RunningApp.Screenshot ("Editor control in ListView cell is focused");
+ RunningApp.EnterText ("Editor in ListView Success");
+ Assert.True(RunningApp.Query(query => query.Text("Editor in ListView Success")).Length > 0);
+ RunningApp.Screenshot ("Editor in ListView Success");
+ }
+
+
+ [Test]
+ [UiTest (typeof(NavigationPage))]
+ public void Issue31333FocusEntryInTableViewCell ()
+ {
+ RunningApp.Tap (q => q.Marked ("Focus Entry in Table"));
+ RunningApp.Screenshot ("Entry control in TableView cell is focused");
+ RunningApp.EnterText ("Entry in TableView Success");
+ Assert.True(RunningApp.Query(query => query.Text("Entry in TableView Success")).Length > 0);
+ RunningApp.Screenshot ("Entry in TableView Success");
+ }
+
+ [Test]
+ [UiTest (typeof(NavigationPage))]
+ public void Issue31333FocusEditorInTableViewCell ()
+ {
+ RunningApp.Tap (q => q.Marked ("Focus Editor in Table"));
+ RunningApp.Screenshot ("Editor control in TableView cell is focused");
+ RunningApp.EnterText ("Editor in TableView Success");
+ Assert.True(RunningApp.Query(query => query.Text("Editor in TableView Success")).Length > 0);
+ RunningApp.Screenshot ("Editor in TableView Success");
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31366.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31366.cs
new file mode 100644
index 00000000..75853f1d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31366.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+
+#endif
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 31366, "Pushing and then popping a page modally causes ArgumentOutOfRangeException",
+ PlatformAffected.All)]
+ public class Bugzilla31366 : TestNavigationPage
+ {
+ protected override void Init ()
+ {
+ var page1 = new ContentPage () { Title = "Page1" };
+
+ var successLabel = new Label ();
+ var startPopOnAppearing = new Button () { Text = "Start PopOnAppearing Test" };
+ var startModalStack = new Button () { Text = "Start ModalStack Test" };
+
+ page1.Content = new StackLayout () {
+ Children = { startPopOnAppearing, startModalStack, successLabel }
+ };
+
+ var popOnAppearing = new ContentPage () {
+ Title = "PopOnAppearing",
+ Content = new StackLayout ()
+ };
+
+ popOnAppearing.Appearing += async (sender, args) => {
+ await Task.Yield ();
+ await popOnAppearing.Navigation.PopModalAsync ();
+ };
+
+ startPopOnAppearing.Clicked += async (sender, args) => {
+ successLabel.Text = string.Empty;
+
+ await page1.Navigation.PushModalAsync (popOnAppearing);
+
+ successLabel.Text = "If this is visible, the PopOnAppearing test has passed.";
+ };
+
+ startModalStack.Clicked += async (sender, args) => {
+ successLabel.Text = string.Empty;
+
+ var intermediatePage = new ContentPage () {
+ Content = new StackLayout () {
+ Children = {
+ new Label () { Text = "If this is visible, the modal stack test has passed." }
+ }
+ }
+ };
+
+ await intermediatePage.Navigation.PushModalAsync (popOnAppearing);
+
+ await page1.Navigation.PushModalAsync (intermediatePage);
+ };
+
+ PushAsync (page1);
+ }
+
+
+#if UITEST
+ [Test]
+ [UiTest (typeof (NavigationPage))]
+ public void Issue31366PushingAndPoppingModallyCausesArgumentOutOfRangeException ()
+ {
+ RunningApp.Tap (q => q.Marked ("Start PopOnAppearing Test"));
+ RunningApp.WaitForElement (q => q.Marked ("If this is visible, the PopOnAppearing test has passed."));
+ }
+
+ [Test]
+ [UiTest (typeof (NavigationPage))]
+ public void Issue31366PushingWithModalStackCausesIncorrectStackOrder ()
+ {
+ RunningApp.Tap (q => q.Marked ("Start ModalStack Test"));
+ RunningApp.WaitForElement (q => q.Marked ("If this is visible, the modal stack test has passed."));
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31395.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31395.cs
new file mode 100644
index 00000000..57b9b98c
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31395.cs
@@ -0,0 +1,54 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ // don't forget to update C:\Users\chrisk\Documents\git\DuploBuddy\Xamarin.Forms.ControlGallery.Android\LinkerRoots.cs
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 31395, "Crash when switching MainPage and using a Custom Render")]
+ public class Bugzilla31395 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ Content = new CustomContentView { // Replace with ContentView and everything works fine
+ Content = new StackLayout {
+ VerticalOptions = LayoutOptions.Center,
+ Children = {
+ new Button {
+ Text = "Switch Main Page",
+ Command = new Command (() => SwitchMainPage ())
+ }
+ }
+ }
+ };
+ }
+
+ void SwitchMainPage ()
+ {
+ Application.Current.MainPage = new ContentPage { Content = new Label { Text = "Hello" } };
+ }
+
+ public class CustomContentView : ContentView
+ {
+
+ }
+
+ #if UITEST
+ [Test]
+ public void Bugzilla31395Test ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Switch Main Page"));
+ Assert.DoesNotThrow (() => {
+ RunningApp.Tap (c => c.Marked ("Switch Main Page"));
+ });
+ RunningApp.WaitForElement (q => q.Marked ("Hello"));
+ }
+ #endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31602.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31602.cs
new file mode 100644
index 00000000..86e8bcb4
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31602.cs
@@ -0,0 +1,130 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using System.Windows.Input;
+
+#if UITEST
+using Xamarin.UITest;
+using Xamarin.UITest.iOS;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 31602, "not possible to programmatically open master page after iPad landscape -> portrait rotation, also tests 31664")]
+ public class Bugzilla31602 : TestMasterDetailPage
+ {
+ protected override void Init ()
+ {
+ BindingContext = new MasterViewModel1 ();
+ ((MasterViewModel1)BindingContext).MasterPage = this;
+
+ Master = new SidemenuPage ();
+ Detail = new NavigationPage (new DetailPage1 (Master as SidemenuPage));
+ }
+
+ public class SidemenuPage : ContentPage
+ {
+ public SidemenuPage ()
+ {
+ Title = "Side";
+ Icon = "menuIcon.png";
+ var lbl = new Label { Text = "SideMenu" };
+ var btn = new Button { Text = "Menu Opener" };
+
+ btn.SetBinding (Button.CommandProperty, new Binding ("OpenSideMenuCommand"));
+
+ var stackpanel = new StackLayout { VerticalOptions = LayoutOptions.Center };
+
+ stackpanel.Children.Add (btn);
+ stackpanel.Children.Add (lbl);
+ Content = stackpanel;
+ }
+
+ public void ChangeIcon() {
+ Icon = "bank.png";
+ }
+ }
+
+ public class DetailPage1 : ContentPage
+ {
+ SidemenuPage _sideMenu;
+
+ public DetailPage1 (SidemenuPage menu)
+ {
+ _sideMenu = menu;
+ Title = "Detail";
+ var btns = new Button { Text = "Change Icon" };
+ btns.Clicked += (object sender, EventArgs e) => {
+ _sideMenu.ChangeIcon();
+ };
+ var btn = new Button { Text = "Sidemenu Opener" };
+ btn.SetBinding (Button.CommandProperty, new Binding ("OpenSideMenuCommand"));
+ Content = new StackLayout { Children = { btns, btn} };
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class MasterViewModel1 : INotifyPropertyChanged
+ {
+ public MasterDetailPage MasterPage;
+
+ public event PropertyChangedEventHandler PropertyChanged = delegate { };
+
+ protected void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ if (PropertyChanged != null) {
+ PropertyChanged (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+
+ bool _isMenuOpen;
+
+ public bool IsMenuOpen {
+ get { return _isMenuOpen; }
+ private set {
+ if (_isMenuOpen != value) {
+ System.Diagnostics.Debug.WriteLine ("setting new sidemenu visibility flag to: " + value);
+ _isMenuOpen = value;
+ OnPropertyChanged ();
+ }
+ }
+ }
+
+ public ICommand OpenSideMenuCommand { get; private set; }
+
+ public MasterViewModel1 ()
+ {
+ IsMenuOpen = true;
+ OpenSideMenuCommand = new Command (OpenSideMenu);
+ }
+
+ void OpenSideMenu ()
+ {
+ IsMenuOpen = true;
+ MasterPage.IsPresented = IsMenuOpen;
+ }
+ }
+
+ #if UITEST
+ [Test]
+ public void Bugzilla31602Test ()
+ {
+ var appAs = RunningApp as iOSApp;
+ if (appAs != null && appAs.Device.IsTablet) {
+ RunningApp.Tap (q => q.Marked ("Sidemenu Opener"));
+ RunningApp.WaitForElement (q => q.Marked ("SideMenu"));
+ RunningApp.SetOrientationLandscape ();
+ RunningApp.WaitForElement (q => q.Marked ("SideMenu"));
+ RunningApp.SetOrientationPortrait ();
+ RunningApp.WaitForNoElement (q => q.Marked ("SideMenu"));
+ RunningApp.Tap (q => q.Marked ("Sidemenu Opener"));
+ RunningApp.WaitForElement (q => q.Marked ("SideMenu"));
+ }
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31964.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31964.cs
new file mode 100644
index 00000000..da673f8f
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31964.cs
@@ -0,0 +1,116 @@
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 31964, "[Xamarin.Forms SwitchCell]OnChange() did not work for Windows platform",
+ PlatformAffected.WinRT)]
+ public class Bugzilla31964 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var listView = new ListView ();
+
+ var selection = new Selection ();
+ listView.SetBinding (ListView.ItemsSourceProperty, "Items");
+
+ listView.ItemTemplate = new DataTemplate (() => {
+ var cell = new SwitchCell ();
+ cell.SetBinding (SwitchCell.TextProperty, "Name");
+ cell.SetBinding (SwitchCell.OnProperty, "IsSelected", BindingMode.TwoWay);
+ return cell;
+ });
+
+ var instructions = new Label {
+ FontSize = 16,
+ Text =
+ "The label at the bottom should equal the number of switches which are in the 'on' position. Flip some of the switches. If the number at the bottom does not equal the number of 'on' switches, the test has failed."
+ };
+
+ var label = new Label { FontSize = 24 };
+ label.SetBinding (Label.TextProperty, "SelectedCount");
+
+ Content = new StackLayout {
+ VerticalOptions = LayoutOptions.Fill,
+ Children = {
+ instructions,
+ listView,
+ label
+ }
+ };
+
+ BindingContext = selection;
+ }
+
+ [Preserve (AllMembers = true)]
+ public class SelectionItem : INotifyPropertyChanged
+ {
+ bool _isSelected;
+
+ public string Name { get; set; }
+
+ public bool IsSelected
+ {
+ get { return _isSelected; }
+ set
+ {
+ _isSelected = value;
+ OnPropertyChanged ();
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChanged?.Invoke (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Selection : INotifyPropertyChanged
+ {
+ int _selectedCount;
+
+ public Selection ()
+ {
+ Items = new List<SelectionItem> {
+ new SelectionItem { Name = "Item1" },
+ new SelectionItem { Name = "Item2" },
+ new SelectionItem { Name = "Item3", IsSelected = true },
+ new SelectionItem { Name = "Item4" },
+ new SelectionItem { Name = "Item5" }
+ };
+
+ SelectedCount = Items.Count (i => i.IsSelected);
+
+ foreach (SelectionItem selectionItem in Items) {
+ selectionItem.PropertyChanged += (sender, args) => SelectedCount = Items.Count (i => i.IsSelected);
+ }
+ }
+
+ public List<SelectionItem> Items { get; }
+
+ public int SelectedCount
+ {
+ get { return _selectedCount; }
+ set
+ {
+ _selectedCount = value;
+ OnPropertyChanged ();
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChanged?.Invoke (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31967.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31967.xaml
new file mode 100644
index 00000000..3cc33841
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31967.xaml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Bugzilla31967">
+ <Grid VerticalOptions="Start"
+ Padding = "20">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="auto" />
+ <RowDefinition Height="{Binding Path=ToolbarHeight,Mode=TwoWay}" />
+ </Grid.RowDefinitions>
+ <Button Text="Click"
+ Command="{Binding Fire}"/>
+ <Label Grid.Row="1"
+ Text="Hello there"
+ BackgroundColor="Red"
+ VerticalOptions="FillAndExpand"/>
+ </Grid>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31967.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31967.xaml.cs
new file mode 100644
index 00000000..acb8230e
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla31967.xaml.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms.CustomAttributes;
+
+using Xamarin.Forms;
+using System.ComponentModel;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 31967, "Grid Layout on Bound RowDefinition")]
+ public partial class Bugzilla31967 : ContentPage
+ {
+ public Bugzilla31967 ()
+ {
+ InitializeComponent ();
+ BindingContext = new Bugzilla31967Vm ();
+ }
+
+ public class Bugzilla31967Vm: INotifyPropertyChanged {
+ public Command Fire {
+ get { return new Command (() => ToolbarHeight = 50); }
+ }
+
+ GridLength _toolbarHeight;
+ public GridLength ToolbarHeight {
+ get { return _toolbarHeight; }
+ set {
+ _toolbarHeight = value;
+ OnPropertyChanged ("ToolbarHeight");
+ }
+ }
+
+ protected void OnPropertyChanged (string propertyName)
+ {
+ var handler = PropertyChanged;
+ if (handler != null)
+ handler (this, new PropertyChangedEventArgs (propertyName));
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+ }
+ }
+#endif
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32034.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32034.cs
new file mode 100644
index 00000000..97ccad1a
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32034.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Bugzilla, 32034, "MissingMethodException while pushing and popping pages",PlatformAffected.Android, NavigationBehavior.PushModalAsync)]
+ public class Bugzilla32034 : NavigationPage
+ {
+ public class ButtonPage : ContentPage
+ {
+ public ButtonPage ()
+ {
+ Content = new StackLayout {
+ Children = {
+ new Button {
+ Text = "Push", Command = new Command (o => ((NavigationPage) Parent).PushAsync (new ButtonPage ()))
+ },
+ new Button {
+ Text = "Pop", Command = new Command (o => ((NavigationPage) Parent).Navigation.PopAsync ())
+ },
+ },
+ };
+ }
+ }
+
+ public Bugzilla32034 () : base (new ButtonPage ())
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32040.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32040.cs
new file mode 100644
index 00000000..a6d9c830
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32040.cs
@@ -0,0 +1,59 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 32040, "EntryCell.Tapped or SwitchCell.Tapped does not fire when within a TableView ")]
+ public class Bugzilla32040 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ var switchCell = new SwitchCell { Text = "blahblah" };
+ switchCell.Tapped += (s, e) =>
+ {
+ switchCell.Text = "Tapped";
+ };
+ switchCell.OnChanged += (sender, e) => {
+ switchCell.Text = "Switched";
+ };
+
+ var entryCell = new EntryCell { Text = "yaddayadda" };
+ entryCell.XAlign = TextAlignment.End;
+ entryCell.Label = "Click Here";
+ entryCell.Tapped += (s, e) =>
+ {
+ entryCell.Text = "Tapped";
+ };
+ entryCell.Completed += (sender, e) => {
+ entryCell.Text = "Completed";
+ };
+
+ // The root page of your application
+ Content = new TableView {
+ Intent = TableIntent.Form,
+ Root = new TableRoot ("Table Title") {
+ new TableSection ("Section 1 Title") {
+ switchCell,
+ entryCell
+ }
+ }
+ };
+ }
+#if UITEST
+ [Test]
+ public void TappedWorksForEntryAndSwithCellTest ()
+ {
+ RunningApp.Tap (q => q.Marked ("blahblah"));
+ RunningApp.Tap (q => q.Marked ("Click Here"));
+ Assert.GreaterOrEqual (RunningApp.Query (q => q.Marked ("Tapped")).Length, 2);
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32148.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32148.cs
new file mode 100644
index 00000000..76e3819b
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32148.cs
@@ -0,0 +1,240 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Collections.Generic;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 32148, " Pull to refresh hides the first item on a list view")]
+ public class Bugzilla32148 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ Button _searchBtn;
+ ListView _contactsListView;
+ ObservableCollection<Grouping1<string, ContactViewModel1>> _listViewItemSource;
+
+ protected override void Init ()
+ {
+ Title = "Contacts";
+ Content = CreateContent();
+ // Disable the await warning
+ #pragma warning disable 4014
+ LoadContactsAsync();
+ #pragma warning restore 4014
+ }
+
+ Layout CreateContent()
+ {
+ _listViewItemSource = new ObservableCollection<Grouping1<string, ContactViewModel1>>();
+
+ _contactsListView = new ListView()
+ {
+ ItemsSource = _listViewItemSource,
+ IsPullToRefreshEnabled = true,
+ IsGroupingEnabled = true,
+ GroupShortNameBinding = new Binding("Key"),
+ GroupHeaderTemplate = new DataTemplate(typeof(HeaderCell)),
+ HasUnevenRows = true,
+ ItemTemplate = new DataTemplate(typeof(ContactItemTemplate))
+ };
+
+ _contactsListView.Refreshing += contactsListView_Refreshing;
+ _searchBtn = new Button() { Text = "Search" };
+ _searchBtn.Clicked += (object sender, EventArgs e) => _contactsListView.BeginRefresh ();
+
+ Grid grd = new Grid ();
+ grd.RowDefinitions.Add (new RowDefinition () { Height = GridLength.Auto } );
+ grd.RowDefinitions.Add (new RowDefinition ());
+ grd.Children.Add (_searchBtn);
+ grd.Children.Add (_contactsListView);
+ Grid.SetRow (_contactsListView, 1);
+ return grd;
+ }
+
+ async void contactsListView_Refreshing(object sender, EventArgs e)
+ {
+ await Task.Delay (1000);
+ await LoadContactsAsync(true);
+ }
+
+ async Task LoadContactsAsync(bool isPullToRefresh = false)
+ {
+ await ReadFromDbAsync();
+ _contactsListView.IsRefreshing &= !isPullToRefresh;
+ }
+
+ async Task ReadFromDbAsync(Expression<Func<Contact1, bool>> searchExpression = null)
+ {
+ await Task.Run(() =>
+ {
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ // If we want to filter the data, GetItems by expression
+ IList<Contact1> contactEntities = new List<Contact1>();
+ List<ContactViewModel1> data = new List<ContactViewModel1>();
+
+ if (contactEntities == null || contactEntities.Count == 0)
+ {
+ // Fill with dummy contacts
+ for (int i = 0; i < 20; i++)
+ {
+ Contact1 contact = new Contact1()
+ {
+ FirstName = "Contact" + i,
+ LastName = "LastName",
+ Company = "Company" + i
+ } ;
+ contactEntities.Add(contact);
+ }
+ }
+
+ // Create Contact items for the listView
+ foreach (Contact1 contact in contactEntities)
+ {
+ ContactViewModel1 contactItem = new ContactViewModel1()
+ {
+ FirstName = contact.FirstName,
+ LastName = contact.LastName,
+ FullName = contact.FirstName + " " + contact.LastName,
+ Company = contact.Company,
+ } ;
+
+ data.Add(contactItem);
+ }
+
+ // Sort, order and group the contacts
+ var contacts = from contact in data
+ orderby contact.LastName, contact.FirstName
+ group contact by contact.FirstNameSort into contactGroup
+ select new Grouping1<string, ContactViewModel1>(contactGroup.Key, contactGroup);
+
+ // Create a new collection of groups
+ var grouppedContacts = new ObservableCollection<Grouping1<string, ContactViewModel1>>(contacts);
+
+ _contactsListView.ItemsSource = grouppedContacts;
+ } );
+ } );
+ }
+
+ public class Grouping1<K, T> : ObservableCollection<T>
+ {
+ public K Key { get; private set; }
+
+ public Grouping1(K key, IEnumerable<T> items)
+ {
+ Key = key;
+ foreach (T item in items)
+ {
+ Items.Add(item);
+ }
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class ContactViewModel1
+ {
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+ public string FullName { get; set; }
+ public string Company { get; set; }
+ public ImageSource IconSource { get; set; }
+
+ public string FirstNameSort
+ {
+ get
+ {
+ if (string.IsNullOrWhiteSpace(FirstName) || FirstName.Length == 0)
+ {
+ return "?";
+ }
+
+ return FirstName[0].ToString().ToUpper();
+ }
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Contact1
+ {
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+ public string Company { get; set; }
+ public byte[] ProfilePicture { get; set; }
+ public string Email { get; set; }
+ public string Mobile { get; set; }
+ public string RoomNumber { get; set; }
+ public string Street { get; set; }
+ public string Zip { get; set; }
+ public string City { get; set; }
+ public string CountryCode { get; set; }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class HeaderCell : ViewCell
+ {
+ public HeaderCell()
+ {
+ Height = 23;
+
+ Label title = new Label
+ {
+ TextColor = Color.White,
+ VerticalOptions = LayoutOptions.Center
+ } ;
+
+ title.SetBinding(Label.TextProperty, "Key");
+
+ View = new StackLayout
+ {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ HeightRequest = 23,
+ BackgroundColor = Color.Pink,
+ Orientation = StackOrientation.Horizontal,
+ Padding = new Thickness(Sizes.GroupingSidePadding, 0, 0, 0),
+ Children = { title }
+ };
+ }
+
+ struct Sizes
+ {
+ public static readonly double GroupingSidePadding = 5;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class ContactItemTemplate : ImageCell
+ {
+ public ContactItemTemplate()
+ : base()
+ {
+
+ SetBinding(TextProperty, new Binding("FullName"));
+ SetBinding(DetailProperty, new Binding("Company"));
+ SetBinding(ImageSourceProperty, new Binding("IconSource"));
+
+ Height = 50;
+ }
+ }
+
+ #if UITEST
+ [Test]
+ public void Bugzilla32148Test ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Contact0 LastName"));
+ RunningApp.Tap (q => q.Marked("Search"));
+ RunningApp.WaitForElement (q => q.Marked ("Contact0 LastName"));
+ RunningApp.Screenshot ("For manual review, is the first cell visible?");
+ }
+ #endif
+ }
+
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32230.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32230.cs
new file mode 100644
index 00000000..e7d99b06
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32230.cs
@@ -0,0 +1,59 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 32230, "isPresentedChanged raises multiple times")]
+ public class Bugzilla32230 : TestMasterDetailPage // or TestMasterDetailPage, etc ...
+ {
+ Label _lblCount;
+ Button _btnOpen;
+ Button _btnClose;
+ int _count;
+
+ protected override void Init ()
+ {
+ _lblCount = new Label { Text = _count.ToString (), AutomationId = "lblCount" };
+ _btnOpen = new Button { Text = "Open", AutomationId = "btnOpen",
+ Command = new Command (() => {
+ IsPresented = true;
+ })
+ };
+ _btnClose = new Button { Text = "Close", AutomationId = "btnClose",
+ Command = new Command (() => {
+ IsPresented = false;
+ })
+ };
+
+ Master = new ContentPage {
+ Title = "Master",
+ Content = new StackLayout { Children = { _lblCount, _btnClose } }
+ };
+
+ Detail = new NavigationPage (new ContentPage { Content = _btnOpen });
+ IsPresentedChanged += (object sender, EventArgs e) => {
+ _count++;
+ _lblCount.Text = _count.ToString();
+ };
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla32230Test ()
+ {
+ RunningApp.Tap (q => q.Marked ("btnOpen"));
+ Assert.AreEqual ("1", RunningApp.Query (q => q.Marked ("lblCount"))[0].Text);
+ RunningApp.Tap (q => q.Marked ("btnClose"));
+ RunningApp.Tap (q => q.Marked ("btnOpen"));
+ Assert.AreEqual ("3", RunningApp.Query (q => q.Marked ("lblCount"))[0].Text);
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32447.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32447.xaml
new file mode 100644
index 00000000..654cf820
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32447.xaml
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<local:TestContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:local="clr-namespace:Xamarin.Forms.Controls"
+xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Forms.Controls.Bugzilla32447">
+ <local:TestContentPage.Content>
+ <TableView HasUnevenRows="true" Intent="Form" BackgroundColor="#DADEE3">
+ <TableRoot>
+ <TableSection Title="Section 1">
+ <ViewCell >
+ <Label Text="Sample" />
+ </ViewCell>
+ <ViewCell >
+ <Picker Title = "Gender" HorizontalOptions="Start">
+ <Picker.Items>
+ <x:String>Male</x:String>
+ <x:String>Female</x:String>
+ <x:String>N/A</x:String>
+ </Picker.Items>
+ </Picker>
+ </ViewCell>
+
+ <ViewCell >
+ <Label Text="Sample" />
+ </ViewCell>
+
+ <ViewCell >
+ <Picker Title = "Gender" HorizontalOptions="Start">
+ <Picker.Items>
+ <x:String>Male</x:String>
+ <x:String>Female</x:String>
+ <x:String>N/A</x:String>
+ </Picker.Items>
+ </Picker>
+ </ViewCell>
+ <ViewCell >
+ <Picker Title = "Gender" HorizontalOptions="Start">
+ <Picker.Items>
+ <x:String>Male</x:String>
+ <x:String>Female</x:String>
+ <x:String>N/A</x:String>
+ </Picker.Items>
+ </Picker>
+ </ViewCell>
+
+ <ViewCell >
+ <Label Text="Sample" />
+ </ViewCell>
+
+ <ViewCell >
+ <Picker Title = "Gender" HorizontalOptions="Start">
+ <Picker.Items>
+ <x:String>Male</x:String>
+ <x:String>Female</x:String>
+ <x:String>N/A</x:String>
+ </Picker.Items>
+ </Picker>
+ </ViewCell>
+ </TableSection>
+
+ <TableSection Title="Section 2">
+ <ViewCell >
+ <Picker x:Name="genderPicker" Title = "Gender" HorizontalOptions="Start">
+ <Picker.Items>
+ <x:String>Male</x:String>
+ <x:String>Female</x:String>
+ <x:String>N/A</x:String>
+ </Picker.Items>
+ </Picker>
+ </ViewCell>
+ <ViewCell >
+ <Picker Title = "Gender" HorizontalOptions="Start">
+ <Picker.Items>
+ <x:String>Male</x:String>
+ <x:String>Female</x:String>
+ <x:String>N/A</x:String>
+ </Picker.Items>
+ </Picker>
+ </ViewCell>
+
+ <ViewCell >
+ <Label Text="Sample" />
+ </ViewCell>
+
+ <ViewCell >
+ <Picker Title = "Gender" HorizontalOptions="Start">
+ <Picker.Items>
+ <x:String>Male</x:String>
+ <x:String>Female</x:String>
+ <x:String>N/A</x:String>
+ </Picker.Items>
+ </Picker>
+ </ViewCell>
+ <ViewCell >
+ <Label Text="Sample" />
+ </ViewCell>
+
+ <ViewCell >
+ <Picker Title = "Gender" HorizontalOptions="Start">
+ <Picker.Items>
+ <x:String>Male</x:String>
+ <x:String>Female</x:String>
+ <x:String>N/A</x:String>
+ </Picker.Items>
+ </Picker>
+ </ViewCell>
+
+ <ViewCell >
+ <Label Text="Sample" />
+ </ViewCell>
+ </TableSection>
+
+ <TableSection Title="Section 2">
+ <ViewCell >
+ <Picker Title = "Gender" HorizontalOptions="Start">
+ <Picker.Items>
+ <x:String>Male</x:String>
+ <x:String>Female</x:String>
+ <x:String>N/A</x:String>
+ </Picker.Items>
+ </Picker>
+ </ViewCell>
+
+ <ViewCell >
+ <Label Text="Sample" />
+ </ViewCell>
+
+ <ViewCell >
+ <Label Text="Sample" />
+ </ViewCell>
+ <ViewCell >
+ <Picker Title = "Gender" HorizontalOptions="Start">
+ <Picker.Items>
+ <x:String>Male</x:String>
+ <x:String>Female</x:String>
+ <x:String>N/A</x:String>
+ </Picker.Items>
+ </Picker>
+ </ViewCell>
+ <ViewCell >
+ <Picker Title = "Gender" HorizontalOptions="Start">
+ <Picker.Items>
+ <x:String>Male</x:String>
+ <x:String>Female</x:String>
+ <x:String>N/A</x:String>
+ </Picker.Items>
+ </Picker>
+ </ViewCell>
+
+ <ViewCell >
+ <Label Text="Sample" />
+ </ViewCell>
+ <ViewCell >
+ <Label Text="Sample" />
+ </ViewCell>
+ </TableSection>
+
+ </TableRoot>
+ </TableView>
+ </local:TestContentPage.Content>
+</local:TestContentPage>
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32447.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32447.xaml.cs
new file mode 100644
index 00000000..719b10d0
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32447.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 32447, "[iOS] App crash when scrolling quickly through a TableView that has Pickers in the cells.", PlatformAffected.iOS)]
+ public partial class Bugzilla32447 : TestContentPage
+ {
+ public Bugzilla32447 ()
+ {
+ #if APP
+
+ InitializeComponent ();
+
+ #endif
+ }
+
+ protected override void Init ()
+ {
+
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32462.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32462.cs
new file mode 100644
index 00000000..86d75e99
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32462.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Linq;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 32462, "Crash after a page disappeared if a ScrollView is in the HeaderTemplate property of a ListView", PlatformAffected.Android)]
+ public class Bugzilla32462 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ [Preserve (AllMembers = true)]
+ public class ListViewPage : ContentPage
+ {
+ public ListViewPage ()
+ {
+ var scrollview = new ScrollView {
+ Orientation = ScrollOrientation.Horizontal,
+ Content = new Label { Text = "some looooooooooooooooooooooooooooooooooooooooooooooooooooooog text" }
+ };
+ var stacklayout = new StackLayout ();
+ stacklayout.Children.Add (scrollview);
+ string[] list = Enumerable.Range (0, 40).Select (c => $"some text {c}").ToArray ();
+ var listview = new ListView { AutomationId = "listview", Header = stacklayout, ItemsSource = list };
+ Content = listview;
+
+ listview.ScrollTo (list[39], ScrollToPosition.Center, false);
+ }
+ }
+
+ protected override void Init ()
+ {
+ var button = new Button {
+ Text = "Click!",
+ };
+ button.Clicked += (object sender, EventArgs e) => Navigation.PushAsync (new ListViewPage ());
+ Content = button;
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla36729Test ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Click!"));
+ RunningApp.Tap (q => q.Marked ("Click!"));
+ RunningApp.WaitForElement (q => q.Marked ("listview"));
+ RunningApp.WaitForElement (q => q.Marked ("some text 35"));
+ RunningApp.Back ();
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32487.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32487.cs
new file mode 100644
index 00000000..2cccc574
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32487.cs
@@ -0,0 +1,50 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 32487, " webview in tabbedpage has black margin")]
+ public class Bugzilla32487 : TestTabbedPage
+ {
+ protected override void Init ()
+ {
+ var cp = new ContentPage ();
+ cp.Title = "bugzila 30047";
+ Children.Add (cp);
+
+ var cp1 = new ContentPage ();
+ cp1.Title = "bugzila 32487";
+ var sl = new StackLayout ();
+ var wv = new WebView ();
+
+ var htmlSource = new HtmlWebViewSource ();
+ htmlSource.Html = "<h3>Welcome to the real-time HTML editor!</h3>\n<p>Try scroll this page, you will see black margins if it isn't working ok</p>";
+ wv.Source = htmlSource;
+ sl.Children.Add (wv);
+ cp1.Content = wv;
+
+ var btn = new Button { Text = "tap and rotate device after ", Command = new Command (async () => {
+ ContentPage cp2 = new ContentPage ();
+ cp.Title = "rotation";
+ var grd = new Grid ();
+ grd.RowDefinitions.Add (new RowDefinition { Height = GridLength.Auto });
+ grd.RowDefinitions.Add (new RowDefinition ());
+ WebView wv1 = new WebView { Source = "http://xamarin.com" };
+ Grid.SetRow (wv1, 1);
+ grd.Children.Add (wv1);
+ grd.Children.Add (new Button {
+ Text = "Back",
+ BackgroundColor = Color.Red,
+ Command = new Command (() => Navigation.PopModalAsync ())
+ });
+ cp2.Content = grd;
+ await Navigation.PushModalAsync (cp2);
+ })
+ };
+ cp.Content = btn;
+
+ Children.Add (cp);
+ Children.Add (cp1);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32615.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32615.cs
new file mode 100644
index 00000000..405133e0
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32615.cs
@@ -0,0 +1,70 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Threading.Tasks;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 32615, "OnAppearing is not called on previous page when modal page is popped")]
+ public class Bugzilla32615 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ int _counter;
+ Label _textField;
+ protected override void Init ()
+ {
+ var btnModal = new Button { AutomationId = "btnModal", Text = "open", HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand };
+ btnModal.Clicked += async (sender, e) => await Navigation.PushModalAsync (new Bugzilla32615Page2 ());
+ _textField = new Label { AutomationId = "lblCount"};
+ var layout = new StackLayout ();
+ layout.Children.Add (btnModal);
+ layout.Children.Add (_textField);
+ // Initialize ui here instead of ctor
+ Content = layout;
+ }
+
+ protected override void OnAppearing()
+ {
+ _textField.Text = _counter++.ToString();
+ }
+
+ class Bugzilla32615Page2 : ContentPage
+ {
+ public Bugzilla32615Page2 ()
+ {
+ var btnPop = new Button { AutomationId = "btnPop", Text = "pop", HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand };
+ btnPop.Clicked += async (sender, e) => await Navigation.PopModalAsync ();
+ Content = btnPop;
+ }
+
+ protected override void OnDisappearing ()
+ {
+ System.Diagnostics.Debug.WriteLine ("Disappearing Modal");
+ base.OnDisappearing ();
+ }
+
+ protected override void OnAppearing ()
+ {
+ System.Diagnostics.Debug.WriteLine ("Appearing Modal");
+ base.OnAppearing ();
+ }
+ }
+
+#if UITEST
+ [Test]
+ public async void Bugzilla32615Test ()
+ {
+ RunningApp.Tap (q => q.Marked ("btnModal"));
+ RunningApp.Tap (q => q.Marked ("btnPop"));
+ await Task.Delay (1000);
+ var lbl = RunningApp.WaitForElement (c => c.Marked("lblCount"));
+ Assert.AreEqual ("1", lbl [0].Text);
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32691.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32691.cs
new file mode 100644
index 00000000..7277f606
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32691.cs
@@ -0,0 +1,60 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ public interface ICacheService
+ {
+ void ClearImageCache ();
+ }
+
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 32691, "Clearing an image by setting Image.Source to null, while Image.IsLoading is true, doesn't work.")]
+ public class Bugzilla32691 : TestContentPage
+ {
+ const string KSetImageSource = "SET IMAGE SOURCE";
+ const string KClearImageSource = "CLEAR IMAGE SOURCE";
+
+ protected override void Init ()
+ {
+ var label = new Label () { XAlign = TextAlignment.Center };
+ var image = new Image ();
+
+ image.PropertyChanged += (sender, e) => {
+ if (e.PropertyName == "IsLoading")
+ label.Text = image.IsLoading ? "Loading" : "Done";
+ };
+
+ var btnSetOrClear = new Button () { Text = KSetImageSource, AutomationId = "btnLoad" };
+
+ btnSetOrClear.Clicked += delegate {
+ if (btnSetOrClear.Text == KSetImageSource) {
+ ClearImageCache ();
+ image.Source =
+ "http://www.public-domain-image.com/free-images/miscellaneous/big-high-border-fence.jpg";
+ btnSetOrClear.Text = KClearImageSource;
+ } else {
+ image.Source = null;
+ btnSetOrClear.Text = KSetImageSource;
+ }
+ };
+
+ Content = new StackLayout {
+ Orientation = StackOrientation.Vertical,
+ Padding = new Thickness (10),
+ Children = { btnSetOrClear, image, label }
+ };
+ }
+
+ void ClearImageCache ()
+ {
+ var cacheService = DependencyService.Get<ICacheService> ();
+ cacheService?.ClearImageCache ();
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32776.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32776.cs
new file mode 100644
index 00000000..f6d0b4c4
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32776.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+ [Issue (IssueTracker.Bugzilla, 32776, "MasterDetail page - page title not showing for Windows Phone 8.1 (any orientation) or in Windows 8.1 (portrait orientation).", PlatformAffected.WinRT, NavigationBehavior.PushModalAsync)]
+ public class Bugzilla32776
+ : MasterDetailPage
+ {
+ public Bugzilla32776 ()
+ {
+ Master = new ContentPage { Title = "Content page" };
+ Detail = new NavigationPage (new ContentPage {
+ Title = "Test"
+ });
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32801.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32801.cs
new file mode 100644
index 00000000..c285aeff
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32801.cs
@@ -0,0 +1,92 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+using Xamarin.UITest.iOS;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 32801, "Memory Leak in TabbedPage + NavigationPage")]
+ public class Bugzilla32801 : TestTabbedPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ Children.Add (new NavigationPage (new TestDemoPage (1)) { Title = "Tab", Icon = "bank.png" });
+ Children.Add (new NavigationPage (new TestDemoPage (1)) { Title = "Tab 1", Icon = "bank.png" });
+
+ }
+
+ public class TestDemoPage : ContentPage
+ {
+ int _level = 0;
+
+ public TestDemoPage (int level)
+ {
+ _level = level;
+
+ System.Diagnostics.Debug.WriteLine ("Page Level {0} : Created", _level);
+
+ Title = string.Format ("Level {0}", level);
+
+ var lblStack = new Label ();
+
+ var buttonAdd = new Button {
+ Text = "Add Level",
+ AutomationId = "btnAdd",
+ BackgroundColor = Color.Aqua
+ };
+
+ buttonAdd.Clicked += (sender, e) => Navigation.PushAsync (new TestDemoPage (_level + 1));
+
+ var buttonStack = new Button {
+ Text = "Show Navigation Stack",
+ AutomationId = "btnStack",
+ BackgroundColor = Color.Aqua
+ };
+
+ buttonStack.Clicked += (object sender, EventArgs e) => {
+ lblStack.Text = "Stack " + Navigation.NavigationStack.Count.ToString ();
+ System.Diagnostics.Debug.WriteLine ("------------------------------------------------------------");
+ foreach (TestDemoPage page in Navigation.NavigationStack)
+ System.Diagnostics.Debug.WriteLine ("Items On Navigation Stack =====> Level {0}", page._level);
+ System.Diagnostics.Debug.WriteLine ("------------------------------------------------------------");
+ };
+
+ Content = new StackLayout {
+ Padding = new Thickness (20.0),
+ Spacing = 20.0,
+ Children = {
+ buttonAdd, buttonStack, lblStack
+ }
+ };
+ }
+
+ ~TestDemoPage ()
+ {
+ System.Diagnostics.Debug.WriteLine ("Page Level {0} : Destroyed", _level);
+ }
+ }
+
+ #if UITEST
+ [Test]
+ public void Bugzilla32801Test ()
+ {
+ if (RunningApp is iOSApp) {
+ RunningApp.Tap (c => c.Marked ("btnAdd"));
+ RunningApp.Tap (c => c.Marked ("btnAdd"));
+ RunningApp.Tap (c => c.Marked ("btnStack"));
+ RunningApp.WaitForElement (c => c.Marked ("Stack 3"));
+ RunningApp.Tap (c => c.Marked ("Tab"));
+ RunningApp.Tap (c => c.Marked ("btnStack"));
+ RunningApp.WaitForElement (c => c.Marked ("Stack 1"));
+ }
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32842.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32842.xaml
new file mode 100644
index 00000000..c38aea00
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32842.xaml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issues.Bugzilla32842">
+
+
+ <StackLayout VerticalOptions="Fill">
+ <Label x:Name="Instructions" Text="Tap on a box in the list below. The Box Taps number should equal 1 and the List Item Selections number should equal 0. If either number is incorrect, this test has failed."></Label>
+
+ <ListView x:Name="MainList" VerticalOptions="Fill">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <StackLayout Orientation="Horizontal" Padding="5" HeightRequest="75" BackgroundColor="Red">
+ <BoxView Color="Teal" WidthRequest="75" HeightRequest="75">
+ <BoxView.GestureRecognizers>
+ <TapGestureRecognizer
+ Tapped="BoxTapped"
+ NumberOfTapsRequired="1"/>
+ </BoxView.GestureRecognizers>
+ </BoxView>
+ </StackLayout>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+
+ <StackLayout Orientation="Horizontal">
+ <Label Text="">List Item Selections: </Label>
+ <Label x:Name="ListResults" Text=""></Label>
+ </StackLayout>
+ <StackLayout Orientation="Horizontal">
+ <Label Text="">Box Taps: </Label>
+ <Label x:Name="BoxResults" Text=""></Label>
+ </StackLayout>
+
+
+
+ </StackLayout>
+
+
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32842.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32842.xaml.cs
new file mode 100644
index 00000000..ec73ea6a
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32842.xaml.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+#if APP
+ [Preserve(AllMembers = true)]
+ [Issue(IssueTracker.Bugzilla, 32842,
+ "[WinRT] ItemSelected Not Ignored When a ListView Item Contains a TapGestureRecognizer", PlatformAffected.WinRT)]
+ public partial class Bugzilla32842 : ContentPage
+ {
+ public Bugzilla32842 ()
+ {
+
+ List<string> items = new List<string> { "item1", "item2", "item3" };
+
+ InitializeComponent ();
+
+ MainList.ItemsSource = items;
+ MainList.ItemSelected += MainListSelectionChanged;
+ }
+
+ int _boxTaps;
+ int _listSelections;
+
+ void MainListSelectionChanged(object sender, SelectedItemChangedEventArgs e)
+ {
+ if (e.SelectedItem == null) {
+ return;
+ }
+
+ _listSelections += 1;
+
+ ListResults.Text = $"Selections = {_listSelections}";
+ }
+
+ void BoxTapped(object sender, EventArgs args)
+ {
+ _boxTaps += 1;
+
+ BoxResults.Text = $"Box Taps = {_boxTaps}";
+ }
+ }
+#endif
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32847.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32847.cs
new file mode 100644
index 00000000..7014cf35
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32847.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 32847,
+ "Picker text is cleared after selecting an item, whether Picker, DatePicker, or TimePicker (when in a TableView (or ListView))", PlatformAffected.WinRT)]
+ public class Bugzilla32847 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var instructions =
+ @"In the picker below, select the option labeled 'Two'. If the selection immediately disappears, the test has failed.
+In the TimePicker below, change the time to 5:21 PM. If the selection immediately disappears, the test has failed.
+In the DatePicker below, change the date to May 25, 1977. If the selection immediately disappears, the test has failed.";
+
+ var tableInstructions = new Label {
+ Text = instructions
+ };
+
+ var picker = new Picker ();
+
+ var pickerItems = new List<string> { "One", "Two", "Three" };
+
+ foreach(string item in pickerItems)
+ {
+ picker.Items.Add(item);
+ }
+
+ var datePicker = new DatePicker ();
+ var timePicker = new TimePicker ();
+
+ var tableView = new TableView() { BackgroundColor = Color.Green };
+
+ var tableSection = new TableSection();
+
+ var pickerCell = new ViewCell { View = picker };
+ var datepickerCell = new ViewCell { View = datePicker };
+ var timepickerCell = new ViewCell { View = timePicker };
+
+ tableSection.Add(pickerCell);
+ tableSection.Add(timepickerCell);
+ tableSection.Add(datepickerCell);
+
+ var tableRoot = new TableRoot() {
+ tableSection
+ };
+
+ tableView.Root = tableRoot;
+
+ var listItems = new List<string> { "One" };
+
+ var listView = new ListView
+ {
+ Header = instructions,
+ BackgroundColor = Color.Pink,
+ ItemTemplate = new DataTemplate(typeof(CustomCell)),
+ ItemsSource = listItems
+ };
+
+ var nonListDatePicker = new DatePicker();
+ var nonListTimePicker = new TimePicker();
+ var nonListPicker = new Picker();
+
+ foreach(string item in pickerItems)
+ {
+ nonListPicker.Items.Add(item);
+ }
+
+ Content = new StackLayout {
+ VerticalOptions = LayoutOptions.Fill,
+ HorizontalOptions = LayoutOptions.Fill,
+ Children = {
+ new Label { Text = instructions },
+ nonListPicker,
+ nonListDatePicker,
+ nonListTimePicker,
+ tableInstructions,
+ tableView,
+ listView
+ }
+ };
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class CustomCell : ViewCell
+ {
+ public CustomCell()
+ {
+ StackLayout cellWrapper = new StackLayout();
+ StackLayout stack = new StackLayout();
+
+ var picker = new Picker();
+ var datePicker = new DatePicker ();
+ var timePicker = new TimePicker ();
+
+ var items = new List<string> { "One", "Two", "Three" };
+
+ foreach(string item in items)
+ {
+ picker.Items.Add(item);
+ }
+
+ cellWrapper.BackgroundColor = Color.FromHex("#eee");
+ stack.Orientation = StackOrientation.Vertical;
+
+ stack.Children.Add(picker);
+ stack.Children.Add(timePicker);
+ stack.Children.Add(datePicker);
+
+ cellWrapper.Children.Add(stack);
+ View = cellWrapper;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32898.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32898.cs
new file mode 100644
index 00000000..ceb91e2b
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32898.cs
@@ -0,0 +1,74 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Threading.Tasks;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 32898, "Memory leak when TabbedPage is popped out ")]
+ public class Bugzilla32898 : TestContentPage
+ {
+ WeakReference _page2Tracker;
+ WeakReference _tabTracker;
+
+ protected override void Init ()
+ {
+ var stack = new StackLayout () { VerticalOptions = LayoutOptions.Center };
+
+ stack.Children.Add (new Label () {
+ VerticalOptions = LayoutOptions.Center,
+ XAlign = TextAlignment.Center,
+ Text = "Page 1"
+ });
+
+ Content = stack;
+ }
+
+ protected override async void OnAppearing ()
+ {
+ base.OnAppearing ();
+
+ if (_page2Tracker == null) {
+ var page2 = new TabbedPage () { Children = { new ContentPage () { Title = "tab" } } };
+ page2.Appearing += async delegate {
+ await Task.Delay (1000);
+ await page2.Navigation.PopModalAsync ();
+ };
+
+ _page2Tracker = new WeakReference (page2, false);
+ _tabTracker = new WeakReference (page2.Children [0], false);
+
+ await Task.Delay (1000);
+ await Navigation.PushModalAsync (page2);
+
+ StartTrackPage2 ();
+ }
+ }
+
+ async void StartTrackPage2 ()
+ {
+ while (true) {
+ ((Label)((StackLayout)Content).Children [0]).Text =
+ $"Page1. But Page2 IsAlive = {_page2Tracker.IsAlive}, tab IsAlive = {_tabTracker.IsAlive}";
+
+ await Task.Delay (1000);
+ GC.Collect ();
+ }
+ }
+
+ #if UITEST
+ [Test]
+ public async void Issu32898Test ()
+ {
+ await Task.Delay (5000);
+ RunningApp.WaitForElement (q => q.Marked ("Page1. But Page2 IsAlive = False, tab IsAlive = False"));
+ }
+ #endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32902.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32902.cs
new file mode 100644
index 00000000..e3bfccff
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32902.cs
@@ -0,0 +1,131 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+
+#if UITEST
+using Xamarin.UITest.iOS;
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 32902, "[iOS | iPad] App Crashes (without debug log) when Master Detail isPresented and navigation being popped")]
+ public class Bugzilla32902 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ ContentPage FirstContentPage { get; set; }
+
+ MasterDetailPage HomePage { get; set; }
+
+ NavigationPage DetailPage { get; set; }
+
+ ContentPage MasterPage { get; set; }
+
+ protected override void Init ()
+ {
+ var rootContentPageLayout = new StackLayout();
+ var rootContentPageButton = new Button()
+ {
+ Text = "PushAsync to next page",
+ AutomationId = "btnNext",
+ BackgroundColor = Color.FromHex("#ecf0f1"),
+ TextColor = Color.Black
+ };
+ rootContentPageButton.Clicked += async (sender, args) =>
+ {
+ await Navigation.PushAsync(FirstContentPage);
+ };
+
+ rootContentPageLayout.Children.Add(rootContentPageButton);
+ Content = rootContentPageLayout;
+
+ Title = "RootPage";
+ BackgroundColor = Color.FromHex ("#2c3e50");
+
+ //MASTER PAGE
+ MasterPage = new ContentPage()
+ {
+ Title = "Master",
+ BackgroundColor = Color.FromHex("#1abc9c")
+ };
+ var masterPageLayout = new StackLayout();
+ var masterPageButton = new Button()
+ {
+ Text = "Pop Modal and Pop Root",
+ AutomationId = "btnPop",
+ BackgroundColor = Color.FromHex("#ecf0f1"),
+ TextColor = Color.Black
+ };
+ masterPageButton.Clicked += async (sender, args) =>
+ {
+ await Navigation.PopModalAsync();
+ await Navigation.PopToRootAsync();
+ };
+ masterPageLayout.Children.Add(masterPageButton);
+ MasterPage.Content = masterPageLayout;
+
+
+ //DETAIL PAGE
+ DetailPage = new NavigationPage (new ContentPage () {
+ Title = "RootNavigationDetailPage",
+ BackgroundColor = Color.FromHex ("#2980b9"),
+ Content = new Button {
+ Text = "PopModal",
+ TextColor = Color.White,
+ Command = new Command (async () => {
+ await Navigation.PopModalAsync ();
+ })
+ }
+ });
+
+ //MASTERDETAIL PAGE
+ HomePage = new MasterDetailPage()
+ {
+ Master = MasterPage,
+ Detail = DetailPage
+ };
+
+ //FIRST CONTENT PAGE
+ FirstContentPage = new ContentPage()
+ {
+ Title = "First Content Page",
+ BackgroundColor = Color.FromHex("#e74c3c")
+ };
+ var firstContentPageLayout = new StackLayout();
+ var firstContentPageButton = new Button()
+ {
+ Text = "Push Modal To Master-Detail Page",
+ AutomationId = "btnPushModal",
+ BackgroundColor = Color.FromHex("#ecf0f1"),
+ TextColor = Color.Black
+ };
+ firstContentPageButton.Clicked += async (sender, args) =>
+ {
+ await Navigation.PushModalAsync(HomePage);
+ };
+ firstContentPageLayout.Children.Add(firstContentPageButton);
+ FirstContentPage.Content = firstContentPageLayout;
+
+
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla32902Test ()
+ {
+ var appIos = RunningApp as iOSApp;
+ if (appIos != null) {
+ if(appIos.Device.IsTablet)
+ {
+ RunningApp.Tap (q => q.Marked ("btnNext"));
+ RunningApp.Tap (q => q.Marked ("btnPushModal"));
+ RunningApp.Tap (q => q.Marked ("Master"));
+ RunningApp.Tap (q => q.Marked ("btnPop"));
+ }
+ }
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33268.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33268.cs
new file mode 100644
index 00000000..96cdc464
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33268.cs
@@ -0,0 +1,143 @@
+using System.Collections.Generic;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 33268, "Picker is broken on Windows Phone 8.1", PlatformAffected.WinRT)]
+ public class Bugzilla33268 : TestTabbedPage
+ {
+ protected override void Init ()
+ {
+ Children.Add (new Bugzilla33268ListView ());
+ Children.Add (new Simple ());
+ Children.Add (new Bugzilla33268NoListView ());
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Simple : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Title = "Simple";
+
+ var fiveItemPicker = new Picker { Title = "Picker With 4 Items" };
+ for (var i = 1; i <= 4; i++) {
+ fiveItemPicker.Items.Add ("Sample Option " + i);
+ }
+
+ Content = new StackLayout {
+ BackgroundColor = Color.Green,
+ VerticalOptions = LayoutOptions.Start,
+ Children = {
+ fiveItemPicker
+ }
+ };
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Bugzilla33268NoListView : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Title = "No ListView";
+
+ var fiveItemLabel = new Label {
+ Text =
+ "The picker below should display four items when opened. If you open it and all four items are not visible, this test has failed."
+ };
+
+ var fiveItemPicker = new Picker { Title = "Picker With 4 Items" };
+ for (var i = 1; i <= 4; i++) {
+ fiveItemPicker.Items.Add ("Sample Option " + i);
+ }
+
+ var sixItemLabel = new Label {
+ Text =
+ "The picker below should display full screen when opened. If you open it and it's not full screen, this test has failed."
+ };
+
+ var sixItemPicker = new Picker { Title = "Picker With 6 Items" };
+ for (var i = 1; i <= 6; i++) {
+ sixItemPicker.Items.Add ("Sample Option " + i);
+ }
+
+ Content = new StackLayout {
+ Children = {
+ fiveItemLabel,
+ fiveItemPicker,
+ sixItemLabel,
+ sixItemPicker
+ }
+ };
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Bugzilla33268ListView : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Title = "ListView";
+
+ var listItems = new List<string> { "One" };
+
+ var listView = new ListView {
+ Header = "Pickers in a ListView",
+ ItemTemplate = new DataTemplate (typeof(PickerCell)),
+ ItemsSource = listItems
+ };
+
+ Content = new StackLayout {
+ Children = {
+ listView
+ }
+ };
+ }
+
+ [Preserve (AllMembers = true)]
+ internal class PickerCell : ViewCell
+ {
+ public PickerCell ()
+ {
+ var cellWrapper = new StackLayout ();
+ var stack = new StackLayout ();
+
+ var fiveItemLabel = new Label {
+ Text =
+ "The picker below should display five items when opened. If you open it and all five items are not visible, this test has failed."
+ };
+
+ var fiveItemPicker = new Picker { Title = "Picker With 5 Items" };
+ for (var i = 1; i <= 5; i++) {
+ fiveItemPicker.Items.Add ("Sample Option " + i);
+ }
+
+ var sixItemLabel = new Label {
+ Text =
+ "The picker below should display full screen when opened. If you open it and it's not full screen, this test has failed."
+ };
+
+ var sixItemPicker = new Picker { Title = "Picker With 6 Items" };
+ for (var i = 1; i <= 6; i++) {
+ sixItemPicker.Items.Add ("Sample Option " + i);
+ }
+
+ stack.Orientation = StackOrientation.Vertical;
+
+ stack.Children.Add (fiveItemLabel);
+ stack.Children.Add (fiveItemPicker);
+ stack.Children.Add (sixItemLabel);
+ stack.Children.Add (sixItemPicker);
+
+ cellWrapper.VerticalOptions = LayoutOptions.StartAndExpand;
+
+ cellWrapper.Children.Add (stack);
+
+ View = cellWrapper;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33450.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33450.cs
new file mode 100644
index 00000000..e92a7d9f
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33450.cs
@@ -0,0 +1,47 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 33450, "[iOS] Cell with ContextAction has a different layout")]
+ public class Bugzilla33450 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ var list = new ListView { ItemTemplate = new DataTemplate (typeof(MyImageCell)) };
+
+ list.ItemsSource = new[] {
+ "One",
+ "Two",
+ "Three",
+ "Four",
+ "Five",
+ "Six",
+ "Seven",
+ "Eight",
+ "Nine",
+ "Ten",
+ };
+
+ Content = list;
+ }
+
+ [Preserve (AllMembers = true)]
+ public class MyImageCell : ImageCell
+ {
+ static bool s_addContextAction = false;
+
+ public MyImageCell()
+ {
+ ImageSource = "bank.png";
+ SetBinding(TextProperty, new Binding("."));
+
+ if(s_addContextAction)
+ {
+ ContextActions.Add(new MenuItem() { Text = "Delete" });
+ }
+ s_addContextAction = !s_addContextAction;
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33578.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33578.cs
new file mode 100644
index 00000000..0df73ddb
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33578.cs
@@ -0,0 +1,99 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using Xamarin.UITest.iOS;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 33578, "TableView EntryCell shows DefaultKeyboard, but after scrolling down and back a NumericKeyboard (")]
+ public class Bugzilla33578 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ Content = new TableView {
+ Root = new TableRoot {
+ new TableSection {
+ new EntryCell {
+ Placeholder = "Enter text here 1",
+ AutomationId = "entryNormal"
+ },
+ new EntryCell {
+ Placeholder = "Enter text here 2"
+ },
+ new EntryCell {
+ Placeholder = "Enter text here"
+ },
+ new EntryCell {
+ Placeholder = "Enter text here"
+ },
+ new EntryCell {
+ Placeholder = "Enter text here"
+ },
+ new EntryCell {
+ Placeholder = "Enter text here"
+ },
+ new EntryCell {
+ Placeholder = "Enter text here"
+ },
+ new EntryCell {
+ Placeholder = "Enter text here"
+ },
+ new EntryCell {
+ Placeholder = "Enter text here"
+ },
+ new EntryCell {
+ Placeholder = "Enter text here"
+ },
+ new EntryCell {
+ Placeholder = "Enter text here"
+ },
+ new EntryCell {
+ Placeholder = "Enter text here"
+ },
+ new EntryCell {
+ Placeholder = "Enter text here"
+ },
+ new EntryCell {
+ Placeholder = "Enter text here",
+ AutomationId = "entryPreviousNumeric"
+ },
+ new EntryCell {
+ Keyboard = Keyboard.Numeric,
+ Placeholder = "0",
+ AutomationId = "entryNumeric"
+ }
+ }
+ }
+ };
+ }
+
+#if UITEST
+ [Test]
+ [Ignore("Needs Xamarin.UITest 0.18")]
+ public void Bugzilla33578Test ()
+ {
+ if (RunningApp is iOSApp) {
+ RunningApp.ScrollDown ();
+ RunningApp.ScrollDown ();
+ RunningApp.Tap (x => x.Marked ("0"));
+ var e = RunningApp.Query (c => c.Marked ("0").Parent ("UITextField").Index (0).Invoke ("keyboardType")) [0];
+ //8 DecimalPad
+ Assert.AreEqual (8, e);
+ RunningApp.DismissKeyboard ();
+ RunningApp.Tap (x => x.Marked ("Enter text here").Index (0).Parent ());
+ RunningApp.ScrollUp ();
+ RunningApp.Tap (x => x.Marked ("Enter text here 1"));
+ RunningApp.Tap (x => x.Marked ("Enter text here 2").Index (0).Parent ());
+ var e1 = RunningApp.Query (c => c.Marked ("Enter text here 2").Parent ("UITextField").Index (0).Invoke ("keyboardType")) [0];
+ Assert.AreEqual (0, e1);
+ }
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33612.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33612.cs
new file mode 100644
index 00000000..95c0b30c
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33612.cs
@@ -0,0 +1,159 @@
+using System;
+using System.Linq;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 33612,
+ "(A) Removing a page from the navigation stack causes an 'Object reference' exception in Android only",
+ PlatformAffected.Android)]
+ public class Bugzilla33612 : TestNavigationPage
+ {
+ class Page1 : ContentPage
+ {
+ public Page1()
+ {
+ var button = new Button { Text = "Go To Page 2" };
+ button.Clicked += (sender, args) => Navigation.PushAsync(new Page2());
+
+ Content = new StackLayout()
+ {
+ Children = {
+ new Label { Text = "This is Page 1 - the root page" },
+ button
+ }
+ };
+ }
+ }
+
+ class FakePage : ContentPage
+ {
+ public FakePage()
+ {
+ Content = new StackLayout()
+ {
+ Children = {
+ new Label { Text = "This is a fake page. It will never show up." }
+ }
+ };
+ }
+ }
+
+ class Page2 : ContentPage
+ {
+ public Page2()
+ {
+ var button = new Button { Text = "Go to Page 3" };
+ button.Clicked += async (sender, args) =>
+ {
+ int numPagesToRemove = Navigation.NavigationStack.Count;
+
+ Page3 page3 = new Page3();
+ await Navigation.PushAsync(page3);
+
+ var fake = new FakePage();
+ Navigation.InsertPageBefore(fake, page3);
+
+ // Remove all the previous pages on the stack (i.e., Page 1)
+ // This should work fine
+ for (int i = 0; i < numPagesToRemove; i++)
+ {
+ Page p = Navigation.NavigationStack.ElementAt(0);
+ Navigation.RemovePage(p);
+ }
+ };
+
+ Content = new StackLayout()
+ {
+ Children = {
+ new Label { Text = "This is Page 2" },
+ button
+ }
+ };
+ }
+ }
+
+ class SuccessPage : ContentPage
+ {
+ public SuccessPage()
+ {
+ Content = new StackLayout()
+ {
+ Children = {
+ new Label { Text = "If you're seeing this, nothing crashed. Yay!" }
+ }
+ };
+ }
+ }
+
+ class Page3 : ContentPage
+ {
+ public Page3()
+ {
+ var button = new Button { AutomationId = "btn", Text = "Return To Page 2" };
+ button.Clicked += (sender, args) =>
+ {
+ int numPagesToRemove = Navigation.NavigationStack.Count;
+
+ // Remove all the previous pages on the stack
+ // Originally this would fail (and crash the app), because FakePage
+ // was never actually run through SwitchContentAsync
+ // which means that it never had its renderer set.
+ // But now it should work just fine
+ for (int i = 0; i < numPagesToRemove - 1; i++)
+ {
+ Page p = Navigation.NavigationStack.ElementAt(0);
+ Navigation.RemovePage(p);
+ }
+
+ var success = new SuccessPage();
+ Navigation.PushAsync(success);
+ };
+
+ Content = new StackLayout()
+ {
+ Children = {
+ new Label { Text = "This is Page 3" },
+ button
+ }
+ };
+ }
+ }
+
+ protected override void Init ()
+ {
+ var page1 = new Page1 ();
+
+ PushAsync (page1);
+ }
+
+#if UITEST
+ [Test]
+ [UiTest (typeof(NavigationPage))]
+ public void Issue33612RemovePagesWithoutRenderers ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Go To Page 2"));
+ RunningApp.Tap (q => q.Marked("Go To Page 2"));
+
+ RunningApp.WaitForElement (q => q.Marked("This is Page 2"));
+ RunningApp.Screenshot ("At Page 2");
+ RunningApp.Tap (q => q.Marked("Go to Page 3"));
+
+ RunningApp.WaitForElement ("This is Page 3");
+ RunningApp.WaitForElement (q => q.Marked ("Return To Page 2"),
+ timeout: TimeSpan.FromSeconds (15));
+ RunningApp.Screenshot("At Page 3");
+ RunningApp.Tap (q => q.Marked("Return To Page 2"));
+
+ RunningApp.WaitForElement ("If you're seeing this, nothing crashed. Yay!");
+ RunningApp.Screenshot ("Success Page");
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33714.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33714.cs
new file mode 100644
index 00000000..6fce942d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33714.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+
+ [Issue (IssueTracker.Bugzilla, 33714, "[WP] Navigating Back Within MasterDetailPage.Detail Causes Crash", NavigationBehavior.PushModalAsync)]
+ public class Bugzilla33714 : MasterDetailPage
+ {
+ public Bugzilla33714 ()
+ {
+ Master = new MasterPage (this);
+ Detail = new NavigationPage (new ContentPage
+ {
+ Title = "Home",
+ Content = new StackLayout
+ {
+ Children = {
+ new Label { Text = "This is the home detail page"}
+ }
+ }
+ });
+ }
+
+ public class MoreDetail : ContentPage
+ {
+ public MoreDetail ()
+ {
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = "More details" },
+ new Button { Text = "Go to more detail page", Command = new Command(async () => await Navigation.PushAsync(new MoreDetail()))},
+ new Button { Text = "Go back", Command = new Command(async () => await Navigation.PopAsync())}
+ }
+ };
+ }
+ }
+
+ public class DetailPage : ContentPage
+ {
+ public DetailPage ()
+ {
+ Title = "Detail";
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = "This is a Detail ContentPage" },
+ new Button { Text = "Go to more detail page", Command = new Command(async () => await Navigation.PushAsync(new MoreDetail()))}
+ }
+ };
+ }
+ }
+
+ public class MasterPage : ContentPage
+ {
+ readonly MasterDetailPage _masterPage;
+ List<string> _items;
+
+ public MasterPage (MasterDetailPage masterPage)
+ {
+ _masterPage = masterPage;
+ Title = "Menu";
+
+ for (int i = 0; i < 5; i++ )
+ {
+ if (i == 0) _items = new List<string>();
+
+ _items.Add("Menu Items");
+ }
+
+ var list = new ListView { ItemsSource = _items, RowHeight = 100, HasUnevenRows = true };
+ list.ItemSelected += list_ItemSelected;
+
+ Content = list;
+ }
+
+ void list_ItemSelected(object sender, SelectedItemChangedEventArgs e)
+ {
+ var listView = (ListView) sender;
+
+ _masterPage.Detail = new NavigationPage(new DetailPage());
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33870.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33870.cs
new file mode 100644
index 00000000..d0d9bbc6
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33870.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 33870, "[W] Crash when the ListView Selection is set to null", PlatformAffected.WinRT)]
+ public class Bugzilla33870 : TestContentPage
+ {
+ public class Section : ObservableCollection<string>
+ {
+ public Section (string title, IEnumerable<string> items = null)
+ : this (items ?? new List<string> ())
+ {
+ Title = title;
+ }
+
+ public Section (IEnumerable<string> items)
+ : base (items)
+ { }
+
+ public string Title { get; set; }
+ }
+
+ protected override void Init ()
+ {
+ var source = new ObservableCollection<Section> {
+ new Section("SECTION 1") {
+ "ITEM 1",
+ "ITEM 2",
+ },
+ new Section("SECTION 2") {
+ "ITEM 3",
+ "CLEAR SELECTION",
+ }
+ };
+
+ var listview = new ListView {
+ ItemsSource = source,
+ IsGroupingEnabled = true,
+ GroupDisplayBinding = Binding.Create<Section> (x => x.Title),
+ };
+
+ var label = new Label { Text = "Tap CLEAR SELECTION. If the app does not crash and no item is selected, the test has passed." };
+
+ listview.ItemSelected += (sender, args) =>
+ {
+ string selecteditem = args.SelectedItem?.ToString ();
+ label.Text = selecteditem;
+ if (selecteditem == "CLEAR SELECTION") {
+ label.Text = "cleared";
+ ((ListView) sender).SelectedItem = null;
+ }
+ };
+
+ var stack = new StackLayout {
+ Children = {
+ label,
+ listview
+ }
+ };
+
+ Content = stack;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33890.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33890.cs
new file mode 100644
index 00000000..bb3a3765
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla33890.cs
@@ -0,0 +1,38 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 33890, "Setting CancelButtonColor does not have any effect", PlatformAffected.iOS)]
+ public class Bugzilla33890 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Label header = new Label {
+ Text = "Search Bar",
+ FontAttributes = FontAttributes.Bold,
+ FontSize = 50,
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ SearchBar searchBar = new SearchBar {
+ Placeholder = "Enter anything",
+ CancelButtonColor = Color.Red
+ };
+
+ Label reproSteps = new Label {
+ Text =
+ "Tap on the search bar and enter some text. The 'Cancel' button should appear. If the 'Cancel' button is not red, this is broken.",
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ Content = new StackLayout {
+ Children = {
+ header,
+ searchBar,
+ reproSteps
+ }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34007.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34007.cs
new file mode 100644
index 00000000..cc490e4c
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34007.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Xml.Linq;
+using Xamarin.Forms.CustomAttributes;
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 34007, "Z order drawing of children views are different on Android, iOS, Win", PlatformAffected.Android | PlatformAffected.iOS)]
+ public class Bugzilla34007 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var grid = new Grid ();
+
+ var button0 = new Button {
+ Text = "Button 0",
+ HorizontalOptions = LayoutOptions.Fill,
+ VerticalOptions = LayoutOptions.Fill
+ };
+
+ var button1 = new Button {
+ Text = "Button 1",
+ HorizontalOptions = LayoutOptions.Fill,
+ VerticalOptions = LayoutOptions.Fill
+ };
+
+ var lastButtonTappedLabel = new Label ();
+
+ Action reorder = () => {
+ // Get the last item in the grid
+ var item = grid.Children[1];
+
+ // Remove it
+ grid.Children.RemoveAt(1);
+
+ // And put it back as the 0th item
+ grid.Children.Insert(0, item);
+ };
+
+ button0.Clicked += (sender, args) => {
+ lastButtonTappedLabel.Text = "Button 0 was tapped last";
+ };
+
+ button1.Clicked += (sender, args) => {
+ lastButtonTappedLabel.Text = "Button 1 was tapped last";
+
+ reorder ();
+ };
+
+ grid.Children.Add(button0, 0, 0);
+ grid.Children.Add(button1, 0, 0);
+
+ Content = new StackLayout {
+ Children = { grid, lastButtonTappedLabel }
+ };
+ }
+
+#if UITEST
+ [Test]
+ [UiTest (typeof (Grid))]
+ public void Issue34007TestFirstElementHasLowestZOrder ()
+ {
+ var buttonLocations = RunningApp.WaitForElement (q => q.Marked ("Button 0"));
+
+ var x = buttonLocations [0].Rect.CenterX;
+ var y = buttonLocations [0].Rect.CenterY;
+
+ // Button 1 was the last item added to the grid; it should be tappable
+ RunningApp.Tap (q => q.Button ("Button 1"));
+
+ // The label should indicate that Button 1 was the last button tapped
+ RunningApp.WaitForElement(q => q.Marked("Button 1 was tapped last"));
+
+ RunningApp.Screenshot("Buttons Reordered");
+
+ // Tapping Button1 1 reordered the buttons in the grid; Button 0 should
+ // now be on top. Tapping at the Button 1 location should actually tap
+ // Button 0, and the label should indicate that
+ RunningApp.TapCoordinates(x, y);
+ RunningApp.WaitForElement(q => q.Marked("Button 0 was tapped last"));
+
+ RunningApp.Screenshot("Button 0 Tapped");
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34061.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34061.cs
new file mode 100644
index 00000000..6af8fb6f
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34061.cs
@@ -0,0 +1,76 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 34061, "RelativeLayout - First child added after page display does not appear")]
+ public class Bugzilla34061 : TestContentPage
+ {
+ readonly RelativeLayout _layout = new RelativeLayout ();
+
+ protected override void Init ()
+ {
+ var label = new Label { Text = "Some content goes here", HorizontalOptions = LayoutOptions.Center };
+
+ var addButton = new Button{ Text = "Add Popover", AutomationId = "btnAdd" };
+ addButton.Clicked += (s, ea) => AddPopover ();
+
+ var stack = new StackLayout {
+ Orientation = StackOrientation.Vertical,
+ Children = {
+ label,
+ addButton
+ },
+ };
+
+ _layout.Children.Add (stack,
+ Forms.Constraint.Constant (0),
+ Forms.Constraint.Constant (0),
+ Forms.Constraint.RelativeToParent (p => p.Width),
+ Forms.Constraint.RelativeToParent (p => p.Height));
+
+ Content = _layout;
+ }
+
+ void AddPopover ()
+ {
+ var newView = new Button {
+ BackgroundColor = Color.FromRgba (64, 64, 64, 64),
+ Text = "Remove Me",
+ AutomationId = "btnRemoveMe"
+ };
+ newView.Clicked += (s, ea) => RemovePopover (newView);
+
+ _layout.Children.Add (
+ newView,
+ Forms.Constraint.Constant (0),
+ Forms.Constraint.RelativeToParent (p => p.Height / 2),
+ Forms.Constraint.RelativeToParent (p => p.Width),
+ Forms.Constraint.RelativeToParent (p => p.Height / 2));
+ }
+
+ void RemovePopover (View view)
+ {
+ _layout.Children.Remove (view);
+ }
+
+ #if UITEST
+ [Test]
+ public void Bugzilla34061Test ()
+ {
+ RunningApp.Screenshot ("I am at Bugzilla34061 ");
+ RunningApp.WaitForElement (q => q.Marked ("btnAdd"));
+ RunningApp.Tap (q => q.Marked ("btnAdd"));
+ RunningApp.WaitForElement (q => q.Marked ("Remove Me"));
+ RunningApp.Screenshot ("I see the button");
+ }
+ #endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34072.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34072.cs
new file mode 100644
index 00000000..d08b2f36
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34072.cs
@@ -0,0 +1,54 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers = true)]
+ [Issue(IssueTracker.Bugzilla, 34072, "Inconsistent Disabled Button behavior between Forms for Android & iOS")]
+ public class Bugzilla34072 : TestContentPage
+ {
+ Button _testButton;
+ Label _reproStepsLabel;
+
+ protected override void Init ()
+ {
+ _testButton = new Button () {
+ Text = "Enabled",
+ TextColor = Color.Yellow,
+ IsEnabled = true
+ };
+
+ var switchStateButton = new Button {
+ Text = "Switch Enabled State",
+ Command = new Command (SwitchState),
+ };
+
+ _reproStepsLabel = new Label () {
+ Text = "Tap the 'Switch Enabled State' button. The top button text should be grayed out when the button is Disabled. If the text remains the same color in both states, this is broken."
+ };
+
+ Content = new StackLayout {
+ Padding = 10,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Orientation = StackOrientation.Vertical,
+ Children = {
+ _testButton,
+ switchStateButton,
+ _reproStepsLabel
+ }
+ };
+ }
+
+ public void SwitchState ()
+ {
+ if (_testButton.IsEnabled) {
+ _testButton.IsEnabled = false;
+ _testButton.Text = "Disabled";
+ return;
+ }
+
+ _testButton.IsEnabled = true;
+ _testButton.Text = "Enabled";
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34561.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34561.cs
new file mode 100644
index 00000000..3bce1e75
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34561.cs
@@ -0,0 +1,89 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+using Xamarin.UITest.iOS;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 34561, "[A] Navigation.PushAsync crashes when used in Context Actions (legacy)", PlatformAffected.Android)]
+ public class Bugzilla34561 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var listView = new ListView () {
+ ItemsSource = new List<string> { "item" },
+ ItemTemplate = new DataTemplate (typeof(ContextActionTemplate))
+ };
+
+ Content = listView;
+ }
+
+ [Preserve (AllMembers = true)]
+ public class NextPage : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Content = new Label {
+ AutomationId = "NextPageLabel",
+ Text = "See if I'm here"
+ };
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class ContextActionTemplate : ViewCell
+ {
+ public ContextActionTemplate ()
+ {
+ MenuItem newMenuItem = new MenuItem { Text = "Click" };
+ newMenuItem.Clicked += NewMenuItem_Clicked;
+ ContextActions.Add (newMenuItem);
+
+ View = new StackLayout {
+ Children = {
+ new Label {
+ Text = "Click and hold",
+ AutomationId = "ListViewItem",
+ VerticalOptions = LayoutOptions.Center,
+ HorizontalOptions = LayoutOptions.Center
+ }
+ }
+ };
+ }
+
+ void NewMenuItem_Clicked (object sender, EventArgs e)
+ {
+ ParentView.Navigation.PushAsync (new NextPage (), false);
+ }
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla34561Test ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("ListViewItem"));
+
+ if(RunningApp is iOSApp) {
+ var listItem = RunningApp.Query (q => q.Marked ("ListViewItem"))[0].Rect;
+ RunningApp.DragCoordinates(listItem.CenterX, listItem.CenterY, 0, listItem.CenterY);
+ } else {
+ RunningApp.TouchAndHold (q => q.Marked ("ListViewItem"));
+ }
+
+ RunningApp.WaitForElement (q => q.Marked ("Click"));
+ RunningApp.Tap (q => q.Marked ("Click"));
+ RunningApp.WaitForElement (q => q.Marked ("NextPageLabel"));
+ RunningApp.Screenshot ("I see the next page");
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34632.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34632.cs
new file mode 100644
index 00000000..d75f4792
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34632.cs
@@ -0,0 +1,79 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+using Xamarin.UITest.iOS;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 34632, "Can't change IsPresented when setting SplitOnLandscape ")]
+ public class Bugzilla34632 : TestMasterDetailPage
+ {
+ protected override void Init ()
+ {
+ if (Device.OS == TargetPlatform.Windows)
+ MasterBehavior = MasterBehavior.Split;
+ else
+ MasterBehavior = MasterBehavior.SplitOnLandscape;
+
+ Master = new ContentPage { Title = "Main Page",
+ Content = new Button { Text = "Master", AutomationId = "btnMaster",
+ Command = new Command (() => {
+ //If we're in potrait toggle hide the menu on click
+ if (Width < Height || Device.Idiom == TargetIdiom.Phone) {
+ IsPresented = false;
+ }
+ })
+ }
+ };
+
+ Detail = new NavigationPage (new ModalRotationIssue ());
+ NavigationPage.SetHasBackButton (Detail, false);
+ }
+
+ [Preserve (AllMembers = true)]
+ public class ModalRotationIssue : ContentPage
+ {
+ public ModalRotationIssue ()
+ {
+ var btn = new Button { Text = "Open Modal", AutomationId = "btnModal" };
+ btn.Clicked += OnButtonClicked;
+ Content = btn;
+ }
+
+ async void OnButtonClicked (object sender, EventArgs e)
+ {
+ var testButton = new Button { Text = "Rotate Before Clicking", AutomationId = "btnDismissModal" };
+ testButton.Clicked += (async (snd, args) => await Navigation.PopModalAsync ());
+
+ var testModal = new ContentPage () {
+ Content = testButton
+ };
+
+ await Navigation.PushModalAsync (testModal);
+ }
+ }
+
+ #if UITEST
+ [Test]
+ public void Bugzilla34632Test ()
+ {
+ var app = RunningApp as iOSApp;
+ if (app != null && app.Device.IsTablet) {
+ RunningApp.SetOrientationPortrait ();
+ RunningApp.Tap (q => q.Marked ("btnModal"));
+ RunningApp.SetOrientationLandscape ();
+ RunningApp.Tap (q => q.Marked ("btnDismissModal"));
+ RunningApp.Tap (q => q.Marked ("btnModal"));
+ RunningApp.SetOrientationPortrait ();
+ RunningApp.Tap (q => q.Marked ("btnDismissModal"));
+ RunningApp.Tap (q => q.Marked ("btnMaster"));
+ }
+ }
+ #endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34720.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34720.cs
new file mode 100644
index 00000000..9d74e8e4
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34720.cs
@@ -0,0 +1,352 @@
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Threading.Tasks;
+using System;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 34720, "Incorrect iOS button IsEnabled when scrolling ListView with command binding ")]
+ public class Bugzilla34720 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ Title = "Test Command Binding";
+ _list = new ListView () {
+ ClassId = "SampleList",
+ // Note: Turning on and off row height does not effect the issue,
+ // but with row heights on there is a visual glitch with the recyclyed row spacing
+ //RowHeight = SampleViewCell.RowHeight,
+ HasUnevenRows = true,
+ ItemTemplate = new DataTemplate (typeof(SampleViewCell)),
+ BackgroundColor = Color.FromHex ("E0E0E0"),
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ };
+ _list.SetBinding (ListView.ItemsSourceProperty, Binding.Create<TestListViewModel> (r => r.Items));
+ _list.SetBinding (ListView.RefreshCommandProperty, Binding.Create<TestListViewModel> (r => r.RefreshCommand));
+ _list.SetBinding (ListView.IsRefreshingProperty, Binding.Create<TestListViewModel> (r => r.IsRefreshing));
+
+ var listViewModel = new TestListViewModel ();
+ listViewModel.AddTestData ();
+ BindingContext = listViewModel;
+
+
+ _list.ItemTapped += (sender, e) =>
+ {
+ DisplayAlert("hello", "You tapped " + e.Item.ToString(), "OK", "Cancel");
+ };
+
+ var btnDisable = new Button () {
+ Text = "Disable ListView",
+ };
+
+ btnDisable.Clicked += (object sender, EventArgs e) => {
+ if (_list.IsEnabled == true){
+ _list.IsEnabled = false;
+ btnDisable.Text = "Enable ListView";
+ }
+ else {
+ _list.IsEnabled = true;
+ btnDisable.Text = "Disable ListView";
+ }
+ };
+
+ Content = new StackLayout
+ {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Children = { btnDisable, _list }
+ };
+ }
+
+ ListView _list;
+
+ [Preserve (AllMembers = true)]
+ public class SampleViewCell : ViewCell
+ {
+ public static int RowHeight = 120;
+ static int s_idSeed;
+ int id;
+
+ public SampleViewCell ()
+ {
+ id = s_idSeed++;
+ var grid = new Grid {
+ ClassId = "SampleCard",
+ Padding = new Thickness (7, 10),
+ RowSpacing = 0,
+ ColumnSpacing = 0,
+ RowDefinitions = {
+ new RowDefinition{ Height = new GridLength (80, GridUnitType.Absolute) },
+ new RowDefinition{ Height = new GridLength (40, GridUnitType.Absolute) },
+ },
+
+ };
+
+ var head = new SampleHeaderView ();
+ grid.Children.Add (head);
+
+ var foot = new SampleListActionView ();
+ Grid.SetRow (foot, 1);
+ grid.Children.Add (foot);
+
+ View = grid;
+ }
+
+ #region Testing Code
+
+ // Note this block can be removed it is just used to observing the ViewCell creation.
+ int _counter;
+
+
+ protected override void OnAppearing ()
+ {
+
+ base.OnAppearing ();
+ _counter++;
+ System.Diagnostics.Debug.WriteLine ("OnAppearing {0}, {1}", id, _counter);
+ }
+
+ protected override void OnDisappearing ()
+ {
+ base.OnDisappearing ();
+ _counter--;
+ System.Diagnostics.Debug.WriteLine ("OnDisappearing {0}, {1}", id, _counter);
+ }
+
+ #endregion
+
+ public class SampleHeaderView : ContentView
+ {
+
+ public SampleHeaderView ()
+ {
+ //+-----------+----------------+
+ //| 1 | |
+ //+-----------+----------------+
+ //| 2 | |
+ //+-----------+----------------+
+
+
+ var grid = new Grid {
+ Padding = new Thickness (5, 5, 5, 1),
+ RowSpacing = 1,
+ ColumnSpacing = 1,
+ BackgroundColor = Color.FromHex ("FAFAFA"),
+ RowDefinitions = {
+ new RowDefinition{ Height = new GridLength (1.25, GridUnitType.Star) },
+ new RowDefinition{ Height = new GridLength (0.8, GridUnitType.Star) },
+ },
+ ColumnDefinitions = {
+ new ColumnDefinition{ Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition{ Width = new GridLength (1, GridUnitType.Star) },
+ }
+ };
+ //1 number
+ var materialNumber = new Label () {
+ VerticalOptions = LayoutOptions.StartAndExpand,
+ HorizontalOptions = LayoutOptions.StartAndExpand
+ };
+ Grid.SetColumnSpan (materialNumber, 2);
+ materialNumber.SetBinding (Label.TextProperty, Binding.Create<TestViewModel> (vm => vm.Number));
+ grid.Children.Add (materialNumber);
+
+ //2 Description
+ var materialDescription = new Label () {
+ VerticalOptions = LayoutOptions.StartAndExpand,
+ HorizontalOptions = LayoutOptions.StartAndExpand
+ };
+ Grid.SetColumnSpan (materialDescription, 2);
+ Grid.SetRow (materialDescription, 1);
+ materialDescription.SetBinding (Label.TextProperty, Binding.Create<TestViewModel> (vm => vm.Description));
+ //grid.Children.Add (materialDescription);
+
+ //3 Approve Label
+ var canApprove = new Label () {
+ VerticalOptions = LayoutOptions.StartAndExpand,
+ HorizontalOptions = LayoutOptions.StartAndExpand
+ };
+ Grid.SetColumn (canApprove, 1);
+ Grid.SetRow (canApprove, 1);
+ canApprove.SetBinding (Label.TextProperty, Binding.Create<TestViewModel> (vm => vm.CanApprove, stringFormat: "Can Approve: {0}"));
+ grid.Children.Add (canApprove);
+
+ //3 Approve Label
+ var canDeny = new Label () {
+ VerticalOptions = LayoutOptions.StartAndExpand,
+ HorizontalOptions = LayoutOptions.StartAndExpand
+ };
+ Grid.SetColumn (canDeny, 0);
+ Grid.SetRow (canDeny, 1);
+ canDeny.SetBinding (Label.TextProperty, Binding.Create<TestViewModel> (vm => vm.CanDeny, stringFormat: "Can Deny: {0}"));
+ grid.Children.Add (canDeny);
+
+ Content = grid;
+
+ }
+ }
+
+ public class SampleListActionView : ContentView
+ {
+ public SampleListActionView ()
+ {
+ var overallGrid = new Grid {
+ BackgroundColor = Color.FromHex ("FAFAFA"),
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ ColumnDefinitions = {
+ new ColumnDefinition{ Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition{ Width = new GridLength (1, GridUnitType.Star) },
+ }
+ };
+
+ var grid = new Grid {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ ColumnDefinitions = {
+ new ColumnDefinition{ Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition{ Width = new GridLength (1, GridUnitType.Star) },
+ }
+ };
+ // 1 Deny
+ var denyBtn = new Button {
+ ClassId = "btnReject",
+ Text = "DENY",
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand
+ };
+
+ denyBtn.SetBinding (Button.CommandProperty, Binding.Create<TestViewModel> (r => r.DenyCommand));
+
+ grid.Children.Add (denyBtn);
+
+ // 2 Approve
+ var approveBtn = new Button {
+ ClassId = "btnApprove",
+ Text = "Approve",
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+
+ };
+ Grid.SetColumn (approveBtn, 1);
+ approveBtn.SetBinding (Button.CommandProperty, Binding.Create<TestViewModel> (r => r.ApproveCommand));
+ grid.Children.Add (approveBtn);
+
+
+ Grid.SetColumn (grid, 1);
+ overallGrid.Children.Add (grid);
+ Content = overallGrid;
+ }
+
+ }
+
+
+ }
+
+ [Preserve (AllMembers = true)]
+ public class TestListViewModel : INotifyPropertyChanged
+ {
+ Collection<TestViewModel> _items = new ObservableCollection<TestViewModel> ();
+
+ public void AddTestData ()
+ {
+ for (int i = 0; i < 20; i++) {
+ _items.Add (new TestViewModel () {
+ Description = string.Format ("Sample Description {0}", i),
+ Number = (i + 1).ToString (),
+ CanApprove = i % 2 == 0,
+ CanDeny = i % 2 == 0
+ });
+ }
+ RaisePropertyChanged ("Items");
+ }
+
+ public Collection<TestViewModel> Items { get { return _items; } set { _items = value; } }
+
+ public Command RefreshCommand {
+ get {
+ return new Command (OnRefresh);
+ }
+ }
+
+ public bool IsRefreshing { get; set; }
+
+ async void OnRefresh ()
+ {
+ IsRefreshing = true;
+ RaisePropertyChanged ("IsRefreshing");
+ _items.Clear ();
+ await Task.Delay (1000);
+ AddTestData ();
+ IsRefreshing = false;
+ RaisePropertyChanged ("IsRefreshing");
+ }
+
+ #region INotifyPropertyChanged implementation
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ #endregion
+
+ protected virtual void RaisePropertyChanged (string propertyName)
+ {
+ PropertyChangedEventHandler propertyChanged = PropertyChanged;
+ if (propertyChanged != null) {
+ propertyChanged (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class TestViewModel
+ {
+
+ public string Number { get; set; }
+
+ public string Description { get; set; }
+
+ bool _canApprove;
+
+ public bool CanApprove {
+ get{ return _canApprove; }
+ set {
+ _canApprove = value;
+ ApproveCommand.ChangeCanExecute ();
+ }
+ }
+
+ bool _canDeny;
+
+ public bool CanDeny {
+ get { return _canDeny; }
+ set {
+ _canDeny = value;
+ DenyCommand.ChangeCanExecute ();
+ }
+ }
+
+ public Command ApproveCommand {
+ get {
+ return new Command (OnApprove, () => CanApprove);
+ }
+ }
+
+ public Command DenyCommand {
+ get {
+ return new Command (OnDeny, () => CanDeny);
+ }
+ }
+
+ async void OnApprove ()
+ {
+ await Application.Current.MainPage.DisplayAlert ("Approve", string.Format ("Can Approve {0} {1}", Number, CanApprove), "Ok");
+ }
+
+ async void OnDeny ()
+ {
+ await Application.Current.MainPage.DisplayAlert ("Deny", string.Format ("Can Deny {0} {1}", Number, CanDeny), "Ok");
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34727.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34727.cs
new file mode 100644
index 00000000..fa17a728
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34727.cs
@@ -0,0 +1,30 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 34727, "(A) Cannot browse files from WebView on Android", PlatformAffected.Android)]
+ public class Bugzilla34727 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var webView = new WebView ();
+
+ var htmlSource = new HtmlWebViewSource { Html = @"
+<h3>Test Web View File Chooser</h3>
+<ol>
+ <li>Open the camera app.</li>
+ <li>Take a picture.</li>
+ <li>Return to this page.</li>
+ <li>Tap the 'Choose File' button; a file picker should appear.</li>
+ <li>Select the picture you just took.</li>
+ <li>The text 'No file chosen' should change to the name of your image file.</li>
+</ol>
+<br/>
+<input type='file' name='file' id='chooser' accept='image/*'>" };
+
+ webView.Source = htmlSource;
+ Content = webView;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34912.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34912.cs
new file mode 100644
index 00000000..5042bc58
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla34912.cs
@@ -0,0 +1,106 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.ObjectModel;
+using System.Linq;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 34912, "ListView.IsEnabled has no effect on iOS")]
+ public class Bugzilla34912 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ Padding = new Thickness (0, 20, 0, 0);
+
+ var source = SetupList ();
+
+ var list = new ListView
+ {
+ ItemTemplate = new DataTemplate(typeof(TextCell))
+ {
+ Bindings = {
+ { TextCell.TextProperty, new Binding ("Name") }
+ }
+ },
+
+ GroupDisplayBinding = new Binding("LongTitle"),
+ GroupShortNameBinding = new Binding("Title"),
+ Header = "HEADER",
+ Footer = "FOOTER",
+ IsGroupingEnabled = true,
+ ItemsSource = SetupList(),
+ };
+
+ list.ItemTapped += (sender, e) =>
+ {
+ var listItem = (Issue2777.ListItemValue)e.Item;
+ DisplayAlert(listItem.Name, "You tapped " + listItem.Name, "OK", "Cancel");
+ };
+
+ var btnDisable = new Button () {
+ Text = "Disable ListView",
+ AutomationId = "btnDisable"
+ };
+ btnDisable.Clicked += (object sender, EventArgs e) => {
+ if (list.IsEnabled == true){
+ list.IsEnabled = false;
+ btnDisable.Text = "Enable ListView";
+ }
+ else {
+ list.IsEnabled = true;
+ btnDisable.Text = "Disable ListView";
+ }
+ };
+
+ Content = new StackLayout
+ {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Children = { btnDisable, list }
+ };
+ }
+
+ ObservableCollection<Issue2777.ListItemCollection> SetupList()
+ {
+ var allListItemGroups = new ObservableCollection<Issue2777.ListItemCollection>();
+
+ foreach (var item in Issue2777.ListItemCollection.GetSortedData())
+ {
+ // Attempt to find any existing groups where theg group title matches the first char of our ListItem's name.
+ var listItemGroup = allListItemGroups.FirstOrDefault(g => g.Title == item.Label);
+
+ // If the list group does not exist, we create it.
+ if (listItemGroup == null)
+ {
+ listItemGroup = new Issue2777.ListItemCollection(item.Label);
+ listItemGroup.Add(item);
+ allListItemGroups.Add(listItemGroup);
+ }
+ else
+ { // If the group does exist, we simply add the demo to the existing group.
+ listItemGroup.Add(item);
+ }
+ }
+ return allListItemGroups;
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla34912Test ()
+ {
+ RunningApp.Tap (q => q.Marked ("Allen"));
+ RunningApp.WaitForElement (q => q.Marked ("You tapped Allen"));
+ RunningApp.Tap (q => q.Marked ("OK"));
+ RunningApp.Tap (q => q.Marked ("btnDisable"));
+ RunningApp.Tap (q => q.Marked ("Allen"));
+ RunningApp.WaitForNoElement (q => q.Marked ("You tapped Allen"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35078.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35078.cs
new file mode 100644
index 00000000..054aca0f
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35078.cs
@@ -0,0 +1,34 @@
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Issue (IssueTracker.Bugzilla, 35078,
+ "Checking IsInvokeRequired on WinRT when off the dispatcher thread causes a null reference exception",
+ PlatformAffected.WinRT)]
+ public class Bugzilla35078 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var button = new Button { Text = "Go" };
+
+ var instructions = new Label {
+ Text =
+ "Click the 'Go' button. If the application crashes or a label with the text 'Sucess' does not appear, the test has failed."
+ };
+
+ var success = new Label ();
+
+ button.Clicked += (sender, args) => {
+ Task.Run (() => {
+ bool invokeRequired = Device.IsInvokeRequired;
+ if (invokeRequired) {
+ Device.BeginInvokeOnMainThread (() => success.Text = "Success");
+ }
+ });
+ };
+
+ Content = new StackLayout { Children = { instructions, button, success } };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35127.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35127.cs
new file mode 100644
index 00000000..f5c338ab
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35127.cs
@@ -0,0 +1,22 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 35127, "It is possible to craft a page such that it will never display on Windows")]
+ public class Bugzilla35127 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = "See me?" },
+ new ScrollView {
+ IsVisible = false,
+ Content = new Button { Text = "Click Me?" }
+ }
+ }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35157.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35157.cs
new file mode 100644
index 00000000..cd4721e3
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35157.cs
@@ -0,0 +1,58 @@
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 35157, "CarouselPage inside NavPage inside TabbedPage gets laid out incorrectly", NavigationBehavior.PushModalAsync)]
+ public class Bugzilla35157 : TestTabbedPage
+ {
+ protected override void Init ()
+ {
+ var button = new Button {
+ Text = "Go",
+ AutomationId = "firstButton"
+ };
+
+
+ button.Clicked += (sender, args) => {
+ Button button2 = null;
+ button.Navigation.PushAsync (new CarouselPage {
+ Children = {
+ new ContentPage {
+ Content = button2 = new Button {
+ AutomationId = "secondButton",
+ VerticalOptions = LayoutOptions.EndAndExpand,
+ Text = "Click Me"
+ }
+ }
+ }
+ });
+
+ button2.Clicked += (s, a) => button2.Text = "Button Clicked!";
+ };
+
+ var tab = new NavigationPage(new ContentPage {Content = button});
+ tab.Title = "Tab";
+ Children.Add (tab);
+
+
+ }
+
+#if UITEST
+ [Test]
+ public void ButtonCanBeClicked ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("firstButton"));
+ RunningApp.Tap (q => q.Marked ("firstButton"));
+ RunningApp.WaitForElement (q => q.Marked ("secondButton"));
+ RunningApp.Tap (q => q.Marked ("secondButton"));
+ RunningApp.WaitForElement (q => q.Button ("Button Clicked!"));
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35294.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35294.cs
new file mode 100644
index 00000000..036b7a91
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35294.cs
@@ -0,0 +1,45 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 35294, "Certain pages do not align properly in RT Desktop")]
+ public class Bugzilla35294 : TestContentPage
+ {
+ public static Label LblMsg = new Label
+ {
+ FontSize = 16,
+ Text = "This is an example.... what is wrong with this? ",
+ HorizontalOptions = LayoutOptions.Center,
+ TextColor = Color.Black,
+ };
+
+ protected override void Init ()
+ {
+ Label header = new Label
+ {
+ Text = "Should not see blue",
+ Font = Font.BoldSystemFontOfSize(40),
+ HorizontalOptions = LayoutOptions.Center,
+ TextColor = Color.Black
+ };
+
+ StackLayout stack = new StackLayout
+ {
+ BackgroundColor = Color.White,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Spacing = 10,
+
+ Children = { header, LblMsg, }
+ };
+
+ Content = new ScrollView
+ {
+ BackgroundColor = Color.Blue,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Orientation = ScrollOrientation.Vertical,
+ Content = stack
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35472.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35472.cs
new file mode 100644
index 00000000..1513463c
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35472.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Diagnostics;
+using Xamarin.Forms.CustomAttributes;
+#if UITEST
+using Xamarin.Forms.Core.UITests;
+using NUnit.Framework;
+using Xamarin.UITest;
+
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 35472, "PopAsync during ScrollToAsync throws NullReferenceException")]
+ public class Bugzilla35472 : TestNavigationPage
+ {
+ protected override void Init ()
+ {
+ // Set up the scroll viewer page
+ var scrollToButton = new Button () { Text = "Now push this button" };
+
+ var stackLayout = new StackLayout ();
+
+ stackLayout.Children.Add (scrollToButton);
+
+ for (int n = 0; n < 100; n++) {
+ stackLayout.Children.Add (new Label () { Text = n.ToString () });
+ }
+
+ var scrollView = new ScrollView () {
+ Content = stackLayout
+ };
+
+ var pageWithScrollView = new ContentPage () {
+ Content = scrollView
+ };
+
+ // Set up the start page
+ var goButton = new Button () {
+ Text = "Push this button"
+ };
+
+ var successLabel = new Label () { Text = "The test has passed", IsVisible = false };
+
+ var startPage = new ContentPage () {
+ Content = new StackLayout {
+ VerticalOptions = LayoutOptions.Center,
+ Children = {
+ goButton,
+ successLabel
+ }
+ }
+ };
+
+ PushAsync (startPage);
+
+ goButton.Clicked += (sender, args) => Navigation.PushAsync (pageWithScrollView);
+
+ scrollToButton.Clicked += async (sender, args) => {
+ try {
+ // Deliberately not awaited so we can simulate a user navigating back
+ scrollView.ScrollToAsync (0, 1500, true);
+ await Navigation.PopAsync ();
+ successLabel.IsVisible = true;
+ } catch (Exception ex) {
+ Debug.WriteLine (ex);
+ }
+ };
+ }
+
+#if UITEST
+ [Test]
+ [UiTest (typeof(NavigationPage))]
+ public void Issue35472PopAsyncDuringAnimatedScrollToAsync ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Push this button"));
+ RunningApp.Tap (q => q.Marked ("Push this button"));
+
+ RunningApp.WaitForElement (q => q.Marked ("Now push this button"));
+ RunningApp.Screenshot ("On Page With ScrollView");
+ RunningApp.Tap (q => q.Marked ("Now push this button"));
+
+ RunningApp.WaitForElement ("The test has passed");
+ RunningApp.Screenshot ("Success");
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35477.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35477.cs
new file mode 100644
index 00000000..8c1e7a69
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35477.cs
@@ -0,0 +1,49 @@
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest.Queries;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 35477, "Tapped event does not fire when added to Frame in Android AppCompat",
+ PlatformAffected.Android)]
+ public class Bugzilla35477 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var instructions = new Label {
+ Text = "Tap the frame below. The label with the text 'No taps yet' should change its text to 'Frame was tapped'."
+ };
+ var frame = new Frame () {};
+ var frameLabel = new Label() {Text = "Tap here" };
+
+ frame.Content = new StackLayout() {Children = { frameLabel }};
+
+ var label = new Label { Text = "No taps yet" };
+
+ var rec = new TapGestureRecognizer { NumberOfTapsRequired = 1 };
+ rec.Tapped += (s, e) => { label.Text = "Frame was tapped"; };
+ frame.GestureRecognizers.Add (rec);
+
+ Content = new StackLayout {
+ Children = { instructions, frame, label }
+ };
+ }
+
+#if UITEST
+ [Test]
+ public void TapGestureFiresOnFrame ()
+ {
+ RunningApp.WaitForElement ("No taps yet");
+ RunningApp.WaitForElement ("Tap here");
+
+ RunningApp.Tap ("Tap here");
+
+ RunningApp.WaitForElement ("Frame was tapped");
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35490.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35490.cs
new file mode 100644
index 00000000..119d297f
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35490.cs
@@ -0,0 +1,39 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 35490, "Label Text Misaligned in Windows Phone 8.1 and WinRT",
+ PlatformAffected.WinPhone | PlatformAffected.WinRT)]
+ public class Bugzilla35490 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var instructions = new Label {
+ Text =
+ "The label in the red box below should be centered horizontally and vertically. If it's not, this test has failed."
+ };
+
+
+ var label = new Label {
+ BackgroundColor = Color.Red,
+ TextColor = Color.White,
+ HorizontalTextAlignment = TextAlignment.Center,
+ VerticalTextAlignment = TextAlignment.Center,
+ HeightRequest = 200,
+ HorizontalOptions = LayoutOptions.Fill,
+ Text = "Should be centered horizontally and vertically"
+ };
+
+
+ Content = new StackLayout {
+ HorizontalOptions = LayoutOptions.Fill,
+ VerticalOptions = LayoutOptions.Fill,
+ Children = {
+ instructions,
+ label
+ }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35733.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35733.cs
new file mode 100644
index 00000000..5e6c39ca
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35733.cs
@@ -0,0 +1,58 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Threading.Tasks;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 35733, "iOS WebView crashes when loading an URL with encoded parameters", PlatformAffected.iOS)]
+ public class Bugzilla35733 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ var thisDoesNotWorkButton = new Button {
+ Text = "This will crash",
+ AutomationId = "btnGo"
+
+ };
+ thisDoesNotWorkButton.Clicked += async (object sender, EventArgs e) => await ShowLocation ("KÅRA");
+
+ Content = new StackLayout {
+ VerticalOptions = LayoutOptions.Center,
+ Children = {
+ thisDoesNotWorkButton
+ }
+ };
+ }
+
+ async Task ShowLocation(string locationString)
+ {
+ var stringUri = string.Format("http://m.liu.se/karta/karta?l=en&px_location={0}", Uri.EscapeDataString(locationString));
+ var uri = new Uri(stringUri);
+ var webPage = new ContentPage {
+ Title = "WebViewTest",
+ Content = new WebView {
+ Source = uri
+ }
+ };
+ await Navigation.PushAsync(webPage);
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla35733Test ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("btnGo"));
+ RunningApp.Tap (q => q.Marked ("btnGo"));
+ RunningApp.WaitForElement (q => q.Marked ("WebViewTest"));
+ RunningApp.Screenshot ("I didn't crash");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35738.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35738.cs
new file mode 100644
index 00000000..e79343b3
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla35738.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Diagnostics;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ public class CustomButton : Button
+ {
+ // In the Android project, there's a custom renderer set up for this type
+ }
+
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 35738, "ButtonRenderer UpdateTextColor function crash", PlatformAffected.Android)]
+ public class Bugzilla35738 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var label = new Label () { Text = "If you can see the button, this test has passed" };
+ var customButton = new CustomButton () { Text = "This is a custom button", TextColor = Color.Fuchsia };
+
+ Content = new StackLayout () {
+ Children = { label, customButton }
+ };
+ }
+
+#if UITEST
+ [Test]
+ [UiTest (typeof(TestContentPage))]
+ public void CallingOnElementChangedOnCustomButtonShouldNotCrash ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("This is a custom button"));
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36009.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36009.cs
new file mode 100644
index 00000000..0e0e470d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36009.cs
@@ -0,0 +1,56 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 36009, "Children of Layouts with data bound IsVisible are not displayed")]
+ public class Bugzilla36009 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ [Preserve (AllMembers = true)]
+ public class SampleViewModel: ViewModelBase
+ {
+ public bool IsContentVisible {
+ get{ return GetProperty<bool> (); }
+ set{ SetProperty (value); }
+ }
+ }
+
+ protected override void Init ()
+ {
+ var boxview = new BoxView{ BackgroundColor = Color.Aqua, AutomationId = "Victory" };
+
+ var contentView = new ContentView {
+ Content = boxview
+ };
+
+ contentView.SetBinding (IsVisibleProperty, Binding.Create<SampleViewModel> (t => t.IsContentVisible));
+
+ var layout = new AbsoluteLayout {
+ Children = { contentView }
+ };
+
+ Content = layout;
+
+ var vm = new SampleViewModel ();
+
+ BindingContext = vm;
+
+ vm.IsContentVisible = true;
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla36009Test ()
+ {
+ RunningApp.WaitForElement(q => q.Marked("Victory"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36014.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36014.cs
new file mode 100644
index 00000000..7e6cd390
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36014.cs
@@ -0,0 +1,16 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Issue (IssueTracker.Bugzilla, 36014, "Picker Control Is Not Rendered Correctly", PlatformAffected.WinPhone)]
+ public class Bugzilla36014 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var picker = new Picker () { Items = {"Leonardo", "Donatello", "Raphael", "Michaelangelo" } };
+ var label = new Label () {Text = "This test is successful if the picker below spans the width of the screen. If the picker is just a sliver on the left edge of the screen, this test has failed." };
+
+ Content = new StackLayout () { Children = {label, picker}};
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36171.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36171.cs
new file mode 100644
index 00000000..6395e28b
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36171.cs
@@ -0,0 +1,107 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest.Queries;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 36171, "WinRT Entry UI not updating on TextChanged",
+ PlatformAffected.WinPhone | PlatformAffected.WinRT)]
+ public class Bugzilla36171 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ var entry = new Entry ();
+ var editor = new Editor();
+ var focuseEntryButton = new Button { Text = "Start Entry" };
+ var focuseEditorButton = new Button { Text = "Start Editor" };
+
+ focuseEntryButton.Clicked += (sender, args) => { entry.Focus (); };
+ focuseEditorButton.Clicked += (sender, args) => { editor.Focus (); };
+
+ var entryLabel = new Label { Text = "Type 123A into the Entry below; the entry should display '123'. If the 'A' is displayed, the test has failed. If the cursor resets to the beginning of the Entry after typing 'A', the test has failed." };
+ var editorLabel = new Label { Text = "Type 123A into the Editor below; the entry should display '123'. If the 'A' is displayed, the test has failed. If the cursor resets to the beginning of the Editor after typing 'A', the test has failed." };
+
+ entry.TextChanged += (sender, args) => {
+ var e = sender as Entry;
+
+ int val;
+
+ if(string.IsNullOrEmpty (args.NewTextValue?.Trim ())) {
+ return;
+ }
+
+ // check if this is numeric
+ if(!int.TryParse (args.NewTextValue, out val)) {
+ // put the old value back.
+ e.Text = args.OldTextValue;
+ }
+ };
+
+ editor.TextChanged += (sender, args) => {
+ var e = sender as Editor;
+
+ int val;
+
+ if(string.IsNullOrEmpty (args.NewTextValue?.Trim ())) {
+ return;
+ }
+
+ // check if this is numeric
+ if(!int.TryParse (args.NewTextValue, out val)) {
+ // put the old value back.
+ e.Text = args.OldTextValue;
+ }
+ };
+
+ // Initialize ui here instead of ctor
+ Content = new StackLayout {
+ Children = { focuseEntryButton, entryLabel, entry, focuseEditorButton, editorLabel, editor }
+ };
+ }
+
+#if UITEST
+ [Test]
+ public void EntryTextDoesNotDisplayNonnumericInput ()
+ {
+ RunningApp.WaitForElement ("Start Entry");
+ RunningApp.Tap ("Start Entry");
+
+ RunningApp.EnterText ("123A");
+
+ var entry = RunningApp.Query (q => q.Text("123"));
+ Assert.That(entry.Length >= 1);
+
+ var failedEntry = RunningApp.Query (q => q.Text("123A"));
+ Assert.That(failedEntry.Length == 0);
+
+ RunningApp.EnterText ("4");
+
+ var entry2 = RunningApp.Query (q => q.Text("1234"));
+ Assert.That(entry2.Length >= 1);
+
+ RunningApp.ClearText();
+
+ RunningApp.WaitForElement ("Start Editor");
+ RunningApp.Tap ("Start Editor");
+
+ RunningApp.EnterText ("123A");
+
+ var editor = RunningApp.Query (q => q.Text("123"));
+ Assert.That(editor.Length >= 1);
+
+ var failedEditor = RunningApp.Query (q => q.Text("123A"));
+ Assert.That(failedEditor.Length == 0);
+
+ RunningApp.EnterText ("4");
+
+ var editor2 = RunningApp.Query (q => q.Text("1234"));
+ Assert.That(editor2.Length >= 1);
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36393.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36393.cs
new file mode 100644
index 00000000..6aecc1a8
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36393.cs
@@ -0,0 +1,43 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve(AllMembers = true)]
+ [Issue(IssueTracker.Bugzilla, 36393, "[A] Default Entry/Editor/SearchBar Font Size is 14 instead of 18")]
+ public class Bugzilla36393 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init()
+ {
+ var label = new Label { FontSize = 18 };
+ var entry = new Entry { };
+ var editor = new Editor { };
+ var searchBar = new SearchBar { };
+
+ label.Text = $"I am label. FontSize:{label.FontSize}";
+ entry.Text = $"I am entry. FontSize:{entry.FontSize}";
+ editor.Text = $"I am editor. FontSize:{editor.FontSize}";
+ searchBar.Text = $"I am search bar. FontSize:{searchBar.FontSize}";
+
+ // Initialize ui here instead of ctor
+ Content = new StackLayout
+ {
+ Children = { label, entry, editor, searchBar }
+ };
+ }
+
+#if UITEST
+ [Test]
+ public void Issue1Test()
+ {
+ RunningApp.Screenshot("If all of the font sizes are visibly the same size, this test has passed.");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36479.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36479.cs
new file mode 100644
index 00000000..bf28ff25
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36479.cs
@@ -0,0 +1,43 @@
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve(AllMembers = true)]
+ [Issue(IssueTracker.Bugzilla, 36479, "[WP8] Picker is not disabled when IsEnabled is set to false", PlatformAffected.WinPhone)]
+ public class Bugzilla36479 : TestContentPage
+ {
+ protected override void Init()
+ {
+ var picker = new Picker
+ {
+ IsEnabled = false
+ };
+ picker.Items.Add("item");
+ picker.Items.Add("item 2");
+
+ Content = new StackLayout
+ {
+ Children =
+ {
+ picker,
+ new Button
+ {
+ Command = new Command(() =>
+ {
+ if (picker.IsEnabled)
+ picker.IsEnabled = false;
+ else
+ picker.IsEnabled = true;
+ }),
+ Text = "Enable/Disable Picker"
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36559.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36559.cs
new file mode 100644
index 00000000..660ad880
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36559.cs
@@ -0,0 +1,54 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve(AllMembers = true)]
+ [Issue(IssueTracker.Bugzilla, 36559, "[WP] Navigating to a ContentPage with a Grid inside a TableView affects Entry heights")]
+ public class Bugzilla36559 : TestContentPage
+ {
+ protected override void Init()
+ {
+ var label = new Label { Text = "Label" };
+ var entry = new Entry { AutomationId = "entry" };
+ var grid = new Grid();
+
+ grid.Children.Add(label, 0, 0);
+ grid.Children.Add(entry, 1, 0);
+ var tableView = new TableView
+ {
+ Root = new TableRoot
+ {
+ new TableSection
+ {
+ new ViewCell
+ {
+ View = grid
+ }
+ }
+ }
+ };
+
+ Content = new StackLayout
+ {
+ Children = { tableView }
+ };
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla36559Test()
+ {
+ RunningApp.WaitForElement(q => q.Marked("entry"));
+ var results = RunningApp.Query(q => q.Marked("entry"));
+ Assert.AreNotEqual(results[0].Rect.Height, -1);
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36649.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36649.cs
new file mode 100644
index 00000000..06bca7b0
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36649.cs
@@ -0,0 +1,29 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Issue (IssueTracker.Bugzilla, 36649, "LineBreakMode.NoWrap is handled incorrectly on Windows Phone 8.1 RT",
+ PlatformAffected.WinRT)]
+ public class Bugzilla36649 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var label = new Label {
+ Style = Device.Styles.BodyStyle,
+ FontSize = 20,
+ Text =
+ "This test is successful if the line below does not wrap and does not have an ellipsis at the end of the visible text."
+ };
+ var testLabel = new Label {
+ TextColor = Color.Red,
+ Style = Device.Styles.BodyStyle,
+ FontSize = 20,
+ LineBreakMode = LineBreakMode.NoWrap,
+ Text =
+ "This text should be long enough that it won't fit on the screen, and since the LineBreakMode is set to NoWrap, there should not be an ellipsis at the end of the visible text."
+ };
+
+ Content = new StackLayout { Children = { label, testLabel } };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36681.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36681.cs
new file mode 100644
index 00000000..d72b82c7
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36681.cs
@@ -0,0 +1,88 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.Generic;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 36681, "[A] NRE when Picker Replaces Page Content (pre-AppCompat only)", PlatformAffected.Android)]
+ public class Bugzilla36681 : TestTabbedPage // or TestMasterDetailPage, etc ...
+ {
+ public class PickerPage : ContentPage
+ {
+ public Picker Picker { get; private set; }
+ public Label Label { get; private set; }
+ public PickerPage ()
+ {
+ Picker = new Picker { Title = "Select Item", AutomationId = "picker" };
+
+ var items = new List<string> { "item", "item2", "item3", "item4" };
+ foreach (var i in items)
+ Picker.Items.Add (i);
+
+ Picker.FocusChangeRequested += Picker_FocusChangeRequested;
+ Picker.SelectedIndexChanged += Picker_SelectedIndexChanged;
+
+ StackLayout stack = new StackLayout { Padding = 20 };
+ stack.Children.Add (Picker);
+
+ Content = stack;
+ }
+
+ void Picker_FocusChangeRequested (object sender, FocusRequestArgs e)
+ {
+ SwitchContent ();
+ }
+
+ void Picker_SelectedIndexChanged (object sender, EventArgs e)
+ {
+ SwitchContent ();
+ }
+
+ void SwitchContent ()
+ {
+ var x = Parent as TabbedPage;
+ var y = x.CurrentPage as ContentPage;
+ y.Content = new Label {
+ Text = "Success!"
+ };
+ y.Padding = new Thickness (0, 20, 0, 0);
+ }
+ }
+
+ protected override void Init ()
+ {
+ PickerPage pickerPage = new PickerPage { Title = "Picker Page" };
+ Children.Add (pickerPage);
+ Children.Add (new ContentPage { BackgroundColor = Color.Blue, Title = "Page 2" });
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla36681Test ()
+ {
+ if (RunningApp is Xamarin.UITest.Android.AndroidApp) {
+ RunningApp.WaitForElement (q => q.Marked ("picker"));
+ RunningApp.Tap ("picker");
+ var ok = RunningApp.Query ("OK");
+ if (ok.Length > 0 && ok[0].Id == "button1" ) { //only in pre-AppCompat; this is the culprit!
+ // We check that the query has any results and that the first
+ // result matched the id "button1" because the query reports a phantom OK button
+ // on Android >= 6.0
+ RunningApp.Tap ("OK");
+ } else {
+ RunningApp.WaitForElement (q => q.Marked ("item2"));
+ RunningApp.Tap ("item2");
+ }
+ RunningApp.WaitForElement (q => q.Marked ("Success!"));
+ }
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36788.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36788.cs
new file mode 100644
index 00000000..76dbbda7
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla36788.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 36788, "Truncation Issues with Relative Layouts")]
+ public class Bugzilla36788 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ Label _resultLabel;
+ Label _testLabel;
+ View _container;
+
+ protected override void Init ()
+ {
+ // Initialize ui here instead of ctor
+ var stackLayout = new StackLayout {
+ Spacing = 8
+ };
+
+ var longString = "Very long text in single line to be truncated at tail. Adding extra text to make sure it gets truncated.";
+
+ var contentView = new ContentView {
+ Padding = 16,
+ BackgroundColor = Color.Gray,
+ Content = new Label {
+ BackgroundColor = Color.Aqua,
+ Text = longString,
+ LineBreakMode = LineBreakMode.TailTruncation
+ }
+ };
+
+ stackLayout.Children.Add (contentView);
+
+ contentView = new ContentView {
+ Padding = 16,
+ BackgroundColor = Color.Gray,
+ Content = new RelativeLayout {
+ BackgroundColor = Color.Navy,
+ Children = {
+ {new Label {
+ BackgroundColor = Color.Blue,
+ Text = longString,
+ LineBreakMode = LineBreakMode.TailTruncation
+ }, Forms.Constraint.Constant (0)},
+ {new Label {
+ BackgroundColor = Color.Fuchsia,
+ Text = longString,
+ LineBreakMode = LineBreakMode.TailTruncation
+ }, Forms.Constraint.Constant (0), Forms.Constraint.Constant (40)},
+ {new Label {
+ BackgroundColor = Color.Fuchsia,
+ Text = longString,
+ LineBreakMode = LineBreakMode.TailTruncation
+ }, Forms.Constraint.Constant (10), Forms.Constraint.Constant (80)},
+ }
+ }
+ };
+
+ stackLayout.Children.Add (contentView);
+
+ contentView = new ContentView {
+ Padding = 16,
+ BackgroundColor = Color.Gray,
+ IsClippedToBounds = true,
+ Content = _container = new RelativeLayout {
+ IsClippedToBounds = true,
+ BackgroundColor = Color.Navy,
+ Children = {
+ {_testLabel = new Label {
+ BackgroundColor = Color.Blue,
+ Text = longString,
+ LineBreakMode = LineBreakMode.TailTruncation
+ }, Forms.Constraint.Constant (0)},
+ {new Label {
+ BackgroundColor = Color.Fuchsia,
+ Text = longString,
+ LineBreakMode = LineBreakMode.TailTruncation
+ }, Forms.Constraint.Constant (0), Forms.Constraint.Constant (40)},
+ {new Label {
+ BackgroundColor = Color.Fuchsia,
+ Text = longString,
+ LineBreakMode = LineBreakMode.TailTruncation
+ }, Forms.Constraint.Constant (10), Forms.Constraint.Constant (80)},
+ }
+ }
+ };
+
+ stackLayout.Children.Add (contentView);
+
+ _resultLabel = new Label ();
+ stackLayout.Children.Add (_resultLabel);
+
+ Content = stackLayout;
+ }
+
+ protected override async void OnAppearing ()
+ {
+ base.OnAppearing ();
+ await Task.Delay (200);
+
+ double fuzzFactor = 15; // labels sometimes overflow slightly, thanks hinting
+
+ if (Math.Abs (_testLabel.Width - _container.Width) < fuzzFactor)
+ _resultLabel.Text = "Passed";
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla36788Test ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Passed"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37462.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37462.cs
new file mode 100644
index 00000000..9eebae8b
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37462.cs
@@ -0,0 +1,88 @@
+using System.Collections.Generic;
+using System.Linq;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 37462, "Using App Compat/App Compat theme breaks Navigation.RemovePage on Android ",PlatformAffected.Android )]
+ public class Bugzilla37462 : TestNavigationPage
+ {
+ protected override void Init ()
+ {
+ var page1 = new ContentPage { Title = "Page 1" };
+ var button1 = new Button { Text = "Go To 2" };
+ var label1 = new Label { Text = "This is a label on page 1" };
+ page1.Content = new StackLayout { Children = { button1, label1 } };
+ page1.Appearing += (sender, args) => {
+ page1.InvalidateMeasure (InvalidationTrigger.MeasureChanged);
+ };
+
+ var page2 = new ContentPage { Title = "Page 2" };
+ var button2 = new Button { Text = "Go To 3" };
+ var label2 = new Label { Text = "This is a label on page 2" };
+ page2.Content = new StackLayout { Children = { button2, label2 } };
+
+ var page3 = new ContentPage { Title = "Page 3" };
+ var button3 = new Button { Text = "Go To 4" };
+ var label3 = new Label { Text = "This is a label on page 3" };
+ page3.Content = new StackLayout { Children = { button3, label3 } };
+
+ var page4 = new ContentPage { Title = "Page 4" };
+ var button4 = new Button { Text = "Back to 1" };
+ var label4 = new Label { Text = "This is a label on page 4" };
+ page4.Content = new StackLayout { Children = { button4, label4 } };
+
+ button1.Clicked += async (sender, args) => { await Navigation.PushAsync (page2); };
+ button2.Clicked += async (sender, args) => { await Navigation.PushAsync (page3); };
+ button3.Clicked += async (sender, args) => { await Navigation.PushAsync (page4); };
+
+ button4.Clicked += async (sender, args) => {
+ List<Page> existingPages = Navigation.NavigationStack.ToList ();
+
+ // Clear all pages except current and home
+ foreach (Page page in existingPages) {
+ if (page.Title != "Page 1" && page.Title != "Page 4") {
+ Navigation.RemovePage (page);
+ }
+ }
+
+ await Navigation.PopAsync ();
+ };
+
+ Navigation.PushAsync (page1);
+ }
+
+#if UITEST
+ [Test]
+ public void CanRemoveIntermediatePagesAndPopToFirstPage ()
+ {
+ // Start at page 1
+ RunningApp.WaitForElement ("Go To 2");
+ RunningApp.WaitForElement ("This is a label on page 1");
+ RunningApp.Tap ("Go To 2");
+
+ RunningApp.WaitForElement ("Go To 3");
+ RunningApp.Tap ("Go To 3");
+
+ RunningApp.WaitForElement ("Go To 4");
+ RunningApp.Tap ("Go To 4");
+
+ RunningApp.WaitForElement ("Back to 1");
+ RunningApp.Tap ("Back to 1");
+
+ // Clicking "Back to 1" should remove pages 2 and 3 from the stack
+ // Then call PopAsync, which should return to page 1
+ RunningApp.WaitForElement ("Go To 2");
+ RunningApp.WaitForElement ("This is a label on page 1");
+ }
+#endif
+
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37601.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37601.cs
new file mode 100644
index 00000000..4d40bd26
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37601.cs
@@ -0,0 +1,50 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 37601, "ToolbarItem throws error when navigating to TabbedPage ",
+ PlatformAffected.WinPhone)]
+ public class Bugzilla37601 : TestNavigationPage
+ {
+ protected override void Init ()
+ {
+ Navigation.PushAsync (new SelectPage ());
+ }
+ }
+
+ internal class SelectPage : ContentPage
+ {
+ public SelectPage ()
+ {
+ var button = new Button { Text = "Move" };
+
+ var label = new Label {
+ Text =
+ "Click the Move button. If the next page is displayed, the test has passed. If the app crashes, the test has failed."
+ };
+
+ Content = new StackLayout {
+ Children = { label, button }
+ };
+
+ button.Clicked += (sender, args) => { Navigation.PushAsync (new TabbedMain (), true); };
+
+ ToolbarItems.Add (new ToolbarItem { Text = "Log Out" });
+ }
+ }
+
+ internal class TabbedMain : TabbedPage
+ {
+ public TabbedMain ()
+ {
+ var page1 = new ContentPage { Title = "Page1" };
+ page1.Content = new StackLayout {
+ Children = { new Label { Text = "If you can see this, we haven't crashed. Yay!" } }
+ };
+
+ Children.Add (page1);
+ Children.Add (new ContentPage { Title = "Page2" });
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37625.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37625.cs
new file mode 100644
index 00000000..dd5f9819
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37625.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 37625, "App crashes when quickly adding/removing Image views (Windows UWP)")]
+ public class Bugzilla37625 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override async void Init ()
+ {
+ int retry = 5;
+ while (retry-- >= 0) {
+ var imageUri = new Uri ("https://xamarin.com/content/images/pages/products/platform.png");
+ Content = new Image () { Source = new UriImageSource () { Uri = imageUri }, BackgroundColor = Color.Black, AutomationId = "success" };
+
+ await Task.Delay (50);
+ }
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla37625Test ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("success"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37841.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37841.cs
new file mode 100644
index 00000000..2a8e236a
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37841.cs
@@ -0,0 +1,153 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve(AllMembers = true)]
+ [Issue(IssueTracker.Bugzilla, 37841, "TableView EntryCells and TextCells cease to update after focus change", PlatformAffected.Android)]
+ public class Bugzilla37841 : TestContentPage
+ {
+ _37841ViewModel _viewModel;
+
+ protected override void Init ()
+ {
+ _viewModel = new _37841ViewModel ();
+
+ var instructions = new Label { FontSize = 16, Text = @"Click on the Generate button.
+The EntryCell should display '12345' and the TextCell should display '6789'.
+Click on the Generate button a second time.
+The EntryCell should display '112358' and the TextCell should display '48151623'." };
+
+ var button = new Button { Text = "Generate" };
+ button.SetBinding (Button.CommandProperty, nameof (_37841ViewModel.GetNextNumbersCommand));
+
+ var random1 = new EntryCell { IsEnabled = false, Label = "Entry Cell" };
+ random1.SetBinding (EntryCell.TextProperty, nameof (_37841ViewModel.Value1));
+
+ var textCell = new TextCell { IsEnabled = false, Detail = "TextCell" };
+ textCell.SetBinding (TextCell.TextProperty, nameof (_37841ViewModel.Value2));
+
+ var buttonViewCell = new ViewCell { View = button };
+
+ var section = new TableSection ("") {
+ random1,
+ textCell,
+ buttonViewCell
+ };
+
+ var root = new TableRoot { section };
+ var tv = new TableView { Root = root };
+
+ Content = new StackLayout {
+ Children = { instructions, tv }
+ };
+
+ BindingContext = _viewModel;
+ }
+
+ [Preserve (AllMembers = true)]
+ public class _37841ViewModel : INotifyPropertyChanged
+ {
+ public int Value1
+ {
+ get { return _value1; }
+ set
+ {
+ if (value != _value1) {
+ _value1 = value;
+ RaisePropertyChanged ();
+ }
+ }
+ }
+
+ public int Value2
+ {
+ get { return _value2; }
+ set
+ {
+ if (value != _value2) {
+ _value2 = value;
+ RaisePropertyChanged ();
+ }
+ }
+ }
+
+ public Command GetNextNumbersCommand
+ => _getNextNumbersCommand ?? (_getNextNumbersCommand = new Command (ExecuteGenerateRandomCommand));
+
+ class SomeNumbers : IEnumerable<int>
+ {
+ public IEnumerator<int> GetEnumerator ()
+ {
+ while (true) {
+ yield return 12345;
+ yield return 6789;
+ yield return 112358;
+ yield return 48151623;
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator ()
+ {
+ return GetEnumerator ();
+ }
+ }
+
+ readonly IEnumerator<int> _numberList = new SomeNumbers ().GetEnumerator ();
+
+ void ExecuteGenerateRandomCommand ()
+ {
+ _numberList.MoveNext ();
+ Value1 = _numberList.Current;
+ _numberList.MoveNext ();
+ Value2 = _numberList.Current;
+ }
+
+ void RaisePropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+
+ handler?.Invoke (this, new PropertyChangedEventArgs (propertyName));
+ }
+
+ #region INotifyPropertyChanged implementation
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ #endregion
+
+ Command _getNextNumbersCommand;
+ int _value1;
+ int _value2;
+ }
+
+#if UITEST
+ [Test]
+ public void TextAndEntryCellsDataBindInTableView()
+ {
+ RunningApp.WaitForElement ("Generate");
+ RunningApp.Tap("Generate");
+
+ RunningApp.Screenshot ("First Generate Tap");
+
+ RunningApp.WaitForElement("12345");
+ RunningApp.WaitForElement("6789");
+
+ RunningApp.Tap("Generate");
+
+ RunningApp.Screenshot("Second Generate Tap");
+
+ RunningApp.WaitForElement("112358");
+ RunningApp.WaitForElement("48151623");
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37863.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37863.cs
new file mode 100644
index 00000000..4dd635c4
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla37863.cs
@@ -0,0 +1,26 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 37863, "Password is readable when Entry.IsEnabled is false ",
+ PlatformAffected.WinPhone)]
+ public class Bugzilla37863 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var label = new Label {
+ Text =
+ "Click the button to toggle IsEnabled on the password entry below. The actual password text should never show. If the text shows, the test has failed."
+ };
+ var entry = new Entry { IsPassword = true, Text = "swordfish" };
+ var button = new Button { Text = "Toggle IsEnabled" };
+
+ button.Clicked += (sender, args) => { entry.IsEnabled = !entry.IsEnabled; };
+
+ Content = new StackLayout {
+ Children = { label, entry, button }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38105.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38105.cs
new file mode 100644
index 00000000..ebb353f6
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38105.cs
@@ -0,0 +1,59 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 38105, "RemovePage does not cause back arrow to go away on Android",
+ NavigationBehavior.PushModalAsync)]
+ internal class Bugzilla38105 : TestMasterDetailPage
+ {
+ protected override void Init ()
+ {
+ Detail = new NavigationPage (new ViewA ());
+
+ var button = new Button () { Text = "Click me" };
+ button.Clicked += (o, e) => {
+ var navPage = (NavigationPage)Detail;
+
+ var rootPage = navPage.CurrentPage;
+
+ navPage.PopToRootAsync (false);
+
+ navPage.Navigation.PushAsync (new ViewB ());
+
+ navPage.Navigation.RemovePage (rootPage);
+
+ IsPresented = false;
+ };
+
+ Master = new ContentPage () {
+ Title = "test",
+ Content = button
+ };
+ }
+
+ public class ViewA : ContentPage
+ {
+ public ViewA ()
+ {
+ Title = "View A";
+ }
+ }
+
+ public class ViewB : ContentPage
+ {
+ public ViewB ()
+ {
+ Title = "View B";
+ }
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38112.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38112.cs
new file mode 100644
index 00000000..bab6f2d9
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38112.cs
@@ -0,0 +1,98 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 38112, "Switch becomes reenabled when previous ViewCell is removed from TableView", PlatformAffected.Android)]
+ public class Bugzilla38112 : TestContentPage
+ {
+ bool _removed;
+ protected override void Init ()
+ {
+ var layout = new StackLayout ();
+ var button = new Button { Text = "Click" };
+ var tablesection = new TableSection { Title = "Switches" };
+ var tableview = new TableView { Intent = TableIntent.Form, Root = new TableRoot { tablesection } };
+ var viewcell1 = new ViewCell {
+ View = new StackLayout {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ new Label { Text = "Switch 1", HorizontalOptions = LayoutOptions.StartAndExpand },
+ new Switch { AutomationId = "switch1", HorizontalOptions = LayoutOptions.End, IsToggled = true }
+ }
+ }
+ };
+ var viewcell2 = new ViewCell {
+ View = new StackLayout {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ new Label { Text = "Switch 2", HorizontalOptions = LayoutOptions.StartAndExpand },
+ new Switch { AutomationId = "switch2", HorizontalOptions = LayoutOptions.End, IsToggled = true }
+ }
+ }
+ };
+ Label label = new Label { Text = "Switch 3", HorizontalOptions = LayoutOptions.StartAndExpand };
+ Switch switchie = new Switch { AutomationId = "switch3", HorizontalOptions = LayoutOptions.End, IsToggled = true, IsEnabled = false };
+ switchie.Toggled += (sender, e) => {
+ label.Text = "FAIL";
+ };
+ var viewcell3 = new ViewCell {
+ View = new StackLayout {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ label,
+ switchie,
+ }
+ }
+ };
+
+ tablesection.Add (viewcell1);
+ tablesection.Add (viewcell2);
+ tablesection.Add (viewcell3);
+
+ button.Clicked += (sender, e) => {
+ if (_removed)
+ tablesection.Insert (1, viewcell2);
+ else
+ tablesection.Remove (viewcell2);
+
+ _removed = !_removed;
+ };
+
+ layout.Children.Add (button);
+ layout.Children.Add (tableview);
+
+ Content = layout;
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla38112_SwitchIsStillOnScreen ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Click"));
+ RunningApp.Tap (q => q.Marked ("Click"));
+ RunningApp.WaitForElement (q => q.Marked ("switch3"));
+ }
+
+ [Test]
+ public void Bugzilla38112_SwitchIsStillDisabled ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Click"));
+ RunningApp.Tap (q => q.Marked ("Click"));
+ RunningApp.WaitForElement (q => q.Marked ("switch3"));
+ RunningApp.Tap (q => q.Marked ("switch3"));
+ RunningApp.WaitForNoElement (q => q.Marked ("FAIL"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38416.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38416.xaml
new file mode 100644
index 00000000..4815563a
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38416.xaml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<local:TestContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Controls"
+ x:Class="Xamarin.Forms.Controls.Bugzilla38416">
+ <local:TestContentPage.Content>
+ <StackLayout>
+ <Button Text="Swap Visibility" Clicked="SwapVisibilityClicked" HorizontalOptions="FillAndExpand" />
+ <BoxView x:Name="Box" BackgroundColor="Red" WidthRequest="50" HorizontalOptions="Center" />
+
+ <StackLayout x:Name="FirstLayout" VerticalOptions="FillAndExpand">
+ <ListView x:Name="FirstListView"
+ HasUnevenRows="True"
+ VerticalOptions="FillAndExpand">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <!--<ViewCell>
+ <Label Text="{Binding Name}" FontSize="19"/>
+ </ViewCell>-->
+ <TextCell Text="{Binding Name}"/>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </StackLayout>
+ </StackLayout>
+ </local:TestContentPage.Content>
+</local:TestContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38416.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38416.xaml.cs
new file mode 100644
index 00000000..98012901
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38416.xaml.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.ObjectModel;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 38416, "ListView Sized Incorrectly After Containing Layout's Visibility is Toggled")]
+ public partial class Bugzilla38416 : TestContentPage
+ {
+ [Preserve (AllMembers = true)]
+ public class ListItem
+ {
+ public string Name { get; set; }
+ }
+
+#if !UITEST
+ void SwapVisibilityClicked(object sender, EventArgs e)
+ {
+ Box.IsVisible = !Box.IsVisible;
+ FirstLayout.IsVisible = !FirstLayout.IsVisible;
+ //FirstListView.IsVisible = !FirstListView.IsVisible; //Workaround. Has to be called after the layout's visibility
+ }
+#endif
+
+ protected override void Init ()
+ {
+#if !UITEST
+ InitializeComponent();
+
+ var items = new ObservableCollection<ListItem>();
+ FirstListView.ItemsSource = items;
+
+ for(int i=0; i<70; i++)
+ {
+ items.Add(new ListItem { Name = string.Format("List Item {0}", i+1) });
+ }
+
+ Box.IsVisible = true;
+ //FirstListView.IsVisible = false; //Workaround
+ FirstLayout.IsVisible = false;
+#endif
+ }
+
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38658.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38658.cs
new file mode 100644
index 00000000..b907a658
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38658.cs
@@ -0,0 +1,74 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 38658, "Rotation causes app containing CarouselPage to freeze", PlatformAffected.iOS)]
+ public class Bugzilla38658 : TestTabbedPage // or TestMasterDetailPage, etc ...
+ {
+ public class TestCarouselPage : CarouselPage
+ {
+ public TestCarouselPage ()
+ {
+ Children.Add (new ContentPage () {
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = "Rotate the device to Landscape and back to Portrait. If the app hangs, this test has failed." },
+ new BoxView { Color = Color.Red, HeightRequest = 200, WidthRequest = 200 }
+ }
+ }
+ });
+ Children.Add (new ContentPage () {
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = "Rotate the device to Landscape and back to Portrait. If the app hangs, this test has failed." },
+ new BoxView { Color = Color.Green, HeightRequest = 200, WidthRequest = 200 }
+ }
+ }
+ });
+ }
+ }
+ public class StartPage : ContentPage
+ {
+ public StartPage ()
+ {
+ Button button = new Button {
+ AutomationId = "btn",
+ Text = "Click"
+ };
+ button.Clicked += button_Clicked;
+ Content = button;
+ }
+
+ async void button_Clicked (object sender, EventArgs e)
+ {
+ await Navigation.PushAsync (new TestCarouselPage ());
+ }
+ }
+
+ protected override void Init ()
+ {
+ Children.Add (new NavigationPage (new StartPage () { Title = "Page" }));
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla38658Test ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("btn"));
+ RunningApp.Tap (q => q.Marked ("btn"));
+ RunningApp.SetOrientationLandscape ();
+ RunningApp.SetOrientationPortrait ();
+ RunningApp.Back ();
+ RunningApp.WaitForElement (q => q.Marked ("btn"));
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38827.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38827.xaml
new file mode 100644
index 00000000..2c0cd86d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38827.xaml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issues.Bugzilla38827">
+ <ScrollView>
+ <Grid RowSpacing="5"
+ ColumnSpacing="5">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="*"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+
+ <StackLayout>
+ <Label HorizontalTextAlignment="Center"
+ HorizontalOptions="FillAndExpand"
+ AutomationId="LoginPageIdentifier"
+ FontSize="Large"
+ Text="Sign in with your Xamarin account to save and sync favorites and session feedback. Sign in with your Xamarin account to save and sync favorites and session feedback. Sign in with your Xamarin account to save and sync favorites and session feedback. Sign in with your Xamarin account to save and sync favorites and session feedback."/>
+
+ </StackLayout>
+ </Grid>
+ </ScrollView>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38827.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38827.xaml.cs
new file mode 100644
index 00000000..c686c2bf
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38827.xaml.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+ public partial class Bugzilla38827 : ContentPage
+ {
+ public Bugzilla38827 ()
+ {
+#if !UITEST
+ InitializeComponent ();
+#endif
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38978.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38978.cs
new file mode 100644
index 00000000..9d8ce68b
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla38978.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Linq;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 38978, "Cell.ForceUpdateSize issues with row selection/deselection (ViewCell)", PlatformAffected.Android)]
+ public class Bugzilla38978 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ [Preserve (AllMembers = true)]
+ public class MyViewCell : ViewCell
+ {
+ Image _image;
+ public MyViewCell ()
+ {
+ _image = new Image {
+ Source = ImageSource.FromFile ("oasis.jpg"),
+ HeightRequest = 50
+ };
+
+ Label label = new Label { Text = "Click the image to resize", VerticalOptions = LayoutOptions.Center };
+
+ var tapGestureRecognizer = new TapGestureRecognizer ();
+ tapGestureRecognizer.Tapped += (object sender, EventArgs e) => {
+ if (_image.HeightRequest < 250) {
+ _image.HeightRequest = _image.Height + 100;
+ ForceUpdateSize ();
+ label.Text = "If the tapped image is not larger, this test has failed.";
+ }
+ };
+ _image.GestureRecognizers.Add (tapGestureRecognizer);
+
+ var stackLayout = new StackLayout {
+ Padding = new Thickness (20, 5, 5, 5),
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ _image,
+ label
+ }
+ };
+
+ View = stackLayout;
+ }
+
+ protected override void OnBindingContextChanged ()
+ {
+ base.OnBindingContextChanged ();
+ var item = BindingContext?.ToString();
+ if (string.IsNullOrWhiteSpace (item))
+ return;
+
+ _image.AutomationId = item;
+ }
+ }
+
+ protected override void Init ()
+ {
+ var listView = new ListView {
+ HasUnevenRows = true,
+ ItemTemplate = new DataTemplate (typeof (MyViewCell)),
+ ItemsSource = Enumerable.Range (0, 10)
+ };
+
+ Content = new StackLayout {
+ Padding = new Thickness (0, 20, 0, 0),
+ Children = {
+ listView
+ }
+ };
+ }
+
+#if UITEST
+ [Test]
+ [Category("ManualReview")]
+ public void Bugzilla38978Test ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("2"));
+ RunningApp.Tap (q => q.Marked ("2"));
+ RunningApp.Screenshot("If the tapped image is not larger, this test has failed.");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39331.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39331.cs
new file mode 100644
index 00000000..d58c752b
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39331.cs
@@ -0,0 +1,71 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 39331, "[Android] BoxView Is InputTransparent Even When Set to False")]
+ public class Bugzilla39331 : TestContentPage
+ {
+ View _busyBackground;
+ Button _btnLogin;
+
+ protected override void Init ()
+ {
+ AbsoluteLayout layout = new AbsoluteLayout {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ };
+
+ BackgroundColor = Color.FromUint (0xFFDBDBDB);
+
+ _btnLogin = new Button {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+
+ Text = "Press me",
+ BackgroundColor = Color.FromUint (0xFF6E932D),
+ TextColor = Color.White,
+ };
+ _btnLogin.Clicked += BtnLogin_Clicked;
+ layout.Children.Add (_btnLogin, new Rectangle (0.5f, 0.5f, 0.25f, 0.25f), AbsoluteLayoutFlags.All);
+
+ _busyBackground = new BoxView {
+ BackgroundColor = new Color (0, 0, 0, 0.5f),
+ IsVisible = false,
+ InputTransparent = false
+ };
+ layout.Children.Add (_busyBackground, new Rectangle (0, 0, 1, 1), AbsoluteLayoutFlags.SizeProportional);
+
+ Content = layout;
+ }
+
+ void BtnLogin_Clicked (object sender, EventArgs e)
+ {
+
+ if (!_busyBackground.IsVisible) {
+ _btnLogin.Text = "Blocked?";
+ _busyBackground.IsVisible = true;
+ } else {
+ _btnLogin.Text = "Guess Not";
+ _busyBackground.IsVisible = false;
+ }
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla34912Test ()
+ {
+ RunningApp.Tap (q => q.Marked ("Press me"));
+ RunningApp.WaitForElement (q => q.Marked ("Blocked?"));
+ RunningApp.Tap (q => q.Marked ("Blocked?"));
+ RunningApp.WaitForNoElement (q => q.Marked ("Guess Not"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39395.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39395.cs
new file mode 100644
index 00000000..8abb0445
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39395.cs
@@ -0,0 +1,30 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 39395, "SwitchCell does not take all available place inside ListView",
+ PlatformAffected.WinRT)]
+ public class Bugzilla39395 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var instructions = new Label {
+ FontSize = 18,
+ Text =
+ "The switch cells below should be aligned with the right edge of the screen. If they are not, this test has failed."
+ };
+
+ Content = new StackLayout {
+ BackgroundColor = Color.Gray,
+ Children = {
+ instructions,
+ new ListView {
+ ItemTemplate = new DataTemplate (typeof(SwitchCell)),
+ ItemsSource = new[] { "Text", "Text" }
+ }
+ }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39461.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39461.cs
new file mode 100644
index 00000000..fe896c54
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39461.cs
@@ -0,0 +1,36 @@
+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, 39461, "[UWP] Labels within a ScrollView are blurred", PlatformAffected.WinRT)]
+ public class Bugzilla39461 : TestContentPage
+ {
+ protected override void Init()
+ {
+ StringBuilder text = new StringBuilder();
+ for (int i = 0; i < 10000; i++)
+ {
+ text.Append("text ");
+ }
+
+ var top = new ScrollView { Content = new Label { FontSize = 12, TextColor = Color.Red, Text = text.ToString() } };
+ AbsoluteLayout.SetLayoutFlags(top, AbsoluteLayoutFlags.All);
+ AbsoluteLayout.SetLayoutBounds(top, new Rectangle(0, 0, 1, 0.5));
+
+ var bottom = new Label { FontSize = 12, TextColor = Color.Red, Text = text.ToString() };
+ AbsoluteLayout.SetLayoutFlags(bottom, AbsoluteLayoutFlags.All);
+ AbsoluteLayout.SetLayoutBounds(bottom, new Rectangle(0, 1, 1, 0.5));
+
+ var layout = new AbsoluteLayout { Children = { top, bottom } };
+
+ Content = layout;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39463.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39463.xaml
new file mode 100644
index 00000000..b1932867
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39463.xaml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issues.Bugzilla39463">
+ <ListView x:Name="lvView" RowHeight="100" >
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <ViewCell.View>
+ <ContentView BackgroundColor="Yellow">
+ <Label Text="{Binding }" TextColor="Black" />
+ </ContentView>
+ </ViewCell.View>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39463.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39463.xaml.cs
new file mode 100644
index 00000000..05fb4c1d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39463.xaml.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+ [Preserve(AllMembers = true)]
+ [Issue(IssueTracker.Bugzilla, 39463, "Items not showing in ListView using DataTemplate when there are more items than can fit on screen", PlatformAffected.WinPhone)]
+ public partial class Bugzilla39463 : ContentPage
+ {
+ public Bugzilla39463 ()
+ {
+ #if !UITEST
+ InitializeComponent ();
+
+ var n = 16;
+
+ var listStr = new List<string>();
+ for (int i = 0; i < n; i++)
+ {
+ listStr.Add("Test : " + i);
+ }
+
+ lvView.ItemsSource = listStr;
+#endif
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39483.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39483.xaml
new file mode 100644
index 00000000..1e81a65e
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39483.xaml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issues.Bugzilla39483">
+
+
+<ListView ItemsSource="{Binding DataList}">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell >
+ <ViewCell.ContextActions>
+ <MenuItem Text="Menü 1" />
+ <MenuItem Text="Menü 2" />
+ <MenuItem Text="Menü 3" />
+ <MenuItem Text="Menü 4" />
+ </ViewCell.ContextActions>
+ <ViewCell.View>
+ <Label Text="{Binding .}" />
+ </ViewCell.View>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+</ListView>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39483.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39483.xaml.cs
new file mode 100644
index 00000000..2b910b7c
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39483.xaml.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+ [Issue(IssueTracker.Bugzilla, 39483, "ListView Context Menu localization", PlatformAffected.iOS)]
+ public partial class Bugzilla39483 : ContentPage
+ {
+ public Bugzilla39483 ()
+ {
+#if APP
+
+ InitializeComponent ();
+
+ BindingContext = new DemoViewModel();
+
+#endif
+ }
+ }
+
+ public class DemoViewModel : ViewModelBase
+ {
+ public DemoViewModel()
+ {
+ DataList = new List<string>();
+ DataList.Add("Listenelement 1");
+ DataList.Add("Listenelement 2");
+ DataList.Add("Listenelement 3");
+ DataList.Add("Listenelement 4");
+ }
+
+ List<string> _dataList;
+ public List<string> DataList
+ {
+ get
+ {
+ return _dataList;
+ }
+ set { _dataList = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39499.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39499.cs
new file mode 100644
index 00000000..44fa2899
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39499.cs
@@ -0,0 +1,134 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Collections.ObjectModel;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 39499, "CarouselViewTest")]
+ public sealed class CarouselViewContentPage : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ [Preserve (AllMembers = true)]
+ public sealed class Item
+ {
+ static int s_id = 0;
+
+ int id;
+
+ internal Item()
+ {
+ id = s_id++;
+ }
+
+ public int Id => id;
+ }
+
+ [Preserve (AllMembers = true)]
+ public sealed class ItemView : ContentView
+ {
+ public ItemView ()
+ {
+ var idLabel = new Label () { StyleId = "id", TextColor = Color.White };
+ idLabel.SetBinding (Label.TextProperty, nameof(Item.Id));
+
+ var stackLayout = new StackLayout {
+ Children = {
+ new Label { Text = "Target" },
+ new Label { Text = "Stack" }
+ },
+ BackgroundColor = Color.Red
+ };
+
+ var button = CreateButton ("Hide Target Stack", () => {
+ stackLayout.IsVisible = false;
+ });
+
+ Content = new StackLayout {
+ Children = {
+ idLabel,
+ button,
+ stackLayout,
+ }
+ };
+ }
+
+ Button CreateButton(string text, Action clicked)
+ {
+ var button = new Button ();
+ button.Text = text;
+ button.Clicked += (s, e) => {
+ clicked ();
+ };
+ return button;
+ }
+ }
+
+ static readonly IList<Item> Items = new ObservableCollection<Item> () {
+ new Item(),
+ new Item(),
+ };
+
+ Button CreateButton(string text, Action onClicked = null)
+ {
+ var button = new Button {
+ Text = text
+ };
+
+ if (onClicked != null)
+ button.Clicked += (s, e) => onClicked();
+
+ return button;
+ }
+
+ protected override void Init ()
+ {
+ BackgroundColor = Color.Blue;
+
+ var carouselView = new CarouselView {
+ BackgroundColor = Color.Purple,
+ ItemsSource = Items,
+ ItemTemplate = new DataTemplate(typeof(ItemView)),
+ Position = 0
+ };
+
+ var moveBar = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Children = {
+ CreateButton ("<<", () => carouselView.Position = 0),
+ CreateButton ("<", () => { try { carouselView.Position--; } catch { } }),
+ CreateButton (">", () => { try { carouselView.Position++; } catch { } }),
+ CreateButton (">>", () => carouselView.Position = Items.Count - 1)
+ }
+ };
+
+ Content = new StackLayout {
+ Children = {
+ carouselView,
+ moveBar,
+ }
+ };
+ }
+
+#if UITEST
+ //[Test]
+ public void CarouselViewTest ()
+ {
+ var app = RunningApp;
+ app.Screenshot ("I am at Issue 1");
+ app.WaitForElement (q => q.Marked ("Remove"));
+
+ app.Screenshot ("I see the Label");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39530.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39530.cs
new file mode 100644
index 00000000..7f510ab6
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39530.cs
@@ -0,0 +1,85 @@
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest.Queries;
+using Xamarin.Forms.Core.UITests;
+#endif
+
+namespace Xamarin.Forms.Controls.Issues
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 39530, "Frames do not handle pan or pinch gestures under AppCompat", PlatformAffected.Android)]
+ public class Bugzilla39530 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var taps = new Label { Text = "Taps: 0" };
+ var pans = new Label ();
+ var pinches = new Label ();
+
+ var pangr = new PanGestureRecognizer ();
+ var tapgr = new TapGestureRecognizer ();
+ var pinchgr = new PinchGestureRecognizer ();
+
+ var frame = new Frame {
+ HasShadow = false,
+ HorizontalOptions = LayoutOptions.Fill,
+ VerticalOptions = LayoutOptions.Fill,
+ BackgroundColor = Color.White,
+ Padding = new Thickness (5),
+ HeightRequest = 300,
+ WidthRequest = 300,
+ AutomationId = "frame"
+ };
+
+ var tapCount = 0;
+
+ tapgr.Command = new Command (() => {
+ tapCount += 1;
+ taps.Text = $"Taps: {tapCount}";
+ });
+
+ pangr.PanUpdated += (sender, args) => pans.Text = $"Panning: {args.StatusType}";
+
+ pinchgr.PinchUpdated += (sender, args) => pinches.Text = $"Pinching: {args.Status}";
+
+ frame.GestureRecognizers.Add (tapgr);
+ frame.GestureRecognizers.Add (pangr);
+ frame.GestureRecognizers.Add(pinchgr);
+
+ Content = new StackLayout {
+ BackgroundColor = Color.Olive,
+ Children = { taps, pans, pinches, frame }
+ };
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla39530PanTest()
+ {
+ AppRect frameBounds = RunningApp.Query (q => q.Marked ("frame"))[0].Rect;
+ RunningApp.Pan (new Drag (frameBounds, frameBounds.X + 10, frameBounds.Y + 10, frameBounds.X + 100, frameBounds.Y + 100, Drag.Direction.LeftToRight));
+
+ RunningApp.WaitForElement (q => q.Marked ("Panning: Completed"));
+ }
+
+ [Test]
+ public void Bugzilla39530PinchTest()
+ {
+ RunningApp.PinchToZoomIn ("frame");
+ RunningApp.WaitForElement(q => q.Marked("Pinching: Completed"));
+ }
+
+ [Test]
+ public void Bugzilla39530TapTest()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("frame"));
+ RunningApp.Tap ("frame");
+ RunningApp.WaitForElement (q => q.Marked ("Taps: 1"));
+ RunningApp.Tap ("frame");
+ RunningApp.WaitForElement (q => q.Marked ("Taps: 2"));
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39624.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39624.cs
new file mode 100644
index 00000000..eddd1b06
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39624.cs
@@ -0,0 +1,40 @@
+using System.Diagnostics;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 39624, "CarouselPage.Children Appear Out of Order", PlatformAffected.WinRT)]
+ public class Bugzilla39624 : TestCarouselPage
+ {
+ protected override void Init ()
+ {
+ var instructions =
+ "Flip through each page of the carousel from 1 to 5; the pages should display in order. Then flip backward to page 1; if any of the pages display out of order, the test has failed.";
+
+ Children.Add (GeneratePage ("Page 1", Color.Red, instructions));
+ Children.Add (GeneratePage ("Page 2", Color.Green, instructions));
+ Children.Add (GeneratePage ("Page 3", Color.Blue, instructions));
+ Children.Add (GeneratePage ("Page 4", Color.Purple, instructions));
+ Children.Add (GeneratePage ("Page 5", Color.Black, instructions));
+
+ CurrentPageChanged += (sender, args) => Debug.WriteLine (CurrentPage.Title);
+ }
+
+ ContentPage GeneratePage (string title, Color color, string instructions)
+ {
+ var page = new ContentPage {
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = title, FontSize = 24, TextColor = Color.White },
+ new Label { Text = instructions, TextColor = Color.White }
+ }
+ },
+ BackgroundColor = color,
+ Title = title
+ };
+
+ return page;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39668.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39668.cs
new file mode 100644
index 00000000..547e39aa
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39668.cs
@@ -0,0 +1,51 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Linq;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 39668, "Overriding ListView.CreateDefault Does Not Work on Windows", PlatformAffected.WinRT)]
+ public class Bugzilla39668 : TestContentPage
+ {
+ [Preserve (AllMembers = true)]
+ public class CustomListView : ListView
+ {
+ protected override Cell CreateDefault (object item)
+ {
+ var cell = new ViewCell ();
+
+ cell.View = new StackLayout {
+ BackgroundColor = Color.Green,
+ Children = {
+ new Label { Text = "Success" }
+ }
+ };
+
+ return cell;
+ }
+ }
+
+ protected override void Init ()
+ {
+ CustomListView lv = new CustomListView () {
+ ItemsSource = Enumerable.Range (0, 10)
+ };
+ Content = new StackLayout { Children = { new Label { Text = "If the ListView does not have green Cells, this test has failed." }, lv } };
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla39668Test ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Success"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/CarouselAsync.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/CarouselAsync.cs
new file mode 100644
index 00000000..d6e9b19a
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/CarouselAsync.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.None, 0, "Carousel Async Add Page Issue", PlatformAffected.All, NavigationBehavior.PushModalAsync)]
+ public class CarouselAsync : TestCarouselPage
+ {
+ protected override void Init ()
+ {
+ Children.Add (new ContentPage {
+ BackgroundColor = Color.Red,
+ Content = new Label {
+ Text = "Page One"
+ }
+ });
+ Children.Add (new ContentPage {
+ BackgroundColor = Color.Green,
+ Content = new Label {
+ Text = "Page Two"
+ }
+ });
+ Update (this);
+ }
+
+ static void Update (CarouselPage page)
+ {
+ Device.StartTimer (TimeSpan.FromSeconds (1), () => {
+ page.Children.Remove (page.Children.Skip (1).First () as ContentPage);
+ Device.StartTimer (TimeSpan.FromSeconds (1), () => {
+ page.Children.Add (new ContentPage {
+ BackgroundColor = Color.Blue,
+ Content = new Label {
+ Text = "Page Two - Added"
+ }
+ });
+ page.Children.Add (new ContentPage {
+ BackgroundColor = Color.Gray,
+ Content = new Label {
+ Text = "Page Three - Added"
+ }
+ });
+ return false;
+ });
+ return false;
+ });
+ }
+
+#if UITEST
+ [Test]
+ [Description ("All elements renderered")]
+ public void CarouselAsycTestsAllElementsPresent ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Page One"));
+ RunningApp.Screenshot ("All elements present");
+ }
+
+ [Test]
+ [Description ("Async Pages inserted into a CarouselPage")]
+ public void CarouselAsycTestsAllPagesExistAfterAsyncAdding ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Page One"));
+
+ var window = RunningApp.Query (q => q.Raw ("*").Index (0));
+ var width = window [0].Rect.Width;
+ var height = window [0].Rect.Height;
+
+ System.Threading.Thread.Sleep (3000);
+
+ // TODO Implement swipe left and swipe right
+ //App.DragFromTo (width - 10.0f, height / 2.0f, 10.0f, height / 2.0f);
+ //App.WaitForElement (q => q.Marked ("Page Two - Added"));
+ //App.Screenshot ("At Page 2");
+
+ //Thread.Sleep (3000);
+
+ //App.DragFromTo (width - 10.0f, height / 2.0f, 10.0f, height / 2.0f);
+ //App.WaitForElement (q => q.Marked ("Page Three - Added"));
+ //App.Screenshot ("At Page 3");
+ }
+
+/*******************************************************/
+/**************** Landscape tests **********************/
+/*******************************************************/
+
+ [Test]
+ [Description ("All elements renderered - landscape")]
+ public void CarouselAsycTestsAllElementsPresentLandscape ()
+ {
+ RunningApp.SetOrientationLandscape ();
+ CarouselAsycTestsAllElementsPresent ();
+ RunningApp.SetOrientationPortrait ();
+ }
+
+ [Test]
+ [Description ("Async Pages inserted into a CarouselPage - landscape")]
+ public void CarouselAsycTestsAllPagesExistAfterAsyncAddingLandscape ()
+ {
+ RunningApp.SetOrientationLandscape ();
+ CarouselAsycTestsAllPagesExistAfterAsyncAdding ();
+ RunningApp.SetOrientationPortrait ();
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ComplexListView.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ComplexListView.cs
new file mode 100644
index 00000000..2e2fa690
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ComplexListView.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.None, 0, "Complex ListView", PlatformAffected.All)]
+ public class ComplexListView
+ : ContentPage
+ {
+ public ComplexListView()
+ {
+ Performance.Clear();
+
+ var showPerf = new Button { Text = "Performance" };
+ showPerf.Clicked += (sender, args) => {
+ Performance.DumpStats();
+ Performance.Clear();
+ };
+
+ Content = new StackLayout {
+ Orientation = StackOrientation.Vertical,
+ Children = {
+ showPerf,
+ new ListView {
+ ItemTemplate = new DataTemplate (typeof (ComplexViewCell)),
+ ItemsSource =
+ new[] {
+ "a", "b", "c", "a", "b", "c", "a", "b", "c", "a", "b", "c", "a", "b", "c", "a", "b", "c", "a", "b", "c", "a",
+ "b", "c", "a", "b", "c", "a", "b", "c", "a", "b", "c", "a", "b", "c"
+ }
+ }
+ }
+ };
+ }
+ }
+
+ internal class ComplexViewCell
+ : ViewCell
+ {
+ static ImageSource s_mImgProdCount;
+ static ImageSource s_mImgEndTime;
+ static ImageSource s_mImgRenewal;
+
+ public ComplexViewCell()
+ {
+ if (s_mImgProdCount == null)
+ s_mImgProdCount = ImageSource.FromFile ("bank.png");
+ if (s_mImgEndTime == null)
+ s_mImgEndTime = ImageSource.FromFile ("bank.png");
+ if (s_mImgRenewal == null)
+ s_mImgRenewal = ImageSource.FromFile ("bank.png");
+
+ var label1 = new Label { Text = "Label 1", Font = Font.SystemFontOfSize (NamedSize.Small, FontAttributes.Bold) };
+ label1.SetBinding (Label.TextProperty, new Binding ("."));
+
+ var label2 = new Label { Text = "Label 2", Font = Font.SystemFontOfSize (NamedSize.Small) };
+
+ // was ListButton?
+ var button = new Button {
+ Text = "X",
+ BackgroundColor = Color.Gray,
+ HorizontalOptions = LayoutOptions.EndAndExpand
+ };
+ button.SetBinding (Button.CommandParameterProperty, new Binding ("."));
+ button.Clicked += (sender, e) => {
+ var b = (Button) sender;
+ var t = b.CommandParameter;
+ ((ContentPage) ((ListView) ((StackLayout) b.ParentView).ParentView).ParentView).DisplayAlert ("Clicked",
+ t + " button was clicked", "OK");
+ Debug.WriteLine ("clicked" + t);
+ };
+
+ Image imgProdCount = new Image {
+ Aspect = Aspect.AspectFit,
+ Source = s_mImgProdCount,
+ };
+
+ Image imgEndTime = new Image {
+ Aspect = Aspect.AspectFit,
+ Source = s_mImgEndTime,
+ };
+
+ Image imgRenewal = new Image {
+ Aspect = Aspect.AspectFit,
+ Source = s_mImgRenewal,
+ };
+
+ View = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ HorizontalOptions = LayoutOptions.StartAndExpand,
+ Padding = new Thickness (15, 5, 5, 15),
+ Children = {
+ new StackLayout {
+ Orientation = StackOrientation.Vertical,
+ Children = { label1, label2 }
+ },
+ button,
+ imgProdCount,
+ imgEndTime,
+ imgRenewal
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/DataTemplateGridImageTest.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/DataTemplateGridImageTest.cs
new file mode 100644
index 00000000..75de0ed7
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/DataTemplateGridImageTest.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.None, 0, "Images in DataTemplates with Grids don't show until resize on UWP",
+ PlatformAffected.WinRT)]
+ public class DataTemplateGridImageTest : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var instructions = new Label { FontSize = 24, Text = "The first ListView below should have a Xamarin logo visible in it. The second should have a pink image with white writing. If either image is not displayed, this test has failed." };
+
+ ImageSource remoteSource =
+ ImageSource.FromUri (new Uri ("https://xamarin.com/content/images/pages/branding/assets/xamagon.png"));
+ ImageSource localSource = ImageSource.FromFile ("oasis.jpg");
+
+ var remoteImage = new Image { Source = remoteSource, BackgroundColor = Color.Red };
+ var localImage = new Image { Source = localSource, BackgroundColor = Color.Red };
+
+ var listViewRemoteImage = new ListView {
+ BackgroundColor = Color.Green,
+ ItemTemplate = new DataTemplate (() => new TestCellGridImage (remoteImage)),
+ ItemsSource = new List<string> { "1" }
+ };
+
+ var listViewLocalImage = new ListView {
+ BackgroundColor = Color.Green,
+ ItemTemplate = new DataTemplate (() => new TestCellGridImage (localImage)),
+ ItemsSource = new List<string> { "1" }
+ };
+
+ Content = new StackLayout {
+ Children = {
+ instructions,
+ listViewRemoteImage,
+ listViewLocalImage
+ }
+ };
+ }
+
+ [Preserve (AllMembers = true)]
+ public class TestCellGridImage : ViewCell
+ {
+ public TestCellGridImage (View image)
+ {
+ var grid = new Grid { BackgroundColor = Color.Yellow, WidthRequest = 200, HeightRequest = 200 };
+ grid.Children.Add (image);
+ View = grid;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/DefaultColorToggleTest.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/DefaultColorToggleTest.cs
new file mode 100644
index 00000000..6f6cec09
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/DefaultColorToggleTest.cs
@@ -0,0 +1,146 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.None, 0, "Default colors toggle test", PlatformAffected.All)]
+ public class DefaultColorToggleTest : ContentPage
+ {
+ Button _buttonColorDefaultToggle;
+ Button _buttonColorInitted;
+ Label _labelColorDefaultToggle;
+ Label _labelColorInitted;
+
+ public DefaultColorToggleTest ()
+ {
+ _buttonColorDefaultToggle = new Button {
+ Text = "Default Button Color"
+ };
+
+ _buttonColorInitted = new Button {
+ Text = "I should be red",
+ TextColor = Color.Red
+ };
+
+ _labelColorDefaultToggle = new Label {
+ Text = "Default Label Color"
+ };
+
+ _labelColorInitted = new Label {
+ Text = "I should be blue",
+ TextColor = Color.Blue
+ };
+
+ _buttonColorDefaultToggle.Clicked += (s, e) => {
+ if (_buttonColorDefaultToggle.TextColor == Color.Default) {
+ _buttonColorDefaultToggle.TextColor = Color.Red;
+ _buttonColorDefaultToggle.Text = "Custom Button Color";
+ } else {
+ _buttonColorDefaultToggle.TextColor = Color.Default;
+ _buttonColorDefaultToggle.Text = "Default Button Color";
+ }
+
+ };
+
+ _labelColorDefaultToggle.GestureRecognizers.Add (new TapGestureRecognizer{Command = new Command (o=>{
+ if (_labelColorDefaultToggle.TextColor == Color.Default) {
+ _labelColorDefaultToggle.TextColor = Color.Green;
+ _labelColorDefaultToggle.Text = "Custom Label Color";
+ } else {
+ _labelColorDefaultToggle.TextColor = Color.Default;
+ _labelColorDefaultToggle.Text = "Default Label Color";
+ }
+ })});
+
+ var entryTextColorDefaultToggle = new Entry () { Text = "Default Entry Text Color" };
+ var entryTextColorInit = new Entry () { Text = "Should Be Red", TextColor = Color.Red };
+ var entryToggleButton = new Button () { Text = "Toggle Entry Color" };
+ entryToggleButton.Clicked += (sender, args) => {
+ if (entryTextColorDefaultToggle.TextColor.IsDefault) {
+ entryTextColorDefaultToggle.TextColor = Color.Fuchsia;
+ entryTextColorDefaultToggle.Text = "Should Be Fuchsia";
+ } else {
+ entryTextColorDefaultToggle.TextColor = Color.Default;
+ entryTextColorDefaultToggle.Text = "Default Entry Text Color";
+ }
+ };
+
+ var entryPlaceholderColorDefaultToggle = new Entry () { Placeholder = "Default Placeholder Color" };
+ var entryPlaceholderColorInit = new Entry () { Placeholder = "Should Be Lime", PlaceholderColor = Color.Lime };
+ var entryPlaceholderToggleButton = new Button () { Text = "Toggle Placeholder Color" };
+ entryPlaceholderToggleButton.Clicked += (sender, args) => {
+ if (entryPlaceholderColorDefaultToggle.PlaceholderColor.IsDefault) {
+ entryPlaceholderColorDefaultToggle.PlaceholderColor = Color.Lime;
+ entryPlaceholderColorDefaultToggle.Placeholder = "Should Be Lime";
+ } else {
+ entryPlaceholderColorDefaultToggle.PlaceholderColor = Color.Default;
+ entryPlaceholderColorDefaultToggle.Placeholder = "Default Placeholder Color";
+ }
+ };
+
+ var passwordColorDefaultToggle = new Entry () { IsPassword = true, Text = "Default Password Color" };
+ var passwordColorInit = new Entry () { IsPassword = true, Text = "Should Be Red", TextColor = Color.Red };
+ var passwordToggleButton = new Button () { Text = "Toggle Password Box (Default)" };
+ passwordToggleButton.Clicked += (sender, args) => {
+ if (passwordColorDefaultToggle.TextColor.IsDefault) {
+ passwordColorDefaultToggle.TextColor = Color.Red;
+ passwordToggleButton.Text = "Toggle Password Box (Red)";
+ } else {
+ passwordColorDefaultToggle.TextColor = Color.Default;
+ passwordToggleButton.Text = "Toggle Password Box (Default)";
+ }
+ };
+
+ var searchbarTextColorDefaultToggle = new Entry () { Text = "Default SearchBar Text Color" };
+ var searchbarTextColorToggleButton = new Button () { Text = "Toggle SearchBar Color" };
+ searchbarTextColorToggleButton.Clicked += (sender, args) => {
+ if (searchbarTextColorDefaultToggle.TextColor.IsDefault) {
+ searchbarTextColorDefaultToggle.TextColor = Color.Fuchsia;
+ searchbarTextColorDefaultToggle.Text = "Should Be Fuchsia";
+ } else {
+ searchbarTextColorDefaultToggle.TextColor = Color.Default;
+ searchbarTextColorDefaultToggle.Text = "Default SearchBar Text Color";
+ }
+ };
+
+ var searchbarPlaceholderColorDefaultToggle = new Entry () { Placeholder = "Default Placeholder Color" };
+ var searchbarPlaceholderToggleButton = new Button () { Text = "Toggle Placeholder Color" };
+ searchbarPlaceholderToggleButton .Clicked += (sender, args) => {
+ if (searchbarPlaceholderColorDefaultToggle.PlaceholderColor.IsDefault) {
+ searchbarPlaceholderColorDefaultToggle.PlaceholderColor = Color.Lime;
+ searchbarPlaceholderColorDefaultToggle.Placeholder = "Should Be Lime";
+ } else {
+ searchbarPlaceholderColorDefaultToggle.PlaceholderColor = Color.Default;
+ searchbarPlaceholderColorDefaultToggle.Placeholder = "Default Placeholder Color";
+ }
+ };
+
+ Title = "Test Color Toggle Page";
+
+ Content = new ScrollView () {
+ Content = new StackLayout {
+ Children = {
+ _buttonColorDefaultToggle,
+ _buttonColorInitted,
+ _labelColorDefaultToggle,
+ _labelColorInitted,
+ entryTextColorDefaultToggle,
+ entryToggleButton,
+ entryTextColorInit,
+ entryPlaceholderColorDefaultToggle,
+ entryPlaceholderToggleButton,
+ entryPlaceholderColorInit,
+ passwordColorDefaultToggle,
+ passwordToggleButton,
+ passwordColorInit,
+ searchbarTextColorDefaultToggle,
+ searchbarTextColorToggleButton,
+ searchbarPlaceholderColorDefaultToggle,
+ searchbarPlaceholderToggleButton
+ }
+ }
+ };
+ }
+
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/DisposedSharedPages.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/DisposedSharedPages.cs
new file mode 100644
index 00000000..ae996383
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/DisposedSharedPages.cs
@@ -0,0 +1,70 @@
+using System;
+
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Controls
+{
+ public class DisposePage : ContentPage
+ {
+ public event EventHandler RendererDisposed;
+
+ public void SendRendererDisposed ()
+ {
+ var handler = RendererDisposed;
+ if (handler != null)
+ handler (this, EventArgs.Empty);
+ }
+
+ public int DisposedLabelCount { get; private set; }
+
+ public Action PopAction { get; set; }
+ public DisposePage ()
+ {
+ var popButton = new Button {Text = "Pop"};
+ popButton.Clicked += (sender, args) => PopAction ();
+
+ var disposeLabel1 = new DisposeLabel {Text = "Label 1"};
+ var disposeLabel2 = new DisposeLabel {Text = "Label 2"};
+ var disposeLabel3 = new DisposeLabel {Text = "Label 3"};
+ var disposeLabel4 = new DisposeLabel {Text = "Label 4"};
+ var disposeLabel5 = new DisposeLabel {Text = "Label 5"};
+
+ EventHandler disposeHandler = (sender, args) => DisposedLabelCount++;
+ disposeLabel1.RendererDisposed += disposeHandler;
+ disposeLabel2.RendererDisposed += disposeHandler;
+ disposeLabel3.RendererDisposed += disposeHandler;
+ disposeLabel4.RendererDisposed += disposeHandler;
+ disposeLabel5.RendererDisposed += disposeHandler;
+
+ Content = new StackLayout {
+ Children = {
+ popButton,
+ disposeLabel1,
+ disposeLabel2,
+ disposeLabel3,
+ disposeLabel4,
+ new StackLayout {
+ Children = {
+ disposeLabel5,
+ }
+ }
+ }
+ };
+ }
+ }
+
+ public class DisposeLabel : Label
+ {
+ public event EventHandler RendererDisposed;
+
+ public void SendRendererDisposed ()
+ {
+ var handler = RendererDisposed;
+ if (handler != null)
+ handler (this, EventArgs.Empty);
+ }
+ }
+
+}
+
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/InputTransparentIssue.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/InputTransparentIssue.cs
new file mode 100644
index 00000000..c6c12a70
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/InputTransparentIssue.cs
@@ -0,0 +1,37 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls.Issues
+{
+
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 30000, "InputTransparentIssue")]
+ public class InputTransparentIssue : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var abs = new AbsoluteLayout();
+ var box = new BoxView { Color = Color.Red };
+ var label = new Label { BackgroundColor = Color.Green , InputTransparent = true };
+ abs.Children.Add(box, new Rectangle(0, 0, 1, 1), AbsoluteLayoutFlags.All);
+ abs.Children.Add(label, new Rectangle(0, 0, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize), AbsoluteLayoutFlags.PositionProportional);
+ label.Text = DateTime.Now.ToString();
+ box.GestureRecognizers.Add(new TapGestureRecognizer
+ {
+ Command = new Command(() =>
+ {
+ label.Text = DateTime.Now.ToString();
+ })
+ });
+ Image img = new Image { Source = ImageSource.FromFile("oasis.jpg"), InputTransparent = true };
+ abs.Children.Add(img, new Rectangle(.5, .5, .5, .5), AbsoluteLayoutFlags.All);
+ Content = abs ;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/IsPasswordToggleTest.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/IsPasswordToggleTest.cs
new file mode 100644
index 00000000..e3bcfb2d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/IsPasswordToggleTest.cs
@@ -0,0 +1,38 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.None, 0, "IsPassword toggle test", PlatformAffected.All)]
+ public class IsPasswordToggleTest : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var entry = new Entry {
+ Text = "Setec Astronomy",
+ FontFamily = "Comic Sans MS",
+ HorizontalTextAlignment = TextAlignment.Center,
+ Keyboard = Keyboard.Chat
+ };
+
+ var label = new Label ();
+ var binding = new Binding ("Text") { Source = entry };
+
+ var otherEntry = new Entry ();
+ var otherBinding = new Binding ("Text") { Source = entry, Mode = BindingMode.TwoWay };
+ otherEntry.SetBinding (Entry.TextProperty, otherBinding);
+
+ label.SetBinding (Label.TextProperty, binding);
+
+ var explanation = new Label() {Text = @"The Text value of the entry at the top should appear in the label and entry below, regardless of whether 'IsPassword' is on.
+Changes to the value in the entry below should be reflected in the entry at the top."};
+
+ var button = new Button { Text = "Toggle IsPassword" };
+ button.Clicked += (sender, args) => { entry.IsPassword = !entry.IsPassword; };
+
+ Content = new StackLayout {
+ Children = { entry, button, explanation, label, otherEntry }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/IsShowingUserIssue.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/IsShowingUserIssue.cs
new file mode 100644
index 00000000..6c0be388
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/IsShowingUserIssue.cs
@@ -0,0 +1,35 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Maps;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.None, 0, "IsShowingUser renderes as pin instead of dot")]
+ public class IsShowingUserIssue : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var map = new Map (MapSpan.FromCenterAndRadius (new Position(37.79, -122.4), Distance.FromMiles(2))) {
+ AutomationId = "FormsMap",
+ IsShowingUser = true
+ };
+
+ Content = map;
+ }
+
+#if UITEST
+ public void IsShowingUserIssueTest ()
+ {
+ RunningApp.Screenshot ("I should see a map");
+ Assert.Inconclusive ("Verify that user location is visible and a dot");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1025.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1025.cs
new file mode 100644
index 00000000..65b17e5d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1025.cs
@@ -0,0 +1,24 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1025, "StackLayout broken when image missing", PlatformAffected.iOS, NavigationBehavior.PushModalAsync)]
+ public class Issue1025 : ContentPage
+ {
+ public Issue1025 ()
+ {
+ BackgroundColor = Color.FromHex("#dae1eb");
+ Content = new StackLayout {
+ Orientation = StackOrientation.Vertical,
+ Children = {
+ new Image {},
+ new Label {Text = "Lorem ipsum dolor" },
+ new Label {Text = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."},
+ new Button {BackgroundColor = Color.FromHex ("#fec240"), Text = "Create an account" },
+ new Button {BackgroundColor = Color.FromHex ("#04acdb"), Text = "Login" },
+ }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1026.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1026.cs
new file mode 100644
index 00000000..58c2b646
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1026.cs
@@ -0,0 +1,91 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1026, "Label cropping", PlatformAffected.iOS | PlatformAffected.WinPhone, NavigationBehavior.PushModalAsync)]
+ public class Issue1026 : ContentPage
+ {
+ public Issue1026 ()
+ {
+ BackgroundColor = Color.FromHex("#dae1eb");
+ Content =
+ new ScrollView {
+ Content =
+ new StackLayout {
+ Padding = new Thickness (0, 18),
+ Spacing = 10,
+ Orientation = StackOrientation.Vertical,
+ Children = {
+ new Button {
+ BackgroundColor = Color.FromHex ("#006599"),
+ TextColor = Color.White,
+ Text = "Subscribe with LinkedIn",
+ WidthRequest = 262,
+ HorizontalOptions = LayoutOptions.Center,
+ BorderRadius = 0,
+ },
+// new Label {
+// Text = "or by email",
+// TextColor = Color.FromHex ("#666"),
+// XAlign = TextAlignment.Center,
+// Font = Font.SystemFontOfSize (NamedSize.Small),
+// WidthRequest = 262,
+// HorizontalOptions = LayoutOptions.Center,
+// },
+ new Entry {
+ Placeholder = "Professional email",
+ WidthRequest = 262,
+ HorizontalOptions = LayoutOptions.Center,
+ Keyboard = Keyboard.Email,
+ },
+ new Entry {
+ Placeholder = "Firstname",
+ WidthRequest = 262,
+ HorizontalOptions = LayoutOptions.Center,
+ },
+ new Entry {
+ Placeholder = "Lastname",
+ WidthRequest = 262,
+ HorizontalOptions = LayoutOptions.Center,
+ },
+ new Entry {
+ Placeholder = "Company",
+ WidthRequest = 262,
+ HorizontalOptions = LayoutOptions.Center,
+ },
+ new Entry {
+ Placeholder = "Password",
+ WidthRequest = 262,
+ IsPassword = true,
+ HorizontalOptions = LayoutOptions.Center,
+ },
+ new Entry {
+ Placeholder = "Confirm password",
+ WidthRequest = 262,
+ IsPassword = true,
+ HorizontalOptions = LayoutOptions.Center,
+ },
+ new Button {
+ BackgroundColor = Color.FromHex ("#05addc"),
+ TextColor = Color.White,
+ Text = "Create an account",
+ WidthRequest = 262,
+ HorizontalOptions = LayoutOptions.Center,
+ BorderRadius = 0,
+ },
+ new Label {
+ Text = "by subscribing, you accept the general conditions.",
+ TextColor = Color.White,
+ XAlign = TextAlignment.Center,
+ Font = Font.SystemFontOfSize (NamedSize.Micro),
+ WidthRequest = 262,
+ HorizontalOptions = LayoutOptions.Center,
+ },
+ },
+ },
+
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1028.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1028.cs
new file mode 100644
index 00000000..4ef26e78
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1028.cs
@@ -0,0 +1,31 @@
+using System.Diagnostics;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1028, "ViewCell in TableView raises exception - root page is ContentPage, Content is TableView" ,PlatformAffected.WinPhone, NavigationBehavior.PushModalAsync)]
+ public class Issue1028 : ContentPage
+ {
+ // Issue1028, ViewCell with StackLayout causes exception when nested in a table section. This occurs when the app's root page is a ContentPage with a TableView.
+ public Issue1028 ()
+ {
+ Content = new TableView {
+ Root = new TableRoot ("Table Title") {
+ new TableSection ("Section 1 Title") {
+ new ViewCell {
+ View = new StackLayout {
+ Children = {
+ new Label {
+ Text = "Custom Slider View:"
+ },
+ }
+ }
+ }
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1075.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1075.cs
new file mode 100644
index 00000000..54a8eb9a
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1075.cs
@@ -0,0 +1,85 @@
+using System.Diagnostics;
+using System.Reflection;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1075, "Does not update Color", PlatformAffected.Android | PlatformAffected.WinPhone)]
+ public class Issue1075 : ContentPage
+ {
+ // Issue1075
+ // BoxView doesn't update color
+ public Issue1075 ()
+ {
+ Label header = new Label
+ {
+ Text = "Picker",
+ Font = Font.BoldSystemFontOfSize(50),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ Picker picker = new Picker
+ {
+ Title = "Color",
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+
+ foreach (string color in new string[]
+ {
+ "Aqua", "Black", "Blue", "Fuschia",
+ "Gray", "Green", "Lime", "Maroon",
+ "Navy", "Olive", "Purple", "Red",
+ "Silver", "Teal", "White", "Yellow"
+ })
+ {
+ picker.Items.Add(color);
+ }
+
+ // Create BoxView for displaying pickedColor
+ BoxView boxView = new BoxView
+ {
+ WidthRequest = 150,
+ HeightRequest = 150,
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+
+ var button = new Button {
+ Text = "Change to blue",
+ Command = new Command (() => boxView.BackgroundColor = Color.Aqua)
+ };
+
+ picker.SelectedIndexChanged += (sender, args) =>
+ {
+ if (picker.SelectedIndex == -1)
+ {
+ boxView.Color = Color.Default;
+ }
+ else
+ {
+ string selectedItem = picker.Items[picker.SelectedIndex];
+ FieldInfo colorField = typeof(Color).GetTypeInfo().GetDeclaredField(selectedItem);
+ boxView.Color = (Color)colorField.GetValue(null);
+ }
+ };
+
+ // Accomodate iPhone status bar.
+ Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 0);
+
+ // Build the page.
+ Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ picker,
+ boxView,
+ button
+ }
+ };
+ }
+ }
+
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1097.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1097.cs
new file mode 100644
index 00000000..7b67e1e2
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1097.cs
@@ -0,0 +1,60 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1097, "Not resizing elements on rotation", PlatformAffected.iOS)]
+ public class Issue1097 : ContentPage
+ {
+ public Issue1097 ()
+ {
+ Grid grid = new Grid {
+ RowSpacing = 0,
+ ColumnSpacing = 0,
+ };
+
+ grid.AddRowDef(count: 2);
+ grid.AddColumnDef(count : 2);
+
+ grid.Children.Add(new BoxView() { Color = Color.Red });
+
+ var v2 = new BoxView { Color = Color.Blue };
+ Grid.SetColumn(v2, 1);
+ grid.Children.Add(v2);
+
+ var v3 = new BoxView { Color = Color.Green };
+ Grid.SetRow(v3, 1);
+ grid.Children.Add(v3);
+
+ var v4 = new BoxView { Color = Color.Purple };
+ Grid.SetRow(v4, 1);
+ Grid.SetColumn(v4, 1);
+ grid.Children.Add(v4);
+
+ Content = grid;
+ }
+ }
+ public static class GridExtensions
+ {
+ public static void AddRowDef(this Grid grid, double size = 1, GridUnitType type = GridUnitType.Star, int count = 1)
+ {
+ for (int i = 0; i < count; i++) {
+ grid.RowDefinitions.Add(new RowDefinition() {
+ Height = new GridLength(size, type)
+ });
+ }
+ }
+
+ public static void AddColumnDef(this Grid grid, double size = 1, GridUnitType type = GridUnitType.Star, int count = 1)
+ {
+ for (int i = 0; i < count; i++) {
+ grid.ColumnDefinitions.Add(new ColumnDefinition() {
+ Width = new GridLength(size, type)
+ });
+ }
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1146.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1146.cs
new file mode 100644
index 00000000..a3466229
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1146.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers=true)]
+ [Issue(IssueTracker.Github, 1146, "Disabled Switch in Button Gallery not rendering on all devices", PlatformAffected.Android)]
+ public class Issue1146 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Content = new ScrollView
+ {
+ Content = new StackLayout
+ {
+ Padding = new Size(20, 20),
+ Children = {
+ new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children= {
+ new Switch() { IsEnabled = false , AutomationId="switch"},
+ },
+ },
+ }
+ }
+ };
+ }
+
+#if UITEST
+ [Test]
+ public void TestSwitchDisable()
+ {
+ RunningApp.WaitForElement (c => c.Marked ("switch"));
+ RunningApp.Screenshot("Is the button here?");
+ }
+#endif
+
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1219.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1219.cs
new file mode 100644
index 00000000..078682a8
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1219.cs
@@ -0,0 +1,19 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1219, "Setting ToolbarItems in ContentPage constructor crashes app", PlatformAffected.iOS)]
+ public class Issue1219 : ContentPage
+ {
+ public Issue1219 ()
+ {
+ ToolbarItems.Add(new ToolbarItem ("MenuItem", "", () => {
+
+ }));
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1228.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1228.cs
new file mode 100644
index 00000000..70ba1a74
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1228.cs
@@ -0,0 +1,67 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1228, "ScrollView not auto scrolling with Editor", PlatformAffected.iOS)]
+ public class Issue1228 : ContentPage
+ {
+ public Issue1228 ()
+ {
+ var grd = new Grid ();
+
+ var layout = new StackLayout ();
+
+ var picker = new Picker { BackgroundColor = Color.Pink };
+ picker.Items.Add ("A");
+ picker.Items.Add ("B");
+ picker.Items.Add ("C");
+ picker.Items.Add ("D");
+ picker.Items.Add ("E");
+ layout.Children.Add (picker);
+
+ layout.Children.Add (new Editor { BackgroundColor = Color.Red, VerticalOptions = LayoutOptions.End });
+ layout.Children.Add (new Editor { BackgroundColor = Color.Red, VerticalOptions = LayoutOptions.End });
+ layout.Children.Add (new Editor { BackgroundColor = Color.Red, VerticalOptions = LayoutOptions.End });
+ layout.Children.Add (new Editor { BackgroundColor = Color.Red, VerticalOptions = LayoutOptions.End });
+ layout.Children.Add (new Editor { BackgroundColor = Color.Red, VerticalOptions = LayoutOptions.End });
+ layout.Children.Add (new Editor { BackgroundColor = Color.Red, VerticalOptions = LayoutOptions.End });
+
+ layout.Children.Add (new SearchBar {
+ BackgroundColor = Color.Gray,
+ CancelButtonColor = Color.Red
+ });
+
+ layout.Children.Add (new Editor { BackgroundColor = Color.Red, VerticalOptions = LayoutOptions.End });
+ layout.Children.Add (new Editor { BackgroundColor = Color.Red, VerticalOptions = LayoutOptions.End });
+ layout.Children.Add (new Editor { BackgroundColor = Color.Red, VerticalOptions = LayoutOptions.End });
+ layout.Children.Add (new Editor { BackgroundColor = Color.Red, VerticalOptions = LayoutOptions.End });
+ layout.Children.Add (new Editor { BackgroundColor = Color.Red, VerticalOptions = LayoutOptions.End });
+ layout.Children.Add (new Editor { BackgroundColor = Color.Red, VerticalOptions = LayoutOptions.End });
+ layout.Children.Add (new Editor { BackgroundColor = Color.Red, VerticalOptions = LayoutOptions.End });
+ layout.Children.Add (new Editor { BackgroundColor = Color.Red, VerticalOptions = LayoutOptions.End });
+
+ layout.Children.Add (new Entry { BackgroundColor = Color.Blue });
+ layout.Children.Add (new SearchBar {
+ BackgroundColor = Color.Gray,
+ CancelButtonColor = Color.Red
+ });
+ grd.Children.Add (layout);
+
+
+ Content = new ContentView {
+ Content = new ScrollView {
+ Padding = new Thickness (0, 20, 0, 0),
+ Orientation = ScrollOrientation.Vertical,
+ Content = grd,
+ HeightRequest = 400,
+ VerticalOptions = LayoutOptions.Start
+ },
+ BackgroundColor = Color.Lime,
+ HeightRequest = 400
+
+ };
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1236.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1236.cs
new file mode 100644
index 00000000..9737fdd6
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1236.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1236, "Label binding", PlatformAffected.iOS)]
+ public class Issue1236 : ContentPage
+ {
+ public Issue1236 ()
+ {
+ Content = new Label { HeightRequest = 30, WidthRequest = 200, BackgroundColor = Color.Purple.WithLuminosity (.7) };
+ Content.SetBinding (Label.TextProperty, ".");
+
+ DelayUpdatingBindingContext ();
+ }
+
+ async void DelayUpdatingBindingContext ()
+ {
+ await Task.Delay (2000);
+ BindingContext = "Lorem Ipsum Dolor Sit Amet";
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1259.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1259.cs
new file mode 100644
index 00000000..681308ff
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1259.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1259, "Layout issue with SwitchCell", PlatformAffected.Android)]
+ public class Issue1259
+ : ContentPage
+ {
+ TableView _table;
+ public Issue1259()
+ {
+ StackLayout st = new StackLayout();
+ st.HorizontalOptions = LayoutOptions.FillAndExpand;
+ st.VerticalOptions = LayoutOptions.FillAndExpand;
+
+ _table = new TableView
+ {
+ Intent = TableIntent.Form,
+ Root = new TableRoot("") {
+ new TableSection
+ {
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new SwitchCell
+ {
+ Text = "SwitchCell:"
+ },
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new SwitchCell
+ {
+ Text = "SwitchCell:"
+ },
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new TextCell(),
+ new SwitchCell
+ {
+ Text = "SwitchCell:"
+ }
+ }
+ }
+ };
+
+ st.Children.Add(_table);
+
+ Button next = new Button
+ {
+ Text = "Ok",
+ };
+ next.Clicked +=next_Clicked;
+
+ st.Children.Add(next);
+
+ Content = st;
+ }
+
+ void next_Clicked(object sender, EventArgs e)
+ {
+ var sw = _table.Root[0].OfType<SwitchCell>().First();
+ sw.On = !sw.On;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1267.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1267.cs
new file mode 100644
index 00000000..f194670d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1267.cs
@@ -0,0 +1,65 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ public class PersonCell:ViewCell
+ {
+ public PersonCell ()
+ {
+ var grid = new Grid{
+ RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition {Height = new GridLength (1, GridUnitType.Star)},
+ new RowDefinition {Height = GridLength.Auto},
+ },
+ ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition {Width = new GridLength (1, GridUnitType.Star)},
+ new ColumnDefinition {Width = GridLength.Auto},
+ }
+ };
+ Label label;
+ grid.Children.Add (label = new Label {BackgroundColor = Color.Lime});
+ label.SetBinding (Label.TextProperty, "FirstName");
+
+ grid.Children.Add (label = new Label (),0,1);
+ label.SetBinding (Label.TextProperty, "LastName");
+
+ grid.Children.Add (label = new Label {XAlign = TextAlignment.End},1,0);
+ label.SetBinding (Label.TextProperty, "Zip");
+
+ grid.Children.Add (label = new Label {XAlign = TextAlignment.End},1,1);
+ label.SetBinding (Label.TextProperty, "City");
+ View = grid;
+
+
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1267, "Star '*' in Grid layout throws exception", PlatformAffected.WinPhone)]
+ public class Issue1267 : ContentPage
+ {
+ public Issue1267 ()
+ {
+ var lv = new ListView {
+ ItemsSource = new []{
+ new {FirstName = "foo", LastName="bar", Zip="1234", City="Gotham City"},
+ new {FirstName = "foo", LastName="bar", Zip="1234", City="Gotham City"},
+ new {FirstName = "foo", LastName="bar", Zip="1234", City="Gotham City"},
+ new {FirstName = "foo", LastName="bar", Zip="1234", City="Gotham City"},
+ new {FirstName = "foo", LastName="bar", Zip="1234", City="Gotham City"},
+ new {FirstName = "foo", LastName="bar", Zip="1234", City="Gotham City"},
+ new {FirstName = "foo", LastName="bar", Zip="1234", City="Gotham City"},
+ new {FirstName = "foo", LastName="bar", Zip="1234", City="Gotham City"},
+ new {FirstName = "foo", LastName="bar", Zip="1234", City="Gotham City"},
+ new {FirstName = "foo", LastName="bar", Zip="1234", City="Gotham City"},
+ new {FirstName = "foo", LastName="bar", Zip="1234", City="Gotham City"},
+ new {FirstName = "foo", LastName="bar", Zip="1234", City="Gotham City"},
+ new {FirstName = "foo", LastName="bar", Zip="1234", City="Gotham City"},
+ },
+ ItemTemplate = new DataTemplate (typeof(PersonCell)),
+ };
+ Content = lv;
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1305.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1305.cs
new file mode 100644
index 00000000..b1c38b10
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1305.cs
@@ -0,0 +1,50 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1305, "ToolbarItems on NavigationPage broken", PlatformAffected.Android, NavigationBehavior.PushModalAsync)]
+ public class Issue1305 : ContentPage
+ {
+ public Issue1305 ()
+ {
+ var settings = new ToolbarItem
+ {
+ Icon = "bank.png",
+ Text = "Settings",
+ Command = new Command(ShowSettingsPage),
+ };
+
+ ToolbarItems.Add(settings);
+
+ Content = new ContentView { Content = new Label { Text = "Testing..." } };
+
+ Title = "Test Page";
+
+ Icon = "Icon.png";
+
+ }
+
+ async void ShowSettingsPage()
+ {
+ await Navigation.PushAsync(new Issue13052());
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1305, "ToolbarItems on NavigationPage broken", PlatformAffected.Android)]
+ public class Issue13052 : ContentPage
+ {
+ public Issue13052 ()
+ {
+ Content = new ContentView { Content = new Label { Text = "Settings..." } };
+
+ Title = "Settings";
+
+ Icon = "bank.png";
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1329.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1329.cs
new file mode 100644
index 00000000..b9d133e1
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1329.cs
@@ -0,0 +1,46 @@
+
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1329, "Losing root page with rapidly pushing and popping", PlatformAffected.Android)]
+ public class Issue1329 : NavigationPage
+ {
+ public Issue1329 () : base (GetPage ("root page"))
+ {
+ var navigation = new NavigationPage (GetPage ("root page"));
+ var pageNum = 0;
+
+ MessagingCenter.Subscribe<Button> (
+ navigation,
+ "PushPage",
+ (sender) => navigation.PushAsync (GetPage ("Page #: " + ++pageNum))
+ );
+
+ navigation.Popped += (sender, e) => {
+ pageNum -= 1;
+ };
+ }
+
+ public static Page GetPage (string name) {
+
+ var button = new Button {
+ Text = name
+ };
+
+ button.Clicked += (sender, e) => MessagingCenter.Send<Button> ((Button)sender, "PushPage");
+
+ var page = new ContentPage {
+ Content = button
+ };
+
+ return page;
+ }
+
+ }
+
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1384.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1384.cs
new file mode 100644
index 00000000..0bf8aeab
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1384.cs
@@ -0,0 +1,40 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1384, "Image is grid issue", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone)]
+ public class Issue1384:ContentPage
+ {
+ public Issue1384 ()
+ {
+ var grid = new Grid {BackgroundColor = Color.Red, VerticalOptions=LayoutOptions.Start};
+ grid.Children.Add (new Image {Source = "photo.jpg", Aspect = Aspect.AspectFit});
+ grid.Children.Add (new Label {
+ Opacity =.75,
+ YAlign = TextAlignment.Start,
+ XAlign = TextAlignment.End,
+ Text ="top and flush right",
+ Font = Font.SystemFontOfSize (NamedSize.Large),
+ VerticalOptions=LayoutOptions.Start,
+ HorizontalOptions=LayoutOptions.End,
+ HeightRequest=30,
+ TextColor = Color.White
+ });
+ grid.Children.Add (new Label {
+ Opacity =.75,
+ YAlign = TextAlignment.End,
+ Text ="bottom and flush left",
+ Font = Font.SystemFontOfSize (NamedSize.Large),
+ VerticalOptions=LayoutOptions.End,
+ HeightRequest=40,
+ TextColor = Color.White,
+ BackgroundColor = Color.Green,
+ });
+ Content = grid;
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1400.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1400.cs
new file mode 100644
index 00000000..b8e4a8ce
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1400.cs
@@ -0,0 +1,153 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1400, "Group binding errors", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone, NavigationBehavior.PushModalAsync)]
+ public class Issue1400 : ContentPage
+ {
+ public static Entry Editfield { get; set; }
+ public static ListView List { get; set; }
+ public static List<MyGroup> Data { get; set; }
+ public Issue1400 ()
+ {
+ Data = new List<MyGroup>();
+ Data.Add(new MyGroup(){Headertitle = "Header 1"});
+ Data.First().Add(new MyData(){Title = "title 1"});
+ Data.First().Add(new MyData() { Title = "title 2" });
+ Data.Add(new MyGroup() { Headertitle = "Header 2" });
+ Data.Last().Add(new MyData() { Title = "title 2a" });
+ Data.Last().Add(new MyData() { Title = "title 2b" });
+
+
+ Editfield = new Entry();
+ Editfield.HorizontalOptions = LayoutOptions.FillAndExpand;
+ Editfield.BindingContext = Data.First().First();
+ Editfield.SetBinding<MyData>(Entry.TextProperty, f => f.Title);
+
+ Editfield.TextChanged += (sender, args) =>
+ {
+
+ AddCell(null);
+ };
+
+ List = new ListView();
+ List.HorizontalOptions = LayoutOptions.FillAndExpand;
+ List.VerticalOptions = LayoutOptions.FillAndExpand;
+ List.BackgroundColor = Color.Yellow;
+ List.ItemTemplate = new DataTemplate(typeof (VCTest));
+ List.GroupHeaderTemplate = new DataTemplate(typeof(VCHeader));
+ List.IsGroupingEnabled = true;
+ List.ItemsSource = Data;
+
+
+
+ Content = new StackLayout () {
+ VerticalOptions = LayoutOptions.StartAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Children = { Editfield, List },
+ Padding = new Thickness (10, 10, 10, 10)
+
+ };
+ }
+
+ public static List<MyGroup> CopyList(List<MyGroup> data)
+ {
+ var newlist = new List<MyGroup>();
+ foreach (var grp in data)
+ {
+ var grpItem = new MyGroup() { Headertitle = grp.Headertitle };
+ foreach (var subItem in grp)
+ {
+ var item = new MyData() { Title = subItem.Title };
+ grpItem.Add(item);
+ }
+ newlist.Add(grpItem);
+ }
+ return newlist;
+ }
+
+ public static void AddCell(MyData data)
+ {
+ var newlist = CopyList(Data);
+
+ // just make some changes
+ newlist.Last().Add(new MyData() { Title = Editfield.Text });
+ newlist.Last().RemoveAt(0);
+ newlist.Last().Add(new MyData() { Title = "2nd "+Editfield.Text });
+
+ Data = newlist;
+
+ List.ItemsSource = newlist;
+ }
+ }
+
+ public class MyData : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ string _title;
+
+ public const string PropTitle = "Title";
+
+ public string Title
+ {
+ get { return _title; }
+ set
+ {
+ if (value.Equals(_title, StringComparison.Ordinal)) return;
+ _title = value;
+ OnPropertyChanged(new PropertyChangedEventArgs(PropTitle));
+ }
+ }
+
+ public void OnPropertyChanged(PropertyChangedEventArgs e)
+ {
+ if (PropertyChanged != null) PropertyChanged(this, e);
+ }
+ }
+
+ public class MyGroup : ObservableCollection<MyData>, INotifyPropertyChanged
+ {
+ string _headertitle;
+
+ public const string PropHeadertitle = "Headertitle";
+
+ public string Headertitle
+ {
+ get { return _headertitle; }
+ set
+ {
+ if (value.Equals(_headertitle, StringComparison.Ordinal)) return;
+ _headertitle = value;
+ OnPropertyChanged( new PropertyChangedEventArgs(PropHeadertitle));
+ }
+ }
+ }
+
+ internal class VCTest : ViewCell
+ {
+ public VCTest()
+ {
+ var label = new Label();
+ label.SetBinding<MyData>(Label.TextProperty, f => f.Title);
+ View = label;
+ }
+ }
+
+ internal class VCHeader : ViewCell
+ {
+ public VCHeader()
+ {
+ var label = new Label();
+ label.SetBinding<MyGroup>(Label.TextProperty, f => f.Headertitle);
+ View = label;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1461.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1461.cs
new file mode 100644
index 00000000..2ad70257
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1461.cs
@@ -0,0 +1,286 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+using Xamarin.UITest.iOS;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+
+#if UITEST
+ public static class Issue1461Helpers
+ {
+ public static bool ShouldRunTest (IApp app)
+ {
+ var appAs = app as iOSApp;
+ return (appAs != null && appAs.Device.IsTablet);
+ }
+ }
+#endif
+
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1461, "1461 - (Popover in Portrait and Landscape)", PlatformAffected.iOS)]
+ public class Issue1461 : TestContentPage
+ {
+ protected override async void Init ()
+ {
+ await Navigation.PushModalAsync (new Issue1461Page (MasterBehavior.Popover, false));
+ }
+
+#if UITEST
+ [Test]
+ [UiTest (typeof (MasterDetailPage), "IsPresented")]
+ [UiTest (typeof (MasterDetailPage), "Master")]
+ public void Test1 ()
+ {
+ if (Issue1461Helpers.ShouldRunTest (RunningApp)) {
+ RunningApp.SetOrientationLandscape ();
+ var query = RunningApp.Query (q => q.Marked ("Master_Label"));
+ Assert.IsTrue (!query.Any (), "Master should not present");
+ RunningApp.Screenshot ("Master should not present");
+ RunningApp.SetOrientationPortrait ();
+ query = RunningApp.Query (q => q.Marked ("Master_Label"));
+ Assert.IsTrue (!query.Any (), "Master should not present");
+ RunningApp.Screenshot ("Master should not present");
+ RunningApp.Tap (q => q.Marked ("Go Back"));
+ } else {
+ Assert.Inconclusive ("Only run on iOS Tablet");
+ }
+ }
+#endif
+ }
+
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1461, "1461 - Default", PlatformAffected.iOS)]
+ public class Issue1461A : TestContentPage
+ {
+ protected override async void Init ()
+ {
+ await Navigation.PushModalAsync (new Issue1461Page (MasterBehavior.Default, null));
+ }
+
+#if UITEST
+ [Test]
+ [UiTest (typeof (MasterDetailPage), "IsPresented")]
+ [UiTest (typeof (MasterDetailPage), "Master")]
+ public void Test2 ()
+ {
+ if (Issue1461Helpers.ShouldRunTest(RunningApp)) {
+ RunningApp.SetOrientationLandscape ();
+ var query = RunningApp.Query (q => q.Marked ("Master_Label"));
+ Assert.IsTrue (query.Any (), "Master should be present");
+ RunningApp.Screenshot ("Master should not present");
+ RunningApp.SetOrientationPortrait ();
+ query = RunningApp.Query (q => q.Marked ("Master_Label"));
+ Assert.IsTrue (!query.Any (), "Master should not present");
+ RunningApp.Screenshot ("Master should not present");
+ RunningApp.Tap (q => q.Marked ("Go Back"));
+ } else {
+ Assert.Inconclusive ("Only run on iOS Tablet");
+ }
+ }
+
+ #if UITEST
+ [Test]
+ [UiTest (typeof (MasterDetailPage), "Button")]
+ public void TestButton ()
+ {
+ if (Issue1461Helpers.ShouldRunTest(RunningApp)) {
+ RunningApp.SetOrientationLandscape ();
+ RunningApp.WaitForNoElement (q => q.Marked ("bank"));
+ RunningApp.SetOrientationPortrait ();
+ RunningApp.WaitForElement (q => q.Marked ("bank"));
+ } else {
+ Assert.Inconclusive ("Only run on iOS Tablet");
+ }
+ }
+ #endif
+#endif
+ }
+
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1461, "1461 - (Splitview in Landscape)", PlatformAffected.iOS)]
+ public class Issue1461B : TestContentPage
+ {
+ protected override async void Init ()
+ {
+ await Navigation.PushModalAsync (new Issue1461Page (MasterBehavior.SplitOnLandscape, null));
+ }
+
+#if UITEST
+ [Test]
+ [UiTest (typeof (MasterDetailPage), "IsPresented")]
+ [UiTest (typeof (MasterDetailPage), "Master")]
+ public void Test3 ()
+ {
+ if (Issue1461Helpers.ShouldRunTest(RunningApp)) {
+ RunningApp.SetOrientationLandscape ();
+ var query = RunningApp.Query (q => q.Marked ("Master_Label"));
+ Assert.IsTrue (query.Any (), "Master should be present");
+ RunningApp.Screenshot ("Master should not present");
+ RunningApp.SetOrientationPortrait ();
+ query = RunningApp.Query (q => q.Marked ("Master_Label"));
+ Assert.IsTrue (!query.Any (), "Master should not present");
+ RunningApp.Screenshot ("Master should not present");
+ RunningApp.Tap (q => q.Marked ("Go Back"));
+ } else {
+ Assert.Inconclusive ("Only run on iOS Tablet");
+ }
+ }
+#endif
+ }
+
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1461, "1461 - (Splitview in Portrait)", PlatformAffected.iOS)]
+ public class Issue1461C : TestContentPage
+ {
+ protected override async void Init ()
+ {
+ await Navigation.PushModalAsync (new Issue1461Page (MasterBehavior.SplitOnPortrait, null));
+ }
+
+#if UITEST
+ [Test]
+ [UiTest (typeof (MasterDetailPage), "IsPresented")]
+ [UiTest (typeof (MasterDetailPage), "Master")]
+ public void Test4 ()
+ {
+ if (Issue1461Helpers.ShouldRunTest(RunningApp)) {
+ RunningApp.SetOrientationPortrait ();
+ var s = RunningApp.Query (q => q.Marked ("Master_Label"));
+ Assert.IsTrue (s.Any (), "Master should be present");
+ RunningApp.Screenshot ("Master should present");
+
+ RunningApp.SetOrientationLandscape ();
+ s = RunningApp.Query (q => q.Marked ("Master_Label"));
+ Assert.IsTrue (!s.Any (), "Master should not present on landscape");
+ RunningApp.Screenshot ("Master should not present");
+ RunningApp.Tap (q => q.Marked ("Go Back"));
+ } else {
+ Assert.Inconclusive ("Only run on iOS Tablet");
+ }
+ }
+#endif
+ }
+
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1461, "1461 - (Splitview in Portrait and Landscape)", PlatformAffected.iOS)]
+ public class Issue1461D : TestContentPage
+ {
+ protected override async void Init ()
+ {
+ await Navigation.PushModalAsync (new Issue1461Page (MasterBehavior.Split, null));
+ }
+
+#if UITEST
+ [Test]
+ [UiTest (typeof (MasterDetailPage), "IsPresented")]
+ [UiTest (typeof (MasterDetailPage), "Master")]
+ public void Test5 ()
+ {
+ if (Issue1461Helpers.ShouldRunTest(RunningApp)) {
+ RunningApp.SetOrientationPortrait ();
+ var s = RunningApp.Query (q => q.Marked ("Master_Label"));
+ Assert.IsTrue (s.Any (), "Master should be present");
+ RunningApp.Screenshot ("Master should be present");
+
+ RunningApp.SetOrientationLandscape ();
+ s = RunningApp.Query (q => q.Marked ("Master_Label"));
+
+ Assert.IsTrue (s.Any (), "Master should be present");
+ RunningApp.Screenshot ("Master should be present");
+ RunningApp.Tap (q => q.Marked ("Go Back"));
+ } else {
+ Assert.Inconclusive ("Only run on iOS Tablet");
+ }
+ }
+#endif
+ }
+
+ internal sealed class Issue1461Page : MasterDetailPage
+ {
+ public Issue1461Page ()
+ : this (MasterBehavior.Default,null)
+ { }
+
+ bool? _showButton;
+ public Issue1461Page (MasterBehavior state, bool? initState)
+ {
+
+ var btn = new Button { Text = "hide me" };
+ btn.Clicked += bnToggle_Clicked;
+ Master = new ContentPage {
+ Title = string.Format ("Master sample for {0}", state),
+ Icon = "bank.png",
+ Padding = Device.OnPlatform (new Thickness (5, 60, 5, 5), 5, 5),
+ Content =
+ new StackLayout { Children = {
+ new Label {
+ Text = "Master Label",
+ AutomationId = "Master_Label",
+ BackgroundColor = Color.Gray
+ },
+ btn
+ }
+ },
+ //BackgroundColor = Color.Red
+ };
+
+ if(initState.HasValue)
+ _showButton = initState.Value;
+
+ var lbl = new Label {
+ HorizontalOptions = LayoutOptions.End,
+ BindingContext = this
+ };
+ lbl.SetBinding (Label.TextProperty, "IsPresented");
+
+ var bnToggle = new Button {
+ Text = "Toggle IsPresented",
+ };
+
+ var bnGoBack = new Button {
+ Text = "Go Back",
+ };
+
+ bnGoBack.Clicked += bnGoBack_Clicked;
+ bnToggle.Clicked += bnToggle_Clicked;
+
+ Detail = new NavigationPage( new ContentPage {
+ Title = "Detail Title",
+ Content = new StackLayout{ Spacing=10, Children= { lbl, bnToggle, bnGoBack} }
+ });
+
+ MasterBehavior = state;
+ }
+
+ public override bool ShouldShowToolbarButton ()
+ {
+ if (_showButton.HasValue)
+ return _showButton.Value;
+ return base.ShouldShowToolbarButton ();
+ }
+
+ async void bnGoBack_Clicked (object sender, EventArgs e)
+ {
+ await Navigation.PopModalAsync ();
+ }
+
+ async void bnToggle_Clicked (object sender, EventArgs e)
+ {
+ try {
+ IsPresented = !IsPresented;
+ } catch (InvalidOperationException ex) {
+ DisplayAlert ("Error", ex.Message, "ok");
+ }
+
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1497.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1497.xaml
new file mode 100644
index 00000000..e7569ed4
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1497.xaml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Forms.Controls.Issue1497">
+ <ContentView
+ Grid.Column="0" Grid.Row="0"
+ VerticalOptions="FillAndExpand"
+ HorizontalOptions="FillAndExpand"
+ BackgroundColor="Silver" Padding="5">
+
+ <Grid x:Name="grid" Grid.Column="0" Grid.Row="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" BackgroundColor="Green">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+ <Label Text="Messages" TextColor="White" HorizontalOptions="FillAndExpand" />
+ <Button
+ Text="GO"
+ TextColor="White"
+ BackgroundColor="Black"
+ Grid.Row="1"
+ HorizontalOptions="FillAndExpand"
+ VerticalOptions="EndAndExpand" />
+ </Grid>
+ </ContentView>
+</ContentPage>
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1497.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1497.xaml.cs
new file mode 100644
index 00000000..186a8b2d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1497.xaml.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1497, "Grid sizing issue", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone)]
+ public partial class Issue1497 : ContentPage
+ {
+ public Issue1497 ()
+ {
+ InitializeComponent ();
+ }
+ }
+#endif
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1538.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1538.cs
new file mode 100644
index 00000000..0497c519
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1538.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1538, "Crash measuring empty ScrollView", PlatformAffected.Android | PlatformAffected.WinPhone)]
+ public class Issue1538 : ContentPage
+ {
+ ScrollView _sv;
+ public Issue1538 ()
+ {
+ StackLayout sl = new StackLayout(){VerticalOptions = LayoutOptions.FillAndExpand};
+ sl.Children.Add( _sv = new ScrollView(){HeightRequest=100} );
+ Content = sl;
+
+ AddContentDelayed ();
+ }
+
+ async void AddContentDelayed ()
+ {
+ await Task.Delay (1000);
+ _sv.Content = new Label { Text = "Foo" };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1545.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1545.xaml
new file mode 100644
index 00000000..7cfb67ca
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1545.xaml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issue1545"
+ Title="{Binding Title}">
+ <StackLayout>
+ <ActivityIndicator IsVisible="{Binding IsBusy}" IsRunning="{Binding IsBusy}"/>
+ <ListView x:Name="List" ItemsSource="{Binding Artists}">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ImageCell Text="{Binding Name}" ImageSource="{Binding MediumImage}"/>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1545.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1545.xaml.cs
new file mode 100644
index 00000000..b00ced62
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1545.xaml.cs
@@ -0,0 +1,129 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1545, "Binding instances cannot be reused", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone)]
+ public partial class Issue1545 : ContentPage
+ {
+ ArtistsViewModel _viewModel;
+ public Issue1545()
+ {
+ InitializeComponent();
+ BindingContext = _viewModel = new ArtistsViewModel();
+ }
+
+ protected override void OnAppearing()
+ {
+ base.OnAppearing();
+ if (_viewModel.IsInitialized)
+ return;
+
+ _viewModel.IsInitialized = true;
+ _viewModel.LoadCommand.Execute(null);
+ }
+ }
+
+ public class BaseViewModel : INotifyPropertyChanged
+ {
+ public string Title { get; set; }
+ public bool IsInitialized { get; set; }
+
+ bool _isBusy;
+
+ /// <summary>
+ /// Gets or sets if VM is busy working
+ /// </summary>
+ public bool IsBusy
+ {
+ get { return _isBusy; }
+ set { _isBusy = value; OnPropertyChanged("IsBusy"); }
+ }
+
+ //INotifyPropertyChanged Implementation
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected void OnPropertyChanged(string propertyName)
+ {
+ if (PropertyChanged == null)
+ return;
+
+ PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+
+ public class ArtistsViewModel : BaseViewModel
+ {
+ public ArtistsViewModel()
+ {
+ Title = "Artists";
+ Artists = new ObservableCollection<Artist>();
+ }
+
+ /// <summary>
+ /// gets or sets the feed items
+ /// </summary>
+ public ObservableCollection<Artist> Artists
+ {
+ get;
+ private set;
+ }
+
+ Command _loadCommand;
+ /// <summary>
+ /// Command to load/refresh artitists
+ /// </summary>
+ public Command LoadCommand
+ {
+ get { return _loadCommand ?? (_loadCommand = new Command(async () => await ExecuteLoadCommand())); }
+ }
+
+ static readonly Artist[] ArtistsToLoad = new Artist[] {
+ new Artist { Name = "Metallica", ListenerCount = "100", PlayCount = "5000" },
+ new Artist { Name = "Epica", ListenerCount = "50", PlayCount = "1000" }
+ };
+
+ async Task ExecuteLoadCommand()
+ {
+ if (IsBusy)
+ return;
+
+ IsBusy = true;
+
+ Artists.Clear();
+
+ await Task.Delay (3000);
+
+ foreach (Artist a in ArtistsToLoad)
+ Artists.Add (a);
+
+ IsBusy = false;
+ }
+ }
+
+ public class Artist
+ {
+
+ public string Name { get; set; }
+
+ public string PlayCount { get; set; }
+
+ public string ListenerCount { get; set; }
+
+ public string Mbid { get; set; }
+
+ public string Url { get; set; }
+
+ public string Streamable { get; set; }
+ }
+#endif
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1546.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1546.cs
new file mode 100644
index 00000000..8e3fa1c0
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1546.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1546, "Crash when Label.Text is null", PlatformAffected.Android)]
+ public class Issue1546
+ : ContentPage
+ {
+ public Issue1546()
+ {
+ Content = new Label();
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1549.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1549.xaml
new file mode 100644
index 00000000..16f3945d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1549.xaml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<local:BaseView
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issue1549"
+ xmlns:local="clr-namespace:Xamarin.Forms.Controls;assembly=Xamarin.Forms.Controls"
+ Padding="0,40,0,0">
+ <local:BaseView.Resources>
+ <ResourceDictionary>
+ <local:InvertBoolenConverter x:Key="cnvInvert"></local:InvertBoolenConverter>
+ </ResourceDictionary>
+ </local:BaseView.Resources>
+ <local:BaseView.Content>
+ <ListView x:Name="lst" VerticalOptions="FillAndExpand"
+ HorizontalOptions="FillAndExpand"
+
+ ItemsSource="{Binding Items}"
+
+ >
+ <ListView.ItemTemplate >
+ <DataTemplate>
+ <ViewCell >
+ <ViewCell.View>
+ <Grid VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" >
+ <Label IsVisible="{Binding IsLocked}" Text="Show Is Locked" />
+ <Label IsVisible="{Binding IsLocked, Converter={StaticResource cnvInvert}}" Text="Show Is Not locked" />
+ </Grid>
+ </ViewCell.View>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </local:BaseView.Content>
+</local:BaseView> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1549.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1549.xaml.cs
new file mode 100644
index 00000000..850201de
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1549.xaml.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms;
+using System.Collections.ObjectModel;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ public class BaseView : ContentPage
+ {
+ public BaseView()
+ {
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1549, "XAML converters not invoked", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone)]
+ public partial class Issue1549 : BaseView
+ {
+ public Issue1549 ()
+ {
+ InitializeComponent ();
+
+ Items = new ObservableCollection<Issue1549Item> ();
+ Items.Add (new Issue1549Item () { IsLocked = true });
+ Items.Add (new Issue1549Item () { IsLocked = true });
+ Items.Add (new Issue1549Item () { IsLocked = true });
+ Items.Add (new Issue1549Item () { IsLocked = true });
+ lst.BindingContext = this;
+ }
+
+ public new ObservableCollection<Issue1549Item> Items {
+ get;
+ set;
+ }
+ }
+
+ public class InvertBoolenConverter : IValueConverter
+ {
+
+ #region IValueConverter implementation
+
+ public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if (value is bool) {
+
+ return !(bool)value;
+ }
+ return value;
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException ();
+ }
+
+ #endregion
+ }
+
+
+ public class Issue1549Item
+ {
+
+ public bool IsLocked {
+ get;
+ set;
+ }
+
+ }
+#endif
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1554.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1554.xaml
new file mode 100644
index 00000000..9db3fa42
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1554.xaml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issue1554">
+ <ListView ItemsSource="{Binding Values}">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <ViewCell.View>
+ <StackLayout>
+ <Label Text="{Binding}"></Label>
+ <Label Text="{Binding}"></Label>
+<!-- <ContentView></ContentView>-->
+ </StackLayout>
+ </ViewCell.View>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+</ContentPage>
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1554.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1554.xaml.cs
new file mode 100644
index 00000000..0a0c20cb
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1554.xaml.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1554, "NRE: NavigationProxy.set_Inner", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone)]
+ public partial class Issue1554 : ContentPage
+ {
+ public Issue1554 ()
+ {
+ BindingContext = new
+ {
+ Values = new[] { "ABC", "DEF", "GHI" }
+ };
+
+ InitializeComponent ();
+ }
+ }
+#endif
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1557.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1557.cs
new file mode 100644
index 00000000..7dc92cc6
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1557.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1557, "Setting source crashes if view was detached from visual tree", PlatformAffected.iOS)]
+ public class Issue1557
+ : ContentPage
+ {
+ ObservableCollection<string> _items = new ObservableCollection<string> { "foo", "bar" };
+ public Issue1557()
+ {
+ Content = new ListView {
+ ItemsSource = _items
+ };
+
+ Task.Delay (3000).ContinueWith (async t => {
+ var list = (ListView) Content;
+
+ await Navigation.PopAsync();
+
+ list.ItemsSource = new List<string>() { "test" };
+
+ }, TaskScheduler.FromCurrentSynchronizationContext());
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1566.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1566.cs
new file mode 100644
index 00000000..223edb6d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1566.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1566, "ListView reuse issue", PlatformAffected.Android)]
+ public class Issue1566
+ : ContentPage
+ {
+ bool _flag = true;
+
+ ObservableCollection<Tuple<string, string>> _collection = new ObservableCollection<Tuple<string, string>>();
+
+ void FillTheList()
+ {
+ _collection.Clear();
+
+ for (int i = 0; i < 100; i++)
+ {
+ var item = new Tuple<string, string>(
+ string.Format("{0} {0} {0} {0} {0} {0}", _flag ? i : 100-i),
+ string.Format("---- i ----{0} {0} {0} {0} {0} {0}", _flag ? i : 100-i)
+ );
+
+
+ _collection.Add(item);
+ }
+
+ //flag = !flag;
+ }
+
+ public Issue1566()
+ {
+ SearchBar search = new SearchBar();
+ search.SearchButtonPressed += (sender, e) => FillTheList();
+
+ ListView list = new ListView() {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HasUnevenRows = true,
+ ItemsSource = _collection,
+ ItemTemplate = new DataTemplate(typeof(CellTemplate))
+ };
+
+ Label info = new Label() {
+ Text = "Type something into searchbox and press search. Then swipe the list. Rows are mixed. It's important to have keyboard visible!!!"
+ };
+
+ StackLayout root = new StackLayout() {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Children =
+ {
+ search,
+ list,
+ info,
+ }
+ };
+
+ Content = root;
+ }
+
+ class CellTemplate : ViewCell
+ {
+ public CellTemplate()
+ {
+ Label cellLabel = new Label() {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ };
+
+ cellLabel.SetBinding(Label.TextProperty, new Binding("Item1", BindingMode.OneWay));
+
+ StackLayout root = new StackLayout() {
+ Children =
+ {
+ cellLabel
+ }
+ };
+
+ View = root;
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1567.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1567.cs
new file mode 100644
index 00000000..0b67d092
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1567.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1567, "NRE in NavigationProxy.set_Inner", PlatformAffected.iOS)]
+ public class Issue1567
+ : ContentPage
+ {
+ public Issue1567()
+ {
+ Title = "Test";
+ var label = new Label { Text = "Whatever" };
+
+ ToolbarItems.Add (new ToolbarItem ("Modal", null, async () => {
+ var cp2 = new ContentPage () {
+ Title = "Modal",
+ Content = new Label (){ Text = "Second screen" },
+ };
+ var np2 = new NavigationPage(cp2) { Title = "Modal" };
+ try {
+ await Navigation.PushModalAsync (cp2);
+ } catch (InvalidOperationException ex) {
+ label.Text = "Exception properly thrown: " + ex.Message;
+ }
+ }));
+
+ Content = label;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1568.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1568.xaml
new file mode 100644
index 00000000..00a5a08e
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1568.xaml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.TestCasesPages.Issue1568">
+ <StackLayout Orientation="Vertical">
+ <StackLayout
+ x:Name="_stackToolbar"
+ Orientation="Horizontal">
+ <Button
+ x:Name="_btnExit"
+ Text="&lt; Exit"
+ Command="{Binding ExitCommand}" />
+ <Button
+ x:Name="_btnSelectOrg"
+ Text="Select Org"
+ Command="{Binding SelectOrgCommand}" />
+ <Button
+ x:Name="_btnSelectStartInterval"
+ Text="Select Start Date"
+ Command="{Binding SelectStartIntervalCommand}" />
+ <Button
+ x:Name="_btnReload"
+ Text="Reload Schedule"
+ Command="{Binding ReloadScheduleCommand}" />
+ <Button
+ x:Name="_btnSave"
+ Text="Save Schedule"
+ Command="{Binding SaveScheduleCommand}" />
+ </StackLayout>
+
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="Auto" />
+ </Grid.ColumnDefinitions>
+
+ <BoxView
+ x:Name="_scheduleGrid"
+ Grid.Column="0"
+ Color="Red"
+ HorizontalOptions="Fill"
+ VerticalOptions="Fill" />
+
+ <BoxView
+ x:Name="_shiftEditor"
+ Grid.Column="1"
+ Color="Blue"
+ WidthRequest="300"
+ HorizontalOptions="Fill"
+ VerticalOptions="Fill" />
+ </Grid>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1568.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1568.xaml.cs
new file mode 100644
index 00000000..6dce5c68
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1568.xaml.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1568, "StackLayout, Grid issue", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone)]
+ public partial class Issue1568 : ContentPage
+ {
+ public Issue1568 ()
+ {
+ InitializeComponent ();
+ }
+ }
+#endif
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1583.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1583.cs
new file mode 100644
index 00000000..f150d46d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1583.cs
@@ -0,0 +1,20 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1583, "NavigationPage.TitleIcon broken", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone)]
+ public class Issue1583 : ContentPage
+ {
+ public Issue1583 ()
+ {
+ Title = "Test";
+ BackgroundColor = Color.Pink;
+ Content = new Label{Text = "Hello"};
+ NavigationPage.SetTitleIcon(this, "bank.png");
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1590.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1590.cs
new file mode 100644
index 00000000..2e1c70c7
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1590.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1590, "ListView.IsGroupingEnabled results ins ArguementOutOfRangeException", PlatformAffected.Android)]
+ public class Issue1590 : ContentPage
+ {
+ ListView _listView;
+
+ public Issue1590()
+ {
+ var vm = new RootPageViewModel();
+ Content = BuildListView(vm);
+ }
+
+ StackLayout BuildListView(RootPageViewModel viewModel)
+ {
+ var headerTemplate = new DataTemplate(typeof(ModuleMediaListHeaderTemplate));
+ headerTemplate.CreateContent();
+
+ var itemTemplate = new DataTemplate(typeof(ModuleMediaListItemTemplate));
+ itemTemplate.CreateContent();
+
+ _listView = new ListView
+ {
+ ItemsSource = viewModel.MediaSections,
+ IsGroupingEnabled = true,
+ GroupDisplayBinding = new Binding("SectionName"),
+ HasUnevenRows = false,
+ GroupHeaderTemplate = headerTemplate,
+ ItemTemplate = itemTemplate
+ };
+
+ return new StackLayout { Children = { _listView } };
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ public class RootPageViewModel
+ {
+ public IEnumerable MediaSections
+ {
+ get
+ {
+ var titles = new[] {"First", "Second", "Third", "Forth", "Fifth"};
+
+ return titles.Select(section => new MediaListSection(section)
+ {
+ new FooViewModel {Title = "Foo", Description = "description for foo"},
+ new FooViewModel {Title = "Bar", Description = "description for bar"},
+ new FooViewModel {Title = "Baz", Description = "description for baz"},
+ new FooViewModel {Title = "Fiz", Description = "description for fiz"},
+ new FooViewModel {Title = "Buz", Description = "description for buz"},
+ }).ToList();
+ }
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ public class MediaListSection : ObservableCollection<FooViewModel>
+ {
+ public string SectionName { get; private set; }
+
+ public MediaListSection(string sectionName)
+ {
+ SectionName = sectionName;
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ public class FooViewModel
+ {
+ public string Title { get; set; }
+ public string Description { get; set; }
+ }
+
+ [Preserve (AllMembers=true)]
+ public class ModuleMediaListItemTemplate : ViewCell
+ {
+ public ModuleMediaListItemTemplate()
+ {
+ var title = new Label { YAlign = TextAlignment.Center };
+ title.SetBinding(Label.TextProperty, new Binding("Title", BindingMode.OneWay));
+
+ var description = new Label { YAlign = TextAlignment.Center };
+ description.SetBinding(Label.TextProperty, new Binding("Description", BindingMode.OneWay));
+
+ View = new StackLayout
+ {
+ Orientation = StackOrientation.Horizontal,
+ Padding = new Thickness(8),
+ Children = { title, description }
+ };
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ public class ModuleMediaListHeaderTemplate : ViewCell
+ {
+ public ModuleMediaListHeaderTemplate()
+ {
+ var title = new Label { TextColor = Color.White, YAlign = TextAlignment.Center };
+ title.SetBinding(Label.TextProperty, new Binding("SectionName", BindingMode.OneWay));
+
+ View = new StackLayout
+ {
+ Padding = new Thickness(8, 0),
+ BackgroundColor = Color.FromHex("#999999"),
+ Orientation = StackOrientation.Horizontal,
+ Children = { title },
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1593.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1593.cs
new file mode 100644
index 00000000..238ab936
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1593.cs
@@ -0,0 +1,169 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1593, "Android reports zero minimum size for almost all controls", PlatformAffected.Android)]
+ public class Issue1593 : ContentPage
+ {
+ public Issue1593 ()
+ {
+ var title = new Label {
+ Text = "Select League",
+ Font = Font.SystemFontOfSize (NamedSize.Large),
+ TextColor = Color.White
+ };
+
+ # region Season Filter
+
+ var seasonLabel = new Label {
+ Text = "Season",
+ Font = Font.SystemFontOfSize (NamedSize.Small),
+ TextColor = Color.White
+ };
+
+ var seasonPicker = new Picker {
+ WidthRequest = 140,
+ Title = "Season",
+ Items = { "Test 1", "Test 2"}
+ };
+
+ var seasonPanel = new StackLayout {
+ Children = {
+ seasonLabel,
+ seasonPicker
+ }
+ };
+
+ #endregion
+
+ # region Sport Filter
+
+ var sportLabel = new Label {
+ Text = "Sport",
+ Font = Font.SystemFontOfSize (NamedSize.Small),
+ TextColor = Color.White
+ };
+
+ var sportPicker = new Picker {
+ WidthRequest = 140,
+ Title = "Sport",
+ Items = { "Test 1", "Test 2"}
+ };
+
+ var sportPanel = new StackLayout {
+ Children = {
+ sportLabel,
+ sportPicker
+ }
+ };
+
+ #endregion
+
+ var filtersPanel = new StackLayout {
+ Padding = new Thickness (0, 10, 0, 0),
+ Orientation = StackOrientation.Horizontal,
+ HorizontalOptions = LayoutOptions.Fill,
+ Children = {
+ seasonPanel,
+ sportPanel
+ }
+ };
+
+ var leagues = new ListView {
+ MinimumHeightRequest = 100,
+ ItemsSource = new [] {
+ "Test 1",
+ "Test 2",
+ "Test 3",
+ "Test 4",
+ "Test 5",
+ "Test 6",
+ "Test 7",
+ "Test 8",
+ "Test 9",
+ "Test 10",
+ "Test 11",
+ "Test 12",
+ "Test 13",
+ "Test 14",
+ "Test 15",
+ },
+ BackgroundColor = Color.Gray,
+ ItemTemplate = new DataTemplate (() => {
+ var leagueName = new Label {
+ Font =
+ Font.SystemFontOfSize (NamedSize.Large),
+ BackgroundColor = Color.Transparent,
+ TextColor = Color.White,
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ LineBreakMode = LineBreakMode.WordWrap
+ };
+ leagueName.SetBinding (Label.TextProperty, ".");
+
+ var row = new StackLayout {
+ Padding = new Thickness (5, 0, 5, 0),
+ BackgroundColor = Color.Transparent,
+ Orientation = StackOrientation.Horizontal,
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ Children = {
+ leagueName
+ }
+ };
+
+ return new ViewCell {
+ View = row
+ };
+ })
+ };
+
+ var activityIndicator = new ActivityIndicator {
+ VerticalOptions =
+ LayoutOptions.CenterAndExpand,
+ IsVisible = false
+ };
+
+ var titlePanel = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Spacing = 50,
+ Children = {
+ title,
+ activityIndicator
+ }
+ };
+
+ var standingsButton = new Button {
+ Text = "Standings",
+ HorizontalOptions = LayoutOptions.CenterAndExpand
+ };
+
+ var scheduleButton = new Button {
+ Text = "Schedule",
+ HorizontalOptions = LayoutOptions.CenterAndExpand
+ };
+
+ var buttonPanel = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ HorizontalOptions = LayoutOptions.CenterAndExpand,
+ Children = {
+ standingsButton,
+ scheduleButton
+ }
+ };
+
+ Content = new StackLayout {
+ Padding = 20,
+ Children = {
+ titlePanel,
+ filtersPanel,
+ leagues,
+ buttonPanel
+ }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1598.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1598.cs
new file mode 100644
index 00000000..bb448743
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1598.cs
@@ -0,0 +1,80 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ public class MasterDetailToolbarBug : MasterDetailPage
+ {
+ public MasterDetailToolbarBug ()
+ {
+ Title = "MasterDetailToolbarBug";
+
+ Master = new ContentPage () {
+ Title = "Master"
+ };
+ Detail = new ContentPage () {
+ Title = "Detail",
+ };
+ Detail.ToolbarItems.Add (new ToolbarItem ("ToolbarItem2", "Icon.png", ()
+ => { }));
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1598, "MasterDetailContainer does not handle adding of views which are already its children", PlatformAffected.Android)]
+ public class Issue1598 : ContentPage
+ {
+ MasterDetailToolbarBug _secondPage = new MasterDetailToolbarBug ();
+
+ public Issue1598 ()
+ {
+ Title = "XamarinTest MainMenu";
+
+ var menu1 = new MainMenuCell ("MasterDetail - Toolbar bug", "Icon.png");
+ menu1.Tapped += (o, e) => {
+ Navigation.PushAsync (_secondPage);
+ };
+
+ var menu = new TableView () {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ HasUnevenRows = true,
+ Intent = TableIntent.Menu,
+ Root = new TableRoot {
+ new TableSection ("Menu") {
+ menu1,
+ }
+ }
+ };
+
+ Content = menu;
+
+ ToolbarItems.Add (new ToolbarItem ("ToolbarItem1", "bank.png", () => { }));
+ }
+
+ class MainMenuCell : ViewCell
+ {
+ public MainMenuCell (string title, string iconFile)
+ {
+ View = new StackLayout () {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Orientation = StackOrientation.Horizontal,
+ Spacing = 15,
+ Padding = 10,
+ Children = {
+ new Image () {
+ Source = ImageSource.FromFile (iconFile),
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ },
+ new Label () {
+ Text = title,
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ Font = Font.SystemFontOfSize (NamedSize.Large,
+ FontAttributes.Bold)
+ }
+ }
+ };
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1613.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1613.cs
new file mode 100644
index 00000000..1eaf95e4
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1613.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Maps;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1613, "Map.GetSizeRequest always returns map's current size", PlatformAffected.Android | PlatformAffected.iOS)]
+ public class Issue1613 : ContentPage
+ {
+ public Issue1613 ()
+ {
+ Build ();
+ }
+
+ async void Build ()
+ {
+ var image = new Image {
+ Source = "http://www.califliving.com/title24-energy/images/sanfrancisco.jpg",
+ Aspect = Aspect.AspectFill,
+ Opacity = 0.5,
+ };
+
+ var name = new Label {
+ Text = "Foo",
+ XAlign = TextAlignment.Center,
+ YAlign = TextAlignment.Center,
+ Font = Font.SystemFontOfSize(30, FontAttributes.Bold),
+ TextColor = Color.White,
+ };
+
+ var nameView = new AbsoluteLayout {
+ HeightRequest = 170,
+ BackgroundColor = Color.Black,
+ Children = {
+ {image, new Rectangle(0, 0, 1, 1), AbsoluteLayoutFlags.All},
+ {name, new Rectangle(0, 0, 1, 1), AbsoluteLayoutFlags.All}
+ },
+ };
+
+ var addressLabel = new Label {
+ Text = "Loading address…",
+ XAlign = TextAlignment.Center,
+ YAlign = TextAlignment.Center,
+ };
+
+ var map = new Map {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ };
+
+ Content = new StackLayout {
+ Children = { nameView, addressLabel, map },
+ };
+
+ await Task.Delay (1000);
+ addressLabel.Text = "Updated with new\nmultiline\nlabel";
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1618.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1618.cs
new file mode 100644
index 00000000..48f519f6
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1618.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Linq;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1618, "Horizontal ScrollView in ListView crashes", PlatformAffected.Android)]
+ public class Issue1618
+ : ContentPage
+ {
+ public Issue1618()
+ {
+ Content = new ListView {
+ ItemsSource = Enumerable.Range(0, 100).Select (i => Enumerable.Repeat (i, 500).Aggregate (string.Empty, (s, n) => s += n + " ")),
+ ItemTemplate = new DataTemplate (typeof (MyCell))
+ };
+ }
+
+ class MyCell
+ : ViewCell
+ {
+ public MyCell()
+ {
+ var scroll = new ScrollView {
+ Orientation = ScrollOrientation.Horizontal,
+ Content = new Label()
+ };
+
+ scroll.Content.SetBinding (Label.TextProperty, ".");
+
+ View = scroll;
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1641.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1641.xaml
new file mode 100644
index 00000000..ddc824a0
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1641.xaml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issue1641">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <x:String x:Key="caption" >Hello there!</x:String>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ <TableView>
+ <TableRoot Title="x">
+ <TableSection Title="y">
+ <TextCell Text="{StaticResource caption}" />
+ </TableSection>
+ </TableRoot>
+ </TableView>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1641.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1641.xaml.cs
new file mode 100644
index 00000000..c5e03f6e
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1641.xaml.cs
@@ -0,0 +1,17 @@
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1641, "Static Resources inside TableView using XAML doesn't work", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone)]
+ public partial class Issue1641 : ContentPage
+ {
+ public Issue1641 ()
+ {
+ InitializeComponent ();
+ }
+ }
+#endif
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1644.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1644.cs
new file mode 100644
index 00000000..c8947782
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1644.cs
@@ -0,0 +1,74 @@
+using System;
+using Xamarin.Forms;
+using System.Collections.ObjectModel;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1644, "ListView reappearing and selecting its item causes jobject exception", PlatformAffected.Android)]
+ public class Issue1644 : ContentPage
+ {
+ public ObservableCollection<string> Collection = new
+ ObservableCollection<string>();
+
+ public Issue1644 ()
+ {
+ for (int i = 0; i < 20; i++)
+ {
+ Collection.Add(DateTime.Now.ToString());
+ }
+
+ var listView = new ListView() {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ HasUnevenRows = true,
+ ItemsSource = Collection,
+ };
+
+ listView.ItemSelected += (sender, e) =>
+ {
+ listView.SelectedItem = null;
+ };
+
+ var root = new StackLayout() {
+ Padding = 5,
+ Spacing = 5,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Children = {
+ listView
+ }
+ };
+
+ Content = root;
+ }
+ }
+
+ public class Issue1644Menu : MasterDetailPage
+ {
+ Issue1644 _secondPage = new Issue1644();
+
+ public Issue1644Menu()
+ {
+ var button = new Button() {
+ Text = "MAIN MENU BUTTON"
+ };
+
+ button.Clicked += (sender, e) =>
+ {
+ Navigation.PushAsync(_secondPage);
+ };
+
+ Master = new ContentPage() {
+ Title = "Master"
+ };
+
+ Detail = new ContentPage() {
+ Title = "Detail",
+ Content = button
+ };
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653.xaml
new file mode 100644
index 00000000..2d937fc4
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653.xaml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issue1653">
+ <StackLayout Spacing="0">
+ <StackLayout x:Name="accountDetailsStack"/>
+ <StackLayout x:Name="carrierHeaderStack">
+ <Label Text="HEADER" Font="40" />
+ </StackLayout>
+ <StackLayout Padding="22,0,22,22">
+ <Label x:Name="productNameLabel" Text="TESTING 345" XAlign="Center" YAlign="Center" TextColor="#808080"></Label>
+ <StackLayout IsClippedToBounds="true">
+ <ScrollView HeightRequest="980" BackgroundColor="Aqua" IsClippedToBounds="true">
+ <StackLayout x:Name="addonGroupStack" Spacing="1" ></StackLayout>
+ </ScrollView>
+ </StackLayout>
+ <Button x:Name="activateButton" Text="ACTIVATE NOW" TextColor="White" BackgroundColor="#00A0FF">
+ </Button>
+ <ActivityIndicator x:Name="checkoutRunningIndicator" HeightRequest="20"/>
+ </StackLayout>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653.xaml.cs
new file mode 100644
index 00000000..e8088be7
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653.xaml.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1653, "ScrollView exceeding bounds", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone)]
+ public partial class Issue1653 : ContentPage
+ {
+ public Issue1653 ()
+ {
+ InitializeComponent ();
+
+ for (int i = 0; i < 40; i++)
+ addonGroupStack.Children.Add (new Label {Text = "Testing 123"});
+ }
+ }
+#endif
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653v2.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653v2.xaml
new file mode 100644
index 00000000..581087dd
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653v2.xaml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issue1653v2">
+ <StackLayout Spacing="0">
+ <StackLayout x:Name="accountDetailsStack"/>
+ <StackLayout x:Name="carrierHeaderStack">
+ <Label Text="HEADER" Font="40" />
+ </StackLayout>
+ <StackLayout Padding="22,0,22,22">
+ <Label x:Name="productNameLabel" Text="TESTING 345" XAlign="Center" YAlign="Center" TextColor="#808080"></Label>
+ <ScrollView HeightRequest="980" BackgroundColor="Aqua" IsClippedToBounds="true">
+ <StackLayout x:Name="addonGroupStack" Spacing="1" ></StackLayout>
+ </ScrollView>
+ <Button x:Name="activateButton" Text="ACTIVATE NOW" TextColor="White" BackgroundColor="#00A0FF">
+ </Button>
+ <ActivityIndicator x:Name="checkoutRunningIndicator" HeightRequest="20"/>
+ </StackLayout>
+ </StackLayout>
+</ContentPage>
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653v2.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653v2.xaml.cs
new file mode 100644
index 00000000..2492e8cf
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1653v2.xaml.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1653, "ScrollView exceeding bounds - v2", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone)]
+ public partial class Issue1653v2 : ContentPage
+ {
+ public Issue1653v2 ()
+ {
+ InitializeComponent ();
+
+ for (int i = 0; i < 40; i++)
+ addonGroupStack.Children.Add (new Label {Text = "Testing 123"});
+ }
+ }
+#endif
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1664.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1664.cs
new file mode 100644
index 00000000..61cbecfd
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1664.cs
@@ -0,0 +1,46 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1664, "Page.Title bubbling", PlatformAffected.iOS)]
+ public class Issue1664 : TabbedPage
+ {
+ public Issue1664 ()
+ {
+ NavigationPage nav1 = new NavigationPage (new ContentPage {Title = "Page1"});
+ NavigationPage nav2 = new NavigationPage (new PageTwo ());
+
+ nav1.Title = "Tab 1";
+ nav2.Title = "Tab 2";
+
+ Children.Add (nav1);
+ Children.Add (nav2);
+ }
+
+ public class PageTwo : ContentPage
+ {
+ public PageTwo ()
+ {
+ var pageTwoEntry = new Entry {
+ VerticalOptions = LayoutOptions.Center,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Placeholder = "Enter a title for page 2",
+ Text = "Page 2",
+ };
+
+ pageTwoEntry.SetBinding (Entry.TextProperty, new Binding ("Title", BindingMode.OneWayToSource));
+ BindingContext = this;
+ Content = new StackLayout {
+ Children = {
+ new Label {Text = "When changing the content of this entry, the page title (on top) should update, but not the tab title"},
+ pageTwoEntry
+ }
+ };
+ }
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1680.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1680.cs
new file mode 100644
index 00000000..eb98b5ed
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1680.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.ObjectModel;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1680, "Disposed object updating ListView ItemSource", PlatformAffected.Android)]
+ public class Issue1680 : ContentPage
+ {
+ XamarinListViewBug _page1 = new XamarinListViewBug();
+
+ public Issue1680()
+ {
+ var button1 = new Button { Text = "PAGE1" };
+
+ button1.Clicked += (sender, e) => Navigation.PushAsync (_page1);
+
+ var root = new StackLayout {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Children = {
+ button1,
+ }
+ };
+
+ Content = root;
+ }
+
+ public class XamarinListViewBug : MasterDetailPage
+ {
+ bool _flag;
+
+ readonly ObservableCollection<Tuple<string, string>> _collection = new ObservableCollection<Tuple<string, string>>();
+
+ void FillTheList()
+ {
+ _collection.Clear();
+
+ for (int i = 0; i < 100; i++) {
+ var item = new Tuple<string, string> (
+ string.Format ("{0} {0} {0} {0} {0} {0}", _flag ? i : 100 - i),
+ string.Format ("---- i ----{0} {0} {0} {0} {0} {0}", _flag ? i : 100 - i)
+ );
+
+
+ _collection.Add (item);
+ }
+
+ _flag = !_flag;
+ }
+
+ public XamarinListViewBug()
+ {
+ Title = "XamarinListViewBug";
+
+ SearchBar search = new SearchBar();
+ search.SearchButtonPressed += (sender, e) => FillTheList();
+
+ ListView list = new ListView {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HasUnevenRows = true,
+ ItemsSource = _collection,
+ ItemTemplate = new DataTemplate (typeof (CellTemplate))
+ };
+
+ StackLayout root = new StackLayout {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Children = {
+ search,
+ list,
+ }
+ };
+
+ Master = new ContentPage { Title = "Master" };
+ Detail = new ContentPage {
+ Title = "Detail",
+ Content = root
+ };
+ }
+
+ class CellTemplate : ViewCell
+ {
+ public CellTemplate()
+ {
+ Label cellLabel = new Label{
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ };
+
+ cellLabel.SetBinding (Label.TextProperty, new Binding ("Item1", BindingMode.OneWay));
+
+ StackLayout root = new StackLayout {
+ Children = {
+ cellLabel
+ }
+ };
+
+ View = root;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1682.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1682.cs
new file mode 100644
index 00000000..b23a534d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1682.cs
@@ -0,0 +1,30 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1682, "Software keyboard does not show up when we set Focus for Entry in Android", PlatformAffected.Android, NavigationBehavior.PushModalAsync)]
+ public class Issue1682 : ContentPage
+ {
+ public Issue1682 ()
+ {
+ var entry = new Entry {
+ WidthRequest = 300
+ };
+
+ var button = new Button {
+ Text = "Click"
+ };
+
+ button.Clicked += (sender, e) => entry.Focus ();
+
+ Content = new StackLayout {
+ Children = { entry, button },
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ HorizontalOptions = LayoutOptions.CenterAndExpand,
+ };
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1685.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1685.cs
new file mode 100644
index 00000000..1f9cbcf2
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1685.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1685, "Entry clears when upadting text from native with one-way binding", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone, NavigationBehavior.PushModalAsync)]
+ public class Issue1685 : ContentPage
+ {
+ class Test : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ decimal _entryValue = decimal.Zero;
+ public decimal EntryValue
+ {
+ get
+ {
+ return _entryValue;
+ }
+ set
+ {
+ _entryValue = value;
+ OnPropertyChanged("EntryValue");
+ }
+ }
+
+ void OnPropertyChanged(string caller) {
+ var handler = PropertyChanged;
+ if (handler != null)
+ {
+ handler(this, new PropertyChangedEventArgs(caller));
+ }
+ }
+ }
+
+ public Issue1685()
+ {
+ Title = "EntryBindingBug";
+
+ BindingContext = new Test();
+
+ var entry = new Entry() {
+ Placeholder = "Entry"
+ };
+ entry.SetBinding(Entry.TextProperty, "EntryValue", BindingMode.OneWay);
+
+ var button = new Button() {
+ Text = "Click me"
+ };
+
+ button.Clicked += (sender, e) =>
+ {
+ var context = BindingContext as Test;
+ context.EntryValue = context.EntryValue + 1;
+ };
+
+ var root = new StackLayout() {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Children = {
+ entry,
+ button
+ }
+ };
+
+ Content = root;
+
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1691.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1691.cs
new file mode 100644
index 00000000..110f9093
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1691.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Linq;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+using System.Diagnostics;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1691, "CarouselPage iOS CurrentPage bug")]
+ public class Issue1691 : TestCarouselPage
+ {
+ int _currentIndex;
+ int _page = 9;
+
+ protected override void Init ()
+ {
+ _currentIndex = 10;
+ ItemsSource = new ObservableCollection<int>() { _currentIndex };
+ SelectedItem = ((ObservableCollection<int>)ItemsSource)[0];
+ }
+
+ protected override ContentPage CreateDefault (object item)
+ {
+ var currentInt = item as int?;
+
+ var label = new Label {
+ Text = "Page " + currentInt,
+ };
+
+ return new ContentPage {
+ Content = new StackLayout {
+ Children = {
+ label,
+ new Button {
+ AutomationId = "CreatePreviousPage" + currentInt,
+ Text = "Create previous page",
+ Command = new Command (() => {
+ ((ObservableCollection<int>)ItemsSource).Insert (0, _page);
+ _page--;
+ label.Text = "Page Created";
+ })
+ },
+ new Button {
+ AutomationId = "GoToPreviousPage" + currentInt,
+ Text = "Go to previous page",
+ Command = new Command (() => {
+ CurrentPage = Children[0];
+ })
+ }
+ }
+ }
+ };
+ }
+
+#if UITEST
+ [Test]
+ public void Issue1691Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue 1691");
+ RunningApp.Tap (q => q.Marked ("CreatePreviousPage10"));
+ RunningApp.WaitForElement (q => q.Marked ("Page Created"));
+ RunningApp.Screenshot ("I should be on the same page with a new page created to the left");
+ RunningApp.Tap (q => q.Marked ("GoToPreviousPage10"));
+ RunningApp.WaitForNoElement (q => q.Marked ("GoToPreviousPage10"));
+ RunningApp.Screenshot ("I should be on page 9");
+ RunningApp.WaitForElement (q => q.Marked ("GoToPreviousPage9"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1698.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1698.cs
new file mode 100644
index 00000000..d50727fd
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1698.cs
@@ -0,0 +1,29 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1698, "ActionSheet extra buttons are not accessible", PlatformAffected.Android | PlatformAffected.WinPhone)]
+ public class Issue1698 : ContentPage
+ {
+ public Issue1698 ()
+ {
+ Button btn = new Button
+ {
+ Text = "Display ActionSheet"
+ };
+
+ btn.Clicked += btn_Clicked;
+
+ Content = btn;
+ }
+
+ public async void btn_Clicked(object sender, EventArgs e)
+ {
+ string x = await DisplayActionSheet("Action Sheet", "Cancel", null, new string[] { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "Eleven", "twelve", "thirteen", "fourteen" });
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1700.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1700.cs
new file mode 100644
index 00000000..5335bf98
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1700.cs
@@ -0,0 +1,30 @@
+using System;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1700, "Image fails loading from long URL", PlatformAffected.iOS | PlatformAffected.Android | PlatformAffected.WinPhone)]
+ public class Issue1700 : ContentPage
+ {
+ public Issue1700 ()
+ {
+ var stack = new StackLayout();
+ var url = "http://imgs.xkcd.com/comics/tasks.png?a=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
+ var url2 = "http://www.optipess.com/wp-content/uploads/2010/08/02_Bad-Comics6-10.png?a=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbasdasdasdasdasasdasdasdasdasd";
+ var img = new Image{
+ Source = new UriImageSource { Uri = new Uri(url) }
+ } ;
+ stack.Children.Add(img);
+ var img2 = new Image{
+ Source = new UriImageSource { Uri = new Uri(url2) }
+ } ;
+ stack.Children.Add(img2);
+ Content = new ScrollView() { Content = stack };
+ }
+ }
+}
+
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1703.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1703.cs
new file mode 100644
index 00000000..3f301d33
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1703.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1703, "Memory leak when navigating a page off of a navigation stack", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone)]
+ public class Issue1703 : NavigationPage
+ {
+ static List<WeakReference> s_pageRefs = new List<WeakReference>();
+
+ public Issue1703 ()
+ {
+ Navigation.PushAsync (GetMainPage ());
+ }
+
+ public static Page GetMainPage()
+ {
+ return CreateWeakReferencedPage();
+ }
+
+ static Page CreateWeakReferencedPage()
+ {
+ GC.Collect();
+ var result = CreatePage();
+ s_pageRefs.Add(new WeakReference(result));
+
+ // Add a second unreferenced page to prove that the problem only exists
+ // when pages are actually navigated to/from
+ s_pageRefs.Add(new WeakReference(CreatePage()));
+ GC.Collect();
+ return result;
+ }
+
+ static Page CreatePage()
+ {
+ var page = new ContentPage();
+ var contents = new StackLayout();
+
+ contents.Children.Add(
+ new Button
+ {
+ Text = "Next Page",
+ Command = new Command(() => page.Navigation.PushAsync(CreateWeakReferencedPage()))
+ });
+ contents.Children.Add(
+ new Label
+ {
+ Text = string.Format(
+ "References alive at time of creation: {0}",
+ s_pageRefs.Count(p => p.IsAlive)),
+ HorizontalOptions = LayoutOptions.CenterAndExpand
+ });
+
+ page.Content = contents;
+ return page;
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1705.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1705.cs
new file mode 100644
index 00000000..c8e2bea6
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1705.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1705, "Editor.IsEnabled = false", PlatformAffected.iOS)]
+ public class Issue1705 : ContentPage
+ {
+ public Issue1705 ()
+ {
+ Title = "test page";
+ Padding = 10;
+
+ var layout = new StackLayout ();
+ var t = new Entry {
+ IsEnabled = false
+ };
+
+ var e = new Editor {
+ IsEnabled = false,
+ BackgroundColor = Color.Aqua
+ };
+
+ layout.Children.Add (e);
+ layout.Children.Add (t);
+
+ Content = layout;
+ }
+ }
+
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1712.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1712.xaml
new file mode 100644
index 00000000..d1720e46
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1712.xaml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Forms.Controls.Issue1712">
+ <ContentPage.Content>
+ <WebView Source="http://xamarin.com/" VerticalOptions="FillAndExpand" />
+ </ContentPage.Content>
+</ContentPage>
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1712.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1712.xaml.cs
new file mode 100644
index 00000000..ca3e2d1e
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1712.xaml.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1712, "Wrong error thrown when setting LayoutOptions property to string", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone)]
+ public partial class Issue1712 : ContentPage
+ {
+ public Issue1712 ()
+ {
+ InitializeComponent ();
+ }
+ }
+#endif
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1722.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1722.cs
new file mode 100644
index 00000000..1b5b3a8d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1722.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1722, "MasterDetailPage crashes when assigning a NavigationPage to Detail with no children pushed", PlatformAffected.iOS)]
+ public class Issue1722 : MasterDetailPage
+ {
+ public Issue1722 ()
+ {
+ Master = new ContentPage {
+ Title = "Master",
+ Content = new Label { Text = "Master" }
+ };
+
+ Detail = new NavigationPage ();
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1723.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1723.cs
new file mode 100644
index 00000000..8671e75d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1723.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1723, "Picker's Items.Clear cause exception", PlatformAffected.WinPhone, NavigationBehavior.PushModalAsync)]
+ public class Issue1723
+ : ContentPage
+ {
+ Picker _picker = null;
+
+ public Issue1723()
+ {
+ StackLayout layout = new StackLayout();
+ Content = layout;
+
+ _picker = new Picker();
+ layout.Children.Add(_picker);
+
+ Button button = new Button();
+ button.Clicked += button_Clicked;
+ button.Text = "prepare magic";
+ layout.Children.Add(button);
+ }
+
+ void button_Clicked(object sender, EventArgs e)
+ {
+ Random r = new Random();
+
+ _picker.Items.Clear();
+
+ for (int j = 0; j < r.Next(10, 30); j++)
+ {
+ StringBuilder sb = new StringBuilder();
+ for (int k = 10; k < r.Next(15, 35); k++)
+ {
+ sb.Append((char)r.Next(65, 90));
+ }
+ _picker.Items.Add(sb.ToString());
+ }
+ _picker.SelectedIndex = r.Next(0, _picker.Items.Count);
+
+ Button button = (Button)sender;
+ button.Text = "crash the magic";
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1741.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1741.xaml
new file mode 100644
index 00000000..ce37314e
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1741.xaml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issue1741">
+ <Switch x:Name="chkAnon" Toggled="Anonymous_Toggled" />
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1741.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1741.xaml.cs
new file mode 100644
index 00000000..8972ae80
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1741.xaml.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1741, "Switch.IsEnabled = false does not disable a switch when switch is defined in XAML", PlatformAffected.WinPhone)]
+ public partial class Issue1741 : ContentPage
+ {
+ public Issue1741 ()
+ {
+ InitializeComponent();
+ }
+
+ public void Anonymous_Toggled (object sender, EventArgs e)
+ {
+ chkAnon.IsEnabled = !chkAnon.IsEnabled;
+ }
+ }
+#endif
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1742.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1742.cs
new file mode 100644
index 00000000..90c5ee57
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1742.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1742, "Invisible Button still fires Clicked event", PlatformAffected.WinPhone)]
+ public class Issue1742 : ContentPage
+ {
+ public Issue1742 ()
+ {
+ var listView = new ListView
+ {
+ RowHeight = 40
+ };
+ var invisibleButton = new Button
+ {
+ IsVisible = false,
+ Text = "INVISIBLE button"
+ };
+ var visibleButton = new Button
+ {
+ IsVisible = true,
+ Text = "Visible button"
+ };
+
+ invisibleButton.Clicked += Button_Clicked;
+ visibleButton.Clicked += Button_Clicked;
+ listView.ItemTapped += ListView_ItemTapped;
+
+ listView.ItemsSource = new string[] { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
+
+ Content = new StackLayout {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Children = { listView, visibleButton, invisibleButton }
+ };
+
+ }
+
+ void ListView_ItemTapped(object sender, ItemTappedEventArgs args)
+ {
+ DisplayAlert("Alert", "List item tapped", "OK", "Cancel");
+ }
+
+ void Button_Clicked(object sender, EventArgs args)
+ {
+ DisplayAlert("Alert", ((Button)sender).Text + " clicked", "OK", "Cancel");
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1747.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1747.xaml
new file mode 100644
index 00000000..5b599790
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1747.xaml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issue1747">
+ <StackLayout>
+ <Switch IsToggled="{Binding ShouldBeToggled, Mode=TwoWay}" IsEnabled="{Binding ShouldBeEnabled}"/>
+ <Button Text="Toggle Enabled" Clicked="Button_OnClick" />
+ </StackLayout>
+</ContentPage>
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1747.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1747.xaml.cs
new file mode 100644
index 00000000..b24e8404
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1747.xaml.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+
+ public class ViewModel : INotifyPropertyChanged
+ {
+ bool _shouldBeToggled;
+ public bool ShouldBeToggled {
+ get { return _shouldBeToggled; }
+ set
+ {
+ _shouldBeToggled = value;
+ OnPropertyChanged ();
+ }
+ }
+
+ bool _shouldBeEnabled;
+ public bool ShouldBeEnabled {
+ get { return _shouldBeEnabled; }
+ set
+ {
+ _shouldBeEnabled = value;
+ OnPropertyChanged ();
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+#if APP
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1747, "Binding to Switch.IsEnabled has no effect", PlatformAffected.WinPhone)]
+ public partial class Issue1747 : ContentPage
+ {
+ readonly ViewModel _vm;
+
+ public Issue1747 ()
+ {
+ _vm = new ViewModel ();
+ BindingContext = _vm;
+ InitializeComponent ();
+ }
+
+ public void Button_OnClick (object sender, EventArgs args)
+ {
+ _vm.ShouldBeToggled = !_vm.ShouldBeToggled;
+ _vm.ShouldBeEnabled = !_vm.ShouldBeEnabled;
+ }
+ }
+#endif
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1755.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1755.cs
new file mode 100644
index 00000000..ed4b88e4
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1755.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Maps;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1755, "Initializing a map with a different MapType other than default has no effect", PlatformAffected.WinPhone)]
+ public class Issue1755
+ : ContentPage
+ {
+ public Issue1755()
+ {
+ var map = new Map (MapSpan.FromCenterAndRadius (new Position (54.767683, -1.571671), Distance.FromMiles (5))) {
+ IsShowingUser = false,
+ HeightRequest = 100,
+ WidthRequest = 960,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ MapType = MapType.Hybrid
+ };
+
+ var switchMapTypeButton = new Button { Text = "Switch to hybrid" };
+ switchMapTypeButton.Clicked += (sender, args) => map.MapType = map.MapType == MapType.Hybrid ? MapType.Street : MapType.Hybrid;
+
+ var stack = new StackLayout { Spacing = 0 };
+ stack.Children.Add(map);
+ stack.Children.Add(switchMapTypeButton);
+ Content = stack;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1758.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1758.cs
new file mode 100644
index 00000000..0afd2ebb
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1758.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1758, "LayoutTo needs to be smarted about using layout specific API calls", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone)]
+ public class Issue1758 : ContentPage
+ {
+ ListView _list;
+ Button _button;
+
+ public Issue1758()
+ {
+ _list = new ListView { ItemsSource = new[] { "hello", "world", "from", "xamarin", "forms" } };
+
+ _button = new Button { Text = "Button" };
+
+ // The same behavior happens for both Absolute and Relative layout.
+ var layout = true ? Relative() : Absolute();
+
+ Animate();
+
+ Content = layout;
+ }
+
+ Layout Relative()
+ {
+ var layout = new RelativeLayout();
+
+ layout.Children.Add(_list,
+ Forms.Constraint.RelativeToParent(p => p.X),
+ Forms.Constraint.RelativeToParent(p => p.Y),
+ Forms.Constraint.RelativeToParent(p => p.Width),
+ Forms.Constraint.RelativeToParent(p => p.Height)
+ );
+
+ layout.Children.Add(_button,
+ Forms.Constraint.Constant(0),
+ Forms.Constraint.Constant(300));
+
+ return layout;
+ }
+
+ Layout Absolute()
+ {
+ var layout = new AbsoluteLayout { Children = { _list, _button } };
+
+ AbsoluteLayout.SetLayoutBounds(_list, new Rectangle(0, 0, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
+ AbsoluteLayout.SetLayoutBounds(_button, new Rectangle(0, 300, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
+
+ return layout;
+ }
+
+ async void Animate()
+ {
+ // Comment this delay out to see the bug
+ // await Task.Delay(500);
+
+ _button.LayoutTo(new Rectangle(100, 100, 100, 100), 1000);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1762.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1762.cs
new file mode 100644
index 00000000..cc50fa52
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1762.cs
@@ -0,0 +1,273 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Runtime.CompilerServices;
+
+using Xamarin.Forms;
+using System.Collections.Generic;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1762, "Binding issue with SwitchCell - System.ArgumentException:'jobject' must not be IntPtr.Zero", PlatformAffected.Android)]
+ public class Issue1762 : ContentPage
+ {
+ public static ObservableGroupMyObjCollection Objs = new ObservableGroupMyObjCollection ();
+
+ public Issue1762 ()
+ {
+ StackLayout stack = new StackLayout
+ {};
+ stack.Children.Add (new ListView {
+ ItemsSource = Objs,
+ ItemTemplate = new DataTemplate (() => {
+ SwitchCell cell = new SwitchCell ();
+ cell.SetBinding<MyObj> (SwitchCell.TextProperty, m => m.DisplayText);
+ cell.SetBinding<MyObj> (SwitchCell.OnProperty, m => m.IsSelected);
+ return cell;
+ }),
+ IsGroupingEnabled = true,
+ GroupDisplayBinding = new Binding ("Key")
+ });
+ Button b = new Button {
+ Text = "add"
+ };
+ b.Clicked += (sender, e) => {
+ Random r = new Random ();
+ Objs.Add (new MyObj {
+ DisplayText = r.Next ().ToString (),
+ IsSelected = r.Next () % 2 == 0
+ });
+ };
+ stack.Children.Add (b);
+
+ Content = stack;
+ }
+ }
+
+ public class Grouping<K, T> : ObservableCollection<T>, IGroupingCollection<K, T> where T : INotifyPropertyChanged
+ {
+ public K Key { get; private set; }
+
+ public Grouping (K key, IEnumerable<T> items)
+ {
+ Key = key;
+ foreach (var item in items)
+ Items.Add (item);
+ }
+
+ public Grouping (K key, T item)
+ {
+ Key = key;
+ Items.Add (item);
+ }
+ }
+
+ public static class Extensions
+ {
+ public static IEnumerable<T> Enumerate<T> (this IEnumerable<IEnumerable<T>> listOfList)
+ {
+ foreach (var list in listOfList) {
+ foreach (T item in list)
+ yield return item;
+ }
+ }
+ }
+
+ public interface IGroupingCollection<K, T> : ICollection<T>, IGrouping<K, T> {}
+
+ public interface ISortingKey<T>
+ {
+ T SortingKey { get; }
+ }
+
+ public class MyObj : ObservableObject, ISortingKey<bool>
+ {
+ public MyObj () {}
+
+ string _displayText;
+
+ public string DisplayText
+ {
+ get { return _displayText; }
+ set { SetProperty (ref _displayText, value); }
+ }
+
+ bool _isSelected;
+
+ public bool IsSelected
+ {
+ get { return _isSelected; }
+ set
+ {
+ if (SetProperty (ref _isSelected, value))
+ NotifyPropertyChanged (() => SortingKey);
+ }
+ }
+
+ #region ISortingKey implementation
+ public bool SortingKey
+ {
+ get { return IsSelected; }
+ }
+ #endregion
+ }
+
+ public abstract class ObservableGroupCollection<K, T> : ObservableCollection<IGroupingCollection<K, T>> where T : class, INotifyPropertyChanged, ISortingKey<K>
+ {
+ Func<K, K, bool> _equalityComparer;
+
+ public ObservableGroupCollection (IEnumerable<IGroupingCollection<K, T>> items, Func<K, K, bool> equalityComparer)
+ : base (items)
+ {
+ _equalityComparer = equalityComparer;
+ if (items != null) {
+ foreach (var propChangeItem in items.Enumerate ())
+ SetupPropertyChanged (propChangeItem, equalityComparer);
+ }
+ }
+
+ void SetupPropertyChanged (T propChangeItem, Func<K, K, bool> equalityComparer)
+ {
+ propChangeItem.PropertyChanged += (sender, e) => {
+ if (e.PropertyName == "SortingKey") {
+ //using (BlockReentrancy())
+ {
+ T changedItem = (T)sender;
+ IGroupingCollection<K, T> oldGroup = null, newGroup = null;
+ foreach (var group in Items) //go through all groups to find item
+ {
+ if (oldGroup == null /* || newGroup == null*/) {
+ foreach (var item2 in group) {
+ if (oldGroup == null && item2 == changedItem)
+ oldGroup = group;
+ }
+ }
+ if (newGroup == null && equalityComparer (group.Key, changedItem.SortingKey))
+ newGroup = group;
+ }
+ if (oldGroup != null) {
+ oldGroup.Remove (changedItem);
+ if (oldGroup.Count == 0) {
+ OnCollectionChanged (new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Remove, oldGroup));
+ Items.Remove (oldGroup);
+ }
+ }
+#if DEBUG
+ else
+ throw new Exception ("oldGroup == null");
+#endif
+ if (newGroup == null) {
+ Items.Add (newGroup = new Grouping<K, T> (changedItem.SortingKey, changedItem));
+ OnCollectionChanged (new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Add, newGroup));
+ } else {
+ foreach (var item in newGroup) {
+ if (item == changedItem)
+ return;
+ }
+ newGroup.Add (changedItem);
+ }
+ }
+ }
+ };
+ }
+
+ public ObservableGroupCollection (IGroupingCollection<K, T> item, Func<K, K, bool> equalityComparer)
+ {
+ _equalityComparer = equalityComparer;
+ if (item != null) {
+ foreach (T t in item)
+ SetupPropertyChanged (t, equalityComparer);
+ }
+ }
+
+ public void Add (T item)
+ {
+ SetupPropertyChanged (item, _equalityComparer);
+ foreach (IGroupingCollection<K, T> group in Items) {
+ if (_equalityComparer (group.Key, item.SortingKey)) {
+ group.Add (item);
+ return;
+ }
+ }
+ Grouping<K, T> newGroup = new Grouping<K, T> (item.SortingKey, item);
+ Items.Add (newGroup);
+ OnCollectionChanged (new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Add, newGroup));
+ }
+
+ /*protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
+ {
+ base.OnCollectionChanged(e);
+ }*/
+ }
+
+ public class ObservableGroupMyObjCollection : ObservableGroupCollection<bool, MyObj>
+ {
+ public ObservableGroupMyObjCollection ()
+ : base ((IGroupingCollection<bool, MyObj>)null, (k1, k2) => k1 == k2) {}
+ }
+
+ public abstract class ObservableObject : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+
+ protected virtual void NotifyPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ OnPropertyChanged (new PropertyChangedEventArgs (propertyName));
+ }
+
+ protected virtual void NotifyPropertyChanged<T> (Expression<Func<T>> propertyExpression)
+ {
+ string propertyName = GetPropertyName (propertyExpression);
+ OnPropertyChanged (new PropertyChangedEventArgs (propertyName));
+ }
+
+ protected virtual void OnPropertyChanged (PropertyChangedEventArgs e)
+ {
+ var eventHandler = PropertyChanged;
+ if (eventHandler != null) {
+ try {
+ eventHandler (this, e); //crashes here!
+ } catch (Exception ex) {
+ System.Diagnostics.Debug.WriteLine (ex);
+ }
+ }
+ }
+
+
+ protected bool SetProperty<T> (ref T storage, T value, Expression<Func<T>> propertyExpression)
+ {
+ var propertyName = GetPropertyName (propertyExpression);
+ return SetProperty<T> (ref storage, value, propertyName);
+ }
+
+
+ protected bool SetProperty<T> (ref T storage, T value, [CallerMemberName] string propertyName = null)
+ {
+ if (EqualityComparer<T>.Default.Equals (storage, value))
+ return false;
+
+ storage = value;
+ NotifyPropertyChanged (propertyName);
+ return true;
+ }
+
+ string GetPropertyName<T> (Expression<Func<T>> propertyExpression)
+ {
+ if (propertyExpression == null)
+ throw new ArgumentNullException ("propertyExpression");
+
+ if (propertyExpression.Body.NodeType != ExpressionType.MemberAccess)
+ throw new ArgumentException ("Should be a member access lambda expression", "propertyExpression");
+
+ var memberExpression = (MemberExpression)propertyExpression.Body;
+ return memberExpression.Member.Name;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1763.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1763.cs
new file mode 100644
index 00000000..e6cb31f3
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1763.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1763, "First item of grouped ListView not firing .ItemTapped", PlatformAffected.WinPhone, NavigationBehavior.PushAsync)]
+ public class Issue1763 : TabbedPage
+ {
+ public Issue1763 ()
+ {
+ Title = "Contacts";
+
+ Children.Add (new ContactsPage ());
+ }
+ }
+
+ public class ContactsPage : ContentPage
+ {
+ public ContactsPage ()
+ {
+ var listView = new ListView {
+ ItemTemplate = new DataTemplate (() => {
+ var cell = new TextCell ();
+ cell.SetBinding (TextCell.TextProperty, new Binding ("Name"));
+ cell.SetBinding (TextCell.DetailProperty, new Binding ("Number"));
+ return cell;
+ }),
+ IsGroupingEnabled = true,
+ GroupDisplayBinding = new Binding ("Name")
+ };
+
+ var groupedContacts = new ObservableCollection<Group<ContactViewModel>> {
+ new Group<ContactViewModel> ("E", new[] {
+ new ContactViewModel { Name = "Egor1", Number = "'Tap' on this item won't fire the event" },
+ new ContactViewModel { Name = "Egor2", Number = "123" },
+ new ContactViewModel { Name = "Egor3", Number = "123" },
+ })
+ };
+
+ listView.ItemsSource = groupedContacts;
+ listView.ItemTapped += ListViewOnItemTapped;
+
+ Content = listView;
+ }
+
+ void ListViewOnItemTapped (object sender, ItemTappedEventArgs itemTappedEventArgs)
+ {
+ DisplayActionSheet ("Tapped a List item", "Cancel", "Destruction");
+ }
+ }
+
+ public class ContactViewModel : ViewModelBase2
+ {
+ string _name;
+ string _number;
+
+ public string Name
+ {
+ get { return _name; }
+ set { SetProperty (ref _name, value); }
+ }
+
+ public string Number
+ {
+ get { return _number; }
+ set { SetProperty (ref _number, value); }
+ }
+ }
+
+ public class Group<TItem> : ObservableCollection<TItem>
+ {
+ public Group (string name, IEnumerable<TItem> items)
+ {
+ Name = name;
+ foreach (var item in items)
+ Add (item);
+ }
+
+ public string Name { get; set; }
+ }
+
+ public class ViewModelBase2 : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual ViewModelBase2 SetProperty<T> (ref T field, T value, [CallerMemberName] string propertyName = null)
+ {
+ field = value;
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler (this, new PropertyChangedEventArgs (propertyName));
+ return this;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1766.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1766.xaml
new file mode 100644
index 00000000..15479bd6
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1766.xaml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issue1766">
+ <ContentPage.Content>
+ <ListView ItemsSource="{Binding MyItems}" x:Name="MyListViewList">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <StackLayout Orientation="Horizontal">
+ <Label Text="{Binding Reference}"/>
+ <Button Clicked="OnButtonClicked"
+ Text=">>>"
+ IsVisible="{Binding ShowButton}"/>
+ </StackLayout>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </ContentPage.Content>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1766.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1766.xaml.cs
new file mode 100644
index 00000000..efac1a1a
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1766.xaml.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1766, "Editor.IsEnabled = false", PlatformAffected.WinPhone)]
+ public partial class Issue1766 : ContentPage
+ {
+ public Issue1766 ()
+ {
+ InitializeComponent();
+ MyItems.Add(new MyItem() { Reference = DateTime.Now.Ticks.ToString(), ShowButton = true });
+ MyItems.Add(new MyItem() { Reference = DateTime.Now.Ticks.ToString(), ShowButton = false });
+ MyItems.Add(new MyItem() { Reference = DateTime.Now.Ticks.ToString(), ShowButton = true });
+ MyItems.Add(new MyItem() { Reference = DateTime.Now.Ticks.ToString(), ShowButton = false });
+
+ var myListViewList = this.FindByName<ListView>("MyListViewList");
+
+ foreach (var item in myListViewList.ItemTemplate.Values)
+ {
+ System.Diagnostics.Debug.WriteLine("item: {0}", item);
+ }
+
+ if (myListViewList != null)
+ {
+ myListViewList.ItemTapped += (sender, args) =>
+ {
+ DisplayAlert("Item Tapped", "Item Tapped", "Ok");
+ };
+ }
+
+ BindingContext = this;
+ }
+
+ List<MyItem> _myItems;
+ public List<MyItem> MyItems
+ {
+ get
+ {
+ if (_myItems == null) {
+ _myItems = new List<MyItem> ();
+ }
+ return _myItems;
+ }
+ }
+
+ public void OnButtonClicked(object sender, EventArgs e)
+ {
+ DisplayAlert("Button Tapped", "Button Tapped", "Ok");
+ }
+ }
+
+ public class MyItem
+ {
+ public string Reference { get; set; }
+ public bool ShowButton { get; set; }
+ }
+#endif
+
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1769.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1769.cs
new file mode 100644
index 00000000..3eabf8e2
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1769.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1769, "PushAsync with Switch produces NRE", PlatformAffected.Android)]
+ public class Issue1769
+ : ContentPage
+ {
+ public Issue1769()
+ {
+ var button = new Button()
+ {
+ Text = "Go To Page 2"
+ };
+
+ var switchDemo = new SwitchDemoPage();
+
+ button.Clicked += async (sender, args) => {
+ await ((Button)sender).Navigation.PushAsync(switchDemo);
+ };
+
+ Content = button;
+ }
+
+ class SwitchDemoPage : ContentPage
+ {
+ Label _label;
+
+ public SwitchDemoPage()
+ {
+ Label header = new Label
+ {
+ Text = "Switch",
+ Font = Font.BoldSystemFontOfSize(50),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ Switch switcher = new Switch
+ {
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+ switcher.Toggled += switcher_Toggled;
+
+ _label = new Label
+ {
+ Text = "Switch is now False",
+ Font = Font.SystemFontOfSize(NamedSize.Large),
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+
+ // Accomodate iPhone status bar.
+ Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
+
+ // Build the page.
+ Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ switcher,
+ _label
+ }
+ };
+ }
+
+ void switcher_Toggled(object sender, ToggledEventArgs e)
+ {
+ _label.Text = string.Format("Switch is now {0}", e.Value);
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1777.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1777.cs
new file mode 100644
index 00000000..31d4345c
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1777.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1777, "Adding picker items when picker is in a ViewCell breaks", PlatformAffected.WinPhone)]
+ public class Issue1777 : ContentPage
+ {
+ Picker _pickerTable = null;
+ Picker _pickerNormal = null;
+
+ public Issue1777 ()
+ {
+ StackLayout stackLayout = new StackLayout();
+ Content = stackLayout;
+
+ TableView tableView = new TableView();
+ stackLayout.Children.Add( tableView);
+
+ TableRoot tableRoot = new TableRoot();
+ tableView.Root = tableRoot;
+
+ TableSection tableSection = new TableSection("Table");
+ tableRoot.Add(tableSection);
+
+ ViewCell viewCell = new ViewCell ();
+ tableSection.Add (viewCell);
+
+ ContentView contentView = new ContentView ();
+ contentView.HorizontalOptions = LayoutOptions.FillAndExpand;
+ viewCell.View = contentView;
+
+ _pickerTable = new Picker ();
+ _pickerTable.HorizontalOptions = LayoutOptions.FillAndExpand;
+ contentView.Content = _pickerTable;
+
+ Label label = new Label ();
+ label.Text = "Normal";
+ stackLayout.Children.Add (label);
+
+ _pickerNormal = new Picker ();
+ stackLayout.Children.Add (_pickerNormal);
+
+ Button button = new Button ();
+ button.Clicked += button_Clicked;
+ button.Text = "do magic";
+ stackLayout.Children.Add (button);
+
+ //button_Clicked(button, EventArgs.Empty);
+ _pickerTable.SelectedIndex = 0;
+ _pickerNormal.SelectedIndex = 0;
+ }
+
+ void button_Clicked (object sender, EventArgs e)
+ {
+ _pickerTable.Items.Add ("test " + _pickerTable.Items.Count);
+ _pickerNormal.Items.Add ("test " + _pickerNormal.Items.Count);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue181.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue181.cs
new file mode 100644
index 00000000..e290c4a6
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue181.cs
@@ -0,0 +1,41 @@
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 181, "Color not initialized for Label", PlatformAffected.Android, NavigationBehavior.PushModalAsync)]
+ public class Issue181 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Title = "Issue 181";
+ Content = new Frame {
+ OutlineColor = Color.Red,
+ BackgroundColor = new Color (1.0, 1.0, 0.0),
+ Content = new Label {
+ Text = "I should have red text",
+ TextColor = Color.Red,
+ BackgroundColor = new Color (0.5, 0.5, 0.5),
+ XAlign = TextAlignment.Center,
+ YAlign = TextAlignment.Center
+ }
+ };
+ }
+
+#if UITEST
+ [Test]
+ [Category ("ManualReview")]
+ [UiTest (typeof(Label), "TextColor")]
+ public void Issue181TestsLabelShouldHaveRedText ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("I should have red text"));
+ RunningApp.Screenshot ("Label should have red text");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1851.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1851.cs
new file mode 100644
index 00000000..608bec6f
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1851.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1851, "ObservableCollection in ListView gets Index out of range when removing item", PlatformAffected.Android)]
+ public class Issue1851 : ContentPage
+ {
+ public Issue1851 ()
+ {
+ var grouping = new Grouping<string, string>("number", new List<string> { "1", "2", "3", "4", "5", "6", "7", "8", "9" });
+ var groupings = new ObservableCollection<Grouping<string, string>>
+ {
+ new Grouping<string, string>("letters", new List<string> {"a", "b", "c", "d", "e", "f", "g", "h", "i"}),
+ new Grouping<string, string>("colours", new List<string> {"red", "green", "blue", "white", "orange", "purple", "grey", "mauve", "pink"}),
+ grouping,
+ };
+
+ var listview = new ListView
+ {
+ HasUnevenRows = true,
+ IsGroupingEnabled = true,
+ ItemsSource = groupings,
+ ItemTemplate = new DataTemplate(typeof(CellTemplate)),
+ GroupDisplayBinding = new Binding("Key")
+ };
+ var groupbtn = new Button() { Text = "add/remove group" };
+ bool group = true;
+ groupbtn.Clicked += (sender, args) =>
+ {
+ listview.GroupShortNameBinding = new Binding ("Key");
+ if (group)
+ {
+ group = false;
+
+ // ***** Crashes here
+ groupings.Remove(grouping);
+ }
+ else
+ {
+ group = true;
+ groupings.Add(grouping);
+ }
+ };
+
+ Content = new StackLayout
+ {
+ Children =
+ {
+ groupbtn,
+ listview,
+ }
+ };
+ }
+ }
+
+ public class CellTemplate : ViewCell
+ {
+ protected override void OnBindingContextChanged()
+ {
+ base.OnBindingContextChanged();
+
+ var text = BindingContext as string;
+ if (text == null)
+ return;
+
+ View = new Label { Text = text };
+ }
+ }
+
+ public class Grouping<TKey, TElement> : ObservableCollection<TElement>
+ {
+ public Grouping(TKey key, IEnumerable<TElement> items)
+ {
+ Key = key;
+ foreach (var item in items)
+ Items.Add(item);
+ }
+
+ public TKey Key { get; private set; }
+
+
+ }
+}
+ \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1875.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1875.cs
new file mode 100644
index 00000000..0391ef4d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1875.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1875, "NSRangeException adding items through ItemAppearing", PlatformAffected.iOS)]
+ public class Issue1875
+ : ContentPage
+ {
+ public Issue1875()
+ {
+ Button loadData = new Button { Text = "Load", HorizontalOptions = LayoutOptions.FillAndExpand };
+ ListView mainList = new ListView {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand
+ };
+
+ mainList.SetBinding (ListView.ItemsSourceProperty, "Items");
+
+ _viewModel = new MainViewModel ();
+ BindingContext = _viewModel;
+ loadData.Clicked += async (sender, e) => {
+ await LoadData ();
+ };
+
+ mainList.ItemAppearing += OnItemAppearing;
+
+ Content = new StackLayout {
+ Children = {
+ loadData,
+ mainList
+ }
+ };
+ }
+
+ readonly MainViewModel _viewModel;
+ int _start = 0;
+ const int NumberOfRecords = 15;
+
+ async void OnItemAppearing(object sender, ItemVisibilityEventArgs e)
+ {
+ var item = (int)e.Item;
+ if (!_viewModel.IsLoading && item == _viewModel.Items.Last())
+ await LoadData();
+ }
+
+ async Task LoadData ()
+ {
+ await _viewModel.LoadData (_start, NumberOfRecords);
+ _start = _start + NumberOfRecords;
+ }
+
+ public class MainViewModel : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public MainViewModel ()
+ {
+ }
+
+ ObservableCollection<int> _items;
+ public ObservableCollection<int> Items {
+ get {
+ if (_items == null)
+ _items = new ObservableCollection<int> ();
+
+ return _items;
+ }
+ set {
+ _items = value;
+ PropertyChanged (this, new PropertyChangedEventArgs ("Items"));
+ }
+ }
+
+ bool _isLoading;
+ public bool IsLoading {
+ get {
+ return _isLoading;
+ }
+ set {
+ if (_isLoading != value) {
+ _isLoading = value;
+ PropertyChanged (this, new PropertyChangedEventArgs ("IsLoading"));
+ }
+ }
+ }
+
+ public async Task LoadData (int start, int numberOfRecords)
+ {
+ IsLoading = true;
+ for (int counter = 0; counter < numberOfRecords; counter++)
+ Items.Add (start + counter);
+
+ IsLoading = false;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1888.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1888.cs
new file mode 100644
index 00000000..b415fbfd
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1888.cs
@@ -0,0 +1,36 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1888, "Fix image resources not being freed after page is navigated away from ", PlatformAffected.iOS)]
+ public class Issue1888: ContentPage
+ {
+ public Issue1888 ()
+ {
+ var btn = new Button
+ {
+ Text = "Click!"
+ };
+ btn.Clicked += (sender, e) => Navigation.PushAsync(new LeakPage());
+ Content = btn;
+ }
+ }
+
+ public class LeakPage : ContentPage
+ {
+ public LeakPage ()
+ {
+ var img = new Image
+ {
+ Source = new FileImageSource
+ {
+ File = "Default-568h@2x.png"
+ }
+ };
+ Content = img;
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1891.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1891.cs
new file mode 100644
index 00000000..5ffd34f0
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1891.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls {
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1891, "Modal dialog scrolls to far when focusing input boxes", PlatformAffected.iOS)]
+ public class Issue1891 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var entry = new Entry {
+ Text = "Email Address",
+ VerticalOptions = LayoutOptions.End,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ HeightRequest = 60
+ };
+ var btn = new Button { Text = "focus entry" };
+ btn.Clicked += async (object sender, EventArgs e) => {
+ await Navigation.PushModalAsync (new ModalWithInputPage ());
+ };
+
+ Content = new ScrollView {
+ Content = new StackLayout {
+ VerticalOptions = LayoutOptions.End,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Children = {
+ new StackLayout{ Children = { btn, entry } }
+ }
+ }
+ };
+ }
+ public class ModalWithInputPage : ContentPage
+ {
+ public ModalWithInputPage()
+ {
+ Content = BuildLayout();
+ }
+
+ static Layout BuildLayout()
+ {
+ return new ScrollView
+ {
+ Content = new StackLayout
+ {
+ VerticalOptions = LayoutOptions.End,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Children = {
+ new Entry {
+ Placeholder = "Email Address",
+ VerticalOptions = LayoutOptions.End,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ HeightRequest = 60
+ }
+ }
+ }
+ };
+ }
+ }
+
+#if UITEST
+ [Test]
+ [UiTest (typeof(TabbedPage))]
+ public void Issue1891Tests ()
+ {
+ // TODO
+ // Please redo, invalid test
+ Assert.Inconclusive ("Needs test");
+ }
+#endif
+
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1895.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1895.cs
new file mode 100644
index 00000000..1e65ecf9
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1895.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1895, "ListView with static BindingContext somehow leaks memory", PlatformAffected.iOS | PlatformAffected.Android)]
+ public class Issue1895
+ : ContentPage
+ {
+ public Issue1895()
+ {
+ var button = new Button { Text = "Push weak page" };
+ button.Clicked += async (sender, args) => await Navigation.PushAsync (CreateWeakReferencedPage());
+ Content = button;
+ }
+
+ static List<WeakReference> s_pageRefs = new List<WeakReference>();
+ static FakeProvider s_fakeProvider = new FakeProvider();
+
+ static Page CreateWeakReferencedPage()
+ {
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+ GC.Collect();
+
+ var result = CreatePage();
+ s_pageRefs.Add(new WeakReference(result));
+
+ return result;
+ }
+
+ class WeakReferencedPage : ContentPage
+ {
+
+ }
+
+ static Page CreatePage()
+ {
+ var page = new WeakReferencedPage();
+ var contents = new StackLayout();
+
+ contents.Children.Add (new Button {
+ Text = "Next Page",
+ Command = new Command(() => page.Navigation.PushAsync(CreateWeakReferencedPage()))
+ });
+
+ contents.Children.Add (new Label {
+ Text = string.Format ("References alive at time of creation: {0}", s_pageRefs.Count(p => p.IsAlive)),
+ HorizontalOptions = LayoutOptions.CenterAndExpand
+ });
+
+ var listView = new ListView { BindingContext = s_fakeProvider };
+ listView.SetBinding (ListView.ItemsSourceProperty, "Items");
+ contents.Children.Add (listView);
+
+ page.Content = contents;
+ return page;
+ }
+
+ class FakeProvider
+ {
+ public ObservableCollection<string> Items { get; private set; }
+
+ public FakeProvider()
+ {
+ Items = new ObservableCollection<string>();
+ Items.Add("Item 1");
+ Items.Add("Item 2");
+ Items.Add("Item 3");
+ Items.Add("Item 4");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1898.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1898.xaml
new file mode 100644
index 00000000..3b5b096e
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1898.xaml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issue1898"
+ xmlns:local="clr-namespace:Xamarin.Forms.Controls;assembly=Xamarin.Forms.Controls">
+ <ContentPage x:Name="Issue1898PageOne" Title="Title 1" Icon="bank.png">
+ <StackLayout>
+ <Button Text="Change Title 1" Command="{Binding ChangeTitleOneCommand}" />
+ <Button Text="Change Icon 1" Command="{Binding ChangeIconOneCommand}" />
+ <Button Text="Change Icon other page 1" Command="{Binding ChangeIconOtherPageOneCommand}" />
+ </StackLayout>
+ </ContentPage>
+ <ContentPage x:Name="Issue1898PageTwo" Title="Title 2" Icon="calculator.png">
+ <StackLayout>
+ <Button Text="Change Title 2" Command="{Binding ChangeTitleTwoCommand}" />
+ <Button Text="Change Icon 2" Command="{Binding ChangeIconTwoCommand}" />
+ <Button Text="Change Icon other page 2" Command="{Binding ChangeIconOtherPageTwoCommand}" />
+ </StackLayout>
+ </ContentPage>
+</TabbedPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1898.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1898.xaml.cs
new file mode 100644
index 00000000..2e0b615d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1898.xaml.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Input;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1898, "TabbedPage Page not watching icon changes", PlatformAffected.iOS, NavigationBehavior.PushAsync)]
+ public partial class Issue1898 : TabbedPage
+ {
+ public Issue1898()
+ {
+ InitializeComponent();
+ var vm = new Isseu1898Vm {
+ ChangeTitleOneCommand = new Command (() => Issue1898PageOne.Title = "Changed 1"),
+ ChangeIconOneCommand = new Command (() => Issue1898PageOne.Icon = "coffee.png"),
+ ChangeIconOtherPageOneCommand = new Command (() => Issue1898PageTwo.Icon = "coffee.png"),
+ ChangeTitleTwoCommand = new Command (() => Issue1898PageTwo.Title = "Changed 2"),
+ ChangeIconTwoCommand = new Command (() => Issue1898PageTwo.Icon = "bank.png"),
+ ChangeIconOtherPageTwoCommand = new Command (() => Issue1898PageOne.Icon = "calculator.png"),
+ };
+ BindingContext = vm;
+ }
+ }
+
+ public class Isseu1898Vm
+ {
+ public ICommand ChangeTitleOneCommand { get; set; }
+ public ICommand ChangeIconOneCommand { get; set; }
+ public ICommand ChangeIconOtherPageOneCommand { get; set; }
+
+ public ICommand ChangeTitleTwoCommand { get; set; }
+ public ICommand ChangeIconTwoCommand { get; set; }
+ public ICommand ChangeIconOtherPageTwoCommand { get; set; }
+ }
+#endif
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1905.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1905.cs
new file mode 100644
index 00000000..b315cb11
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1905.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages {
+
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1905, "AlertView doesn't scroll when text is to large", PlatformAffected.iOS | PlatformAffected.Android)]
+ public class Issue1905 : ContentPage {
+
+ public Issue1905 () {
+ var btn = new Button { Text="Show alert" };
+ btn.Clicked += async (object sender, EventArgs e) => {
+ await DisplayAlert ("Long Message", "Start - kajsd;lfkjals;kddfjkl;asdadjsf;lkasjdfl;kasjdf;lkajsd;flkjasd;flkjasd;lkdfjkakls;dfjkl;asdjfkl;asdjfl;kasdjadsfkl;asjdfl;kajadjs;flkjasdl;fklf;jas;dlkjf;alskdjdfakl;sddfjsakls;djfjl;aksdadfjsl;kasdjadsfl;kasdadfjskl;asjdfl;kasdjfl;kasdjfl;kasjdfl;kasjdfkl;asjdfl;kasjdfl;kasjdfl;kasjdfkl;ajsdl;kfkl;jsadkl;fjklasl;dkfjals;kdfjals;kdjfals;kdfalksjdflkajsd;lkfjasl;dkdfjk;alskdjdfjal;skjdfl;askjdfl;aksjdfakl;sdjfkl;asjdfkl;asjdfl;kajsdfl;kajsdfl;kajsdl;ffkl;jasdl;kkl;dfjadls;kdfjkals;kdjkadfsal;ksdjdfal;skddfjal;skdfjal;skdjfal;ksdfjakls;djdfakls;dfjl;askdfjal;skdjfakls;dfjkajsd;lfkjals;kddfjkl;asdadjsf;lkasjdfl;kasjdf;lkajsd;flkjasd;flkjasd;lkdfjkakls;dfjkl;asdjfkl;asdjfl;kasdjadsfkl;asjdfl;kajadjs;flkjasdl;fklf;jas;dlkjf;alskdjdfakl;sddfjsakls;djfjl;aksdadfjsl;kasdjadsfl;kasdadfjskl;asjdfl;kasdjfl;kasdjfl;kasjdfl;kasjdfkl;asjdfl;kasjdfl;kasjdfl;kasjdfkl;ajsdl;kfkl;jsadkl;fjklasl;dkfjals;kdfjals;kdjfals;kdfalksjdflkajsd;lkfjasl;dkdfjk;alskdjdfjal;skjdfl;askjdfl;aksjdfakl;sdjfkl;asjdfkl;asjdfl;kajsdfl;kajsdfl;kajsdl;ffkl;jasdl;kkl;dfjadls;kdfjkals;kdjkadfsal;ksdjdfal;skddfjal;skdfjal;skdjfal;ksdfjakls;djdfakls;dfjl;askdfjal;skdjfakls;dfjkajsd;lfkjals;kddfjkl;asdadjsf;lkasjdfl;kasjdf;lkajsd;flkjasd;flkjasd;lkdfjkakls;dfjkl;asdjfkl;asdjfl;kasdjadsfkl;asjdfl;kajadjs;flkjasdl;fklf;jas;dlkjf;alskdjdfakl;sddfjsakls;djfjl;aksdadfjsl;kasdjadsfl;kasdadfjskl;asjdfl;kasdjfl;kasdjfl;kasjdfl;kasjdfkl;asjdfl;kasjdfl;kasjdfl;kasjdfkl;ajsdl;kfkl;jsadkl;fjklasl;dkfjals;kdfjals;kdjfals;kdfalksjdflkajsd;lkfjasl;dkdfjk;alskdjdfjal;skjdfl;askjdfl;aksjdfakl;sdjfkl;asjdfkl;asjdfl;kajsdfl;kajsdfl;kajsdl;ffkl;jasdl;kkl;dfjadls;kdfjkals;kdjkadfsal;ksdjdfal;skddfjal;skdfjal;skdjfal;ksdfjakls;djdfakls;dfjl;askdfjal;skdjfakls;dfjkajsd;lfkjals;kddfjkl;asdadjsf;lkasjdfl;kasjdf;lkajsd;flkjasd;flkjasd;lkdfjkakls;dfjkl;asdjfkl;asdjfl;kasdjadsfkl;asjdfl;kajadjs;flkjasdl;fklf;jas;dlkjf;alskdjdfakl;sddfjsakls;djfjl;aksdadfjsl;kasdjadsfl;kasdadfjskl;asjdfl;kasdjfl;kasdjfl;kasjdfl;kasjdfkl;asjdfl;kasjdfl;kasjdfl;kasjdfkl;ajsdl;kfkl;jsadkl;fjklasl;dkfjals;kdfjals;kdjfals;kdfalksjdflkajsd;lkfjasl;dkdfjk;alskdjdfjal;skjdfl;askjdfl;aksjdfakl;sdjfkl;asjdfkl;asjdfl;kajsdfl;kajsdfl;kajsdl;ffkl;jasdl;kkl;dfjadls;kdfjkals;kdjkadfsal;ksdjdfal;skddfjal;skdfjal;skdjfal;ksdfjakls;djdfakls;dfjl;askdfjal;skdjfakls;dfjkajsd;lfkjals;kddfjkl;asdadjsf;lkasjdfl;kasjdf;lkajsd;flkjasd;flkjasd;lkdfjkakls;dfjkl;asdjfkl;asdjfl;kasdjadsfkl;asjdfl;kajadjs;flkjasdl;fklf;jas;dlkjf;alskdjdfakl;sddfjsakls;djfjl;aksdadfjsl;kasdjadsfl;kasdadfjskl;asjdfl;kasdjfl;kasdjfl;kasjdfl;kasjdfkl;asjdfl;kasjdfl;kasjdfl;kasjdfkl;ajsdl;kfkl;jsadkl;fjklasl;dkfjals;kdfjals;kdjfals;kdfalksjdflkajsd;lkfjasl;dkdfjk;alskdjdfjal;skjdfl;askjdfl;aksjdfakl;sdjfkl;asjdfkl;asjdfl;kajsdfl;kajsdfl;kajsdl;ffkl;jasdl;kkl;dfjadls;kdfjkals;kdjkadfsal;ksdjdfal;skddfjal;skdfjal;skdjfal;ksdfjakls;djdfakls;dfjl;askdfjal;skdjfakls;dfjkajsd;lfkjals;kddfjkl;asdadjsf;lkasjdfl;kasjdf;lkajsd;flkjasd;flkjasd;lkdfjkakls;dfjkl;asdjfkl;asdjfl;kasdjadsfkl;asjdfl;kajadjs;flkjasdl;fklf;jas;dlkjf;alskdjdfakl;sddfjsakls;djfjl;aksdadfjsl;kasdjadsfl;kasdadfjskl;asjdfl;kasdjfl;kasdjfl;kasjdfl;kasjdfkl;asjdfl;kasjdfl;kasjdfl;kasjdfkl;ajsdl;kfkl;jsadkl;fjklasl;dkfjals;kdfjals;kdjfals;kdfalksjdflkajsd;lkfjasl;dkdfjk;alskdjdfjal;skjdfl;askjdfl;aksjdfakl;sdjfkl;asjdfkl;asjdfl;kajsdfl;kajsdfl;kajsdl;ffkl;jasdl;kkl;dfjadls;kdfjkals;kdjkadfsal;ksdjdfal;skddfjal;skdfjal;skdjfal;ksdfjakls;djdfakls;dfjl;askdfjal;skdjfakls;dfjkajsd;lfkjals;kddfjkl;asdadjsf;lkasjdfl;kasjdf;lkajsd;flkjasd;flkjasd;lkdfjkakls;dfjkl;asdjfkl;asdjfl;kasdjadsfkl;asjdfl;kajadjs;flkjasdl;fklf;jas;dlkjf;alskdjdfakl;sddfjsakls;djfjl;aksdadfjsl;kasdjadsfl;kasdadfjskl;asjdfl;kasdjfl;kasdjfl;kasjdfl;kasjdfkl;asjdfl;kasjdfl;kasjdfl;kasjdfkl;ajsdl;kfkl;jsadkl;fjklasl;dkfjals;kdfjals;kdjfals;kdfalksjdflkajsd;lkfjasl;dkdfjk;alskdjdfjal;skjdfl;askjdfl;aksjdfakl;sdjfkl;asjdfkl;asjdfl;kajsdfl;kajsdfl;kajsdl;ffkl;jasdl;kkl;dfjadls;kdfjkals;kdjkadfsal;ksdjdfal;skddfjal;skdfjal;skdjfal;ksdfjakls;djdfakls;dfjl;askdfjal;skdjfakls;dfjkajsd;lfkjals;kddfjkl;asdadjsf;lkasjdfl;kasjdf;lkajsd;flkjasd;flkjasd;lkdfjkakls;dfjkl;asdjfkl;asdjfl;kasdjadsfkl;asjdfl;kajadjs;flkjasdl;fklf;jas;dlkjf;alskdjdfakl;sddfjsakls;djfjl;aksdadfjsl;kasdjadsfl;kasdadfjskl;asjdfl;kasdjfl;kasdjfl;kasjdfl;kasjdfkl;asjdfl;kasjdfl;kasjdfl;kasjdfkl;ajsdl;kfkl;jsadkl;fjklasl;dkfjals;kdfjals;kdjfals;kdfalksjdflkajsd;lkfjasl;dkdfjk;alskdjdfjal;skjdfl;askjdfl;aksjdfakl;sdjfkl;asjdfkl;asjdfl;kajsdfl;kajsdfl;kajsdl;ffkl;jasdl;kkl;dfjadls;kdfjkals;kdjkadfsal;ksdjdfal;skddfjal;skdfjal;skdjfal;ksdfjakls;djdfakls;dfjl;askdfjal;skdjfakls;dfjkajsd;lfkjals;kddfjkl;asdadjsf;lkasjdfl;kasjdf;lkajsd;flkjasd;flkjasd;lkdfjkakls;dfjkl;asdjfkl;asdjfl;kasdjadsfkl;asjdfl;kajadjs;flkjasdl;fklf;jas;dlkjf;alskdjdfakl;sddfjsakls;djfjl;aksdadfjsl;kasdjadsfl;kasdadfjskl;asjdfl;kasdjfl;kasdjfl;kasjdfl;kasjdfkl;asjdfl;kasjdfl;kasjdfl;kasjdfkl;ajsdl;kfkl;jsadkl;fjklasl;dkfjals;kdfjals;kdjfals;kdfalksjdflkajsd;lkfjasl;dkdfjk;alskdjdfjal;skjdfl;askjdfl;aksjdfakl;sdjfkl;asjdfkl;asjdfl;kajsdfl;kajsdfl;kajsdl;ffkl;jasdl;kkl;dfjadls;kdfjkals;kdjkadfsal;ksdjdfal;skddfjal;skdfjal;skdjfal;ksdfjakls;djdfakls;dfjl;askdfjal;skdjfakls;dfj - End", "Ok", "Cancel");
+ };
+
+ Content = btn;
+ }
+
+
+
+ protected override void OnAppearing () {
+
+ base.OnAppearing ();
+ }
+
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1914.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1914.cs
new file mode 100644
index 00000000..ebdbbd23
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1914.cs
@@ -0,0 +1,27 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 1914, "Android rotation ignores anchor", PlatformAffected.Android)]
+ public class Issue1914 : ContentPage
+ {
+ public Issue1914 ()
+ {
+ Content = new Rotator ();
+ }
+
+ class Rotator : AbsoluteLayout
+ {
+ public Rotator ()
+ {
+ var image = new Image {Aspect = Aspect.AspectFit, Source = "bank.png"};
+ Children.Add (image, new Rectangle (.5,0,100,100), AbsoluteLayoutFlags.All);
+ VerticalOptions = HorizontalOptions = LayoutOptions.Center;
+ image.RotateTo (3600, 10000);
+ }
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue194.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue194.cs
new file mode 100644
index 00000000..d53becb7
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue194.cs
@@ -0,0 +1,72 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 194, "iOS tab edit has no done button to return", PlatformAffected.iOS)]
+ public class Issue194 : TabbedPage
+ {
+ public Issue194 ()
+ {
+ Title = "Issue 194";
+
+ var leavePageBtn = new Button {
+ Text = "Leave"
+ };
+
+ // May have unexpected behavior but navigation page is needed to replicate the bug.
+ leavePageBtn.Clicked += (s, e) => Navigation.PopModalAsync ();
+
+ var pageOne = new ContentPage {
+ Title = "Page 1",
+ Content = leavePageBtn
+ };
+ var pageTwo = new ContentPage {
+ Title = "Page 2"
+ };
+ var pageThree = new ContentPage {
+ Title = "Page 3"
+ };
+ var pageFour = new ContentPage {
+ Title = "Page 4"
+ };
+ var pageFive = new ContentPage {
+ Title = "Page 5"
+ };
+ var pageSix = new ContentPage {
+ Title = "Page 6"
+ };
+ var pageSeven = new ContentPage {
+ Title = "Page 7"
+ };
+ var pageEight = new ContentPage {
+ Title = "Page 8"
+ };
+ var pageNine = new ContentPage {
+ Title = "Page 9"
+ };
+
+ Device.OnPlatform (iOS: () => {
+ // Create an overflow amount of tabs depending on device
+ if (Device.Idiom == TargetIdiom.Tablet) {
+ Children.Add (pageOne);
+ Children.Add (pageTwo);
+ Children.Add (pageThree);
+ Children.Add (pageFour);
+ Children.Add (pageFive);
+ Children.Add (pageSix);
+ Children.Add (pageSeven);
+ Children.Add (pageEight);
+ Children.Add (pageNine);
+ } else {
+ Children.Add (pageOne);
+ Children.Add (pageTwo);
+ Children.Add (pageThree);
+ Children.Add (pageFour);
+ Children.Add (pageFive);
+ Children.Add (pageSix);
+ }
+ });
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue198.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue198.cs
new file mode 100644
index 00000000..099ea3f9
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue198.cs
@@ -0,0 +1,78 @@
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 198, "TabbedPage shouldn't proxy content of NavigationPage", PlatformAffected.iOS)]
+ public class Issue198 : TestTabbedPage
+ {
+ protected override void Init ()
+ {
+ Title = "Tabbed Navigation Page";
+
+ var leavePageBtn = new Button {
+ Text = "Leave"
+ };
+
+ // Should work as expected, however, causes NRE
+ leavePageBtn.Clicked += (s, e) => Navigation.PopModalAsync ();
+
+ var navigationPageOne = new NavigationPage (new ContentPage {
+ Icon = "calculator.png",
+ Content = leavePageBtn
+ }) {
+ Title = "Page One",
+ };
+ var navigationPageTwo = new NavigationPage (new ContentPage {
+ Icon = "calculator.png",
+ }) {
+ Title = "Page Two",
+ };
+ var navigationPageThree = new NavigationPage (new ContentPage {
+ Title = "No Crash",
+ }) {
+ Title = "Page Three",
+ Icon = "calculator.png"
+ };
+ var navigationPageFour = new NavigationPage (new ContentPage ()) {
+ Title = "Page Four",
+ Icon = "calculator.png"
+ };
+
+ Children.Add (navigationPageOne);
+ Children.Add (navigationPageTwo);
+ Children.Add (navigationPageThree);
+ Children.Add (navigationPageFour);
+ }
+
+#if UITEST
+ [Test]
+ [UiTest (typeof(TabbedPage))]
+ public void Issue198TestsNREWithPopModal ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Page One"));
+ RunningApp.WaitForElement (q => q.Button ("Leave"));
+ RunningApp.Screenshot ("All Elements Present");
+
+ RunningApp.Tap (q => q.Marked ("Leave"));
+ RunningApp.Screenshot ("Clicked Leave");
+
+ RunningApp.WaitForElement (q => q.Marked ("Bug Repro's"));
+ RunningApp.Tap (q => q.Marked ("SearchButton"));
+ RunningApp.Screenshot ("Navigate into gallery again");
+
+ RunningApp.WaitForElement (q => q.Marked ("Page Three"));
+ RunningApp.Tap (q => q.Marked ("Page Three"));
+
+ RunningApp.WaitForElement (q => q.Marked ("No Crash"));
+ RunningApp.Screenshot ("App did not crash");
+ }
+#endif
+
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue206.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue206.cs
new file mode 100644
index 00000000..96ab9095
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue206.cs
@@ -0,0 +1,143 @@
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 206, "ViewCell with Label's text does not resize when value is changed", PlatformAffected.iOS)]
+ public class Issue206 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ _listScreen = new Issue206ListScreen ();
+ Title = "Click 9";
+ Content = _listScreen.View;
+ }
+
+ Issue206ListScreen _listScreen;
+
+#if UITEST
+ [Test]
+ [NUnit.Framework.Category ("ManualReview")]
+ [UiTest (typeof(ViewCell))]
+ public void Issue206TestsTextInTextCellResizes ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Click 9"));
+ RunningApp.WaitForElement (q => q.Marked ("0"));
+ RunningApp.WaitForElement (q => q.Marked ("1"));
+ RunningApp.WaitForElement (q => q.Marked ("2"));
+
+ RunningApp.Screenshot ("All elements exist");
+
+ var scrollRect = RunningApp.Query (q => q.Raw ("* index:0"))[0].Rect;
+ Xamarin.Forms.Core.UITests.Gestures.ScrollForElement (RunningApp, "* marked:'9'", new Xamarin.Forms.Core.UITests.Drag (scrollRect, Xamarin.Forms.Core.UITests.Drag.Direction.BottomToTop, Xamarin.Forms.Core.UITests.Drag.DragLength.Long));
+ RunningApp.Screenshot ("I see 9");
+
+ RunningApp.Tap (q => q.Marked ("9"));
+ RunningApp.WaitForNoElement (q => q.Marked ("9"));
+
+ RunningApp.Screenshot ("The text should not be cropped");
+ }
+#endif
+
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Issue206ListScreen
+ {
+ public ListView View { get; private set; }
+
+ internal class A : INotifyPropertyChanged
+ {
+ string _text;
+ public string Text {
+ get {
+ return _text;
+ }
+ set {
+ _text = value;
+ if(PropertyChanged != null)
+ PropertyChanged(this, new PropertyChangedEventArgs("Text"));
+ }
+ }
+
+ #region INotifyPropertyChanged implementation
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ #endregion
+ }
+
+ [Preserve (AllMembers = true)]
+ internal class ViewCellTest : ViewCell
+ {
+ static int s_inc = 0;
+
+ public ViewCellTest ()
+ {
+ var stackLayout = new StackLayout {
+ Orientation = StackOrientation.Horizontal
+ };
+
+ var label = new Label ();
+ label.SetBinding (Label.TextProperty, "Text");
+
+ var box = new BoxView {WidthRequest = 100, HeightRequest = 10, Color = Color.Red};
+
+ stackLayout.Children.Add (label);
+ stackLayout.Children.Add (box);
+
+ View = stackLayout;
+ }
+
+ protected override void OnAppearing ()
+ {
+ base.OnAppearing ();
+ Debug.WriteLine ("Appearing: " + ((A)BindingContext).Text + " : " + s_inc);
+ s_inc++;
+ }
+
+ protected override void OnDisappearing ()
+ {
+ base.OnDisappearing ();
+ Debug.WriteLine ("Disappearing: " + ((A)BindingContext).Text + " : " + s_inc);
+ s_inc++;
+ }
+ }
+
+ public Issue206ListScreen ()
+ {
+
+ View = new ListView ();
+
+ View.RowHeight = 30;
+
+ var n = 50;
+ var items = Enumerable.Range (0, n).Select (i => new A {Text = i.ToString ()}).ToList ();
+ View.ItemsSource = items;
+
+ View.ItemTemplate = new DataTemplate (typeof (ViewCellTest));
+
+ View.ItemSelected += (sender, e) => {
+ var cell = (e.SelectedItem as A);
+ if (cell == null)
+ return;
+ var x = int.Parse (cell.Text);
+ if (x == 5) {
+ n += 10;
+ View.ItemsSource = Enumerable.Range (0, n).Select (i => new A { Text = i.ToString () }).ToList ();
+ } else {
+ cell.Text = (x + 1).ToString ();
+ }
+ };
+
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue214.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue214.cs
new file mode 100644
index 00000000..bb18f5f2
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue214.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Linq;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 214, "TextCell DetailColor change not immediate", PlatformAffected.iOS)]
+ public class Issue214 : ContentPage
+ {
+ public Issue214 ()
+ {
+ var items = Enumerable.Range (0, 50).Select (i => new TextCell {
+ Text = i.ToString (),
+ Detail = i.ToString ()
+ }).ToList ();
+
+ var tableSection = new TableSection("First Section");
+ foreach (TextCell cell in items) {
+ tableSection.Add (cell);
+ }
+
+ var tableRoot = new TableRoot () {
+ tableSection
+ };
+
+ var tableLayout = new TableView {
+ Root = tableRoot
+ };
+
+ tableLayout.Intent = TableIntent.Data;
+ Content = tableLayout;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2143.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2143.cs
new file mode 100644
index 00000000..8bad724e
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2143.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2143, "Picker on windows phone",PlatformAffected.WinPhone)]
+ public class Issue2143 : ContentPage
+ {
+ public Issue2143 ()
+ {
+ var table = GetTableView ();
+ var list = GetListView ();
+ Content = list;
+ }
+
+ static ListView GetListView ()
+ {
+ var listView = new ListView ();
+ listView.ItemTemplate = new DataTemplate (typeof (PickerCell));
+ listView.ItemsSource = new[] { "one", "two", "three" }; ;
+ return listView;
+ }
+
+ static TableView GetTableView ()
+ {
+ var tableSection = new TableSection ("Picker");
+ tableSection.Add (new PickerCell ());
+ var root = new TableRoot ("Root");
+ root.Add (tableSection);
+ var table = new TableView (root);
+ return table;
+ }
+ }
+
+ internal class PickerCell : ViewCell
+ {
+ public PickerCell ()
+ {
+ var picker = new Picker { Title ="Select Level of Activity." };
+ picker.Items.Add ("Sedentary");
+ picker.Items.Add ("Moderate");
+ picker.Items.Add ("Active");
+ picker.Items.Add ("None");
+ picker.SelectedIndex = 0;
+ View = picker;
+ }
+ }
+
+
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2191.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2191.cs
new file mode 100644
index 00000000..b334030f
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2191.cs
@@ -0,0 +1,51 @@
+using System;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2191, "ToolBarItem not showing as disabled when CanExecute is set to false", PlatformAffected.Android)]
+ public class Issue2191 : ContentPage
+ {
+ public Issue2191 ()
+ {
+ var stackPanel = new StackLayout { VerticalOptions = LayoutOptions.End };
+ var button = new Button { Text = "Disable" };
+ var button1 = new Button { Text = "Enable" };
+ button1.Clicked+= (sender, e) => {
+ _dummyResult = true;
+ PunchSubmitCommand.ChangeCanExecute();
+ };
+ var tbItem = new ToolbarItem { Icon = "menuIcon.png" };
+ var tbItem2 = new ToolbarItem { Icon = "menuIcon.png", Text="submit" };
+ button.SetBinding (Button.CommandProperty, new Binding ("PunchSubmitCommand"));
+ tbItem.SetBinding (MenuItem.CommandProperty, new Binding ("PunchSubmitCommand"));
+ tbItem2.SetBinding (MenuItem.CommandProperty, new Binding ("PunchSubmitCommand"));
+ button.BindingContext = tbItem.BindingContext = tbItem2.BindingContext = this;
+ ToolbarItems.Add(tbItem);
+ var toolbar = new Toolbar { BackgroundColor = Color.Red };
+ toolbar.Add (tbItem2);
+ stackPanel.Children.Add (toolbar);
+ stackPanel.Children.Add (button);
+ stackPanel.Children.Add (button1);
+ Content = stackPanel;
+ }
+
+ bool _dummyResult = true;
+
+ Command _punchSubmitCommand;
+ public Command PunchSubmitCommand
+ {
+ get
+ {
+ return _punchSubmitCommand ?? (_punchSubmitCommand = new Command(() => {
+ _dummyResult = !_dummyResult;
+ PunchSubmitCommand.ChangeCanExecute();
+ },
+ () => _dummyResult));
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2222.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2222.cs
new file mode 100644
index 00000000..aa4e19e8
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2222.cs
@@ -0,0 +1,49 @@
+using System;
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2222, "NavigationBar.ToolbarItems.Add() crashes / breaks app in iOS7. works fine in iOS8", PlatformAffected.iOS)]
+ public class Issue2222 : TestNavigationPage
+ {
+ protected override void Init ()
+ {
+ var tbItem = new ToolbarItem { Text = "hello", Icon="wrongName" };
+ ToolbarItems.Add(tbItem);
+
+ PushAsync (new Issue22221 ());
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Issue22221 : ContentPage
+ {
+ public Issue22221 ()
+ {
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = "Hello Toolbaritem" }
+ }
+ };
+ }
+ }
+
+#if UITEST
+ [Test]
+ public void TestItDoesntCrashWithWrongIconName ()
+ {
+ RunningApp.WaitForElement(c=>c.Marked("Hello Toolbaritem"));
+ RunningApp.Screenshot ("Was label on page shown");
+ }
+#endif
+
+ }
+}
+
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue22246_BZ.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue22246_BZ.cs
new file mode 100644
index 00000000..30985085
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue22246_BZ.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Bugzilla, 22246, "Entry in Grid nested in ViewCell isn't expanding", PlatformAffected.WinPhone, NavigationBehavior.PushModalAsync)]
+ public class Issue22246Bz : ContentPage
+ {
+ public Issue22246Bz()
+ {
+ var table = new TableView {
+ Root = new TableRoot {
+ new TableSection("Testing Section") {
+ new ViewCell {
+ View = CreateBugView()
+ }
+ }
+ }
+ };
+
+ var layout = new StackLayout {
+ Children = {
+ CreateBugView(),
+ table
+ }
+ };
+
+ Content = layout;
+ }
+
+ View CreateBugView()
+ {
+ return new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Spacing = 10,
+ Children = {
+ new Entry {Placeholder = "Entry", HorizontalOptions = LayoutOptions.FillAndExpand},
+ new Button {Text = "Button"}
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2241.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2241.cs
new file mode 100644
index 00000000..5bd750b3
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2241.cs
@@ -0,0 +1,58 @@
+using System;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+using Xamarin.UITest.Android;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2241, "ScrollView content can become stuck on orientation change (iOS)", PlatformAffected.iOS)]
+ public class Issue2241 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ ScrollView scrollView = new ScrollView () {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Padding = new Thickness (20),
+ Content = new BoxView () {
+ Color = Color.Red,
+ HeightRequest = 400,
+ HorizontalOptions = LayoutOptions.FillAndExpand
+ }
+ };
+
+ Content = scrollView;
+ }
+
+#if UITEST
+ [Test]
+ [Ignore("Fails intermittently on TestCloud")]
+ public void ChangeOrientationCheckScroll ()
+ {
+ var isAndroid = RunningApp is AndroidApp;
+ var className = "Xamarin_Forms_Platform_iOS_BoxRenderer";
+ if (isAndroid) {
+ className = "BoxRenderer";
+ }
+ var box1 = RunningApp.Query (c => c.Class (className)) [0];
+ RunningApp.SetOrientationLandscape ();
+ RunningApp.ScrollDown ();
+ RunningApp.SetOrientationPortrait ();
+ var box2 = RunningApp.Query (c => c.Class (className)) [0];
+ RunningApp.Screenshot ("Did it resize ok? Do you see some white on the bottom?");
+ if (!isAndroid) {
+ Assert.AreEqual (box1.Rect.CenterY, box2.Rect.CenterY);
+ }
+ }
+#endif
+ }
+}
+
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2248.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2248.cs
new file mode 100644
index 00000000..3d224f65
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2248.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2248, "ListView.ScrollTo crashes app", PlatformAffected.WinPhone)]
+ public class Issue2248 : ContentPage
+ {
+ ObservableCollection<Item> _items;
+
+ public Issue2248()
+ {
+ _items = new ObservableCollection<Item>()
+ {
+ new Item() {Id = 1, Name = "First"},
+ new Item() {Id = 2, Name = "Second"},
+ new Item() {Id = 3, Name = "Third"},
+ new Item() {Id = 4, Name = "Fourth"},
+ new Item() {Id = 5, Name = "Fifth"}
+ };
+
+
+ var listView = new ListView()
+ {
+ ItemsSource = _items,
+ ItemTemplate = new DataTemplate(typeof (ItemCell))
+ };
+
+ Content = listView;
+ }
+
+ public void RemoveItemFromCollection(Item item)
+ {
+ _items.Remove(item);
+ }
+ public class Item
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ }
+
+ public class ItemCell : ViewCell
+ {
+ public ItemCell()
+ {
+ var nameLabel = new Label();
+ nameLabel.SetBinding(Label.TextProperty, "Name");
+ nameLabel.GestureRecognizers.Add(new TapGestureRecognizer()
+ {
+ Command = new Command(DeleteItem),
+ NumberOfTapsRequired = 1
+ });
+
+ View = nameLabel;
+ }
+
+ void DeleteItem()
+ {
+ var parent = Parent.Parent as Issue2248;
+
+ if (parent != null)
+ {
+ parent.RemoveItemFromCollection((Item) BindingContext);
+ }
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2259.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2259.cs
new file mode 100644
index 00000000..125f1a60
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2259.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Collections.ObjectModel;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2259, "ListView.ScrollTo crashes app", PlatformAffected.iOS)]
+ public class Issue2259 : TestContentPage
+ {
+ [Preserve (AllMembers = true)]
+ public class Person
+ {
+ public string Name { private set; get; }
+
+ public DateTime Birthday { private set; get; }
+
+ public Color FavoriteColor { private set; get; }
+
+ public Person (string name, DateTime birthday, Color favoriteColor)
+ {
+ Name = name;
+ Birthday = birthday;
+ FavoriteColor = favoriteColor;
+ }
+ };
+
+ int _count = 1;
+
+ protected override void Init ()
+ {
+ var people = new ObservableCollection<Person> {
+ new Person ("Abigail", new DateTime (1975, 1, 15), Color.Aqua),
+ new Person ("Bob", new DateTime (1976, 2, 20), Color.Black),
+ new Person ("Cathy", new DateTime (1977, 3, 10), Color.Blue),
+ new Person ("David", new DateTime (1978, 4, 25), Color.Fuschia),
+ };
+
+ var buttonAdd = new Button {
+ Text = "Add",
+ HorizontalOptions = LayoutOptions.Start,
+ VerticalOptions = LayoutOptions.Center,
+ };
+
+ var buttonRemove = new Button {
+ Text = "Remove",
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.Center,
+ };
+
+ var buttonScrollToBottom = new Button {
+ Text = "Bottom",
+ HorizontalOptions = LayoutOptions.Start,
+ VerticalOptions = LayoutOptions.Center,
+ };
+
+ var buttonStack = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ buttonAdd,
+ buttonRemove,
+ buttonScrollToBottom,
+ }
+ };
+
+ var listView = new ListView {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ ItemsSource = people,
+ ItemTemplate = new DataTemplate (() =>
+ {
+ var nameLabel = new Label ();
+ var birthdayLabel = new Label ();
+ var boxView = new BoxView ();
+
+ var stack = new StackLayout {
+ Padding = new Thickness (0, 5),
+ Orientation = StackOrientation.Horizontal,
+ BackgroundColor = Color.Black,
+ Children = {
+ boxView,
+ new StackLayout {
+ VerticalOptions = LayoutOptions.Center,
+ Spacing = 0,
+ Children = {
+ nameLabel,
+ birthdayLabel
+ }
+ }
+ }
+ };
+
+ nameLabel.SetBinding (Label.TextProperty, "Name");
+ birthdayLabel.SetBinding (Label.TextProperty, new Binding ("Birthday", BindingMode.OneWay, null, null, "Born {0:d}"));
+ boxView.SetBinding (BoxView.ColorProperty, "FavoriteColor");
+ stack.SetBinding (BackgroundColorProperty, "BackgroundColor");
+
+ return new ViewCell {
+ View = stack
+ };
+ })
+ };
+
+ buttonAdd.Clicked += (sender, e) =>
+ {
+ var person = new Person (string.Format ("Name {0}", _count++), DateTime.Today, Color.Blue);
+
+ people.Add (person);
+
+ listView.ScrollTo (person, ScrollToPosition.End, true);
+
+ };
+
+ buttonRemove.Clicked += (sender, e) => people.RemoveAt (people.Count - 1);
+
+ buttonScrollToBottom.Clicked += (sender, e) =>
+ {
+ var person = people[people.Count - 1];
+
+ listView.ScrollTo (person, ScrollToPosition.End, true);
+ };
+
+ Padding = new Thickness (10, Device.OnPlatform (20, 0, 0), 10, 5);
+
+ Content = new StackLayout {
+ Orientation = StackOrientation.Vertical,
+ Children = {
+ buttonStack,
+ listView,
+ }
+ };
+ }
+
+#if UITEST
+ [Test]
+ [UiTest (typeof(ListView), "ScrollTo")]
+ public void Issue2259Tests ()
+ {
+ for (int i = 0; i < 20; i++) {
+ RunningApp.Tap (q => q.Button ("Add"));
+ RunningApp.WaitForElement (q => q.Marked ("Name " + (i + 1).ToString ()));
+ RunningApp.Screenshot ("Added Cell");
+ }
+ }
+#endif
+ }
+}
+
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2266.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2266.cs
new file mode 100644
index 00000000..06330460
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2266.cs
@@ -0,0 +1,162 @@
+using System;
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2266, "Setting a different Detail page from a MasterDetailPage after 2nd time on MainPage", PlatformAffected.iOS, NavigationBehavior.SetApplicationRoot)]
+ public class Issue2266 : ContentPage
+ {
+ public Issue2266 ()
+ {
+ InitPageContent ();
+ }
+
+ void InitPageContent ()
+ {
+ var labelHeader = new Label {
+ Text = "Select a test",
+ FontSize = 30,
+ FontAttributes = FontAttributes.Bold,
+ VerticalOptions = LayoutOptions.Center,
+ HorizontalOptions = LayoutOptions.CenterAndExpand
+ };
+
+ string[] listItems = {
+ "MasterDetail Navigation",
+ "MasterDetail Navigation ->> Page 1",
+ "MasterDetail Navigation ->> Page 2",
+ "MasterDetail Navigation ->> Page 3"
+ };
+
+ var listView = new ListView {
+ ItemsSource = listItems
+ };
+
+ Content = new StackLayout {
+ Padding = new Thickness (0, 20, 0, 0),
+ Children = {
+ labelHeader,
+ listView
+ }
+ };
+
+ listView.ItemSelected += delegate(object sender, SelectedItemChangedEventArgs e) {
+ if (e.SelectedItem == null)
+ return;
+ if (e.SelectedItem.Equals (listItems [0])) {
+ Application.Current.MainPage = MasterDetailHost;
+ } else if (e.SelectedItem.Equals (listItems [1]) || e.SelectedItem.Equals (listItems [2]) || e.SelectedItem.Equals (listItems [3])) {
+ // MasterDetail Navigation - direct page open
+ var item = e.SelectedItem.ToString ();
+ var index = int.Parse (item.Substring (item.Length - 1)) - 1;
+ Application.Current.MainPage = MasterDetailHost;
+ MasterDetailHost.OpenPage (index);
+ }
+
+ listView.SelectedItem = null;
+ };
+ }
+
+ static MasterDetailNavigation s_masterDetailHost;
+
+ public static MasterDetailNavigation MasterDetailHost {
+ get {
+ if (s_masterDetailHost == null)
+ s_masterDetailHost = new MasterDetailNavigation ();
+ return s_masterDetailHost;
+ }
+ }
+
+ }
+
+ public class MasterDetailNavigation : MasterDetailPage
+ {
+ List<NavigationPage> _pages;
+
+ public MasterDetailNavigation ()
+ {
+ InitPages ();
+
+ var menuList = new ListView {
+ BackgroundColor = Color.Transparent,
+ ItemsSource = _pages,
+ ItemTemplate = new DataTemplate (typeof(TextCell))
+ };
+ menuList.ItemTemplate.SetBinding (TextCell.TextProperty, "Title");
+
+ Master = new ContentPage {
+ BackgroundColor = Color.FromHex ("363636"),
+ Title = "Menu",
+ Content = menuList
+ };
+
+ Detail = new NavigationPage (new ContentPage {
+ Padding = new Thickness (20, 20),
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = "Select a menu item" }
+ }
+ }
+ });
+
+ menuList.ItemSelected += (sender, e) => {
+ var page = e.SelectedItem as NavigationPage;
+ if (page != null) {
+ Detail = page;
+ IsPresented = false;
+ }
+ };
+ }
+
+ void InitPages ()
+ {
+ _pages = new List<NavigationPage> ();
+
+ for (int i = 1; i <= 10; i++) {
+ var btnSubPage = new Button {
+ Text = string.Format ("Open sub-page"),
+ };
+ btnSubPage.Clicked += delegate {
+ OpenSubPage (string.Format ("Sub for page: {0}", i));
+ };
+ var page = new ContentPage {
+ Padding = new Thickness (20, 20),
+ Title = string.Format ("Page {0}", i),
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = string.Format ("Page {0}", i) },
+ btnSubPage
+ }
+ }
+ };
+ page.ToolbarItems.Add (new ToolbarItem ("START", null, delegate {
+ Application.Current.MainPage = App.MenuPage;
+ }));
+ _pages.Add (new NavigationPage (page) { Title = page.Title });
+ }
+ }
+
+ public void OpenPage (int index)
+ {
+ if (index >= _pages.Count) {
+ // Index out of range
+ return;
+ }
+ Detail = _pages [index];
+ }
+
+ async void OpenSubPage (string text)
+ {
+ await Detail.Navigation.PushAsync (new ContentPage {
+ Content = new Label { Text = text }
+ });
+ }
+ }
+#endif
+}
+
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2270.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2270.cs
new file mode 100644
index 00000000..1c2a3a33
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2270.cs
@@ -0,0 +1,77 @@
+using System.Collections.ObjectModel;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2270, "NSInternalCOnsistencyException when bound to ObservableCollection", PlatformAffected.iOS)]
+ public class Issue2270 : ContentPage
+ {
+ public Issue2270()
+ {
+ BindingContext = new TestListViewModel();
+
+ Padding = new Thickness(0, 40, 0, 0);
+
+ var btn = new Button {
+ Text = "Load Data",
+ BorderWidth = 1,
+ BorderColor = Color.Gray,
+ };
+ btn.SetBinding (Button.CommandProperty, "LoadDataCommand");
+
+ var lv = new ListView();// { IsGroupingEnabled = true };
+
+ var dt = new DataTemplate (typeof(TextCell));
+ dt.SetBinding (TextCell.TextProperty, "Name");
+
+ lv.ItemTemplate = dt;
+ lv.SetBinding (ListView.ItemsSourceProperty, "Rows");
+
+ Content = new StackLayout {
+ Children = {
+ btn,
+ lv
+ }
+ };
+
+ }
+
+ public class TestListViewModel
+ {
+ //public ObservableCollection<ObservableCollection<Row>> Rows {
+ public ObservableCollection<Row> Rows {
+ get;
+ set;
+ }
+
+ public TestListViewModel ()
+ {
+ //Rows = new ObservableCollection<ObservableCollection<Row>>();
+ Rows = new ObservableCollection<Row>();
+ }
+
+ Command _command;
+
+ public Command LoadDataCommand {
+ get {
+ return _command ?? (_command = new Command (LoadData));
+ }
+ }
+
+ void LoadData() {
+ Rows.Clear ();
+
+ foreach (var row in new[] { new Row { Name = "one" }, new Row { Name = "Two" } }) {
+ Rows.Add (row);
+ }
+ }
+
+ }
+
+ public class Row
+ {
+ public string Name { get; set; }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2272.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2272.cs
new file mode 100644
index 00000000..7f6c50ad
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2272.cs
@@ -0,0 +1,54 @@
+using System;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest.Android;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2272, "Entry text updating set focus on the beginning of text not the end of it", PlatformAffected.Android)]
+ public class Issue2272 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var userNameEditor = new Entry () { Text = "userNameEditorEmptyString" };
+ userNameEditor.Focused += (sender, args) => {
+ userNameEditor.Text = "focused";
+ };
+
+ Content = new StackLayout {
+ Spacing = 10,
+ VerticalOptions = LayoutOptions.Start,
+ Children = { userNameEditor }
+ };
+ }
+
+#if UITEST
+ [Test]
+ public void TestFocusIsOnTheEndAfterSettingText ()
+ {
+ RunningApp.Tap (c => c.Marked ("userNameEditorEmptyString"));
+ RunningApp.EnterText ("1");
+ PressEnter ();
+ Assert.Greater (RunningApp.Query (c => c.Marked ("focused1")).Length, 0);
+ }
+
+ void PressEnter ()
+ {
+ var androidApp = RunningApp as AndroidApp;
+ if (androidApp != null) {
+ androidApp.PressUserAction (UserAction.Done);
+ }
+ else {
+ RunningApp.PressEnter ();
+ }
+ }
+#endif
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2282.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2282.xaml
new file mode 100644
index 00000000..32850bed
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2282.xaml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.TestCasesPages.Issue2282">
+ <Grid>
+
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+
+ <Grid.RowDefinitions>
+ <RowDefinition Height="*" />
+ <RowDefinition Height="100" />
+ </Grid.RowDefinitions>
+ <ListView x:Name="MyListView"
+ RowHeight="80"
+ ItemsSource="{Binding }">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <ViewCell.View>
+ <Label Text="{Binding }"
+ TextColor="Green"
+ Font="28" />
+ </ViewCell.View>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ <Label Grid.Row="1" x:Name="LogLabel" Font="28" Text="XXX" TextColor="Red" />
+ </Grid>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2282.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2282.xaml.cs
new file mode 100644
index 00000000..63b134ff
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2282.xaml.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2282, "ListView ItemTapped issue on Windows phone", PlatformAffected.WinPhone)]
+ public partial class Issue2282 : ContentPage
+ {
+ public Issue2282 ()
+ {
+ Items = new ObservableCollection<string>();
+ InitializeComponent();
+
+ BindingContext = Items;
+ MyListView.ItemTapped += (sender, e) => {
+ LogLabel.Text = string.Format("{0} - Item {1} Tapped!", _counter++, (string)e.Item);
+ };
+ }
+
+ public ObservableCollection<string> Items { get; set; }
+
+ int _counter = 0;
+
+ protected override void OnAppearing()
+ {
+ Items.Add("First");
+ Items.Add("Second");
+ Items.Add("Third");
+ base.OnAppearing();
+ }
+ }
+#endif
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2288.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2288.xaml
new file mode 100644
index 00000000..40f4b833
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2288.xaml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Forms.Controls.Issue2288">
+ <ContentPage.ToolbarItems>
+ <ToolbarItem Text="{Binding MainText}" Command="{Binding MainTextCommand}" />
+ <ToolbarItem Text="{Binding MainText}" Command="{Binding MainTextCommand}" Order="Secondary"/>
+ </ContentPage.ToolbarItems>
+ <StackLayout>
+ <Label Text="{Binding MainText}" VerticalOptions="Center" HorizontalOptions="Center" />
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2288.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2288.xaml.cs
new file mode 100644
index 00000000..fa9d45c9
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2288.xaml.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using System.ComponentModel;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2288, "ToolbarItem.Text change", PlatformAffected.iOS | PlatformAffected.Android)]
+ public partial class Issue2288 : ContentPage
+ {
+ int _count = 0;
+ public Issue2288 ()
+ {
+ InitializeComponent ();
+ MainText = "initial";
+ MainTextCommand = new Command(o =>
+ {
+ MainText = "changed " + _count++;
+ });
+
+ BindingContext = this;
+ }
+
+ string _mainText;
+ public string MainText {
+ get { return _mainText; }
+ set {
+ _mainText = value;
+ OnPropertyChanged ();
+ }
+ }
+
+ public Command MainTextCommand { get; set; }
+ }
+#endif
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2289.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2289.xaml
new file mode 100644
index 00000000..c4d45742
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2289.xaml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<local:TestContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Controls"
+ x:Class="Xamarin.Forms.Controls.Issue2289">
+ <local:TestContentPage.Content>
+ <TableView HasUnevenRows="true">
+ <TableView.Root>
+ <TableSection Title="TextCell Disable">
+ <TextCell Text="txtCellDisable1" Detail="test" IsEnabled="false" />
+ <TextCell Text="txtCellDisable2" Height="25" IsEnabled="false" />
+ </TableSection>
+ <TableSection Title="TextCell Enable">
+ <TextCell Text="txtCellEnable1" Detail="test" IsEnabled="true" />
+ <TextCell Text="txtCellEnable2" Height="25" IsEnabled="true" />
+ </TableSection>
+ <TableSection Title="TextCell ContextActions Disable">
+ <TextCell Text="txtCellDisableContextActions1" Detail="test" IsEnabled="false">
+ <TextCell.ContextActions>
+ <MenuItem Command="{Binding MoreCommand}" Text="More" />
+ <MenuItem Command="{Binding DeleteCommand}" Text="Delete" />
+ </TextCell.ContextActions>
+ </TextCell>
+ </TableSection>
+ <TableSection Title="TextCell ContextActions Enable">
+ <TextCell Text="txtCellEnabledContextActions1" Detail="test" IsEnabled="true">
+ <TextCell.ContextActions>
+ <MenuItem Command="{Binding MoreCommand}" Text="More" />
+ <MenuItem Command="{Binding DeleteCommand}" Text="Delete" IsDestructive="true" />
+ </TextCell.ContextActions>
+ </TextCell>
+ </TableSection>
+ </TableView.Root>
+ </TableView>
+ </local:TestContentPage.Content>
+</local:TestContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2289.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2289.xaml.cs
new file mode 100644
index 00000000..7a1cb70d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2289.xaml.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+using System.Windows.Input;
+using System.Diagnostics;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+using Xamarin.UITest.iOS;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2289, "TextCell IsEnabled property not disabling element in TableView", PlatformAffected.iOS)]
+ public partial class Issue2289 : TestContentPage
+ {
+
+#if APP
+ public Issue2289 ()
+ {
+ InitializeComponent ();
+ }
+#endif
+
+ protected override void Init ()
+ {
+ MoreCommand = new Command<MenuItem> ((menuItem) => {
+ Debug.WriteLine ("More! Command Called!");
+ });
+
+ DeleteCommand = new Command<MenuItem> ((menuItem) => {
+ Debug.WriteLine ("Delete Command Called!");
+ });
+ BindingContext = this;
+ }
+
+ public ICommand MoreCommand { get; protected set; }
+
+ public ICommand DeleteCommand { get; protected set; }
+
+#if UITEST
+ [Test]
+ [Ignore("Fails sometimes on XTC")]
+ public void TestIsEnabledFalse ()
+ {
+ if (RunningApp is iOSApp) {
+ var disable1 = RunningApp.Query (c => c.Marked ("txtCellDisable1")) [0];
+ Assert.IsFalse (disable1.Enabled);
+ var disable2 = RunningApp.Query (c => c.Marked ("txtCellDisable2")) [0];
+ Assert.IsFalse (disable2.Enabled);
+ }
+ }
+
+ [Test]
+ [Ignore("Fails sometimes on XTC")]
+ public void TestIsEnabledFalseContextActions ()
+ {
+ if (RunningApp is iOSApp) {
+ var disable1 = RunningApp.Query (c => c.Marked ("txtCellDisableContextActions1")) [0];
+ Assert.IsFalse (disable1.Enabled);
+
+ var screenBounds = RunningApp.Query (q => q.Raw ("* index:0")) [0].Rect;
+
+ if (RunningApp is iOSApp) {
+ RunningApp.DragCoordinates (screenBounds.Width - 10, disable1.Rect.CenterY, 10, disable1.Rect.CenterY);
+ } else {
+ disable1 = RunningApp.Query (c => c.Marked ("txtCellDisableContextActions1")) [0];
+ RunningApp.TouchAndHoldCoordinates (disable1.Rect.CenterX, disable1.Rect.CenterY);
+ }
+ RunningApp.Screenshot ("Not showing context menu");
+ RunningApp.WaitForNoElement (c => c.Marked ("More"));
+ RunningApp.TapCoordinates (screenBounds.CenterX, screenBounds.CenterY);
+ }
+ }
+
+ [Test]
+ [Ignore("Fails sometimes on XTC")]
+ public void TestIsEnabledTrue ()
+ {
+ if (RunningApp is iOSApp) {
+ var disable1 = RunningApp.Query (c => c.Marked ("txtCellEnable1")) [0];
+ Assert.IsTrue (disable1.Enabled);
+ var disable2 = RunningApp.Query (c => c.Marked ("txtCellEnable2")) [0];
+ Assert.IsTrue (disable2.Enabled);
+ }
+
+ }
+
+ [Test]
+ [Ignore("Fails sometimes on XTC")]
+ public void TestIsEnabledTrueContextActions ()
+ {
+ if (RunningApp is iOSApp) {
+ var disable1 = RunningApp.Query (c => c.Marked ("txtCellEnabledContextActions1")) [0];
+ Assert.IsTrue (disable1.Enabled);
+
+ var screenBounds = RunningApp.Query (q => q.Raw ("* index:0")) [0].Rect;
+
+ if (RunningApp is iOSApp) {
+ RunningApp.DragCoordinates (screenBounds.Width - 10, disable1.Rect.CenterY, 10, disable1.Rect.CenterY);
+ } else {
+ disable1 = RunningApp.Query (c => c.Marked ("txtCellEnabledContextActions1")) [0];
+ RunningApp.TouchAndHoldCoordinates (disable1.Rect.CenterX, disable1.Rect.CenterY);
+ }
+
+ RunningApp.Screenshot ("Showing context menu");
+ RunningApp.WaitForElement (c => c.Marked ("More"));
+ }
+
+ }
+#endif
+
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue229.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue229.cs
new file mode 100644
index 00000000..d0c36ac2
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue229.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Diagnostics;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 229, "ToolbarItems broken", PlatformAffected.Android)]
+ public class Issue229 : ContentPage
+ {
+ public Issue229 ()
+ {
+ Title = "I am a navigation page.";
+
+ var label = new Label {
+ Text = "I should have a toolbar item",
+ XAlign = TextAlignment.Center,
+ YAlign = TextAlignment.Center
+ };
+
+ var refreshBtn = new ToolbarItem ("Refresh", null, () => label.Text = "Clicking it works");
+
+ ToolbarItems.Add (refreshBtn);
+
+ Content = label;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2291.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2291.cs
new file mode 100644
index 00000000..febdc51b
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2291.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2291, "DatePicker.IsVisible = false issue", PlatformAffected.WinPhone)]
+ public class Issue2291 : ContentPage
+ {
+ public Issue2291 ()
+ {
+ var btnTest = new Button {
+ Text = "Fundo"
+ };
+
+ var dtPicker = new DatePicker {
+ IsVisible = false
+ };
+
+ Content = new StackLayout {
+ Children = {
+ btnTest,
+ dtPicker
+ }
+ };
+
+ btnTest.Clicked += (s, e) => {
+ dtPicker.Focus ();
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2292.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2292.cs
new file mode 100644
index 00000000..491d5fdd
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2292.cs
@@ -0,0 +1,39 @@
+using System.Diagnostics;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2292, "DatePicker not shown when .Focus() is called", PlatformAffected.WinPhone)]
+ public class Issue2292 : ContentPage
+ {
+ public Issue2292 ()
+ {
+ var datePicker = new DatePicker ();
+ var datePickerBtn = new Button {
+ Text = "Click me to call .Focus on DatePicker"
+ };
+
+ datePickerBtn.Clicked += (sender, args) => {
+ datePicker.Focus ();
+ };
+
+ var datePickerBtn2 = new Button {
+ Text = "Click me to call .Unfocus on DatePicker"
+ };
+
+ datePickerBtn2.Clicked += (sender, args) => {
+ datePicker.Unfocus ();
+ };
+
+ Content = new StackLayout {
+ Children = {
+ datePickerBtn,
+ datePickerBtn2,
+ datePicker,
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2294.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2294.cs
new file mode 100644
index 00000000..1f8bcf39
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2294.cs
@@ -0,0 +1,60 @@
+using System;
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2294, "Scrolling view causes timer to stop incrementing", PlatformAffected.iOS)]
+ public class Issue2294 : ContentPage
+ {
+ public Issue2294 ()
+ {
+ var labelUpdatedByTimer = new Label{ };
+ var layout = new StackLayout {
+ Children = {
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ labelUpdatedByTimer,
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ new Label {Text = "lots of content to scroll"},
+ },
+ };
+ var scroll = new ScrollView {
+ Content = layout,
+ };
+ double counter = 0.0;
+ Device.StartTimer (TimeSpan.FromSeconds (0.02), () => {
+ counter += 0.02;
+ labelUpdatedByTimer.Text = counter.ToString();
+ return true;
+ });
+ Content = scroll;
+ }
+ }
+}
+
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2333.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2333.cs
new file mode 100644
index 00000000..74329676
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2333.cs
@@ -0,0 +1,39 @@
+using System.Diagnostics;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2333, "TimePicker not shown when .Focus() is called", PlatformAffected.WinPhone)]
+ public class Issue2333 : ContentPage
+ {
+ public Issue2333 ()
+ {
+ var timePicker = new TimePicker ();
+ var timePickerBtn = new Button {
+ Text = "Click me to call .Focus on TimePicker"
+ };
+
+ timePickerBtn.Clicked += (sender, args) => {
+ timePicker.Focus ();
+ };
+
+ var timePickerBtn2 = new Button {
+ Text = "Click me to call .Unfocus on TimePicker"
+ };
+
+ timePickerBtn2.Clicked += (sender, args) => {
+ timePicker.Unfocus ();
+ };
+
+ Content = new StackLayout {
+ Children = {
+ timePickerBtn,
+ timePickerBtn2,
+ timePicker,
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2339.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2339.cs
new file mode 100644
index 00000000..aa958607
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2339.cs
@@ -0,0 +1,66 @@
+using System.Diagnostics;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2339, "Picker not shown when .Focus() is called", PlatformAffected.WinPhone)]
+ public class Issue2339 : ContentPage
+ {
+ public Issue2339 ()
+ {
+ var picker = new Picker { Items = {"One", "Two", "Three"} };
+ var pickerBtn = new Button {
+ Text = "Click me to call .Focus on Picker"
+ };
+
+ pickerBtn.Clicked += (sender, args) => {
+ picker.Focus ();
+ };
+
+ var pickerBtn2 = new Button {
+ Text = "Click me to call .Unfocus on Picker"
+ };
+
+ pickerBtn2.Clicked += (sender, args) => {
+ picker.Unfocus ();
+ };
+
+ var pickerBtn3 = new Button {
+ Text = "Click me to .Focus () picker, wait 2 seconds, and .Unfocus () picker",
+ Command = new Command (async () => {
+ picker.Focus ();
+ await Task.Delay (2000);
+ picker.Unfocus ();
+ })
+ };
+
+ var focusFiredCount = 0;
+ var unfocusFiredCount = 0;
+
+ var focusFiredLabel = new Label { Text = "Picker Focused: " + focusFiredCount };
+ var unfocusedFiredLabel = new Label { Text = "Picker UnFocused: " + unfocusFiredCount };
+
+ picker.Focused += (s, e) => {
+ focusFiredCount++;
+ focusFiredLabel.Text = "Picker Focused: " + focusFiredCount;
+ };
+ picker.Unfocused += (s, e) => {
+ unfocusFiredCount++;
+ unfocusedFiredLabel.Text = "Picker UnFocused: " + unfocusFiredCount;
+ };
+
+ Content = new StackLayout {
+ Children = {
+ focusFiredLabel,
+ unfocusedFiredLabel,
+ pickerBtn,
+ pickerBtn2,
+ pickerBtn3,
+ picker
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2354.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2354.cs
new file mode 100644
index 00000000..1e676f12
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2354.cs
@@ -0,0 +1,116 @@
+using System;
+
+using Xamarin.Forms;
+using System.Collections.Generic;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue(IssueTracker.Github, 2354, "ListView, ImageCell and disabled source cache and same image url",PlatformAffected.iOS | PlatformAffected.Android)]
+ public class Issue2354 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var presidents = new List<President> ();
+ for (int i = 0; i < 10; i++) {
+ presidents.Add (new President ($"Presidente {44 - i}", 1, $"http://static.c-span.org/assets/images/series/americanPresidents/{43 - i}_400.png"));
+ }
+
+ var header = new Label {
+ Text = "Presidents",
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ var cell = new DataTemplate (typeof(CustomCell));
+
+ var listView = new ListView {
+ ItemsSource = presidents,
+ ItemTemplate = cell,
+ RowHeight = 200
+ };
+
+
+ Content = new StackLayout {
+ Children = {
+ header,
+ listView
+ }
+ };
+ }
+
+ public class President
+ {
+ public President (string name, int position, string image)
+ {
+ Name = name;
+ Position = position;
+ Image = image;
+ }
+
+ public string Name { private set; get; }
+
+ public int Position { private set; get; }
+
+ public string Image { private set; get; }
+ }
+
+
+ [Preserve (AllMembers = true)]
+ public class CustomCell : ViewCell
+ {
+ public CustomCell()
+ {
+ var image = new Image
+ {
+ HorizontalOptions = LayoutOptions.Start,
+ Aspect = Aspect.AspectFill
+ };
+
+ var source = new UriImageSource {
+ CachingEnabled = false,
+ };
+
+ source.SetBinding(UriImageSource.UriProperty, new Binding("Image", converter: new UriConverter()));
+
+ image.Source = source;
+
+
+ View = image;
+ }
+ }
+
+ public class UriConverter : IValueConverter
+ {
+
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ return new Uri((string) value);
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+
+ }
+
+#if UITEST
+ [Test]
+ public void TestDoesntCrashWithCachingDisable ()
+ {
+ RunningApp.ScrollDown ();
+ RunningApp.ScrollDown ();
+ }
+#endif
+
+ }
+
+}
+
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2357.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2357.xaml
new file mode 100644
index 00000000..b01a5ccf
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2357.xaml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Forms.Controls.Issue2357" IsBusy="{Binding IsBusy}">
+ <MasterDetailPage.Master>
+ <ContentPage Title="Menu" Icon="menuIcon.png">
+ <StackLayout Spacing="0">
+ <ContentView Padding="10,36,0,5" BackgroundColor="Transparent">
+ <Label Text="MENU" Font="Medium">
+ </Label>
+ </ContentView>
+ <ListView ItemsSource="{Binding MainMenuItems}" ItemTapped="ListViewOnItemTapped">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <TextCell Text="{Binding Title}">
+ </TextCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </StackLayout>
+ </ContentPage>
+ </MasterDetailPage.Master>
+</MasterDetailPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2357.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2357.xaml.cs
new file mode 100644
index 00000000..54c8e0b3
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2357.xaml.cs
@@ -0,0 +1,418 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Threading.Tasks;
+using System.Linq;
+using System.ComponentModel;
+using System.Text;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2357, "Webview waits to load the content until webviews on previous pages are loaded", PlatformAffected.iOS | PlatformAffected.Android)]
+ public partial class Issue2357 : MasterDetailPage
+ {
+ public Issue2357 ()
+ {
+ MasterViewModel = new MasterViewModel ();
+ MasterViewModel.PageSelectionChanged += MasterViewModelOnPageSelectionChanged;
+ BindingContext = MasterViewModel;
+
+ Detail = new NavigationPage (new ContentPage {
+ Title = "Home",
+ Content = new Label {
+ Text = "Hello, Forms !",
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ HorizontalOptions = LayoutOptions.CenterAndExpand
+ }
+ });
+ InitializeComponent ();
+ }
+
+ public MasterViewModel MasterViewModel { get; set; }
+
+ async void MasterViewModelOnPageSelectionChanged (object sender, NavigationEventArgs eventArgs)
+ {
+ Debug.WriteLine ("MasterViewModelOnPageSelectionChanged");
+ IsPresented = false;
+ var page = eventArgs.Page;
+ await Detail.Navigation.PushAsync (page, true);
+ }
+
+ protected override async void OnAppearing ()
+ {
+ await TryInitializeMasterViewModel ();
+ base.OnAppearing ();
+ }
+
+ protected override void OnDisappearing ()
+ {
+ //MasterViewModel.PageSelectionChanged -= MasterViewModelOnPageSelectionChanged;
+ base.OnDisappearing ();
+ }
+
+ async Task TryInitializeMasterViewModel ()
+ {
+ while (true) {
+ string errorMessage;
+ try {
+ await MasterViewModel.InitializeAsync ();
+ break;
+ } catch (Exception ex) {
+ Insights.Report (ex, Insights.Severity.Error);
+ errorMessage = ex.Message;
+ }
+
+ if (!string.IsNullOrWhiteSpace (errorMessage)) {
+ var retry = await DisplayAlert ("Error", errorMessage, "Retry", "Close Application");
+ if (retry) {
+ continue;
+ }
+
+ }
+
+ break;
+ }
+ }
+
+ protected void ListViewOnItemTapped (object sender, ItemTappedEventArgs e)
+ {
+ Debug.WriteLine ("ListViewOnItemTapped");
+
+ if (((ListView)sender).SelectedItem == null)
+ return;
+
+ var menuItem = e.Item as MainMenuItem;
+
+ if (menuItem != null) {
+ switch (menuItem.MenuType) {
+ case MenuType.Login:
+ {
+ break;
+ }
+
+ case MenuType.WebView:
+ {
+ var webViewViewModel = new WebViewViewModel (menuItem);
+ MasterViewModel.CurrentDetailPage = new CustomWebView (webViewViewModel);
+ break;
+ }
+
+ default:
+ {
+ //MenuType Standard
+ break;
+ }
+ }
+
+ ((ListView)sender).SelectedItem = null;
+ }
+ }
+ }
+
+ internal class CustomWebView : ContentPage
+ {
+ WebView _titledWebView;
+
+ public CustomWebView ()
+ {
+ _titledWebView = new WebView ();
+ _titledWebView.SetBinding (WebView.SourceProperty, new Binding ("Url"));
+ _titledWebView.Navigating += WebView_OnNavigating;
+ this.SetBinding (TitleProperty, "Title");
+ Content = _titledWebView;
+ }
+
+ public CustomWebView (WebViewViewModel webViewViewModel) : this ()
+ {
+ Debug.WriteLine ("New WebView");
+
+ _titledWebView.BindingContext = webViewViewModel;
+ }
+
+ static void WebView_OnNavigating (object sender, WebNavigatingEventArgs e)
+ {
+ Debug.WriteLine ("OS: " + Device.OS + " Current Url: " + GetSourceUrl (((WebView)sender).Source) + "Destination Url: " + e.Url + " " + DateTime.Now);
+
+ if (e.Url.IsValidAbsoluteUrl ()) {
+ var destinationUri = new Uri (e.Url);
+ var sourceUri = GetSourceUrl (((WebView)sender).Source);
+ if (sourceUri.HasSameHost (destinationUri)) {
+ if (destinationUri == sourceUri) {
+ //Do nothing. This happens on webview load
+ Debug.WriteLine ("WebView_OnNavigating Same URI");
+ return;
+ }
+
+ //If it reaches here, A link could have been clicked.
+ e.Cancel = true;
+ Debug.WriteLine ("WebView_OnNavigating Same Host but different Uri");
+ } else {
+ //if external link is clicked
+ Debug.WriteLine ("WebView_OnNavigating, DIfferent Uri, so open in Native Browser");
+ e.Cancel = true;
+ Device.OpenUri (new Uri (e.Url));
+ }
+ }
+ }
+
+ static Uri GetSourceUrl (WebViewSource source)
+ {
+ Debug.Assert (source != null, "source cannot be null.");
+
+ var urlWebViewSource = source as UrlWebViewSource;
+ if (urlWebViewSource != null) {
+ if (urlWebViewSource.Url.IsValidAbsoluteUrl ()) {
+ return new Uri (urlWebViewSource.Url);
+ }
+ }
+
+ throw new InvalidOperationException ("WebViewSource is Invalid. Only UrlWebViewSource is accepted.");
+ }
+ }
+
+ public static class UriExtensions
+ {
+ public static bool HasSameHost (this Uri sourceUri, Uri destinationUri, UriFormat uriFormat = UriFormat.Unescaped)
+ {
+ Debug.Assert (sourceUri != null, "sourceUri cannot be null.");
+ Debug.Assert (destinationUri != null, "destinationUri cannot be null.");
+
+ return destinationUri.GetComponents (UriComponents.Host, uriFormat) ==
+ sourceUri.GetComponents (UriComponents.Host, uriFormat);
+ }
+ }
+
+ public static class StringExtensions
+ {
+ public static bool IsValidAbsoluteUrl (this string stringValue)
+ {
+ Uri result;
+ return !string.IsNullOrWhiteSpace (stringValue) && Uri.TryCreate (stringValue, UriKind.Absolute, out result) && (result.Scheme == "http" || result.Scheme == "https");
+ }
+ }
+ public delegate void PageSelectionChanged (object sender, NavigationEventArgs e);
+
+ public class MasterViewModel : ViewModelBase1
+ {
+ public static event PageSelectionChanged PageSelectionChanged;
+
+ ObservableCollection<MainMenuItem> _mainMenuItems;
+ Page _currentDetailPage;
+
+ public MasterViewModel ()
+ {
+ _mainMenuItems = new ObservableCollection<MainMenuItem> (Enumerable.Empty<MainMenuItem> ());
+ }
+
+ public async Task InitializeAsync ()
+ {
+ var items = new List<MainMenuItem> ();
+ items.Add (new MainMenuItem {
+ Title = "SHORT",
+ MenuType = MenuType.WebView,
+ Uri = new Uri ("http://api.morgans.bluearc-uat.com/mobile/SamplePage.aspx?page=Portfolio")
+ });
+ items.Add (new MainMenuItem {
+ Title = "LONG",
+ MenuType = MenuType.WebView,
+ Uri = new Uri ("http://api.morgans.bluearc-uat.com/mobile/SamplePage.aspx?page=long")
+ });
+
+ MainMenuItems = new ObservableCollection<MainMenuItem> (items);
+ }
+
+ public ObservableCollection<MainMenuItem> MainMenuItems {
+ get { return _mainMenuItems; }
+ set {
+ _mainMenuItems = value;
+ OnPropertyChanged ("MainMenuItems");
+ }
+ }
+
+ public Page CurrentDetailPage {
+ get { return _currentDetailPage; }
+ set {
+ _currentDetailPage = value;
+
+ var handler = PageSelectionChanged;
+ if (handler != null) {
+ handler (null, new NavigationEventArgs (value));
+ }
+ }
+ }
+ }
+
+ public class WebViewViewModel : ViewModelBase1
+ {
+ string _title;
+ string _url;
+
+ public WebViewViewModel (MainMenuItem menuItem)
+ {
+ Debug.WriteLine ("New WebViewViewModel");
+ _title = menuItem.Title;
+ _url = menuItem.Uri.AbsoluteUri;
+ }
+
+ public string Title {
+ get { return _title; }
+ set {
+ _title = value;
+ OnPropertyChanged ("Title");
+ }
+ }
+
+ public string Url {
+ get { return _url; }
+ set {
+ Debug.WriteLine ("WebViewViewModel Url Changed");
+ _url = value;
+ OnPropertyChanged ("Url");
+ }
+ }
+ }
+
+ public interface IMenuService
+ {
+ Task<IEnumerable<MainMenuItem>> GetMenuItemsAsync ();
+ }
+
+ public class MainMenuItem
+ {
+ public object Id { get; set; }
+
+ public MenuType MenuType { get; set; }
+
+ public string Title { get; set; }
+
+ public Uri Uri { get; set; }
+ }
+
+ public enum MenuType
+ {
+ Login,
+ WebView,
+ Standard
+ }
+
+ public class ViewModelBase1 : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ /// <summary>
+ /// Event for when IsBusy changes
+ /// </summary>
+ public event EventHandler IsBusyChanged;
+
+ /// <summary>
+ /// Event for when IsValid changes
+ /// </summary>
+ public event EventHandler IsValidChanged;
+
+ readonly List<string> _errors = new List<string> ();
+ bool _isBusy;
+
+ /// <summary>
+ /// Default constructor
+ /// </summary>
+ public ViewModelBase1 ()
+ {
+ //Make sure validation is performed on startup
+ Validate ();
+ }
+
+ /// <summary>
+ /// Returns true if the current state of the ViewModel is valid
+ /// </summary>
+ public bool IsValid {
+ get { return _errors.Count == 0; }
+ }
+
+ /// <summary>
+ /// A list of errors if IsValid is false
+ /// </summary>
+ protected List<string> Errors {
+ get { return _errors; }
+ }
+
+ /// <summary>
+ /// An aggregated error message
+ /// </summary>
+ public string Error {
+ get {
+ return _errors.Aggregate (new StringBuilder (), (b, s) => b.AppendLine (s)).ToString ().Trim ();
+ }
+ }
+
+ /// <summary>
+ /// Protected method for validating the ViewModel
+ /// - Fires PropertyChanged for IsValid and Errors
+ /// </summary>
+ protected void Validate ()
+ {
+ OnPropertyChanged ("IsValid");
+ OnPropertyChanged ("Errors");
+
+ var method = IsValidChanged;
+ if (method != null)
+ method (this, EventArgs.Empty);
+ }
+
+ /// <summary>
+ /// Other viewmodels should call this when overriding Validate, to validate each property
+ /// </summary>
+ /// <param name="validate">Func to determine if a value is valid</param>
+ /// <param name="error">The error message to use if not valid</param>
+ protected void ValidateProperty (Func<bool> validate, string error)
+ {
+ if (validate ()) {
+ if (!Errors.Contains (error))
+ Errors.Add (error);
+ } else {
+ Errors.Remove (error);
+ }
+ }
+
+ /// <summary>
+ /// Value indicating if a spinner should be shown
+ /// </summary>
+ public bool IsBusy {
+ get { return _isBusy; }
+ set {
+ if (_isBusy != value) {
+ _isBusy = value;
+
+ OnPropertyChanged ("IsBusy");
+ OnIsBusyChanged ();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Other viewmodels can override this if something should be done when busy
+ /// </summary>
+ protected void OnIsBusyChanged ()
+ {
+ var ev = IsBusyChanged;
+ if (ev != null) {
+ ev (this, EventArgs.Empty);
+ }
+ }
+
+ protected void OnPropertyChanged (string name)
+ {
+ var ev = PropertyChanged;
+ if (ev != null) {
+ ev (this, new PropertyChangedEventArgs (name));
+ }
+ }
+ }
+#endif
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2411.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2411.cs
new file mode 100644
index 00000000..9221803b
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2411.cs
@@ -0,0 +1,276 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2411, "ListView.ScrollTo not working in TabbedPage", PlatformAffected.Android)]
+ public class Issue2411 : TestTabbedPage
+ {
+ protected override void Init ()
+ {
+ Children.Add (new XamarinListViewScrollToBugPage1 ());
+ Children.Add (new XamarinListViewScrollToBugPage2 ());
+ Children.Add (new XamarinListViewScrollToBugPage3 ());
+ }
+
+#if UITEST
+ [Test]
+#if __ANDROID__
+ [Ignore ("Appearing event is tied to virtualization in TabbedPage for Material")]
+#endif
+ [Issue (IssueTracker.Github, 2411, "ScrollToPositon.MakeVisible not called every time TabbedPage", PlatformAffected.Android)]
+ public void Issue2411ScrollToPositionMakeVisible ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("99 99 99 99 99 99"));
+ RunningApp.Screenshot ("ScrollTo working correctly");
+ RunningApp.Tap (q => q.Marked ("Crash in ScrollToPosition.End"));
+ RunningApp.Screenshot ("On Second Tab");
+ RunningApp.WaitForElement (q => q.Marked ("2 0 0 0 0 0 0"));
+ RunningApp.Tap (q => q.Marked ("Scroll To in OnAppearing"));
+ RunningApp.Screenshot ("On First Tab");
+ RunningApp.WaitForElement (q => q.Marked ("99 99 99 99 99 99"));
+
+ var listViewBound = RunningApp.Query (q => q.Marked ("listView"))[0].Rect;
+ Xamarin.Forms.Core.UITests.Gestures.ScrollForElement (RunningApp, "* marked:'0 0 0 0 0 0'", new Xamarin.Forms.Core.UITests.Drag (listViewBound, Xamarin.Forms.Core.UITests.Drag.Direction.TopToBottom, Xamarin.Forms.Core.UITests.Drag.DragLength.Long));
+ RunningApp.Screenshot ("Scrolled to Top");
+
+ RunningApp.Tap (q => q.Marked ("Crash in ScrollToPosition.End"));
+ RunningApp.Screenshot ("On Second Tab");
+ RunningApp.WaitForElement (q => q.Marked ("2 0 0 0 0 0 0"));
+ RunningApp.Tap (q => q.Marked ("Scroll To in OnAppearing"));
+ RunningApp.Screenshot ("On First Tab");
+ RunningApp.WaitForElement (q => q.Marked ("99 99 99 99 99 99"));
+ }
+
+ [Test]
+ [Issue (IssueTracker.Github, 2411, "ScrollToPositon.End crashing in TabbedPage", PlatformAffected.Android)]
+ public void Issue2411ScrollToPositionEndCrash ()
+ {
+ RunningApp.Tap (q => q.Marked ("Crash in ScrollToPosition.End"));
+ RunningApp.Screenshot ("On Second Tab");
+ RunningApp.Tap (q => q.Marked ("Scroll To in OnAppearing"));
+ RunningApp.Screenshot ("On First Tab");
+ RunningApp.Tap (q => q.Marked ("Crash in ScrollToPosition.End"));
+ RunningApp.Screenshot ("On Second Tab Again");
+ RunningApp.Tap (q => q.Marked ("ScrollToPosition.End End - Not animated"));
+ RunningApp.WaitForElement (q => q.Marked ("2 99 99 99 99 99 99"));
+ }
+
+ [Test]
+ [Issue (IssueTracker.Github, 2411, "ScrollToPositon.End crashing in TabbedPage", PlatformAffected.Android)]
+ public void Issue2411ScrollToPositionWrongOnUneven ()
+ {
+ RunningApp.Tap (q => q.Marked ("Crash in ScrollToPosition.End"));
+ RunningApp.Tap (q => q.Marked ("Scroll To in OnAppearing Uneven"));
+ RunningApp.Screenshot ("On Third Tab");
+ RunningApp.WaitForElement (q => q.Marked ("99 99 99 99 99 99"));
+ }
+#endif
+ }
+
+ [Preserve (AllMembers = true)]
+ internal class ListObj
+ {
+ public string Name { get; set; }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class CellTemplateScrollTo : ViewCell
+ {
+ public CellTemplateScrollTo ()
+ {
+ Label cellLabel = new Label () {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ };
+
+ cellLabel.SetBinding (Label.TextProperty, new Binding ("Name", BindingMode.OneWay));
+
+ StackLayout root = new StackLayout () {
+ Children = {
+ cellLabel
+ }
+ };
+
+ View = root;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class CellTemplateScrollToUneven : CellTemplateScrollTo
+ {
+ public CellTemplateScrollToUneven ()
+ {
+
+ Height = 60 + new Random().Next(10, 100);
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class XamarinListViewScrollToBugPage1 : ContentPage
+ {
+ ListView _listView;
+ ObservableCollection<ListObj> _collection = new ObservableCollection<ListObj> ();
+
+ public XamarinListViewScrollToBugPage1 ()
+ {
+ Title = "Scroll To in OnAppearing";
+
+ for (int i = 0; i < 100; i++) {
+ var item = new ListObj { Name = string.Format ("{0} {0} {0} {0} {0} {0}", i) };
+ _collection.Add (item);
+ }
+
+ _listView = new ListView {
+ ItemsSource = _collection,
+ ItemTemplate = new DataTemplate (typeof(CellTemplateScrollTo))
+ };
+
+ _listView.AutomationId = "listView";
+
+ Content = new StackLayout {
+ Children = {
+ _listView
+ }
+ };
+ }
+
+ protected override void OnAppearing ()
+ {
+ base.OnAppearing ();
+ _listView.ScrollTo (_collection.Last(), ScrollToPosition.MakeVisible, false);
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class XamarinListViewScrollToBugPage2 : ContentPage
+ {
+ ListView _listView;
+ ObservableCollection<ListObj> _collection = new ObservableCollection<ListObj> ();
+
+ public XamarinListViewScrollToBugPage2 ()
+ {
+ Title = "Crash in ScrollToPosition.End";
+
+ for (int i = 0; i < 100; i++) {
+ var item = new ListObj { Name = string.Format ("2 {0} {0} {0} {0} {0} {0}", i) };
+ _collection.Add (item);
+ }
+
+ _listView = new ListView {
+ ItemsSource = _collection,
+ ItemTemplate = new DataTemplate (typeof(CellTemplateScrollTo))
+ };
+
+ var endButton = new Button {
+ Text = "ScrollToPosition.End End - Not animated",
+ Command = new Command (() => {
+ _listView.ScrollTo (_collection.Last(), ScrollToPosition.End, false);
+ })
+ };
+
+ var endButtonAnimated = new Button {
+ Text = "ScrollToPosition.MakeVisible End - Animated",
+ Command = new Command (() => {
+ _listView.ScrollTo (_collection.Last(), ScrollToPosition.MakeVisible, true);
+ })
+ };
+
+ Content = new StackLayout {
+ Children = {
+ endButton,
+ endButtonAnimated,
+ _listView
+ }
+ };
+ }
+ }
+
+ public class XamarinListViewScrollToBugPage3 : ContentPage
+ {
+ ListView _listView;
+ ObservableCollection<ListObj> _collection = new ObservableCollection<ListObj> ();
+ int _i =0;
+ public XamarinListViewScrollToBugPage3 ()
+ {
+ Title = "Scroll To in OnAppearing Uneven";
+
+ for (_i = 0; _i < 100; _i++) {
+ var item = new ListObj { Name = string.Format ("{0} {0} {0} {0} {0} {0}", _i) };
+ _collection.Add (item);
+ }
+
+ var btnAdd = new Button {
+ Text = "Add item",
+ WidthRequest = 100
+ };
+ btnAdd.Clicked += BtnAddOnClicked;
+
+ var btnBottom = new Button {
+ Text = "Scroll to end",
+ WidthRequest = 100
+ };
+ btnBottom.Clicked += BtnBottomOnClicked;
+
+ var btnPanel = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ HorizontalOptions = LayoutOptions.Center,
+ Children = {
+ btnAdd,
+ btnBottom
+ }
+ };
+
+ _listView = new ListView {
+ ItemsSource = _collection,
+ BackgroundColor = Color.Transparent,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HasUnevenRows = true,
+ ItemTemplate = new DataTemplate (typeof(CellTemplateScrollToUneven))
+ };
+ _listView.TakePerformanceHit = true;
+ _listView.ItemTapped += (sender, e) => ((ListView)sender).SelectedItem = null;
+
+ _listView.AutomationId = "listView";
+
+ Content = new StackLayout {
+ Children = {
+ btnPanel,
+ _listView
+ }
+ };
+ }
+
+ protected override void OnAppearing ()
+ {
+ base.OnAppearing ();
+ _listView.ScrollTo (_collection.Last(), ScrollToPosition.MakeVisible, false);
+ }
+
+ void BtnBottomOnClicked(object sender, EventArgs e)
+ {
+ var item = _collection.Last();
+ _listView.ScrollTo(item, ScrollToPosition.End, true);
+ }
+
+ void BtnAddOnClicked(object sender, EventArgs eventArgs)
+ {
+ var str = string.Format("Item {0}", _i++);
+ var item = new ListObj { Name = string.Format ("{0} {0} {0} {0} {0} {0}", _i) };
+ _collection.Add(item);
+
+ _listView.ScrollTo(item, ScrollToPosition.End, true);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2414.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2414.cs
new file mode 100644
index 00000000..894d0d6c
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2414.cs
@@ -0,0 +1,97 @@
+using System;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest.iOS;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2414, "NullReferenceException when swiping over Context Actions", PlatformAffected.WinPhone)]
+ public class Issue2414 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var tableView = new TableView
+ {
+ Intent = TableIntent.Settings,
+ Root = new TableRoot("TableView Title")
+ {
+ new TableSection("Table Section 2")
+ {
+ new TextCell
+ {
+ Text = "Swipe ME",
+ Detail = "And I will crash!",
+ ContextActions = {
+ new MenuItem
+ {
+ Text = "Text0"
+ },new MenuItem
+ {
+ Text = "Text1"
+ },
+ new MenuItem
+ {
+ Text = "Text2"
+ },
+ new MenuItem
+ {
+ Text = "Text3"
+ },
+ new MenuItem
+ {
+ Text = "Text4",
+ IsDestructive = true,
+ }}
+ },
+ }
+ }
+ };
+ Content = tableView;
+ }
+
+#if UITEST
+ [Test]
+ public void TestDoesntCrashShowingContextMenu ()
+ {
+ var screenBounds = RunningApp.Query (q => q.Raw ("* index:0"))[0].Rect;
+
+ var cell = RunningApp.Query (c => c.Marked ("Swipe ME")) [0];
+ if (RunningApp is iOSApp) {
+ RunningApp.DragCoordinates (screenBounds.Width - 10, cell.Rect.CenterY, 0, cell.Rect.CenterY);
+ //TODO: fix this when context menu bug is fixed
+ RunningApp.WaitForElement (c => c.Marked ("Text4"));
+ }
+ else {
+ RunningApp.TouchAndHoldCoordinates (cell.Rect.CenterX, cell.Rect.CenterY);
+ RunningApp.WaitForElement (c => c.Marked ("Text0"));
+ }
+ RunningApp.Screenshot ("Didn't crash");
+ RunningApp.TapCoordinates (screenBounds.CenterX, screenBounds.CenterY);
+ }
+
+ [Test]
+ public void TestShowContextMenuItemsInTheRightOrder ()
+ {
+ var screenBounds = RunningApp.Query (q => q.Raw ("* index:0"))[0].Rect;
+
+ var cell = RunningApp.Query (c => c.Marked ("Swipe ME")) [0];
+ if (RunningApp is iOSApp)
+ RunningApp.DragCoordinates (screenBounds.Width -10, cell.Rect.CenterY, 0, cell.Rect.CenterY);
+ else
+ RunningApp.TouchAndHoldCoordinates (cell.Rect.CenterX, cell.Rect.CenterY);
+ RunningApp.WaitForElement (c => c.Marked ("Text0"));
+ RunningApp.Screenshot ("Are the menuitems in the right order?");
+
+ }
+#endif
+
+ }
+}
+
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2470.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2470.xaml
new file mode 100644
index 00000000..b462f8ba
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2470.xaml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<local:TestTabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Controls"
+ x:Class="Xamarin.Forms.Controls.Issue2470">
+ <local:TestTabbedPage.Children>
+ <ContentPage Title="Generate">
+ <StackLayout>
+ <Label Text="Bug" FontSize="Large"/>
+ <Label Text="We have a TabbedPage with a ListView bound to an ObservableCollection."/>
+ <Label Text="If the switch is off, there should be 2 items in the Results tab."/>
+ <Label Text="If the switch is on, there should be 5 items in the Results tab."/>
+ <Label Text="Flip the switch, go to the Results tab, notice the wrong data. If the data is correct, come back here and flip the switch and try it again. After a few tries, you should see the bug."/>
+ <Label Text="Then swipe the data down and notice it gets better."/>
+ <Label Text="This bug only happens on Android."/>
+ <Switch IsToggled="{Binding TwoOrFive}" AutomationId="Switch" />
+ </StackLayout>
+ </ContentPage>
+ <ContentPage Title="Results">
+ <ListView ItemsSource="{Binding Entries}">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <SwitchCell Text="{Binding Name}" On="{Binding Selected}"/>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </ContentPage>
+ </local:TestTabbedPage.Children>
+</local:TestTabbedPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2470.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2470.xaml.cs
new file mode 100644
index 00000000..4cb0a3e8
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2470.xaml.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ public class Issue2470ViewModelBase : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class EntryViewModel : ViewModelBase
+ {
+ string _name;
+ public string Name
+ {
+ get { return _name; }
+ set { _name = value; OnPropertyChanged (); }
+ }
+
+ bool _selected;
+ public bool Selected
+ {
+ get { return _selected; }
+ set { _selected = value; OnPropertyChanged (); }
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Issue2470MainViewModel : Issue2470ViewModelBase
+ {
+ public ObservableCollection<EntryViewModel> Entries { get; private set; }
+
+ double _desiredCount;
+ public double DesiredCount
+ {
+ get { return _desiredCount; }
+ set
+ {
+ _desiredCount = value;
+ OnPropertyChanged ();
+ GenerateEntries ();
+ }
+ }
+
+ bool _twoOrFive;
+ public bool TwoOrFive
+ {
+ get { return _twoOrFive; }
+ set
+ {
+ _twoOrFive = value;
+ OnPropertyChanged ();
+ DesiredCount = _twoOrFive ? 5 : 2;
+ }
+ }
+
+ public Issue2470MainViewModel ()
+ {
+ Entries = new ObservableCollection<EntryViewModel> ();
+ TwoOrFive = false; // prime
+ }
+
+ void GenerateEntries ()
+ {
+ Entries.Clear ();
+ for (var i = 0; i < DesiredCount; i++) {
+ Entries.Add (new EntryViewModel { Name = "Entry " + i + " of " + DesiredCount });
+ }
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2470, "ObservableCollection changes do not update ListView", PlatformAffected.Android)]
+ public partial class Issue2470 : TestTabbedPage
+ {
+ protected override void Init ()
+ {
+ var mainViewModel = new Issue2470MainViewModel ();
+ BindingContext = mainViewModel;
+ }
+
+#if APP
+ [Preserve (AllMembers = true)]
+ public Issue2470 ()
+ {
+ InitializeComponent ();
+ }
+#endif
+
+#if UITEST
+ [Test]
+ public void OnservableCollectionChangeListView ()
+ {
+ // Tab 1
+ RunningApp.Tap (q => q.Marked ("Switch"));
+ RunningApp.Screenshot ("Switch On");
+ RunningApp.Tap (q => q.Marked ("Results"));
+
+ // Tab 2
+ RunningApp.WaitForElement (q => q.Marked ("Entry 0 of 5"));
+ RunningApp.WaitForElement (q => q.Marked ("Entry 1 of 5"));
+ RunningApp.WaitForElement (q => q.Marked ("Entry 2 of 5"));
+ RunningApp.WaitForElement (q => q.Marked ("Entry 3 of 5"));
+ RunningApp.WaitForElement (q => q.Marked ("Entry 4 of 5"));
+ RunningApp.Screenshot ("Should be 5 elements");
+ RunningApp.Tap (q => q.Marked ("Generate"));
+
+ // Tab 1
+ RunningApp.Tap (q => q.Marked ("Switch"));
+ RunningApp.Screenshot ("Switch Off");
+ RunningApp.Tap (q => q.Marked ("Results"));
+
+ // Tab 2
+ RunningApp.WaitForElement (q => q.Marked ("Entry 0 of 2"));
+ RunningApp.WaitForElement (q => q.Marked ("Entry 1 of 2"));
+ RunningApp.Screenshot ("Should be 2 elements");
+
+ // Tab 1
+ RunningApp.Tap (q => q.Marked ("Generate"));
+ RunningApp.Tap (q => q.Marked ("Switch"));
+ RunningApp.Screenshot ("Switch On");
+ RunningApp.Tap (q => q.Marked ("Results"));
+
+ // Tab 2
+ RunningApp.WaitForElement (q => q.Marked ("Entry 0 of 5"));
+ RunningApp.WaitForElement (q => q.Marked ("Entry 1 of 5"));
+ RunningApp.WaitForElement (q => q.Marked ("Entry 2 of 5"));
+ RunningApp.WaitForElement (q => q.Marked ("Entry 3 of 5"));
+ RunningApp.WaitForElement (q => q.Marked ("Entry 4 of 5"));
+ RunningApp.Screenshot ("Should be 5 elements");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2563.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2563.cs
new file mode 100644
index 00000000..538d1553
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2563.cs
@@ -0,0 +1,41 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2563, "NavigationPage should support queuing of navigation events", PlatformAffected.Android | PlatformAffected.WinPhone | PlatformAffected.iOS)]
+ public class Issue2563 : ContentPage
+ {
+ public Issue2563 ()
+ {
+ var button = new Button {
+ Text = "Click Me",
+ VerticalOptions = LayoutOptions.Center,
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ Content = button;
+
+ var random = new Random ();
+ button.Clicked += (sender, args) => {
+ for (int i = 0; i < 10; i++) {
+ button.Navigation.PushAsync (new ContentPage {
+ Title = "Page " + i,
+ Content = new Label {
+ Text = "Page " + i,
+ XAlign = TextAlignment.Center,
+ YAlign = TextAlignment.Center
+ }
+ }, random.NextDouble () > 0.5);
+ }
+
+ for (int i = 0; i < 6; i++) {
+ button.Navigation.PopAsync (random.NextDouble () > 0.5);
+ }
+
+ button.Navigation.PopToRootAsync (random.NextDouble () > 0.5);
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2594.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2594.cs
new file mode 100644
index 00000000..c4658a5f
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2594.cs
@@ -0,0 +1,33 @@
+using Xamarin.Forms.CustomAttributes;
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2594, "StackLayout produces overlapping layouts on some phones with specific screen sizes", PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.WinPhone)]
+ public class Issue2594 : ContentPage
+ {
+ public Issue2594 ()
+ {
+ var layout = new StackLayout {
+ Children = {
+ new StackLayout {
+ BackgroundColor = Color.Red,
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ new StackLayout {
+ BackgroundColor = Color.Gray,
+ Children = {
+ new Label {Text = "LONG TEXT. LONG TEXT. LONG TEXT. LONG TEXT. LONG TEXT.", TextColor = Color.Olive},
+ }
+ },
+ new Label {Text = "Some other text"}
+ }
+ },
+ new Label {Text = "Overlapped text.", TextColor = Color.Red}
+ }
+ };
+
+ Padding = new Thickness (0, 20, 0, 0);
+ Content = layout;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2597.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2597.cs
new file mode 100644
index 00000000..7d925018
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2597.cs
@@ -0,0 +1,61 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2597, "Stepper control .IsEnabled doesn't work", PlatformAffected.Android)]
+ public class Issue2597 : ContentPage
+ {
+ Label _label;
+
+ public Issue2597()
+ {
+ Label header = new Label
+ {
+ Text = "Stepper",
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ Stepper stepper = new Stepper
+ {
+ Minimum = 0,
+ Maximum = 10,
+ Increment = 0.1,
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ IsEnabled = false
+ };
+ stepper.ValueChanged += OnStepperValueChanged;
+
+ _label = new Label
+ {
+ Text = "Stepper value is 0",
+ Font = Font.SystemFontOfSize(NamedSize.Large),
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+
+ // Accomodate iPhone status bar.
+ Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10,
+ 5);
+
+ // Build the page.
+ Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ stepper,
+ _label
+ }
+ };
+ }
+
+ void OnStepperValueChanged(object sender, ValueChangedEventArgs e)
+ {
+ _label.Text = string.Format("Stepper value is {0:F1}", e.NewValue);
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue260.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue260.cs
new file mode 100644
index 00000000..cd53a95d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue260.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Linq;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 260, "Layout issue for TableView", PlatformAffected.WinPhone)]
+ public class Issue260 : ContentPage
+ {
+ // Issue: #229
+ // ToolbarItems broken on Android
+
+ // Doesn't seem to working on All Platforms
+
+ public Issue260 ()
+ {
+ var items = Enumerable.Range (0, 50).Select (i => new TextCell {
+ Text = i.ToString (),
+ Detail = i.ToString ()
+ }).ToList ();
+
+ var tableSection = new TableSection("First Section");
+ foreach (TextCell cell in items) {
+ tableSection.Add (cell);
+ }
+
+ var tableRoot = new TableRoot () {
+ tableSection
+ };
+
+ var tableLayout = new TableView {
+ Root = tableRoot
+ };
+
+ tableLayout.Intent = TableIntent.Data;
+ Content = tableLayout;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2615.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2615.cs
new file mode 100644
index 00000000..211b5be6
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2615.cs
@@ -0,0 +1,80 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2615, "iOS Cell Reuse screws up when cells are both ViewCell with different children", PlatformAffected.iOS)]
+ public class Issue2615 : ContentPage
+ {
+ public Issue2615 ()
+ {
+ Title = "Test Blank Rows";
+
+ var tableView = new TableView ();
+ tableView.HasUnevenRows = true;
+
+ var tableHeaderSection = new TableSection ();
+
+ var viewHeaderCell = new ViewCell ();
+
+ var headerCellLayout = new StackLayout ();
+ headerCellLayout.Orientation = StackOrientation.Vertical;
+ headerCellLayout.Spacing = 6;
+ headerCellLayout.HorizontalOptions = LayoutOptions.Fill;
+ headerCellLayout.VerticalOptions = LayoutOptions.Fill;
+
+ var largeNumberLabel = new Label ();
+ largeNumberLabel.FontFamily = "HelveticaNeue-Light";
+ largeNumberLabel.FontSize = 52;
+ largeNumberLabel.Text = "90";
+ largeNumberLabel.TextColor = Color.FromRgb(0.00392156885936856, 0.47843137383461, 0.996078431606293);
+ largeNumberLabel.HorizontalOptions = LayoutOptions.Center;
+ largeNumberLabel.VerticalOptions = LayoutOptions.Fill;
+ headerCellLayout.Children.Add(largeNumberLabel);
+
+ var nameLabel = new Label ();
+ nameLabel.FontFamily = "HelveticaNeue-Light";
+ nameLabel.FontSize = 17;
+ nameLabel.Text = "Name: John Doe";
+ nameLabel.HorizontalOptions = LayoutOptions.CenterAndExpand;
+ nameLabel.VerticalOptions = LayoutOptions.Center;
+ headerCellLayout.Children.Add(nameLabel);
+
+ viewHeaderCell.Height = 100;
+ viewHeaderCell.View = headerCellLayout;
+ tableHeaderSection.Add (viewHeaderCell);
+ tableView.Root.Add (tableHeaderSection);
+
+ for (int sectionNumber = 1; sectionNumber < 11; sectionNumber++) {
+ var tableSection = new TableSection ("Section #" + sectionNumber);
+
+ for (int cellNumber = 1; cellNumber < 11; cellNumber++) {
+
+ var viewCell = new ViewCell ();
+ var viewCellLayout = new StackLayout ();
+ viewCellLayout.Orientation = StackOrientation.Horizontal;
+ viewCellLayout.Spacing = 6;
+ viewCellLayout.Padding = new Thickness (20, 10);
+ viewCellLayout.HorizontalOptions = LayoutOptions.Center;
+ viewCellLayout.VerticalOptions = LayoutOptions.Center;
+
+ var titleLabel = new Label ();
+ titleLabel.FontFamily = "HelveticaNeue-Light";
+ titleLabel.FontSize = 17;
+ titleLabel.Text = "Cell #" + cellNumber;
+ viewCellLayout.Children.Add(titleLabel);
+
+ viewCell.View = viewCellLayout;
+
+ tableSection.Add (viewCell);
+ }
+
+ tableView.Root.Add (tableSection);
+
+ }
+
+ Content = tableView;
+
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2628.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2628.cs
new file mode 100644
index 00000000..136c7054
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2628.cs
@@ -0,0 +1,31 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2628, "Unable to change page BackgroundImage from code", PlatformAffected.Android)]
+ public class Issue2628 : ContentPage
+ {
+ public Issue2628 ()
+ {
+ var button1 = new Button { Text = "Click !!!!!!!!!!"};
+ BackgroundImage="bank.png";
+ button1.Clicked += ButtonAction;
+
+ Content = new StackLayout {
+ Spacing = 10,
+ VerticalOptions = LayoutOptions.Center,
+ Children = {
+ button1
+ }
+ };
+ }
+
+ public void ButtonAction(object sender, EventArgs args)
+ {
+ BackgroundImage="calculator.png";
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2634.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2634.cs
new file mode 100644
index 00000000..992b342f
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2634.cs
@@ -0,0 +1,333 @@
+using System;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2634, "Keyboard causes view to scroll incorrectly", PlatformAffected.iOS)]
+ public class Issue2634 : ContentPage
+ {
+ public Issue2634 ()
+ {
+ Content = new AddPatientView ();
+ }
+
+ public class AddPatientView : ContentView
+ {
+ Entry _firstNameEntry;
+
+ public AddPatientView ()
+ {
+ var bvBackground = new Frame {
+ Content = new Label { Text = "" },
+ OutlineColor = Color.FromRgb (0x06, 0x68, 0xCF),
+ BackgroundColor = Color.FromRgba (0f, 0f, 0f, 0.4f),
+ HasShadow = true
+ };
+
+ var addGrid = new Grid {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ RowDefinitions = {
+ new RowDefinition { Height = new GridLength (10, GridUnitType.Absolute) },
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = new GridLength (1, GridUnitType.Star) },
+ new RowDefinition { Height = new GridLength (10, GridUnitType.Absolute) },
+ },
+ ColumnDefinitions = {
+ new ColumnDefinition { Width = new GridLength (10, GridUnitType.Absolute) },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength (10, GridUnitType.Absolute) },
+ },
+ ColumnSpacing = 1,
+ RowSpacing = 1,
+ Padding = 0
+ };
+
+
+ #region QuickAdd Data Entry
+ var gridAddData = new Grid {
+ RowDefinitions = {
+ new RowDefinition { Height = new GridLength (0, GridUnitType.Absolute) },
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = new GridLength (15, GridUnitType.Absolute) },
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = new GridLength (15, GridUnitType.Absolute) },
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = new GridLength (15, GridUnitType.Absolute) },
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = new GridLength (15, GridUnitType.Absolute) },
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = new GridLength (20, GridUnitType.Absolute) },
+ },
+ ColumnDefinitions = {
+ new ColumnDefinition { Width = new GridLength (60, GridUnitType.Absolute) },
+ new ColumnDefinition { Width = GridLength.Auto },
+ new ColumnDefinition { Width = new GridLength (10, GridUnitType.Absolute) },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength (60, GridUnitType.Absolute) }
+ },
+ BackgroundColor = Color.Transparent,
+ ColumnSpacing = 1,
+ RowSpacing = 1,
+ Padding = 0
+ };
+ Color textColor = Color.Blue;
+ Color dataColor = Color.Black;
+
+ var slFirstName = new StackLayout { Orientation = StackOrientation.Vertical };
+ var lblFirstNameLabel = new Label {
+ Text = "First Name",
+ Font = Font.SystemFontOfSize (NamedSize.Medium, FontAttributes.Bold),
+ TextColor = textColor
+ };
+ _firstNameEntry = new Entry {
+ Keyboard = Keyboard.Default,
+ TextColor = dataColor,
+ Placeholder = "First Name (required)",
+ };
+ slFirstName.Children.Add (lblFirstNameLabel);
+ slFirstName.Children.Add (_firstNameEntry);
+ gridAddData.Children.Add (slFirstName, 1, 4, 1, 2);
+
+ var slMiddleName = new StackLayout { Orientation = StackOrientation.Vertical };
+ var lblMiddleNameLabel = new Label {
+ Text = "Middle Name",
+ Font = Font.SystemFontOfSize (NamedSize.Medium, FontAttributes.Bold),
+ TextColor = textColor
+ };
+ var entMiddleName = new Entry {
+ Keyboard = Keyboard.Default,
+ TextColor = dataColor,
+ Placeholder = "Middle Name",
+ };
+ slMiddleName.Children.Add (lblMiddleNameLabel);
+ slMiddleName.Children.Add (entMiddleName);
+ gridAddData.Children.Add (slMiddleName, 1, 4, 3, 4);
+
+ var slLastName = new StackLayout { Orientation = StackOrientation.Vertical };
+ var lblLastNameLabel = new Label {
+ Text = "Last Name",
+ Font = Font.SystemFontOfSize (NamedSize.Medium, FontAttributes.Bold),
+ TextColor = textColor
+ };
+ var entLastName = new Entry {
+ Keyboard = Keyboard.Default,
+ TextColor = dataColor,
+ Placeholder = "Last Name (required)",
+ };
+ slLastName.Children.Add (lblLastNameLabel);
+ slLastName.Children.Add (entLastName);
+ gridAddData.Children.Add (slLastName, 1, 4, 5, 6);
+
+ var slDob = new StackLayout { Orientation = StackOrientation.Vertical };
+ var lblDobLabel = new Label {
+ Text = "Date of Birth",
+ Font = Font.SystemFontOfSize (NamedSize.Medium, FontAttributes.Bold),
+ TextColor = textColor,
+ XAlign = TextAlignment.Start
+ };
+ var entDob = new Entry {
+ TextColor = dataColor,
+ Placeholder = "mm/dd/yyyy (required)",
+ Keyboard = Keyboard.Numeric
+ };
+ slDob.Children.Add (lblDobLabel);
+ slDob.Children.Add (entDob);
+ gridAddData.Children.Add (slDob, 1, 7);
+
+ var slGender = new StackLayout { Orientation = StackOrientation.Vertical };
+ var lblGenderLabel = new Label {
+ Text = "Gender",
+ Font = Font.SystemFontOfSize (NamedSize.Medium, FontAttributes.Bold),
+ TextColor = textColor,
+ XAlign = TextAlignment.Start
+ };
+ slGender.Children.Add (lblGenderLabel);
+
+
+ gridAddData.Children.Add (slGender, 3, 7);
+
+ var slHomePhone = new StackLayout { Orientation = StackOrientation.Vertical };
+ var lblHomePhoneLabel = new Label {
+ Text = "Home Phone",
+ Font = Font.SystemFontOfSize (NamedSize.Medium, FontAttributes.Bold),
+ TextColor = textColor,
+ XAlign = TextAlignment.Start
+ };
+ var entHomePhone = new Entry {
+ TextColor = dataColor,
+ Keyboard = Keyboard.Telephone,
+ Placeholder = "888-888-8888",
+ //MaxLength = 12
+ };
+ entHomePhone.TextChanged += (object sender, TextChangedEventArgs e) => {
+ };
+ slHomePhone.Children.Add (lblHomePhoneLabel);
+ slHomePhone.Children.Add (entHomePhone);
+ gridAddData.Children.Add (slHomePhone, 1, 9);
+
+ var slMobilePhone = new StackLayout { Orientation = StackOrientation.Vertical };
+ var lblMobilePhoneLabel = new Label {
+ Text = "Mobile Phone",
+ Font = Font.SystemFontOfSize (NamedSize.Medium, FontAttributes.Bold),
+ TextColor = textColor,
+ XAlign = TextAlignment.Start
+ };
+ var entMobilePhone = new Entry {
+ TextColor = dataColor,
+ Keyboard = Keyboard.Telephone,
+ Placeholder = "888-888-8888",
+ };
+ entMobilePhone.TextChanged += (object sender, TextChangedEventArgs e) => {
+ };
+ slMobilePhone.Children.Add (lblMobilePhoneLabel);
+ slMobilePhone.Children.Add (entMobilePhone);
+ gridAddData.Children.Add (slMobilePhone, 3, 9);
+ #endregion
+
+ string breakText = "_______________________________________________________________________________________________________________________________________________________________________________";
+ var lblBreakLine = new Label { LineBreakMode = LineBreakMode.NoWrap, TextColor = Color.Red };
+ lblBreakLine.Text = breakText;
+ addGrid.Children.Add (lblBreakLine, 0, 3, 2, 3);
+
+ var slFrameContent = new StackLayout { Orientation = StackOrientation.Vertical };
+ slFrameContent.Children.Add (addGrid);
+ var svAddData = new ScrollView { Content = gridAddData, IsClippedToBounds = true, IsVisible = true };
+ slFrameContent.Children.Add (svAddData);
+
+ var addFrame = new Frame {
+ Content = slFrameContent,
+ Padding = 5,
+ HasShadow = true
+ };
+
+ var rl = new RelativeLayout ();
+ rl.Children.Add (bvBackground, Forms.Constraint.Constant (0), Forms.Constraint.Constant (0),
+ Forms.Constraint.RelativeToParent ((parent) =>
+ parent.Width),
+ Forms.Constraint.RelativeToParent ((parent) =>
+ parent.Height));
+
+ rl.Children.Add (addFrame,
+ Forms.Constraint.RelativeToParent ((parent) =>
+ (parent.Width * .25) / 2),
+ Forms.Constraint.Constant (Device.OnPlatform (60, 40, 40)),
+ Forms.Constraint.RelativeToParent ((parent) =>
+ parent.Width * .75));
+
+ Content = rl;
+ }
+
+ void cancelButton_Clicked (object sender, EventArgs e)
+ {
+ _firstNameEntry.Focus ();
+ _firstNameEntry.Unfocus (); // done to remove focus from an entry field so keyboard will go away
+ }
+
+ void doneButton_Clicked (object sender, EventArgs e)
+ {
+ _firstNameEntry.Focus ();
+ _firstNameEntry.Unfocus (); // done to remove focus from an entry field so keyboard will go away
+ }
+
+ DataTemplate CreateDtForList ()
+ {
+ var dt = new DataTemplate (() => {
+ // grid for one row definition
+ var grid = new Grid {
+ RowDefinitions = {
+ new RowDefinition { Height = new GridLength (84, GridUnitType.Absolute) },
+ },
+ ColumnDefinitions = {
+ new ColumnDefinition { Width = new GridLength (15, GridUnitType.Absolute) },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength (3, GridUnitType.Absolute) }
+ },
+ ColumnSpacing = 1,
+ RowSpacing = 1,
+ Padding = 0,
+ VerticalOptions = LayoutOptions.Center
+ };
+
+ Color txtColor = Color.Blue;
+ Font dataFont = Font.SystemFontOfSize (NamedSize.Medium);
+ var nameData = new Label {
+ TextColor = txtColor,
+ Font = dataFont,
+ XAlign = TextAlignment.Start,
+ YAlign = TextAlignment.Center,
+ VerticalOptions = LayoutOptions.Center
+ };
+ nameData.SetBinding (Label.TextProperty, "Name");
+ var genderData = new Label {
+ TextColor = txtColor,
+ Font = dataFont,
+ XAlign = TextAlignment.Start,
+ YAlign = TextAlignment.Center,
+ VerticalOptions = LayoutOptions.Center
+ };
+ genderData.SetBinding (Label.TextProperty, "Gender");
+ var slNameGender = new StackLayout { Orientation = StackOrientation.Horizontal };
+ var lblGender1 = new Label { Text = " (", Font = dataFont };
+ var lblGender2 = new Label { Text = ")", Font = dataFont };
+ slNameGender.Children.Add (nameData);
+ slNameGender.Children.Add (lblGender1);
+ slNameGender.Children.Add (genderData);
+ slNameGender.Children.Add (lblGender2);
+
+
+ var lblDob = new Label {
+ TextColor = txtColor,
+ Text = "DOB: ",
+ Font = Font.SystemFontOfSize (NamedSize.Medium, FontAttributes.Bold)
+ };
+ var dobData = new Label {
+ TextColor = txtColor,
+ Font = dataFont,
+ XAlign = TextAlignment.Start,
+ YAlign = TextAlignment.Center,
+ VerticalOptions = LayoutOptions.Center
+ };
+ dobData.SetBinding (Label.TextProperty, "DateOfBirth");
+ var slDobPhone = new StackLayout { Orientation = StackOrientation.Horizontal };
+ slDobPhone.Children.Add (lblDob);
+ slDobPhone.Children.Add (dobData);
+
+ var lblSpacer = new Label { Text = " ", Font = dataFont };
+ slDobPhone.Children.Add (lblSpacer);
+
+ var lblPhone = new Label {
+ TextColor = txtColor,
+ Text = "PHONE: ",
+ Font = Font.SystemFontOfSize (NamedSize.Medium, FontAttributes.Bold)
+ };
+ var phoneData = new Label {
+ TextColor = txtColor,
+ Font = dataFont,
+ XAlign = TextAlignment.Start,
+ YAlign = TextAlignment.Center,
+ VerticalOptions = LayoutOptions.Center
+ };
+ phoneData.SetBinding (Label.TextProperty, "PrimaryPhone");
+ slDobPhone.Children.Add (lblPhone);
+ slDobPhone.Children.Add (phoneData);
+
+ var slTotal = new StackLayout { Orientation = StackOrientation.Vertical };
+ slTotal.Children.Add (slNameGender);
+ slTotal.Children.Add (slDobPhone);
+
+ grid.Children.Add (slTotal, 1, 0);
+ return new ViewCell {
+ View = grid
+ };
+
+ });
+ return dt;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue264.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue264.cs
new file mode 100644
index 00000000..4f1f3ae2
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue264.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Linq;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 264, "PopModal NRE", PlatformAffected.Android | PlatformAffected.iOS)]
+ public class Issue264 : TestContentPage
+ {
+ Page _current;
+
+ protected override void Init ()
+ {
+ var aboutBtn = new Button {
+ Text = "About"
+ };
+
+ aboutBtn.Clicked += (s, e) => Navigation.PushModalAsync (new AboutPage ());
+
+ var popButton = new Button {
+ Text = "Pop me",
+ Command = new Command (async () => await Navigation.PopAsync ())
+ };
+
+ Content = new StackLayout {
+ Children = {
+ new Label {Text = "Home"},
+ aboutBtn,
+ popButton
+ }
+ };
+ }
+
+ // Pop modal null reference exception
+
+#if UITEST
+ [Test]
+ public void Issue264TestsPushAndPopModal ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Home"));
+ RunningApp.WaitForElement (q => q.Button ("About"));
+ RunningApp.Screenshot ("All elements present");
+
+ RunningApp.Tap (q => q.Button ("About"));
+ RunningApp.WaitForElement (q => q.Button ("Close"));
+ RunningApp.Screenshot ("Modal pushed");
+
+ RunningApp.Tap (q => q.Button ("Close"));
+ RunningApp.WaitForElement (q => q.Button ("About"));
+ RunningApp.Screenshot ("Modal popped");
+
+ RunningApp.Tap (q => q.Button ("Pop me"));
+ RunningApp.WaitForElement (q => q.Marked ("Bug Repro's"));
+ RunningApp.Screenshot ("No crash");
+ }
+#endif
+ }
+
+ public class AboutPage : ContentPage
+ {
+ public AboutPage()
+ {
+ BackgroundColor = Color.Black;
+ Content = new Button { Text = "Close", Command = new Command (() => Navigation.PopModalAsync ()) };
+
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2659.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2659.xaml
new file mode 100644
index 00000000..05e2b4dc
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2659.xaml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issue2659">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <Style x:Key="buttonStyle" TargetType="Button">
+ <Setter Property="HorizontalOptions" Value="Center" />
+ <Setter Property="VerticalOptions" Value="CenterAndExpand" />
+ <Setter Property="FontSize" Value="Large" />
+ <Setter Property="TextColor" Value="Blue" />
+ <Setter Property="FontAttributes" Value="Italic" />
+ </Style>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+
+ <StackLayout x:Name="stackLayout">
+ <Button Text="Set Style from Resource"
+ Clicked="OnSetStyleButtonClicked"
+ x:Name="button0"/>
+
+ <Button Text="Set Style to null"
+ Clicked="OnUnsetStyleButtonClicked"
+ x:Name="button1"/>
+
+ <Button Text="Set Local Properties"
+ Clicked="OnSetLocalButtonClicked"
+ x:Name="button2"/>
+
+ <Button Text="Clear Local Properties"
+ Clicked="OnClearLocalButtonClicked"
+ x:Name="button3"/>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2659.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2659.xaml.cs
new file mode 100644
index 00000000..e1d36f72
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2659.xaml.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+#if APP
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2659, "", PlatformAffected.Android | PlatformAffected.iOS)]
+ public partial class Issue2659 : ContentPage
+ {
+ public Issue2659 ()
+ {
+ try {
+ InitializeComponent ();
+ }catch (Exception e){
+ System.Diagnostics.Debug.WriteLine (e.Message);
+ }
+ }
+
+ internal void OnSetStyleButtonClicked(object sender, EventArgs args)
+ {
+ Style style = (Style)Resources["buttonStyle"];
+ SetButtonStyle(style);
+ }
+
+ internal void OnUnsetStyleButtonClicked(object sender, EventArgs args)
+ {
+ SetButtonStyle (null);
+ }
+
+ internal void OnSetLocalButtonClicked(object sender, EventArgs args)
+ {
+ EnumerateButtons ((Button button) => {
+ button.TextColor = Color.Red;
+ button.FontAttributes = FontAttributes.Bold;
+ });
+ }
+
+ internal void OnClearLocalButtonClicked(object sender, EventArgs args)
+ {
+ EnumerateButtons ((Button button) => {
+ button.ClearValue (Button.TextColorProperty);
+ button.ClearValue (Button.FontAttributesProperty);
+ });
+ }
+
+ void SetButtonStyle(Style style)
+ {
+ EnumerateButtons (button => {
+ button.Style = style;
+ });
+ }
+
+ void EnumerateButtons(Action<Button> action)
+ {
+ foreach (View view in stackLayout.Children)
+ action ((Button)view);
+ }
+ }
+#endif
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2775.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2775.cs
new file mode 100644
index 00000000..f0ea174a
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2775.cs
@@ -0,0 +1,116 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.Generic;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2775, "ViewCell background conflicts with ListView Semi-Transparent and Transparent backgrounds")]
+ public class Issue2775 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ var list = new ListView {
+ ItemsSource = GetList ("Normal BG Blue"),
+ BackgroundColor = Color.Blue,
+ ItemTemplate = new DataTemplate (typeof(NormalCell))
+ };
+
+ var listTransparent = new ListView {
+ ItemsSource = GetList ("Normal BG Transparent"),
+ BackgroundColor = Color.Transparent,
+ ItemTemplate = new DataTemplate (typeof(NormalCell))
+ };
+
+ var listSemiTransparent = new ListView {
+ ItemsSource = GetList ("Normal BG SEMI Transparent"),
+ BackgroundColor = Color.FromHex("#801B2A39"),
+ ItemTemplate = new DataTemplate (typeof(NormalCell))
+ };
+
+ var listContextActions = new ListView {
+ ItemsSource = GetList ("ContextActions BG PINK"),
+ BackgroundColor = Color.Pink,
+ ItemTemplate = new DataTemplate (typeof(ContextActionsCell))
+ };
+
+ var listContextActionsTransparent = new ListView {
+ ItemsSource = GetList ("ContextActions BG Transparent"),
+ BackgroundColor = Color.Transparent,
+ ItemTemplate = new DataTemplate (typeof(ContextActionsCell))
+ };
+
+ var listContextActionsSemiTransparent = new ListView {
+ ItemsSource = GetList ("ContextActions BG Semi Transparent"),
+ BackgroundColor = Color.FromHex("#801B2A39"),
+ ItemTemplate = new DataTemplate (typeof(ContextActionsCell))
+ };
+
+ Content = new StackLayout {
+ Children = {
+ list,
+ listTransparent,
+ listSemiTransparent,
+ listContextActions,
+ listContextActionsTransparent,
+ listContextActionsSemiTransparent
+ },
+ BackgroundColor = Color.Red
+ };
+ }
+
+ [Preserve (AllMembers = true)]
+ internal class ContextActionsCell : ViewCell
+ {
+ public ContextActionsCell ()
+ {
+ ContextActions.Add (new MenuItem{ Text = "action" });
+ var label = new Label ();
+ label.SetBinding (Label.TextProperty, "Name");
+ View = label;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ internal class NormalCell : ViewCell
+ {
+ public NormalCell ()
+ {
+ var label = new Label ();
+ label.SetBinding (Label.TextProperty, "Name");
+ View = label;
+ }
+ }
+
+ List<ListItemViewModel> GetList (string description)
+ {
+ var itemList = new List<ListItemViewModel> ();
+ for (var i = 1; i < 3; i++) {
+ itemList.Add (new ListItemViewModel () { Name = description });
+ }
+ return itemList;
+ }
+
+ [Preserve (AllMembers = true)]
+ public class ListItemViewModel
+ {
+ public string Name { get; set; }
+ }
+
+#if UITEST
+ [Test]
+ public void Issue2775Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue 2775");
+ //RunningApp.WaitForElement (q => q.Marked ("IssuePageLabel"));
+ RunningApp.Screenshot ("I see the Label");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2777.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2777.xaml
new file mode 100644
index 00000000..b5959511
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2777.xaml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<local:TestContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Controls"
+ x:Class="Xamarin.Forms.Controls.Issue2777">
+ <local:TestContentPage.Content>
+ <ListView x:Name="itemListView" IsGroupingEnabled="true" ItemTapped="OnItemTapped">
+ <ListView.GroupHeaderTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <Label Text="{Binding LongTitle}" TextColor="Blue" />
+ </ViewCell>
+ </DataTemplate>
+ </ListView.GroupHeaderTemplate>
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <TextCell Text="{Binding Name}">
+ </TextCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </local:TestContentPage.Content>
+</local:TestContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2777.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2777.xaml.cs
new file mode 100644
index 00000000..545600c1
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2777.xaml.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms;
+using System.Collections.ObjectModel;
+using System.Linq;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2777, "When add GroupHeaderTemplate in XAML the group header does not show up")]
+ public partial class Issue2777 : TestContentPage
+ {
+ public Issue2777 ()
+ {
+ #if APP
+ InitializeComponent ();
+ var list = SetupList ();
+ itemListView.ItemsSource = list;
+ #endif
+
+ }
+
+ protected override void Init ()
+ {
+
+ }
+
+ internal void OnItemTapped (object sender, ItemTappedEventArgs ea)
+ {
+ var listItem = (ListItemValue)ea.Item;
+ DisplayAlert (listItem.Name, "You tapped " + listItem.Name, "OK", "Cancel");
+ }
+
+ ObservableCollection<ListItemCollection> SetupList ()
+ {
+ var allListItemGroups = new ObservableCollection<ListItemCollection> ();
+
+ foreach (var item in ListItemCollection.GetSortedData()) {
+ // Attempt to find any existing groups where theg group title matches the first char of our ListItem's name.
+ var listItemGroup = allListItemGroups.FirstOrDefault (g => g.Title == item.Label);
+
+ // If the list group does not exist, we create it.
+ if (listItemGroup == null) {
+ listItemGroup = new ListItemCollection (item.Label);
+ listItemGroup.Add (item);
+ allListItemGroups.Add (listItemGroup);
+ } else { // If the group does exist, we simply add the demo to the existing group.
+ listItemGroup.Add (item);
+ }
+ }
+ return allListItemGroups;
+ }
+
+ // Represents a group of items in our list.
+ [Preserve (AllMembers = true)]
+ public class ListItemCollection : ObservableCollection<ListItemValue>
+ {
+ public string Title { get; private set; }
+
+ public string LongTitle { get { return "The letter " + Title; } }
+
+ public ListItemCollection (string title)
+ {
+ Title = title;
+ }
+
+ public static List<ListItemValue> GetSortedData ()
+ {
+ var items = ListItems;
+ items.Sort ();
+ return items;
+ }
+
+ // Data used to populate our list.
+ static readonly List<ListItemValue> ListItems = new List<ListItemValue> () {
+ new ListItemValue ("Babbage"),
+ new ListItemValue ("Boole"),
+ new ListItemValue ("Berners-Lee"),
+ new ListItemValue ("Atanasoff"),
+ new ListItemValue ("Allen"),
+ new ListItemValue ("Cormack"),
+ new ListItemValue ("Cray"),
+ new ListItemValue ("Dijkstra"),
+ new ListItemValue ("Dix"),
+ new ListItemValue ("Dewey"),
+ new ListItemValue ("Erdős"),
+ };
+ }
+
+ // Represents one item in our list.
+ [Preserve (AllMembers = true)]
+ public class ListItemValue : IComparable<ListItemValue>
+ {
+ public string Name { get; private set; }
+
+
+ public ListItemValue (string name)
+ {
+ Name = name;
+ }
+
+ int IComparable<ListItemValue>.CompareTo (ListItemValue value)
+ {
+ return Name.CompareTo (value.Name);
+ }
+
+ public string Label {
+ get {
+ return Name [0].ToString ();
+ }
+ }
+ }
+
+
+ #if UITEST
+ [Test]
+ public void Issue2777Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue 2965");
+ RunningApp.WaitForElement (q => q.Marked ("The letter A"));
+ }
+ #endif
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2783.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2783.cs
new file mode 100644
index 00000000..5ff83c1c
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2783.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2783, "MemoryLeak in FrameRenderer", PlatformAffected.Android, NavigationBehavior.PushModalAsync)]
+ public class Issue2783 : ContentPage
+ {
+ public Issue2783 ()
+ {
+ Frame frPatientInfo = new Frame
+ {
+ OutlineColor = Color.Black,
+ BackgroundColor = Color.White,
+ HasShadow = true,
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.Center,
+ Padding = 5,
+ Content = new AbsoluteLayout {
+ BackgroundColor = Color.Red,
+ HeightRequest = 1000,
+ WidthRequest = 2000,
+ }
+ };
+
+ Content = frPatientInfo;
+
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2794.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2794.cs
new file mode 100644
index 00000000..6eaf2b45
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2794.cs
@@ -0,0 +1,48 @@
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2794, "TableView does not react on underlying collection change", PlatformAffected.Android)]
+ public class Issue2794 : ContentPage
+ {
+ TableSection _dataSection;
+
+ public Issue2794 ()
+ {
+
+ var tableView = new TableView ();
+ _dataSection = new TableSection ();
+ var cell1 = new TextCell { Text = "Cell1" };
+ cell1.ContextActions.Add (new MenuItem {
+ Text = "Delete me after",
+ IsDestructive = true,
+ Command = new Command (Delete),
+ CommandParameter = 0
+ });
+
+ var cell2 = new TextCell { Text = "Cell2" };
+ cell2.ContextActions.Add (new MenuItem {
+ Text = "Delete me first",
+ IsDestructive = true,
+ Command = new Command (Delete),
+ CommandParameter = 1
+ });
+
+ _dataSection.Add (cell1);
+ _dataSection.Add (cell2);
+ tableView.Root.Add (_dataSection);
+
+ Content = tableView;
+ }
+
+ protected void Delete(object parameters)
+ {
+ int rowId = (int)parameters;
+ _dataSection.RemoveAt (rowId);
+ }
+ }
+}
+
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2809.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2809.cs
new file mode 100644
index 00000000..44746217
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2809.cs
@@ -0,0 +1,50 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+using Xamarin.UITest.Android;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 2809, "Secondary ToolbarItems cause app to hang during PushAsync", PlatformAffected.iOS)]
+ public class Issue2809: TestContentPage
+ {
+ protected override void Init ()
+ {
+ ToolbarItems.Add(new ToolbarItem("Item 1", string.Empty,
+ DummyAction, ToolbarItemOrder.Secondary));
+
+ ToolbarItems.Add(new ToolbarItem("Item 2", string.Empty,
+ DummyAction, ToolbarItemOrder.Secondary));
+ }
+
+ public void DummyAction()
+ {
+ }
+
+#if UITEST
+ [Test]
+ public void TestPageDoesntCrash ()
+ {
+ ShouldShowMenu();
+ RunningApp.Tap (c => c.Marked ("Item 1"));
+ RunningApp.Screenshot ("Didn't crash");
+ }
+
+ void ShouldShowMenu ()
+ {
+ if (RunningApp is AndroidApp) {
+ //show secondary menu
+ RunningApp.Tap (c => c.Class ("android.support.v7.widget.ActionMenuPresenter$OverflowMenuButton"));
+ }
+ }
+
+#endif
+
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2883.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2883.cs
new file mode 100644
index 00000000..12ed2006
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2883.cs
@@ -0,0 +1,125 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.Generic;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+using Xamarin.UITest.iOS;
+
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2883, "ViewCell IsEnabled set to false does not disable a cell in a TableView")]
+ public class Issue2883 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var btnCustom1 = new Button () {
+ AutomationId = "btnCustomCellTable",
+ Text = "Custom Table Cell" ,
+ HorizontalOptions = LayoutOptions.Start
+ };
+ var btnCustom1Enabled = new Button () {
+ AutomationId = "btnCustomCellTableEnabled",
+ Text = "Custom Table Cell Enabled" ,
+ HorizontalOptions = LayoutOptions.Start
+ };
+
+ var btnCustom = new Button () {
+ AutomationId = "btnCustomCellListView",
+ Text = "Custom Cell" ,
+ HorizontalOptions = LayoutOptions.Start
+ };
+
+ var btnCustomEnabled = new Button () {
+ AutomationId = "btnCustomCellListViewEnabled",
+ Text = "Custom Cell Enabled" ,
+ HorizontalOptions = LayoutOptions.Start
+ };
+
+ btnCustom.Clicked += (object sender, EventArgs e) => {
+ DisplayAlert ("Clicked", "I was clicked even disabled", "ok");
+ };
+ btnCustom1.Clicked += (object sender, EventArgs e) => {
+ DisplayAlert ("Clicked", "I was clicked even disabled", "ok");
+ };
+
+ btnCustom1Enabled.Clicked += (object sender, EventArgs e) => {
+ DisplayAlert ("Clicked", "I was clicked", "ok");
+ };
+ btnCustomEnabled.Clicked += (object sender, EventArgs e) => {
+ DisplayAlert ("Clicked", "I was clicked", "ok");
+ };
+
+ var customCell = new ViewCell () {
+ IsEnabled = false,
+ View = new StackLayout { Children = { btnCustom } }
+ };
+
+ var customCellEnabled = new ViewCell () {
+ View = new StackLayout { Children = { btnCustomEnabled } }
+ };
+
+ var customTableCell = new ViewCell () {
+ IsEnabled = false,
+ View = new StackLayout { Children = { btnCustom1 } }
+ };
+
+ var customTableCellEnabled = new ViewCell () {
+ View = new StackLayout { Children = { btnCustom1Enabled } }
+ };
+
+ var tableview = new TableView () {
+ Intent = TableIntent.Form,
+ Root = new TableRoot (),
+ VerticalOptions = LayoutOptions.Start
+ };
+
+ tableview.Root.Add (new TableSection () { customTableCell, customTableCellEnabled });
+
+ var listview = new ListView { VerticalOptions = LayoutOptions.Start };
+ var listview2 = new ListView { VerticalOptions = LayoutOptions.Start };
+
+ listview.ItemTemplate = new DataTemplate (() => customCell);
+ listview2.ItemTemplate = new DataTemplate (() => customCellEnabled);
+ listview2.ItemsSource = listview.ItemsSource = new List<string> () { "1" };
+
+ Content = new StackLayout {
+ Orientation = StackOrientation.Vertical,
+ VerticalOptions = LayoutOptions.Start,
+ Children = { tableview, listview, listview2 }
+ };
+ }
+
+ #if UITEST
+ [Test]
+ public void Issue2883TestDisabled ()
+ {
+ RunningApp.Screenshot ("I am at Issue 2883");
+ RunningApp.Tap( c=> c.Marked("btnCustomCellTable"));
+ RunningApp.WaitForNoElement( c=> c.Marked("Clicked"));
+ RunningApp.Screenshot ("I dont see the disable cell");
+ RunningApp.Tap( c=> c.Marked("btnCustomCellListView"));
+ RunningApp.WaitForNoElement( c=> c.Marked("Clicked"));
+ RunningApp.Screenshot ("I dont see the disable cell");
+ }
+
+ [Test]
+ public void Issue2883TestEnabled ()
+ {
+
+ RunningApp.Tap( c=> c.Marked("btnCustomCellTableEnabled"));
+ RunningApp.Screenshot ("I see the cell that is enabled");
+ RunningApp.WaitForElement( c=> c.Marked("Clicked"));
+ RunningApp.Tap (c => c.Marked ("ok"));
+ RunningApp.Tap( c=> c.Marked("btnCustomCellListViewEnabled"));
+ RunningApp.WaitForElement( c=> c.Marked("Clicked"));
+ RunningApp.Tap (c => c.Marked ("ok"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2923.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2923.cs
new file mode 100644
index 00000000..68768459
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2923.cs
@@ -0,0 +1,83 @@
+using System.Collections.ObjectModel;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2923, "First tab does not load until navigating", PlatformAffected.WinRT)]
+ public class Issue2923 : TestTabbedPage
+ {
+ protected override void Init()
+ {
+ var tabOne = new ContentPage {
+ Title = "Page One",
+ BackgroundColor = Color.Blue,
+ };
+
+ var tabTwo = new ContentPage {
+ Title = "Page Two",
+ BackgroundColor = Color.Red,
+ Content = new Label {
+ AutomationId = "SecondPageLabel",
+ Text = "Second Page"
+ }
+ };
+
+ var buttonResetTabbedPage = new Button {
+ Text = "Reset",
+ AutomationId = "ResetButton",
+ Command = new Command (() => {
+
+ Children.Remove (tabOne);
+ Children.Remove (tabTwo);
+
+ Children.Add (new ContentPage {
+ Title = "Reset page",
+ BackgroundColor = Color.Green,
+ Content = new Label {
+ AutomationId = "ResetPageLabel",
+ Text = "I was reset"
+ }
+ });
+
+ })
+ };
+
+ tabOne.Content = new StackLayout {
+ Children = {
+ new Label {
+ AutomationId = "FirstPageLabel",
+ Text = "First Page"
+ },
+ buttonResetTabbedPage
+ }
+ };
+
+ Children.Add (tabOne);
+ Children.Add (tabTwo);
+ }
+
+#if UITEST
+ [Test]
+ public void Issue2923TestOne ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("FirstPageLabel"));
+ RunningApp.Screenshot ("First Tab is showing");
+ }
+
+ [Test]
+ public void Issue2923TestTwo ()
+ {
+ RunningApp.Tap (q => q.Marked ("ResetButton"));
+ RunningApp.Screenshot ("Tabs Reset");
+ RunningApp.WaitForElement (q => q.Marked ("ResetPageLabel"));
+ }
+#endif
+
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2927.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2927.cs
new file mode 100644
index 00000000..02db4696
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2927.cs
@@ -0,0 +1,105 @@
+using System;
+using System.ComponentModel;
+using Xamarin.Forms.Controls;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2927, "ListView item tapped not firing multiple times")]
+ public class Issue2927 : TestContentPage // or TestMasterDetailPage, etc .
+ {
+ [Preserve (AllMembers = true)]
+ public class Issue2927Cell : TextCell, INotifyPropertyChanged
+ {
+ int _numberOfTimesTapped;
+ string _text;
+ string _cellId;
+
+ public Issue2927Cell (string id)
+ {
+ _cellId = id;
+ NumberOfTimesTapped = 0;
+ }
+
+ void OnPropertyChanged (string prop)
+ {
+ var handler = PropertyChanged;
+ if (handler != null) {
+ handler(this, new PropertyChangedEventArgs(prop));
+ }
+ }
+
+ public int NumberOfTimesTapped
+ {
+ get { return _numberOfTimesTapped; }
+ set {
+ _numberOfTimesTapped = value;
+ Text = _cellId + " " + _numberOfTimesTapped.ToString ();
+ }
+ }
+
+ public string Text {
+ get { return _text; }
+ set {
+ _text = value;
+ OnPropertyChanged ("Text");
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ }
+
+ protected override void Init ()
+ {
+ var cells = new[] {
+ new Issue2927Cell ("Cell1"),
+ new Issue2927Cell ("Cell2"),
+ new Issue2927Cell ("Cell3"),
+ };
+
+ BindingContext = cells;
+ var template = new DataTemplate (typeof (TextCell));
+ template.SetBinding (TextCell.TextProperty, "Text");
+
+ var listView = new ListView {
+ ItemTemplate = template,
+ ItemsSource = cells
+ };
+
+ listView.ItemTapped += (s, e) => {
+ var obj = (Issue2927Cell)e.Item;
+ obj.NumberOfTimesTapped += 1;
+ };
+
+ Content = listView;
+ }
+
+#if UITEST
+ [Test]
+ public void Issue2927Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue 2927");
+ RunningApp.WaitForElement (q => q.Marked ("Cell1 0"));
+ RunningApp.Tap (q => q.Marked ("Cell1 0"));
+ RunningApp.WaitForElement (q => q.Marked ("Cell1 1"));
+ RunningApp.Screenshot ("Tapped Once");
+ RunningApp.Tap (q => q.Marked ("Cell1 1"));
+ RunningApp.WaitForElement (q => q.Marked ("Cell1 2"));
+ RunningApp.Screenshot ("Tapped Twice");
+ RunningApp.Tap (q => q.Marked ("Cell3 0"));
+ RunningApp.WaitForElement (q => q.Marked ("Cell3 1"));
+ RunningApp.Screenshot ("Click other cell");
+ RunningApp.Tap (q => q.Marked ("Cell1 2"));
+ RunningApp.WaitForElement (q => q.Marked ("Cell1 3"));
+ RunningApp.Screenshot ("Click first cell again");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2948.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2948.cs
new file mode 100644
index 00000000..b763c9e7
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2948.cs
@@ -0,0 +1,232 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.Generic;
+using System.Threading;
+
+#if UITEST
+using Xamarin.UITest;
+using Xamarin.UITest.iOS;
+using Xamarin.UITest.Android;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2948, "MasterDetailPage Detail is interactive even when Master is open when in Landscape")]
+ public class Issue2948 : TestMasterDetailPage
+ {
+ static MasterDetailPage s_mdp;
+
+ protected override void Init ()
+ {
+ s_mdp = this;
+ var menuPage = new MenuPage ();
+
+ menuPage.Menu.ItemSelected += (sender, e) => NavigateTo (e.SelectedItem as MenuItem);
+
+ Master = menuPage;
+ Detail = new NavigationPage (new ContractsPage ());
+ }
+
+ [Preserve (AllMembers = true)]
+ public class MenuListData : List<MenuItem>
+ {
+ public MenuListData ()
+ {
+ Add (new MenuItem () {
+ Title = "Contracts",
+ IconSource = "bank.png",
+ TargetType = typeof(ContractsPage)
+ });
+
+ Add (new MenuItem () {
+ Title = "Leads",
+ IconSource = "bank.png",
+ TargetType = typeof(ContractsPage)
+ });
+
+ Add (new MenuItem () {
+ Title = "Accounts",
+ IconSource = "bank.png",
+ TargetType = typeof(ContractsPage)
+ });
+
+ Add (new MenuItem () {
+ Title = "Opportunities",
+ IconSource = "bank.png",
+ TargetType = typeof(ContractsPage)
+ });
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class ContractsPage : ContentPage
+ {
+ public ContractsPage ()
+ {
+ Title = "Contracts";
+ Icon = "bank.png";
+
+ var grid = new Grid();
+ grid.ColumnDefinitions.Add(new ColumnDefinition());
+ grid.ColumnDefinitions.Add(new ColumnDefinition());
+
+ var btn = new Button {
+ HeightRequest = 300,
+ HorizontalOptions = LayoutOptions.End,
+ BackgroundColor = Color.Pink,
+ AutomationId = "btnOnDetail"
+ };
+
+ btn.Clicked+= (object sender, EventArgs e) => {
+ DisplayAlert("Clicked","I was clicked","Ok");
+ };
+
+ Grid.SetColumn(btn,1);
+
+ grid.Children.Add(btn);
+
+ var showMasterButton = new Button {
+ AutomationId = "ShowMasterBtn",
+ Text = "Show Master"
+ };
+ showMasterButton.Clicked += (sender, e) => {
+ s_mdp.IsPresented = true;
+ };
+
+ Content = new ScrollView {
+
+ Content = new StackLayout {
+ Children = {
+ showMasterButton,
+ grid,
+ new BoxView {
+ HeightRequest = 100,
+ Color = Color.Red,
+ },
+ new BoxView {
+ HeightRequest = 200,
+ Color = Color.Green,
+ },
+ new BoxView {
+ HeightRequest = 300,
+ Color = Color.Red,
+ },
+ new BoxView {
+ HeightRequest = 400,
+ Color = Color.Green,
+ },
+ new BoxView {
+ HeightRequest = 500,
+ Color = Color.Red,
+ }
+ }
+ },
+
+ };
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class MenuListView : ListView
+ {
+ public MenuListView ()
+ {
+ List<MenuItem> data = new MenuListData ();
+
+ ItemsSource = data;
+ VerticalOptions = LayoutOptions.FillAndExpand;
+ BackgroundColor = Color.Transparent;
+
+ var cell = new DataTemplate (typeof(ImageCell));
+ cell.SetBinding (TextCell.TextProperty, "Title");
+ cell.SetBinding (ImageCell.ImageSourceProperty, "IconSource");
+
+ ItemTemplate = cell;
+ SelectedItem = data [0];
+ }
+ }
+
+ public class MenuPage : ContentPage
+ {
+ public ListView Menu { get; set; }
+
+ public MenuPage ()
+ {
+ Title = "Menu";
+ BackgroundColor = Color.FromHex ("333333");
+
+ Menu = new MenuListView ();
+
+ var menuLabel = new ContentView {
+ Padding = new Thickness (10, 36, 0, 5),
+ Content = new Label {
+ TextColor = Color.FromHex ("AAAAAA"),
+ Text = "MENU",
+ }
+ };
+
+ var layout = new StackLayout {
+ Spacing = 0,
+ VerticalOptions = LayoutOptions.FillAndExpand
+ };
+ layout.Children.Add (menuLabel);
+ layout.Children.Add (Menu);
+
+ Content = layout;
+ }
+ }
+
+ void NavigateTo (MenuItem menu)
+ {
+ var displayPage = (Page)Activator.CreateInstance (menu.TargetType);
+
+ Detail = new NavigationPage (displayPage);
+
+ }
+
+ [Preserve (AllMembers = true)]
+ public class MenuItem
+ {
+ public string Title { get; set; }
+
+ public string IconSource { get; set; }
+
+ public Type TargetType { get; set; }
+ }
+
+#if UITEST
+ [Test]
+ public void Issue2948Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue 2948");
+ RunningApp.SetOrientationLandscape ();
+ Thread.Sleep (5000);
+ if (ShouldRunTest ()) {
+ OpenMDP ();
+ var btns = RunningApp.Query (c => c.Marked ("btnOnDetail"));
+ if (btns.Length > 0) {
+ // on iOS the button could be out of screen
+ RunningApp.Tap (c => c.Marked ("btnOnDetail"));
+ RunningApp.Screenshot ("I in landscape and master is open");
+ }
+ RunningApp.WaitForNoElement (c => c.Marked ("Clicked"),"Time out",new TimeSpan(0,0,1));
+ }
+ }
+
+ public bool ShouldRunTest() {
+ var isMasterVisible = RunningApp.Query (q => q.Marked ("Leads")).Length > 0;
+ return !isMasterVisible;
+ }
+ public void OpenMDP() {
+ if (RunningApp is iOSApp) {
+ RunningApp.Tap (q => q.Marked ("Menu"));
+ } else {
+ RunningApp.Tap ("ShowMasterBtn");
+ }
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2951.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2951.xaml
new file mode 100644
index 00000000..a4942512
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2951.xaml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<controls:TestContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:controls="clr-namespace:Xamarin.Forms.Controls;assembly=Xamarin.Forms.Controls" x:Name="ThePageIssue2951" x:Class="Xamarin.Forms.Controls.Issue2951">
+ <controls:TestContentPage.Resources>
+ <ResourceDictionary>
+ <Style x:Key="ButtonStyle" TargetType="Button">
+ <Setter Property="BackgroundColor" Value="Silver" />
+ <Setter Property="TextColor" Value="Black" />
+ <Style.Triggers>
+ <Trigger Property="controls:ButtonExtensions.IsPrimary" Value="True" TargetType="Button">
+ <Setter Property="BackgroundColor" Value="#FAC54A" />
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ <Style x:Key="ChangeStatusButton" TargetType="Button" BasedOn="{StaticResource ButtonStyle}">
+ <Setter Property="controls:ButtonExtensions.IsPrimary" Value="False" />
+ <Setter Property="Text" Value="A" />
+ <Setter Property="Command" Value="{Binding Source={x:Reference ThePageIssue2951},Path=BindingContext.ButtonTapped}" />
+ <Setter Property="CommandParameter" Value="{Binding .}" />
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding IsStarted}" Value="True" TargetType="Button">
+ <Setter Property="controls:ButtonExtensions.IsPrimary" Value="True" />
+ <Setter Property="Text" Value="B" />
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ <DataTemplate x:Key="TheItemTemplate">
+ <ViewCell>
+ <ViewCell.View>
+ <Grid Padding="12,5" RowSpacing="4">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="75" />
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+ <Label Grid.Column="0" Text="{Binding Name}" TextColor="Yellow" />
+ <Button AutomationId="btnChangeStatus" Grid.Column="1" Style="{StaticResource ChangeStatusButton}" />
+ </Grid>
+ </ViewCell.View>
+ </ViewCell>
+ </DataTemplate>
+ </ResourceDictionary>
+ </controls:TestContentPage.Resources>
+ <controls:TestContentPage.Content>
+ <ListView ItemTemplate="{StaticResource TheItemTemplate}" ItemsSource="{Binding Items}" RowHeight="74" />
+ </controls:TestContentPage.Content>
+</controls:TestContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2951.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2951.xaml.cs
new file mode 100644
index 00000000..fb4b75ea
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2951.xaml.cs
@@ -0,0 +1,140 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+#if UITEST
+using Xamarin.UITest.Queries;
+using NUnit.Framework;
+#endif
+
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2951, "On Android, button background is not updated when color changes ")]
+ public partial class Issue2951 : TestContentPage
+ {
+ public Issue2951 ()
+ {
+ #if APP
+ InitializeComponent ();
+ #endif
+ }
+
+ protected override void Init ()
+ {
+ BindingContext = new MyViewModel ();
+ }
+
+ [Preserve (AllMembers = true)]
+ public class MyViewModel
+ {
+ public ObservableCollection<MyItemViewModel> Items { get; private set; }
+
+ public Command<MyItemViewModel> ButtonTapped { get; private set; }
+
+ public MyViewModel ()
+ {
+ ButtonTapped = new Command<MyItemViewModel> (OnItemTapped);
+
+ Items = new ObservableCollection<MyItemViewModel> ();
+
+ Items.Add (new MyItemViewModel { Name = "A", IsStarted = false });
+ Items.Add (new MyItemViewModel { Name = "B", IsStarted = false });
+ Items.Add (new MyItemViewModel { Name = "C", IsStarted = false });
+ }
+
+ void OnItemTapped (MyItemViewModel model)
+ {
+ if (model.IsStarted) {
+ Items.Remove (model);
+ } else {
+ model.IsStarted = true;
+ }
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class MyItemViewModel : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ string _name;
+
+ public string Name {
+ get { return _name; }
+ set {
+ _name = value;
+ OnPropertyChanged ("Name");
+ }
+ }
+
+ bool _isStarted;
+
+ public bool IsStarted {
+ get { return _isStarted; }
+ set {
+ _isStarted = value;
+ OnPropertyChanged ("IsStarted");
+ }
+ }
+
+ void OnPropertyChanged (string propertyName)
+ {
+ if (PropertyChanged != null) {
+ PropertyChanged (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+ }
+
+ #if UITEST
+ [Test]
+ public void Issue2951Test ()
+ {
+ var bt = RunningApp.WaitForElement (c => c.Marked ("btnChangeStatus"));
+ var buttons = RunningApp.Query (c => c.Marked ("btnChangeStatus"));
+ Assert.That (buttons.Length, Is.EqualTo (3));
+ RunningApp.Tap(c => c.Marked ("btnChangeStatus").Index(1));
+ buttons = RunningApp.Query (c => c.Marked ("btnChangeStatus"));
+ var text = buttons [1].Text ?? buttons [1].Label;
+ Assert.That (text, Is.EqualTo ("B"));
+ RunningApp.Tap(c => c.Marked ("btnChangeStatus").Index(1));
+ buttons = RunningApp.Query (c => c.Marked ("btnChangeStatus"));
+ Assert.That (buttons.Length, Is.EqualTo (2));
+ //TODO: we should check the color of the button
+ //var buttonTextColor = GetProperty<Color> ("btnChangeStatus", Button.BackgroundColorProperty);
+ //Assert.AreEqual (Color.Pink, buttonTextColor);
+ }
+
+
+ #endif
+ }
+
+
+
+
+ [Preserve (AllMembers = true)]
+ public class ButtonExtensions
+ {
+ public static readonly BindableProperty IsPrimaryProperty = BindableProperty.CreateAttached<ButtonExtensions, bool> (
+ bindable => GetIsPrimary (bindable),
+ false,
+ BindingMode.TwoWay,
+ null,
+ null,
+ null,
+ null);
+
+ public static bool GetIsPrimary (BindableObject bo)
+ {
+ return (bool)bo.GetValue (IsPrimaryProperty);
+ }
+
+ public static void SetIsPrimary (BindableObject bo, bool value)
+ {
+ bo.SetValue (IsPrimaryProperty, value);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2953.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2953.cs
new file mode 100644
index 00000000..28aed46e
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2953.cs
@@ -0,0 +1,89 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.ObjectModel;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2953, "GroupHeaderCells disappear when item is removed from a group in ListView (iOS only) ")]
+ public class Issue2953 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var items = new ObservableCollection<GroupedItems> () {
+ new GroupedItems ("Header 1") { "1.1", "1.2", "1.3" },
+ new GroupedItems ("Header 2") { "2.1", "2.2", "2.3" },
+ new GroupedItems ("Header 3") { "3.1", "3.2", "3.3" },
+ new GroupedItems ("Header 4") { "4.1", "4.2", "4.3" },
+ };
+
+ var listview = new ListView {
+ HasUnevenRows = true,
+ IsGroupingEnabled = true
+ };
+
+ listview.GroupHeaderTemplate = new DataTemplate
+ (typeof(HeaderCell));
+ listview.ItemTemplate = new DataTemplate (typeof(ItemCell));
+ listview.ItemsSource = items;
+
+ var btnRemove = new Button () { Text = "Remove", AutomationId="btnRemove" };
+ btnRemove.Clicked += delegate {
+ if (items[1].Count > 0) {
+ items[1].RemoveAt(0);
+ }
+ };
+
+ Content = new StackLayout {
+ Orientation = StackOrientation.Vertical,
+ Children = { listview, btnRemove }
+ };
+ }
+
+ [Preserve (AllMembers = true)]
+ internal class GroupedItems : ObservableCollection<string> {
+ public GroupedItems (string groupName) { GroupName = groupName; }
+ public string GroupName { get; private set; }
+ }
+
+ [Preserve (AllMembers = true)]
+ internal class HeaderCell : ViewCell
+ {
+ public HeaderCell () {
+ Height = 44;
+ var label = new Label { BackgroundColor = Color.Pink };
+ label.SetBinding (Label.TextProperty, "GroupName");
+ View = label;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ internal class ItemCell : ViewCell
+ {
+ public ItemCell () {
+ var label = new Label { BackgroundColor = Color.Aqua };
+ label.SetBinding (Label.TextProperty, ".");
+ View = label;
+ }
+ }
+
+#if UITEST
+ [Test]
+ public void Issue2953Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue 2953");
+ RunningApp.WaitForElement (q => q.Marked ("Header 3"));
+ RunningApp.Screenshot ("I see the Header 3");
+ RunningApp.Tap (q => q.Marked ("btnRemove"));
+ RunningApp.WaitForElement (q => q.Marked ("Header 3"));
+ RunningApp.Screenshot ("I still see the Header 3");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2954.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2954.cs
new file mode 100644
index 00000000..6c645eeb
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2954.cs
@@ -0,0 +1,58 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2954, "Cell becomes empty after adding a new one with context actions (TableView) ")]
+ public class Issue2954 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ TableSection _dataSection;
+ TableView _tableView;
+ int _count = 0;
+ protected override void Init ()
+ {
+ _dataSection = new TableSection {
+ new TextCell{ Text = "Cell1" },
+ new TextCell{ Text = "Cell2", ContextActions = { new MenuItem{ Text = "Delete" } } },
+ new TextCell{ Text = "Add new", Command = new Command (AddNew) }
+ };
+
+ _tableView = new TableView {
+ Root = new TableRoot {
+ _dataSection
+ }
+ };
+
+ Content = _tableView;
+ }
+
+ void AddNew (object parameters)
+ {
+ _count++;
+ _dataSection.Insert (0, new TextCell { Text = "Fresh cell " + _count
+ , ContextActions = { new MenuItem{ Text = "Delete" } }
+ });
+ _tableView.Root = _tableView.Root; //HACK - force table reload
+ }
+
+ #if UITEST
+ [Test]
+ public void Issue2954Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue 2954");
+ RunningApp.WaitForElement (q => q.Marked ("Cell2"));
+ RunningApp.Screenshot ("I see the Cell2");
+ RunningApp.Tap(c => c.Marked("Add new"));
+ RunningApp.WaitForElement (q => q.Marked ("Cell2"));
+ RunningApp.Screenshot ("I still see the Cell2");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2961.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2961.cs
new file mode 100644
index 00000000..24665ea7
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2961.cs
@@ -0,0 +1,290 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+using System.ComponentModel;
+using System.Diagnostics;
+
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+using Xamarin.UITest.iOS;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+#if UITEST
+ [Ignore("This test is looking for an invalid behavior; the second tap *should* keep the drawer open.")]
+#endif
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2961, "MasterDetail NavigationDrawer Does Not Hide On DoubleTap of Item", PlatformAffected.Android)]
+ public class Issue2961 : TestMasterDetailPage
+ {
+ static MasterDetailPage s_mdp;
+
+ SliderMenuItem _selectedMenuItem;
+ SliderMenuPage _slidingPage;
+ ContentPage _displayPage;
+
+ protected override void Init ()
+ {
+ s_mdp = this;
+
+ _slidingPage = new SliderMenuPage {
+ Title = "Menu",
+ BackgroundColor = Color.FromHex ("1e1e1e")
+ };
+ _slidingPage.MenuListView.ItemTapped += (sender, e) => OnMenuSelected (e.Item as SliderMenuItem);
+ Padding = new Thickness (0);
+
+ Master = _slidingPage;
+ OnMenuSelected (_slidingPage.MenuListView.SelectedItem as SliderMenuItem);
+ }
+
+ void OnMenuSelected (SliderMenuItem menu)
+ {
+ Debug.WriteLine (IsPresented);
+
+ IsPresented = false;
+
+ if (menu == null || menu == _selectedMenuItem) {
+ return;
+ }
+ _displayPage = null;
+
+ if (menu.TargetType.Equals (typeof(SignOutPage))) {
+ HandleSignOut ();
+ return;
+ }
+ _displayPage = (ContentPage)Activator.CreateInstance (menu.TargetType);
+ Detail = new NavigationPage (_displayPage);
+
+ if (_selectedMenuItem != null) {
+ _selectedMenuItem.IsSelected = false;
+ }
+
+ _selectedMenuItem = menu;
+ _selectedMenuItem.IsSelected = true;
+ }
+
+ void HandleSignOut ()
+ {
+ DisplayAlert (
+ "",
+ "Do you want to sign out?",
+ "OK",
+ "Cancel"
+ );
+ }
+
+ [Preserve (AllMembers = true)]
+ public class SliderMenuItem: INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ void NotifyPropertyChanged (string info)
+ {
+ if (PropertyChanged != null) {
+ PropertyChanged (this, new PropertyChangedEventArgs (info));
+ }
+ }
+
+ public SliderMenuItem (string title, Type targetType)
+ {
+ Title = title;
+ TargetType = targetType;
+
+ }
+
+ public string Title { get; set; }
+
+ bool _isSelected;
+
+ public bool IsSelected {
+ get{ return _isSelected; }
+ set {
+ if (_isSelected != value) {
+ _isSelected = value;
+ Background = _isSelected ? Color.FromHex ("101010") : Color.Transparent;
+ NotifyPropertyChanged ("Background");
+ }
+ }
+ }
+
+ public Type TargetType { get; set; }
+
+ public Color Background { get; private set; }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class SliderMenuPage: ContentPage
+ {
+ public ListView MenuListView { get; set; }
+
+ public SliderMenuPage ()
+ {
+ var data = GetData ();
+ MenuListView = new ListView {
+ HorizontalOptions = LayoutOptions.StartAndExpand,
+ ItemTemplate = new DataTemplate (typeof(MenuCell)),
+ ItemsSource = data,
+ BackgroundColor = Color.FromHex ("1e1e1e"),
+ };
+
+ MenuListView.SelectedItem = data [0];
+ data [0].IsSelected = true;
+
+ var logoImg = new Image {
+ Source = ImageSource.FromFile ("bank.png"),
+ HorizontalOptions = LayoutOptions.Start,
+ VerticalOptions = LayoutOptions.EndAndExpand
+ };
+ var logoImgWrapper = new StackLayout {
+ Padding = new Thickness (12, 24),
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Children = { logoImg }
+ };
+
+ var paddingTop = Device.OnPlatform (40, 2, 2);
+ Content = new StackLayout {
+ Spacing = 0,
+ BackgroundColor = Color.FromHex ("1e1e1e"),
+ Padding = new Thickness (0, paddingTop, 0, 10),
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Children = {
+ MenuListView,
+ logoImgWrapper
+ }
+ };
+ }
+
+ SliderMenuItem[] GetData ()
+ {
+ return new [] {
+ new SliderMenuItem ("Home", typeof(HomePage)),
+ new SliderMenuItem ("About", typeof(AboutPage)),
+ new SliderMenuItem ("Sign Out", typeof(SignOutPage))
+ };
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class HomePage : ContentPage
+ {
+
+
+ public HomePage ()
+ {
+ var showMasterButton = new Button {
+ AutomationId = "ShowMasterBtnHome",
+ Text = "Show Master"
+ };
+ showMasterButton.Clicked += (sender, e) => {
+ s_mdp.IsPresented = true;
+ };
+
+ Content = new StackLayout {
+
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ HorizontalOptions = LayoutOptions.CenterAndExpand,
+ Children = {
+ showMasterButton,
+ new Label {
+ AutomationId = "lblHome",
+ Text = "Sample Home page",
+ XAlign = TextAlignment.Center,
+ YAlign = TextAlignment.Center
+ }
+ }
+ };
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class AboutPage: ContentPage
+ {
+ public AboutPage ()
+ {
+ var showMasterButton = new Button {
+ AutomationId = "ShowMasterBtnAbout",
+ Text = "Show Master"
+ };
+ showMasterButton.Clicked += (sender, e) => {
+ s_mdp.IsPresented = true;
+ };
+
+ Content = new StackLayout {
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ HorizontalOptions = LayoutOptions.CenterAndExpand,
+ Children = {
+ showMasterButton,
+ new Label {
+ AutomationId = "lblAbout",
+ Text = "Sample About page",
+ XAlign = TextAlignment.Center,
+ YAlign = TextAlignment.Center
+ }
+ }
+ };
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class SignOutPage
+ {
+ public SignOutPage ()
+ {
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class MenuCell: ViewCell
+ {
+ public MenuCell ()
+ {
+ Label textLabel = new Label {
+ FontSize = 18,
+ };
+
+ textLabel.SetBinding (Label.TextProperty, "Title");
+ var root = new StackLayout {
+ Padding = new Thickness (12, 8),
+ Children = { textLabel }
+ };
+ root.SetBinding (BackgroundColorProperty, "Background");
+ View = root;
+ }
+ }
+
+
+ #if UITEST
+ [Test]
+ public void Issue2961Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue 2961");
+ OpenMDP ("ShowMasterBtnHome");
+ RunningApp.Tap (c => c.Marked ("Home"));
+ RunningApp.WaitForElement (c => c.Marked ("lblHome"));
+ OpenMDP ("ShowMasterBtnHome");
+ RunningApp.Tap (c => c.Marked ("About"));
+ RunningApp.WaitForElement (c => c.Marked ("lblAbout"));
+ OpenMDP ("ShowMasterBtnAbout");
+ if(RunningApp is iOSApp)
+ return;
+ RunningApp.DoubleTap (c => c.Marked ("Home"));
+ RunningApp.WaitForElement (c => c.Marked ("lblHome"));
+ RunningApp.Tap (c => c.Marked ("About"));
+ RunningApp.WaitForNoElement (c => c.Marked ("Home"));
+
+ }
+
+ public void OpenMDP(string masterBtnId) {
+ if(RunningApp is iOSApp) {
+ RunningApp.Tap (q => q.Marked("Menu"));
+ } else {
+ RunningApp.Tap (masterBtnId);
+ }
+ }
+ #endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2963.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2963.cs
new file mode 100644
index 00000000..e84a47d1
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2963.cs
@@ -0,0 +1,53 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2963, "Disabling Editor in iOS does not disable entry of text")]
+ public class Issue2963 : TestContentPage
+ {
+ readonly string _editorId = "DisabledEditor";
+ readonly string _focusedLabelId = "FocusedLabel";
+
+ protected override void Init ()
+ {
+
+ var disabledEditor = new Editor {
+ AutomationId = _editorId,
+ Text = "You should not be able to edit me",
+ IsEnabled = false
+ };
+
+ BindingContext = disabledEditor;
+ var focusedLabel = new Label {
+ AutomationId = _focusedLabelId
+ };
+ focusedLabel.SetBinding (Label.TextProperty, "IsFocused");
+
+ Content = new StackLayout {
+ Children = {
+ disabledEditor,
+ focusedLabel,
+ }
+ };
+ }
+
+#if UITEST
+ [Test]
+ public void Issue2963Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue 2963");
+ RunningApp.Tap (q => q.Marked (_editorId));
+ Assert.AreEqual ("False", RunningApp.Query (q => q.Marked (_focusedLabelId))[0].Text);
+ RunningApp.Screenshot ("Label should still be false");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2964.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2964.cs
new file mode 100644
index 00000000..e86dad15
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2964.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using System.Linq;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2964, "TabbedPage toolbar item crash")]
+ public class Issue2964 : TestMasterDetailPage
+ {
+ public class ModalPage : ContentPage
+ {
+ public ModalPage ()
+ {
+ Content = new Button {
+ AutomationId = "ModalPagePopButton",
+ Text ="Pop Me",
+ Command = new Command (async () => {
+ MessagingCenter.Send (this, "update");
+ await Navigation.PopModalAsync ();
+ })
+ };
+ }
+ }
+
+ public class Page1 : ContentPage
+ {
+ public Page1 ()
+ {
+ Title = "Testpage 1";
+
+ MessagingCenter.Subscribe<ModalPage> (this, "update", sender => {
+ BlowUp ();
+ });
+
+ Content = new Button {
+ AutomationId = "Page1PushModalButton",
+ Text = "press me",
+ Command = new Command (async () => await Navigation.PushModalAsync (new ModalPage ()))
+ };
+ }
+
+ void BlowUp ()
+ {
+ Content = new Label {
+ AutomationId = "Page1Label",
+ Text = "Page1"
+ };
+ }
+ }
+
+ protected override void Init ()
+ {
+ Title = "Test";
+
+ Master = new ContentPage {
+ Title = "Master",
+ Content = new Button {
+ AutomationId = "MasterButton",
+ Text = "Make a new page",
+ Command= new Command(() => {
+ Detail = new Page1 ();
+ IsPresented = false;
+ })
+ }
+ };
+
+ Detail = new Page1 ();
+
+ IsPresented = true;
+ }
+
+#if UITEST
+ [Test]
+ public void Issue2964Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue 2964");
+
+ RunningApp.Tap (q => q.Marked ("MasterButton"));
+ RunningApp.Screenshot ("Create new Detail instance");
+
+ RunningApp.Tap (q => q.Marked ("Page1PushModalButton"));
+ RunningApp.Screenshot ("Modal is pushed");
+
+ RunningApp.Tap (q => q.Marked ("ModalPagePopButton"));
+ RunningApp.Screenshot ("Modal is popped");
+
+ RunningApp.WaitForElement (q => q.Marked ("Page1Label"));
+ RunningApp.Screenshot ("Didn't blow up! :)");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2965.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2965.cs
new file mode 100644
index 00000000..fd65c13b
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2965.cs
@@ -0,0 +1,152 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Diagnostics;
+
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+using Xamarin.UITest.iOS;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2965, "CarouselPage Disappearing event does not fire on Android")]
+ public class Issue2965 : TestMasterDetailPage
+ {
+ static MasterDetailPage s_mdp;
+
+ int _countAppearing;
+
+ protected override void Init ()
+ {
+ s_mdp = this;
+
+ var lblCount = new Label { AutomationId = "lblCount" };
+
+ var myCarouselPage = new CarouselPage () {
+
+ Children = {
+ new ContentPage {
+ BackgroundColor = Color.Green,
+ Content = new StackLayout {
+ Children = {
+ new Button {
+ AutomationId = "ShowMasterBtnPage1",
+ Text = "ShowMaster",
+ Command = new Command(()=> s_mdp.IsPresented = true)
+ },
+ lblCount
+ }
+ }
+ },
+ new ContentPage {
+ BackgroundColor = Color.Red
+ },
+ new ContentPage {
+ BackgroundColor = Color.Lime,
+ },
+ new ContentPage {
+ BackgroundColor = Color.Purple,
+ },
+ }
+ };
+
+ var myCarouselDetailPage = new NavigationPage (myCarouselPage);
+
+ var myPushButton = new Button () {
+ Text = "Push Page",
+ HorizontalOptions = LayoutOptions.Start
+ };
+
+ myCarouselPage.Appearing += (sender, e) => {
+ _countAppearing++;
+ lblCount.Text = _countAppearing.ToString ();
+ };
+ myCarouselPage.Disappearing += (sender, e) => {
+ _countAppearing--;
+ };
+
+
+ var mySecondDetailPage = new NavigationPage (new ContentPage () {
+ Title = "My Second Page",
+
+ Content = new StackLayout () {
+ Orientation = StackOrientation.Vertical,
+ Children = {
+ new Button {
+ AutomationId = "ShowMasterBtnPage2",
+ Text = "ShowMaster",
+ Command = new Command(()=> s_mdp.IsPresented = true)
+ },
+ myPushButton
+ }
+ }
+ });
+
+ myPushButton.Command = new Command (() => mySecondDetailPage.Navigation.PushAsync (new ContentPage () { Title = "My Pushed Page" }));
+
+ var myMasterPage = new ContentPage () {
+ Padding = new Thickness (0, 60, 0, 0),
+ Title = "Menu",
+ Content = new StackLayout () {
+ Orientation = StackOrientation.Vertical,
+ Children = {
+ new Button () {
+ Text = "Detail 1",
+ AutomationId = "btnDetail1",
+ Command = new Command (() => {
+ Detail = myCarouselDetailPage;
+ IsPresented = false;
+ }),
+ HorizontalOptions = LayoutOptions.Start
+ },
+
+ new Button () {
+ Text = "Detail 2",
+ AutomationId = "btnDetail2",
+ Command = new Command (() => {
+ Detail = mySecondDetailPage;
+ IsPresented = false;
+ }),
+ HorizontalOptions = LayoutOptions.Start
+ }
+
+ }
+ }
+ };
+
+ Master = myMasterPage;
+ Detail = myCarouselDetailPage;
+ }
+
+#if UITEST
+ [Test]
+ [Ignore("Fails intermittently on TestCloud")]
+ public void Issue2965Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue 2965");
+ var element = RunningApp.WaitForElement (q => q.Marked ("lblCount"))[0];
+ Assert.That (element.Text, Is.EqualTo ("1"));
+
+ if(RunningApp is iOSApp)
+ RunningApp.Tap (q => q.Marked("Menu"));
+ else
+ RunningApp.Tap ("ShowMasterBtnPage1");
+
+ RunningApp.Tap (q => q.Marked("btnDetail2"));
+
+ if(RunningApp is iOSApp)
+ RunningApp.Tap (q => q.Marked("Menu"));
+ else
+ RunningApp.Tap ("ShowMasterBtnPage2");
+
+ RunningApp.Tap (q => q.Marked("btnDetail1"));
+ element = RunningApp.WaitForElement (q => q.Marked ("lblCount"))[0];
+ Assert.That (element.Text, Is.EqualTo ("1"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2976.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2976.cs
new file mode 100644
index 00000000..c5da93f5
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2976.cs
@@ -0,0 +1,441 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.Generic;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2976, "Sample 'WorkingWithListviewNative' throw Exception on Xam.Android project.", PlatformAffected.Android)]
+ public class Issue2976 : TestTabbedPage
+ {
+ protected override void Init ()
+ {
+
+ // built-in Xamarin.Forms controls
+ Children.Add (new XamarinFormsPage {Title = "DEMOA", Icon = "bank.png"});
+
+ // custom renderer for the list, using a native built-in cell type
+ Children.Add (new NativeListPage {Title = "DEMOB", Icon = "bank.png"});
+
+ // built in Xamarin.Forms list, but with a native cell custom-renderer
+ Children.Add (new XamarinFormsNativeCellPage {Title = "DEMOC", Icon = "bank.png"});
+
+ // custom renderer for the list, using a native cell that has been custom-defined in native code
+ Children.Add (new NativeListViewPage2 {Title = "DEMOD", Icon = "bank.png"});
+ }
+
+#if UITEST
+ [Test]
+ public void Issue1Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue 2976");
+ RunningApp.Tap (q => q.Marked ("DEMOA"));
+ RunningApp.Tap (q => q.Marked ("DEMOB"));
+ RunningApp.Tap (q => q.Marked ("DEMOC"));
+ RunningApp.Tap (q => q.Marked ("DEMOD"));
+ }
+#endif
+ }
+
+ /// <summary>
+ /// This page uses a custom renderer that wraps native list controls:
+ /// iOS : UITableView
+ /// Android : ListView (do not confuse with Xamarin.Forms ListView)
+ /// Windows Phone : ?
+ ///
+ /// It uses a built-in row/cell class provided by the native platform
+ /// and is therefore faster than building a custom ViewCell in Xamarin.Forms.
+ /// </summary>
+ [Preserve (AllMembers = true)]
+ public class NativeListPage : ContentPage
+ {
+ public NativeListPage ()
+ {
+ var tableItems = new List<string> ();
+ for (var i = 0; i < 100; i++) {
+ tableItems.Add (i + " row ");
+ }
+
+
+ var fasterListView = new NativeListView (); // CUSTOM RENDERER using a native control
+ fasterListView.VerticalOptions = LayoutOptions.FillAndExpand; // REQUIRED: To share a scrollable view with other views in a StackLayout, it should have a VerticalOptions of FillAndExpand.
+ fasterListView.Items = tableItems;
+ fasterListView.ItemSelected += async (sender, e) => {
+ await Navigation.PushModalAsync (new DetailPage(e.SelectedItem));
+ };
+
+ // The root page of your application
+ Content = new StackLayout {
+ Padding = new Thickness (0, Device.OnPlatform(20,0,0), 0, 0),
+ Children = {
+ new Label {
+ XAlign = TextAlignment.Center,
+ Text = Device.OnPlatform("Custom renderer UITableView","Custom renderer ListView","Custom renderer todo")
+ },
+ fasterListView
+ }
+ };
+ }
+ }
+
+ /// <summary>
+ /// Xamarin.Forms representation for a custom-renderer that uses
+ /// the native list control on each platform.
+ /// </summary>
+ public class NativeListView : View
+ {
+ public static readonly BindableProperty ItemsProperty =
+ BindableProperty.Create ("Items", typeof(IEnumerable<string>), typeof(NativeListView), new List<string>());
+
+ public IEnumerable<string> Items {
+ get { return (IEnumerable<string>)GetValue (ItemsProperty); }
+ set { SetValue (ItemsProperty, value); }
+ }
+
+ public event EventHandler<SelectedItemChangedEventArgs> ItemSelected;
+
+ public void NotifyItemSelected (object item) {
+
+ if (ItemSelected != null)
+ ItemSelected (this, new SelectedItemChangedEventArgs (item));
+ }
+
+ public NativeListView ()
+ {
+ }
+ }
+
+ /// <summary>
+ /// This page uses built-in Xamarin.Forms controls to display a fast-scrolling list.
+ ///
+ /// It uses the built-in <c>TextCell</c> class which does not require special 'layout'
+ /// and is therefore faster than building a custom ViewCell in Xamarin.Forms.
+ /// </summary>
+ [Preserve (AllMembers = true)]
+ public class XamarinFormsPage : ContentPage
+ {
+ public XamarinFormsPage ()
+ {
+ var tableItems = new List<string> ();
+ for (var i = 0; i < 100; i++) {
+ tableItems.Add (i + " row ");
+ }
+
+ var listView = new ListView ();
+ listView.ItemsSource = tableItems;
+ listView.ItemTemplate = new DataTemplate(typeof(TextCell));
+ listView.ItemTemplate.SetBinding(TextCell.TextProperty, ".");
+
+ listView.ItemSelected += async (sender, e) => {
+ if (e.SelectedItem == null)
+ return;
+ listView.SelectedItem= null; // deselect row
+ await Navigation.PushModalAsync (new DetailPage(e.SelectedItem));
+ };
+
+ Content = new StackLayout {
+ Padding = new Thickness (5, Device.OnPlatform(20,0,0), 5, 0),
+ Children = {
+ new Label {
+ XAlign = TextAlignment.Center,
+ Text = "Xamarin.Forms built-in ListView"
+ },
+ listView
+ }
+ };
+ }
+ }
+
+ /// <summary>
+ /// This page uses built-in Xamarin.Forms controls to display a fast-scrolling list.
+ ///
+ /// It uses the built-in <c>TextCell</c> class which does not require special 'layout'
+ /// and is therefore faster than building a custom ViewCell in Xamarin.Forms.
+ /// </summary>
+ [Preserve (AllMembers = true)]
+ public class XamarinFormsNativeCellPage : ContentPage
+ {
+ public XamarinFormsNativeCellPage ()
+ {
+ var listView = new ListView ();
+ listView.ItemsSource = DataSource.GetList ();
+ listView.ItemTemplate = new DataTemplate(typeof(NativeCell));
+
+ listView.ItemTemplate.SetBinding(NativeCell.NameProperty, "Name");
+ listView.ItemTemplate.SetBinding(NativeCell.CategoryProperty, "Category");
+ listView.ItemTemplate.SetBinding(NativeCell.ImageFilenameProperty, "ImageFilename");
+
+ listView.ItemSelected += async (sender, e) => {
+ if (e.SelectedItem == null)
+ return;
+ listView.SelectedItem= null; // deselect row
+
+ await Navigation.PushModalAsync (new DetailPage(e.SelectedItem));
+ };
+
+ Content = new StackLayout {
+ Padding = new Thickness (0, Device.OnPlatform(20,0,0), 0, 0),
+ Children = {
+ new Label {
+ XAlign = TextAlignment.Center,
+ Text = "Xamarin.Forms native Cell"
+ },
+ listView
+ }
+ };
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class NativeCell : ViewCell
+ {
+ public NativeCell ()
+ {
+ //View = new ContentView ();
+ }
+
+ public static readonly BindableProperty NameProperty =
+ BindableProperty.Create ("Name", typeof(string), typeof(NativeCell), "");
+ public string Name {
+ get { return (string)GetValue (NameProperty); }
+ set { SetValue (NameProperty, value); }
+ }
+
+
+ public static readonly BindableProperty CategoryProperty =
+ BindableProperty.Create ("Category", typeof(string), typeof(NativeCell), "");
+ public string Category {
+ get { return (string)GetValue (CategoryProperty); }
+ set { SetValue (CategoryProperty, value); }
+ }
+
+
+ public static readonly BindableProperty ImageFilenameProperty =
+ BindableProperty.Create ("ImageFilename", typeof(string), typeof(NativeCell), "");
+ public string ImageFilename {
+ get { return (string)GetValue (ImageFilenameProperty); }
+ set { SetValue (ImageFilenameProperty, value); }
+ }
+
+ }
+
+ public class DetailPage : ContentPage
+ {
+ public DetailPage (object detail)
+ {
+ var l = new Label { Text = "Xamarin.Forms Detail Page" };
+
+ var t = new Label ();
+
+ if (detail is string) {
+ t.Text = (string)detail;
+ } else if (detail is DataSource) {
+ t.Text = ((DataSource)detail).Name;
+ }
+
+ var b = new Button { Text = "Dismiss" };
+ b.Clicked += (sender, e) => Navigation.PopModalAsync();
+
+ Content = new StackLayout {
+ Padding = new Thickness (0, Device.OnPlatform(20,0,0), 0, 0),
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.Center,
+ Children = {
+ l,
+ t,
+ b
+ }
+ };
+ }
+ }
+
+ /// <summary>
+ /// This page uses a custom renderer that wraps native list controls:
+ /// iOS : UITableView
+ /// Android : ListView (do not confuse with Xamarin.Forms ListView)
+ /// Windows Phone : ?
+ ///
+ /// It uses a CUSTOM row/cell class that is defined natively which
+ /// is still faster than a Xamarin.Forms-defined ViewCell subclass.
+ /// </summary>
+ [Preserve (AllMembers = true)]
+ public class NativeListViewPage2 : ContentPage
+ {
+ public NativeListViewPage2 ()
+ {
+ var nativeListView2 = new NativeListView2 (); // CUSTOM RENDERER using a native control
+
+ nativeListView2.VerticalOptions = LayoutOptions.FillAndExpand; // REQUIRED: To share a scrollable view with other views in a StackLayout, it should have a VerticalOptions of FillAndExpand.
+
+ nativeListView2.Items = DataSource.GetList ();
+
+ nativeListView2.ItemSelected += async (sender, e) => {
+ //await Navigation.PushModalAsync (new DetailPage(e.SelectedItem));
+ await DisplayAlert ("clicked", "one of the rows was clicked", "ok");
+ };
+
+ // The root page of your application
+ Content = new StackLayout {
+ Padding = new Thickness (0, Device.OnPlatform(20,0,0), 0, 0),
+ Children = {
+ new Label {
+ XAlign = TextAlignment.Center,
+ Text = Device.OnPlatform("Custom UITableView+UICell","Custom ListView+Cell","Custom renderer todo")
+ },
+ nativeListView2
+ }
+ };
+ }
+ }
+
+ /// <summary>
+ /// Xamarin.Forms representation for a custom-renderer that uses
+ /// the native list control on each platform.
+ /// </summary>
+ public class NativeListView2 : View
+ {
+ public static readonly BindableProperty ItemsProperty =
+ BindableProperty.Create ("Items", typeof(IEnumerable<DataSource>), typeof(NativeListView2), new List<DataSource>());
+
+ public IEnumerable<DataSource> Items {
+ get { return (IEnumerable<DataSource>)GetValue (ItemsProperty); }
+ set { SetValue (ItemsProperty, value); }
+ }
+
+ public event EventHandler<SelectedItemChangedEventArgs> ItemSelected;
+
+ public void NotifyItemSelected (object item) {
+
+ if (ItemSelected != null)
+ ItemSelected (this, new SelectedItemChangedEventArgs (item));
+ }
+
+ public NativeListView2 ()
+ {
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class DataSource
+ {
+ public string Name { get; set; }
+ public string Category { get; set; }
+ public string ImageFilename { get; set; }
+
+ public DataSource ()
+ {
+ }
+
+ public DataSource (string name, string category, string imageFilename)
+ {
+ Name = name;
+ Category = category;
+ ImageFilename = imageFilename;
+ }
+
+ public static List<DataSource> GetList (){
+ var l = new List<DataSource> ();
+
+
+ l.Add (new DataSource ("Asparagus","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Avocados","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Beetroots","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Capsicum","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Broccoli","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Brussel sprouts","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Cabbage","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Carrots","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Cauliflower","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Celery","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Corn","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Cucumbers","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Eggplant","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Fennel","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Garlic","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Beans","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Peas","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Kale","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Leeks","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Mushrooms","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Olives","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Onions","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Potatoes","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Lettuce","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Spinach","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Squash","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Sweet potatoes","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Tomatoes","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Turnips","Vegetables","Vegetables"));
+ l.Add (new DataSource ("Apples","Fruits","Fruits"));
+ l.Add (new DataSource ("Apricots","Fruits","Fruits"));
+ l.Add (new DataSource ("Bananas","Fruits","Fruits"));
+ l.Add (new DataSource ("Blueberries","Fruits","Fruits"));
+ l.Add (new DataSource ("Rockmelon","Fruits","Fruits"));
+ l.Add (new DataSource ("Figs","Fruits","Fruits"));
+ l.Add (new DataSource ("Grapefruit","Fruits","Fruits"));
+ l.Add (new DataSource ("Grapes","Fruits","Fruits"));
+ l.Add (new DataSource ("Honeydew Melon","Fruits","Fruits"));
+ l.Add (new DataSource ("Kiwifruit","Fruits","Fruits"));
+ l.Add (new DataSource ("Lemons","Fruits","Fruits"));
+ l.Add (new DataSource ("Oranges","Fruits","Fruits"));
+ l.Add (new DataSource ("Pears","Fruits","Fruits"));
+ l.Add (new DataSource ("Pineapple","Fruits","Fruits"));
+ l.Add (new DataSource ("Plums","Fruits","Fruits"));
+ l.Add (new DataSource ("Raspberries","Fruits","Fruits"));
+ l.Add (new DataSource ("Strawberries","Fruits","Fruits"));
+ l.Add (new DataSource ("Watermelon","Fruits","Fruits"));
+ l.Add (new DataSource ("Balmain Bugs","Seafood",""));
+ l.Add (new DataSource ("Calamari","Seafood",""));
+ l.Add (new DataSource ("Cod","Seafood",""));
+ l.Add (new DataSource ("Prawns","Seafood",""));
+ l.Add (new DataSource ("Lobster","Seafood",""));
+ l.Add (new DataSource ("Salmon","Seafood",""));
+ l.Add (new DataSource ("Scallops","Seafood",""));
+ l.Add (new DataSource ("Shrimp","Seafood",""));
+ l.Add (new DataSource ("Tuna","Seafood",""));
+ l.Add (new DataSource ("Almonds","Nuts",""));
+ l.Add (new DataSource ("Cashews","Nuts",""));
+ l.Add (new DataSource ("Peanuts","Nuts",""));
+ l.Add (new DataSource ("Walnuts","Nuts",""));
+ l.Add (new DataSource ("Black beans","Beans & Legumes","Legumes"));
+ l.Add (new DataSource ("Dried peas","Beans & Legumes","Legumes"));
+ l.Add (new DataSource ("Kidney beans","Beans & Legumes","Legumes"));
+ l.Add (new DataSource ("Lentils","Beans & Legumes","Legumes"));
+ l.Add (new DataSource ("Lima beans","Beans & Legumes","Legumes"));
+ l.Add (new DataSource ("Miso","Beans & Legumes","Legumes"));
+ l.Add (new DataSource ("Soybeans","Beans & Legumes","Legumes"));
+ l.Add (new DataSource ("Beef","Meat",""));
+ l.Add (new DataSource ("Buffalo","Meat",""));
+ l.Add (new DataSource ("Chicken","Meat",""));
+ l.Add (new DataSource ("Lamb","Meat",""));
+ l.Add (new DataSource ("Cheese","Dairy",""));
+ l.Add (new DataSource ("Milk","Dairy",""));
+ l.Add (new DataSource ("Eggs","Dairy",""));
+ l.Add (new DataSource ("Basil","Herbs & Spices","FlowerBuds"));
+ l.Add (new DataSource ("Black pepper","Herbs & Spices","FlowerBuds"));
+ l.Add (new DataSource ("Chili pepper, dried","Herbs & Spices","FlowerBuds"));
+ l.Add (new DataSource ("Cinnamon","Herbs & Spices","FlowerBuds"));
+ l.Add (new DataSource ("Cloves","Herbs & Spices","FlowerBuds"));
+ l.Add (new DataSource ("Cumin","Herbs & Spices","FlowerBuds"));
+ l.Add (new DataSource ("Dill","Herbs & Spices","FlowerBuds"));
+ l.Add (new DataSource ("Ginger","Herbs & Spices","FlowerBuds"));
+ l.Add (new DataSource ("Mustard","Herbs & Spices","FlowerBuds"));
+ l.Add (new DataSource ("Oregano","Herbs & Spices","FlowerBuds"));
+ l.Add (new DataSource ("Parsley","Herbs & Spices","FlowerBuds"));
+ l.Add (new DataSource ("Peppermint","Herbs & Spices","FlowerBuds"));
+ l.Add (new DataSource ("Rosemary","Herbs & Spices","FlowerBuds"));
+ l.Add (new DataSource ("Sage","Herbs & Spices","FlowerBuds"));
+ l.Add (new DataSource ("Thyme","Herbs & Spices","FlowerBuds"));
+ l.Add (new DataSource ("Turmeric","Herbs & Spices","FlowerBuds"));
+
+
+ return l;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2981.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2981.cs
new file mode 100644
index 00000000..d94e09f7
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2981.cs
@@ -0,0 +1,37 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2981, "Long Press on ListView causes crash")]
+ public class Issue2981 : TestContentPage
+ {
+
+ protected override void Init ()
+ {
+ var listView = new ListView ();
+
+ listView.ItemsSource = new [] { "Cell1", "Cell2" };
+ Content = listView;
+ }
+
+#if UITEST
+ [Test]
+ public void Issue2981Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue 1");
+ RunningApp.TouchAndHold (q => q.Marked ("Cell1"));
+ RunningApp.Screenshot ("Long Press first cell");
+ RunningApp.TouchAndHold (q => q.Marked ("Cell2"));
+ RunningApp.Screenshot ("Long Press second cell");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2983.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2983.cs
new file mode 100644
index 00000000..93d96cda
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2983.cs
@@ -0,0 +1,30 @@
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers = true)]
+ [Issue(IssueTracker.Github, 2983, "ListView.Footer can cause NullReferenceException", PlatformAffected.iOS)]
+ public class Issue2983 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Content = new ListView {
+ Footer = new StackLayout {
+ Children = {new Label {Text = "Footer", AutomationId = "footer"}}
+ }
+ };
+ }
+
+#if UITEST
+ [Test]
+ public void TestDoesNotCrash ()
+ {
+ RunningApp.WaitForElement (c => c.Marked ("footer"));
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2987.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2987.cs
new file mode 100644
index 00000000..770320b0
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue2987.cs
@@ -0,0 +1,39 @@
+using System;
+using Xamarin.Forms.CustomAttributes;
+using System.Diagnostics;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2987, "When setting the minimum and maximum date for a date picker, only allow valid dates to be seen/selected from the DatePicker dialog", PlatformAffected.Android)]
+ public class Issue2987 : TestContentPage
+ {
+ public AbsoluteLayout layout;
+
+ protected override void Init ()
+ {
+ var datePicker = new DatePicker { AutomationId = "datePicker" };
+ datePicker.MinimumDate = new DateTime (2015, 1, 1);
+ datePicker.MaximumDate = new DateTime (2015, 6, 1);
+ datePicker.Date = DateTime.Now;
+ datePicker.Format = "MMM dd, yyyy";
+ datePicker.DateSelected += (object sender, DateChangedEventArgs e) => {
+ Debug.WriteLine ("Date changed");
+ };
+
+ Padding = new Thickness (10, Device.OnPlatform (20, 0, 0), 10, 5);
+
+ layout = new AbsoluteLayout {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand
+ };
+
+ AbsoluteLayout.SetLayoutFlags (datePicker, AbsoluteLayoutFlags.None);
+ AbsoluteLayout.SetLayoutBounds (datePicker, new Rectangle (0f, 0f, 300f, 50f));
+
+ layout.Children.Add (datePicker);
+
+ Content = layout;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3086.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3086.xaml
new file mode 100644
index 00000000..b78ee1de
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3086.xaml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.Issues.Issue3086">
+<ListView x:Name="TestListView"
+ IsGroupingEnabled = "true"
+ HasUnevenRows="true">
+ <ListView.GroupHeaderTemplate >
+ <DataTemplate>
+ <ViewCell Height="30">
+ <ContentView>
+ <Label Text="{Binding GroupName}" BackgroundColor="Green"/>
+ </ContentView>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.GroupHeaderTemplate >
+
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <ContentView>
+ <Label Text="{Binding}"/>
+ </ContentView>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+</ListView>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3086.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3086.xaml.cs
new file mode 100644
index 00000000..77dc6f11
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3086.xaml.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.ObjectModel;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+ [Issue (IssueTracker.Github, 3086, "On iOS, groupheadertemplate is broken")]
+ public partial class Issue3086 : ContentPage
+ {
+ public Issue3086 ()
+ {
+ #if APP
+ InitializeComponent ();
+ TestListView.ItemsSource = new ObservableCollection<GroupedItems> () {
+ new GroupedItems ("Header 1") { "1.1", "1.2", "1.3" },
+ new GroupedItems ("Header 2") { "2.1", "2.2", "2.3" },
+ new GroupedItems ("Header 3") { "3.1", "3.2", "3.3" },
+ new GroupedItems ("Header 4") { "4.1", "4.2", "4.3" },
+ };
+ #endif
+ }
+
+ internal class GroupedItems : ObservableCollection<string> {
+ public GroupedItems (string groupName) { GroupName = groupName; }
+ public string GroupName { get; private set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3276.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3276.cs
new file mode 100644
index 00000000..6f0b0ea9
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3276.cs
@@ -0,0 +1,91 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections.ObjectModel;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.ComponentModel;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 3276, "Crashing Unknown cell parent type on ContextAction Bindings")]
+ public class Issue3276 : TestTabbedPage
+ {
+ protected override void Init ()
+ {
+ var listview = new ListView ();
+ listview.ItemTemplate = new DataTemplate (typeof(CaCell));
+
+ listview.SetBinding (ListView.ItemsSourceProperty, new Binding ("SearchResults"));
+
+ var page = new ContentPage {Title = "First", Content = listview, BindingContext = new VM () };
+
+ page.Appearing += (object sender, EventArgs e) => (page.BindingContext as VM).Load ();
+
+ Children.Add (page);
+ Children.Add (new ContentPage { Title = "Second" });
+ }
+
+ [Preserve (AllMembers = true)]
+ public class VM : ViewModel
+ {
+ public void Load ()
+ {
+ var list = new List<string> ();
+ for (int i = 0; i < 20; i++) {
+ list.Add ("second " + i.ToString ());
+ }
+ SearchResults = new ObservableCollection<string> (list);
+ }
+
+ ObservableCollection<string> _list = null;
+
+ public ObservableCollection<string> SearchResults {
+ get { return _list; }
+
+ set {
+ _list = value;
+ OnPropertyChanged ();
+ }
+ }
+
+ }
+
+ [Preserve (AllMembers = true)]
+ public class CaCell : ViewCell
+ {
+ public CaCell ()
+ {
+ var label = new Label ();
+ label.SetBinding (Label.TextProperty, new Binding ("."));
+ var menu = new MenuItem { Text = "Delete", IsDestructive = true };
+ menu.SetBinding (MenuItem.CommandParameterProperty, new Binding ("."));
+ var menu1 = new MenuItem { Text = "Settings" };
+ menu1.SetBinding (MenuItem.CommandParameterProperty, new Binding ("."));
+ ContextActions.Add (menu);
+ ContextActions.Add (menu1);
+
+ var stack = new StackLayout ();
+ stack.Children.Add (label);
+ View = stack;
+ }
+ }
+
+
+ #if UITEST
+ [Test]
+ public void Issue3276Test ()
+ {
+ RunningApp.Tap (q => q.Marked ("Second"));
+ RunningApp.Tap (q => q.Marked ("First"));
+ RunningApp.WaitForElement (q => q.Marked ("second 1"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3292.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3292.cs
new file mode 100644
index 00000000..910b96fd
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3292.cs
@@ -0,0 +1,83 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Threading.Tasks;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 3292, "TableSection.Title property binding fails in XAML")]
+ public class Issue3292 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var vm = new SomePageViewModel ();
+ BindingContext = vm;
+
+ var tableview = new TableView ();
+ var section = new TableSection ();
+ section.SetBinding (TableSectionBase.TitleProperty, new Binding ("SectionTitle"));
+ var root = new TableRoot ();
+ root.Add (section);
+ tableview.Root = root;
+
+ Content = tableview;
+
+ vm.Init ();
+ }
+
+ [Preserve (AllMembers = true)]
+ public class SomePageViewModel : INotifyPropertyChanged
+ {
+ string _sectionTitle;
+
+ public SomePageViewModel()
+ {
+ SectionTitle = "Hello World";
+ }
+
+ public void Init()
+ {
+ Task.Delay(1000).ContinueWith(t =>
+ {
+ Device.BeginInvokeOnMainThread(() => {
+ SectionTitle = "Hello World Changed";
+ });
+ });
+ }
+
+ public string SectionTitle
+ {
+ get { return _sectionTitle; }
+ set
+ {
+ _sectionTitle = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ var handler = PropertyChanged;
+ if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+
+#if UITEST
+ [Test]
+ public void Issue3292Test ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Hello World Changed"));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3319.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3319.xaml
new file mode 100644
index 00000000..7df95596
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3319.xaml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<local:TestContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Controls"
+ x:Class="Xamarin.Forms.Controls.Issue3319">
+ <StackLayout Orientation="Vertical">
+ <ListView x:Name="listView"
+ ItemsSource="{Binding FavoriteArticles}"
+ HasUnevenRows="True"
+ IsPullToRefreshEnabled="True"
+ RefreshCommand="{Binding LoadFavoritesCommand}"
+ IsRefreshing="{Binding IsBusy, Mode=OneWay}"
+ >
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell >
+ <ViewCell.ContextActions>
+ <MenuItem Clicked="OnDelete" CommandParameter="{Binding .}"
+ Text="Delete" IsDestructive="True" />
+ </ViewCell.ContextActions>
+
+ <Grid Padding="10,5">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+ <StackLayout Grid.Column="1"
+ Padding="5"
+ Spacing="1"
+ VerticalOptions="Center">
+ <Label Text="{Binding ArticleTitle}" FontSize="Medium" FontAttributes="Bold" TextColor="#333333" LineBreakMode="WordWrap"/>
+ <Label Text="{Binding AuthorString}" FontSize="Small" TextColor="#919191" LineBreakMode="TailTruncation"/>
+ <Label Text="{Binding FormattedPostedDate}" FontSize="Small" TextColor="#919191" LineBreakMode="NoWrap"/>
+ <Label Text="{Binding ItemId}" FontSize="Small" TextColor="#919191" LineBreakMode="NoWrap" IsVisible="false"/>
+ </StackLayout>
+ </Grid>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </StackLayout>
+</local:TestContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3319.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3319.xaml.cs
new file mode 100644
index 00000000..d2f54cd0
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3319.xaml.cs
@@ -0,0 +1,264 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using System.Threading.Tasks;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 3319, "[iOS] Clear and adding rows exception")]
+ public partial class Issue3319 : TestContentPage
+ {
+ #if UITEST
+ [Test]
+ public void Issue3319Test ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Will this repo work?"));
+
+ }
+ #endif
+
+ FavoritesViewModel ViewModel {
+ get { return BindingContext as FavoritesViewModel; }
+ }
+
+ public Issue3319 ()
+ {
+ #if APP
+ InitializeComponent ();
+ BindingContext = new FavoritesViewModel ();
+
+ listView.SeparatorVisibility = SeparatorVisibility.Default;
+ listView.SeparatorColor = Color.FromHex ("#ababab");
+
+ listView.ItemTapped += (sender, args) => {
+ if (listView.SelectedItem == null)
+ return;
+
+ //do nothing anyway
+ return;
+ };
+ #endif
+
+ }
+
+ protected override void Init ()
+ {
+
+ }
+
+ public async void OnDelete (object sender, EventArgs e)
+ {
+ var mi = ((MenuItem)sender);
+ if (mi.CommandParameter == null)
+ return;
+
+ var articlelistingitem = mi.CommandParameter;
+
+ if (articlelistingitem != null)
+ DisplayAlert ("Alert", "I'm not deleting just refreshing...", "Ok");
+ ViewModel.LoadFavoritesCommand.Execute (null);
+ }
+
+
+ protected override void OnAppearing ()
+ {
+ base.OnAppearing ();
+ if (ViewModel == null || !ViewModel.CanLoadMore || ViewModel.IsBusy)
+ return;
+
+ Device.BeginInvokeOnMainThread (() => {
+ ViewModel.LoadFavoritesCommand.Execute (null);
+ });
+ }
+
+ [Preserve (AllMembers = true)]
+ public class FavoritesViewModel :BaseViewModelF
+ {
+ public ObservableCollection<ArticleListing> FavoriteArticles { get; set; }
+
+ public FavoritesViewModel ()
+ {
+ Title = "Favorites";
+ FavoriteArticles = new ObservableCollection<ArticleListing> ();
+ }
+
+ Command _loadFavoritesCommand;
+
+ public Command LoadFavoritesCommand {
+ get {
+ return _loadFavoritesCommand ??
+ (_loadFavoritesCommand = new Command (async () => {
+ await ExecuteFavoritesCommand ();
+ }, () => {
+ return !IsBusy;
+ }));
+ }
+ }
+
+ public async Task ExecuteFavoritesCommand ()
+ {
+ if (IsBusy)
+ return;
+
+ IsBusy = true;
+ LoadFavoritesCommand.ChangeCanExecute ();
+ FavoriteArticles.Clear ();
+ var articles = new ObservableCollection<ArticleListing> {
+ new ArticleListing {
+ ArticleTitle = "Will this repo work?",
+ AuthorString = "Ben Crispin",
+ FormattedPostedDate = "7-28-2015"
+ },
+ new ArticleListing {
+ ArticleTitle = "Xamarin Forms BugZilla",
+ AuthorString = "Some Guy",
+ FormattedPostedDate = "7-28-2015"
+ }
+ };
+ var templist = new ObservableCollection<ArticleListing> ();
+ foreach (var article in articles) {
+ //templist.Add(article);
+ FavoriteArticles.Add (article);
+ }
+ //FavoriteArticles = templist;
+ OnPropertyChanged ("FavoriteArticles");
+ IsBusy = false;
+ LoadFavoritesCommand.ChangeCanExecute ();
+ }
+
+ }
+ }
+
+ public class BaseViewModelF : INotifyPropertyChanged
+ {
+ public BaseViewModelF ()
+ {
+ }
+
+ string _title = string.Empty;
+ public const string TitlePropertyName = "Title";
+
+ /// <summary>
+ /// Gets or sets the "Title" property
+ /// </summary>
+ /// <value>The title.</value>
+ public string Title {
+ get { return _title; }
+ set { SetProperty (ref _title, value, TitlePropertyName); }
+ }
+
+ string _subTitle = string.Empty;
+ /// <summary>
+ /// Gets or sets the "Subtitle" property
+ /// </summary>
+ public const string SubtitlePropertyName = "Subtitle";
+
+ public string Subtitle {
+ get { return _subTitle; }
+ set { SetProperty (ref _subTitle, value, SubtitlePropertyName); }
+ }
+
+ string _icon = null;
+ /// <summary>
+ /// Gets or sets the "Icon" of the viewmodel
+ /// </summary>
+ public const string IconPropertyName = "Icon";
+
+ public string Icon {
+ get { return _icon; }
+ set { SetProperty (ref _icon, value, IconPropertyName); }
+ }
+
+ bool _isBusy;
+ /// <summary>
+ /// Gets or sets if the view is busy.
+ /// </summary>
+ public const string IsBusyPropertyName = "IsBusy";
+
+ public bool IsBusy {
+ get { return _isBusy; }
+ set { SetProperty (ref _isBusy, value, IsBusyPropertyName); }
+ }
+
+ bool _canLoadMore = true;
+ /// <summary>
+ /// Gets or sets if we can load more.
+ /// </summary>
+ public const string CanLoadMorePropertyName = "CanLoadMore";
+
+ public bool CanLoadMore {
+ get { return _canLoadMore; }
+ set { SetProperty (ref _canLoadMore, value, CanLoadMorePropertyName); }
+ }
+
+ protected void SetProperty<T> (
+ ref T backingStore, T value,
+ string propertyName,
+ Action onChanged = null)
+ {
+
+ if (EqualityComparer<T>.Default.Equals (backingStore, value))
+ return;
+
+ backingStore = value;
+
+ if (onChanged != null)
+ onChanged ();
+
+ OnPropertyChanged (propertyName);
+ }
+
+ #region INotifyPropertyChanged implementation
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ #endregion
+
+ public void OnPropertyChanged (string propertyName)
+ {
+ if (PropertyChanged == null)
+ return;
+
+ PropertyChanged (this, new PropertyChangedEventArgs (propertyName));
+ }
+
+ }
+
+ [Preserve (AllMembers = true)]
+ public class ArticleListing
+ {
+ public ArticleListing ()
+ {
+ }
+
+ public string ArticleTitle { get; set; }
+
+ public string ShortArticleTitle { get; set; }
+
+ public string AuthorString { get; set; }
+
+ public string FormattedPostedDate { get; set; }
+
+ public string KickerName { get; set; }
+
+ public string ArticleUrl { get; set; }
+ }
+
+ public class YearOloArticleList
+ {
+ public string Year { get; set; }
+
+ public List<ArticleListing> ListArticleListing { get; set; }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue342.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue342.cs
new file mode 100644
index 00000000..792d9711
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue342.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Linq;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 342, "NRE when Image is not assigned source", PlatformAffected.WinPhone)]
+ public class Issue342NoSource : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Title = "Issue 342";
+ Content = new StackLayout {
+ Children = {
+ new Label {
+ Text = "Uninitialized image"
+ },
+ new Image ()
+ }
+ };
+ }
+
+ // Should not throw exception when user does not include image
+
+#if UITEST
+ [Test]
+ public void Issue342NoSourceTestsLablePresentNoImage ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Uninitialized image"), "Cannot see label");
+ RunningApp.Screenshot ("All elements present");
+ }
+#endif
+ }
+
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 342, "NRE when Image is delayed source", PlatformAffected.WinPhone)]
+ public class Issue342DelayedSource : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Title = "Issue 342";
+
+ _image = new Image ();
+
+ Content = new StackLayout {
+ Children = {
+ new Label {
+ Text = "Delayed image"
+ },
+ _image
+ }
+ };
+
+ AddSourceAfterDelay ();
+ }
+
+ // Should not throw exception when user does not include image
+ Image _image;
+
+ void AddSourceAfterDelay ()
+ {
+ Device.StartTimer (TimeSpan.FromSeconds (2), () => {
+ _image.Source = "cover1.jpg";
+ return false;
+ });
+ }
+
+#if UITEST
+ [Test]
+ [Category ("ManualReview")]
+ public void Issue342DelayedLoadTestsImageLoads ()
+ {
+ RunningApp.Screenshot ("Should not crash");
+ Assert.Inconclusive ("Manual review");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue416.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue416.cs
new file mode 100644
index 00000000..ec71d472
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue416.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Linq;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 416, "NavigationPage in PushModal does not show NavigationBar", PlatformAffected.Android, NavigationBehavior.PushModalAsync)]
+ public class Issue416 : TestNavigationPage
+ {
+ protected override void Init ()
+ {
+ Navigation.PushAsync (new ContentPage {
+ Title = "Test Page",
+ Content = new Label {
+ Text = "I should have a nav bar"
+ }
+ });
+ }
+
+ // Issue 416
+ // NavigationBar should be visible in modal
+
+#if UITEST
+ [Test]
+ [UiTest (typeof(NavigationPage))]
+ public void Issue416TestsNavBarPresent ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Test Page"));
+ RunningApp.WaitForElement (q => q.Marked ("I should have a nav bar"));
+ RunningApp.Screenshot ("All element present");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue417.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue417.cs
new file mode 100644
index 00000000..43aad7e4
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue417.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 417, "Navigation.PopToRootAsync does nothing", PlatformAffected.Android)]
+ public class Issue417 : TestNavigationPage
+ {
+ public static NavigationPage NavRoot;
+
+ protected override void Init ()
+ {
+ Navigation.PushAsync (new FirstPage ());
+ NavRoot = this;
+ }
+
+ public class FirstPage : ContentPage
+ {
+ public FirstPage ()
+ {
+ Title = "First Page";
+ BackgroundColor = Color.Black;
+
+ var nextPageBtn = new Button {
+ Text = "Next Page"
+ };
+
+ nextPageBtn.Clicked += (s, e) => NavRoot.Navigation.PushAsync (new NextPage ());
+
+ Content = nextPageBtn;
+ }
+
+ }
+
+ public class NextPage : ContentPage
+ {
+ public NextPage ()
+ {
+ Title = "Second Page";
+
+ var nextPage2Btn = new Button {
+ Text = "Next Page 2"
+ };
+
+ nextPage2Btn.Clicked += (s, e) => NavRoot.Navigation.PushAsync (new NextPage2 ());
+ BackgroundColor = Color.Black;
+ Content = nextPage2Btn;
+
+ }
+ }
+
+ public class NextPage2 : ContentPage
+ {
+ public NextPage2 ()
+ {
+ Title = "Third Page";
+
+ var popToRootButton = new Button {
+ Text = "Pop to root"
+ };
+
+ popToRootButton.Clicked += (s, e) => NavRoot.PopToRootAsync ();
+ BackgroundColor = Color.Black;
+ Content = popToRootButton;
+ }
+ }
+
+
+#if UITEST
+ [Test]
+ [UiTest (typeof(NavigationPage), "PopToRootAsync")]
+ public void Issue417TestsNavigateAndPopToRoot ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("First Page"));
+ RunningApp.WaitForElement (q => q.Button ("Next Page"));
+ RunningApp.Screenshot ("All elements present");
+
+ RunningApp.Tap (q => q.Button ("Next Page"));
+
+ RunningApp.WaitForElement (q => q.Marked ("Second Page"));
+ RunningApp.WaitForElement (q => q.Button ("Next Page 2"));
+ RunningApp.Screenshot ("At second page");
+ RunningApp.Tap (q => q.Button ("Next Page 2"));
+
+ RunningApp.WaitForElement (q => q.Marked ("Third Page"));
+ RunningApp.WaitForElement (q => q.Button ("Pop to root"));
+ RunningApp.Screenshot ("At third page");
+ RunningApp.Tap (q => q.Button ("Pop to root"));
+
+ RunningApp.WaitForElement (q => q.Marked ("First Page"));
+ RunningApp.WaitForElement (q => q.Button ("Next Page"));
+ RunningApp.Screenshot ("All elements present");
+
+ RunningApp.Screenshot ("Popped to root");
+ }
+#endif
+ }
+
+
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue465.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue465.cs
new file mode 100644
index 00000000..75c880af
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue465.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 465, "Change in Navigation.PushModal", PlatformAffected.All)]
+ public class Issue465 : TestTabbedPage
+ {
+ protected override async void Init ()
+ {
+ Children.Add (
+ new ContentPage {
+ Content = new Label {
+ Text = "I was popppppped"
+ }
+ }
+ );
+
+ await Navigation.PushModalAsync (new ModalPage ());
+ }
+
+ [Preserve (AllMembers = true)]
+ public class ModalPage : ContentPage
+ {
+ public ModalPage ()
+ {
+ var popButton = new Button {
+ Text = "Pop this page"
+ };
+ popButton.Clicked += (s, e) => Navigation.PopModalAsync ();
+
+ Content = popButton;
+ }
+ }
+
+#if UITEST
+ [Test]
+ public void Issue465TestsPushPopModal ()
+ {
+ RunningApp.WaitForElement (q => q.Button ("Pop this page"));
+ RunningApp.Screenshot ("All elements exist");
+
+ RunningApp.Tap (q => q.Button ("Pop this page"));
+ RunningApp.WaitForElement (q => q.Marked ("I was popppppped"));
+ RunningApp.Screenshot ("Popped modal successful");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue488.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue488.cs
new file mode 100644
index 00000000..7d010e72
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue488.cs
@@ -0,0 +1,45 @@
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 488, "Resizing the Label results in wrapped text being cropped on iOS", PlatformAffected.iOS)]
+ public class Issue488 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var layout = new RelativeLayout {
+ BackgroundColor = Color.Gray
+ };
+ var label = new Label {
+ Text = "I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text."
+ };
+ layout.Children.Add (label, () => new Rectangle(0, 0, 250, 400));
+ Content = layout;
+ }
+
+ // Issue: #488
+ // Text wrapping issue in Label
+
+#if UITEST
+ [Test]
+ [Category ("ManualReview")]
+ public void Issue488TestsLongTextRotation ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text."));
+ RunningApp.SetOrientationLandscape ();
+ RunningApp.Screenshot ("Resize Label.Text by rotating to landscape");
+ RunningApp.WaitForElement (q => q.Marked ("I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text. I am a long bit of text."));
+ RunningApp.Screenshot ("Entire Label.Text present");
+ RunningApp.SetOrientationPortrait ();
+ RunningApp.Screenshot ("Rotated back to portrait");
+ Assert.Inconclusive ("Manual Review");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue530.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue530.cs
new file mode 100644
index 00000000..f71f53bf
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue530.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 530, "ListView does not render if source is async", PlatformAffected.iOS)]
+ public class Issue530 : TestContentPage
+ {
+ ListView _list;
+ Button _button;
+
+ protected override void Init ()
+ {
+ var dataTemplate = new DataTemplate (typeof (TextCell));
+ dataTemplate.SetBinding (TextCell.TextProperty, new Binding ("."));
+
+ _list = new ListView {
+ ItemTemplate = dataTemplate
+ };
+
+ _button = new Button {
+ Text = "Load",
+ };
+
+ _button.Clicked += async (sender, e) => {
+ await Task.Delay (1000);
+ _list.ItemsSource = new [] {"John","Paul", "George", "Ringo"};
+ };
+ Content = new StackLayout {
+ Children = {
+ _button,
+ _list,
+ }
+ };
+ }
+
+#if UITEST
+ [Test]
+ [UiTest (typeof(ListView))]
+ public void Issue530TestsLoadAsync ()
+ {
+ RunningApp.WaitForElement (q => q.Button ("Load"));
+ RunningApp.Screenshot ("All elements present");
+ RunningApp.Tap (q => q.Button ("Load"));
+
+ RunningApp.WaitForElement (q => q.Marked ("John"));
+ RunningApp.WaitForElement (q => q.Marked ("Paul"));
+ RunningApp.WaitForElement (q => q.Marked ("George"));
+ RunningApp.WaitForElement (q => q.Marked ("Ringo"));
+
+ RunningApp.Screenshot ("List items loaded async");
+ }
+#endif
+
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue764.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue764.cs
new file mode 100644
index 00000000..7604fbab
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue764.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Linq;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 764, "Keyboard does not dismiss on SearchBar", PlatformAffected.Android)]
+ public class Issue764 : TestContentPage
+ {
+
+ protected override void Init ()
+ {
+ Title = "Issue 764";
+
+ var searchBar = new SearchBar {
+ Placeholder = "Search Me!"
+ };
+
+ var label = new Label {
+ Text = "Pending Search"
+ };
+
+ searchBar.SearchButtonPressed += (s, e) => label.Text = "Search Activated";
+
+ var layout = new StackLayout {
+ Children = {
+ searchBar,
+ label
+ }
+ };
+
+ Content = layout;
+ }
+
+ // Issue 416
+ // NavigationBar should be visible in modal
+
+#if UITEST
+ [Test]
+ [Category ("ManualReview")]
+ public void Issue764TestsKeyboardDismissedForEnter ()
+ {
+ Assert.Inconclusive ("Needs test");
+ }
+#endif
+
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue773.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue773.cs
new file mode 100644
index 00000000..f2ffc5f6
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue773.cs
@@ -0,0 +1,174 @@
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+#endif
+
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 773, "Horizontal ScrollView locks after rotation", PlatformAffected.iOS)]
+ public class Issue773 : TestNavigationPage
+ {
+ protected override void Init ()
+ {
+ PushAsync (new CannotScrollRepro ());
+ }
+
+#if UITEST
+ [Test]
+ [Issue (IssueTracker.Github, 773, "Horizontal ScrollView locks after rotation - relayout correctly after rotation", PlatformAffected.iOS)]
+ [UiTest (typeof(ScrollView))]
+ public void Issue773TestsRotationRelayoutIssue ()
+ {
+ RunningApp.SetOrientationLandscape ();
+
+ var buttonLabels = new [] {
+ "Button 1",
+ "Button 2",
+ "Button 3",
+ };
+
+ foreach (string buttonLabel in buttonLabels)
+ RunningApp.WaitForElement (q => q.Button (buttonLabel));
+
+ RunningApp.Screenshot ("StackLayout in Modal respects rotation");
+
+ RunningApp.SetOrientationPortrait ();
+ }
+
+ //[Test]
+ //[Issue (IssueTracker.Github, 773, "Horizontal ScrollView locks after rotation - can scroll after rotation", PlatformAffected.iOS)]
+ //[UiTest (typeof (ScrollView))]
+ //public void Issue773TestsScrollingBeforeAndAfterRotation ()
+ //{
+// ScrollHorizontalForEnd ();
+// App.WaitForElement (q => q.Marked ("I was clicked once!"));
+// App.Screenshot ("Scrolling successful before rotation");
+//
+// App.SetOrientationLandscape ();
+// App.Tap (q => q.Marked ("Button 8"));
+// App.WaitForElement (q => q.Marked ("I was clicked again!"));
+// App.Screenshot ("Scrolling successful after rotation");
+//
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Can scroll back to beginning");
+//
+// ScrollHorizontalForBeginning ();
+// App.Screenshot ("Can scroll back to beginning");
+// }
+
+ //void ScrollHorizontalForEnd ()
+ //{
+ // int count = 0;
+
+ // AppRect screenBounds = App.ScreenBounds ();
+
+ // float scrollXStart = (4 / 5.0f) * screenBounds.Width;
+ // float scrollXEnd = screenBounds.Width / 5;
+ // float scrollY = App.Query (q => q.Marked ("Button 1"))[0].Rect.CenterY;
+
+ // while (count < 4) {
+ // App.Pan (new Drag (screenBounds, scrollXStart, scrollY, scrollXEnd, scrollY, Drag.Direction.RightToLeft));
+ // count++;
+ // }
+
+ // App.Tap (q => q.Button ("Button 8"));
+ //}
+
+ //void ScrollHorizontalForBeginning ()
+ //{
+ // int count = 0;
+
+ // AppRect screenBounds = App.ScreenBounds ();
+
+ // float scrollXStart = screenBounds.Width / 5;
+ // float scrollXEnd = (4 / 5.0f) * screenBounds.Width;
+ // float scrollY = App.Query (q => q.Button ("Button 8"))[0].Rect.CenterY;
+
+ // while (count < 4) {
+ // App.Pan (new Drag (screenBounds, scrollXStart, scrollY, scrollXEnd, scrollY, Drag.Direction.LeftToRight));
+ // count++;
+ // }
+
+ // App.Tap (q => q.Button ("Button 1"));
+
+ //}
+#endif
+ }
+
+ public class CannotScrollRepro : ContentPage
+ {
+ public CannotScrollRepro ()
+ {
+ Title = "Nav Bar";
+
+ var layout = new StackLayout {
+ Padding = new Thickness (20),
+ BackgroundColor = Color.Gray
+ };
+
+ var button1 = new Button { Text = "Button 1" };
+ var button2 = new Button { Text = "Button 2", IsEnabled = false };
+ var button3 = new Button { Text = "Button 3", IsEnabled = false };
+ var button4 = new Button { Text = "Button 4", IsEnabled = false };
+ var button5 = new Button { Text = "Button 5", IsEnabled = false };
+ var button6 = new Button { Text = "Button 6", IsEnabled = false };
+ var button7 = new Button { Text = "Button 7", IsEnabled = false };
+ var button8 = new Button { Text = "Button 8" };
+
+ var label = new Label { Text = "Not Clicked" };
+
+ var buttonStack = new StackLayout {
+ Padding = new Thickness (30, 0),
+ Orientation = StackOrientation.Horizontal,
+ Spacing = 30,
+ Children = {
+ button1,
+ button2,
+ button3,
+ button4,
+ button5,
+ button6,
+ button7,
+ button8,
+ }
+ };
+
+ button1.Clicked += (sender, args) => Navigation.PopModalAsync ();
+
+ int count = 0;
+ button8.Clicked += (sender, e) => {
+ if (count == 0) {
+ label.Text = "I was clicked once!";
+ count++;
+ } else if (count == 1) {
+ label.Text = "I was clicked again!";
+ count++;
+ } else if (count == 2) {
+ label.Text = "I was clicked again again!";
+ }
+ };
+
+ layout.Children.Add (new BoxView {
+ BackgroundColor = Color.Red,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand
+ });
+
+ layout.Children.Add (label);
+
+ layout.Children.Add (new ScrollView {
+ BackgroundColor = Color.Aqua,
+ Orientation = ScrollOrientation.Horizontal,
+ HeightRequest = Device.OnPlatform (44, 44, 80),
+ Content = buttonStack
+ });
+
+ Content = layout;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue774.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue774.cs
new file mode 100644
index 00000000..7eec0f6c
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue774.cs
@@ -0,0 +1,77 @@
+using System.Diagnostics;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+using Xamarin.UITest.iOS;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 774, "ActionSheet won't dismiss after rotation to landscape", PlatformAffected.Android, NavigationBehavior.PushModalAsync)]
+ public class Issue774 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Content = new StackLayout {
+ Children = {
+ new Label {
+ Text = "Hi"
+ },
+ new Button {
+ Text = "Show ActionSheet",
+ Command = new Command (async () => await DisplayActionSheet ("What's up", "Dismiss", "Destroy"))
+ }
+ }
+ };
+ }
+
+#if UITEST
+ [Test]
+ public void Issue774TestsDismissActionSheetAfterRotation ()
+ {
+
+ RunningApp.Tap (q => q.Button ("Show ActionSheet"));
+ RunningApp.Screenshot ("Show ActionSheet");
+
+ RunningApp.SetOrientationLandscape ();
+ RunningApp.Screenshot ("Rotate Device");
+
+ var app = (RunningApp as iOSApp);
+
+ if (app != null) {
+
+ if (!app.Device.IsTablet)
+ RunningApp.Tap (q => q.Marked ("Dismiss"));
+ else // iPad does not have dismiss option
+ RunningApp.Tap (q => q.Marked ("Destroy"));
+
+ if(app.Device.IsTablet)
+ RunningApp.WaitForNoElement (q => q.Marked ("Destroy"));
+ else
+ RunningApp.WaitForNoElement (q => q.Marked ("Dismiss"));
+ RunningApp.Screenshot ("Dismiss ActionSheet");
+
+// App.SetOrientationPortrait ();
+// App.Tap (q => q.Button ("Show ActionSheet"));
+// App.Screenshot ("Rotate and show ActionSheet");
+//
+// if (!app.Device.IsTablet)
+// App.Tap (q => q.Button ("Dismiss"));
+// else // iPad does not have dismiss option
+// App.Tap (q => q.Marked ("Destroy"));
+//
+// if (app.Device.IsTablet)
+// App.WaitForNoElement (q => q.Marked ("Destroy"));
+// else // iPad does not have dismiss option
+// App.WaitForNoElement (q => q.Marked ("Dismiss"));
+
+ }
+ }
+#endif
+
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue852.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue852.cs
new file mode 100644
index 00000000..b68a6285
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue852.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 852, "Async loading of Content causes UI element to be unclickable", PlatformAffected.Android | PlatformAffected.iOS)]
+ public class Issue852 : ContentPage
+ {
+#if APP
+ StackLayout _loggingInStackLayout;
+ Button _loginButton;
+ ScrollView _loginScrollView;
+
+ public Issue852 ()
+ {
+ var welcomeLabel = new Label()
+ {
+ Text = "Logging into the System",
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ var activitySpinner = new ActivityIndicator
+ {
+ Color = new Color(0, 0, 1),
+ IsRunning = true
+ };
+
+ _loggingInStackLayout = new StackLayout
+ {
+ Orientation = StackOrientation.Vertical,
+ VerticalOptions = LayoutOptions.Center,
+ Spacing = 15
+ };
+
+ _loggingInStackLayout.Children.Add(welcomeLabel);
+ _loggingInStackLayout.Children.Add(activitySpinner);
+
+ Content = _loggingInStackLayout;
+ }
+
+ protected override async void OnAppearing()
+ {
+ base.OnAppearing();
+
+ if (!(await AttemptLogin())) //try to log in, if login fails show login screen
+ {
+ Device.BeginInvokeOnMainThread (() => BuildLogin ());
+ }
+ else
+ {
+ Navigation.PopModalAsync();
+ }
+ IsBusy = false;
+
+ }
+
+ void BuildLogin()
+ {
+ Title = "Login";
+ var welcomeLabel = new Label()
+ {
+ Text = "Welcome to the System",
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ var usernameEntry = new Entry
+ {
+ IsPassword = false,
+ Placeholder = "Username",
+ };
+ usernameEntry.SetBinding(Entry.TextProperty, new Binding("Username"));
+ usernameEntry.Focused += (s, e) => welcomeLabel.Text = "Clicked User";
+
+ var passwordEntry = new Entry
+ {
+ IsPassword = true,
+ Placeholder = "Password",
+ };
+ passwordEntry.SetBinding(Entry.TextProperty, new Binding("Password", BindingMode.TwoWay));
+ passwordEntry.Focused += (s, e) => welcomeLabel.Text = "Clicked Password";
+
+ _loginButton = new Button
+ {
+ ClassId = "loginButton",
+ Text = "Login",
+ };
+ _loginButton.SetBinding(Button.CommandProperty, new Binding("LoginCommand"));
+
+ var loginStackLayout = new StackLayout
+ {
+ Orientation = StackOrientation.Vertical,
+ VerticalOptions = LayoutOptions.Center,
+ Spacing = 15
+ };
+
+ loginStackLayout.Children.Add(welcomeLabel);
+ loginStackLayout.Children.Add(usernameEntry);
+ loginStackLayout.Children.Add(passwordEntry);
+ loginStackLayout.Children.Add(_loginButton);
+
+
+ _loginScrollView = new ScrollView
+ {
+ Orientation = ScrollOrientation.Vertical,
+ Content = loginStackLayout
+ };
+ Content = _loginScrollView;
+ }
+
+ async Task<bool> AttemptLogin()
+ {
+ await Task.Delay(2000);
+ return false; //for this test we are always going ot fail, want to show login screen and error
+ }
+#endif
+#if UITEST
+ [Test]
+ [UiTest (typeof(ContentPage))]
+ public void Issue852TestsEntriesClickable ()
+ {
+ // TODO: Fix ME
+
+ //App.WaitForElement (q => q.Marked ("Welcome to the System"));
+ //App.WaitForElement (PlatformQueries.EntryWithPlaceholder ("Username"));
+ //App.WaitForElement (PlatformQueries.EntryWithPlaceholder ("Password"));
+ //App.WaitForElement (q => q.Button ("Login"));
+ //App.Screenshot ("All elements present");
+
+ //App.Tap (PlatformQueries.EntryWithPlaceholder ("Username"));
+ //App.WaitForElement (q => q.Marked ("Clicked User"));
+ //App.EnterText (PlatformQueries.EntryWithPlaceholder ("Username"), "Usertest");
+ //App.Screenshot ("User entered");
+
+ //App.Tap (PlatformQueries.EntryWithPlaceholder ("Password"));
+ //App.WaitForElement (q => q.Marked ("Clicked Password"));
+ //App.EnterText (PlatformQueries.EntryWithPlaceholder ("Password"), "Userpass");
+ //App.Screenshot ("Password entered");
+
+ //App.Screenshot ("Enties clickable");
+ Assert.Inconclusive ("Fix Test");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue886.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue886.cs
new file mode 100644
index 00000000..c8a1043e
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue886.cs
@@ -0,0 +1,71 @@
+using System.Diagnostics;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Maps;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 886, "Map scrolling problems", PlatformAffected.Android)]
+ public class Issue886 : ContentPage
+ {
+ public Issue886 ()
+ {
+ var isScrollEnabledSwitch = new Switch {
+ IsToggled = true
+ };
+ var isScrollEnabledLabel = new Label {
+ Text = "Scroll Enabled"
+ };
+ var isScrollEnabledLabelOn = new Label {
+ Text = isScrollEnabledSwitch.IsToggled.ToString ()
+ };
+
+ var isZoomEnabledSwitch = new Switch {
+ IsToggled = true
+ };
+ var isZoomEnabledLabel = new Label {
+ Text = "Zoom Enabled"
+ };
+ var isZoomEnabledLabelOn = new Label {
+ Text = isZoomEnabledSwitch.IsToggled.ToString ()
+ };
+
+ var map = new Map ();
+ isScrollEnabledSwitch.Toggled += (sender, e) => {
+ isScrollEnabledLabelOn.Text = e.Value.ToString ();
+ map.HasScrollEnabled = e.Value;
+ };
+
+ isZoomEnabledSwitch.Toggled += (sender, e) => {
+ isZoomEnabledLabelOn.Text = e.Value.ToString ();
+ map.HasZoomEnabled = e.Value;
+ };
+
+ Content = new StackLayout {
+ Children ={
+ new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ isScrollEnabledSwitch,
+ isScrollEnabledLabel,
+ isScrollEnabledLabelOn
+ }
+ },
+ new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ isZoomEnabledSwitch,
+ isZoomEnabledLabel,
+ isZoomEnabledLabelOn
+ }
+ },
+ map
+ }
+ };
+
+ }
+
+ }
+
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue889.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue889.cs
new file mode 100644
index 00000000..bc8a5ecd
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue889.cs
@@ -0,0 +1,140 @@
+using System.Diagnostics;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 889, "Assigning to MasterDetailPage.Detail after construction doesn't work", PlatformAffected.Android | PlatformAffected.iOS)]
+ public class Issue889 : TestMasterDetailPage
+ {
+ protected override void Init ()
+ {
+ var cells = new [] {
+ new NavPageNameObject ("Page 1"),
+ new NavPageNameObject ("Page 3"),
+ new NavPageNameObject ("Page 4"),
+ new NavPageNameObject ("Page 5"),
+ new NavPageNameObject ("Page 6"),
+ new NavPageNameObject ("Page 7"),
+ new NavPageNameObject ("Page 8"),
+ };
+
+ var template = new DataTemplate (typeof (TextCell));
+ template.SetBinding (TextCell.TextProperty, "PageName");
+
+ var listView = new ListView {
+ ItemTemplate = template,
+ ItemsSource = cells
+ };
+
+ listView.BindingContext = cells;
+
+ listView.ItemTapped += (sender, e) => {
+ var cellName = ((NavPageNameObject)e.Item).PageName;
+ Detail = new CustomNavTabDetailPage (cellName);
+ };
+
+ var master = new ContentPage {
+ Title = "Master",
+ Icon = "bank.png",
+ Content = listView
+ };
+
+
+
+ Master = master;
+ Detail = new CustomNavTabDetailPage ("Initial Page");
+ }
+
+ // Issue892
+ // NavigationPage nested in MasterDetail not working as expected Android
+
+#if UITEST
+ [Test]
+ [Description ("Reproduce app crash - Issue #983")]
+ [UiTest (typeof(MasterDetailPage), "Detail")]
+ public void Issue899TestsAppCrashWhenSwitchingTabs ()
+ {
+ RunningApp.Tap (q => q.Marked ("Push new page"));
+ RunningApp.WaitForElement (q => q.Marked ("I have been pushed"));
+ RunningApp.Screenshot ("Push page");
+ RunningApp.Back ();
+ RunningApp.Screenshot ("Navigate back");
+
+ RunningApp.Tap (q => q.Marked ("Tab 2 Title"));
+ RunningApp.Screenshot ("Go to second tab");
+ }
+#endif
+ }
+
+ public class CustomNavTabDetailPage : NavigationPage
+ {
+ public CustomNavTabDetailPage (string pageName)
+ {
+ PushAsync (new NestedNavTabPageRootView (pageName));
+ }
+ }
+
+ public class NestedNavTabPageRootView : TabbedPage
+ {
+ public NestedNavTabPageRootView (string pageTitle)
+ {
+ Title = pageTitle;
+
+ var tabOne = new ContentPage {
+ Title = "Tab 1 Title",
+ BackgroundColor = Color.FromHex ("#666"),
+ Content = new StackLayout {
+ Children = {
+ new Button {
+ Text = "Push new page",
+ Command = new Command (() => Navigation.PushAsync (new NestedNavTabPageOneLevel ()))
+ }
+ }
+ }
+ };
+
+ var tabTwo = new ContentPage {
+ Title = "Tab 2 Title",
+ BackgroundColor = Color.FromHex ("#BBB"),
+ Content = new StackLayout {
+ Children = {
+ new Button {
+ Text = "Push new page",
+ Command = new Command (() => Navigation.PushAsync (new NestedNavTabPageOneLevel ()))
+ }
+ }
+ }
+ };
+
+ tabOne.SetValue (IconProperty, "bank.png");
+ tabTwo.SetValue (IconProperty, "coffee.png");
+ Children.Add (tabOne);
+ Children.Add (tabTwo);
+ }
+ }
+
+ public class NestedNavTabPageOneLevel : ContentPage
+ {
+ public NestedNavTabPageOneLevel ()
+ {
+ Title = "One pushed";
+ BackgroundColor = Color.FromHex("#999");
+
+ Content = new StackLayout {
+ Children = {
+ new Label {
+ TextColor = Color.Red,
+ Text = "I have been pushed"
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue892.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue892.cs
new file mode 100644
index 00000000..eb93bc82
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue892.cs
@@ -0,0 +1,224 @@
+using System.Diagnostics;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+
+ public class NavPageNameObject
+ {
+ public string PageName { get; private set; }
+
+ public NavPageNameObject (string pageName)
+ {
+ PageName = pageName;
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 892, "NavigationPages as details in MasterDetailPage don't work as expected", PlatformAffected.Android)]
+ public class Issue892 : TestMasterDetailPage
+ {
+ protected override void Init ()
+ {
+ var cells = new [] {
+ new NavPageNameObject ("Close Master"),
+ new NavPageNameObject ("Page 1"),
+ new NavPageNameObject ("Page 3"),
+ new NavPageNameObject ("Page 4"),
+ new NavPageNameObject ("Page 5"),
+ new NavPageNameObject ("Page 6"),
+ new NavPageNameObject ("Page 7"),
+ new NavPageNameObject ("Page 8"),
+ };
+
+ var template = new DataTemplate (typeof (TextCell));
+ template.SetBinding (TextCell.TextProperty, "PageName");
+
+ var listView = new ListView {
+ ItemTemplate = template,
+ ItemsSource = cells
+ };
+
+ listView.BindingContext = cells;
+
+ listView.ItemTapped += (sender, e) => {
+ var cellName = ((NavPageNameObject)e.Item).PageName;
+ if (cellName == "Close Master") {
+ IsPresented = false;
+ } else {
+ Detail = new CustomNavDetailPage (cellName);
+ }
+ };
+
+ var master = new ContentPage {
+ Padding = new Thickness(0, 20, 0, 0),
+ Title = "Master",
+ Content = listView
+ };
+
+ Master = master;
+ Detail = new CustomNavDetailPage ("Initial Page");
+
+ MessagingCenter.Subscribe<NestedNavPageRootView> (this, "PresentMaster", (sender) => {
+ IsPresented = true;
+ });
+ }
+
+ // Issue892
+ // NavigationPage nested in MasterDetail not working as expected Android
+
+#if UITEST
+ [Test]
+ [Description ("Change pages in the Master ListView, and navigate to the end and back")]
+ [UiTest (typeof(MasterDetailPage))]
+ [UiTest (typeof(NavigationPage))]
+ public void Issue892TestsNavigateChangePagesNavigate ()
+ {
+ NavigateToEndAndBack ();
+
+ RunningApp.Tap (q => q.Marked ("Present Master"));
+
+ RunningApp.Tap (q => q.Marked ("Page 5"));
+
+ RunningApp.Tap (q => q.Marked ("Close Master"));
+
+ RunningApp.Screenshot ("Select new detail navigation");
+
+ NavigateToEndAndBack ();
+ }
+
+ void NavigateToEndAndBack ()
+ {
+ RunningApp.WaitForElement (q => q.Button ("Push next page")); // still required on iOS
+ RunningApp.Tap (q => q.Marked ("Push next page"));
+ RunningApp.Screenshot ("Pushed first page");
+
+ RunningApp.WaitForElement (q => q.Button ("Push next next page")); // still required on iOS
+ RunningApp.Tap (q => q.Marked ("Push next next page"));
+ RunningApp.Screenshot ("Pushed second page");
+
+ RunningApp.WaitForElement (q => q.Marked ("You are at the end of the line"));
+ RunningApp.Screenshot ("Pushed last page");
+
+ RunningApp.Tap (q => q.Marked ("Check back one"));
+ RunningApp.WaitForElement (q => q.Marked ("Pop one"));
+ RunningApp.Back ();
+ RunningApp.Screenshot ("Navigate Back");
+
+ RunningApp.Tap (q => q.Marked ("Check back two"));
+ RunningApp.WaitForElement (q => q.Marked ("Pop two"));
+ RunningApp.Back ();
+ RunningApp.Screenshot ("Navigate Back");
+
+ RunningApp.Tap (q => q.Marked ("Check back three"));
+ RunningApp.WaitForElement (q => q.Marked ("At root"));
+ RunningApp.Screenshot ("At root");
+ }
+#endif
+
+ }
+
+ public class CustomNavDetailPage : NavigationPage
+ {
+ public CustomNavDetailPage (string pageName)
+ {
+ PushAsync (new NestedNavPageRootView (pageName));
+ }
+ }
+
+ public class NestedNavPageRootView : ContentPage
+ {
+ public NestedNavPageRootView (string pageTitle)
+ {
+ Title = pageTitle;
+ BackgroundColor = Color.FromHex("#666");
+
+ var label = new Label {
+ Text = "Not Tapped"
+ };
+
+ Content = new StackLayout {
+ Children = {
+ label,
+ new Button {
+ Text = "Check back three",
+ Command = new Command (() => { label.Text = "At root"; })
+ },
+ new Button {
+ Text = "Push next page",
+ Command = new Command (() => Navigation.PushAsync (new NestedNavPageOneLevel ()))
+ },
+ new Button {
+ Text = "Present Master",
+ Command = new Command (() => {
+ MessagingCenter.Send<NestedNavPageRootView> (this, "PresentMaster");
+ })
+ }
+ }
+ };
+ }
+ }
+
+ public class NestedNavPageOneLevel : ContentPage
+ {
+ public NestedNavPageOneLevel ()
+ {
+ Title = "One pushed";
+ BackgroundColor = Color.FromHex("#999");
+
+ var label = new Label {
+ Text = "Not Tapped"
+ };
+
+ Content = new StackLayout {
+ Children = {
+ label,
+ new Button {
+ Text = "Check back two",
+ Command = new Command (() => { label.Text = "Pop two"; })
+ },
+ new Button {
+ Text = "Push next next page",
+ Command = new Command (() => Navigation.PushAsync (new NestedNavPageTwoLevels ()))
+ }
+ }
+ };
+ }
+ }
+
+ public class NestedNavPageTwoLevels : ContentPage
+ {
+ public NestedNavPageTwoLevels ()
+ {
+ Title = "Two pushed";
+ BackgroundColor = Color.FromHex("#BBB");
+
+ var label = new Label {
+ Text = "Not Tapped",
+ TextColor = Color.Red
+ };
+
+ var label2 = new Label {
+ Text = "You are at the end of the line",
+ TextColor = Color.Red
+ };
+
+ Content = new StackLayout {
+ Children = {
+ label,
+ label2,
+ new Button {
+ Text = "Check back one",
+ Command = new Command (() => { label.Text = "Pop one"; })
+ },
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue935.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue935.cs
new file mode 100644
index 00000000..6ddc21bc
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue935.cs
@@ -0,0 +1,83 @@
+using System.Diagnostics;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ public class Person
+ {
+ public string Name { get; set; }
+
+ public Person (string name)
+ {
+ Name = name;
+ }
+ }
+
+
+ public class CustomViewCell : ViewCell
+ {
+
+ public CustomViewCell ()
+ {
+ int tapsFired = 0;
+
+ Height = 50;
+
+ var label = new Label {
+ Text = "I have been selected:"
+ };
+
+ Tapped += (s, e) => {
+ tapsFired++;
+ label.Text = "I have been selected:" + tapsFired;
+ };
+
+ View = label;
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 935, "ViewCell.ItemTapped only fires once for ListView.SelectedItem", PlatformAffected.Android)]
+ public class Issue935 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Title = "List Page";
+
+ var items = new [] {
+ new CustomViewCell (),
+ };
+
+ var cellTemplate = new DataTemplate (typeof(CustomViewCell));
+
+ var list = new ListView () {
+ ItemTemplate = cellTemplate,
+ ItemsSource = items
+ };
+
+ Content = list;
+ }
+
+#if UITEST
+ [Test]
+ [Description ("Verify that OnTapped is fired every time a ViewCell is tapped")]
+ [UiTest (typeof(ViewCell))]
+ [UiTest (typeof(ListView))]
+ [UiTest (typeof(ListView), "SelectedItem")]
+ public void Issue935TestsMultipleOnTappedViewCell ()
+ {
+ RunningApp.Tap (q => q.Marked ("I have been selected:"));
+ RunningApp.Screenshot ("Tapped Cell Once");
+ RunningApp.Tap (q => q.Marked ("I have been selected:1"));
+ RunningApp.WaitForElement (q => q.Marked ("I have been selected:2"));
+ RunningApp.Screenshot ("Tapped Cell Twice");
+ }
+#endif
+
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue968.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue968.cs
new file mode 100644
index 00000000..64c5c8f8
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue968.cs
@@ -0,0 +1,52 @@
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 968, "StackLayout does not relayout on device rotation", PlatformAffected.iOS, NavigationBehavior.PushModalAsync)]
+ public class Issue968 : TestContentPage
+ {
+ protected override void Init ()
+ {
+ Title = "Nav Bar";
+
+ var layout = new StackLayout {
+ Padding = new Thickness (20),
+ BackgroundColor = Color.Gray
+ };
+
+ layout.Children.Add (new BoxView {
+ BackgroundColor = Color.Red,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand
+ });
+
+ layout.Children.Add (new Label {
+ Text = "You should see me after rotating"
+ });
+
+ Content = layout;
+ }
+
+#if UITEST
+ [Test]
+ [Description ("Verify the layout lays out on rotations")]
+ [UiTest (typeof(StackLayout))]
+ public void Issue968TestsRotationRelayoutIssue ()
+ {
+ RunningApp.SetOrientationLandscape ();
+ RunningApp.Screenshot ("Rotated to Landscape");
+ RunningApp.WaitForElement (q => q.Marked ("You should see me after rotating"));
+ RunningApp.Screenshot ("StackLayout in Modal respects rotation");
+ RunningApp.SetOrientationPortrait ();
+ }
+#endif
+
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue973.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue973.cs
new file mode 100644
index 00000000..71a9a629
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue973.cs
@@ -0,0 +1,164 @@
+using System.Diagnostics;
+
+using Xamarin.Forms.CustomAttributes;
+using System;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ internal class PageNameObject
+ {
+ public string PageName { get; private set; }
+
+ public PageNameObject (string pageName)
+ {
+ PageName = pageName;
+ }
+ }
+
+ [Preserve (AllMembers=true)]
+ [Issue (IssueTracker.Github, 973, "ActionBar doesn't immediately update when nested TabbedPage is changed", PlatformAffected.Android)]
+ public class Issue973 : TestMasterDetailPage
+ {
+ protected override void Init ()
+ {
+ var cells = new [] {
+ new PageNameObject ("Close Master"),
+ new PageNameObject ("Page 1"),
+ new PageNameObject ("Page 2"),
+ new PageNameObject ("Page 3"),
+ new PageNameObject ("Page 4"),
+ new PageNameObject ("Page 5"),
+ new PageNameObject ("Page 6"),
+ new PageNameObject ("Page 7"),
+ new PageNameObject ("Page 8"),
+ };
+
+ var template = new DataTemplate (typeof (TextCell));
+ template.SetBinding (TextCell.TextProperty, "PageName");
+
+ var listView = new ListView {
+ ItemTemplate = template,
+ ItemsSource = cells
+ };
+
+ listView.BindingContext = cells;
+
+ listView.ItemTapped += (sender, e) => {
+
+ var cellName = ((PageNameObject)e.Item).PageName;
+
+ if (cellName == "Close Master") {
+ IsPresented = false;
+ } else {
+ var d = new CustomDetailPage (cellName) {
+ Title = "Detail"
+ };
+
+ d.PresentMaster += (s, args) => {
+ IsPresented = true;
+ };
+
+ Detail = d;
+ }
+ };
+
+ var master = new ContentPage {
+ Padding = new Thickness (0, 20, 0, 0),
+ Title = "Master",
+ Content = listView
+ };
+
+ Master = master;
+
+ var detail = new CustomDetailPage ("Initial Page") {
+ Title = "Detail"
+ };
+
+ detail.PresentMaster += (sender, e) => {
+ IsPresented = true;
+ };
+
+ Detail = detail;
+ }
+
+#if UITEST
+ [Test]
+ [Description ("Test tab reset when swapping out detail")]
+ [UiTest (typeof(NavigationPage))]
+ [UiTest (typeof(TabbedPage))]
+ public void Issue973TestsTabResetAfterDetailSwap ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Initial Page Left aligned"));
+ RunningApp.WaitForElement (q => q.Marked ("Tab 1"));
+
+ RunningApp.Tap (q => q.Marked ("Tab 2"));
+ RunningApp.WaitForElement (q => q.Marked ("Initial Page Right aligned"));
+ RunningApp.Screenshot ("Tab 2 showing");
+
+ RunningApp.Tap (q => q.Marked ("Present Master"));
+
+ RunningApp.Tap (q => q.Marked ("Page 4"));
+ RunningApp.Screenshot ("Change detail page");
+
+ RunningApp.Tap (q => q.Marked ("Close Master"));
+
+ RunningApp.WaitForElement (q => q.Marked ("Page 4 Left aligned"));
+ RunningApp.Screenshot ("Tab 1 Showing and tab 1 should be selected");
+
+ RunningApp.Tap (q => q.Marked ("Tab 2"));
+ RunningApp.WaitForElement (q => q.Marked ("Page 4 Right aligned"));
+ RunningApp.Screenshot ("Tab 2 showing");
+ }
+#endif
+
+ }
+
+ internal class CustomDetailPage : TabbedPage
+ {
+ public event EventHandler PresentMaster;
+
+ public CustomDetailPage (string pageName)
+ {
+ Title = pageName;
+
+ Children.Add (new ContentPage {
+ Title = "Tab 1",
+ Content = new StackLayout {
+ Children = {
+ new Label {
+ VerticalOptions = LayoutOptions.Center,
+ HorizontalOptions = LayoutOptions.Start,
+ Text = pageName + " Left aligned"
+ }
+ }
+ }
+ });
+
+ Children.Add (new ContentPage {
+ Title = "Tab 2",
+ Content = new StackLayout {
+ Children = {
+ new Label {
+ VerticalOptions = LayoutOptions.Center,
+ HorizontalOptions = LayoutOptions.End,
+ Text = pageName + " Right aligned"
+ },
+ new Button {
+ Text = "Present Master",
+ Command = new Command (() => {
+ var handler = PresentMaster;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ })
+ }
+ }
+ }
+ });
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ListViewViewCellBinding.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ListViewViewCellBinding.cs
new file mode 100644
index 00000000..dbc3c8ea
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ListViewViewCellBinding.cs
@@ -0,0 +1,168 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Threading;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+
+ public class GenericValueConverter : IValueConverter
+ {
+ Func<object, object> _convert;
+ Func<object, object> _back;
+ public GenericValueConverter (Func<object, object> convert, Func<object, object> back = null)
+ {
+ _convert = convert;
+ _back = back;
+ }
+
+ public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ return _convert (value);
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ return _back (value);
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Expense
+ {
+ public string Name { get; private set; }
+ public decimal Amount { get; private set; }
+
+ public Expense (string name, decimal amount)
+ {
+ Name = name;
+ Amount = amount;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class ExpenseListViewCell : ViewCell
+ {
+ public ExpenseListViewCell ()
+ {
+ var expenseNameLabel = new Label ();
+ expenseNameLabel.SetBinding (Label.TextProperty, "Name");
+
+ var expenseAmountLabel = new Label ();
+ var expenseAmountToStringConverter = new GenericValueConverter (obj => string.Format ("{0:C}", ((decimal)obj)));
+ expenseAmountLabel.SetBinding (Label.TextProperty, new Binding ("Amount", converter: expenseAmountToStringConverter));
+
+ var layout = new StackLayout ();
+
+ layout.Children.Add (expenseNameLabel);
+ layout.Children.Add (expenseAmountLabel);
+
+ View = layout;
+ }
+
+ protected override void OnBindingContextChanged ()
+ {
+ // Fixme : this is happening because the View.Parent is getting
+ // set after the Cell gets the binding context set on it. Then it is inheriting
+ // the parents binding context.
+ View.BindingContext = BindingContext;
+ base.OnBindingContextChanged ();
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.None, 0, "ListView ViewCell binding", PlatformAffected.All)]
+ public class ListViewViewCellBinding : TestContentPage
+ {
+
+ // Binding issue with view cells
+ public ObservableCollection<Expense> Expenses;
+
+ protected override void Init ()
+ {
+ //BindingContext = this;
+
+ Expenses = new ObservableCollection<Expense> {
+ new Expense ("1", 100.0m),
+ new Expense ("2", 200.0m),
+ new Expense ("3", 300.0m)
+ };
+
+ var listView = new ListView ();
+
+ listView.ItemsSource = Expenses;
+ listView.ItemTemplate = new DataTemplate (typeof (ExpenseListViewCell));
+
+ var layout = new StackLayout ();
+ int numberAdded = 3;
+
+ var label = new Label {
+ Text = numberAdded.ToString()
+ };
+
+ var removeBtn = new Button { Text = "Remove" };
+ removeBtn.Clicked += (s, e) => {
+ if (numberAdded > 0) {
+ numberAdded--;
+ Expenses.RemoveAt (0);
+ label.Text = numberAdded.ToString ();
+ }
+ };
+ var addBtn = new Button { Text = "Add" };
+ addBtn.Clicked += (s, e) => {
+ Expenses.Add (new Expense ("4", 400.0m));
+ numberAdded++;
+ label.Text = numberAdded.ToString ();
+ };
+
+
+ layout.Children.Add (label);
+ layout.Children.Add (removeBtn);
+ layout.Children.Add (addBtn);
+ layout.Children.Add (listView);
+
+ Content = layout;
+ }
+
+#if UITEST
+ [Test]
+ public void ListViewViewCellBindingTestsAllElementsPresent ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Remove"));
+ RunningApp.WaitForElement (q => q.Marked ("Add"));
+ RunningApp.WaitForElement (q => q.Marked ("1"));
+ RunningApp.WaitForElement (q => q.Marked ("$100.00"));
+ RunningApp.WaitForElement (q => q.Marked ("2"));
+ RunningApp.WaitForElement (q => q.Marked ("$200.00"));
+ RunningApp.WaitForElement (q => q.Marked ("3"));
+ RunningApp.WaitForElement (q => q.Marked ("$300.00"));
+
+ RunningApp.Screenshot ("All elements exist");
+ }
+
+ [Test]
+ public void ListViewViewCellBindingTestsAddListItem ()
+ {
+ RunningApp.Tap (q => q.Button ("Add"));
+ RunningApp.WaitForElement (q => q.Marked ("4"));
+ RunningApp.WaitForElement (q => q.Marked ("$400.00"));
+ RunningApp.Screenshot ("List item added");
+ }
+
+ [Test]
+ public void ListViewViewCellBindingTestsRemoveListItem ()
+ {
+ RunningApp.Tap (q => q.Button ("Remove"));
+ RunningApp.WaitForNoElement (q => q.Marked ("1"));
+ RunningApp.WaitForNoElement (q => q.Marked ("$100.00"));
+ RunningApp.Screenshot ("List item removed");
+ }
+#endif
+
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ModalActivityIndicatorTest.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ModalActivityIndicatorTest.cs
new file mode 100644
index 00000000..b60c6351
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ModalActivityIndicatorTest.cs
@@ -0,0 +1,150 @@
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms;
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.None, 0, "Activity Indicator Does Not Show when set to default color")]
+ public class ModalActivityIndicatorTest : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var vm = new ModalActivityIndicatorModel () { IsBusy = false, BusyText = "Not busy" };
+
+ var button = new Button () { Text = "Make Busy" };
+ var colorToggle = new Button() {Text = "Toggle Activity Indicator Color" };
+
+ button.Clicked += async (sender, args) => {
+ vm.IsBusy = true;
+ vm.BusyText = "Busy";
+ await Task.Delay (1500);
+ vm.IsBusy = false;
+ vm.BusyText = "Not Busy";
+ };
+
+ var activityIndicator = new ModalActivityIndicator();
+ activityIndicator.BindingContext = vm;
+
+ colorToggle.Clicked += (sender, args) => {
+ vm.Color = vm.Color.IsDefault ? Color.Green : Color.Default;
+ };
+
+ Content = new StackLayout() {
+ Children = { button, colorToggle, activityIndicator }
+ };
+ }
+
+ [Preserve(AllMembers = true)]
+ public class ModalActivityIndicatorModel : INotifyPropertyChanged
+ {
+ bool _isBusy;
+ string _busyText;
+ Color _color;
+
+ public ModalActivityIndicatorModel ()
+ {
+ _color = Color.Default;
+ }
+
+ public bool IsBusy
+ {
+ get { return _isBusy; }
+ set
+ {
+ _isBusy = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public string BusyText
+ {
+ get { return _busyText; }
+ set
+ {
+ _busyText = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public Color Color
+ {
+ get { return _color; }
+ set
+ {
+ _color = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChanged?.Invoke (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+
+ [Preserve(AllMembers = true)]
+ public class ModalActivityIndicator : RelativeLayout
+ {
+ public ModalActivityIndicator()
+ {
+ this.SetBinding(IsVisibleProperty, "IsBusy");
+ this.SetBinding(IsEnabledProperty, "IsBusy");
+
+ Children.Add(
+ view: new BoxView
+ {
+ Opacity = .4,
+ BackgroundColor = Color.FromHex("#ccc")
+ },
+ widthConstraint: Forms.Constraint.RelativeToParent((parent) => {
+ return parent.Width;
+ }),
+ heightConstraint: Forms.Constraint.RelativeToParent((parent) => {
+ return parent.Height;
+ })
+ );
+
+ var content = new StackLayout
+ {
+ BackgroundColor = Color.White,
+ Spacing = 10,
+ Padding = new Thickness(
+ horizontalSize: 10,
+ verticalSize: 20
+ )
+ };
+
+ var activityIndicator = new ActivityIndicator { IsRunning = true };
+ activityIndicator.SetBinding(ActivityIndicator.ColorProperty, "Color");
+
+ content.Children.Add(activityIndicator);
+ var label = new Label { HorizontalOptions = LayoutOptions.CenterAndExpand };
+
+ label.SetBinding(Label.TextProperty, "BusyText");
+ label.SetBinding(Label.TextColorProperty, "Color");
+
+ content.Children.Add(label);
+
+ Children.Add(
+ view: content,
+ widthConstraint: Forms.Constraint.RelativeToParent((parent) => {
+ return parent.Width / 2;
+ }),
+ heightConstraint: Forms.Constraint.RelativeToParent((parent) => {
+ return parent.Width / 3;
+ }),
+ xConstraint: Forms.Constraint.RelativeToParent((parent) => {
+ return parent.Width / 4;
+ }),
+ yConstraint: Forms.Constraint.RelativeToParent((parent) => {
+ return (parent.Height / 2) - (parent.Width / 6);
+ })
+ );
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ModelContentPage.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ModelContentPage.cs
new file mode 100644
index 00000000..d5c0dfc0
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ModelContentPage.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.None, 0,"Modal ContentPage", PlatformAffected.All, NavigationBehavior.PushModalAsync)]
+ public class ModalContentPage : ContentPage
+ {
+ public ModalContentPage ()
+ {
+ Title = "Test Modal";
+ Content = new Button {
+ Text = "I am button",
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ HorizontalOptions = LayoutOptions.CenterAndExpand
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/NavPage.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/NavPage.cs
new file mode 100644
index 00000000..6d6607d6
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/NavPage.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.None, 0,"NavigationPage push pop", PlatformAffected.All, NavigationBehavior.PushModalAsync)]
+ public class NavPage : ContentPage
+ {
+ public NavPage ()
+ {
+ NavigationPage page = null;
+
+ var popButton1 = new Button () { Text = "Pop", BackgroundColor = Color.Blue };
+ popButton1.Clicked += (s, a) => Navigation.PopModalAsync ();
+
+ page = new NavigationPage (new ContentPage { Content = popButton1 });
+ Navigation.PushModalAsync (page);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/NavigationStackTests.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/NavigationStackTests.cs
new file mode 100644
index 00000000..5268dca5
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/NavigationStackTests.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls.TestCasesPages
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.None, 0, "Navigation Backstack tests", PlatformAffected.All)]
+ public class NavigationStackTests : ContentPage
+ {
+ static int s_pageNumber = 0;
+
+ public NavigationStackTests ()
+ {
+ Title = "Navigation Page " + s_pageNumber;
+
+ var label = new Label {Text = Title};
+ var pushBtn = new Button {Text = "Push"};
+ var pushModalBtn = new Button {Text = "Push Modal"};
+ var pushNoAnimBtn = new Button {Text = "Push No Animation"};
+ var pushModalNoAnimBtn = new Button {Text = "Push Modal No Animation"};
+ var popBtn = new Button {Text = "Pop"};
+ var popModalBtn = new Button {Text = "Pop Modal"};
+ var popNoAnimBtn = new Button {Text = "Pop No Animation"};
+ var popModalNoAnimBtn = new Button {Text = "Pop Modal No Animation"};
+ var insertPageBtn = new Button {Text = "Insert Page"};
+ var removePageBtn = new Button {Text = "Remove Page"};
+
+ pushBtn.Clicked += async (sender, args) => await ((Button) sender).Navigation.PushAsync (new NavigationStackTests ());
+
+ pushModalBtn.Clicked += async (sender, args) => await ((Button) sender).Navigation.PushModalAsync (new NavigationPage(new NavigationStackTests ()));
+
+ pushNoAnimBtn.Clicked += async (sender, args) => await ((Button) sender).Navigation.PushAsync (new NavigationStackTests (), false);
+
+ pushModalNoAnimBtn.Clicked += async (sender, args) => await ((Button) sender).Navigation.PushModalAsync (new NavigationPage(new NavigationStackTests ()), false);
+
+ popBtn.Clicked += async (sender, args) => await ((Button) sender).Navigation.PopAsync ();
+
+ popModalBtn.Clicked += async (sender, args) => await ((Button) sender).Navigation.PopModalAsync ();
+
+ popNoAnimBtn.Clicked += async (sender, args) => await ((Button) sender).Navigation.PopAsync (false);
+
+ popModalNoAnimBtn.Clicked += async (sender, args) => await ((Button) sender).Navigation.PopModalAsync (false);
+
+ insertPageBtn.Clicked += (sender, args) => ((Button) sender).Navigation.InsertPageBefore (new NavigationStackTests (), this);
+
+ removePageBtn.Clicked += (sender, args) => {
+ Element parent = ((Element) sender);
+ NavigationPage navPage = null;
+ while (navPage == null && parent != null) {
+ navPage = parent as NavigationPage;
+ parent = parent.Parent;
+ }
+
+ if (navPage != null) {
+ navPage.Navigation.RemovePage ((Page) navPage.InternalChildren[navPage.InternalChildren.Count - 2]);
+ }
+ };
+
+ Content = new ScrollView {
+ Content = new StackLayout {
+ Children = {
+ label,
+ pushBtn,
+ pushModalBtn,
+ pushNoAnimBtn,
+ pushModalNoAnimBtn,
+ popBtn,
+ popModalBtn,
+ popNoAnimBtn,
+ popModalNoAnimBtn,
+ insertPageBtn,
+ removePageBtn
+ }
+ }
+ };
+
+ s_pageNumber++;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ScrollViewOutOfBounds.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ScrollViewOutOfBounds.cs
new file mode 100644
index 00000000..e0abcc36
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ScrollViewOutOfBounds.cs
@@ -0,0 +1,59 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.None, 0, "ScrollView out of bounds", PlatformAffected.All)]
+ public class ScrollViewOutOfBounds : ContentPage
+ {
+ public ScrollViewOutOfBounds ()
+ {
+ var header = new Label {
+ Text = "ScrollView",
+ Font = Font.SystemFontOfSize (50, FontAttributes.Bold),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ var scrollView = new ScrollView {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Content = new Label {
+ Text = "Sometimes page content fits entirely on " +
+ "the page. That's very convenient. But " +
+ "on many occasions, the content of the page " +
+ "is much too large for the page, or only " +
+ "becomes available at runtime." +
+ "\n\n" +
+ "For cases such as these, the ScrollView " +
+ "provides a solution. Simply set its " +
+ "Content property to your content \u2014 in this " +
+ "case a Label but in the general case very " +
+ "likely a Layout derivative with multiple " +
+ "children \u2014 and the ScrollView provides " +
+ "scrolling with the distinctive look and touch " +
+ "familiar to the user." +
+ "\n\n" +
+ "The ScrollView is also capable of " +
+ "horizontal scrolling, and while that's " +
+ "usually not as common as vertical scrolling, " +
+ "sometimes it comes in handy." +
+ "\n\n" +
+ "Most often, the content of a ScrollView is " +
+ "a StackLayout. Whenever you're using a " +
+ "StackLayout with a number of items determined " +
+ "only at runtime, you should probably put it in " +
+ "a StackLayout just to be sure your stuff doesn't " +
+ "go running off the bottom of the screen.",
+ Font = Font.SystemFontOfSize (NamedSize.Large)
+ }
+ };
+
+ // Build the page.
+ Content = new StackLayout {
+ Children = {
+ header,
+ scrollView
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/StackLayoutIssue.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/StackLayoutIssue.cs
new file mode 100644
index 00000000..56931857
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/StackLayoutIssue.cs
@@ -0,0 +1,132 @@
+using System.Diagnostics;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.None, 0, "StackLayout issue", PlatformAffected.All, NavigationBehavior.PushModalAsync)]
+ public class StackLayoutIssue : TestContentPage
+ {
+ protected override void Init ()
+ {
+ var logo = new Image {
+ Source = "cover1.jpg",
+ WidthRequest = 20,
+ HeightRequest = 20,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ };
+
+ var winPrizeLabel = new Label {
+ Text = "Win a Xamarin Prize",
+ XAlign = TextAlignment.Center,
+ YAlign = TextAlignment.Center,
+ VerticalOptions = LayoutOptions.FillAndExpand
+ };
+
+ Device.OnPlatform (iOS: () => winPrizeLabel.Font = Font.OfSize ("HelveticaNeue-UltraLight", NamedSize.Large));
+
+ StackLayout form = MakeForm ();
+
+ var spinButton = new Button {
+ Text = "Spin"
+ };
+
+ var mainLayout = new StackLayout {
+ Children = {
+ logo,
+ winPrizeLabel,
+ form,
+ spinButton
+ }
+ };
+
+ Content = mainLayout;
+ Padding = new Thickness (50);
+ }
+
+#if UITEST
+ [Test]
+ public void StackLayoutIssueTestsAllElementsPresent ()
+ {
+ // TODO: Fix ME
+
+ //var images = App.Query (PlatformQueries.Images);
+ //Assert.AreEqual (2, images.Length);
+
+ //App.WaitForElement (q => q.Marked ("Win a Xamarin Prize"));
+ //App.WaitForElement (PlatformQueries.EntryWithPlaceholder ("Full Name"));
+ //App.WaitForElement (PlatformQueries.EntryWithPlaceholder ("Email"));
+ //App.WaitForElement (PlatformQueries.EntryWithPlaceholder ("Company"));
+ //App.WaitForElement (q => q.Marked ("Completed Azure Mobile Services Challenge?"));
+
+ //var switches = App.Query (q => q.Raw ("Switch"));
+ //Assert.AreEqual (1, switches.Length);
+
+ //App.WaitForElement (q => q.Button ("Spin"));
+ //App.Screenshot ("All elements present");
+
+ Assert.Inconclusive ("Fix Test");
+ }
+#endif
+
+ StackLayout MakeForm ()
+ {
+ var nameEntry = new Entry {
+ Placeholder = "Full Name"
+ };
+ var emailEntry = new Entry {
+ Placeholder = "Email"
+ };
+
+ var companyEntry = new Entry {
+ Placeholder = "Company"
+ };
+
+ var switchContainer = new StackLayout {
+ Orientation = StackOrientation.Horizontal
+ };
+
+ var switchLabel = new Label {
+ Text = "Completed Azure Mobile Services Challenge?"
+ };
+ var switchElement = new Switch ();
+
+ switchContainer.Children.Add (switchLabel);
+ switchContainer.Children.Add (switchElement);
+
+ var entryContainer = new StackLayout {
+ Children = {
+ nameEntry,
+ emailEntry,
+ companyEntry,
+ switchContainer
+ },
+ MinimumWidthRequest = 50
+ };
+
+ var qrButton = new Image {
+ Source = "cover1.jpg",
+ WidthRequest = 100,
+ HeightRequest = 100
+ };
+
+ var result = new StackLayout {
+ Orientation = StackOrientation.Horizontal
+ };
+
+ result.Children.Add (entryContainer);
+ result.Children.Add (qrButton);
+
+ result.SizeChanged += (sender, args) => {
+ Debug.WriteLine (result.Bounds);
+ };
+
+ return result;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/SwipeBackNavCrash.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/SwipeBackNavCrash.cs
new file mode 100644
index 00000000..1ec592ba
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/SwipeBackNavCrash.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+using Xamarin.UITest.iOS;
+#endif
+
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.None, 0, "Swipe back nav crash", PlatformAffected.iOS)]
+ public class SwipeBackNavCrash : TestNavigationPage
+ {
+ protected override void Init ()
+ {
+ Navigation.PushAsync (new SwipeBackNavCrashPageOne ());
+ }
+
+#if UITEST
+ [Test]
+ public void SwipeBackNavCrashTestsAllElementsPresent ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Page One"));
+ RunningApp.WaitForElement (q => q.Button ("Go to second page"));
+ }
+
+ [Test]
+ public void SwipeBackNavCrashTestsGoToSecondPage ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Page One"));
+ RunningApp.Tap (q => q.Button ("Go to second page"));
+ RunningApp.Screenshot ("At Second Page");
+ }
+
+ [Test]
+ public void SwipeBackNavCrashTestsSwipeBackDoesNotCrash ()
+ {
+ if (RunningApp is iOSApp) {
+ RunningApp.WaitForElement (q => q.Marked ("Page One"));
+ RunningApp.Tap (q => q.Button ("Go to second page"));
+ RunningApp.WaitForElement (q => q.Marked ("Swipe lightly left and right to crash this page"));
+ System.Threading.Thread.Sleep (3);
+
+ var mainBounds = RunningApp.Query (q => q.Raw ("* index:0")) [0].Rect;
+
+ Xamarin.Forms.Core.UITests.Gestures.Pan (RunningApp, new Xamarin.Forms.Core.UITests.Drag (mainBounds, 0, 125, 75, 125, Xamarin.Forms.Core.UITests.Drag.Direction.LeftToRight));
+ System.Threading.Thread.Sleep (3);
+ RunningApp.Screenshot ("Crash?");
+ RunningApp.WaitForElement (q => q.Marked ("Swipe lightly left and right to crash this page"));
+ }
+ }
+#endif
+
+ }
+
+ public class SwipeBackNavCrashPageOne : ContentPage
+ {
+ public SwipeBackNavCrashPageOne ()
+ {
+ Title = "Page One";
+ var button = new Button {
+ Text = "Go to second page"
+ };
+ button.Clicked += (sender, e) => Navigation.PushAsync (new PageTwo ());
+ Content = button;
+ }
+ }
+
+ public class PageTwo : ContentPage
+ {
+ public PageTwo ()
+ {
+ Title = "Second Page";
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = "Swipe lightly left and right to crash this page" },
+ new BoxView { Color = new Color (0.0) }
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TabbedPageTests.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TabbedPageTests.cs
new file mode 100644
index 00000000..d2c4de71
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TabbedPageTests.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.None, 0,"TabbedPage nav tests", PlatformAffected.All)]
+ public class TabbedPageTests : TestTabbedPage
+ {
+ protected override void Init ()
+ {
+ var popButton1 = new Button () { Text = "Pop", BackgroundColor = Color.Blue };
+ popButton1.Clicked += (s, a) => Navigation.PopModalAsync ();
+
+ var popButton2 = new Button () { Text = "Pop 2", BackgroundColor = Color.Blue };
+ popButton2.Clicked += (s, a) => Navigation.PopModalAsync ();
+
+ Children.Add (new ContentPage () { Title = "Page 1", Content = popButton1 });
+ Children.Add (new ContentPage () { Title = "Page 2", Content = popButton2 });
+ }
+
+#if UITEST
+ [Test]
+ public void TabbedPageWithModalIssueTestsAllElementsPresent ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Page 1"));
+ RunningApp.WaitForElement (q => q.Marked ("Page 2"));
+ RunningApp.WaitForElement (q => q.Button ("Pop"));
+
+ RunningApp.Screenshot ("All elements present");
+ }
+
+ [Test]
+ public void TabbedPageWithModalIssueTestsPopFromFirstTab ()
+ {
+ RunningApp.Tap (q => q.Button ("Pop"));
+ RunningApp.WaitForElement (q => q.Marked ("Bug Repro's"));
+
+ RunningApp.Screenshot ("Popped from first tab");
+ }
+
+ [Test]
+ public void TabbedPageWithModalIssueTestsPopFromSecondTab ()
+ {
+ RunningApp.Tap (q => q.Marked ("Page 2"));
+ RunningApp.WaitForElement (q => q.Button ("Pop 2"));
+ RunningApp.Screenshot ("On second tab");
+
+ RunningApp.Tap (q => q.Button ("Pop 2"));
+ RunningApp.WaitForElement (q => q.Marked ("Bug Repro's"));
+ RunningApp.Screenshot ("Popped from second tab");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TabbedPageWithList.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TabbedPageWithList.cs
new file mode 100644
index 00000000..a602d8b6
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TabbedPageWithList.cs
@@ -0,0 +1,71 @@
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+#endif
+
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ public class TabbedPageWithListName {
+ public string Name { get; set; }
+ }
+
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.None, 0, "TabbedPage with list", PlatformAffected.All)]
+ public class TabbedPageWithList : TestTabbedPage
+ {
+ protected override void Init ()
+ {
+ Title = "Tabbed Page with List";
+ Children.Add (new ContentPage { Title = "Tab Two" });
+ Children.Add (new ListViewTest ());
+ }
+
+#if UITEST
+ [Test]
+ public void TabbedPageWithListViewIssueTestsAllElementsPresent ()
+ {
+ RunningApp.WaitForElement (q => q.Marked ("Tab Two"));
+ RunningApp.WaitForElement (q => q.Marked ("List Page"));
+ RunningApp.Screenshot ("All elements present");
+ }
+
+ [Test]
+ public void TabbedPageWithListViewIssueTestsNavigateToAndVerifyListView ()
+ {
+ RunningApp.Tap (q => q.Marked ("List Page"));
+
+ RunningApp.WaitForElement (q => q.Marked ("Jason"));
+ RunningApp.WaitForElement (q => q.Marked ("Ermau"));
+ RunningApp.WaitForElement (q => q.Marked ("Seth"));
+
+ RunningApp.Screenshot ("ListView correct");
+ }
+#endif
+
+ public class ListViewTest : ContentPage
+ {
+ public ListViewTest ()
+ {
+ Title = "List Page";
+
+ var items = new[] {
+ new TabbedPageWithListName () { Name = "Jason" },
+ new TabbedPageWithListName () { Name = "Ermau" },
+ new TabbedPageWithListName () { Name = "Seth" }
+ };
+
+ var cellTemplate = new DataTemplate (typeof(TextCell));
+ cellTemplate.SetBinding (TextCell.TextProperty, "Name");
+
+ Content = new ListView () {
+ ItemTemplate = cellTemplate,
+ ItemsSource = items
+ };
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TestPages/TestPages.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TestPages/TestPages.cs
new file mode 100644
index 00000000..156a701d
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/TestPages/TestPages.cs
@@ -0,0 +1,223 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Reflection;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using NUnit.Framework;
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ internal static class AppPaths
+ {
+ public static string ApkPath = "../../../Xamarin.Forms.ControlGallery.Android/bin/Debug/AndroidControlGallery.AndroidControlGallery-Signed.apk";
+ public static string BundleId = "com.xamarin.quickui.controlgallery";
+ }
+
+#if UITEST
+ internal static class AppSetup
+ {
+ static IApp InitializeApp ()
+ {
+ IApp app = null;
+#if __ANDROID__
+ app = ConfigureApp.Android.ApkFile (AppPaths.ApkPath).Debug ().StartApp ();
+#elif __IOS__
+ app = ConfigureApp.iOS.InstalledApp (AppPaths.BundleId).Debug ()
+ //Uncomment to run from a specific iOS SIM, get the ID from XCode -> Devices
+ //.DeviceIdentifier("55555555-5555-5555-5555-555555555555")
+ .StartApp ();
+#endif
+ if (app == null)
+ throw new NullReferenceException ("App was not initialized.");
+
+ return app;
+ }
+
+ static void NavigateToIssue (Type type, IApp app)
+ {
+ var typeIssueAttribute = type.GetTypeInfo ().GetCustomAttribute <IssueAttribute> ();
+
+ string cellName = "";
+ if (typeIssueAttribute.IssueTracker.ToString () != "None" &&
+ typeIssueAttribute.IssueNumber != 1461 &&
+ typeIssueAttribute.IssueNumber != 342) {
+ cellName = typeIssueAttribute.IssueTracker.ToString ().Substring(0, 1) + typeIssueAttribute.IssueNumber.ToString ();
+ } else {
+ cellName = typeIssueAttribute.Description;
+ }
+
+ app.Tap (q => q.Button ("Go to Test Cases"));
+ app.WaitForElement (q => q.Raw ("* marked:'TestCasesIssueList'"));
+
+ app.EnterText (q => q.Raw ("* marked:'SearchBarGo'"), cellName);
+
+ app.WaitForElement (q => q.Raw ("* marked:'SearchButton'"));
+ app.Tap (q => q.Raw ("* marked:'SearchButton'"));
+ }
+
+ public static IApp Setup (Type pageType)
+ {
+ IApp runningApp = null;
+ try {
+ runningApp = InitializeApp ();
+ } catch {
+ Assert.Inconclusive ("App did not start for some reason");
+ }
+
+ NavigateToIssue (pageType, runningApp);
+ return runningApp;
+ }
+ }
+#endif
+
+ public abstract class TestPage : Page
+ {
+#if UITEST
+ public IApp RunningApp { get; private set; }
+#endif
+
+ protected TestPage ()
+ {
+#if APP
+ Init ();
+#endif
+ }
+
+#if UITEST
+ [SetUp]
+ public void Setup ()
+ {
+ RunningApp = AppSetup.Setup (GetType ());
+ }
+#endif
+
+ protected abstract void Init ();
+ }
+
+
+ public abstract class TestContentPage : ContentPage
+ {
+#if UITEST
+ public IApp RunningApp { get; private set; }
+#endif
+
+ protected TestContentPage ()
+ {
+#if APP
+ Init ();
+#endif
+ }
+
+#if UITEST
+ [SetUp]
+ public void Setup ()
+ {
+ RunningApp = AppSetup.Setup (GetType ());
+ }
+#endif
+
+ protected abstract void Init ();
+ }
+
+ public abstract class TestCarouselPage : CarouselPage
+ {
+#if UITEST
+ public IApp RunningApp { get; private set; }
+#endif
+
+ protected TestCarouselPage ()
+ {
+#if APP
+ Init ();
+#endif
+ }
+
+#if UITEST
+ [SetUp]
+ public void Setup ()
+ {
+ RunningApp = AppSetup.Setup (GetType ());
+ }
+#endif
+
+ protected abstract void Init ();
+ }
+
+ public abstract class TestMasterDetailPage : MasterDetailPage
+ {
+#if UITEST
+ public IApp RunningApp { get; private set; }
+#endif
+
+ protected TestMasterDetailPage ()
+ {
+#if APP
+ Init ();
+#endif
+ }
+
+#if UITEST
+ [SetUp]
+ public void Setup ()
+ {
+ RunningApp = AppSetup.Setup (GetType ());
+ }
+#endif
+
+ protected abstract void Init ();
+ }
+
+ public abstract class TestNavigationPage : NavigationPage
+ {
+#if UITEST
+ public IApp RunningApp { get; private set; }
+#endif
+
+ protected TestNavigationPage ()
+ {
+#if APP
+ Init ();
+#endif
+ }
+
+#if UITEST
+ [SetUp]
+ public void Setup ()
+ {
+ RunningApp = AppSetup.Setup (GetType ());
+ }
+#endif
+
+ protected abstract void Init ();
+ }
+
+ public abstract class TestTabbedPage : TabbedPage
+ {
+#if UITEST
+ public IApp RunningApp { get; private set; }
+#endif
+
+ protected TestTabbedPage ()
+ {
+#if APP
+ Init ();
+#endif
+ }
+
+#if UITEST
+ [SetUp]
+ public void Setup ()
+ {
+ RunningApp = AppSetup.Setup (GetType ());
+ }
+#endif
+
+ protected abstract void Init ();
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
new file mode 100644
index 00000000..c13429db
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
@@ -0,0 +1,485 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+ <HasSharedItems>true</HasSharedItems>
+ <SharedGUID>0f0db9cc-ea65-429c-9363-38624bf8f49c</SharedGUID>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration">
+ <Import_RootNamespace>Xamarin.Forms.Controls.Issues</Import_RootNamespace>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="$(MSBuildThisFileDirectory)AddingMultipleItemsListView.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)AppBarIconColors.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla21368.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla21501.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla21780.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla22229.xaml.cs">
+ <DependentUpon>Bugzilla22229.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla22401.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla24769.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla25662.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla26501.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla26868.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla27378.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla27581.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla28570.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla28796.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla28939.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla29107.xaml.cs">
+ <DependentUpon>Bugzilla29107.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla29158.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla29363.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla29229.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla31145.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla31333.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla31366.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla31964.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32034.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32776.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32842.xaml.cs">
+ <DependentUpon>Bugzilla32842.xaml</DependentUpon>
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32847.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla33268.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla33612.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla33714.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla33890.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla34072.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla34007.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla35078.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla35127.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla35157.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla35294.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla35472.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla35477.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla35490.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla35738.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla36014.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla36649.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla36559.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla36171.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla37462.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla37841.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla37863.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla37601.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla38105.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla38827.xaml.cs">
+ <DependentUpon>Bugzilla38827.xaml</DependentUpon>
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla39395.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla39461.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla39483.xaml.cs">
+ <DependentUpon>Bugzilla39483.xaml</DependentUpon>
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla39530.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla39624.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla39463.xaml.cs">
+ <DependentUpon>Bugzilla39463.xaml</DependentUpon>
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)CarouselAsync.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla34561.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla34727.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)ComplexListView.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)DefaultColorToggleTest.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla38416.xaml.cs">
+ <DependentUpon>Bugzilla38416.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)InputTransparentIssue.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)IsPasswordToggleTest.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1025.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1026.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1691.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2983.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2963.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2981.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2964.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla29017.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2927.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)IsShowingUserIssue.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla25979.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla30317.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla29128.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla31029.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla24574.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla26233.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla27642.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla36393.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla33870.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32462.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla36681.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla36479.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)ModalActivityIndicatorTest.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla37625.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla38658.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)DataTemplateGridImageTest.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla39331.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla36788.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla38978.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla38112.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla39499.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla39668.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)_Template.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1028.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1075.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1097.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1146.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1219.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1228.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1236.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1259.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1267.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1305.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1329.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1384.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1400.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1461.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1497.xaml.cs">
+ <DependentUpon>Issue1497.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1538.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1545.xaml.cs">
+ <DependentUpon>Issue1545.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1546.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1549.xaml.cs">
+ <DependentUpon>Issue1549.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1554.xaml.cs">
+ <DependentUpon>Issue1554.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1557.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1566.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1567.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1568.xaml.cs">
+ <DependentUpon>Issue1568.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1583.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1590.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1593.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1598.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1613.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1618.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1641.xaml.cs">
+ <DependentUpon>Issue1641.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1644.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1653.xaml.cs">
+ <DependentUpon>Issue1653.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1653v2.xaml.cs">
+ <DependentUpon>Issue1653v2.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1664.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1680.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1682.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1685.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1698.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1700.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1703.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1705.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1712.xaml.cs">
+ <DependentUpon>Issue1712.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1722.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1723.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1741.xaml.cs">
+ <DependentUpon>Issue1741.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1742.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1747.xaml.cs">
+ <DependentUpon>Issue1747.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1755.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1758.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1762.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1763.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1766.xaml.cs">
+ <DependentUpon>Issue1766.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1769.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1777.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue181.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1851.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1875.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1888.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1891.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1895.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1898.xaml.cs">
+ <DependentUpon>Issue1898.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1905.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1914.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue194.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue198.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue206.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue214.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2143.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2191.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2222.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue22246_BZ.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2241.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2248.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2259.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2266.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2270.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2272.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2282.xaml.cs">
+ <DependentUpon>Issue2282.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2288.xaml.cs">
+ <DependentUpon>Issue2288.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2289.xaml.cs">
+ <DependentUpon>Issue2289.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue229.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2291.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2292.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2294.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2333.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2339.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2354.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2357.xaml.cs">
+ <DependentUpon>Issue2357.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2411.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2414.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2470.xaml.cs">
+ <DependentUpon>Issue2470.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2563.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2594.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2597.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue260.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2615.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2628.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2634.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue264.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2659.xaml.cs">
+ <DependentUpon>Issue2659.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2783.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2794.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2809.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2923.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue342.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue416.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue417.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue488.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue530.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue764.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue773.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue774.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue852.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue886.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue892.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue889.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue935.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue968.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue973.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue465.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)ListViewViewCellBinding.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)ModelContentPage.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)NavigationStackTests.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)NavPage.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)ScrollViewOutOfBounds.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)StackLayoutIssue.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)SwipeBackNavCrash.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)TabbedPageTests.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)TabbedPageWithList.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)TestPages\TestPages.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2965.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2775.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2987.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2976.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2951.xaml.cs">
+ <DependentUpon>Issue2951.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2961.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2948.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2883.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2953.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2777.xaml.cs">
+ <DependentUpon>Issue2777.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue2954.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue3086.xaml.cs">
+ <DependentUpon>Issue3086.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla27779.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla27698.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla29247.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla27318.xaml.cs">
+ <DependentUpon>Bugzilla27318.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla29453.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla28001.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)DisposedSharedPages.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla28575.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla30935.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla26032.xaml.cs">
+ <DependentUpon>Bugzilla26032.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla30835.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla27085.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla31395.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla30651.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla26171.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla31602.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla30353.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla28240.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla30324.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla31255.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla28498.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32148.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla31967.xaml.cs">
+ <DependentUpon>Bugzilla31967.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Issue3276.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla26993.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue3292.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32230.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32898.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla31330.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla31114.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue3319.xaml.cs">
+ <DependentUpon>Issue3319.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32691.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32487.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla34061.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla34632.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32902.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32801.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32447.xaml.cs">
+ <DependentUpon>Bugzilla32447.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla29257.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32040.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla33450.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla34720.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla35733.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla36009.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla34912.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32615.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla27350.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla28709.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla33578.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla22229.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue1497.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue1545.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue1549.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue1554.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue1568.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue1641.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue1653.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue1653v2.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue1712.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue1741.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue1747.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue1766.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue1898.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue2282.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue2288.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue2289.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue2357.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue2470.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue2659.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue2951.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue2777.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue3086.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla27318.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla29107.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla26032.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla31967.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue3319.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla32447.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla38827.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla32842.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla39463.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla38416.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla39483.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.shproj b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.shproj
new file mode 100644
index 00000000..07518054
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.shproj
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>0f0db9cc-ea65-429c-9363-38624bf8f49c</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
+ <PropertyGroup />
+ <Import Project="Xamarin.Forms.Controls.Issues.Shared.projitems" Label="Shared" />
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
+</Project>
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/_Template.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/_Template.cs
new file mode 100644
index 00000000..7a1f7711
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/_Template.cs
@@ -0,0 +1,35 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 1, "Issue Description")]
+ public class Issue1 : TestContentPage // or TestMasterDetailPage, etc ...
+ {
+ protected override void Init ()
+ {
+ // Initialize ui here instead of ctor
+ Content = new Label {
+ AutomationId = "IssuePageLabel",
+ Text = "See if I'm here"
+ };
+ }
+
+#if UITEST
+ [Test]
+ public void Issue1Test ()
+ {
+ RunningApp.Screenshot ("I am at Issue 1");
+ RunningApp.WaitForElement (q => q.Marked ("IssuePageLabel"));
+ RunningApp.Screenshot ("I see the Label");
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls/App.cs b/Xamarin.Forms.Controls/App.cs
new file mode 100644
index 00000000..53424cce
--- /dev/null
+++ b/Xamarin.Forms.Controls/App.cs
@@ -0,0 +1,321 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class AppLifeCycle : Application
+ {
+ protected override void OnStart ()
+ {
+ base.OnStart ();
+ }
+
+ protected override void OnSleep ()
+ {
+ base.OnSleep ();
+ }
+
+ protected override void OnResume ()
+ {
+ base.OnResume ();
+ }
+
+ public AppLifeCycle ()
+ {
+ MainPage = new ContentPage {
+ Content = new Label {
+ Text = "Testing Lifecycle events"
+ }
+ };
+ }
+ }
+
+ public class SimpleApp : Application
+ {
+ Label label;
+
+ public SimpleApp ()
+ {
+ label = new Label { VerticalOptions = LayoutOptions.CenterAndExpand };
+
+ if (Current.Properties.ContainsKey ("LabelText")) {
+ label.Text = (string) Current.Properties["LabelText"] + " Restored!";
+ Debug.WriteLine ("Initialized");
+ } else {
+ Current.Properties["LabelText"] = "Wowza";
+ label.Text = (string) Current.Properties["LabelText"] + " Set!";
+ Debug.WriteLine ("Saved");
+ }
+
+ MainPage = new ContentPage {
+ Content = new StackLayout {
+ Children = {
+ label
+ }
+ }
+ };
+
+ SerializeProperties ();
+ }
+
+ async void SerializeProperties ()
+ {
+ await Current.SavePropertiesAsync ();
+ }
+ }
+
+ public class App : Application
+ {
+ public string InsightsApiKey = Secrets["InsightsApiKey"];
+ public const string AppName = "XamarinFormsControls";
+ public const string AppVersion = "1.4.3";
+ public static int IOSVersion = -1;
+ readonly ITestCloudService _testCloudService;
+ // make sure serialized data is available here
+
+ //protected override void OnStart ()
+ //{
+ // // called right after property store is populated
+ // MainPage.BackgroundColor = Color.Green;
+ // Current.Properties["TimesStarted"] = ((int)Current.Properties["TimesStarted"]) + 1;
+ // ((MainPageLifeCycleTests)MainPage).UpdateLabels ();
+ //}
+
+ //protected override void OnResume ()
+ //{
+ // MainPage.BackgroundColor = Color.White;
+ // Current.Properties["TimesResumed"] = ((int)Current.Properties["TimesResumed"]) + 1;
+ // ((MainPageLifeCycleTests)MainPage).UpdateLabels ();
+ //}
+
+ //protected override void OnSleep ()
+ //{
+ // MainPage.BackgroundColor = Color.Red;
+ // Current.Properties["TimesSlept"] = ((int)Current.Properties["TimesSlept"]) + 1;
+ // ((MainPageLifeCycleTests)MainPage).UpdateLabels ();
+ //}
+ public static List<string> AppearingMessages = new List<string>();
+
+ public static ContentPage MenuPage { get; set; }
+
+
+
+ public App ()
+ {
+ _testCloudService = DependencyService.Get<ITestCloudService> ();
+ InitInsights ();
+ // MainPage = new MainPageLifeCycleTests ();
+ MainPage = new MasterDetailPage () {
+ Master = new ContentPage { Title = "Master", BackgroundColor = Color.Red },
+ Detail = CoreGallery.GetMainPage ()
+ };
+ }
+
+ public void SetMainPage (Page rootPage)
+ {
+ MainPage = rootPage;
+ }
+
+ void InitInsights ()
+ {
+ if (Insights.IsInitialized) {
+ Insights.ForceDataTransmission = true;
+ if (_testCloudService != null && _testCloudService.IsOnTestCloud ())
+ Insights.Identify (_testCloudService.GetTestCloudDevice (), "Name", _testCloudService.GetTestCloudDeviceName ());
+ else
+ Insights.Identify ("DemoUser", "Name", "Demo User");
+ }
+ }
+
+ public static Assembly GetAssembly (out string assemblystring)
+ {
+ assemblystring = typeof(App).AssemblyQualifiedName.Split (',')[1].Trim ();
+ var assemblyname = new AssemblyName (assemblystring);
+ return Assembly.Load (assemblyname);
+ }
+
+ public static async Task<string> LoadResource (string filename)
+ {
+ string assemblystring;
+ Assembly assembly = GetAssembly (out assemblystring);
+
+ Stream stream = assembly.GetManifestResourceStream ($"{assemblystring}.{filename}");
+ string text;
+ using (var reader = new StreamReader (stream)) {
+ text = await reader.ReadToEndAsync ();
+ }
+ return text;
+ }
+
+ public static void InitSecrets ()
+ {
+ secrets = new Dictionary<string, string> ();
+
+ string keyData = LoadResource ("secrets.txt").Result;
+ string[] entries = keyData.Split ("\n\r".ToCharArray (), StringSplitOptions.RemoveEmptyEntries);
+ foreach (string entry in entries) {
+ string[] parts = entry.Split (':');
+ if (parts.Length < 2) {
+ continue;
+ }
+
+ secrets.Add (parts[0].Trim (), parts[1].Trim ());
+ }
+ }
+
+ private static Dictionary<string, string> secrets;
+
+ public static Dictionary<string, string> Secrets
+ {
+ get
+ {
+ if (secrets == null) {
+ InitSecrets ();
+ }
+
+ return secrets;
+ }
+ }
+ }
+
+ // Not quite sure how to turn this into a test case, effectively replace the normal Application with this to repro issues reported.
+ // Full repro requires assignment to MainPage, hence the issue
+ public class NavReproApp : Application
+ {
+ NavigationPage navPage1 = new NavigationPage ();
+
+ public NavReproApp ()
+ {
+
+ var btn = new Button () { Text = "Start" };
+
+ btn.Clicked += Btn_Clicked;
+
+ navPage1.PushAsync (new ContentPage () { Content = btn });
+
+ MainPage = navPage1;
+
+ }
+
+ async void Btn_Clicked (object sender, EventArgs e)
+ {
+ await navPage1.PushAsync (new ContentPage () { Content = new Label () { Text = "Page 2" } });
+ await navPage1.PushAsync (new ContentPage () { Content = new Label () { Text = "Page 3" } });
+
+
+ var navPage2 = new NavigationPage ();
+
+ var btn = new Button () { Text = "Start Next" };
+ btn.Clicked += Btn_Clicked1;
+
+ await navPage2.PushAsync (new ContentPage () { Content = btn });
+
+ MainPage = navPage2;
+
+
+ }
+
+ async void Btn_Clicked1 (object sender, EventArgs e)
+ {
+ MainPage = navPage1;
+ await navPage1.PopAsync ();
+
+
+ await navPage1.PushAsync (new ContentPage () { Content = new Label () { Text = "Page 3a" } });
+ }
+
+ protected override void OnStart ()
+ {
+ // Handle when your app starts
+ }
+
+ protected override void OnSleep ()
+ {
+ // Handle when your app sleeps
+ }
+
+ protected override void OnResume ()
+ {
+ // Handle when your app resumes
+ }
+ }
+
+ public class MainPageLifeCycleTests : ContentPage
+ {
+ int numTimesStarted;
+ int numTimesSlept;
+ int numTimesResumed;
+
+ StackLayout numTimesStartedLayout;
+ StackLayout numTimesSleptLayout;
+ StackLayout numTimesResumedLayout;
+
+ public MainPageLifeCycleTests ()
+ {
+ object timesStarted;
+ if (!Application.Current.Properties.TryGetValue ("TimesStarted", out timesStarted)) {
+ Application.Current.Properties["TimesStarted"] = 0;
+ }
+ var numTimesStarted = (int)Application.Current.Properties["TimesStarted"];
+
+
+ object timesSlept;
+ if (!Application.Current.Properties.TryGetValue ("TimesSlept", out timesSlept)) {
+ Application.Current.Properties["TimesSlept"] = 0;
+ }
+ var numTimesSlept = (int)Application.Current.Properties["TimesSlept"];
+
+
+ object timesResumed;
+ if (!Application.Current.Properties.TryGetValue ("TimesResumed", out timesResumed)) {
+ Application.Current.Properties["TimesResumed"] = 0;
+ }
+ var numTimesResumed = (int)Application.Current.Properties["TimesResumed"];
+
+ numTimesStartedLayout = BuildLabelLayout ("TimesStarted", numTimesStarted);
+ numTimesSleptLayout = BuildLabelLayout ("TimesSlept", numTimesSlept);
+ numTimesResumedLayout = BuildLabelLayout ("TimesResumed", numTimesResumed);
+
+ var layout = new StackLayout {
+ Children = {
+ numTimesStartedLayout,
+ numTimesSleptLayout,
+ numTimesResumedLayout
+ }
+ };
+
+ Content = layout;
+ }
+
+ StackLayout BuildLabelLayout (string title, int property)
+ {
+ var labelTitle = new Label {
+ Text = title
+ };
+
+ var valueLabel = new Label {
+ Text = property.ToString ()
+ };
+
+ return new StackLayout {
+ Children = {
+ labelTitle,
+ valueLabel
+ }
+ };
+ }
+
+ public void UpdateLabels ()
+ {
+ ((Label)numTimesStartedLayout.Children[1]).Text = ((int)Application.Current.Properties["TimesStarted"]).ToString ();
+ ((Label)numTimesSleptLayout.Children[1]).Text = ((int)Application.Current.Properties["TimesSlept"]).ToString ();
+ ((Label)numTimesResumedLayout.Children[1]).Text = ((int)Application.Current.Properties["TimesResumed"]).ToString ();
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/AppearingGalleryPage.cs b/Xamarin.Forms.Controls/ControlGalleryPages/AppearingGalleryPage.cs
new file mode 100644
index 00000000..0df2eeb3
--- /dev/null
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/AppearingGalleryPage.cs
@@ -0,0 +1,129 @@
+using System;
+
+using Xamarin.Forms;
+using System.Diagnostics;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Controls
+{
+ public class AppearingGalleryPage : ContentPage
+ {
+ const string NavPageTitle = "NavAppearingPage";
+ const string MasterPageTitle = "MasterAppearingPage";
+ const string TabbedPageTitle = "TabbedAppearingPage";
+ const string CarouselPageTitle = "CarouselAppearingPage";
+
+ public AppearingGalleryPage ()
+ {
+ var initalPage = new AppearingPage (1);
+ var initalPage2 = new AppearingPage (2);
+
+ Content = new StackLayout {
+ Children = {
+ new Button { Text = NavPageTitle, Command = new Command (() => {
+ Application.Current.MainPage = new NavAppearingPage(initalPage);
+ })
+ },
+ new Button { Text = MasterPageTitle, Command = new Command (() => {
+ var page = new MasterDetailPage {
+ Title = MasterPageTitle,
+ Master = new ContentPage { Title = "Master", BackgroundColor = Color.Red },
+ Detail = new NavAppearingPage(initalPage)
+ };
+ SetMainPage (page);
+ })
+ },
+ new Button { Text = TabbedPageTitle, Command = new Command (() => {
+ var page = new TabbedPage {
+ Title = TabbedPageTitle,
+ Children = { initalPage, initalPage2 }
+ };
+ SetMainPage (page);
+ })
+ },
+ new Button { Text = CarouselPageTitle, Command = new Command (() => {
+
+ var page = new CarouselPage {
+ Title = CarouselPageTitle,
+ Children = { initalPage, initalPage2 }
+ };
+ SetMainPage (page);
+ })
+ }
+ }
+ };
+ }
+
+ static void SetMainPage (Page page)
+ {
+ var tracker = new AppearingTracker (page);
+ Application.Current.MainPage = page;
+ }
+
+ class AppearingTracker
+ {
+ int _isAppearingFired;
+ int _isDisappearingFired;
+
+ public AppearingTracker (Page page)
+ {
+ page.Appearing += (object sender, EventArgs e) => {
+ _isAppearingFired++;
+ App.AppearingMessages.Add ($"Appearing {page.Title}");
+ Debug.WriteLine ($"Appearing {page.Title}");
+ };
+
+ page.Disappearing += (object sender, EventArgs e) => {
+ _isDisappearingFired++;
+ App.AppearingMessages.Add ($"Disappearing {page.Title}");
+ Debug.WriteLine( $"Disappearing {page.Title}");
+ };
+ }
+ }
+
+ class AppearingPage : ContentPage
+ {
+ int _theId;
+ ListView _listMessages;
+ public AppearingPage (int id)
+ {
+ var tracker = new AppearingTracker (this);
+ _listMessages = new ListView ();
+ _theId = id;
+ Title = $"Page {_theId}";
+ Padding = new Thickness (20);
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = $"Hello Appearing {_theId} page" },
+ new Button { Text = "Push new Page", Command = new Command ( async () => { await Navigation.PushAsync( new AppearingPage(2)); }) },
+ new Button { Text = "Pop page", Command = new Command ( async () => { await Navigation.PopAsync(); }) },
+ new Button { Text = "Pop to root", Command = new Command ( async () => { await Navigation.PopToRootAsync(); }) },
+ new Button { Text = "Change Main Page", Command = new Command ( () => {
+ App.AppearingMessages.Clear();
+ Application.Current.MainPage = new AppearingPage(3); })
+ },
+ _listMessages
+ }
+ };
+ }
+ protected override void OnAppearing ()
+ {
+ base.OnAppearing ();
+ Device.StartTimer (new TimeSpan (200), () => {
+ _listMessages.ItemsSource = App.AppearingMessages;
+ return false;
+ });
+ }
+ }
+
+ class NavAppearingPage : NavigationPage
+ {
+ public NavAppearingPage (Page page) : base(page)
+ {
+ Title = NavPageTitle;
+ var tracker = new AppearingTracker (this);
+ }
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/AutomationIDGallery.cs b/Xamarin.Forms.Controls/ControlGalleryPages/AutomationIDGallery.cs
new file mode 100644
index 00000000..c93a9b69
--- /dev/null
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/AutomationIDGallery.cs
@@ -0,0 +1,104 @@
+using System;
+
+namespace Xamarin.Forms.Controls
+{
+ public class AutomationIdGallery : ContentPage
+ {
+
+ public AutomationIdGallery ()
+ {
+ var scrollView = new ScrollView { AutomationId = "scrollMain" };
+ var rootLayout = new StackLayout { AutomationId = "stckMain" };
+
+ var btn = new Button {
+ AutomationId = "btnTest1",
+ Text = "Test1",
+ Command = new Command (async () => await Navigation.PushModalAsync (new TestPage1 ()))
+ };
+
+ var btn2 = new Button {
+ AutomationId = "btnTest2",
+ Text = "Test2",
+ Command = new Command (async () => await Navigation.PushModalAsync (new TestPage2 ()))
+ };
+
+ rootLayout.Children.Add (btn);
+ rootLayout.Children.Add (btn2);
+
+ var toolBarItem = new ToolbarItem { AutomationId = "tbItemHello", Text= "Hello", Command = new Command(async ()=> { await DisplayAlert("Hello","","ok"); }) };
+ var toolBarItem2 = new ToolbarItem { AutomationId = "tbItemHello2", Order= ToolbarItemOrder.Secondary, Text= "Hello2", Command = new Command(async ()=> { await DisplayAlert("Hello2","","ok"); }) };
+
+ ToolbarItems.Add (toolBarItem);
+ ToolbarItems.Add (toolBarItem2);
+
+ scrollView.Content = rootLayout;
+ Content = scrollView;
+ }
+
+ internal class TestPage1 : ContentPage
+ {
+ public TestPage1 ()
+ {
+ var rootLayout = new StackLayout { AutomationId = "stckMain" };
+ var btn = new Button {
+ AutomationId = "popModal",
+ Text = "Pop",
+ Command = new Command (async () => Navigation.PopModalAsync ())
+ };
+ rootLayout.Children.Add (btn);
+ rootLayout.Children.Add (new ActivityIndicator { AutomationId = "actHello", IsRunning = true });
+ rootLayout.Children.Add (new BoxView {
+ AutomationId = "bxvHello",
+ WidthRequest = 40,
+ HeightRequest = 40,
+ BackgroundColor = Color.Red
+ });
+ rootLayout.Children.Add (new Button { AutomationId = "btnHello", Text = "Hello" });
+ rootLayout.Children.Add (new DatePicker { AutomationId = "dtPicker", Date = DateTime.Parse ("01/01/2014") });
+ rootLayout.Children.Add (new TimePicker { AutomationId = "tPicker", Time = new TimeSpan (14, 45, 50) });
+ rootLayout.Children.Add (new Label { AutomationId = "lblHello", Text = "Hello Label" });
+ rootLayout.Children.Add (new Editor { AutomationId = "editorHello", Text = "Hello Editor" });
+ rootLayout.Children.Add (new Entry { AutomationId = "entryHello", Text = "Hello Entry" });
+
+ Content = rootLayout;
+ }
+ }
+
+ internal class TestPage2 : ContentPage
+ {
+ public TestPage2 ()
+ {
+ var rootLayout = new StackLayout { AutomationId = "stckMain" };
+ var btn = new Button {
+ AutomationId = "popModal",
+ Text = "Pop",
+ Command = new Command (async () => Navigation.PopModalAsync ())
+ };
+ rootLayout.Children.Add (btn);
+ rootLayout.Children.Add (new Image { AutomationId = "imgHello", Source = "menuIcon" });
+ rootLayout.Children.Add (new ListView {
+ AutomationId = "lstView",
+ ItemsSource = new string[2] { "one", "two" },
+ HeightRequest = 50
+ });
+ rootLayout.Children.Add (new Picker { AutomationId = "pickerHello", Items = { "one", "two" } });
+ rootLayout.Children.Add (new ProgressBar { AutomationId = "progressHello", Progress = 2 });
+ rootLayout.Children.Add (new SearchBar { AutomationId = "srbHello", Text = "Hello Search" });
+ rootLayout.Children.Add (new Slider { AutomationId = "sliHello", Value = 0.5 });
+ rootLayout.Children.Add (new Stepper { AutomationId = "stepperHello", Value = 5 });
+ rootLayout.Children.Add (new Switch { AutomationId = "switchHello" });
+ rootLayout.Children.Add (new WebView {
+ AutomationId = "webviewHello",
+ WidthRequest = 100,
+ HeightRequest = 50,
+ Source = new UrlWebViewSource { Url = "http://blog.xamarin.com/" }
+ });
+
+ Content = rootLayout;
+ }
+ }
+
+
+ }
+}
+
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/BehaviorsAndTriggers.xaml b/Xamarin.Forms.Controls/ControlGalleryPages/BehaviorsAndTriggers.xaml
new file mode 100644
index 00000000..accd9186
--- /dev/null
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/BehaviorsAndTriggers.xaml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.BehaviorsAndTriggers"
+ xmlns:local="clr-namespace:Xamarin.Forms.Controls;assembly=Xamarin.Forms.Controls"
+ Padding="8">
+ <StackLayout>
+ <Label Text="Type red in the entry below" />
+ <Entry x:Name="entry" BackgroundColor="Lime">
+ <Entry.Triggers>
+ <Trigger TargetType="Entry" Property="Text" Value="red">
+ <Setter Property="Entry.BackgroundColor">
+ <Color>#ff0000</Color>
+ </Setter>
+ <Trigger.EnterActions>
+ <local:HThrob />
+ </Trigger.EnterActions>
+ <Trigger.ExitActions>
+ <local:VThrob />
+ </Trigger.ExitActions>
+ </Trigger>
+ <Trigger TargetType="Entry" Property="IsFocused" Value="true">
+ <Setter Property="Entry.BackgroundColor">
+ <Color>#0000ff</Color>
+ </Setter>
+ </Trigger>
+ </Entry.Triggers>
+ </Entry>
+ <Button Text="Click me!">
+ <Button.Behaviors>
+ <local:StopItBehavior />
+ </Button.Behaviors>
+ </Button>
+ <Label BindingContext="{x:Reference entry}" Text="{Binding Path=IsFocused}" />
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/BehaviorsAndTriggers.xaml.cs b/Xamarin.Forms.Controls/ControlGalleryPages/BehaviorsAndTriggers.xaml.cs
new file mode 100644
index 00000000..de9d4d2b
--- /dev/null
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/BehaviorsAndTriggers.xaml.cs
@@ -0,0 +1,75 @@
+using Xamarin.Forms;
+using System;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ public partial class BehaviorsAndTriggers : ContentPage
+ {
+ public BehaviorsAndTriggers ()
+ {
+ InitializeComponent ();
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class Throb : TriggerAction<VisualElement>
+ {
+ bool _horizontal;
+
+ public Throb (bool horizontal)
+ {
+ _horizontal = horizontal;
+ }
+
+ protected override async void Invoke (VisualElement sender)
+ {
+ for (var i=0;i<5;i++){
+ await sender.TranslateTo (_horizontal ? -5:0,!_horizontal ? -5 : 0, 25);
+ await sender.TranslateTo (_horizontal ? 5:0,!_horizontal ? 5: 0, 25);
+ }
+ await sender.TranslateTo (0, 0, 25);
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class HThrob : Throb
+ {
+ [Preserve]
+ public HThrob ()
+ : base (true)
+ {
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class VThrob : Throb
+ {
+ public VThrob () : base (false)
+ {
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class StopItBehavior : Behavior<Button>
+ {
+ protected override void OnAttachedTo (Button bindable)
+ {
+ base.OnAttachedTo (bindable);
+ bindable.Clicked += OnClicked;
+ }
+
+ protected override void OnDetachingFrom (Button bindable)
+ {
+ bindable.Clicked -= OnClicked;
+ base.OnDetachingFrom (bindable);
+ }
+
+ void OnClicked (object sender, EventArgs e)
+ {
+ var button = (Button)sender;
+ button.Text = "Don't do this again";
+ button.IsEnabled = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/CellForceUpdateSizeGalleryPage.cs b/Xamarin.Forms.Controls/ControlGalleryPages/CellForceUpdateSizeGalleryPage.cs
new file mode 100644
index 00000000..35b29d48
--- /dev/null
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/CellForceUpdateSizeGalleryPage.cs
@@ -0,0 +1,193 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ public class CellForceUpdateSizeGalleryPage : TabbedPage
+ {
+ public class ViewCellPage : ContentPage
+ {
+ [Preserve (AllMembers = true)]
+ public class MyViewCell : ViewCell
+ {
+ public MyViewCell ()
+ {
+ var image = new Image {
+ Source = ImageSource.FromFile ("crimson.jpg"),
+ BackgroundColor = Color.Gray,
+ HeightRequest = 50,
+ VerticalOptions = LayoutOptions.Fill,
+ HorizontalOptions = LayoutOptions.Fill
+ };
+
+ var button = new Button { Text = "+" };
+ button.Clicked += (object sender, EventArgs e) =>
+ {
+ image.HeightRequest = image.Height + 100;
+ ForceUpdateSize ();
+ };
+
+ Tapped += (object sender, EventArgs e) =>
+ {
+ image.HeightRequest = image.Height - 100;
+ ForceUpdateSize ();
+ };
+
+ View = new StackLayout { Orientation = StackOrientation.Horizontal, Children = { image, button } };
+ }
+ }
+
+ public ViewCellPage ()
+ {
+ var listview = new ListView {
+ HasUnevenRows = true,
+ };
+ var items = Enumerable.Range (0, 10);
+ listview.ItemsSource = items;
+ listview.ItemTemplate = new DataTemplate (typeof (MyViewCell));
+ Content = listview;
+ Title = "View Cell";
+ }
+ }
+
+ public class ImageCellPage : ContentPage
+ {
+ [Preserve (AllMembers = true)]
+ public class MyImageCell : ImageCell
+ {
+ public MyImageCell ()
+ {
+ ImageSource = ImageSource.FromFile ("crimson.jpg");
+ Height = 20;
+ Command = new Command (() =>
+ {
+ Height += 20;
+ ForceUpdateSize ();
+ });
+ }
+ }
+ public ImageCellPage ()
+ {
+ var listview = new ListView {
+ HasUnevenRows = true,
+ };
+ var items = Enumerable.Range (0, 10);
+ listview.ItemsSource = items;
+ listview.ItemTemplate = new DataTemplate (typeof (MyImageCell));
+ Content = listview;
+ Title = "Image Cell";
+ }
+ }
+
+ public class TextCellPage : ContentPage
+ {
+ [Preserve (AllMembers = true)]
+ public class MyTextCell : TextCell
+ {
+ public MyTextCell ()
+ {
+ Text = "I am a TextCell, short and stout.";
+ Height = 20;
+ Command = new Command (() =>
+ {
+ Height += 20;
+ ForceUpdateSize ();
+ });
+ }
+ }
+
+ public TextCellPage ()
+ {
+ var listview = new ListView {
+ HasUnevenRows = true,
+ };
+ var items = Enumerable.Range (0, 10);
+ listview.ItemsSource = items;
+ listview.ItemTemplate = new DataTemplate (typeof (MyTextCell));
+ Content = listview;
+ Title = "Text Cell";
+ }
+ }
+
+ public class EntryCellPage : ContentPage
+ {
+ [Preserve (AllMembers = true)]
+ public class MyEntryCell : EntryCell
+ {
+ public MyEntryCell ()
+ {
+ Text = "I am an EntryCell, short and stout.";
+ Height = 20;
+ Tapped += (object sender, EventArgs e) =>
+ {
+ Height += 20;
+ ForceUpdateSize ();
+ };
+ Completed += (object sender, EventArgs e) =>
+ {
+ Height -= 20;
+ ForceUpdateSize ();
+ };
+ }
+ }
+
+ public EntryCellPage ()
+ {
+ var listview = new ListView {
+ HasUnevenRows = true,
+ };
+ var items = Enumerable.Range (0, 10);
+ listview.ItemsSource = items;
+ listview.ItemTemplate = new DataTemplate (typeof (MyEntryCell));
+ Content = listview;
+ Title = "Entry Cell";
+ }
+ }
+
+ public class SwitchCellPage : ContentPage
+ {
+ [Preserve (AllMembers = true)]
+ public class MySwitchCell : SwitchCell
+ {
+ public MySwitchCell ()
+ {
+ Text = "I am a SwitchCell, short and stout.";
+ Height = 20;
+ Tapped += (object sender, EventArgs e) =>
+ {
+ Height += 20;
+ ForceUpdateSize ();
+ };
+ OnChanged += (object sender, ToggledEventArgs e) =>
+ {
+ Height -= 20;
+ ForceUpdateSize ();
+ };
+ }
+ }
+
+ public SwitchCellPage ()
+ {
+ var listview = new ListView {
+ HasUnevenRows = true,
+ };
+ var items = Enumerable.Range (0, 10);
+ listview.ItemsSource = items;
+ listview.ItemTemplate = new DataTemplate (typeof (MySwitchCell));
+ Content = listview;
+ Title = "Switch Cell";
+ }
+ }
+
+ public CellForceUpdateSizeGalleryPage ()
+ {
+ Children.Add (new ViewCellPage ());
+ Children.Add (new ImageCellPage ());
+ Children.Add (new TextCellPage ());
+ Children.Add (new EntryCellPage ());
+ Children.Add (new SwitchCellPage ());
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/LayoutAddPerformance.xaml b/Xamarin.Forms.Controls/ControlGalleryPages/LayoutAddPerformance.xaml
new file mode 100644
index 00000000..da51089d
--- /dev/null
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/LayoutAddPerformance.xaml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.LayoutAddPerformance">
+ <ScrollView>
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ </Grid.RowDefinitions>
+ <Label x:Name="timingLabel" BackgroundColor="Gray" />
+ <StackLayout Grid.Row="1" x:Name="layout">
+ </StackLayout>
+ </Grid>
+ </ScrollView>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/LayoutAddPerformance.xaml.cs b/Xamarin.Forms.Controls/ControlGalleryPages/LayoutAddPerformance.xaml.cs
new file mode 100644
index 00000000..1c25c633
--- /dev/null
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/LayoutAddPerformance.xaml.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Controls
+{
+ public partial class LayoutAddPerformance : ContentPage
+ {
+ public LayoutAddPerformance ()
+ {
+ InitializeComponent ();
+ }
+
+ protected override async void OnAppearing ()
+ {
+ base.OnAppearing ();
+
+ layout.Children.Clear ();
+
+ await Task.Delay (2000);
+
+ Stopwatch sw = new Stopwatch();
+ sw.Start ();
+ for (int i = 0; i < 500; i++) {
+ layout.Children.Add (new Label { Text = i.ToString () });
+ }
+ sw.Stop ();
+ this.timingLabel.Text = sw.ElapsedMilliseconds.ToString ();
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/ListRefresh.cs b/Xamarin.Forms.Controls/ControlGalleryPages/ListRefresh.cs
new file mode 100644
index 00000000..28afd7be
--- /dev/null
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/ListRefresh.cs
@@ -0,0 +1,115 @@
+using System;
+using Xamarin.Forms;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace Xamarin.Forms.Controls
+{
+ public class ListRefresh : ContentPage
+ {
+ public ListRefresh ()
+ {
+ var refreshingCount = 0;
+
+ var grid = new Grid ();
+ var fooViewModel = new FooViewModel ();
+ var lv = new ListView {BindingContext = fooViewModel, IsGroupingEnabled = true, GroupDisplayBinding = new Binding ("Name"), IsPullToRefreshEnabled = false};
+
+ var stack = new StackLayout ();
+ var btn = new Button { Text = string.Format ("IsRefreshing {0}", lv.IsRefreshing) };
+ btn.Command = new Command (s => {
+ lv.IsRefreshing = !lv.IsRefreshing;
+ btn.Text = string.Format("IsRefreshing {0}",lv.IsRefreshing);
+ });
+
+ var btn4 = new Button { Text = "BeginRefresh", Command = new Command (s => {
+ lv.BeginRefresh();
+ btn.Text = string.Format("IsRefreshing {0}",lv.IsRefreshing);
+ }) };
+ var btn1 = new Button { Text = "EndRefresh", Command = new Command (s => {
+ lv.EndRefresh();
+ btn.Text = string.Format("IsRefreshing {0}",lv.IsRefreshing);
+ }) };
+
+ var btn2 = new Button { Text = string.Format ("Pull {0}", lv.IsPullToRefreshEnabled) };
+ btn2.Command = new Command (s => {
+ lv.IsPullToRefreshEnabled = !lv.IsPullToRefreshEnabled;
+ btn2.Text = string.Format("Pull {0}",lv.IsPullToRefreshEnabled);
+ });
+
+ var btn3 = new Button { Text = string.Format("CanExecute {0}",fooViewModel.CanExecute) };
+ btn3.Command = new Command (s => {
+ fooViewModel.CanExecute = !fooViewModel.CanExecute;
+ btn3.Text = string.Format("CanExecute {0}",fooViewModel.CanExecute);
+ });
+
+ var lbl = new Label { Text = string.Format ("Refreshing {0}", refreshingCount) };
+ lv.Refreshing += (object sender, EventArgs e) => {
+ refreshingCount++;
+ lbl.Text = string.Format ("Refreshing {0}", refreshingCount);
+ };
+
+ stack.Children.Add (btn);
+ stack.Children.Add (btn4);
+ stack.Children.Add (btn1);
+ stack.Children.Add (btn2);
+ stack.Children.Add (btn3);
+ stack.Children.Add (lbl);
+ lv.Header = new ContentView { HeightRequest = 300, HorizontalOptions = LayoutOptions.FillAndExpand, Content = stack };
+
+ lv.SetBinding<FooViewModel> (ListView.ItemsSourceProperty, m => m.Things);
+ lv.SetBinding<FooViewModel> (ListView.RefreshCommandProperty, m => m.RefreshThingsCommand);
+ grid.Children.Add (lv, 0, 0);
+
+ Content = grid;
+ }
+
+ public class FooViewModel
+ {
+ List<Group<string>> _things;
+ public List<Group<string>> Things {
+ get
+ {
+ return _things ?? (_things = new List<Group<string>> {
+ new Group<string>(new []{"A","B","C","D","E","F","G","H","I","J","K"}) {Name = "Letters"},
+ new Group<string>(new []{"1","2","3","4","5","6","7","8","9","10"}) {Name = "Numbers"}
+ });
+ }
+ }
+
+ bool _canExecute;
+ public bool CanExecute {
+ get
+ {
+ return _canExecute;
+ }
+ set {
+ _canExecute = value;
+ RefreshThingsCommand.ChangeCanExecute ();
+ }
+ }
+
+ Command _refreshThingsCommand;
+ public Command RefreshThingsCommand {
+ get {return _refreshThingsCommand ?? (_refreshThingsCommand = new Command (BeginRefreshThings, () => _canExecute ));}
+ }
+
+ protected void BeginRefreshThings()
+ {
+
+ }
+ }
+
+ public class Group<T> : ObservableCollection<T>
+ {
+ public Group (IEnumerable<T> seed) : base(seed){}
+
+ public string Name {
+ get;
+ set;
+ }
+ }
+ }
+}
+
+
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/ListScrollTo.cs b/Xamarin.Forms.Controls/ControlGalleryPages/ListScrollTo.cs
new file mode 100644
index 00000000..9e0d8a67
--- /dev/null
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/ListScrollTo.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class RandomSizeCell
+ : TextCell
+ {
+ static readonly Random Rand = new Random (42);
+
+ public RandomSizeCell()
+ {
+ SetBinding (TextProperty, new Binding ("."));
+ Height = Rand.Next (25, 60);
+ }
+ }
+
+ public class ListScrollTo
+ : ContentPage
+ {
+ readonly List<List<string>> _items = new List<List<string>> ();
+ bool _animate = true;
+ readonly ListView _listView;
+
+ public ListScrollTo()
+ {
+ Title = "ListView ScrollTo";
+
+ for (int i = 0; i < 10; i++) {
+ List<string> subItems = new List<string> ();
+ for (int x = 0; x < 10; x++) {
+ subItems.Add (((i * 10) + x + 1).ToString());
+ }
+
+ _items.Add (subItems);
+ }
+
+ _listView = new ListView {
+ Header = "Fooooo",
+ Footer = "Baaaaar",
+ ItemsSource = _items,
+ IsGroupingEnabled = true,
+ GroupDisplayBinding = new Binding ("[0]"),
+ GroupShortNameBinding = new Binding("[0]"),
+ HasUnevenRows = true,
+ ItemTemplate = new DataTemplate (typeof(RandomSizeCell))
+ };
+
+ _listView.ScrollTo (_items[2][1], _items[2], ScrollToPosition.Center, true);
+
+ var visible = new Button { Text = "Visible" };
+ visible.Clicked += (sender, args) => _listView.ScrollTo (_items[4][4], _items[4], ScrollToPosition.MakeVisible, _animate);
+
+ var start = new Button { Text = "Start" };
+ start.Clicked += (sender, args) => _listView.ScrollTo (_items[4][4], _items[4], ScrollToPosition.Start, _animate);
+
+ var center = new Button { Text = "Center"};
+ center.Clicked += (sender, args) => _listView.ScrollTo (_items[4][4], _items[4], ScrollToPosition.Center, _animate);
+
+ var end = new Button { Text = "End" };
+ end.Clicked += (sender, args) => _listView.ScrollTo (_items[4][4], _items[4], ScrollToPosition.End, _animate);
+
+ var animate = new Button { Text = "Animate" };
+ animate.Clicked += (sender, args) => {
+ _animate = !_animate;
+ animate.Text = (_animate) ? "Animate" : "No Animate";
+ };
+
+ var buttons = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Spacing = 1,
+ HorizontalOptions = LayoutOptions.Center,
+ Children = {
+ visible,
+ start,
+ center,
+ end,
+ animate
+ }
+ };
+
+ Content = new StackLayout {
+ Children = {
+ buttons,
+ _listView
+ }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/ListViewSelectionColor.cs b/Xamarin.Forms.Controls/ControlGalleryPages/ListViewSelectionColor.cs
new file mode 100644
index 00000000..66a8ad86
--- /dev/null
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/ListViewSelectionColor.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ internal sealed class ListViewSelectionColor : ContentPage
+ {
+ [Preserve (AllMembers = true)]
+ internal sealed class GroupHeaderTemplate : ViewCell
+ {
+ public GroupHeaderTemplate ()
+ {
+ var label = new Label { BackgroundColor = Color.Red };
+ label.SetBinding (Label.TextProperty, "Key");
+ View = label;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ internal sealed class GroupItemTemplate : ViewCell
+ {
+ public GroupItemTemplate ()
+ {
+ var label = new Label { BackgroundColor = Color.Green };
+ label.SetBinding (Label.TextProperty, "Name");
+ View = label;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ internal sealed class ItemTemplate : ViewCell
+ {
+ public ItemTemplate ()
+ {
+ var label = new Label { BackgroundColor = Color.Green };
+ label.SetBinding (Label.TextProperty, "Name");
+ View = label;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ internal sealed class Artist
+ {
+ public string Name { get; private set; }
+
+ public Artist (string name)
+ {
+ Name = name;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ internal sealed class Grouping<K, T> : ObservableCollection<T>
+ {
+ public K Key { get; private set; }
+
+ public Grouping (K key, IEnumerable<T> values)
+ {
+ Key = key;
+
+ foreach (T value in values) {
+ Items.Add (value);
+ }
+ }
+ }
+
+ Button _swapListButton;
+
+ [Preserve (AllMembers = true)]
+ public ListViewSelectionColor()
+ {
+ Title = "ListView ScrollTo";
+
+ var itemSource = new [] {
+ new { Name = "John Hassel" },
+ new { Name = "Brian Eno" },
+ new { Name = "Rober Fripp" },
+ new { Name = "Edgar Froese" }
+ };
+
+ var groupedItemSource = new List<Grouping<string, Artist>> {
+ new Grouping<string, Artist> ("Prog", new List<Artist> { new Artist ("King Crimson"), new Artist ("Yes"), new Artist ("Rush") }),
+ new Grouping<string, Artist> ("Techno", new List<Artist> { new Artist ("Juan Atkins"), new Artist ("Jeff Mills"), new Artist ("Gerald Donald") } ),
+ new Grouping<string, Artist> ("Pop", new List<Artist> { new Artist ("Japan"), new Artist ("Roxy Music"), new Artist ("Talking Heads") }),
+ };
+
+ var normalList = new ListView {
+ ItemTemplate = new DataTemplate (typeof (ItemTemplate)),
+ ItemsSource = itemSource
+ };
+ var groupedList = new ListView {
+ IsGroupingEnabled = true,
+ GroupHeaderTemplate = new DataTemplate (typeof (GroupHeaderTemplate)),
+ ItemTemplate = new DataTemplate (typeof (GroupItemTemplate)),
+ ItemsSource = groupedItemSource
+ };
+
+ var currentList = normalList;
+ _swapListButton = new Button {
+ Text = "Swap List Type",
+ Command = new Command (() => {
+ if (currentList == normalList) {
+ SetContent (groupedList);
+ currentList = groupedList;
+ } else {
+ SetContent (normalList);
+ currentList = normalList;
+ }
+ })
+ };
+
+ var clear = new Button {
+ Text = "Clear",
+ Command = new Command (() => {
+ currentList.SelectedItem = null;
+ })
+ };
+
+ Content = new StackLayout {
+ Children = {
+ new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ _swapListButton,
+ clear
+ }
+ },
+ normalList
+ }
+ };
+
+ }
+
+ void SetContent (ListView list)
+ {
+ Content = new StackLayout {
+ Children = {
+ _swapListButton,
+ list
+ }
+ };
+ }
+
+
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/NavBarTitleTestPage.cs b/Xamarin.Forms.Controls/ControlGalleryPages/NavBarTitleTestPage.cs
new file mode 100644
index 00000000..d6031cbe
--- /dev/null
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/NavBarTitleTestPage.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class NavBarTitleTestPage : ContentPage
+ {
+
+ public NavBarTitleTestPage ()
+ {
+ var navTab = new NavigationPage { Title = "Hello 1 nav"};
+ navTab.PushAsync (GetPage (navTab));
+
+ var stackPages = new StackLayout ();
+
+ var btn3 = new Button {
+ Text = "tab", Command = new Command (async () => {
+ var tabbed = new TabbedPage { Title = "Main Tab" };
+ tabbed.Children.Add (navTab);
+ tabbed.Children.Add (GetPage (navTab));
+ await Navigation.PushModalAsync (tabbed);
+ })
+ };
+
+ var btn4 = new Button {
+ Text = "mdp", Command = new Command (async () => {
+ var newNav = new NavigationPage { Title = "Hello 1 nav", BarBackgroundColor = Color.Pink, BarTextColor = Color.Blue };
+ var mdp = new MasterDetailPage ();
+ await newNav.PushAsync (GetPage (newNav));
+ mdp.Master = new ContentPage {
+ Title = "Master", BackgroundColor = Color.Red, Content = new Button {
+ Text = "new", Command = new Command (() => {
+ mdp.Detail = new ContactsPage { Title = "hello 3" };
+ mdp.IsPresented = false;
+ })
+ }
+ };
+ mdp.Detail = newNav;
+ await Navigation.PushModalAsync (mdp);
+ })
+ };
+
+ var btn5 = new Button {
+ Text = "nav", Command = new Command (async () => {
+ var newNav = new NavigationPage { Title = "Hello 1 nav" };
+ await newNav.PushAsync (GetPage (newNav));
+ await Navigation.PushModalAsync (newNav);
+ })
+ };
+
+ var btn6 = new Button {
+ Text = "change nav", Command = new Command (() => {
+ (Parent as NavigationPage).BarBackgroundColor = Color.Blue;
+ (Parent as NavigationPage).BarTextColor = Color.Pink;
+ })
+ };
+
+ stackPages.Children.Add (btn3);
+ stackPages.Children.Add (btn4);
+ stackPages.Children.Add (btn5);
+ stackPages.Children.Add (btn6);
+ Content = stackPages;
+ }
+
+ static Page GetPage (NavigationPage navTab)
+ {
+ var stack = new StackLayout ();
+ var newPage = new ContentPage { Title = "Hello 2", Content = stack };
+ var btn1 = new Button { Text = "next", Command = new Command (async () => await newPage.Navigation.PushAsync (new ContactsPage { Title = "hello 3" })) };
+ var btn2 = new Button {
+ Text = "change nav", Command = new Command (() => {
+ navTab.BarBackgroundColor = Color.Blue;
+ navTab.BarTextColor = Color.Pink;
+ })
+ };
+ var btn3 = new Button {
+ Text = "pop modal", Command = new Command (() => {
+ newPage.Navigation.PopModalAsync ();
+ })
+ };
+ stack.Children.Add (btn1);
+ stack.Children.Add (btn2);
+ stack.Children.Add (btn3);
+ return newPage;
+
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/NestedNativeControlGalleryPage.cs b/Xamarin.Forms.Controls/ControlGalleryPages/NestedNativeControlGalleryPage.cs
new file mode 100644
index 00000000..9f596601
--- /dev/null
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/NestedNativeControlGalleryPage.cs
@@ -0,0 +1,27 @@
+namespace Xamarin.Forms.Controls
+{
+ public partial class NestedNativeControlGalleryPage : ContentPage
+ {
+ public StackLayout Layout { get; set; }
+
+ public bool NativeControlsAdded { get; set; }
+
+ public NestedNativeControlGalleryPage ()
+ {
+ Layout = new StackLayout { Padding = 20, VerticalOptions = LayoutOptions.FillAndExpand };
+
+ Content = new ScrollView { Content = Layout };
+
+ var label = new Label { Text = "There should be some native controls right below this", FontSize = 12 };
+
+ var testLabel = new Label { Text = "Forms Label", FontSize = 14 };
+ var button = new Button { Text = "Resize Forms Label", HeightRequest = 80 };
+ double originalSize = testLabel.FontSize;
+ button.Clicked += (sender, args) => { testLabel.FontSize = testLabel.FontSize == originalSize ? 24 : 14; };
+
+ Layout.Children.Add(testLabel);
+ Layout.Children.Add(button);
+ Layout.Children.Add(label);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/PanGestureGalleryPage.cs b/Xamarin.Forms.Controls/ControlGalleryPages/PanGestureGalleryPage.cs
new file mode 100644
index 00000000..b37e8e48
--- /dev/null
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/PanGestureGalleryPage.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class PanGestureGalleryPage : ContentPage
+ {
+ public class PanContainer : ContentView
+ {
+ public PanContainer ()
+ {
+ var pan = new PanGestureRecognizer
+ {
+ TouchPoints = 1
+ };
+
+ pan.PanUpdated += (object s, PanUpdatedEventArgs e) =>
+ {
+ switch (e.StatusType) {
+
+ case GestureStatus.Started: break;
+
+ case GestureStatus.Running:
+ Content.TranslationX = e.TotalX;
+ Content.TranslationY = e.TotalY;
+ break;
+
+ default:
+ Content.TranslationX = Content.TranslationY = 0;
+ break;
+ }
+ };
+
+ var pinch = new PinchGestureRecognizer ();
+
+ double xOffset = 0;
+ double yOffset = 0;
+ double startScale = 1;
+
+ pinch.PinchUpdated += (sender, e) =>
+ {
+
+ if (e.Status == GestureStatus.Started) {
+ startScale = Content.Scale;
+ Content.AnchorX = Content.AnchorY = 0;
+ }
+ if (e.Status == GestureStatus.Running) {
+
+ _currentScale += (e.Scale - 1) * startScale;
+ _currentScale = Math.Max (1, _currentScale);
+
+ var renderedX = Content.X + xOffset;
+ var deltaX = renderedX / Width;
+ var deltaWidth = Width / (Content.Width * startScale);
+ var originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;
+
+ var renderedY = Content.Y + yOffset;
+ var deltaY = renderedY / Height;
+ var deltaHeight = Height / (Content.Height * startScale);
+ var originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
+
+ double targetX = xOffset - (originX * Content.Width) * (_currentScale - startScale);
+ double targetY = yOffset - (originY * Content.Height) * (_currentScale - startScale);
+
+ Content.TranslationX = targetX.Clamp (-Content.Width * (_currentScale - 1), 0);
+ Content.TranslationY = targetY.Clamp (-Content.Height * (_currentScale - 1), 0);
+
+ Content.Scale = _currentScale;
+ }
+ if (e.Status == GestureStatus.Completed) {
+ xOffset = Content.TranslationX;
+ yOffset = Content.TranslationY;
+ }
+ };
+
+ GestureRecognizers.Add (pinch);
+
+ GestureRecognizers.Add (pan);
+ }
+
+ double _currentScale = 1;
+ }
+
+ public PanGestureGalleryPage ()
+ {
+ var image = new Image { Source = "http://placehold.it/2000x2000", BackgroundColor = Color.Gray, WidthRequest = 2000, HeightRequest = 2000, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
+
+ var panme = new PanContainer { Content = image };
+
+ Content = new StackLayout { Children = { new Label { Text = "Use two fingers to pinch. Use one finger to pan." }, panme }, Padding = new Thickness (20) };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/PinchGestureTestPage.cs b/Xamarin.Forms.Controls/ControlGalleryPages/PinchGestureTestPage.cs
new file mode 100644
index 00000000..44dd6ae8
--- /dev/null
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/PinchGestureTestPage.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Diagnostics;
+
+namespace Xamarin.Forms.Controls
+{
+ public class PinchToZoomContainer : ContentView
+ {
+ public PinchToZoomContainer ()
+ {
+
+ }
+
+ public void AddPinch ()
+ {
+
+ var pinch = new PinchGestureRecognizer ();
+
+ double xOffset = 0;
+ double yOffset = 0;
+ double startScale = 1;
+
+ pinch.PinchUpdated += (sender, e) => {
+
+ if (e.Status == GestureStatus.Started) {
+ startScale = Content.Scale;
+ Content.AnchorX = Content.AnchorY = 0;
+ }
+ if (e.Status == GestureStatus.Running) {
+
+ _currentScale += (e.Scale - 1) * startScale;
+ _currentScale = Math.Max (1, _currentScale);
+
+ var renderedX = Content.X + xOffset;
+ var deltaX = renderedX / Width;
+ var deltaWidth = Width / (Content.Width * startScale);
+ var originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;
+
+ var renderedY = Content.Y + yOffset;
+ var deltaY = renderedY / Height;
+ var deltaHeight = Height / (Content.Height * startScale);
+ var originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
+
+ double targetX = xOffset - (originX * Content.Width) * (_currentScale - startScale);
+ double targetY = yOffset - (originY * Content.Height) * (_currentScale - startScale);
+
+ Content.TranslationX = targetX.Clamp (-Content.Width * (_currentScale - 1), 0);
+ Content.TranslationY = targetY.Clamp (-Content.Height * (_currentScale - 1), 0);
+
+ Content.Scale = _currentScale;
+ }
+ if (e.Status == GestureStatus.Completed) {
+ xOffset = Content.TranslationX;
+ yOffset = Content.TranslationY;
+ }
+ };
+
+ GestureRecognizers.Add (pinch);
+ }
+
+ public bool AlwaysZoomCenter { get; set; }
+
+ double _currentScale = 1;
+ }
+
+ public class PinchGestureTestPage : ContentPage
+ {
+ public PinchGestureTestPage ()
+ {
+ var stack = new StackLayout { VerticalOptions = LayoutOptions.Start, HorizontalOptions = LayoutOptions.Center };
+ var textBoxScale = new Label { VerticalOptions = LayoutOptions.Start, HorizontalOptions = LayoutOptions.Center };
+ var textBox = new Label { VerticalOptions = LayoutOptions.Start, HorizontalOptions = LayoutOptions.Center };
+ var textBoxPoint = new Label { VerticalOptions = LayoutOptions.Start, HorizontalOptions = LayoutOptions.Center };
+ stack.Children.Add (textBox);
+ stack.Children.Add (textBoxScale);
+ stack.Children.Add (textBoxPoint);
+
+ var box = new Image { Source = "crimson.jpg", BackgroundColor = Color.Red, WidthRequest = 200, HeightRequest = 200, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
+
+ var zoomContainer = new PinchToZoomContainer ();
+ zoomContainer.Content = box;
+
+ var btn = new Button { Text = "add pinch gesture", Command = new Command (() => zoomContainer.AddPinch ()) };
+ var btnRemove = new Button { Text = "remove pinch gesture", Command = new Command (() => zoomContainer.GestureRecognizers.Clear ()) };
+
+ Content = new StackLayout { Children = { btn, btnRemove, new Grid { Children = { zoomContainer }, Padding = new Thickness (20) } } };
+ }
+
+ double _currentScale = 1;
+ }
+}
+
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/ToolbarItems.cs b/Xamarin.Forms.Controls/ControlGalleryPages/ToolbarItems.cs
new file mode 100644
index 00000000..3e98fc88
--- /dev/null
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/ToolbarItems.cs
@@ -0,0 +1,55 @@
+using System;
+
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Controls
+{
+ public class ToolbarItems : ContentPage
+ {
+ bool _isEnable = false;
+ public ToolbarItems ()
+ {
+ var label = new Label { Text = "Hello ContentPage", AutomationId ="label_id" };
+
+ var tb1 = new ToolbarItem ("tb1", "menuIcon.png", () => {
+ label.Text = "tb1";
+ }, ToolbarItemOrder.Primary);
+ tb1.IsEnabled = _isEnable;
+ tb1.AutomationId = "toolbaritem_primary";
+ tb1.IsEnabled = _isEnable;
+
+ var tb2 = new ToolbarItem ("tb2", null, () => {
+ label.Text = "tb2";
+ }, ToolbarItemOrder.Primary);
+ tb2.AutomationId = "toolbaritem_primary2";
+
+ var tb3 = new ToolbarItem ("tb3", "bank.png", () => {
+ label.Text = "tb3";
+ }, ToolbarItemOrder.Secondary);
+ tb3.AutomationId = "toolbaritem_secondary";
+
+ var tb4 = new ToolbarItem ();
+ tb4.Text = "tb4";
+ tb4.Order = ToolbarItemOrder.Secondary;
+ tb4.Command = new Command( (obj)=> {
+ _isEnable = true;
+ label.Text = "tb4";
+ (tb4.Command as Command).ChangeCanExecute();
+ },(obj) => _isEnable);
+ tb4.AutomationId = "toolbaritem_secondary2";
+
+ ToolbarItems.Add(tb1);
+ ToolbarItems.Add(tb2);
+ ToolbarItems.Add(tb3);
+ ToolbarItems.Add(tb4);
+
+ Content = new StackLayout {
+ Children = {
+ label
+ }
+ };
+ }
+ }
+}
+
+
diff --git a/Xamarin.Forms.Controls/Controls/Issue3076Button.cs b/Xamarin.Forms.Controls/Controls/Issue3076Button.cs
new file mode 100644
index 00000000..0ab43bce
--- /dev/null
+++ b/Xamarin.Forms.Controls/Controls/Issue3076Button.cs
@@ -0,0 +1,14 @@
+namespace Xamarin.Forms.Controls
+{
+ public class Issue3076Button : Button
+ {
+ public static readonly BindableProperty HorizontalContentAlignmentProperty =
+ BindableProperty.Create ("HorizontalContentAlignemnt", typeof(TextAlignment), typeof(Issue3076Button), TextAlignment.Center);
+
+ public TextAlignment HorizontalContentAlignment
+ {
+ get { return (TextAlignment)GetValue (HorizontalContentAlignmentProperty); }
+ set { SetValue (HorizontalContentAlignmentProperty, value); }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGallery.cs b/Xamarin.Forms.Controls/CoreGallery.cs
new file mode 100644
index 00000000..21c45e08
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGallery.cs
@@ -0,0 +1,419 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Dynamic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Runtime.InteropServices.WindowsRuntime;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Xamarin.Forms.Controls.GalleryPages;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ public static class Messages
+ {
+ public const string ChangeRoot = "com.xamarin.ChangeRoot";
+ }
+
+ internal class CoreCarouselPage : CarouselPage
+ {
+ public CoreCarouselPage ()
+ {
+ AutomationId = "CarouselPageRoot";
+ Children.Add (new CoreRootPage (this, NavigationBehavior.PushModalAsync) { Title = "Page 1" });
+ Children.Add (new CoreRootPage (this, NavigationBehavior.PushModalAsync) { Title = "Page 2" });
+ }
+ }
+
+ internal class CoreContentPage : ContentPage
+ {
+ public CoreContentPage ()
+ {
+ AutomationId = "ContentPageRoot";
+ Content = new StackLayout { Children = { new CoreRootView (), new CorePageView (this, NavigationBehavior.PushModalAsync) } };
+ }
+ }
+
+ internal class CoreMasterDetailPage : MasterDetailPage
+ {
+ public CoreMasterDetailPage ()
+ {
+ AutomationId = "MasterDetailPageRoot";
+
+ var toCrashButton = new Button {Text = "Crash Me"};
+
+ var masterPage = new ContentPage {Title = "Menu", Icon = "bank.png", Content = toCrashButton};
+ var detailPage = new CoreRootPage (this, NavigationBehavior.PushModalAsync) { Title = "DetailPage" };
+
+ bool toggle = false;
+ toCrashButton.Clicked += (sender, args) => {
+ if (toggle)
+ Detail = new ContentPage { BackgroundColor = Color.Green, };
+ else
+ Detail = detailPage;
+
+ toggle = !toggle;
+ };
+
+ Master = masterPage;
+ Detail = detailPage;
+ }
+ }
+
+ internal class CoreNavigationPage : NavigationPage
+ {
+ public CoreNavigationPage ()
+ {
+ AutomationId = "NavigationPageRoot";
+ Navigation.PushAsync (new CoreRootPage (this));
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Github, 2456, "StackOverflow after reordering tabs in a TabbedPageView", PlatformAffected.All)]
+ public class CoreTabbedPage : TestTabbedPage
+ {
+ protected override void Init ()
+ {
+
+ }
+#if APP
+ public CoreTabbedPage ()
+ {
+ AutomationId = "TabbedPageRoot";
+ Children.Add (new CoreRootPage (this, NavigationBehavior.PushModalAsync) { Title = "Tab 1" });
+ Children.Add (new CoreRootPage (this, NavigationBehavior.PushModalAsync) { Title = "Tab 2" });
+ Children.Add(new NavigationPage(new Page())
+ {
+ Title = "Rubriques",
+ });
+
+ Children.Add(new NavigationPage(new Page())
+ {
+ Title = "Le Club",
+ });
+
+ Children.Add(new NavigationPage(new Page{Title = "Bookmarks"})
+ {
+ Title = "Bookmarks",
+ });
+
+ Children.Add(new NavigationPage(new Page() { Title = "Alertes" })
+ {
+ Title = "Notifications",
+ });
+
+ Children.Add(new NavigationPage (new Page(){Title = "My account"})
+ {
+ Title = "My account",
+ });
+
+ Children.Add(new NavigationPage(new Page(){Title = "About"})
+ {
+ Title = "About",
+ });
+ }
+#endif
+
+#if UITest
+ [Test]
+ [Issue (IssueTracker.Github, 2456, "StackOverflow after reordering tabs in a TabbedPageView", PlatformAffected.iOS)]
+ public void TestReorderTabs ()
+ {
+ App.Tap (c => c.Marked("More"));
+ App.Tap (c => c.Marked("Edit"));
+ var bookmarks = App.Query (c => c.Marked ("Bookmarks"))[0];
+ var notifications = App.Query (c => c.Marked ("Notifications"))[0];
+ var tab2 = App.Query (c => c.Marked ("Tab 2"))[2];
+ var rubriques = App.Query (c => c.Marked ("Rubriques"))[2];
+ App.DragCoordinates (bookmarks.Rect.CenterX, bookmarks.Rect.CenterY, rubriques.Rect.CenterX, rubriques.Rect.CenterY);
+ App.DragCoordinates (notifications.Rect.CenterX, notifications.Rect.CenterY, tab2.Rect.CenterX, tab2.Rect.CenterY);
+ App.Tap (c => c.Marked("Done"));
+ App.Tap (c => c.Marked("Tab 1"));
+ App.Tap (c => c.Marked("Le Club"));
+ App.Tap (c => c.Marked("Bookmarks"));
+ App.Tap (c => c.Marked("Notifications"));
+ }
+#endif
+ }
+
+ [Preserve (AllMembers = true)]
+ internal class CoreViewContainer
+ {
+ public string Name { get; private set; }
+ public Type PageType { get; private set; }
+
+ public CoreViewContainer (string name, Type pageType)
+ {
+ Name = name;
+ PageType = pageType;
+ }
+ }
+
+ public class CoreRootView : ListView
+ {
+ public CoreRootView ()
+ {
+ var roots = new [] {
+ new CoreViewContainer ("SwapRoot - CarouselPage", typeof(CoreCarouselPage)),
+ new CoreViewContainer ("SwapRoot - ContentPage", typeof(CoreContentPage)),
+ new CoreViewContainer ("SwapRoot - MasterDetailPage", typeof(CoreMasterDetailPage)),
+ new CoreViewContainer ("SwapRoot - NavigationPage", typeof(CoreNavigationPage)),
+ new CoreViewContainer ("SwapRoot - TabbedPage", typeof(CoreTabbedPage)),
+ };
+
+ var template = new DataTemplate (typeof(TextCell));
+ template.SetBinding (TextCell.TextProperty, "Name");
+
+ ItemTemplate = template;
+ ItemsSource = roots;
+
+#if PRE_APPLICATION_CLASS
+ ItemSelected += (sender, args) => MessagingCenter.Send (this, Messages.ChangeRoot, ((CoreViewContainer)args.SelectedItem).PageType);
+#else
+ ItemSelected += (sender, args) => {
+ var app = Application.Current as App;
+ if (app != null) {
+ var page = (Page)Activator.CreateInstance (((CoreViewContainer)args.SelectedItem).PageType);
+ app.SetMainPage (page);
+ }
+ };
+#endif
+ }
+ }
+
+ internal class CorePageView : ListView
+ {
+ public CorePageView (Page rootPage, NavigationBehavior navigationBehavior = NavigationBehavior.PushAsync)
+ {
+ var pages = new List<Page> {
+ new CarouselViewGallaryPage {Title = "CarouselView Gallery"},
+ new NestedNativeControlGalleryPage {Title = "Nested Native Controls Gallery"},
+ new CellForceUpdateSizeGalleryPage {Title = "Cell Force Update Size Gallery"},
+ new AppearingGalleryPage {Title = "Appearing Gallery"},
+ new EntryCoreGalleryPage { Title = "Entry Gallery" },
+ new NavBarTitleTestPage {Title = "Titles And Navbar Windows"},
+ new PanGestureGalleryPage {Title = "Pan gesture Gallery"},
+ new PinchGestureTestPage {Title = "Pinch gesture Gallery"},
+ new AutomationIdGallery { Title ="AutomationID Gallery" },
+ new LayoutPerformanceGallery {Title = "Layout Perf Gallery"},
+ new ListViewSelectionColor { Title = "ListView SelectionColor Gallery" },
+ new AlertGallery { Title = "DisplayAlert Gallery" },
+ new ToolbarItems { Title = "ToolbarItems Gallery" },
+ new ActionSheetGallery { Title = "ActionSheet Gallery" },
+ new ActivityIndicatorCoreGalleryPage { Title = "ActivityIndicator Gallery" },
+ new BehaviorsAndTriggers { Title = "BehaviorsTriggers Gallery" },
+ new ContextActionsGallery { Title = "ContextActions List Gallery"},
+ new ContextActionsGallery (tableView: true) { Title = "ContextActions Table Gallery"},
+ new CoreBoxViewGalleryPage { Title = "BoxView Gallery" },
+ new ButtonCoreGalleryPage { Title = "Button Gallery" },
+ new DatePickerCoreGalleryPage { Title = "DatePicker Gallery" },
+ new EditorCoreGalleryPage { Title = "Editor Gallery" },
+ new FrameCoreGalleryPage { Title = "Frame Gallery" },
+ new ImageCoreGalleryPage { Title = "Image Gallery" },
+ new KeyboardCoreGallery { Title = "Keyboard Gallery" },
+ new LabelCoreGalleryPage { Title = "Label Gallery" },
+ new ListViewCoreGalleryPage { Title = "ListView Gallery" },
+ new OpenGLViewCoreGalleryPage { Title = "OpenGLView Gallery" },
+ new PickerCoreGalleryPage { Title = "Picker Gallery" },
+ new ProgressBarCoreGalleryPage { Title = "ProgressBar Gallery" },
+ new ScrollGallery { Title = "ScrollView Gallery" },
+ new ScrollGallery(ScrollOrientation.Horizontal) { Title = "ScrollView Gallery Horizontal" },
+ new ScrollGallery(ScrollOrientation.Both) { Title = "ScrollView Gallery 2D" },
+ new SearchBarCoreGalleryPage { Title = "SearchBar Gallery" },
+ new SliderCoreGalleryPage { Title = "Slider Gallery" },
+ new StepperCoreGalleryPage { Title = "Stepper Gallery" },
+ new SwitchCoreGalleryPage { Title = "Switch Gallery" },
+ new TableViewCoreGalleryPage { Title = "TableView Gallery" },
+ new TimePickerCoreGalleryPage { Title = "TimePicker Gallery" },
+ new WebViewCoreGalleryPage { Title = "WebView Gallery" },
+ //pages
+ new RootContentPage ("Content") { Title = "RootPages Gallery" },
+ new MasterDetailPageTabletPage { Title = "MasterDetailPage Tablet Page" },
+ // legacy galleries
+ new AbsoluteLayoutGallery { Title = "AbsoluteLayout Gallery - Legacy" },
+ new BoundContentPage { Title = "BoundPage Gallery - Legacy" },
+ new BackgroundImageGallery { Title = "BackgroundImage gallery" },
+ new ButtonGallery { Title = "Button Gallery - Legacy" },
+ new CarouselPageGallery { Title = "CarouselPage Gallery - Legacy" },
+ new CellTypesListPage { Title = "Cells Gallery - Legacy" },
+ new ClipToBoundsGallery { Title = "ClipToBounds Gallery - Legacy" },
+ new ControlTemplatePage { Title = "ControlTemplated Gallery - Legacy" },
+ new ControlTemplateXamlPage { Title = "ControlTemplated XAML Gallery - Legacy" },
+ new DisposeGallery { Title = "Dispose Gallery - Legacy" },
+ new EditorGallery { Title = "Editor Gallery - Legacy" },
+ new EntryGallery { Title = "Entry Gallery - Legacy" },
+ new FrameGallery { Title = "Frame Gallery - Legacy" },
+ new GridGallery { Title = "Grid Gallery - Legacy" },
+ new GroupedListActionsGallery { Title = "GroupedListActions Gallery - Legacy" },
+ new GroupedListContactsGallery { Title = "GroupedList Gallery - Legacy" },
+ new ImageGallery { Title = "Image Gallery - Legacy" },
+ new ImageLoadingGallery { Title = "ImageLoading Gallery - Legacy" },
+ new InputIntentGallery { Title = "InputIntent Gallery - Legacy" },
+ new LabelGallery { Title = "Label Gallery - Legacy" },
+ new LayoutAddPerformance { Title = "Layout Add Performance - Legacy" },
+ new LayoutOptionsGallery { Title = "LayoutOptions Gallery - Legacy" },
+ new LineBreakModeGallery { Title = "LineBreakMode Gallery - Legacy" },
+ new ListPage { Title = "ListView Gallery - Legacy" },
+ new ListScrollTo { Title = "ListView.ScrollTo" },
+ new ListRefresh { Title = "ListView.PullToRefresh" },
+ new ListViewDemoPage { Title = "ListView Demo Gallery - Legacy" },
+ new MapGallery { Title = "Map Gallery - Legacy" },
+ new MinimumSizeGallery { Title = "MinimumSize Gallery - Legacy" },
+ new MultiGallery { Title = "Multi Gallery - Legacy" },
+ new NavigationMenuGallery { Title = "NavigationMenu Gallery - Legacy" },
+ new NavigationPropertiesGallery { Title = "Navigation Properties" },
+#if HAVE_OPENTK
+ new OpenGLGallery { Title = "OpenGLGallery - Legacy" },
+#endif
+ new PickerGallery {Title = "Picker Gallery - Legacy"},
+ new ProgressBarGallery { Title = "ProgressBar Gallery - Legacy" },
+ new RelativeLayoutGallery { Title = "RelativeLayout Gallery - Legacy" },
+ new ScaleRotate { Title = "Scale Rotate Gallery - Legacy" },
+ new SearchBarGallery { Title = "SearchBar Gallery - Legacy" },
+ new SettingsPage { Title = "Settings Page - Legacy" },
+ new SliderGallery { Title = "Slider Gallery - Legacy" },
+ new StackLayoutGallery { Title = "StackLayout Gallery - Legacy" },
+ new StepperGallery { Title = "Stepper Gallery - Legacy" },
+ new StyleGallery {Title = "Style Gallery"},
+ new StyleXamlGallery {Title = "Style Gallery in Xaml"},
+ new SwitchGallery { Title = "Switch Gallery - Legacy" },
+ new TableViewGallery { Title = "TableView Gallery - Legacy" },
+ new TemplatedCarouselGallery { Title = "TemplatedCarouselPage Gallery - Legacy" },
+ new TemplatedTabbedGallery { Title = "TemplatedTabbedPage Gallery - Legacy" },
+ new ToolbarGallery { Title = "Toolbar Gallery - Legacy" },
+ new UnevenViewCellGallery { Title = "UnevenViewCell Gallery - Legacy" },
+ new UnevenListGallery { Title = "UnevenList Gallery - Legacy" },
+ new ViewCellGallery { Title = "ViewCell Gallery - Legacy" },
+ new WebViewGallery {Title = "WebView Gallery - Legacy"},
+ };
+
+ titleToPage = pages.ToDictionary (o => o.Title);
+
+ // avoid NRE for root pages without NavigationBar
+ if (navigationBehavior == NavigationBehavior.PushAsync && rootPage.GetType () == typeof (CoreNavigationPage)) {
+ pages.Add (new NavigationBarGallery ((NavigationPage)rootPage) { Title = "NavigationBar Gallery - Legacy" });
+ }
+
+ var template = new DataTemplate (typeof(TextCell));
+ template.SetBinding (TextCell.TextProperty, "Title");
+
+ BindingContext = pages;
+ ItemTemplate = template;
+ ItemsSource = pages;
+
+ ItemSelected += async (sender, args) => {
+ if (SelectedItem == null)
+ return;
+
+ var item = args.SelectedItem;
+ var page = item as Page;
+ if (page != null)
+ await PushPage (page);
+
+ SelectedItem = null;
+ };
+ }
+
+ NavigationBehavior navigationBehavior;
+
+ async Task PushPage (Page contentPage)
+ {
+ if (Insights.IsInitialized) {
+ Insights.Track ("Navigation", new Dictionary<string, string> {
+ { "Pushing", contentPage.GetType().Name }
+ });
+ }
+
+ if (navigationBehavior == NavigationBehavior.PushModalAsync) {
+ await Navigation.PushModalAsync (contentPage);
+ } else {
+ await Navigation.PushAsync (contentPage);
+ }
+ }
+
+ Dictionary<string, Page> titleToPage = new Dictionary<string, Page>();
+ public async Task PushPage (string pageTitle)
+ {
+
+ Page page = null;
+ if (!titleToPage.TryGetValue (pageTitle, out page))
+ return;
+
+ if (Insights.IsInitialized) {
+ Insights.Track ("Navigation", new Dictionary<string, string> {
+ { "Pushing", page.GetType().Name }
+ });
+ }
+
+ await PushPage (page);
+ }
+ }
+
+ internal class CoreRootPage : ContentPage
+ {
+ public CoreRootPage (Page rootPage, NavigationBehavior navigationBehavior = NavigationBehavior.PushAsync)
+ {
+ IStringProvider stringProvider = DependencyService.Get<IStringProvider> ();
+
+ Title = stringProvider.CoreGalleryTitle;
+
+ var corePageView = new CorePageView (rootPage, navigationBehavior);
+
+ var searchBar = new SearchBar () {
+ AutomationId = "SearchBar"
+ };
+
+ var testCasesButton = new Button {
+ Text = "Go to Test Cases",
+ AutomationId = "GoToTestButton",
+ Command = new Command (async () => {
+ if (!string.IsNullOrEmpty (searchBar.Text))
+ await corePageView.PushPage (searchBar.Text);
+ else
+ await Navigation.PushModalAsync (TestCases.GetTestCases ());
+ })
+ };
+
+ var stackLayout = new StackLayout () {
+ Children = {
+ testCasesButton,
+ searchBar,
+ new Button {
+ Text = "Click to Force GC",
+ Command = new Command(() => {
+ GC.Collect ();
+ GC.WaitForPendingFinalizers ();
+ GC.Collect ();
+ })
+ }
+
+ }
+ };
+
+ Content = new AbsoluteLayout {
+ Children = {
+ { new CoreRootView (), new Rectangle(0, 0.0, 1, 0.35), AbsoluteLayoutFlags.All },
+ { stackLayout, new Rectangle(0, 0.5, 1, 0.30), AbsoluteLayoutFlags.All },
+ { corePageView, new Rectangle(0, 1.0, 1.0, 0.35), AbsoluteLayoutFlags.All },
+ }
+ };
+ }
+ }
+
+ public interface IStringProvider
+ {
+ string CoreGalleryTitle { get; }
+ }
+
+ public static class CoreGallery
+ {
+ public static Page GetMainPage ()
+ {
+ return new CoreNavigationPage ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/ActivityIndicatorCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/ActivityIndicatorCoreGalleryPage.cs
new file mode 100644
index 00000000..8265cf74
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/ActivityIndicatorCoreGalleryPage.cs
@@ -0,0 +1,39 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class ActivityIndicatorCoreGalleryPage : CoreGalleryPage<ActivityIndicator>
+ {
+ protected override bool SupportsTapGestureRecognizer
+ {
+ get { return true; }
+ }
+
+ protected override void InitializeElement (ActivityIndicator element)
+ {
+ element.IsRunning = true;
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+
+ var colorContainer = new ViewContainer<ActivityIndicator> (Test.ActivityIndicator.Color, new ActivityIndicator {
+ Color = Color.Lime,
+ IsRunning = true
+
+ });
+
+ var isRunningContainer = new StateViewContainer<ActivityIndicator> (Test.ActivityIndicator.IsRunning, new ActivityIndicator {
+ IsRunning = true
+ });
+
+ isRunningContainer.StateChangeButton.Clicked += (sender, args) => {
+ isRunningContainer.View.IsRunning = !isRunningContainer.View.IsRunning;
+ };
+
+ Add (colorContainer);
+ Add (isRunningContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/ButtonCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/ButtonCoreGalleryPage.cs
new file mode 100644
index 00000000..65aa6fa3
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/ButtonCoreGalleryPage.cs
@@ -0,0 +1,106 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class ButtonCoreGalleryPage : CoreGalleryPage<Button>
+ {
+ protected override bool SupportsTapGestureRecognizer {
+ get { return false; }
+ }
+
+ protected override bool SupportsFocus {
+ get { return false; }
+ }
+
+ protected override void InitializeElement (Button element)
+ {
+ element.Text = "Button";
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+
+ IsEnabledStateViewContainer.View.Clicked += (sender, args) => IsEnabledStateViewContainer.TitleLabel.Text += " (Tapped)";
+
+ var borderButtonContainer = new ViewContainer<Button> (Test.Button.BorderColor,
+ new Button {
+ Text = "BorderColor",
+ BackgroundColor = Color.Transparent,
+ BorderColor = Color.Red,
+ BorderWidth = 1,
+ }
+ );
+
+ var borderRadiusContainer = new ViewContainer<Button> (Test.Button.BorderRadius,
+ new Button {
+ Text = "BorderRadius",
+ BackgroundColor = Color.Transparent,
+ BorderColor = Color.Red,
+ BorderRadius = 20,
+ BorderWidth = 1,
+ }
+ );
+
+ var borderWidthContainer = new ViewContainer<Button> (Test.Button.BorderWidth,
+ new Button {
+ Text = "BorderWidth",
+ BackgroundColor = Color.Transparent,
+ BorderColor = Color.Red,
+ BorderWidth = 15,
+ }
+ );
+
+ var clickedContainer = new EventViewContainer<Button> (Test.Button.Clicked,
+ new Button {
+ Text = "Clicked"
+ }
+ );
+ clickedContainer.View.Clicked += (sender, args) => clickedContainer.EventFired ();
+
+ var commandContainer = new ViewContainer<Button> (Test.Button.Command,
+ new Button {
+ Text = "Command",
+ Command = new Command (() => DisplayActionSheet ("Hello Command", "Cancel", "Destroy"))
+ }
+ );
+
+ var fontContainer = new ViewContainer<Button> (Test.Button.Font,
+ new Button {
+ Text = "Font",
+ Font = Font.SystemFontOfSize (NamedSize.Large, FontAttributes.Bold)
+ }
+ );
+
+ var imageContainer = new ViewContainer<Button> (Test.Button.Image,
+ new Button {
+ Text = "Image",
+ Image = new FileImageSource { File = "bank.png" }
+ }
+ )
+ ;
+ var textContainer = new ViewContainer<Button> (Test.Button.Text,
+ new Button {
+ Text = "Text"
+ }
+ );
+
+ var textColorContainer = new ViewContainer<Button> (Test.Button.TextColor,
+ new Button {
+ Text = "TextColor", TextColor = Color.Pink
+ }
+ );
+
+ Add (borderButtonContainer);
+ Add (borderRadiusContainer);
+ Add (borderWidthContainer);
+ Add (clickedContainer);
+ Add (commandContainer);
+ Add (fontContainer);
+ Add (imageContainer);
+ Add (textContainer);
+ Add (textColorContainer);
+ //stackLayout.Children.Add (textColorContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/CoreBoxViewGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/CoreBoxViewGalleryPage.cs
new file mode 100644
index 00000000..57ceaf44
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/CoreBoxViewGalleryPage.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Threading;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class CoreBoxViewGalleryPage : CoreGalleryPage<BoxView>
+ {
+ static readonly object SyncLock = new object ();
+ static readonly Random Rand = new Random ();
+
+ protected override bool SupportsFocus
+ {
+ get { return false; }
+ }
+
+ protected override void InitializeElement (BoxView element)
+ {
+ lock (SyncLock) {
+ var red = Rand.NextDouble ();
+ var green = Rand.NextDouble ();
+ var blue = Rand.NextDouble ();
+ element.Color = new Color (red, green, blue);
+ }
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+
+ var colorContainer = new ViewContainer<BoxView> (Test.BoxView.Color, new BoxView { Color = Color.Pink });
+
+ Add (colorContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/CoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/CoreGalleryPage.cs
new file mode 100644
index 00000000..41b3a796
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/CoreGalleryPage.cs
@@ -0,0 +1,185 @@
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Threading;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class CoreGalleryPage<T> : ContentPage
+ where T : View, new ()
+ {
+ List<View> _views;
+ int _currentIndex;
+ Picker _picker;
+ StackLayout _moveNextStack;
+
+ ViewContainer<T> _backgroundColorViewContainer;
+ ViewContainer<T> _opacityViewContainer;
+ ViewContainer<T> _rotationViewContainer;
+ ViewContainer<T> _rotationXViewContainer;
+ ViewContainer<T> _rotationYViewContainer;
+ ViewContainer<T> _scaleViewContainer;
+ ViewContainer<T> _translationXViewContainer;
+ ViewContainer<T> _translationYViewContainer;
+
+ StateViewContainer<T> _focusStateViewContainer;
+ StateViewContainer<T> _isFocusedStateViewContainer;
+ StateViewContainer<T> _isVisibleStateViewContainer;
+
+ EventViewContainer<T> _gestureRecognizerEventViewContainer;
+ EventViewContainer<T> _focusedEventViewContainer;
+ EventViewContainer<T> _unfocusedEventViewContainer;
+
+ LayeredViewContainer<T> _inputTransparentViewContainer;
+
+ protected StateViewContainer<T> IsEnabledStateViewContainer { get; private set; }
+
+ protected StackLayout Layout { get; private set; }
+
+ internal CoreGalleryPage ()
+ {
+ Layout = new StackLayout {
+ Padding = new Thickness (20)
+ };
+
+ var modalDismissButton = new Button () {
+ Text = "Dismiss Page",
+ Command = new Command (async () => await Navigation.PopModalAsync ())
+ };
+ Layout.Children.Add (modalDismissButton);
+
+ Build (Layout);
+
+ Content = new ScrollView { AutomationId = "GalleryScrollView", Content = Layout };
+
+ }
+
+ protected virtual void InitializeElement (T element) {}
+
+ protected virtual void Build (StackLayout stackLayout)
+ {
+ var isFocusedView = new T ();
+ isFocusedView.SetValueCore (IsFocusedPropertyKey, true);
+
+ var viewContainers = new[] {
+ _isFocusedStateViewContainer = new StateViewContainer<T> (Test.VisualElement.IsFocused, isFocusedView),
+ _backgroundColorViewContainer = new ViewContainer<T> (Test.VisualElement.BackgroundColor, new T { BackgroundColor = Color.Blue }),
+ _focusStateViewContainer = new StateViewContainer<T> (Test.VisualElement.Focus, new T ()),
+ _gestureRecognizerEventViewContainer = new EventViewContainer<T> (Test.View.GestureRecognizers, new T ()),
+ _inputTransparentViewContainer = new LayeredViewContainer<T> (Test.VisualElement.InputTransparent, new T { InputTransparent = true }),
+ IsEnabledStateViewContainer = new StateViewContainer<T> (Test.VisualElement.IsEnabled, new T { IsEnabled = true }),
+ _focusedEventViewContainer = new EventViewContainer<T> (Test.VisualElement.Focused, new T ()),
+ _unfocusedEventViewContainer = new EventViewContainer<T> (Test.VisualElement.Unfocused, new T ()),
+ _isVisibleStateViewContainer = new StateViewContainer<T> (Test.VisualElement.IsVisible, new T { IsVisible = true }),
+ _opacityViewContainer = new ViewContainer<T> (Test.VisualElement.Opacity, new T { Opacity = 0.5 }),
+ _rotationViewContainer = new ViewContainer<T> (Test.VisualElement.Rotation, new T { Rotation = 10 }),
+ _rotationXViewContainer = new ViewContainer<T> (Test.VisualElement.RotationX, new T { RotationX = 33 }),
+ _rotationYViewContainer = new ViewContainer<T> (Test.VisualElement.RotationY, new T { RotationY = 10 }),
+ _scaleViewContainer = new ViewContainer<T> (Test.VisualElement.Scale, new T { Scale = 0.5 }),
+ _translationXViewContainer = new ViewContainer<T> (Test.VisualElement.TranslationX, new T { TranslationX = 30 }),
+ _translationYViewContainer = new ViewContainer<T> (Test.VisualElement.TranslationY, new T { TranslationY = 30 }),
+ };
+
+ // Set state
+ IsEnabledStateViewContainer.StateChangeButton.Command = new Command (() => {
+ IsEnabledStateViewContainer.View.IsEnabled = !IsEnabledStateViewContainer.View.IsEnabled;
+ });
+ _isVisibleStateViewContainer.StateChangeButton.Command = new Command (() => {
+ _isVisibleStateViewContainer.View.IsVisible = !_isVisibleStateViewContainer.View.IsVisible;
+ });
+
+ _focusStateViewContainer.StateChangeButton.Command = new Command (() => {
+ if (_focusStateViewContainer.View.IsFocused) {
+ _focusStateViewContainer.View.Unfocus ();
+ } else {
+ _focusStateViewContainer.View.Focus ();
+ }
+ });
+
+ _focusedEventViewContainer.View.Focused += (sender, args) => _focusedEventViewContainer.EventFired ();
+ _unfocusedEventViewContainer.View.Unfocused += (sender, args) => _unfocusedEventViewContainer.EventFired ();
+
+ _gestureRecognizerEventViewContainer.View.GestureRecognizers.Add (
+ new TapGestureRecognizer {
+ Command = new Command (() => _gestureRecognizerEventViewContainer.EventFired ())
+ }
+ );
+
+ _views = new List<View> (viewContainers.Select (o => o.ContainerLayout));
+
+ _moveNextStack = new StackLayout ();
+ var moveNextButton = new Button ();
+ moveNextButton.Text = "Move Next";
+ moveNextButton.AutomationId = "MoveNextButton";
+ moveNextButton.Clicked += delegate (object sender, EventArgs e) {
+ if (!_views.Any ())
+ return;
+
+ if (_currentIndex + 1 >= _views.Count) {
+ return;
+ }
+
+ _currentIndex += 1;
+
+ _moveNextStack.Children.RemoveAt (2);
+ _moveNextStack.Children.Add (_views[_currentIndex]);
+ _picker.SelectedIndexChanged -= PickerSelectedIndexChanged;
+ _picker.SelectedIndex = _currentIndex;
+ _picker.SelectedIndexChanged += PickerSelectedIndexChanged;
+ };
+
+ _picker = new Picker();
+ foreach (var container in viewContainers) {
+ _picker.Items.Add(container.TitleLabel.Text);
+ }
+
+ _picker.SelectedIndex = _currentIndex;
+
+ _picker.SelectedIndexChanged += PickerSelectedIndexChanged;
+
+ _moveNextStack.Children.Add (_picker);
+ _moveNextStack.Children.Add (moveNextButton);
+ _moveNextStack.Children.Add (_views[_currentIndex]);
+
+ stackLayout.Children.Add (_moveNextStack);
+
+ if (!SupportsFocus) {
+ stackLayout.Children.Remove (_focusStateViewContainer.ContainerLayout);
+ stackLayout.Children.Remove (_isFocusedStateViewContainer.ContainerLayout);
+ }
+
+ if (!SupportsTapGestureRecognizer)
+ stackLayout.Children.Remove (_gestureRecognizerEventViewContainer.ContainerLayout);
+
+ foreach (var element in viewContainers)
+ InitializeElement (element.View);
+ }
+
+ void PickerSelectedIndexChanged (object sender, EventArgs eventArgs)
+ {
+ _currentIndex = _picker.SelectedIndex;
+ _moveNextStack.Children.RemoveAt (2);
+ _moveNextStack.Children.Add (_views[_currentIndex]);
+ }
+
+
+ protected virtual bool SupportsTapGestureRecognizer
+ {
+ get { return true; }
+ }
+
+ protected virtual bool SupportsFocus
+ {
+ get { return true; }
+ }
+
+ protected void Add (ViewContainer<T> view) {
+ _views.Add (view.ContainerLayout);
+ _picker.Items.Add(view.TitleLabel.Text);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/DatePickerCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/DatePickerCoreGalleryPage.cs
new file mode 100644
index 00000000..1dbb9bb2
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/DatePickerCoreGalleryPage.cs
@@ -0,0 +1,34 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class DatePickerCoreGalleryPage : CoreGalleryPage<DatePicker>
+ {
+ protected override bool SupportsTapGestureRecognizer
+ {
+ get { return false; }
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+
+ var dateContainer = new ViewContainer<DatePicker> (Test.DatePicker.Date, new DatePicker { Date = new DateTime (1987, 9, 13) });
+
+ var dateSelectedContainer = new EventViewContainer<DatePicker> (Test.DatePicker.DateSelected, new DatePicker ());
+ dateSelectedContainer.View.DateSelected += (sender, args) => dateSelectedContainer.EventFired ();
+
+ var formatDateContainer = new ViewContainer<DatePicker> (Test.DatePicker.Format, new DatePicker { Format = "ddd" });
+ var minimumDateContainer = new ViewContainer<DatePicker> (Test.DatePicker.MinimumDate, new DatePicker { MinimumDate = new DateTime (1987, 9, 13) });
+ var maximumDateContainer = new ViewContainer<DatePicker> (Test.DatePicker.MaximumDate, new DatePicker { MaximumDate = new DateTime (2087, 9, 13) });
+
+ Add (dateContainer);
+ Add (dateSelectedContainer);
+ Add (formatDateContainer);
+ Add (minimumDateContainer);
+ Add (maximumDateContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/EditorCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/EditorCoreGalleryPage.cs
new file mode 100644
index 00000000..d7c749be
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/EditorCoreGalleryPage.cs
@@ -0,0 +1,51 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class EditorCoreGalleryPage : CoreGalleryPage<Editor>
+ {
+ protected override bool SupportsTapGestureRecognizer
+ {
+ get { return false; }
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+
+ var completedContainer = new EventViewContainer<Editor> (Test.Editor.Completed, new Editor ());
+ completedContainer.View.Completed += (sender, args) => completedContainer.EventFired ();
+
+ var textContainer = new ViewContainer<Editor> (Test.Editor.Text, new Editor { Text = "I have text" });
+
+ var textChangedContainer = new EventViewContainer<Editor> (Test.Editor.TextChanged, new Editor ());
+ textChangedContainer.View.TextChanged += (sender, args) => textChangedContainer.EventFired ();
+
+ var textFontAttributesContainer = new ViewContainer<Editor> (Test.Editor.FontAttributes, new Editor { Text = "I have italic text", FontAttributes = FontAttributes.Italic });
+ var textFamilyContainer1 = new ViewContainer<Editor> (Test.Editor.FontFamily, new Editor { Text = "I have Comic Sans text in Win & Android", FontFamily = "Comic Sans MS" });
+ var textFamilyContainer2 = new ViewContainer<Editor> (Test.Editor.FontFamily, new Editor { Text = "I have bold Chalkboard text in iOS", FontFamily = "ChalkboardSE-Regular", FontAttributes = FontAttributes.Bold });
+ var textFontSizeContainer = new ViewContainer<Editor> (Test.Editor.FontSize, new Editor { Text = "I have default size text" });
+ var textFontSizeDefaultContainer = new ViewContainer<Editor> (Test.Editor.FontSize, new Editor { Text = "I also have default size text" });
+ textFontSizeDefaultContainer.View.FontSize = Device.GetNamedSize (NamedSize.Default, textFontSizeDefaultContainer.View);
+ var textFontSizeLargeContainer = new ViewContainer<Editor> (Test.Editor.FontSize, new Editor { Text = "I have size 48 (huge) text", FontSize = 48 });
+
+ var textColorContainer = new ViewContainer<Editor> (Test.Editor.TextColor,
+ new Editor { Text = "I should have red text", TextColor = Color.Red });
+
+ var textColorDisabledContainer = new ViewContainer<Editor> (Test.Editor.TextColor,
+ new Editor { Text = "I should have the default disabled text color", TextColor = Color.Red, IsEnabled = false });
+
+ Add (completedContainer);
+ Add (textContainer);
+ Add (textChangedContainer);
+ Add (textFontAttributesContainer);
+ Add (textFamilyContainer1);
+ Add (textFamilyContainer2);
+ Add (textFontSizeContainer);
+ Add (textFontSizeDefaultContainer);
+ Add (textFontSizeLargeContainer);
+ Add (textColorContainer);
+ Add (textColorDisabledContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/EntryCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/EntryCoreGalleryPage.cs
new file mode 100644
index 00000000..2180f1f1
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/EntryCoreGalleryPage.cs
@@ -0,0 +1,92 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class EntryCoreGalleryPage : CoreGalleryPage<Entry>
+ {
+ protected override bool SupportsTapGestureRecognizer
+ {
+ get { return false; }
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+
+ var completedContainer = new EventViewContainer<Entry> (Test.Entry.Completed, new Entry { Placeholder = "Completed" });
+ completedContainer.View.Completed += (sender, args) => completedContainer.EventFired ();
+
+ var placeholderContainer = new ViewContainer<Entry> (Test.Entry.Placeholder, new Entry { Placeholder = "Placeholder" });
+ var keyboardContainer = new ViewContainer<Entry> (Test.InputView.Keyboard, new Entry { Keyboard = Keyboard.Numeric });
+ var isPasswordContainer = new ViewContainer<Entry> (Test.Entry.IsPassword, new Entry { IsPassword = true });
+ var textContainer = new ViewContainer<Entry> (Test.Entry.Text, new Entry { Text = "Hi, I am Text" });
+
+ var textChangedContainer = new EventViewContainer<Entry> (Test.Entry.TextChanged, new Entry ());
+ textChangedContainer.View.TextChanged += (sender, args) => textChangedContainer.EventFired ();
+
+ var textFontAttributesContainer = new ViewContainer<Entry> (Test.Entry.FontAttributes, new Entry { Text = "I have italic text", FontAttributes = FontAttributes.Italic });
+ var textFamilyContainer1 = new ViewContainer<Entry> (Test.Entry.FontFamily, new Entry { Text = "I have Comic Sans text in Win & Android", FontFamily = "Comic Sans MS" });
+ var textFamilyContainer2 = new ViewContainer<Entry> (Test.Entry.FontFamily, new Entry { Text = "I have bold Chalkboard text in iOS", FontFamily = "ChalkboardSE-Regular", FontAttributes = FontAttributes.Bold });
+ var textFontSizeContainer = new ViewContainer<Entry> (Test.Entry.FontSize, new Entry { Text = "I have default size text" });
+ var textFontSizeDefaultContainer = new ViewContainer<Entry> (Test.Entry.FontSize, new Entry { Text = "I also have default size text" });
+ textFontSizeDefaultContainer.View.FontSize = Device.GetNamedSize (NamedSize.Default, textFontSizeDefaultContainer.View);
+ var textFontSizeLargeContainer = new ViewContainer<Entry> (Test.Entry.FontSize, new Entry { Text = "I have size 48 (huge) text", FontSize = 48 });
+
+ var textColorContainer = new ViewContainer<Entry> (Test.Entry.TextColor, new Entry { Text = "Hi, I should be red", TextColor = Color.Red });
+
+ var xAlignCenterContainer = new ViewContainer<Entry> (Test.Entry.HorizontalTextAlignmentCenter,
+ new Entry { Text = "Should be centered", HorizontalTextAlignment = TextAlignment.Center });
+ var xAlignEndContainer = new ViewContainer<Entry> (Test.Entry.HorizontalTextAlignmentEnd,
+ new Entry { Text = "Should be aligned end", HorizontalTextAlignment = TextAlignment.End });
+ var xAlignStartContainer = new ViewContainer<Entry> (Test.Entry.HorizontalTextAlignmentStart,
+ new Entry { Text = "Should be aligned start", HorizontalTextAlignment = TextAlignment.Start });
+
+ var xAlignPlaceholderCenter = new ViewContainer<Entry> (Test.Entry.HorizontalTextAlignmentPlaceholderCenter,
+ new Entry { Placeholder = "Should be centered", HorizontalTextAlignment = TextAlignment.Center });
+ var xAlignPlaceholderEnd = new ViewContainer<Entry> (Test.Entry.HorizontalTextAlignmentPlaceholderEnd,
+ new Entry { Placeholder = "Should be aligned end", HorizontalTextAlignment = TextAlignment.End });
+ var xAlignPlaceholderStart = new ViewContainer<Entry> (Test.Entry.HorizontalTextAlignmentPlaceholderStart,
+ new Entry { Placeholder = "Should be aligned start", HorizontalTextAlignment = TextAlignment.Start });
+
+ var placeholderColorContainer = new ViewContainer<Entry> (Test.Entry.PlaceholderColor,
+ new Entry { Placeholder = "Hi, I should be red", PlaceholderColor = Color.Red });
+
+ var textColorDisabledContainer = new ViewContainer<Entry> (Test.Entry.TextDisabledColor,
+ new Entry { IsEnabled = false, Text = "I should be the default disabled color", TextColor = Color.Red });
+
+ var placeholderColorDisabledContainer = new ViewContainer<Entry> (Test.Entry.PlaceholderDisabledColor,
+ new Entry {
+ IsEnabled = false,
+ Placeholder = "I should be the default placeholder disabled color",
+ PlaceholderColor = Color.Red
+ });
+
+ var passwordColorContainer = new ViewContainer<Entry> (Test.Entry.PasswordColor,
+ new Entry { IsPassword = true, Text = "12345", TextColor = Color.Red });
+
+ Add (isPasswordContainer);
+ Add (completedContainer);
+ Add (placeholderContainer);
+ Add (keyboardContainer);
+ Add (textContainer);
+ Add (textChangedContainer);
+ Add (textColorContainer);
+ Add (xAlignPlaceholderCenter);
+ Add (xAlignCenterContainer);
+ Add (xAlignPlaceholderEnd);
+ Add (xAlignEndContainer);
+ Add (xAlignPlaceholderStart);
+ Add (xAlignStartContainer);
+ Add (textFontAttributesContainer);
+ Add (textFamilyContainer1);
+ Add (textFamilyContainer2);
+ Add (textFontSizeContainer);
+ Add (textFontSizeDefaultContainer);
+ Add (textFontSizeLargeContainer);
+ Add (placeholderColorContainer);
+ Add (textColorDisabledContainer);
+ Add (placeholderColorDisabledContainer);
+ Add (passwordColorContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/FrameCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/FrameCoreGalleryPage.cs
new file mode 100644
index 00000000..aa24172f
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/FrameCoreGalleryPage.cs
@@ -0,0 +1,36 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class FrameCoreGalleryPage : CoreGalleryPage<Frame>
+ {
+ // TODO
+ protected override bool SupportsFocus
+ {
+ get { return false; }
+ }
+
+ protected override void InitializeElement (Frame element)
+ {
+ element.HeightRequest = 50;
+ element.WidthRequest = 100;
+ element.OutlineColor = Color.Olive;
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+
+ var hasShadowContainer = new StateViewContainer<Frame> (Test.Frame.HasShadow, new Frame { HasShadow = true });
+ var outlineColorContainer = new StateViewContainer<Frame> (Test.Frame.OutlineColor, new Frame { OutlineColor = Color.Teal, });
+ var viewContainer = new StateViewContainer<Frame> (Test.Frame.OutlineColor, new Frame {
+ OutlineColor = Color.Teal,
+ Content = new Label { Text = "I am a frame" }
+ });
+
+ Add (hasShadowContainer);
+ Add (outlineColorContainer);
+ Add (viewContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/ImageCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/ImageCoreGalleryPage.cs
new file mode 100644
index 00000000..8657e3c0
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/ImageCoreGalleryPage.cs
@@ -0,0 +1,56 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class ImageCoreGalleryPage : CoreGalleryPage<Image>
+ {
+ static readonly Random Rand = new Random ();
+
+ protected override bool SupportsFocus
+ {
+ get { return false; }
+ }
+
+ protected override void InitializeElement (Image element)
+ {
+// var sourceIndex = rand.Next (0, 3);
+//
+// var sources = new [] {
+// ImageSource.FromFile ("oasis.jpg"),
+// //ImageSource.FromUri (new Uri("http://www.nasa.gov/sites/default/files/styles/1600x1200_autoletterbox/public/images/298773main_EC02-0282-3_full.jpg")),
+// //ImageSource.FromResource ("Xamarin.Forms.Controls.ControlGalleryPages.crimson.jpg")
+// };
+
+ //element.Source = sources[sourceIndex];
+ element.Source = "oasissmall.jpg";
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+
+ var aspectFillContainer = new ViewContainer<Image> (Test.Image.AspectFill, new Image { Aspect = Aspect.AspectFill });
+ var aspectFitContainer = new ViewContainer<Image> (Test.Image.AspectFit, new Image { Aspect = Aspect.AspectFit });
+ var fillContainer = new ViewContainer<Image> (Test.Image.Fill, new Image { Aspect = Aspect.Fill });
+ var isLoadingContainer = new StateViewContainer<Image> (Test.Image.IsLoading, new Image ());
+ var isOpaqueContainer = new StateViewContainer<Image> (Test.Image.IsOpaque, new Image ());
+
+ InitializeElement (aspectFillContainer.View);
+ InitializeElement (aspectFitContainer.View);
+ InitializeElement (fillContainer.View);
+ InitializeElement (isLoadingContainer.View);
+ InitializeElement (isOpaqueContainer.View);
+
+ var sourceContainer = new ViewContainer<Image> (Test.Image.Source, new Image { Source = "http://sethrosetter.com/images/projects/bezierdraw/bezierdraw_5.jpg" });
+
+ Add (aspectFillContainer);
+ Add (aspectFitContainer);
+ Add (fillContainer);
+ Add (isLoadingContainer);
+ Add (isOpaqueContainer);
+ Add (sourceContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/KeyboardCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/KeyboardCoreGalleryPage.cs
new file mode 100644
index 00000000..cf5f2139
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/KeyboardCoreGalleryPage.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class KeyboardCoreGallery : ContentPage
+ {
+ public KeyboardCoreGallery ()
+ {
+ var keyboardTypes = new[] {
+ Keyboard.Chat,
+ Keyboard.Default,
+ Keyboard.Email,
+ Keyboard.Numeric,
+ Keyboard.Telephone,
+ Keyboard.Text,
+ Keyboard.Url
+ };
+
+ var layout = new StackLayout ();
+
+ foreach (var keyboardType in keyboardTypes) {
+ var viewContainer = new ViewContainer<Entry> (Test.Entry.Keyboard, new Entry { Placeholder = keyboardType.ToString (), Keyboard = keyboardType } );
+ layout.Children.Add (viewContainer.ContainerLayout);
+ }
+
+ var customKeyboards = new [] {
+ Tuple.Create ("Suggestions", Keyboard.Create (KeyboardFlags.Suggestions)),
+ Tuple.Create ("Spellcheck", Keyboard.Create (KeyboardFlags.Spellcheck)),
+ Tuple.Create ("SpellcheckSuggestions", Keyboard.Create (KeyboardFlags.Spellcheck | KeyboardFlags.Suggestions)),
+ Tuple.Create ("Capitalize", Keyboard.Create (KeyboardFlags.CapitalizeSentence)),
+ Tuple.Create ("CapitalizeSuggestions", Keyboard.Create (KeyboardFlags.CapitalizeSentence | KeyboardFlags.Suggestions)),
+ Tuple.Create ("CapitalizeSpellcheck", Keyboard.Create (KeyboardFlags.CapitalizeSentence | KeyboardFlags.Spellcheck)),
+ Tuple.Create ("CapitalizeSpellcheckSuggestions", Keyboard.Create (KeyboardFlags.CapitalizeSentence | KeyboardFlags.Spellcheck | KeyboardFlags.Suggestions)),
+ Tuple.Create ("All", Keyboard.Create (KeyboardFlags.All)),
+ };
+
+ foreach (var customKeyboard in customKeyboards) {
+ var viewContainer = new ViewContainer<Entry> (Test.Entry.Keyboard, new Entry { Placeholder = customKeyboard.Item1, Keyboard = customKeyboard.Item2 } );
+ layout.Children.Add (viewContainer.ContainerLayout);
+ }
+
+ Content = new ScrollView { Content = layout };
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/LabelCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/LabelCoreGalleryPage.cs
new file mode 100644
index 00000000..9043c701
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/LabelCoreGalleryPage.cs
@@ -0,0 +1,158 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class LabelCoreGalleryPage : CoreGalleryPage<Label>
+ {
+ protected override bool SupportsFocus
+ {
+ get { return false; }
+ }
+
+ protected override void InitializeElement (Label element)
+ {
+ element.Text = "I am a label's text.";
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+
+ var namedSizeMediumBoldContainer = new ViewContainer<Label> (Test.Label.FontAttibutesBold, new Label { Text = "Medium Bold Font", Font = Font.SystemFontOfSize (NamedSize.Medium, FontAttributes.Bold) });
+ var namedSizeMediumItalicContainer = new ViewContainer<Label> (Test.Label.FontAttributesItalic, new Label { Text = "Medium Italic Font", Font = Font.SystemFontOfSize (NamedSize.Medium, FontAttributes.Italic) });
+ var namedSizeLargeContainer = new ViewContainer<Label> (Test.Label.FontNamedSizeLarge, new Label { Text = "Large Font", Font = Font.SystemFontOfSize (NamedSize.Large) });
+ var namedSizeMediumContainer = new ViewContainer<Label> (Test.Label.FontNamedSizeMedium, new Label { Text = "Medium Font", Font = Font.SystemFontOfSize (NamedSize.Medium) });
+ var namedSizeMicroContainer = new ViewContainer<Label> (Test.Label.FontNamedSizeMicro, new Label { Text = "Micro Font", Font = Font.SystemFontOfSize (NamedSize.Micro) });
+ var namedSizeSmallContainer = new ViewContainer<Label> (Test.Label.FontNamedSizeSmall, new Label { Text = "Small Font", Font = Font.SystemFontOfSize (NamedSize.Small) });
+
+ var formattedString = new FormattedString ();
+ formattedString.Spans.Add (new Span { BackgroundColor = Color.Red, ForegroundColor = Color.Olive, Text = "Span 1 " });
+ formattedString.Spans.Add (new Span { BackgroundColor = Color.Black, ForegroundColor = Color.White, Text = "Span 2 " });
+ formattedString.Spans.Add (new Span { BackgroundColor = Color.Pink, ForegroundColor = Color.Purple, Text = "Span 3" });
+
+ var formattedTextContainer = new ViewContainer<Label> (Test.Label.FormattedText, new Label { FormattedText = formattedString });
+
+ const string longText = "Lorem ipsum dolor sit amet, cu mei malis petentium, dolor tempor delicata no qui, eos ex vitae utinam vituperata. Utroque habemus philosophia ut mei, doctus placerat eam cu. An inermis scaevola pro, quo legimus deleniti ei, equidem docendi urbanitas ea eum. Saepe doctus ut pri. Nec ex wisi dolorem. Duo dolor vituperatoribus ea. Id purto instructior per. Nec partem accusamus ne. Qui ad saepe accumsan appellantur, duis omnesque has et, vim nihil nemore scaevola ne. Ei populo appetere recteque cum, meliore splendide appellantur vix id.";
+ var lineBreakModeCharacterWrapContainer = new ViewContainer<Label> (Test.Label.LineBreakModeCharacterWrap, new Label { Text = longText, LineBreakMode = LineBreakMode.CharacterWrap });
+ var lineBreakModeHeadTruncationContainer = new ViewContainer<Label> (Test.Label.LineBreakModeHeadTruncation, new Label { Text = longText, LineBreakMode = LineBreakMode.HeadTruncation });
+ var lineBreakModeMiddleTruncationContainer = new ViewContainer<Label> (Test.Label.LineBreakModeMiddleTruncation, new Label { Text = longText, LineBreakMode = LineBreakMode.MiddleTruncation });
+ var lineBreakModeNoWrapContainer = new ViewContainer<Label> (Test.Label.LineBreakModeNoWrap, new Label { Text = longText, LineBreakMode = LineBreakMode.NoWrap });
+ var lineBreakModeTailTruncationContainer = new ViewContainer<Label> (Test.Label.LineBreakModeTailTruncation, new Label { Text = longText, LineBreakMode = LineBreakMode.TailTruncation });
+ var lineBreakModeWordWrapContainer = new ViewContainer<Label> (Test.Label.LineBreakModeWordWrap, new Label { Text = longText, LineBreakMode = LineBreakMode.WordWrap });
+
+ var textContainer = new ViewContainer<Label> (Test.Label.Text, new Label { Text = "I should have text" });
+ var textColorContainer = new ViewContainer<Label> (Test.Label.TextColor, new Label { Text = "I should have lime text", TextColor = Color.Lime });
+
+ const int alignmentTestsHeightRequest = 100;
+ const int alignmentTestsWidthRequest = 100;
+
+ var xAlignCenterContainer = new ViewContainer<Label> (Test.Label.HorizontalTextAlignmentCenter,
+ new Label {
+ Text = "HorizontalTextAlignment Center",
+ HorizontalTextAlignment = TextAlignment.Center,
+ HeightRequest = alignmentTestsHeightRequest,
+ WidthRequest = alignmentTestsWidthRequest
+ }
+ );
+
+ var xAlignEndContainer = new ViewContainer<Label> (Test.Label.HorizontalTextAlignmentEnd,
+ new Label {
+ Text = "HorizontalTextAlignment End",
+ HorizontalTextAlignment = TextAlignment.End,
+ HeightRequest = alignmentTestsHeightRequest,
+ WidthRequest = alignmentTestsWidthRequest
+ }
+ );
+
+ var xAlignStartContainer = new ViewContainer<Label> (Test.Label.HorizontalTextAlignmentStart,
+ new Label {
+ Text = "HorizontalTextAlignment Start",
+ HorizontalTextAlignment = TextAlignment.Start,
+ HeightRequest = alignmentTestsHeightRequest,
+ WidthRequest = alignmentTestsWidthRequest
+ }
+ );
+
+ var yAlignCenterContainer = new ViewContainer<Label> (Test.Label.VerticalTextAlignmentCenter,
+ new Label {
+ Text = "VerticalTextAlignment Start",
+ VerticalTextAlignment = TextAlignment.Center,
+ HeightRequest = alignmentTestsHeightRequest,
+ WidthRequest = alignmentTestsWidthRequest
+ }
+ );
+
+ var yAlignEndContainer = new ViewContainer<Label> (Test.Label.VerticalTextAlignmentEnd,
+ new Label {
+ Text = "VerticalTextAlignment End",
+ VerticalTextAlignment = TextAlignment.End,
+ HeightRequest = alignmentTestsHeightRequest,
+ WidthRequest = alignmentTestsWidthRequest
+ }
+ );
+
+ var yAlignStartContainer = new ViewContainer<Label> (Test.Label.VerticalTextAlignmentStart,
+ new Label {
+ Text = "VerticalTextAlignment Start",
+ VerticalTextAlignment = TextAlignment.Start,
+ HeightRequest = alignmentTestsHeightRequest,
+ WidthRequest = alignmentTestsWidthRequest
+ }
+ );
+
+ var styleTitleContainer = new ViewContainer<Label> (Test.Device.Styles,
+ new Label {
+ Text = "Device.Styles.TitleStyle",
+ Style = Device.Styles.TitleStyle
+ }
+ );
+
+ var styleSubtitleContainer = new ViewContainer<Label> (Test.Device.Styles,
+ new Label {
+ Text = "Device.Styles.SubtitleStyle",
+ Style = Device.Styles.SubtitleStyle
+ }
+ );
+
+ var styleBodyContainer = new ViewContainer<Label> (Test.Device.Styles,
+ new Label {
+ Text = "Device.Styles.BodyStyle",
+ Style = Device.Styles.BodyStyle
+ }
+ );
+
+ var styleCaptionContainer = new ViewContainer<Label> (Test.Device.Styles,
+ new Label {
+ Text = "Device.Styles.CaptionStyle",
+ Style = Device.Styles.CaptionStyle,
+ }
+ );
+
+ Add (namedSizeMediumBoldContainer);
+ Add (namedSizeMediumItalicContainer);
+ Add (namedSizeLargeContainer);
+ Add (namedSizeMediumContainer);
+ Add (namedSizeMicroContainer);
+ Add (namedSizeSmallContainer);
+ Add (formattedTextContainer);
+ Add (lineBreakModeCharacterWrapContainer);
+ Add (lineBreakModeHeadTruncationContainer);
+ Add (lineBreakModeMiddleTruncationContainer);
+ Add (lineBreakModeNoWrapContainer);
+ Add (lineBreakModeTailTruncationContainer);
+ Add (lineBreakModeWordWrapContainer);
+ Add (textContainer);
+ Add (textColorContainer);
+ Add (xAlignCenterContainer);
+ Add (xAlignEndContainer);
+ Add (xAlignStartContainer);
+ Add (yAlignCenterContainer);
+ Add (yAlignEndContainer);
+ Add (yAlignStartContainer);
+ Add (styleTitleContainer);
+ Add (styleSubtitleContainer);
+ Add (styleBodyContainer);
+ Add (styleCaptionContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/ListViewCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/ListViewCoreGalleryPage.cs
new file mode 100644
index 00000000..ddcd7cef
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/ListViewCoreGalleryPage.cs
@@ -0,0 +1,268 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Threading;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ internal class ListViewCoreGalleryPage : CoreGalleryPage<ListView>
+ {
+ internal class Employee : INotifyPropertyChanged
+ {
+ string _name;
+ public string Name
+ {
+ get { return _name; }
+ set
+ {
+ if (value != null && value != _name) {
+ _name = value;
+ OnPropertyChanged ();
+ }
+ }
+ }
+
+ TimeSpan _daysWorked;
+ public TimeSpan DaysWorked
+ {
+ get { return _daysWorked; }
+ set
+ {
+ if (value != null && value != _daysWorked) {
+ _daysWorked = value;
+ OnPropertyChanged ();
+ }
+ }
+ }
+
+ int _rowHeight;
+ public int RowHeight
+ {
+ get { return _rowHeight; }
+ set
+ {
+ if (value != null && value != _rowHeight) {
+ _rowHeight = value;
+ OnPropertyChanged ();
+ }
+ }
+ }
+
+ public Employee (string name, TimeSpan daysWorked, int rowHeight)
+ {
+ _name = name;
+ _daysWorked = daysWorked;
+ _rowHeight = rowHeight;
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ internal class Grouping<K, T> : ObservableCollection<T>
+ {
+ public K Key { get; private set; }
+
+ public Grouping (K key, IEnumerable<T> items)
+ {
+ Key = key;
+ foreach (T item in items) {
+ Items.Add (item);
+ }
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class HeaderCell : ViewCell
+ {
+ public HeaderCell ()
+ {
+ Height = 60;
+ var title = new Label {
+ HeightRequest = 60,
+ BackgroundColor = Color.Navy,
+ TextColor = Color.White
+ };
+
+ title.SetBinding (Label.TextProperty, new Binding ("Key"));
+
+ View = new StackLayout {
+ BackgroundColor = Color.Pink,
+ Children = { title }
+ };
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ class UnevenCell : ViewCell
+ {
+ public UnevenCell ()
+ {
+
+ SetBinding (HeightProperty, new Binding("RowHeight"));
+
+ var label = new Label ();
+ label.SetBinding (Label.TextProperty, new Binding("Name"));
+
+ var layout = new StackLayout {
+ BackgroundColor = Color.Red,
+ Children = {
+ label
+ }
+ };
+
+ View = layout;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ internal class ListViewViewModel
+ {
+ public ObservableCollection<Grouping<string, Employee>> CategorizedEmployees { get; private set; }
+ public ObservableCollection<Employee> Employees { get; private set; }
+
+ public ListViewViewModel ()
+ {
+ CategorizedEmployees = new ObservableCollection<Grouping<string, Employee>> {
+ new Grouping<string, Employee> (
+ "Engineer",
+ new [] {
+ new Employee ("Seth", TimeSpan.FromDays (10), 60),
+ new Employee ("Jason", TimeSpan.FromDays (100), 100),
+ new Employee ("Eric", TimeSpan.FromDays (1000), 160),
+ }
+ ),
+ new Grouping<string, Employee> (
+ "Sales",
+ new [] {
+ new Employee ("Andrew 1", TimeSpan.FromDays (10), 160),
+ new Employee ("Andrew 2", TimeSpan.FromDays (100), 100),
+ new Employee ("Andrew 3", TimeSpan.FromDays (1000), 60),
+ }
+ ),
+ };
+
+ Employees = new ObservableCollection<Employee> {
+ new Employee ("Seth", TimeSpan.FromDays (10), 60),
+ new Employee ("Jason", TimeSpan.FromDays (100), 100),
+ new Employee ("Eric", TimeSpan.FromDays (1000), 160),
+ new Employee ("Andrew 1", TimeSpan.FromDays (10), 160),
+ new Employee ("Andrew 2", TimeSpan.FromDays (100), 100),
+ new Employee ("Andrew 3", TimeSpan.FromDays (1000), 60),
+ };
+
+ Enumerable.Range (0, 9000).Select (e => new Employee (e.ToString (), TimeSpan.FromDays (1), 60)).ForEach (e => Employees.Add (e));
+ }
+ }
+
+ protected override bool SupportsFocus
+ {
+ get { return false; }
+ }
+
+ protected override void InitializeElement (ListView element)
+ {
+ element.HeightRequest = 350;
+ element.RowHeight = 60;
+
+ var viewModel = new ListViewViewModel ();
+ element.BindingContext = viewModel;
+
+ element.ItemsSource = viewModel.Employees;
+
+ var template = new DataTemplate (typeof(TextCell));
+ template.SetBinding (TextCell.TextProperty, "Name");
+ template.SetBinding (TextCell.DetailProperty, new Binding("DaysWorked", converter: new GenericValueConverter (time => time.ToString ())));
+
+ element.ItemTemplate = template;
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+
+ var viewModel = new ListViewViewModel ();
+
+ var groupDisplayBindingContainer = new ViewContainer<ListView> (Test.ListView.GroupDisplayBinding, new ListView ());
+ InitializeElement (groupDisplayBindingContainer.View);
+ groupDisplayBindingContainer.View.ItemsSource = viewModel.CategorizedEmployees;
+ groupDisplayBindingContainer.View.IsGroupingEnabled = true;
+ groupDisplayBindingContainer.View.GroupDisplayBinding = new Binding ("Key");
+
+
+ var groupHeaderTemplateContainer = new ViewContainer<ListView> (Test.ListView.GroupHeaderTemplate, new ListView ());
+ InitializeElement (groupHeaderTemplateContainer.View);
+ groupHeaderTemplateContainer.View.ItemsSource = viewModel.CategorizedEmployees;
+ groupHeaderTemplateContainer.View.IsGroupingEnabled = true;
+ groupHeaderTemplateContainer.View.GroupHeaderTemplate = new DataTemplate (typeof (HeaderCell));
+
+ var groupShortNameContainer = new ViewContainer<ListView> (Test.ListView.GroupShortNameBinding, new ListView ());
+ InitializeElement (groupShortNameContainer.View);
+ groupShortNameContainer.View.ItemsSource = viewModel.CategorizedEmployees;
+ groupShortNameContainer.View.IsGroupingEnabled = true;
+ groupShortNameContainer.View.GroupShortNameBinding = new Binding("Key");
+
+ // TODO - not sure how to do this
+ var hasUnevenRowsContainer = new ViewContainer<ListView> (Test.ListView.HasUnevenRows, new ListView ());
+ InitializeElement (hasUnevenRowsContainer.View);
+ hasUnevenRowsContainer.View.HasUnevenRows = true;
+ hasUnevenRowsContainer.View.ItemTemplate = new DataTemplate (typeof(UnevenCell));
+
+ var isGroupingEnabledContainer = new StateViewContainer<ListView> (Test.ListView.IsGroupingEnabled, new ListView ());
+ InitializeElement (isGroupingEnabledContainer.View);
+ isGroupingEnabledContainer.View.ItemsSource = viewModel.CategorizedEmployees;
+ isGroupingEnabledContainer.View.IsGroupingEnabled = true;
+ isGroupingEnabledContainer.StateChangeButton.Clicked += (sender, args) => isGroupingEnabledContainer.View.IsGroupingEnabled = !isGroupingEnabledContainer.View.IsGroupingEnabled;
+
+
+ var itemAppearingContainer = new EventViewContainer<ListView> (Test.ListView.ItemAppearing, new ListView ());
+ InitializeElement (itemAppearingContainer.View);
+ itemAppearingContainer.View.ItemAppearing += (sender, args) => itemAppearingContainer.EventFired ();
+
+ var itemDisappearingContainer = new EventViewContainer<ListView> (Test.ListView.ItemDisappearing, new ListView ());
+ InitializeElement (itemDisappearingContainer.View);
+ itemDisappearingContainer.View.ItemDisappearing += (sender, args) => itemDisappearingContainer.EventFired ();
+
+ var itemSelectedContainer = new EventViewContainer<ListView> (Test.ListView.ItemSelected, new ListView ());
+ InitializeElement (itemSelectedContainer.View);
+ itemSelectedContainer.View.ItemSelected += (sender, args) => itemSelectedContainer.EventFired ();
+
+ var itemTappedContainer = new EventViewContainer<ListView> (Test.ListView.ItemTapped, new ListView ());
+ InitializeElement (itemTappedContainer.View);
+ itemTappedContainer.View.ItemTapped += (sender, args) => itemTappedContainer.EventFired ();
+
+ // TODO
+ var rowHeightContainer = new ViewContainer<ListView> (Test.ListView.RowHeight, new ListView ());
+ InitializeElement (rowHeightContainer.View);
+
+ var selectedItemContainer = new ViewContainer<ListView> (Test.ListView.SelectedItem, new ListView ());
+ InitializeElement (selectedItemContainer.View);
+ selectedItemContainer.View.SelectedItem = viewModel.Employees[2];
+
+ Add (groupDisplayBindingContainer);
+ Add (groupHeaderTemplateContainer);
+ Add (groupShortNameContainer);
+ Add (hasUnevenRowsContainer);
+ Add (isGroupingEnabledContainer);
+ Add (itemAppearingContainer);
+ Add (itemDisappearingContainer);
+ Add (itemSelectedContainer);
+ Add (itemTappedContainer);
+ Add (rowHeightContainer);
+ Add (selectedItemContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/OpenGLViewCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/OpenGLViewCoreGalleryPage.cs
new file mode 100644
index 00000000..d057ca9d
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/OpenGLViewCoreGalleryPage.cs
@@ -0,0 +1,16 @@
+namespace Xamarin.Forms.Controls
+{
+ internal class OpenGLViewCoreGalleryPage : CoreGalleryPage<OpenGLView>
+ {
+ // TODO
+ protected override bool SupportsFocus
+ {
+ get { return false; }
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/PickerCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/PickerCoreGalleryPage.cs
new file mode 100644
index 00000000..cea755d4
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/PickerCoreGalleryPage.cs
@@ -0,0 +1,35 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class PickerCoreGalleryPage : CoreGalleryPage<Picker>
+ {
+ // TODO
+ protected override bool SupportsTapGestureRecognizer
+ {
+ get { return false; }
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+ var itemsContainer = new ViewContainer<Picker> (Test.Picker.Items, new Picker ());
+ itemsContainer.View.Items.Add ("Item 1");
+ itemsContainer.View.Items.Add ("Item 2");
+ itemsContainer.View.Items.Add ("Item 3");
+
+ var selectedIndexContainer = new ViewContainer<Picker> (Test.Picker.SelectedIndex, new Picker ());
+ selectedIndexContainer.View.Items.Add ("Item 1");
+ selectedIndexContainer.View.Items.Add ("Item 2");
+ selectedIndexContainer.View.Items.Add ("Item 3");
+ selectedIndexContainer.View.SelectedIndex = 2;
+
+ var titleContainer = new ViewContainer<Picker> (Test.Picker.Title, new Picker ());
+ titleContainer.View.Title = "Title";
+
+ Add (itemsContainer);
+ Add (selectedIndexContainer);
+ Add (titleContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/ProgressBarCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/ProgressBarCoreGalleryPage.cs
new file mode 100644
index 00000000..1cc51ae8
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/ProgressBarCoreGalleryPage.cs
@@ -0,0 +1,27 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class ProgressBarCoreGalleryPage : CoreGalleryPage<ProgressBar>
+ {
+ protected override bool SupportsFocus
+ {
+ get { return false; }
+ }
+
+ protected override void InitializeElement (ProgressBar element)
+ {
+ base.InitializeElement (element);
+
+ element.Progress = 1;
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+
+ var progressContainer = new ViewContainer<ProgressBar> (Test.ProgressBar.Progress, new ProgressBar { Progress = 0.5 });
+ Add (progressContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/SearchBarCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/SearchBarCoreGalleryPage.cs
new file mode 100644
index 00000000..0221b87c
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/SearchBarCoreGalleryPage.cs
@@ -0,0 +1,89 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class SearchBarCoreGalleryPage : CoreGalleryPage<SearchBar>
+ {
+ // TODO
+ protected override bool SupportsTapGestureRecognizer
+ {
+ get { return false; }
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+ var placeholderContainer = new ViewContainer<SearchBar> (Test.SearchBar.PlaceHolder, new SearchBar { Placeholder = "Placeholder" });
+
+ var searchButtonPressedContainer = new EventViewContainer<SearchBar> (Test.SearchBar.SearchButtonPressed, new SearchBar { });
+ searchButtonPressedContainer.View.SearchButtonPressed += (sender, args) => searchButtonPressedContainer.EventFired ();
+
+ var searchCommandContainer = new ViewContainer<SearchBar> (Test.SearchBar.SearchCommand,
+ new SearchBar {
+ SearchCommand = new Command (async () => await DisplayAlert ("Search command", "Fired", "Ok"))
+ }
+ );
+
+ var textContainer = new ViewContainer<SearchBar> (Test.SearchBar.Text, new SearchBar { Text = "I am text" });
+
+ var textChangedContainer = new EventViewContainer<SearchBar> (Test.SearchBar.TextChanged, new SearchBar { Placeholder = "I am text changed" });
+ textChangedContainer.View.TextChanged += (sender, args) => textChangedContainer.EventFired ();
+
+ var cancelButtonColor = new ViewContainer<SearchBar> (
+ Test.SearchBar.CancelButtonColor,
+ new SearchBar {
+ Placeholder = "Should have a red cancel button",
+ CancelButtonColor = Color.Red
+ }
+ );
+
+ var textFontAttributesContainer = new ViewContainer<SearchBar> (Test.SearchBar.FontAttributes, new SearchBar { Text = "I have italic text", FontAttributes = FontAttributes.Italic });
+ var textFamilyContainer1 = new ViewContainer<SearchBar> (Test.SearchBar.FontFamily, new SearchBar { Text = "I have Comic Sans text in Win & Android", FontFamily = "Comic Sans MS" });
+ var textFamilyContainer2 = new ViewContainer<SearchBar> (Test.SearchBar.FontFamily, new SearchBar { Text = "I have bold Chalkboard text in iOS", FontFamily = "ChalkboardSE-Regular", FontAttributes = FontAttributes.Bold });
+ var textFontSizeContainer = new ViewContainer<SearchBar> (Test.SearchBar.FontSize, new SearchBar { Text = "I have default size text" });
+ var textFontSizeDefaultContainer = new ViewContainer<SearchBar> (Test.SearchBar.FontSize, new SearchBar { Text = "I also have default size text" });
+ textFontSizeDefaultContainer.View.FontSize = Device.GetNamedSize (NamedSize.Default, textFontSizeDefaultContainer.View);
+ var textFontSizeLargeContainer = new ViewContainer<SearchBar> (Test.SearchBar.FontSize, new SearchBar { Text = "I have size 48 (huge) text", FontSize = 48 });
+
+ var textAlignmentStartContainer = new ViewContainer<SearchBar> (Test.SearchBar.TextAlignmentStart,
+ new SearchBar { Text = "I should be at the start", HorizontalTextAlignment = TextAlignment.Start });
+ var textAlignmentCenterContainer = new ViewContainer<SearchBar> (Test.SearchBar.TextAlignmentCenter,
+ new SearchBar { Text = "I should be centered", HorizontalTextAlignment = TextAlignment.Center });
+ var textAlignmentEndContainer = new ViewContainer<SearchBar> (Test.SearchBar.TextAlignmentEnd,
+ new SearchBar { Text = "I should be at the end", HorizontalTextAlignment = TextAlignment.End });
+
+ var placeholderAlignmentStartContainer = new ViewContainer<SearchBar> (Test.SearchBar.PlaceholderAlignmentStart,
+ new SearchBar { Placeholder = "I should be at the start", HorizontalTextAlignment = TextAlignment.Start });
+ var placeholderAlignmentCenterContainer = new ViewContainer<SearchBar> (Test.SearchBar.PlaceholderAlignmentCenter,
+ new SearchBar { Placeholder = "I should be centered", HorizontalTextAlignment = TextAlignment.Center });
+ var placeholderAlignmentEndContainer = new ViewContainer<SearchBar> (Test.SearchBar.PlaceholderAlignmentEnd,
+ new SearchBar { Placeholder = "I should be at the end", HorizontalTextAlignment = TextAlignment.End });
+
+ var textColorContainer = new ViewContainer<SearchBar> (Test.SearchBar.TextColor,
+ new SearchBar { Text = "I should be red", TextColor = Color.Red });
+
+ var placeholderColorContainer = new ViewContainer<SearchBar> (Test.SearchBar.PlaceholderColor,
+ new SearchBar { Placeholder = "I should be red", PlaceholderColor = Color.Red });
+ Add (placeholderContainer);
+ Add (searchButtonPressedContainer);
+ Add (searchCommandContainer);
+ Add (textContainer);
+ Add (textChangedContainer);
+ Add (textFontAttributesContainer);
+ Add (textFamilyContainer1);
+ Add (textFamilyContainer2);
+ Add (textFontSizeContainer);
+ Add (textFontSizeDefaultContainer);
+ Add (textFontSizeLargeContainer);
+ Add (cancelButtonColor);
+ Add (textAlignmentStartContainer);
+ Add (textAlignmentCenterContainer);
+ Add (textAlignmentEndContainer);
+ Add (placeholderAlignmentStartContainer);
+ Add (placeholderAlignmentCenterContainer);
+ Add (placeholderAlignmentEndContainer);
+ Add (textColorContainer);
+ Add (placeholderColorContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/SliderCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/SliderCoreGalleryPage.cs
new file mode 100644
index 00000000..be813110
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/SliderCoreGalleryPage.cs
@@ -0,0 +1,29 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class SliderCoreGalleryPage : CoreGalleryPage<Slider>
+ {
+ protected override bool SupportsFocus
+ {
+ get { return false; }
+ }
+
+ protected override bool SupportsTapGestureRecognizer
+ {
+ get { return false; }
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+ var maximumContainer = new ValueViewContainer<Slider> (Test.Slider.Maximum, new Slider { Maximum = 10, Minimum = 5 }, "Value", value => value.ToString ());
+ var minimumContainer = new ValueViewContainer<Slider> (Test.Slider.Minimum, new Slider { Maximum = 10 }, "Value", value => value.ToString ());
+ var valueContainer = new ValueViewContainer<Slider> (Test.Slider.Value, new Slider { Value = 0.5 }, "Value", value => value.ToString ());
+
+ Add (maximumContainer);
+ Add (minimumContainer);
+ Add (valueContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/StepperCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/StepperCoreGalleryPage.cs
new file mode 100644
index 00000000..2ff15466
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/StepperCoreGalleryPage.cs
@@ -0,0 +1,29 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class StepperCoreGalleryPage : CoreGalleryPage<Stepper>
+ {
+ protected override bool SupportsFocus
+ {
+ get { return false; }
+ }
+
+ protected override bool SupportsTapGestureRecognizer
+ {
+ get { return false; }
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+ var maximumContainer = new ValueViewContainer<Stepper> (Test.Stepper.Maximum, new Stepper { Maximum = 10 }, "Value", value => value.ToString ());
+ var minimumContainer = new ValueViewContainer<Stepper> (Test.Stepper.Minimum, new Stepper { Minimum = 2 }, "Value", value => value.ToString ());
+ var incrememtContainer = new ValueViewContainer<Stepper> (Test.Stepper.Increment, new Stepper { Maximum = 20, Minimum = 10, Increment = 2 }, "Value", value => value.ToString ());
+
+ Add (maximumContainer);
+ Add (minimumContainer);
+ Add (incrememtContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/SwitchCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/SwitchCoreGalleryPage.cs
new file mode 100644
index 00000000..5d9ebcfb
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/SwitchCoreGalleryPage.cs
@@ -0,0 +1,25 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class SwitchCoreGalleryPage : CoreGalleryPage<Switch>
+ {
+ protected override bool SupportsFocus
+ {
+ get { return false; }
+ }
+
+ protected override bool SupportsTapGestureRecognizer
+ {
+ get { return false; }
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+
+ var isToggledContainer = new ValueViewContainer<Switch> (Test.Switch.IsToggled, new Switch (), "IsToggled", value => value.ToString ());
+ Add (isToggledContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/TableViewCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/TableViewCoreGalleryPage.cs
new file mode 100644
index 00000000..f5c7a077
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/TableViewCoreGalleryPage.cs
@@ -0,0 +1,16 @@
+namespace Xamarin.Forms.Controls
+{
+ internal class TableViewCoreGalleryPage : CoreGalleryPage<TableView>
+ {
+ // TODO
+ protected override bool SupportsFocus
+ {
+ get { return false; }
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/TimePickerCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/TimePickerCoreGalleryPage.cs
new file mode 100644
index 00000000..bf8b9c98
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/TimePickerCoreGalleryPage.cs
@@ -0,0 +1,24 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class TimePickerCoreGalleryPage : CoreGalleryPage<TimePicker>
+ {
+ protected override bool SupportsTapGestureRecognizer
+ {
+ get { return false; }
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+ var formatContainer = new ViewContainer<TimePicker> (Test.TimePicker.Format, new TimePicker { Format = "HH-mm-ss" });
+ var timeContainer = new ViewContainer<TimePicker> (Test.TimePicker.Time, new TimePicker { Time = new TimeSpan (14, 45, 50) });
+
+ Add (formatContainer);
+ Add (timeContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/CoreGalleryPages/WebViewCoreGalleryPage.cs b/Xamarin.Forms.Controls/CoreGalleryPages/WebViewCoreGalleryPage.cs
new file mode 100644
index 00000000..229aed3b
--- /dev/null
+++ b/Xamarin.Forms.Controls/CoreGalleryPages/WebViewCoreGalleryPage.cs
@@ -0,0 +1,62 @@
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class WebViewCoreGalleryPage : CoreGalleryPage<WebView>
+ {
+ protected override bool SupportsFocus
+ {
+ get { return false; }
+ }
+
+ protected override void InitializeElement (WebView element)
+ {
+ element.HeightRequest = 200;
+
+ element.Source = new UrlWebViewSource { Url = "http://xamarin.com/" };
+ }
+
+ protected override void Build (StackLayout stackLayout)
+ {
+ base.Build (stackLayout);
+
+ var urlWebViewSourceContainer = new ViewContainer<WebView> (Test.WebView.UrlWebViewSource,
+ new WebView {
+ Source = new UrlWebViewSource { Url = "https://www.google.com/" },
+ HeightRequest = 200
+ }
+ );
+
+ const string html = "<html><div class=\"test\"><h2>I am raw html</h2></div></html>";
+ var htmlWebViewSourceContainer = new ViewContainer<WebView> (Test.WebView.HtmlWebViewSource,
+ new WebView {
+ Source = new HtmlWebViewSource { Html = html },
+ HeightRequest = 200
+ }
+ );
+
+ var htmlFileWebSourceContainer = new ViewContainer<WebView> (Test.WebView.LoadHtml,
+ new WebView {
+ Source = new HtmlWebViewSource {
+ Html = @"<html>
+<head>
+<link rel=""stylesheet"" href=""default.css"">
+</head>
+<body>
+<h1>Xamarin.Forms</h1>
+<p>The CSS and image are loaded from local files!</p>
+<img src='WebImages/XamarinLogo.png'/>
+<p><a href=""local.html"">next page</a></p>
+</body>
+</html>"
+ },
+ HeightRequest = 200
+ }
+ );
+
+ Add (urlWebViewSourceContainer);
+ Add (htmlWebViewSourceContainer);
+ Add (htmlFileWebSourceContainer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/GalleryPages/AbsoluteLayoutGallery.cs b/Xamarin.Forms.Controls/GalleryPages/AbsoluteLayoutGallery.cs
new file mode 100644
index 00000000..b38798f1
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/AbsoluteLayoutGallery.cs
@@ -0,0 +1,151 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ internal class AbsolutePositioningExplorationViewModel : INotifyPropertyChanged
+ {
+ double _rectangleX = 0.5;
+ double _rectangleY = 0.5;
+ double _rectangleWidth = 0.5;
+ double _rectangleHeight = 0.5;
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler (this, new PropertyChangedEventArgs (propertyName));
+ }
+
+ public double RectangleX
+ {
+ get { return _rectangleX; }
+ set
+ {
+ if (_rectangleX == value)
+ return;
+ _rectangleX = value;
+ OnPropertyChanged ();
+ OnPropertyChanged ("Rectangle");
+ }
+ }
+
+ public double RectangleY
+ {
+ get { return _rectangleY; }
+ set
+ {
+ if (_rectangleY == value)
+ return;
+ _rectangleY = value;
+ OnPropertyChanged ();
+ OnPropertyChanged ("Rectangle");
+ }
+ }
+
+ public double RectangleWidth
+ {
+ get { return _rectangleWidth; }
+ set
+ {
+ if (_rectangleWidth == value)
+ return;
+ _rectangleWidth = value;
+ OnPropertyChanged ();
+ OnPropertyChanged ("Rectangle");
+ }
+ }
+
+ public double RectangleHeight
+ {
+ get { return _rectangleHeight; }
+ set
+ {
+ if (_rectangleHeight == value)
+ return;
+ _rectangleHeight = value;
+ OnPropertyChanged ();
+ OnPropertyChanged ("Rectangle");
+ }
+ }
+
+ public Rectangle Rectangle
+ {
+ get { return new Rectangle(RectangleX, RectangleY, RectangleWidth, RectangleHeight); }
+ }
+ }
+ public class AbsoluteLayoutGallery : ContentPage
+ {
+ public AbsoluteLayoutGallery ()
+ {
+ Device.OnPlatform (iOS: () => {
+ if (Device.Idiom == TargetIdiom.Tablet) {
+ Padding = new Thickness (0, 0, 0, 60);
+ }
+ });
+
+ BindingContext = new AbsolutePositioningExplorationViewModel ();
+ var absLayout = new AbsoluteLayout {
+ BackgroundColor = Color.Gray,
+ VerticalOptions = LayoutOptions.FillAndExpand
+ };
+
+ var rect = new BoxView {Color = Color.Lime};
+
+ var xSlider = new Slider ();
+ var ySlider = new Slider ();
+ var widthSlider = new Slider ();
+ var heightSlider = new Slider ();
+
+ var grid = new Grid {
+ Padding = 10,
+ RowSpacing = 0,
+ ColumnDefinitions = {
+ new ColumnDefinition {Width = GridLength.Auto},
+ new ColumnDefinition {Width = new GridLength (1, GridUnitType.Star)}
+ }
+ };
+
+ grid.Children.Add (new Label {Text = "X:", VerticalTextAlignment = TextAlignment.Center}, 0, 0);
+ grid.Children.Add (xSlider, 1, 0);
+
+ grid.Children.Add (new Label {Text = "Y:", VerticalTextAlignment = TextAlignment.Center}, 0, 1);
+ grid.Children.Add (ySlider, 1, 1);
+
+ grid.Children.Add (new Label {Text = "Width:", VerticalTextAlignment = TextAlignment.Center}, 0, 2);
+ grid.Children.Add (widthSlider, 1, 2);
+
+ grid.Children.Add (new Label {Text = "Height:", VerticalTextAlignment = TextAlignment.Center}, 0, 3);
+ grid.Children.Add (heightSlider, 1, 3);
+
+ absLayout.Children.Add (rect);
+
+ var mainLayout = new StackLayout {
+ Spacing = 0,
+ Children = {
+ absLayout,
+ grid
+ }
+ };
+
+ rect.SetBinding (AbsoluteLayout.LayoutBoundsProperty, "Rectangle");
+ AbsoluteLayout.SetLayoutFlags (rect, AbsoluteLayoutFlags.All);
+
+ xSlider.SetBinding (Slider.ValueProperty, new Binding ("RectangleX", BindingMode.TwoWay));
+ ySlider.SetBinding (Slider.ValueProperty, new Binding ("RectangleY", BindingMode.TwoWay));
+ widthSlider.SetBinding (Slider.ValueProperty, new Binding ("RectangleWidth", BindingMode.TwoWay));
+ heightSlider.SetBinding (Slider.ValueProperty, new Binding ("RectangleHeight", BindingMode.TwoWay));
+
+ //Content = new ScrollView {Content = mainLayout};
+ Content = mainLayout;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/ActionSheetGallery.cs b/Xamarin.Forms.Controls/GalleryPages/ActionSheetGallery.cs
new file mode 100644
index 00000000..4f60c1e1
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/ActionSheetGallery.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class ActionSheetGallery : ContentPage
+ {
+ public ActionSheetGallery ()
+ {
+ AutomationId = "ActionSheetPage";
+
+ var extras = new string[] {
+ "Extra One",
+ "Extra Two",
+ "Extra Three",
+ "Extra Four",
+ "Extra Five",
+ "Extra Six",
+ "Extra Seven",
+ "Extra Eight",
+ "Extra Nine",
+ "Extra Ten",
+ "Extra Eleven",
+ };
+
+ Content = new ScrollView {
+ Content = new StackLayout {
+ Spacing = 0,
+ Children = {
+ MakeActionSheetButton (this, "ActionSheet Cancel", null, "Cancel", null),
+ MakeActionSheetButton (this, "ActionSheet Cancel Extras", null, "Cancel", null, extras),
+ MakeActionSheetButton (this, "ActionSheet Cancel Destruction", null, "Cancel", "Destruction"),
+ MakeActionSheetButton (this, "ActionSheet Cancel Destruction Extras", null, "Cancel", "Destruction", extras),
+ MakeActionSheetButton (this, "ActionSheet Destruction", null, null, "Destruction"),
+ MakeActionSheetButton (this, "ActionSheet Destruction Extras", null, null, "Destruction", extras),
+ MakeActionSheetButton (this, "ActionSheet Extras", null, null, null, extras),
+ MakeActionSheetButton (this, "ActionSheet Title", "Title", null, null),
+ MakeActionSheetButton (this, "ActionSheet Title Cancel", "Title", "Cancel", null),
+ MakeActionSheetButton (this, "ActionSheet Title Cancel Extras", "Title", "Cancel", null, extras),
+ MakeActionSheetButton (this, "ActionSheet Title Cancel Destruction", "Title", "Cancel", "Destruction"),
+ MakeActionSheetButton (this, "ActionSheet Title Cancel Destruction Extras", "Title", "Cancel", "Destruction", extras),
+ MakeActionSheetButton (this, "ActionSheet Title Destruction", "Title", null, "Destruction"),
+ MakeActionSheetButton (this, "ActionSheet Title Destruction Extras", "Title", null, "Destruction", extras),
+ MakeActionSheetButton (this, "ActionSheet Title Extras", "Title", null, null, extras),
+ }
+ }
+ };
+ }
+
+ static Button MakeActionSheetButton (Page page, string buttonText, string title, string cancel, string destruction, params string[] extras)
+ {
+ var actionSheetButton = new Button {
+ Text = buttonText
+ };
+
+ actionSheetButton.Clicked += async (sender, e) => await page.DisplayActionSheet (title, cancel, destruction, extras);
+
+ return actionSheetButton;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/AlertGallery.cs b/Xamarin.Forms.Controls/GalleryPages/AlertGallery.cs
new file mode 100644
index 00000000..8a666a10
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/AlertGallery.cs
@@ -0,0 +1,28 @@
+using System;
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Controls
+{
+ public class AlertGallery : ContentPage
+ {
+ public AlertGallery ()
+ {
+ var lblResult = new Label { Text = "Result: ", AutomationId = "testResult" };
+
+ var btn1 = new Button { Text = "Alert Override1", AutomationId = "test1" };
+ btn1.Clicked += async (sender, e) => {
+ await DisplayAlert ("TheAlertTitle", "TheAlertMessage", "TheCancelButton");;
+ };
+
+ var btn2 = new Button { Text = "Alert Override2", AutomationId = "test2" };
+ btn2.Clicked += async (sender, e) => {
+ var result = await DisplayAlert ("TheAlertTitle", "TheAlertMessage", "TheAcceptButton", "TheCancelButton");
+ lblResult.Text = string.Format("Result: {0}", result);
+ };
+
+ Content = new StackLayout { Children = { lblResult, btn1, btn2 }};
+ }
+ }
+}
+
+
diff --git a/Xamarin.Forms.Controls/GalleryPages/BackgroundImageGallery.cs b/Xamarin.Forms.Controls/GalleryPages/BackgroundImageGallery.cs
new file mode 100644
index 00000000..7282a0ed
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/BackgroundImageGallery.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class BackgroundImageGallery
+ : ContentPage
+ {
+ public BackgroundImageGallery ()
+ {
+ var contentIntabs = new Button { Text = "Tabbed children" };
+ contentIntabs.Clicked += async (sender, args) => {
+ await Navigation.PushModalAsync (new TabbedPage {
+ ItemTemplate = new DataTemplate (() => {
+ var page = new ContentPage();
+ page.SetBinding (BackgroundImageProperty, ".");
+ return page;
+ }),
+
+ ItemsSource = new[] {
+ "oasis.jpg",
+ "crimson.jpg"
+ }
+ /*ItemsSource = new[] {
+ "http://www.zemwallpaper.com/wp-content/uploads/2014/05/Desktop-background-download-21.jpg",
+ "http://www.zemwallpaper.com/wp-content/uploads/2014/05/Desktop-background-download-31.jpg",
+ "http://www.zemwallpaper.com/wp-content/uploads/2014/05/Desktop-background-download-61.jpg",
+ "http://www.zemwallpaper.com/wp-content/uploads/2014/05/Desktop-background-download-71.jpg"
+ };*/
+ });
+ };
+
+ var contentInCarosel = new Button { Text = "Carousel children" };
+ contentInCarosel.Clicked += async (sender, args) => {
+ await Navigation.PushModalAsync (new CarouselPage {
+ ItemTemplate = new DataTemplate (() => {
+ var page = new ContentPage();
+ page.SetBinding (BackgroundImageProperty, ".");
+ return page;
+ }),
+
+ ItemsSource = new[] {
+ "oasis.jpg",
+ "crimson.jpg"
+ }
+ /*ItemsSource = new[] {
+ "http://www.zemwallpaper.com/wp-content/uploads/2014/05/Desktop-background-download-21.jpg",
+ "http://www.zemwallpaper.com/wp-content/uploads/2014/05/Desktop-background-download-31.jpg",
+ "http://www.zemwallpaper.com/wp-content/uploads/2014/05/Desktop-background-download-61.jpg",
+ "http://www.zemwallpaper.com/wp-content/uploads/2014/05/Desktop-background-download-71.jpg"
+ };*/
+ });
+ };
+
+ var navigation = new Button { Text = "NavigationPage"};
+ navigation.Clicked += async (sender, args) => {
+ await Navigation.PushModalAsync (new NavigationPage (new ContentPage {
+ Content = new Label {
+ Text = "Text",
+ FontSize = 42
+ }})
+ {
+ BackgroundImage = "oasis.jpg"
+ }
+ );
+ };
+
+ var carousel = new Button { Text = "CarouselPage" };
+ carousel.Clicked += async (sender, args) => {
+ await Navigation.PushAsync (new CarouselPage {
+ BackgroundImage = "crimson.jpg",
+ ItemsSource = new[] { "test1", "test2" }
+ });
+ };
+
+ var tabbed = new Button { Text = "TabbedPage" };
+ tabbed.Clicked += async (sender, args) => {
+ await Navigation.PushAsync (new TabbedPage {
+ BackgroundImage = "crimson.jpg",
+ ItemsSource = new[] { "test1", "test2" }
+ });
+ };
+
+ var master = new Button { Text = "MasterDetail" };
+ master.Clicked += async (sender, args) => {
+ await Navigation.PushModalAsync (new MasterDetailPage {
+ Master = new ContentPage { Title = "Master" },
+ Detail = new ContentPage(),
+ BackgroundImage = "crimson.jpg",
+ });
+ };
+
+ Content = new StackLayout {
+ Children = {
+ navigation,
+ carousel,
+ tabbed,
+ master,
+ contentIntabs,
+ contentInCarosel
+ }
+
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/BoundContentPage.cs b/Xamarin.Forms.Controls/GalleryPages/BoundContentPage.cs
new file mode 100644
index 00000000..e3051fde
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/BoundContentPage.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Globalization;
+using System.Windows.Input;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ public class BoundContentPage : ContentPage
+ {
+ internal class NavWrapperConverter : IValueConverter
+ {
+ public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return new NavigationWrapper ((INavigation) value);
+ }
+ }
+
+ internal class NavigationWrapper
+ {
+ // This class is dumb but proves you can wrap the INavigation with a converter to do some MVVM goodness
+ // Normally this class would implement pushes with ViewModel then do the conversion
+ readonly INavigation _inner;
+
+ public NavigationWrapper (INavigation inner )
+ {
+ _inner = inner;
+ }
+
+ public void WrappedPush ()
+ {
+ _inner.PushAsync (new ContentPage {
+ Content = new StackLayout {
+ BackgroundColor = Color.Red,
+ Children = {
+ new Label {
+ Text = "Second Page"
+ }
+ }
+ }
+ });
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ internal class BoundContentPageViewModel
+ {
+ public string ButtonText { get { return "Click Me!"; } }
+
+ public ICommand ButtonCommand { get; set; }
+
+ public NavigationWrapper Navigation { get; set; }
+
+ public BoundContentPageViewModel ()
+ {
+ ButtonCommand = new Command (() => Navigation.WrappedPush ());
+ }
+ }
+
+ public BoundContentPage ()
+ {
+ Title ="Bound Gallery";
+
+ BindingContext = new BoundContentPageViewModel ();
+
+ var button = new Button ();
+ button.SetBinding (Button.TextProperty, "ButtonText");
+ button.SetBinding (Button.CommandProperty, "ButtonCommand");
+
+ SetBinding (NavigationProperty, new Binding ("Navigation", converter: new NavWrapperConverter ()));
+
+ Content = button;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/ButtonGallery.cs b/Xamarin.Forms.Controls/GalleryPages/ButtonGallery.cs
new file mode 100644
index 00000000..bb276014
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/ButtonGallery.cs
@@ -0,0 +1,115 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class ButtonGallery : ContentPage
+ {
+ public ButtonGallery ()
+ {
+ BackgroundColor = new Color (0.9);
+
+ var normal = new Button { Text = "Normal Button" };
+ normal.Effects.Add (Effect.Resolve ("XamControl.BorderEffect"));
+
+ var disabled = new Button { Text = "Disabled Button"};
+ var disabledswitch = new Switch ();
+ disabledswitch.SetBinding (Switch.IsToggledProperty, "IsEnabled");
+ disabledswitch.BindingContext = disabled;
+
+ var canTapLabel = new Label {
+ Text = "Cannot Tap"
+ };
+
+ disabled.Clicked += (sender, e) => {
+ canTapLabel.Text = "TAPPED!";
+ };
+
+ var click = new Button { Text = "Click Button" };
+ var rotate = new Button { Text = "Rotate Button" };
+ var transparent = new Button { Text = "Transparent Button" };
+
+ var fontName = Device.OnPlatform ("Georgia", "sans-serif-light", "Comic Sans MS");
+ var font = Font.OfSize (fontName, NamedSize.Medium);
+
+ var themedButton = new Button {
+ Text = "Accent Button",
+ BackgroundColor = Color.Accent,
+ TextColor = Color.White,
+ ClassId = "AccentButton",
+ Font = font
+ };
+ var borderButton = new Button {
+ Text = "Border Button",
+ BorderColor = Color.Black,
+ BackgroundColor = Color.Purple,
+ BorderWidth = 5,
+ BorderRadius = 5
+ };
+ var timer = new Button { Text = "Timer" };
+ var busy = new Button { Text = "Toggle Busy" };
+ var alert = new Button { Text = "Alert" };
+ var alertSingle = new Button {Text = "Alert Single"};
+ var image = new Button { Text = "Image Button", Image = new FileImageSource {File = "bank.png"}, BackgroundColor = Color.Blue.WithLuminosity (.8) };
+
+ themedButton.Clicked += (sender, args) => themedButton.Font = Font.Default;
+
+ alertSingle.Clicked += (sender, args) => DisplayAlert ("Foo", "Bar", "Cancel");
+
+ disabled.IsEnabled = false;
+ int i = 1;
+ click.Clicked += (sender, e) => { click.Text = "Clicked " + i++; };
+ rotate.Clicked += (sender, e) => rotate.RelRotateTo (180);
+ transparent.Opacity = .5;
+
+ int j = 1;
+ timer.Clicked += (sender, args) => Device.StartTimer (TimeSpan.FromSeconds (1), () => {
+ timer.Text = "Timer Elapsed " + j++;
+ return j < 4;
+ });
+
+ bool isBusy = false;
+ busy.Clicked += (sender, args) => IsBusy = isBusy = !isBusy;
+
+ alert.Clicked += async (sender, args) => {
+ var result = await DisplayAlert ("User Alert", "This is a user alert. This is only a user alert.", "Accept", "Cancel");
+ alert.Text = result ? "Accepted" : "Cancelled";
+ };
+
+ borderButton.Clicked += (sender, args) => borderButton.BackgroundColor = Color.Default;
+
+ Content = new ScrollView {
+ Content = new StackLayout {
+ Padding = new Size (20, 20),
+ Children = {
+ normal,
+ new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children={
+ disabled,
+ disabledswitch,
+ },
+ },
+ canTapLabel,
+ click,
+ rotate,
+ transparent,
+ themedButton,
+ borderButton,
+ new Button {Text = "Thin Border", BorderWidth = 1, BackgroundColor=Color.White, BorderColor = Color.Black, TextColor = Color.Black},
+ new Button {Text = "Thinner Border", BorderWidth = .5, BackgroundColor=Color.White, BorderColor = Color.Black, TextColor = Color.Black},
+ timer,
+ busy,
+ alert,
+ alertSingle,
+ image,
+ }
+ }
+ };
+
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/CarouselPageGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CarouselPageGallery.cs
new file mode 100644
index 00000000..478b3018
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/CarouselPageGallery.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+
+ public class CarouselPageGallery : CarouselPage
+ {
+ public CarouselPageGallery ()
+ {
+ var pageOneLabel = new Label {
+ Text = "No click one"
+ };
+
+ var pageTwoLabel = new Label {
+ Text = "No click two"
+ };
+
+ var pageThreeLabel = new Label {
+ Text = "No click three"
+ };
+
+ var pageOneButton = new Button {
+ Text = "Click me one",
+ Command = new Command (() => pageOneLabel.Text = "Clicked one")
+ };
+
+ var pageTwoButton = new Button {
+ Text = "Click me two",
+ Command = new Command (() => pageTwoLabel.Text = "Clicked two")
+ };
+
+ var pageThreeButton = new Button {
+ Text = "Click me three",
+ Command = new Command (() => pageThreeLabel.Text = "Clicked three")
+ };
+
+ Children.Add (new ContentPage {
+ Title = "Page One",
+ BackgroundColor = new Color (1, 0, 0),
+ Content = new StackLayout {
+ Children = {
+ pageOneLabel,
+ pageOneButton
+ }
+ }
+ });
+
+ Children.Add (new ContentPage {
+ Title = "Page Two",
+ BackgroundColor = new Color (0, 1, 0),
+ Content = new StackLayout {
+ Children = {
+ pageTwoLabel,
+ pageTwoButton
+ }
+ }
+ });
+
+ Children.Add (new ContentPage {
+ Title = "Page Three",
+ BackgroundColor = new Color (0, 0, 1),
+ Content = new StackLayout {
+ Children = {
+ pageThreeLabel,
+ pageThreeButton
+ }
+ }
+ });
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls/GalleryPages/CarouselViewGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CarouselViewGallery.cs
new file mode 100644
index 00000000..87f741cc
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/CarouselViewGallery.cs
@@ -0,0 +1,292 @@
+using System;
+
+using Xamarin.Forms.CustomAttributes;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Collections.ObjectModel;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ public sealed class CarouselViewGallaryPage : ContentPage // or TestMasterDetailPage, etc ...
+ {
+ public abstract class Item
+ {
+ static int s_id = 0;
+
+ int id;
+
+ internal Item()
+ {
+ id = s_id++;
+ }
+
+ public int Id => id;
+ public string TypeName => GetType ().Name;
+ }
+ public sealed class Foo : Item { }
+ public sealed class Bar : Item { }
+ public sealed class Baz : Item { }
+ public sealed class Poo : Item { }
+ public sealed class Moo : Item { }
+
+ [Preserve (AllMembers = true)]
+ public sealed class ItemView : ContentView
+ {
+ public static readonly BindableProperty TextColorProperty = BindableProperty.Create (
+ propertyName: nameof(TextColor),
+ returnType: typeof (Color),
+ declaringType: typeof (ItemView),
+ defaultValue: Color.White,
+ defaultBindingMode: BindingMode.TwoWay
+ );
+ public static readonly BindableProperty ContextProperty = BindableProperty.Create (
+ propertyName: nameof(Context),
+ returnType: typeof (CarouselView),
+ declaringType: typeof (ItemView),
+ defaultBindingMode: BindingMode.TwoWay
+ );
+
+ public ItemView ()
+ {
+
+ var change = CreateButton("Change", (items, index) => items[index] = new Moo ());
+
+ var removeBar = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Children = {
+ CreateButton ("- Left", (items, index) => items.RemoveAt (index - 1)),
+ CreateButton ("Remove", (items, index) => items.RemoveAt (index)),
+ CreateButton ("- Right", (items, index) => items.RemoveAt (index + 1)),
+ }
+ };
+
+ var addBar = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Children = {
+ CreateButton ("+ Left", (items, index) => items.Insert (index, new Moo ())),
+ CreateButton ("+ Right", (items, index) => {
+ if (index == items.Count - 1)
+ items.Add (new Moo ());
+ else
+ items.Insert (index + 1, new Moo ());
+ }),
+ }
+ };
+
+ var typeNameLabel = new Label () { StyleId = "typename" };
+ typeNameLabel.SetBinding (Label.TextProperty, nameof(Item.TypeName));
+
+ var idLabel = new Label () { StyleId = "id", TextColor = Color.White };
+ idLabel.SetBinding (Label.TextProperty, nameof(Item.Id));
+
+ Content = new StackLayout {
+ Children = {
+ typeNameLabel,
+ idLabel,
+ change,
+ removeBar,
+ addBar,
+ }
+ };
+
+ PropertyChanged += (s, e) => {
+ if (e.PropertyName == "TextColor")
+ typeNameLabel.TextColor = TextColor;
+ };
+ }
+
+ Button CreateButton(string text, Action<IList<Item>, int> clicked)
+ {
+ var button = new Button ();
+ button.Text = text;
+ button.Clicked += (s, e) => {
+ var items = (IList<Item>)Context.ItemsSource;
+ var index = items.IndexOf (BindingContext);
+ clicked (items, index);
+ };
+ return button;
+ }
+
+ public CarouselView Context
+ {
+ get { return (CarouselView)GetValue (ContextProperty); }
+ set { SetValue (ContextProperty, value); }
+ }
+ public Color TextColor
+ {
+ get { return (Color)GetValue(TextColorProperty); }
+ set { SetValue(TextColorProperty, value); }
+ }
+ }
+ public sealed class MyDataTemplateSelector : DataTemplateSelector
+ {
+ Dictionary<Type, Color> m_colorByType = new Dictionary<Type, Color> ();
+ Dictionary<Type, DataTemplate> m_dataTemplateByType = new Dictionary<Type, DataTemplate> ();
+
+ public MyDataTemplateSelector()
+ {
+ m_colorByType[typeof (Foo)] = Color.Green;
+ m_colorByType[typeof (Bar)] = Color.Red;
+ }
+
+ protected override DataTemplate OnSelectTemplate (object item, BindableObject container)
+ {
+ return OnSelectTemplate (item.GetType (), container);
+ }
+
+ DataTemplate OnSelectTemplate (Type itemType, BindableObject container)
+ {
+ DataTemplate dataTemplate;
+ if (!m_dataTemplateByType.TryGetValue(itemType, out dataTemplate))
+ m_dataTemplateByType[itemType] = dataTemplate = CreateTemplate(itemType, container);
+ return dataTemplate;
+ }
+
+ DataTemplate CreateTemplate(Type itemType, BindableObject container)
+ {
+ var dataTemplate = new DataTemplate (typeof (ItemView));
+
+ Color color;
+ if (!m_colorByType.TryGetValue (itemType, out color)) {
+ color = Color.Pink;
+ dataTemplate.SetValue (BackgroundColorProperty, Color.Black);
+ } else {
+ dataTemplate.SetValue (BackgroundColorProperty, Color.Blue);
+ }
+
+ dataTemplate.SetValue (ItemView.TextColorProperty, color);
+ dataTemplate.SetValue (ItemView.ContextProperty, container);
+ return dataTemplate;
+ }
+ }
+
+ static readonly MyDataTemplateSelector Selector = new MyDataTemplateSelector ();
+
+ static readonly IList<Item> Items = new ObservableCollection<Item> () {
+ new Baz(),
+ new Poo(),
+ new Foo(),
+ new Bar(),
+ };
+
+ Button CreateButton(string text, Action onClicked = null)
+ {
+ var button = new Button {
+ Text = text
+ };
+
+ if (onClicked != null)
+ button.Clicked += (s, e) => onClicked();
+
+ return button;
+ }
+
+ public CarouselViewGallaryPage ()
+ {
+ BackgroundColor = Color.Blue;
+
+ var logLabel = new Label () { TextColor = Color.White };
+ var selectedItemLabel = new Label () { TextColor = Color.White, Text = "0" };
+ var selectedPositionLabel = new Label () { TextColor = Color.White, Text = "@0" };
+ //var appearingLabel = new Label () { TextColor = Color.White };
+ //var disappearingLabel = new Label () { TextColor = Color.White };
+
+ var carouselView = new CarouselView {
+ BackgroundColor = Color.Purple,
+ ItemsSource = Items,
+ ItemTemplate = Selector,
+ Position = 1
+ };
+
+ bool capture = false;
+ carouselView.ItemSelected += (s, o) => {
+ var item = (Item)o.SelectedItem;
+ selectedItemLabel.Text = $"{item.Id}";
+ if (capture)
+ logLabel.Text += $"({item.Id}) ";
+ };
+ carouselView.PositionSelected += (s, o) => {
+ var position = (int)o.SelectedPosition;
+ selectedPositionLabel.Text = $"@{position}=={carouselView.Position}";
+ if (capture)
+ logLabel.Text += $"(@{position}) ";
+ };
+ //carouselView.ItemDisappearing += (s, o) => {
+ // var item = (Item)o.Item;
+ // var id = item.Id;
+ // disappearingLabel.Text = $"-{id}";
+ // if (capture)
+ // logLabel.Text += $"(-{id}) ";
+ //};
+ //carouselView.ItemAppearing += (s, o) => {
+ // var item = (Item)o.Item;
+ // var id = item.Id;
+ // appearingLabel.Text = $"+{id}";
+ // if (capture)
+ // logLabel.Text += $"(+{id}) ";
+ //};
+
+ var moveBar = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Children = {
+ CreateButton ("<<", () => carouselView.Position = 0),
+ CreateButton ("<", () => { try { carouselView.Position--; } catch { } }),
+ CreateButton (">", () => { try { carouselView.Position++; } catch { } }),
+ CreateButton (">>", () => carouselView.Position = Items.Count - 1)
+ }
+ };
+
+ var statusBar = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ selectedItemLabel,
+ selectedPositionLabel,
+ //disappearingLabel,
+ //appearingLabel,
+ }
+ };
+
+ var logBar = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ CreateButton ("Clear", () => logLabel.Text = ""),
+ CreateButton ("On/Off", () => capture = !capture ),
+ logLabel,
+ }
+ };
+
+ Content = new StackLayout {
+ Children = {
+ carouselView,
+ moveBar,
+ statusBar,
+ logBar
+ }
+ };
+ }
+
+#if UITEST
+ //[Test]
+ //public void CarouselViewTest ()
+ //{
+ // var app = RunningApp;
+ // app.Screenshot ("I am at Issue 1");
+ // app.WaitForElement (q => q.Marked ("Remove"));
+
+ // app.Screenshot ("I see the Label");
+ // app.SwipeRight ();
+ // app.SwipeLeft ();
+ //}
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/CellTypeList.cs b/Xamarin.Forms.Controls/GalleryPages/CellTypeList.cs
new file mode 100644
index 00000000..4298bc81
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/CellTypeList.cs
@@ -0,0 +1,63 @@
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class CellTypesListPage : ContentPage
+ {
+ public CellTypesListPage ()
+ {
+ Content = new CellTypeList ();
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ public class CellNavigation
+ {
+ public string CellType { get; set; }
+ public ContentPage Page { get; set; }
+
+ public CellNavigation (string type, ContentPage page)
+ {
+ CellType = type;
+ Page = page;
+ }
+ }
+
+ public class CellTypeList : ListView
+ {
+ // TODO Add gallerys for ViewCell, ListView and TableView
+ public CellTypeList ()
+ {
+ var itemList = new List<CellNavigation> {
+ new CellNavigation ("TextCell List", new TextCellListPage ()),
+ new CellNavigation ("TextCell Table", new TextCellTablePage ()),
+ new CellNavigation ("ImageCell List", new ImageCellListPage ()),
+ new CellNavigation ("ImageCell Url List", new UrlImageCellListPage()),
+ new CellNavigation ("ImageCell Table", new ImageCellTablePage ()),
+ new CellNavigation ("SwitchCell List", new SwitchCellListPage ()),
+ new CellNavigation ("SwitchCell Table", new SwitchCellTablePage ()),
+ new CellNavigation ("EntryCell List", new EntryCellListPage ()),
+ new CellNavigation ("EntryCell Table", new EntryCellTablePage ()),
+ new CellNavigation ("ViewCell Image url table", new UrlImageViewCellListPage())
+ };
+
+ ItemsSource = itemList;
+
+ var template = new DataTemplate (typeof (TextCell));
+ template.SetBinding (TextCell.TextProperty, new Binding ("CellType"));
+
+ ItemTemplate = template;
+ ItemSelected += (s, e) => {
+ if (SelectedItem == null)
+ return;
+
+ var cellNav = (CellNavigation) e.SelectedItem;
+ Navigation.PushAsync (cellNav.Page);
+ SelectedItem = null;
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/EntryCellListPage.cs b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/EntryCellListPage.cs
new file mode 100644
index 00000000..b70a9f82
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/EntryCellListPage.cs
@@ -0,0 +1,54 @@
+using System.Linq;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ public class EntryCellTest {
+ public string Label { get; set; }
+ public string Placeholder { get; set; }
+ public Color LabelColor { get; set; }
+ public Color PlaceholderColor { get; set; }
+
+ }
+
+ public class EntryCellListPage : ContentPage
+ {
+ public EntryCellListPage ()
+ {
+ Title = "EntryCell List Gallery - Legacy";
+
+ Device.OnPlatform (iOS: () => {
+ if (Device.Idiom == TargetIdiom.Tablet) {
+ Padding = new Thickness (0, 0, 0, 60);
+ }
+ });
+
+ var dataTemplate = new DataTemplate (typeof(EntryCell));
+ dataTemplate.SetBinding (EntryCell.LabelProperty, new Binding ("Label"));
+ dataTemplate.SetBinding (EntryCell.LabelColorProperty, new Binding ("LabelColor"));
+ dataTemplate.SetBinding (EntryCell.PlaceholderProperty, new Binding ("Placeholder"));
+
+ var label = new Label {
+ Text = "I have not been selected"
+ };
+
+ var listView = new ListView {
+ ItemsSource = Enumerable.Range (0, 100).Select (i => new EntryCellTest {
+ Label = "Label " + i,
+ LabelColor = i % 2 == 0 ? Color.Red : Color.Blue,
+ Placeholder = "Placeholder " + i,
+ PlaceholderColor = i % 2 == 0 ? Color.Red : Color.Blue,
+ }),
+ ItemTemplate = dataTemplate
+ };
+
+ listView.ItemSelected += (sender, args) => {
+ label.Text = "I have been selected";
+ };
+
+
+
+ Content = new StackLayout { Children = { label, listView } };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/EntryCellTablePage.cs b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/EntryCellTablePage.cs
new file mode 100644
index 00000000..c37dd441
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/EntryCellTablePage.cs
@@ -0,0 +1,85 @@
+namespace Xamarin.Forms.Controls
+{
+ public class EntryCellTablePage : ContentPage
+ {
+ public EntryCellTablePage ()
+ {
+ Title = "EntryCell Table Gallery - Legacy";
+
+ Device.OnPlatform (iOS: () => {
+ if (Device.Idiom == TargetIdiom.Tablet) {
+ Padding = new Thickness (0, 0, 0, 60);
+ }
+ });
+
+ int timesEntered = 1;
+
+ var entryCell = new EntryCell { Label = "Enter text", Placeholder = "I am a placeholder" };
+ entryCell.Completed += (sender, args) => {
+ ((EntryCell)sender).Label = "Entered: " + timesEntered;
+ timesEntered++;
+ };
+
+ var tableSection = new TableSection ("Section One") {
+ new EntryCell { Label = "disabled", Placeholder = "disabled", IsEnabled = false },
+ new EntryCell { Label = "Text 2" },
+ new EntryCell { Label = "Text 3", Placeholder = "Placeholder 2" },
+ new EntryCell { Label = "Text 4" },
+ new EntryCell { Label = "Text 5", Placeholder = "Placeholder 3" },
+ new EntryCell { Label = "Text 6" },
+ new EntryCell { Label = "Text 7", Placeholder = "Placeholder 4" },
+ new EntryCell { Label = "Text 8" },
+ new EntryCell { Label = "Text 9", Placeholder = "Placeholder 5" },
+ new EntryCell { Label = "Text 10" },
+ new EntryCell { Label = "Text 11", Placeholder = "Placeholder 6" },
+ new EntryCell { Label = "Text 12" },
+ new EntryCell { Label = "Text 13", Placeholder = "Placeholder 7" },
+ new EntryCell { Label = "Text 14" },
+ new EntryCell { Label = "Text 15", Placeholder = "Placeholder 8" },
+ new EntryCell { Label = "Text 16" },
+ entryCell
+ };
+
+ var tableSectionTwo = new TableSection ("Section Two") {
+ new EntryCell { Label = "Text 17", Placeholder = "Placeholder 9" },
+ new EntryCell { Label = "Text 18" },
+ new EntryCell { Label = "Text 19", Placeholder = "Placeholder 10" },
+ new EntryCell { Label = "Text 20" },
+ new EntryCell { Label = "Text 21", Placeholder = "Placeholder 11" },
+ new EntryCell { Label = "Text 22" },
+ new EntryCell { Label = "Text 23", Placeholder = "Placeholder 12" },
+ new EntryCell { Label = "Text 24" },
+ new EntryCell { Label = "Text 25", Placeholder = "Placeholder 13" },
+ new EntryCell { Label = "Text 26" },
+ new EntryCell { Label = "Text 27", Placeholder = "Placeholder 14" },
+ new EntryCell { Label = "Text 28" },
+ new EntryCell { Label = "Text 29", Placeholder = "Placeholder 15" },
+ new EntryCell { Label = "Text 30" },
+ new EntryCell { Label = "Text 31", Placeholder = "Placeholder 16" },
+ new EntryCell { Label = "Text 32" },
+ };
+
+ var keyboards = new TableSection ("Keyboards") {
+ new EntryCell { Label = "Chat", Keyboard = Keyboard.Chat },
+ new EntryCell { Label = "Default", Keyboard = Keyboard.Default },
+ new EntryCell { Label = "Email", Keyboard = Keyboard.Email },
+ new EntryCell { Label = "Numeric", Keyboard = Keyboard.Numeric },
+ new EntryCell { Label = "Telephone", Keyboard = Keyboard.Telephone },
+ new EntryCell { Label = "Text", Keyboard = Keyboard.Text },
+ new EntryCell { Label = "Url", Keyboard = Keyboard.Url }
+ };
+
+ var root = new TableRoot ("Text Cell table") {
+ tableSection,
+ tableSectionTwo,
+ keyboards
+ };
+
+ var table = new TableView {
+ Root = root
+ };
+
+ Content = table;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ImageCellListPage.cs b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ImageCellListPage.cs
new file mode 100644
index 00000000..1f58a339
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ImageCellListPage.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Linq;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ public class ImageCellTest {
+ public object Text { get; set; }
+ public object TextColor { get; set; }
+ public object Detail { get; set; }
+ public object DetailColor { get; set; }
+ public object Image { get; set; }
+ }
+
+ public class ImageCellListPage : ContentPage
+ {
+
+ public ImageCellListPage ()
+ {
+ Title = "ImageCell List Gallery - Legacy";
+
+ Device.OnPlatform (iOS: () => {
+ if (Device.Idiom == TargetIdiom.Tablet) {
+ Padding = new Thickness (0, 0, 0, 60);
+ }
+ });
+
+ var dataTemplate = new DataTemplate (typeof (ImageCell));
+ var stringToImageSourceConverter = new GenericValueConverter (
+ obj => new FileImageSource {
+ File = (string) obj
+ }
+ );
+
+ dataTemplate.SetBinding (TextCell.TextProperty, new Binding ("Text"));
+ dataTemplate.SetBinding (TextCell.TextColorProperty, new Binding ("TextColor"));
+ dataTemplate.SetBinding (TextCell.DetailProperty, new Binding ("Detail"));
+ dataTemplate.SetBinding (TextCell.DetailColorProperty, new Binding ("DetailColor"));
+ dataTemplate.SetBinding (ImageCell.ImageSourceProperty, new Binding ("Image", converter: stringToImageSourceConverter));
+
+ Random rand = new Random(250);
+
+ var albums = new [] {
+ "crimsonsmall.jpg",
+ "oasissmall.jpg",
+ "cover1small.jpg"
+ };
+
+ var label = new Label { Text = "I have not been selected" };
+
+ var listView = new ListView {
+ AutomationId = "ImageCellListView",
+ ItemsSource = Enumerable.Range (0, 100).Select (i => new ImageCellTest {
+ Text = "Text " + i,
+ TextColor = i % 2 == 0 ? Color.Red : Color.Blue,
+ Detail = "Detail " + i,
+ DetailColor = i % 2 == 0 ? Color.Red : Color.Blue,
+ Image = albums[rand.Next(0,3)]
+ }),
+ ItemTemplate = dataTemplate
+ };
+
+ listView.ItemSelected += (sender, args) => label.Text = "I was selected";
+
+ Content = new StackLayout { Children = { label, listView } };
+
+ }
+ }
+
+ public class UrlImageCellListPage : ContentPage
+ {
+ public UrlImageCellListPage()
+ {
+ Device.OnPlatform (iOS: () => {
+ if (Device.Idiom == TargetIdiom.Tablet) {
+ Padding = new Thickness (0, 0, 0, 60);
+ }
+ });
+
+ var dataTemplate = new DataTemplate (typeof (ImageCell));
+ var stringToImageSourceConverter = new GenericValueConverter (
+ obj => new UriImageSource() {
+ Uri = new Uri ((string) obj)
+ });
+
+ dataTemplate.SetBinding (TextCell.TextProperty, new Binding ("Text"));
+ dataTemplate.SetBinding (TextCell.TextColorProperty, new Binding ("TextColor"));
+ dataTemplate.SetBinding (TextCell.DetailProperty, new Binding ("Detail"));
+ dataTemplate.SetBinding (TextCell.DetailColorProperty, new Binding ("DetailColor"));
+ dataTemplate.SetBinding (ImageCell.ImageSourceProperty,
+ new Binding ("Image", converter: stringToImageSourceConverter));
+
+ var albums = new List<string> ();
+ for (int i = 0; i < 30; i++) {
+ albums.Add (string.Format ("http://cdn.instructables.com/FCP/9TOJ/GCJ0ZQV5/FCP9TOJGCJ0ZQV5.MEDIUM.jpg?ticks={0}",i ));
+ }
+
+
+ var random = new Random();
+ var label = new Label { Text = "I have not been selected" };
+
+ var listView = new ListView {
+ AutomationId = "ImageUrlCellListView",
+ ItemsSource = Enumerable.Range (0, 300).Select (i => new ImageCellTest {
+ Text = "Text " + i,
+ TextColor = i % 2 == 0 ? Color.Red : Color.Blue,
+ Detail = "Detail " + i,
+ DetailColor = i % 2 == 0 ? Color.Red : Color.Blue,
+ Image = albums [random.Next (0, albums.Count - 1)]
+ }),
+ ItemTemplate = dataTemplate
+ };
+
+ listView.ItemSelected += (sender, args) => label.Text = "I was selected";
+
+ Content = new StackLayout { Children = { label, listView } };
+
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ImageCellTablePage.cs b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ImageCellTablePage.cs
new file mode 100644
index 00000000..2b941bfd
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ImageCellTablePage.cs
@@ -0,0 +1,68 @@
+namespace Xamarin.Forms.Controls
+{
+ public class ImageCellTablePage : ContentPage
+ {
+
+ public ImageCellTablePage ()
+ {
+ Title = "ImageCell Table Gallery - Legacy";
+
+ Device.OnPlatform (iOS: () => {
+ if (Device.Idiom == TargetIdiom.Tablet) {
+ Padding = new Thickness (0, 0, 0, 60);
+ }
+ });
+
+ var tableSection = new TableSection ("Section One") {
+ new ImageCell { Text = "Text 1", ImageSource = new FileImageSource { File = "crimson.jpg" } },
+ new ImageCell { Text = "Text 2", Detail = "Detail 1", ImageSource = new FileImageSource { File = "crimson.jpg" } },
+ new ImageCell { Text = "Text 3", ImageSource = new FileImageSource { File = "cover1.jpg" } },
+ new ImageCell { Text = "Text 4", Detail = "Detail 2", ImageSource = new FileImageSource { File = "cover1.jpg" } },
+ new ImageCell { Text = "Text 5", ImageSource = new FileImageSource { File = "oasis.jpg" } },
+ new ImageCell { Text = "Text 6", Detail = "Detail 3", ImageSource = new FileImageSource { File = "oasis.jpg" } },
+ new ImageCell { Text = "Text 7", ImageSource = new FileImageSource { File = "crimson.jpg" } },
+ new ImageCell { Text = "Text 8", Detail = "Detail 4", ImageSource = new FileImageSource { File = "crimson.jpg" } },
+ new ImageCell { Text = "Text 9", ImageSource = new FileImageSource { File = "cover1.jpg" } },
+ new ImageCell { Text = "Text 10", Detail = "Detail 5", ImageSource = new FileImageSource { File = "cover1.jpg" } },
+ new ImageCell { Text = "Text 11", ImageSource = new FileImageSource { File = "oasis.jpg" } },
+ new ImageCell { Text = "Text 12", Detail = "Detail 6", ImageSource = new FileImageSource { File = "oasis.jpg" } },
+ };
+
+ ImageCell imageCell = null;
+ imageCell = new ImageCell {
+ Text = "not tapped",
+ ImageSource = "oasis.jpg",
+ Command = new Command(()=>{
+ imageCell.Text = "tapped";
+ (imageCell.ImageSource as FileImageSource).File = "crimson.jpg";
+ })
+ };
+ var tableSectionTwo = new TableSection ("Section Two") {
+ new ImageCell { Text = "Text 13", ImageSource = new FileImageSource { File = "crimson.jpg" } },
+ new ImageCell { Text = "Text 14", Detail = "Detail 7", ImageSource = new FileImageSource { File = "crimson.jpg" } },
+ new ImageCell { Text = "Text 15", ImageSource = new FileImageSource { File = "cover1.jpg" } },
+ new ImageCell { Text = "Text 16", Detail = "Detail 8", ImageSource = new FileImageSource { File = "cover1.jpg" } },
+ new ImageCell { Text = "Text 17", ImageSource = new FileImageSource { File = "oasis.jpg" } },
+ new ImageCell { Text = "Text 18", Detail = "Detail 9", ImageSource = new FileImageSource { File = "oasis.jpg" } },
+ new ImageCell { Text = "Text 19", ImageSource = new FileImageSource { File = "crimson.jpg" } },
+ new ImageCell { Text = "Text 20", Detail = "Detail 10", ImageSource = new FileImageSource { File = "crimson.jpg" } },
+ new ImageCell { Text = "Text 21", ImageSource = new FileImageSource { File = "cover1.jpg" } },
+ new ImageCell { Text = "Text 22", Detail = "Detail 11", ImageSource = new FileImageSource { File = "cover1.jpg" } },
+ new ImageCell { Text = "Text 23", ImageSource = new FileImageSource { File = "oasis.jpg" } },
+ new ImageCell { Text = "Text 24", Detail = "Detail 12", ImageSource = new FileImageSource { File = "oasis.jpg" } },
+ imageCell,
+ };
+
+ var root = new TableRoot ("Text Cell table") {
+ tableSection,
+ tableSectionTwo
+ };
+
+ var table = new TableView {
+ Root = root,
+ };
+
+ Content = table;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ProductViewCell.cs b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ProductViewCell.cs
new file mode 100644
index 00000000..5973ebab
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ProductViewCell.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class ProductCellView : StackLayout
+ {
+ Label _timeLabel;
+ Label _brandLabel;
+ StackLayout _stack;
+ public ProductCellView (string text)
+ {
+ _stack = new StackLayout ();
+ _brandLabel = new Label {Text = "BrandLabel", HorizontalTextAlignment = TextAlignment.Center};
+ _stack.Children.Add (_brandLabel);
+
+
+ var frame = new Frame {
+ Content = _stack,
+ BackgroundColor = Device.OnPlatform (iOS: new Color (1), Android: new Color (0.2), WinPhone: new Color (0.2))
+ };
+ _timeLabel = new Label {
+ Text = text
+ };
+ Children.Add (_timeLabel);
+ Children.Add (frame);
+ Padding = new Size (20, 20);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/SwitchCellListPage.cs b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/SwitchCellListPage.cs
new file mode 100644
index 00000000..c2502339
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/SwitchCellListPage.cs
@@ -0,0 +1,47 @@
+using System.Linq;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ public class SwitchCellItem
+ {
+ public string Label { get; set; }
+ public bool SwitchOn { get; set; }
+ }
+
+ public class SwitchCellListPage : ContentPage
+ {
+ public SwitchCellListPage ()
+ {
+ Title = "SwitchCell List Gallery - Legacy";
+
+ Device.OnPlatform (iOS: () => {
+ if (Device.Idiom == TargetIdiom.Tablet) {
+ Padding = new Thickness (0, 0, 0, 60);
+ }
+ });
+
+ var dataTemplate = new DataTemplate (typeof (SwitchCell)) {
+ Bindings = {
+ {SwitchCell.TextProperty, new Binding ("Label")},
+ {SwitchCell.OnProperty, new Binding ("SwitchOn")},
+ }
+ };
+
+ var label = new Label { Text = "I have not been selected" };
+
+ var listView = new ListView {
+ ItemsSource = Enumerable.Range (0, 100).Select (i => new SwitchCellItem {
+ Label = "Label " + i,
+ SwitchOn = i % 2 == 0 ? false : true,
+ }),
+ ItemTemplate = dataTemplate
+ };
+
+ listView.ItemSelected += (sender, args) => label.Text = "I was selected.";
+
+ Content = new StackLayout { Children = { label, listView } };
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/SwitchCellTablePage.cs b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/SwitchCellTablePage.cs
new file mode 100644
index 00000000..a0deb8e6
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/SwitchCellTablePage.cs
@@ -0,0 +1,65 @@
+namespace Xamarin.Forms.Controls
+{
+ public class SwitchCellTablePage : ContentPage
+ {
+ public SwitchCellTablePage ()
+ {
+ Title = "SwitchCell Table Gallery - Legacy";
+
+ Device.OnPlatform (iOS: () => {
+ if (Device.Idiom == TargetIdiom.Tablet) {
+ Padding = new Thickness (0, 0, 0, 60);
+ }
+ });
+
+ var tableSection = new TableSection ("Section One") {
+ new SwitchCell { Text = "text 1", On = true },
+ new SwitchCell { Text = "text 2" },
+ new SwitchCell { Text = "text 3", On = true },
+ new SwitchCell { Text = "text 4", On = false },
+ new SwitchCell { Text = "text 5", On = true },
+ new SwitchCell { Text = "text 6" },
+ new SwitchCell { Text = "text 7", On = true },
+ new SwitchCell { Text = "text 8", On = false },
+ new SwitchCell { Text = "text 9", On = true },
+ new SwitchCell { Text = "text 10" },
+ new SwitchCell { Text = "text 11", On = true },
+ new SwitchCell { Text = "text 12", On = false },
+ new SwitchCell { Text = "text 13", On = true },
+ new SwitchCell { Text = "text 14" },
+ new SwitchCell { Text = "text 15", On = true },
+ new SwitchCell { Text = "text 16", On = false },
+ };
+
+ var tableSectionTwo = new TableSection ("Section Two") {
+ new SwitchCell { Text = "text 17", On = true },
+ new SwitchCell { Text = "text 18" },
+ new SwitchCell { Text = "text 19", On = true },
+ new SwitchCell { Text = "text 20", On = false },
+ new SwitchCell { Text = "text 21", On = true },
+ new SwitchCell { Text = "text 22" },
+ new SwitchCell { Text = "text 23", On = true },
+ new SwitchCell { Text = "text 24", On = false },
+ new SwitchCell { Text = "text 25", On = true },
+ new SwitchCell { Text = "text 26" },
+ new SwitchCell { Text = "text 27", On = true },
+ new SwitchCell { Text = "text 28", On = false },
+ new SwitchCell { Text = "text 29", On = true },
+ new SwitchCell { Text = "text 30" },
+ new SwitchCell { Text = "text 31", On = true },
+ new SwitchCell { Text = "text 32", On = false },
+ };
+
+ var root = new TableRoot ("Text Cell table") {
+ tableSection,
+ tableSectionTwo
+ };
+
+ var table = new TableView {
+ Root = root,
+ };
+
+ Content = table;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/TextCellListPage.cs b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/TextCellListPage.cs
new file mode 100644
index 00000000..fbd5e265
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/TextCellListPage.cs
@@ -0,0 +1,48 @@
+using System.Linq;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ public class TextCellTest {
+ public object Text { get; set; }
+ public object TextColor { get; set; }
+ public object Detail { get; set; }
+ public object DetailColor { get; set; }
+ }
+
+ public class TextCellListPage : ContentPage
+ {
+ public TextCellListPage ()
+ {
+ Title = "TextCell List Gallery - Legacy";
+
+ Device.OnPlatform (iOS: () => {
+ if (Device.Idiom == TargetIdiom.Tablet) {
+ Padding = new Thickness (0, 0, 0, 60);
+ }
+ });
+
+ var label = new Label { Text = "Not Selected" };
+
+ var dataTemplate = new DataTemplate (typeof (TextCell));
+ dataTemplate.SetBinding (TextCell.TextProperty, new Binding ("Text"));
+ dataTemplate.SetBinding (TextCell.TextColorProperty, new Binding ("TextColor"));
+ dataTemplate.SetBinding (TextCell.DetailProperty, new Binding ("Detail"));
+ dataTemplate.SetBinding (TextCell.DetailColorProperty, new Binding ("DetailColor"));
+
+ var listView = new ListView {
+ ItemsSource = Enumerable.Range (0, 100).Select (i => new TextCellTest {
+ Text = "Text " + i,
+ TextColor = i % 2 == 0 ? Color.Red : Color.Blue,
+ Detail = "Detail " + i,
+ DetailColor = i % 2 == 0 ? Color.Red : Color.Blue
+ }),
+ ItemTemplate = dataTemplate
+ };
+
+ listView.ItemSelected += (sender, args) => { label.Text = "I was selected"; };
+
+ Content = new StackLayout { Children = { label, listView } };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/TextCellTablePage.cs b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/TextCellTablePage.cs
new file mode 100644
index 00000000..b9cc0cf3
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/TextCellTablePage.cs
@@ -0,0 +1,58 @@
+namespace Xamarin.Forms.Controls
+{
+ public class TextCellTablePage : ContentPage
+ {
+
+ public TextCellTablePage ()
+ {
+ Title = "TextCell Table Gallery - Legacy";
+
+ Device.OnPlatform (iOS: () => {
+ if (Device.Idiom == TargetIdiom.Tablet) {
+ Padding = new Thickness (0, 0, 0, 60);
+ }
+ });
+
+ var tableSection = new TableSection ("Section One") {
+ new TextCell { Text = "Text 1" },
+ new TextCell { Text = "Text 2", Detail = "Detail 1" },
+ new TextCell { Text = "Text 3" },
+ new TextCell { Text = "Text 4", Detail = "Detail 2" },
+ new TextCell { Text = "Text 5" },
+ new TextCell { Text = "Text 6", Detail = "Detail 3" },
+ new TextCell { Text = "Text 7" },
+ new TextCell { Text = "Text 8", Detail = "Detail 4" },
+ new TextCell { Text = "Text 9" },
+ new TextCell { Text = "Text 10", Detail = "Detail 5" },
+ new TextCell { Text = "Text 11" },
+ new TextCell { Text = "Text 12", Detail = "Detail 6" }
+ };
+
+ var tableSectionTwo = new TableSection ("Section Two") {
+ new TextCell { Text = "Text 13" },
+ new TextCell { Text = "Text 14", Detail = "Detail 7" },
+ new TextCell { Text = "Text 15" },
+ new TextCell { Text = "Text 16", Detail = "Detail 8" },
+ new TextCell { Text = "Text 17" },
+ new TextCell { Text = "Text 18", Detail = "Detail 9" },
+ new TextCell { Text = "Text 19" },
+ new TextCell { Text = "Text 20", Detail = "Detail 10" },
+ new TextCell { Text = "Text 21" },
+ new TextCell { Text = "Text 22", Detail = "Detail 11" },
+ new TextCell { Text = "Text 23" },
+ new TextCell { Text = "Text 24", Detail = "Detail 12" }
+ };
+
+ var root = new TableRoot ("Text Cell table") {
+ tableSection,
+ tableSectionTwo
+ };
+
+ var table = new TableView {
+ Root = root,
+ };
+
+ Content = table;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/UnEvenViewCellGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/UnEvenViewCellGallery.cs
new file mode 100644
index 00000000..00c2980f
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/UnEvenViewCellGallery.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class UnevenViewCellGallery : ContentPage
+ {
+ public UnevenViewCellGallery ()
+ {
+ Title = "UnevenViewCell Gallery - Legacy";
+
+ var map = MapGallery.MakeMap ();
+ map.HasScrollEnabled = false;
+
+ Content = new TableView {
+ RowHeight = 150,
+ HasUnevenRows = true,
+ Root = new TableRoot {
+ new TableSection ("Testing") {
+ new ViewCell {View = map, Height = 250},
+ new ViewCell {View = new ProductCellView ("1 day")},
+ new ViewCell {View = new ProductCellView ("2 days")},
+ new ViewCell {View = new ProductCellView ("3 days")},
+ new ViewCell {View = new ProductCellView ("4 days")},
+ new ViewCell {View = new ProductCellView ("5 days")}
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ViewCellGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ViewCellGallery.cs
new file mode 100644
index 00000000..099a786a
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/CellsGalleries/ViewCellGallery.cs
@@ -0,0 +1,115 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class ViewCellGallery : ContentPage
+ {
+ public ViewCellGallery ()
+ {
+ Title = "ViewCell Gallery - Legacy";
+
+ Content = new TableView {
+ RowHeight = 150,
+ Root = new TableRoot {
+ new TableSection ("Testing") {
+ new ViewCell {View = new ProductCellView ("0")},
+ new ViewCell {View = new ProductCellView ("1")},
+ new ViewCell {View = new ProductCellView ("2")},
+ new ViewCell {View = new ProductCellView ("3")},
+ new ViewCell {View = new ProductCellView ("4")}
+ }
+ }
+ };
+ }
+ }
+
+ public class UrlImageViewCellListPage : ContentPage
+ {
+ public UrlImageViewCellListPage()
+ {
+ Device.OnPlatform (iOS: () => {
+ if (Device.Idiom == TargetIdiom.Tablet) {
+ Padding = new Thickness (0, 0, 0, 60);
+ }
+ });
+
+ var stringToImageSourceConverter = new GenericValueConverter (
+ obj => new UriImageSource() {
+ Uri = new Uri ((string) obj)
+ });
+
+ var dataTemplate = new DataTemplate (() => {
+ var cell = new ViewCell();
+
+ var image = new Image();
+ image.SetBinding (Image.SourceProperty, new Binding ("Image", converter: stringToImageSourceConverter));
+ image.WidthRequest = 160;
+ image.HeightRequest = 160;
+
+ var text = new Label();
+ text.SetBinding (Label.TextProperty, new Binding ("Text"));
+ text.SetBinding (Label.TextColorProperty, new Binding ("TextColor"));
+
+ cell.View = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ image,
+ text
+ }
+ };
+
+ return cell;
+ });
+
+ var albums = new[] {
+ "https://evolve.xamarin.com/images/sessions/joseph-mayo-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/jon-skeet-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/rachel-reese-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/mike-james-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/daniel-cazzulino-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/michael-hutchinson-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/laurent-bugnion-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/craig-dunn-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/charles-petzold-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/jason-smith-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/frank-krueger-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/james-clancey-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/daniel-plaisted-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/jesse-liberty-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/miguel-de-icaza-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/rene-ruppert-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/brent-schooley-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/adrian-stevens-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/rodrigo-kumpera-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/alex-corrado-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/jonathan-pryor-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/michael-stonis-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/jeremie-laval-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/james-montemagno-icon.jpg",
+ "https://evolve.xamarin.com/images/sessions/brett-duncavage-icon.jpg"
+ };
+
+ var label = new Label { Text = "I have not been selected" };
+
+ var listView = new ListView {
+ ItemsSource = Enumerable.Range (0, albums.Length).Select (i => new {
+ Text = "Text " + i,
+ TextColor = i % 2 == 0 ? Color.Red : Color.Blue,
+ Detail = "Detail " + i,
+ DetailColor = i % 2 == 0 ? Color.Red : Color.Blue,
+ Image = albums[i]
+ }),
+ ItemTemplate = dataTemplate
+ };
+
+ listView.ItemSelected += (sender, args) => label.Text = "I was selected";
+
+ Content = new StackLayout { Children = { label, listView } };
+
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/ClipToBoundsGallery.cs b/Xamarin.Forms.Controls/GalleryPages/ClipToBoundsGallery.cs
new file mode 100644
index 00000000..b7cdd8fb
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/ClipToBoundsGallery.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class ClipToBoundsGallery : ContentPage
+ {
+ public ClipToBoundsGallery ()
+ {
+ var child1 = new BoxView { Color = Color.Red };
+ var child2 = new BoxView { Color = Color.Blue };
+ var button = new Button { Text = "Clip", BackgroundColor = Color.Green };
+
+ Padding = new Thickness (55);
+ var layout = new AbsoluteLayout {
+ Children = {
+ {child1, new Rectangle (-50, 0, 100, 100)},
+ {child2, new Rectangle (0, -50, 100, 100)},
+ {button, new Rectangle (1.0, 0.5, 100, 100), AbsoluteLayoutFlags.PositionProportional}
+ }
+ };
+
+ button.Clicked += (sender, args) => layout.IsClippedToBounds = !layout.IsClippedToBounds;
+
+ Content = layout;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/ControlTemplatePage.cs b/Xamarin.Forms.Controls/GalleryPages/ControlTemplatePage.cs
new file mode 100644
index 00000000..32eb2a19
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/ControlTemplatePage.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls.GalleryPages
+{
+ internal class ControlTemplatePage : ContentPage
+ {
+ [Preserve (AllMembers = true)]
+ class MyLayout : StackLayout
+ {
+ public MyLayout ()
+ {
+ Children.Add (new Label {Text = "Before"});
+ Children.Add (new ContentPresenter ());
+ Children.Add (new Label {Text = "After"});
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ class MyOtherLayout : StackLayout
+ {
+ public MyOtherLayout ()
+ {
+ Children.Add (new Entry {Text = "Before"});
+ Children.Add (new ContentPresenter ());
+ Children.Add (new Entry {Text = "After"});
+ }
+ }
+
+ public ControlTemplatePage ()
+ {
+ var button = new Button { Text = "Replace Template" };
+ var content = new ContentView {
+ Content = button,
+ ControlTemplate = new ControlTemplate (typeof (MyLayout))
+ };
+
+ button.Clicked += (sender, args) => {
+ content.ControlTemplate = new ControlTemplate (typeof (MyOtherLayout));
+ };
+
+ Content = content;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/ControlTemplateXamlPage.xaml b/Xamarin.Forms.Controls/GalleryPages/ControlTemplateXamlPage.xaml
new file mode 100644
index 00000000..38ad4753
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/ControlTemplateXamlPage.xaml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Controls.GalleryPages.ControlTemplateXamlPage">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <ControlTemplate x:Key="ViewTemplate">
+ <StackLayout>
+ <Label Text="{TemplateBinding Parent.AboveText}" />
+ <ContentPresenter />
+ <Label Text="Below" />
+ </StackLayout>
+ </ControlTemplate>
+ <Style TargetType="ContentView">
+ <Style.Setters>
+ <Setter Property="ControlTemplate" Value="{StaticResource ViewTemplate}" />
+ </Style.Setters>
+ </Style>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ <ContentView>
+ <Label Text="I R CONTENT" />
+ </ContentView>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/GalleryPages/ControlTemplateXamlPage.xaml.cs b/Xamarin.Forms.Controls/GalleryPages/ControlTemplateXamlPage.xaml.cs
new file mode 100644
index 00000000..b329ea12
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/ControlTemplateXamlPage.xaml.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Controls.GalleryPages
+{
+ public partial class ControlTemplateXamlPage : ContentPage
+ {
+ public static readonly BindableProperty AboveTextProperty =
+ BindableProperty.Create (nameof (AboveText), typeof (string), typeof (ControlTemplateXamlPage), null);
+
+ public string AboveText
+ {
+ get { return (string)GetValue (AboveTextProperty); }
+ set { SetValue (AboveTextProperty, value); }
+ }
+
+ public ControlTemplateXamlPage ()
+ {
+ BindingContext = new {
+ Text = "Testing 123"
+ };
+ this.SetBinding (AboveTextProperty, "Text");
+ InitializeComponent ();
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/DisposeGallery.cs b/Xamarin.Forms.Controls/GalleryPages/DisposeGallery.cs
new file mode 100644
index 00000000..910c1af7
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/DisposeGallery.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class DisposeGallery : ContentPage
+ {
+ public DisposeGallery ()
+ {
+ var disposePage = new DisposePage ();
+
+ var pushButton = new Button {Text = "Push disposable page"};
+ var pushModalButton = new Button {Text = "PushModal disposable page"};
+
+ pushButton.Clicked += (sender, args) => {
+ disposePage.PopAction = () => Navigation.PopAsync ();
+ Navigation.PushAsync (disposePage);
+ };
+ pushModalButton.Clicked += (sender, args) => {
+ disposePage.PopAction = () => Navigation.PopModalAsync ();
+ Navigation.PushModalAsync (disposePage);
+ };
+
+ var appearingLabel = new Label {Text = "Appearing not sent"};
+ var disappearingLabel = new Label {Text = "Disappearing not sent"};
+
+ var disposedPageLabel = new Label {Text = "Page renderer not yet disposed"};
+ var disposedLabelsLabel = new Label {Text = "Number of disposed labels: 0"};
+
+ disposePage.Appearing += (sender, args) => appearingLabel.Text = "Appearing sent";
+ disposePage.Disappearing += (sender, args) => disappearingLabel.Text = "Disappearing sent";
+ disposePage.RendererDisposed += (sender, args) => {
+ disposedPageLabel.Text = "Page renderer disposed";
+ // give some time for this to propogate
+ Device.StartTimer (TimeSpan.FromSeconds (1), () => {
+ disposedLabelsLabel.Text = "Number of disposed labels: " + disposePage.DisposedLabelCount;
+ return false;
+ });
+
+ };
+
+ Content = new StackLayout {
+ Padding = new Thickness (20),
+ Children = {
+ pushButton,
+ pushModalButton,
+ appearingLabel,
+ disappearingLabel,
+ disposedLabelsLabel,
+ disposedPageLabel
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/EditableList.cs b/Xamarin.Forms.Controls/GalleryPages/EditableList.cs
new file mode 100644
index 00000000..2a7b1a85
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/EditableList.cs
@@ -0,0 +1,116 @@
+using System.Collections.ObjectModel;
+using System.Windows.Input;
+using System.Linq;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class MessagesViewModel : ViewModelBase
+ {
+ public MessagesViewModel()
+ {
+ Messages = new ObservableCollection<MessageViewModel> (Enumerable.Range (0, 100).Select (i => {
+ return new MessageViewModel { Subject = "Subject Line " + i, MessagePreview = "Lorem ipsum dolorem monkeys bonkers " + i };
+ }));
+
+ MessagingCenter.Subscribe<MessageViewModel, MessageViewModel> (this, "DeleteMessage", (vm, vm2) => {
+ Messages.Remove (vm);
+ });
+ }
+
+ public ObservableCollection<MessageViewModel> Messages
+ {
+ get;
+ private set;
+ }
+ }
+
+ [Preserve (AllMembers = true)]
+ internal class MessageViewModel : ViewModelBase
+ {
+ public MessageViewModel()
+ {
+ Delete = new Command (() => MessagingCenter.Send (this, "DeleteMessage", this));
+ Move = new Command (() => MessagingCenter.Send (this, "MoveMessage", this));
+ }
+
+ public string Subject
+ {
+ get;
+ set;
+ }
+
+ public string MessagePreview
+ {
+ get;
+ set;
+ }
+
+ public ICommand Delete
+ {
+ get;
+ private set;
+ }
+
+ public ICommand Move
+ {
+ get;
+ private set;
+ }
+ }
+
+ internal class ContextActionsGallery : ContentPage
+ {
+ class MessageCell : TextCell
+ {
+ public MessageCell()
+ {
+ this.SetBinding (TextProperty, "Subject");
+ this.SetBinding (DetailProperty, "MessagePreview");
+
+ var delete = new MenuItem { Text = "Delete", IsDestructive = true };
+ delete.SetBinding (MenuItem.CommandProperty, "Delete");
+
+ var mark = new MenuItem { Text = "Mark", Icon = "calculator.png" };
+ var move = new MenuItem { Text = "Move" };
+
+ //move.Clicked += async (sender, e) => await Navigation.PopAsync();
+
+ ContextActions.Add (mark);
+ ContextActions.Add (delete);
+ ContextActions.Add (move);
+
+ var clear = new MenuItem { Text = "Clear Items" };
+ clear.Clicked += (sender, args) => ContextActions.Clear();
+ ContextActions.Add (clear);
+ }
+ }
+
+ public ContextActionsGallery (bool tableView = false)
+ {
+ BindingContext = new MessagesViewModel();
+
+ View list;
+ if (!tableView) {
+ list = new ListView();
+ list.SetBinding (ListView.ItemsSourceProperty, "Messages");
+ ((ListView)list).ItemTemplate = new DataTemplate (typeof (MessageCell));
+ } else {
+ var section = new TableSection();
+ section.Add (new TextCell { Text = "I have no ContextActions", Detail = "Sup" });
+ foreach (var msg in ((MessagesViewModel) BindingContext).Messages) {
+ section.Add (new MessageCell { BindingContext = msg });
+ }
+
+ list = new TableView();
+ ((TableView)list).Root = new TableRoot { section };
+ }
+
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = "Email" },
+ list
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/EditorGallery.cs b/Xamarin.Forms.Controls/GalleryPages/EditorGallery.cs
new file mode 100644
index 00000000..fde03236
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/EditorGallery.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class EditorGallery : ContentPage
+ {
+ public EditorGallery ()
+ {
+ var cellTemplate = new DataTemplate (typeof (TextCell));
+ cellTemplate.SetBinding (TextCell.TextProperty, new Binding ("Title"));
+
+ var list = new ListView {
+ ItemsSource = new ContentPage [] {
+ new EditorGalleryPage ("Default Keyboard", Keyboard.Default),
+ new EditorGalleryPage ("Chat Keyboard", Keyboard.Chat),
+ new EditorGalleryPage ("Text Keyboard", Keyboard.Text),
+ new EditorGalleryPage ("Url Keyboard", Keyboard.Url),
+ new EditorGalleryPage ("Numeric Keyboard", Keyboard.Numeric),
+ new EditableEditorPage ("Enabled", true),
+ new EditableEditorPage ("Disabled", false),
+
+ },
+ ItemTemplate = cellTemplate
+ };
+
+ list.ItemSelected += (sender, arg) => {
+ if (list.SelectedItem != null) {
+ Navigation.PushAsync ((ContentPage)list.SelectedItem);
+ list.SelectedItem = null;
+ }
+ };
+
+ Content = list;
+ }
+ }
+
+ internal class EditableEditorPage : ContentPage
+ {
+ public EditableEditorPage (string title, bool enabled)
+ {
+ Title = "Editable " + enabled.ToString ();
+ Padding = new Thickness (20);
+ var editor = new Editor {
+ Text = Title,
+ IsEnabled = enabled,
+ HeightRequest = 75,
+ };
+
+ var disableButton = new Button {
+ Text = "Disable Editor",
+ };
+
+ var enableButton = new Button {
+ Text = "Enable Editor",
+ };
+
+ disableButton.Clicked += (object sender, EventArgs e) => {
+ editor.IsEnabled = false;
+ };
+
+ enableButton.Clicked += (object sender, EventArgs e) => {
+ editor.IsEnabled = true;
+ };
+
+ Content = new StackLayout {
+ Children = { editor, disableButton, enableButton, }
+ };
+ }
+ }
+
+ public class EditorGalleryPage : ContentPage
+ {
+ public EditorGalleryPage (string title, Keyboard keyboard)
+ {
+ Title = title;
+ BackgroundColor = Color.Red;
+ Padding = new Thickness (20);
+
+ var label = new Label {
+ Text = "Nothing entered"
+ };
+
+ var label2 = new Label {
+ Text = ""
+ };
+
+ var editor = new Editor {
+ HeightRequest = 75,
+ Keyboard = keyboard,
+ Text = "PlaceHolder",
+ };
+
+ editor.Completed += (sender, e) => {
+ label.Text = "Entered : " + editor.Text;
+ };
+
+ editor.TextChanged += (sender, e) => {
+ label2.Text += "x";
+ };
+
+ var unfocus = new Button {
+ Text = "Unfocus",
+ };
+
+ var focus = new Button {
+ Text = "Focus",
+ };
+
+ unfocus.Clicked += (sender, e) => {
+ editor.Unfocus();
+ };
+
+ focus.Clicked += (sender, e) => {
+ editor.Focus();
+ };
+
+ Content = new StackLayout {
+ Children = {
+ label,
+ label2,
+ editor,
+ focus,
+ unfocus,
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/EntryGallery.cs b/Xamarin.Forms.Controls/GalleryPages/EntryGallery.cs
new file mode 100644
index 00000000..5fcf7b83
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/EntryGallery.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class EntryGallery : ContentPage
+ {
+ public EntryGallery ()
+ {
+ var label = new Label { Text = "Enter something in Normal" };
+ var label2 = new Label { Text = "No typing has happened in Normal yet" };
+ var normal = new Entry { Placeholder = "Normal" };
+ var password = new Entry { Placeholder = "Password" };
+ var numericPassword = new Entry { Placeholder = "Numeric Password" };
+ var activation = new Entry { Placeholder = "Activation" };
+ var disabled = new Entry { Placeholder = "Disabled" };
+ var transparent = new Entry { Placeholder = "Transparent" };
+
+ var isFocusedlabel = new Label {
+ Text = "Focus an Entry"
+ };
+
+ var changeKeyboardType = new Entry {
+ Placeholder = "Keyboard.Default",
+ Keyboard = Keyboard.Default
+ };
+
+ changeKeyboardType.Completed += (sender, e) => {
+ changeKeyboardType.Placeholder = "Keyboard.Numeric";
+ changeKeyboardType.Keyboard = Keyboard.Numeric;
+ };
+
+ normal.TextChanged += (s, e) => label2.Text = "You typed in normal";
+
+ normal.Focused += (s, e) => isFocusedlabel.Text = "Normal Focused";
+ normal.Completed += (s, e) => { label.Text = normal.Text; };
+ password.Focused += (s, e) => isFocusedlabel.Text = "Password Focused";
+ numericPassword.Focused += (s, e) => isFocusedlabel.Text = "Numeric Password Focused";
+ activation.Focused += (s, e) => isFocusedlabel.Text = "Activation Focused";
+ disabled.Focused += (s, e) => isFocusedlabel.Text = "Disabled Focused";
+ transparent.Focused += (s, e) => isFocusedlabel.Text = "Transparent Focused";
+ changeKeyboardType.Focused += (s, e) => isFocusedlabel.Text = "Keyboard.Default Focused";
+
+ var toggleColorButton = new Button { Text = "Toggle Text Color" };
+ var changeSecureButton = new Button { Text = "Toggle Secure" };
+ var changePlaceholderButton = new Button { Text = "Change Placeholder" };
+ var focusNormalButton = new Button { Text = "Focus First" };
+
+ transparent.Opacity = 0.5;
+ password.IsPassword = true;
+ numericPassword.IsPassword = true;
+ numericPassword.Keyboard = Keyboard.Numeric;
+ activation.Completed += (sender, e) => activation.Text = "Activated";
+ disabled.IsEnabled = false;
+
+ toggleColorButton.Clicked += (sender, e) => {
+ if (normal.TextColor == Color.Default) {
+ normal.TextColor = Color.Red;
+ password.TextColor = Color.Red;
+ numericPassword.TextColor = Color.Red;
+ } else {
+ normal.TextColor = Color.Default;
+ password.TextColor = Color.Default;
+ numericPassword.TextColor = Color.Default;
+ }
+ };
+
+ changeSecureButton.Clicked += (sender, e) => {
+ password.IsPassword = !password.IsPassword;
+ numericPassword.IsPassword = !numericPassword.IsPassword;
+ };
+
+ int i = 1;
+ changePlaceholderButton.Clicked += (sender, e) => { normal.Placeholder = "Placeholder " + i++.ToString (); };
+
+ focusNormalButton.Clicked += (sender, args) => normal.Focus ();
+
+ Content = new ScrollView {
+ Content = new StackLayout {
+ Padding = new Thickness (80),
+ Children = {
+ label,
+ label2,
+ normal,
+ password,
+ numericPassword,
+ disabled,
+ isFocusedlabel,
+ activation,
+ transparent,
+ changeKeyboardType,
+ toggleColorButton,
+ changeSecureButton,
+ changePlaceholderButton,
+ focusNormalButton,
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/FrameGallery.cs b/Xamarin.Forms.Controls/GalleryPages/FrameGallery.cs
new file mode 100644
index 00000000..ee7c1822
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/FrameGallery.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class FrameGallery : ContentPage
+ {
+ readonly StackLayout _stack;
+
+ public FrameGallery ()
+ {
+ Content = _stack = new StackLayout { Padding = new Size (20, 20) };
+
+ //BackgroundColor = new Color (0.5, 0.5, 0.5);
+ BackgroundColor = Color.FromHex ("#8a2be2");
+ //BackgroundColor = Color.Aqua;
+
+ var frame = new Frame {
+ Content = new Button {
+ Text = "Framous!"
+ },
+ BackgroundColor = Device.OnPlatform (iOS: new Color (1), Android: new Color (0), WinPhone: new Color (0)),
+ VerticalOptions = LayoutOptions.FillAndExpand
+ };
+
+ _stack.Children.Add (frame);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/GridGallery.cs b/Xamarin.Forms.Controls/GalleryPages/GridGallery.cs
new file mode 100644
index 00000000..d786a81b
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/GridGallery.cs
@@ -0,0 +1,174 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+
+ public class GridGallery : ContentPage
+ {
+ public GridGallery ()
+ {
+ var layout = new StackLayout {
+ Orientation = StackOrientation.Vertical
+ };
+
+ //ColumnTypes
+ layout.Children.Add (new Label { Text = "Column Types:" });
+ var grid = new Grid {
+ ColumnDefinitions = {
+ new ColumnDefinition { Width = 80 },
+ new ColumnDefinition (),
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) }
+ },
+ BackgroundColor = Color.FromRgb (0xee, 0xee, 0xee)
+ };
+
+ grid.Children.Add (new Label {
+ Text = "Absolute Width",
+ BackgroundColor = Color.FromRgb (0xcc, 0xcc, 0xcc),
+ }, 0, 0);
+ grid.Children.Add (new Label {
+ Text = "Auto Width",
+ BackgroundColor = Color.FromRgb (0xcc, 0xcc, 0xcc),
+ }, 1, 0);
+ grid.Children.Add (new Label {
+ Text = "Star",
+ BackgroundColor = Color.FromRgb (0xcc, 0xcc, 0xcc),
+ }, 2, 0);
+ layout.Children.Add (grid);
+
+ //Star
+ layout.Children.Add (new Label { Text = "Star Columns:" });
+ grid = new Grid {
+ ColumnDefinitions = {
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength (2, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength (3, GridUnitType.Star) },
+ },
+ BackgroundColor = Color.FromRgb (0xee, 0xee, 0xee),
+ ColumnSpacing = 0,
+ RowSpacing = 0,
+ };
+
+ grid.Children.Add (new Label {
+ Text = "*",
+ BackgroundColor = Color.FromRgb (0xcc, 0xcc, 0xcc),
+ }, 0, 0);
+ grid.Children.Add (new Label {
+ Text = "**",
+ BackgroundColor = Color.FromRgb (0xcc, 0xcc, 0xcc),
+ }, 1, 0);
+ grid.Children.Add (new Label {
+ Text = "***",
+ BackgroundColor = Color.FromRgb (0xcc, 0xcc, 0xcc),
+ }, 2, 0);
+ layout.Children.Add (grid);
+
+ //Alignment
+ layout.Children.Add (new Label { Text = "Alignment:" });
+ grid = new Grid {
+ ColumnDefinitions = {
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ },
+ BackgroundColor = Color.FromRgb (0xee, 0xee, 0xee)
+ };
+
+ grid.Children.Add (new Label {
+ Text = "Right",
+ BackgroundColor = Color.FromRgb (0xcc, 0xcc, 0xcc),
+ HorizontalOptions = LayoutOptions.End,
+ }, 0, 0);
+ grid.Children.Add (new Label {
+ Text = "Center",
+ BackgroundColor = Color.FromRgb (0xcc, 0xcc, 0xcc),
+ HorizontalOptions = LayoutOptions.Center,
+
+ }, 1, 0);
+ grid.Children.Add (new Label {
+ Text = "Left",
+ BackgroundColor = Color.FromRgb (0xcc, 0xcc, 0xcc),
+ HorizontalOptions = LayoutOptions.Start,
+ }, 2, 0);
+ grid.Children.Add (new Label {
+ Text = "Fill",
+ BackgroundColor = Color.FromRgb (0xcc, 0xcc, 0xcc),
+ HorizontalOptions = LayoutOptions.Fill,
+ }, 3, 0);
+ layout.Children.Add (grid);
+
+ //Spanning
+ layout.Children.Add (new Label { Text = "Spans:" });
+ grid = new Grid {
+ ColumnDefinitions = {
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ },
+ BackgroundColor = Color.FromRgb (0xee, 0xee, 0xee),
+ ColumnSpacing = 0,
+ RowSpacing = 0
+ };
+
+ for (var i=0;i<5;i++)
+ for (var j=0;j<5;j++)
+ grid.Children.Add (new Label {
+ Text = "Unit",
+ BackgroundColor = Color.FromRgb (0xcc, 0xcc, 0xcc),
+ }, i, j);
+
+
+ grid.Children.Add (new Label {
+ Text = "Spanning 4 columns",
+ BackgroundColor = Color.Red,
+ }, 0,4,0,1);
+ grid.Children.Add (new Label {
+ Text = "Spanning 3 rows",
+ BackgroundColor = Color.Gray,
+ }, 4,5, 0,3);
+ grid.Children.Add (new Label {
+ Text = "a block 3x3",
+ BackgroundColor = Color.Green,
+ }, 1,4,1,4);
+ layout.Children.Add (grid);
+
+
+ //Change Width
+ var col0 = new ColumnDefinition { Width = 40 };
+ var col1 = new ColumnDefinition { Width = 80 };
+
+ grid = new Grid {
+ ColumnDefinitions = new ColumnDefinitionCollection {
+ col0, col1
+ }
+ };
+
+ grid.Children.Add (new BoxView { BackgroundColor = Color.Red });
+ grid.Children.Add (new BoxView { BackgroundColor = Color.Blue },1,0);
+
+ layout.Children.Add (grid);
+ layout.Children.Add (new Button {
+ Text = "ChangeWidth",
+ Command = new Command (()=>{
+ var t = col0.Width;
+ col0.Width = col1.Width;
+ col1.Width = t;
+ })
+ });
+
+ Content = new ScrollView {
+ Content = layout,
+ };
+
+
+
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/GroupedListActionsGallery.cs b/Xamarin.Forms.Controls/GalleryPages/GroupedListActionsGallery.cs
new file mode 100644
index 00000000..3d8b85c9
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/GroupedListActionsGallery.cs
@@ -0,0 +1,282 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class GroupedListActionsGallery
+ : ContentPage
+ {
+ class Group
+ : ObservableList<GroupAction>, INotifyPropertyChanged
+ {
+ public Group (string name)
+ {
+ if (name == null)
+ throw new ArgumentNullException ("name");
+
+ Name = name;
+ ShortName = Name[0].ToString();
+ }
+
+ string _name;
+ string _shortName;
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public string Name
+ {
+ get { return _name; }
+ set
+ {
+ if (_name == value)
+ return;
+
+ _name = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public string ShortName
+ {
+ get { return _shortName; }
+ set
+ {
+ if (_shortName == value)
+ return;
+
+ _shortName = value;
+ OnPropertyChanged();
+ }
+ }
+
+ protected override void InsertItem (int index, GroupAction item)
+ {
+ item.Parent = this;
+ base.InsertItem (index, item);
+ }
+
+ void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+
+ class GroupAction
+ {
+ readonly Action<GroupAction> _action;
+
+ public GroupAction (string name, Action<GroupAction> action = null)
+ {
+ if (name == null)
+ throw new ArgumentNullException ("name");
+
+ Name = name;
+ _action = action;
+ }
+
+ public string Name
+ {
+ get;
+ private set;
+ }
+
+ public void DoStuff()
+ {
+ if (_action == null)
+ return;
+
+ _action (this);
+ }
+
+ public Group Parent
+ {
+ get;
+ set;
+ }
+ }
+
+ readonly ListView _list = new ListView {
+ IsGroupingEnabled = true,
+ GroupHeaderTemplate = new DataTemplate(() => {
+ var label = new Label {
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ TextColor = Color.Red
+ };
+
+ label.SetBinding (Label.TextProperty, "Name");
+
+ return new ViewCell {
+ View = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ new Image {
+ Source = ImageSource.FromFile ("cover1.jpg"),
+ HeightRequest = 20,
+ WidthRequest = 20
+ },
+
+ label,
+ }
+ }
+ };
+ }),
+
+ ItemTemplate = new DataTemplate (() => {
+ var c = new TextCell();
+ c.SetBinding (TextCell.TextProperty, "Name");
+ return c;
+ })
+ };
+
+ readonly ObservableList<Group> _groups;
+
+ ObservableList<Group> CreateItemSource()
+ {
+ return new ObservableList<Group> {
+ new Group ("General") {
+ new GroupAction ("Change group name", ga => ga.Parent.Name += " (changed)"),
+ new GroupAction ("Change group short name", ga => ga.Parent.ShortName = ga.Parent.Name[1].ToString())
+ },
+
+ new Group ("Child item actions") {
+ new GroupAction ("Clear this group", ga => ga.Parent.Clear()),
+ new GroupAction ("Insert group item", ga => ga.Parent.Insert (1, new GroupAction ("Inserted item S"))),
+ new GroupAction ("Insert 2 group items", ga => ga.Parent.InsertRange (1, GetGroupActions ("Inserted item D", 2))),
+ new GroupAction ("Remove next item", ga => ga.Parent.Remove (ga.Parent[GetIndexOfDummy (ga)])),
+ new GroupAction ("Dummy item RDI"),
+ new GroupAction ("Remove next 2 dummy items", ga => ga.Parent.RemoveRange (GetNextDummyItems (ga, 2))),
+ new GroupAction ("Dummy item RmDI-1"),
+ new GroupAction ("Dummy item RmDI-2"),
+ new GroupAction ("Replace dummy item", ga => ga.Parent[GetIndexOfDummy(ga)] = new GroupAction ("Replaced item")),
+ new GroupAction ("Dummy item RpDI"),
+ new GroupAction ("Replace next two dummy items", ga =>
+ ga.Parent.ReplaceRange (GetIndexOfDummy (ga, 2), GetGroupActions ("Replaced items", 2))),
+ new GroupAction ("Dummy item RpDI-1"),
+ new GroupAction ("Dummy item RpDI-2"),
+ new GroupAction ("Select next dummy item", ga => {
+ int index = GetIndexOfDummy (ga);
+ _list.SelectedItem = ga.Parent[index];
+ }),
+ new GroupAction ("Dummy item SI"),
+ new GroupAction ("Move dummy above this one", ga => {
+ int nindex = GetIndexOfDummy (ga);
+ ga.Parent.Move (nindex, ga.Parent.IndexOf (c => c.Name.StartsWith ("Move dummy")));
+ }),
+ new GroupAction ("Dummy item MDI"),
+ new GroupAction ("Move last 2 items above this one", ga => {
+ int nindex = GetIndexOfDummy (ga, 2);
+ ga.Parent.Move (nindex, ga.Parent.IndexOf (c => c.Name.StartsWith ("Move last 2")), 2);
+ }),
+ new GroupAction ("Dummy item M2DI-1"),
+ new GroupAction ("Dummy item M2DI-2"),
+ },
+
+ CreateDummyGroup (2),
+ CreateDummyGroup (2),
+
+ new Group ("Group item actions") {
+ new GroupAction ("Clear all", ga => _groups.Clear()),
+ new GroupAction ("Insert group", ga => {
+ int index = _groups.IndexOf (g => g.Name == "Group item actions");
+ _groups.Insert (index, CreateDummyGroup (2));
+ }),
+
+ new GroupAction ("Insert 2 groups", ga => {
+ int index = _groups.IndexOf (g => g.Name == "Group item actions");
+ _groups.InsertRange (index, new[] { CreateDummyGroup (2), CreateDummyGroup (2) });
+ }),
+
+ new GroupAction ("Remove previous dummy group", ga => {
+ int index = _groups.IndexOf (g => g.Name == "Group item actions");
+ var dg = _groups.Take (index).Last (g => g.Name == "Dummy group");
+ _groups.Remove (dg);
+ }),
+
+ new GroupAction ("Remove previous 2 dummy groups", ga => {
+ int index = _groups.IndexOf (g => g.Name == "Group item actions");
+ var dgs = _groups.Take (index).Reverse().Where (g => g.Name == "Dummy group").Take (2);
+ _groups.RemoveRange (dgs);
+ }),
+
+ new GroupAction ("Replace previous dummy group", ga => {
+ int index = _groups.IndexOf (g => g.Name == "Group item actions");
+ var dg = _groups.Take (index).Last (g => g.Name == "Dummy group");
+ _groups[_groups.IndexOf (dg)] = new Group ("Replaced group") {
+ new GroupAction ("Replaced group item")
+ };
+ }),
+
+ new GroupAction ("Replace previous 2 dummy groups", ga => {
+ int index = _groups.IndexOf (g => g.Name == "Group item actions");
+ var dgs = _groups.Take (index).Reverse().Where (g => g.Name == "Dummy group").Take (2).Reverse();
+ _groups.ReplaceRange (_groups.IndexOf (dgs.First()), new[] {
+ new Group ("Replaced group") {
+ new GroupAction ("Replaced group item")
+ },
+ new Group ("Replaced group") {
+ new GroupAction ("Replaced group item")
+ }
+ });
+ }),
+
+ new GroupAction ("Move next group above", ga => {
+ int index = _groups.IndexOf (g => g.Name == ga.Parent.Name);
+ int dgindex = _groups.IndexOf (_groups.Skip (index + 1).First (dg => dg.Name == "Dummy group"));
+ _groups.Move (dgindex, index);
+ }),
+
+ new GroupAction ("Move next 2 groups above", ga => {
+ int index = _groups.IndexOf (g => g.Name == ga.Parent.Name);
+ int dgindex = _groups.IndexOf (_groups.Skip (index + 1).First (dg => dg.Name == "Dummy group"));
+ _groups.Move (dgindex, index, 2);
+ }),
+ },
+
+ CreateDummyGroup (1),
+ CreateDummyGroup (1),
+ CreateDummyGroup (1)
+ };
+ }
+
+ public GroupedListActionsGallery()
+ {
+ NavigationPage.SetHasNavigationBar (this, false);
+ _groups = CreateItemSource();
+
+ _list.ItemTapped += (sender, arg) => ((GroupAction)arg.Item).DoStuff();
+
+ _list.ItemsSource = _groups;
+ Title = "Actions";
+ Content = _list;
+ }
+
+ IEnumerable<GroupAction> GetGroupActions (string name, int count)
+ {
+ return Enumerable.Range (0, count).Select (i => new GroupAction (name + " " + i));
+ }
+
+ Group CreateDummyGroup (int children)
+ {
+ var group = new Group ("Dummy group");
+ group.AddRange (Enumerable.Range (0, children).Select (i => new GroupAction ("Dummy item")));
+ return group;
+ }
+
+ int GetIndexOfDummy (GroupAction source, int count = 1)
+ {
+ var dummies = GetNextDummyItems (source, count);
+ return source.Parent.IndexOf (dummies.First());
+ }
+
+ IEnumerable<GroupAction> GetNextDummyItems (GroupAction source, int count)
+ {
+ int start = source.Parent.IndexOf (source);
+ return source.Parent.Skip (start).Where (xga => xga.Name.StartsWith ("Dummy item")).Take (count);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/GroupedListContactsGallery.cs b/Xamarin.Forms.Controls/GalleryPages/GroupedListContactsGallery.cs
new file mode 100644
index 00000000..1058b692
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/GroupedListContactsGallery.cs
@@ -0,0 +1,244 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ public class GroupedListContactsGallery
+ : ContentPage
+ {
+ internal class Contact
+ {
+ public string FirstName
+ {
+ get;
+ set;
+ }
+
+ public string LastName
+ {
+ get;
+ set;
+ }
+
+ public string FullName
+ {
+ get { return FirstName + " " + LastName; }
+ }
+
+ public string Title
+ {
+ get;
+ set;
+ }
+ }
+
+ readonly ListView _list = new ListView {
+ ItemTemplate = new DataTemplate (() => {
+ Label name = new Label();
+ name.SetBinding (Label.TextProperty, "FullName");
+
+ Label title = new Label { Font = Font.SystemFontOfSize (NamedSize.Micro) };
+ title.SetBinding (Label.TextProperty, "Title");
+
+ return new ViewCell { View = new StackLayout {
+ Children = {
+ name,
+ title
+ }
+ } };
+ }),
+
+ GroupDisplayBinding = new Binding ("Key"),
+ GroupShortNameBinding = new Binding ("Key"),
+ IsGroupingEnabled = true
+ };
+
+ readonly List<Contact> _contacts = new List<Contact> {
+ new Contact { FirstName = "Jason", LastName = "Smith", Title = "Software Engineer" },
+ new Contact { FirstName = "Eric", LastName = "Maupin", Title = "Software Engineer" },
+ new Contact { FirstName = "Seth", LastName = "Rosetter", Title = "Software Engineer" },
+ new Contact { FirstName = "Stephane", LastName = "Delcroix", Title = "Software Engineer" }
+ };
+
+ readonly Random _rand = new Random (42);
+
+ [Preserve (AllMembers = true)]
+ internal class Group
+ : ObservableCollection<Contact>
+ {
+ public Group (string key)
+ {
+ Key = key;
+ }
+
+ public string Key
+ {
+ get;
+ private set;
+ }
+ }
+
+ bool _sortedByFirst = true;
+ ObservableCollection<Group> _sortedContacts;
+
+ public GroupedListContactsGallery()
+ {
+ var addRandom = new Button { Text = "Random" };
+ addRandom.Clicked += (sender, args) => {
+ Contact contact = GetRandomContact();
+ _contacts.Add (contact);
+
+ AddContact (_sortedContacts, contact);
+ };
+
+ var addRandomToExisting = new Button { Text = "Random Group" };
+ addRandomToExisting.Clicked += (sender, args) => {
+ Contact contact;
+ do {
+ contact = GetRandomContact();
+ } while (!_sortedContacts.Any (g => GetSortChar (g.First()) == GetSortChar (contact)));
+
+ _contacts.Add (contact);
+ AddContact (_sortedContacts, contact);
+ };
+
+ var groupByFirst = new Button { Text = "First" };
+ groupByFirst.Clicked += (sender, args) => {
+ _sortedByFirst = true;
+
+ SetupContacts();
+ _list.ItemsSource = _sortedContacts;
+ };
+
+ var groupByLast = new Button { Text = "Last" };
+ groupByLast.Clicked += (sender, args) => {
+ _sortedByFirst = false;
+
+ SetupContacts();
+ _list.ItemsSource = _sortedContacts;
+ };
+
+ Content = new StackLayout {
+ Orientation = StackOrientation.Vertical,
+ Children = {
+ new StackLayout {
+ Orientation = StackOrientation.Vertical,
+ Children = {
+ new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ new Label { Text = "Sort: " },
+ groupByFirst,
+ groupByLast
+ }
+ },
+
+ new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ addRandom,
+ addRandomToExisting,
+ }
+ }
+ },
+ },
+
+
+ _list
+ }
+ };
+
+ SetupContacts();
+ _list.ItemsSource = _sortedContacts;
+ }
+
+ const string Chars = "abcdefghijklmnopqrstuvwxyz";
+
+ void SetupContacts()
+ {
+ var coll = new ObservableCollection<Group>();
+ foreach (var contact in _contacts)
+ AddContact (coll, contact);
+
+ _sortedContacts = coll;
+ }
+
+ void AddContact (ObservableCollection<Group> contactGroups, Contact contact)
+ {
+ char sortChar = GetSortChar (contact);
+
+ var collection = contactGroups.FirstOrDefault (col => {
+ var c = col.First();
+ return (GetSortChar (c) == sortChar);
+ });
+
+ if (collection == null) {
+ var ocontacts = new Group (GetSortChar (contact).ToString()) { contact };
+ InsertBasedOnSort (contactGroups, ocontacts, c => GetSortChar (c.First()));
+ } else
+ InsertBasedOnSort (collection, contact, c => GetSortString (c)[0]);
+ }
+
+ int IndexOf<T> (IEnumerable<T> elements, T element)
+ {
+ int i = 0;
+ foreach (T e in elements) {
+ if (Equals (e, element))
+ return i;
+
+ i++;
+ }
+
+ return -1;
+ }
+
+ void InsertBasedOnSort<T,TSort> (IList<T> items, T item, Func<T, TSort> sortBy)
+ {
+ List<T> newItems = new List<T> (items);
+ newItems.Add (item);
+ int index = IndexOf (newItems.OrderBy (sortBy), item);
+ items.Insert (index, item);
+ }
+
+ char GetSortChar (Contact contact)
+ {
+ return GetSortString (contact)[0];
+ }
+
+ string GetSortString (Contact contact)
+ {
+ return (_sortedByFirst) ? contact.FirstName : contact.LastName;
+ }
+
+ Contact GetRandomContact()
+ {
+ Contact contact = new Contact();
+
+ int firstLen = _rand.Next (3, 7);
+
+ var builder = new StringBuilder (firstLen);
+ for (int i = 0; i < firstLen; i++) {
+ char c = Chars[_rand.Next (0, Chars.Length)];
+ builder.Append ((i != 0) ? c : char.ToUpper (c));
+ }
+
+ contact.FirstName = builder.ToString();
+
+ int lastLen = _rand.Next (3, 7);
+ builder.Clear();
+ for (int i = 0; i < lastLen; i++) {
+ char c = Chars[_rand.Next (0, Chars.Length)];
+ builder.Append ((i != 0) ? c : char.ToUpper (c));
+ }
+
+ contact.LastName = builder.ToString();
+ contact.Title = "Software Engineer";
+
+ return contact;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/ImageGallery.cs b/Xamarin.Forms.Controls/GalleryPages/ImageGallery.cs
new file mode 100644
index 00000000..9d4a32c9
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/ImageGallery.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class ImageGallery : ContentPage
+ {
+ public ImageGallery ()
+ {
+
+ Padding = new Thickness (20);
+
+ var normal = new Image { Source = ImageSource.FromFile ("cover1.jpg") };
+ var disabled = new Image { Source = ImageSource.FromFile ("cover1.jpg") };
+ var rotate = new Image { Source = ImageSource.FromFile ("cover1.jpg") };
+ var transparent = new Image { Source = ImageSource.FromFile ("cover1.jpg") };
+ var embedded = new Image { Source = ImageSource.FromResource ("Xamarin.Forms.Controls.ControlGalleryPages.crimson.jpg", typeof (ImageGallery)) };
+
+ // let the stack shrink the images
+ normal.MinimumHeightRequest = normal.MinimumHeightRequest = 10;
+ disabled.MinimumHeightRequest = disabled.MinimumHeightRequest = 10;
+ rotate.MinimumHeightRequest = rotate.MinimumHeightRequest = 10;
+ transparent.MinimumHeightRequest = transparent.MinimumHeightRequest = 10;
+ embedded.MinimumHeightRequest = 10;
+
+ disabled.IsEnabled = false;
+ rotate.GestureRecognizers.Add (new TapGestureRecognizer { Command = new Command (o => rotate.RelRotateTo (180))});
+ transparent.Opacity = .5;
+
+ Content = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ new StackLayout {
+ //MinimumWidthRequest = 20,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ Children = {
+ normal,
+ disabled,
+ transparent,
+ rotate,
+ embedded,
+ new StackLayout {
+ HeightRequest = 30,
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ new Image {Source = "cover1.jpg"},
+ new Image {Source = "cover1.jpg"},
+ new Image {Source = "cover1.jpg"},
+ new Image {Source = "cover1.jpg"}
+ }
+ }
+ }
+ },
+ new StackLayout {
+ WidthRequest = 30,
+ Children = {
+ new Image {Source = "cover1.jpg"},
+ new Image {Source = "cover1.jpg"},
+ new Image {Source = "cover1.jpg"},
+ new Image {Source = "cover1.jpg"}
+ }
+ }
+
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/ImageLoadingGallery.cs b/Xamarin.Forms.Controls/GalleryPages/ImageLoadingGallery.cs
new file mode 100644
index 00000000..f916d7dc
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/ImageLoadingGallery.cs
@@ -0,0 +1,43 @@
+using System;
+using System.ComponentModel;
+
+namespace Xamarin.Forms.Controls
+{
+
+ public class ImageLoadingGallery : ContentPage
+ {
+ public ImageLoadingGallery ()
+ {
+ Padding = new Thickness (20);
+
+ var source = new UriImageSource {
+ Uri = new Uri ("http://www.nasa.gov/sites/default/files/styles/1600x1200_autoletterbox/public/images/298773main_EC02-0282-3_full.jpg"),
+ CachingEnabled = false
+ };
+
+ var image = new Image {
+ Source = source,
+ WidthRequest = 200,
+ HeightRequest = 200,
+ };
+
+ var indicator = new ActivityIndicator {Color = new Color (.5),};
+ indicator.SetBinding (ActivityIndicator.IsRunningProperty, "IsLoading");
+ indicator.BindingContext = image;
+
+ var grid = new Grid();
+ grid.RowDefinitions.Add (new RowDefinition());
+ grid.RowDefinitions.Add (new RowDefinition());
+
+ grid.Children.Add (image);
+ grid.Children.Add (indicator);
+
+ var cancel = new Button { Text = "Cancel" };
+ cancel.Clicked += (s, e) => source.Cancel();
+ Grid.SetRow (cancel, 1);
+ grid.Children.Add (cancel);
+
+ Content = grid;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/InputIntentGallery.cs b/Xamarin.Forms.Controls/GalleryPages/InputIntentGallery.cs
new file mode 100644
index 00000000..0f1461bf
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/InputIntentGallery.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class InputIntentGallery : ContentPage
+ {
+ public InputIntentGallery ()
+ {
+ var label = new Label {
+ Text = "Custom Not Focused"
+ };
+
+ var label2 = new Label {
+ Text = ""
+ };
+
+ var defaultEntry = new Entry {
+ Placeholder = "Default",
+ Keyboard = Keyboard.Default
+ };
+
+ defaultEntry.Completed += (sender, e) => label2.Text = "Default completed";
+
+ var emailEntry = new Entry {
+ Placeholder = "Email Input",
+ Keyboard = Keyboard.Email
+ };
+
+ emailEntry.Completed += (sender, e) => label2.Text = "Email completed";
+
+ var textEntry = new Entry {
+ Placeholder = "Text Input",
+ Keyboard = Keyboard.Text
+ };
+
+ textEntry.Completed += (sender, e) => label2.Text = "Text completed";
+
+ var urlEntry = new Entry {
+ Placeholder = "Url Input",
+ Keyboard = Keyboard.Url
+ };
+
+ urlEntry.Completed += (sender, e) => label2.Text = "URL completed";
+
+ var numericEntry = new Entry {
+ Placeholder = "Numeric Input",
+ Keyboard = Keyboard.Numeric
+ };
+
+ numericEntry.Completed += (sender, e) => label2.Text = "Numeric completed";
+
+ var telephoneEntry = new Entry {
+ Placeholder = "Telephone Input",
+ Keyboard = Keyboard.Telephone
+ };
+
+ telephoneEntry.Completed += (sender, e) => label2.Text = "Telephone completed";
+
+ var chatEntry = new Entry {
+ Placeholder = "Chat Input",
+ Keyboard = Keyboard.Chat
+ };
+
+ chatEntry.Completed += (sender, e) => label2.Text = "Chat completed";
+
+ var customEntry = new Entry {
+ Placeholder = "Custom Entry",
+ Keyboard = Keyboard.Create (KeyboardFlags.CapitalizeSentence)
+ };
+
+ customEntry.Completed += (sender, e) => label2.Text = "Custom completed";
+
+ customEntry.Focused += (s, e) => {
+ label.Text = "Custom Focused";
+ };
+
+ Content = new ScrollView {
+ Content = new StackLayout {
+ VerticalOptions = LayoutOptions.Center,
+ Padding = new Thickness (40, 20),
+ Children = {
+ label,
+ label2,
+ defaultEntry,
+ emailEntry,
+ textEntry,
+ urlEntry,
+ numericEntry,
+ telephoneEntry,
+ chatEntry,
+ customEntry
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/LabelGallery.cs b/Xamarin.Forms.Controls/GalleryPages/LabelGallery.cs
new file mode 100644
index 00000000..65210969
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/LabelGallery.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class LabelGallery : ContentPage
+ {
+ public LabelGallery ()
+ {
+ var normal = new Label { Text = "Normal Label" };
+ var center = new Label { Text = "Center Label" };
+ var right = new Label { Text = "Right Label" };
+ var moving = new Label { Text = "Move On Click" };
+ var click = new Label { Text = "Click Label" };
+ var rotate = new Label { Text = "Rotate Label" };
+ var transparent = new Label { Text = "Transparent Label" };
+ var color = new Label { Text = "Color Change" };
+ var micro = new Label { Text = "Micro Label" };
+ var small = new Label { Text = "Small Label" };
+ var medium = new Label { Text = "Medium Label" };
+ var large = new Label { Text = "Large Label", VerticalOptions = LayoutOptions.FillAndExpand, VerticalTextAlignment = TextAlignment.Center};
+ var bold = new Label { Text = "Bold Label" };
+ var italic = new Label { Text = "Italic Label" };
+ var bolditalic = new Label { Text = "Bold Italic Label" };
+ var customFont = new Label { Text = "Custom Font" };
+ var italicfont = new Label { Text = "Custom Italic Font" };
+ var boldfont = new Label { Text = "Custom Bold Font" };
+ var bolditalicfont = new Label { Text = "Custom Bold Italic Font" };
+ var huge = new Label {
+ Text = "This is the label that never ends, yes it go on and on my friend. " +
+ "Some people started catting it not knowing what it was, and they'll continue catting it forever just because...",
+ LineBreakMode = LineBreakMode.WordWrap
+ };
+ var formatted = new Label { FormattedText = new FormattedString {
+ Spans = {
+ new Span {Text="FormattedStrings ", ForegroundColor=Color.Blue, BackgroundColor = Color.Yellow, Font = Font.BoldSystemFontOfSize (NamedSize.Large)},
+ new Span {Text="are ", ForegroundColor=Color.Red, BackgroundColor = Color.Gray},
+ new Span {Text="not pretty!", ForegroundColor = Color.Green,},
+ }
+ } };
+ var missingfont = new Label { Text = "Missing font: use default" };
+
+ micro.Font = Font.SystemFontOfSize (NamedSize.Micro);
+ small.Font = Font.SystemFontOfSize (NamedSize.Small);
+ medium.Font = Font.SystemFontOfSize (NamedSize.Medium);
+ large.Font = Font.SystemFontOfSize (NamedSize.Large);
+
+ bold.Font = Font.SystemFontOfSize (NamedSize.Medium, FontAttributes.Bold);
+ italic.Font = Font.SystemFontOfSize (NamedSize.Medium, FontAttributes.Italic);
+ bolditalic.Font = Font.SystemFontOfSize (NamedSize.Medium, FontAttributes.Bold | FontAttributes.Italic);
+
+ var fontName = Device.OnPlatform ("Georgia", "sans-serif-light", "Comic Sans MS");
+ var font = Font.OfSize (fontName, NamedSize.Medium);
+ customFont.Font = font;
+ italicfont.Font = font.WithAttributes (FontAttributes.Italic);
+ boldfont.Font = font.WithAttributes (FontAttributes.Bold);
+ bolditalicfont.Font = font.WithAttributes (FontAttributes.Bold | FontAttributes.Italic);
+
+ customFont.GestureRecognizers.Add (new TapGestureRecognizer{Command = new Command (o => customFont.Font = Font.Default)});
+
+ missingfont.Font = Font.OfSize ("FooBar", 20);
+ center.HorizontalTextAlignment = TextAlignment.Center;
+ right.HorizontalTextAlignment = TextAlignment.End;
+ int i = 1;
+ click.GestureRecognizers.Add (new TapGestureRecognizer{Command = new Command (o=>click.Text = "Clicked " + i++)});
+ rotate.GestureRecognizers.Add (new TapGestureRecognizer{Command = new Command (o=>rotate.RelRotateTo (180))});
+ transparent.Opacity = .5;
+ moving.GestureRecognizers.Add (new TapGestureRecognizer{Command = new Command (o=>moving.HorizontalTextAlignment = TextAlignment.End)});
+
+ color.GestureRecognizers.Add (new TapGestureRecognizer{Command = new Command (o=>{
+ color.TextColor = new Color (1, 0, 0);
+ color.BackgroundColor = new Color (0, 1, 0);
+ })});
+
+ Thickness padding = new Thickness (20);
+ // Padding Adjust for iPad
+ Device.OnPlatform (iOS: () => {
+ if (Device.Idiom == TargetIdiom.Tablet)
+ padding = new Thickness (20, 20, 20, 60);
+ });
+
+ Content = new ScrollView {
+ Content = new StackLayout {
+ Padding = padding,
+ Children = {
+ formatted,
+ normal,
+ center,
+ right,
+ huge,
+ moving,
+ click,
+ rotate,
+ transparent,
+ color,
+ micro,
+ small,
+ medium,
+ large,
+ bold,
+ italic,
+ bolditalic,
+ customFont,
+ italicfont,
+ boldfont,
+ bolditalicfont,
+ missingfont,
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/LayoutOptionsGallery.cs b/Xamarin.Forms.Controls/GalleryPages/LayoutOptionsGallery.cs
new file mode 100644
index 00000000..13c6c575
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/LayoutOptionsGallery.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class LayoutOptionsGallery : ContentPage
+ {
+ public LayoutOptionsGallery ()
+ {
+ Build ();
+ }
+
+ void Build ()
+ {
+ var mainLayout = new StackLayout {
+ BackgroundColor = Color.Silver,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Children = {
+ BuildLayoutRegion (),
+ BuildLayoutRegion ()
+ }
+ };
+
+ var changeOrientationButton = new Button {Text = "Change Orientation"};
+ changeOrientationButton.Clicked += (sender, args) => mainLayout.Orientation = (mainLayout.Orientation == StackOrientation.Horizontal) ? StackOrientation.Vertical : StackOrientation.Horizontal;
+
+ Content = new StackLayout {
+ Children = {
+ changeOrientationButton,
+ mainLayout
+ }
+ };
+ }
+
+ LayoutOptions StringToLayoutOptions (string options)
+ {
+ switch (options) {
+ case "Start":
+ return LayoutOptions.Start;
+ case "StartAndExpand":
+ return LayoutOptions.StartAndExpand;
+ case "Center":
+ return LayoutOptions.Center;
+ case "CenterAndExpand":
+ return LayoutOptions.CenterAndExpand;
+ case "End":
+ return LayoutOptions.End;
+ case "EndAndExpand":
+ return LayoutOptions.EndAndExpand;
+ case "Fill":
+ return LayoutOptions.Fill;
+ case "FillAndExpand":
+ return LayoutOptions.FillAndExpand;
+ }
+ throw new InvalidDataException ();
+ }
+
+ View BuildLayoutRegion ()
+ {
+ // Set these to fill and expand so they just fill their parent which is the thing we actually want to play with.
+ var horizontalButton = new Button {
+ Text = "H Options",
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ };
+
+ var verticalButton = new Button {
+ Text = "V Options",
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ };
+
+ var result = new StackLayout {
+ BackgroundColor = Color.Gray,
+ Children = {
+ horizontalButton,
+ verticalButton
+ }
+ };
+
+ horizontalButton.Clicked += async (sender, args) => {
+ var selection = await DisplayActionSheet ("Select Horizontal Options", null, null,
+ "Start", "StartAndExpand",
+ "Center", "CenterAndExpand",
+ "End", "EndAndExpand",
+ "Fill", "FillAndExpand");
+
+ result.HorizontalOptions = StringToLayoutOptions (selection);
+ };
+
+ verticalButton.Clicked += async (sender, args) => {
+ var selection = await DisplayActionSheet ("Select Horizontal Options", null, null,
+ "Start", "StartAndExpand",
+ "Center", "CenterAndExpand",
+ "End", "EndAndExpand",
+ "Fill", "FillAndExpand");
+
+ result.VerticalOptions = StringToLayoutOptions (selection);
+ };
+
+ return result;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/LayoutPerformanceGallery.cs b/Xamarin.Forms.Controls/GalleryPages/LayoutPerformanceGallery.cs
new file mode 100644
index 00000000..9778e372
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/LayoutPerformanceGallery.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls.GalleryPages
+{
+ public class LayoutPerformanceGallery : ContentPage
+ {
+ public LayoutPerformanceGallery ()
+ {
+ int size = 3;
+
+ var grid = new Grid {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ RowDefinitions = {
+ new RowDefinition { Height = new GridLength (100, GridUnitType.Absolute) },
+ new RowDefinition { Height = new GridLength (5, GridUnitType.Star) },
+ new RowDefinition { Height = new GridLength (7, GridUnitType.Star) },
+ },
+ ColumnDefinitions = {
+ new ColumnDefinition { Width = new GridLength (3, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength (100, GridUnitType.Absolute) },
+ new ColumnDefinition { Width = new GridLength (7, GridUnitType.Star) },
+ }
+ };
+
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < size; j++) {
+ var g = new Grid {
+ RowDefinitions = {
+ new RowDefinition { Height = new GridLength (100, GridUnitType.Absolute) },
+ new RowDefinition { Height = new GridLength (5, GridUnitType.Star) },
+ new RowDefinition { Height = new GridLength (7, GridUnitType.Star) },
+ },
+ ColumnDefinitions = {
+ new ColumnDefinition { Width = new GridLength (3, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength (100, GridUnitType.Absolute) },
+ new ColumnDefinition { Width = new GridLength (7, GridUnitType.Star) },
+ }
+ };
+
+ for (int k = 0; k < size; k++) {
+ for (int l = 0; l < size; l++) {
+ var label = new Label { Text = "10" };
+ g.Children.Add (label, k, l);
+ _labelList.Add (label);
+ }
+ }
+
+ grid.Children.Add (g, i, j);
+ }
+ }
+
+
+
+
+ Content = new StackLayout {
+ Children = {
+ (_mainLabel = new Label ()),
+ grid
+ }
+ };
+ }
+
+ Label _mainLabel = null;
+ List<Label> _labelList = new List<Label> ();
+ Stopwatch _sw = new Stopwatch ();
+ long _ticks = 0;
+ int _count = 0;
+ int _cycle = 0;
+ bool _flip = true;
+ Random _r = new Random (34269027);
+ bool _repeat = false;
+
+ protected override void OnAppearing ()
+ {
+ base.OnAppearing ();
+ _repeat = true;
+ Device.StartTimer (TimeSpan.FromMilliseconds (10), () => {
+ _sw.Start ();
+ foreach (var label in _labelList) {
+ if (_flip) {
+ label.Text = _r.Next (10, 40).ToString ();
+ } else {
+ label.Text = _r.Next (50, 90).ToString ();
+ }
+ }
+ _sw.Stop ();
+ _ticks += _sw.ElapsedMilliseconds;
+ _sw.Reset ();
+
+ _cycle = (_cycle + 1) % 100;
+ _count++;
+ if (_cycle == 0) {
+ _mainLabel.Text = string.Format ("Avg Time: {0:0.000}ms", _ticks / (double)_count);
+ }
+
+ _flip = !_flip;
+ return _repeat;
+ });
+ }
+
+ protected override void OnDisappearing ()
+ {
+ _repeat = false;
+ _ticks = 0;
+ _count = 0;
+ _cycle = 0;
+
+ base.OnDisappearing ();
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/LineBreakModeGallery.cs b/Xamarin.Forms.Controls/GalleryPages/LineBreakModeGallery.cs
new file mode 100644
index 00000000..8089bc79
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/LineBreakModeGallery.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class LineBreakModeGallery : ContentPage
+ {
+ public LineBreakModeGallery ()
+ {
+ var label = new Label {
+ Text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
+ };
+
+ Content = new ScrollView {
+ Content = new StackLayout {
+ Spacing = 0,
+ Children = {
+ MakeLineBreakModeButton ("CharacterWrap", label, LineBreakMode.CharacterWrap),
+ MakeLineBreakModeButton ("HeadTruncation", label, LineBreakMode.HeadTruncation),
+ MakeLineBreakModeButton ("MiddleTruncation", label, LineBreakMode.MiddleTruncation),
+ MakeLineBreakModeButton ("NoWrap", label, LineBreakMode.NoWrap),
+ MakeLineBreakModeButton ("TailTruncation", label, LineBreakMode.TailTruncation),
+ MakeLineBreakModeButton ("WordWrap", label, LineBreakMode.WordWrap),
+ label
+ }
+ }
+ };
+ }
+
+ static Button MakeLineBreakModeButton (string buttonText, Label label, LineBreakMode lineBreakMode) {
+ var button = new Button {
+ Text = buttonText,
+ Command = new Command (() => label.LineBreakMode = lineBreakMode)
+ };
+ return button;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/ListPage.cs b/Xamarin.Forms.Controls/GalleryPages/ListPage.cs
new file mode 100644
index 00000000..0eeaf147
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/ListPage.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class ListPage : ContentPage
+ {
+ ListScreen _listScreen;
+ public ListPage ()
+ {
+ _listScreen = new ListScreen ();
+ Content = new StackLayout {
+ Children = {
+ new Label {Text = "Foo"},
+ _listScreen.View
+ }
+ };
+ }
+ }
+
+ public class ListScreen
+ {
+ public ListView View { get; private set; }
+
+ internal class A : INotifyPropertyChanged
+ {
+ string _text;
+ public string Text {
+ get {
+ return _text;
+ }
+ set {
+ _text = value;
+ if(PropertyChanged != null)
+ PropertyChanged(this, new PropertyChangedEventArgs("Text"));
+ }
+ }
+
+ #region INotifyPropertyChanged implementation
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ #endregion
+ }
+
+ [Preserve (AllMembers = true)]
+ internal class ViewCellTest : ViewCell
+ {
+ static int s_inc = 0;
+
+ public ViewCellTest ()
+ {
+ var stackLayout = new StackLayout {
+ Orientation = StackOrientation.Horizontal
+ };
+
+ var label = new Label ();
+ label.SetBinding (Label.TextProperty, "Text");
+
+ var box = new BoxView {WidthRequest = 100, HeightRequest = 10, Color = Color.Red};
+
+ stackLayout.Children.Add (label);
+ stackLayout.Children.Add (box);
+
+ View = stackLayout;
+ }
+
+ protected override void OnAppearing ()
+ {
+ base.OnAppearing ();
+ Debug.WriteLine ("Appearing: " + (BindingContext as A)?.Text + " : " + s_inc);
+ s_inc++;
+ }
+
+ protected override void OnDisappearing ()
+ {
+ base.OnDisappearing ();
+ Debug.WriteLine ("Disappearing: " + (BindingContext as A)?.Text + " : " + s_inc);
+ s_inc++;
+ }
+ }
+
+ public ListScreen ()
+ {
+
+ View = new ListView (ListViewCachingStrategy.RecycleElement);
+
+ View.RowHeight = 30;
+
+ var n = 500;
+ var items = Enumerable.Range (0, n).Select (i => new A {Text = i.ToString ()}).ToList ();
+ View.ItemsSource = items;
+
+ View.ItemTemplate = new DataTemplate (typeof (ViewCellTest));
+
+ View.ItemSelected += (sender, e) => {
+ var cell = (e.SelectedItem as A);
+ if (cell == null)
+ return;
+ var x = int.Parse (cell.Text);
+ if (x == 5) {
+ n += 10;
+ View.ItemsSource = Enumerable.Range (0, n).Select (i => new A { Text = i.ToString () }).ToList ();
+ } else {
+ cell.Text = (x + 1).ToString ();
+ }
+ };
+
+
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/ListViewDemoPage.cs b/Xamarin.Forms.Controls/GalleryPages/ListViewDemoPage.cs
new file mode 100644
index 00000000..a30ec170
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/ListViewDemoPage.cs
@@ -0,0 +1,231 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class ListViewDemoPage : ContentPage
+ {
+ class Person
+ {
+ public Person(string name, DateTime birthday, Color favoriteColor)
+ {
+ Name = name;
+ Birthday = birthday;
+ FavoriteColor = favoriteColor;
+ }
+
+ public string Name { private set; get; }
+
+ public DateTime Birthday { private set; get; }
+
+ public Color FavoriteColor { private set; get; }
+ };
+
+ class MyDataTemplateSelector : DataTemplateSelector
+ {
+ DataTemplate _oddTemplate;
+ DataTemplate _evenTemplate;
+
+ public MyDataTemplateSelector ()
+ {
+ _evenTemplate = new DataTemplate (() => {
+ // Create views with bindings for displaying each property.
+ Label nameLabel = new Label ();
+ nameLabel.SetBinding (Label.TextProperty, "Name");
+
+ Label birthdayLabel = new Label ();
+ birthdayLabel.SetBinding (Label.TextProperty,
+ new Binding ("Birthday", BindingMode.OneWay,
+ null, null, "Born {0:d}"));
+
+ BoxView boxView = new BoxView ();
+ boxView.SetBinding (BoxView.ColorProperty, "FavoriteColor");
+
+ // Return an assembled ViewCell.
+ return new ViewCell {
+ View = new StackLayout {
+ Padding = new Thickness (0, 5),
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ new Image {
+ HeightRequest = 40,
+ WidthRequest = 40,
+ Source = new UriImageSource {
+ // CacheValidity = TimeSpan.FromSeconds (10),
+ Uri = new Uri ("https://xamarin.com/content/images/pages/index/xamarin-studio-icon.png"),
+ }
+ },
+ boxView,
+ new StackLayout {
+ VerticalOptions = LayoutOptions.Center,
+ Spacing = 0,
+ Children = {
+ nameLabel,
+ birthdayLabel
+ }
+ }
+ }
+ }
+ };
+ });
+
+ _oddTemplate = new DataTemplate (() => {
+ // Create views with bindings for displaying each property.
+ Label nameLabel = new Label ();
+ nameLabel.SetBinding (Label.TextProperty, "Name");
+
+ Label birthdayLabel = new Label ();
+ birthdayLabel.SetBinding (Label.TextProperty,
+ new Binding ("Birthday", BindingMode.OneWay,
+ null, null, "Born {0:d}"));
+
+ BoxView boxView = new BoxView ();
+ boxView.SetBinding (BoxView.ColorProperty, "FavoriteColor");
+
+ // Return an assembled ViewCell.
+ return new ViewCell {
+ View = new StackLayout {
+ Padding = new Thickness (0, 5),
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ new Image {
+ HeightRequest = 40,
+ WidthRequest = 40,
+ Source = new UriImageSource {
+ // CacheValidity = TimeSpan.FromSeconds (10),
+ Uri = new Uri ("https://xamarin.com/content/images/pages/index/xamarin-studio-icon.png"),
+ }
+ },
+
+ new StackLayout {
+ VerticalOptions = LayoutOptions.Center,
+ Spacing = 0,
+ Children = {
+ birthdayLabel,
+ nameLabel,
+ }
+ },
+ boxView,
+ }
+ }
+ };
+ });
+ }
+
+ protected override DataTemplate OnSelectTemplate (object item, BindableObject container)
+ {
+ return ((Person)item).Birthday.Month % 2 == 0 ? _evenTemplate : _oddTemplate;
+ }
+ }
+
+ public ListViewDemoPage()
+ {
+ Label header = new Label
+ {
+ Text = "ListView",
+ Font = Font.BoldSystemFontOfSize(50),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ // Define some data.
+ List<Person> people = new List<Person>
+ {
+ new Person("Abigail", new DateTime(1975, 1, 15), Color.Aqua),
+ new Person("Bob", new DateTime(1976, 2, 20), Color.Black),
+ new Person("Cathy", new DateTime(1977, 3, 10), Color.Blue),
+ new Person("David", new DateTime(1978, 4, 25), Color.Fuschia),
+ new Person("Eugenie", new DateTime(1979, 5, 5), Color.Gray),
+ new Person("Freddie", new DateTime(1980, 6, 30), Color.Green),
+ new Person("Greta", new DateTime(1981, 7, 15), Color.Lime),
+ new Person("Harold", new DateTime(1982, 8, 10), Color.Maroon),
+ new Person("Irene", new DateTime(1983, 9, 25), Color.Navy),
+ new Person("Jonathan", new DateTime(1984, 10, 10), Color.Olive),
+ new Person("Kathy", new DateTime(1985, 11, 20), Color.Purple),
+ new Person("Larry", new DateTime(1986, 12, 5), Color.Red),
+ new Person("Monica", new DateTime(1975, 1, 5), Color.Silver),
+ new Person("Nick", new DateTime(1976, 2, 10), Color.Teal),
+ new Person("Olive", new DateTime(1977, 3, 20), Color.White),
+ new Person("Pendleton", new DateTime(1978, 4, 10), Color.Yellow),
+ new Person("Queenie", new DateTime(1979, 5, 15), Color.Aqua),
+ new Person("Rob", new DateTime(1980, 6, 30), Color.Blue),
+ new Person("Sally", new DateTime(1981, 7, 5), Color.Fuschia),
+ new Person("Timothy", new DateTime(1982, 8, 30), Color.Green),
+ new Person("Uma", new DateTime(1983, 9, 10), Color.Lime),
+ new Person("Victor", new DateTime(1984, 10, 20), Color.Maroon),
+ new Person("Wendy", new DateTime(1985, 11, 5), Color.Navy),
+ new Person("Xavier", new DateTime(1986, 12, 30), Color.Olive),
+ new Person("Yvonne", new DateTime(1987, 1, 10), Color.Purple),
+ new Person("Zachary", new DateTime(1988, 2, 5), Color.Red)
+ };
+ List<Person> people2 = new List<Person>
+ {
+ new Person("Abigail", new DateTime(1975, 1, 15), Color.Aqua),
+ new Person("Bob", new DateTime(1976, 2, 20), Color.Black),
+ new Person("Cathy", new DateTime(1977, 3, 10), Color.Blue),
+ new Person("David", new DateTime(1978, 4, 25), Color.Fuschia),
+ new Person("Eugenie", new DateTime(1979, 5, 5), Color.Gray),
+ new Person("Freddie", new DateTime(1980, 6, 30), Color.Green),
+ new Person("Greta", new DateTime(1981, 7, 15), Color.Lime),
+ new Person("Harold", new DateTime(1982, 8, 10), Color.Maroon),
+ new Person("Irene", new DateTime(1983, 9, 25), Color.Navy),
+ new Person("Jonathan", new DateTime(1984, 10, 10), Color.Olive),
+ new Person("Kathy", new DateTime(1985, 11, 20), Color.Purple),
+ new Person("Larry", new DateTime(1986, 12, 5), Color.Red),
+ new Person("Monica", new DateTime(1975, 1, 5), Color.Silver),
+ new Person("Nick", new DateTime(1976, 2, 10), Color.Teal),
+ new Person("Olive", new DateTime(1977, 3, 20), Color.White),
+ new Person("Pendleton", new DateTime(1978, 4, 10), Color.Yellow),
+ new Person("Queenie", new DateTime(1979, 5, 15), Color.Aqua),
+ new Person("Rob", new DateTime(1980, 6, 30), Color.Blue),
+ new Person("Sally", new DateTime(1981, 7, 5), Color.Fuschia),
+ new Person("Timothy", new DateTime(1982, 8, 30), Color.Green),
+ new Person("Uma", new DateTime(1983, 9, 10), Color.Lime),
+ new Person("Victor", new DateTime(1984, 10, 20), Color.Maroon),
+ new Person("Wendy", new DateTime(1985, 11, 5), Color.Navy),
+ new Person("Xavier", new DateTime(1986, 12, 30), Color.Olive),
+ new Person("Yvonne", new DateTime(1987, 1, 10), Color.Purple),
+ new Person("Zachary", new DateTime(1988, 2, 5), Color.Red)
+ };
+
+ // Create the ListView.
+ ListView listView = new ListView (ListViewCachingStrategy.RecycleElement)
+ {
+ // Source of data items.
+ ItemsSource = new List<List<Person>> {people, people2},
+ IsPullToRefreshEnabled = true,
+ IsGroupingEnabled = true,
+
+ // Define template for displaying each item.
+ // (Argument of DataTemplate constructor is called for
+ // each item; it must return a Cell derivative.)
+ ItemTemplate = new MyDataTemplateSelector ()
+ };
+
+ listView.Refreshing += async (sender, e) => {
+ await Task.Delay (5000);
+ listView.IsRefreshing = false;
+ };
+
+ listView.ItemSelected += (sender, args) => {
+ if (listView.SelectedItem == null)
+ return;
+ listView.SelectedItem = null;
+ };
+
+ // Accomodate iPhone status bar.
+ Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
+
+ // Build the page.
+ Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ listView
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/MapGallery.cs b/Xamarin.Forms.Controls/GalleryPages/MapGallery.cs
new file mode 100644
index 00000000..dd283c3a
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/MapGallery.cs
@@ -0,0 +1,153 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms.Maps;
+
+namespace Xamarin.Forms.Controls
+{
+ public class MapGallery : ContentPage
+ {
+ readonly StackLayout _stack;
+
+ public MapGallery ()
+ {
+ Device.OnPlatform (iOS: () => {
+ if (Device.Idiom == TargetIdiom.Tablet) {
+ Padding = new Thickness (0, 0, 0, 60);
+ }
+ });
+
+ var map = MakeMap ();
+
+ map.MoveToRegion (MapSpan.FromCenterAndRadius (new Position (41.890202, 12.492049), Distance.FromMiles (0.5)));
+
+ var searchAddress = new SearchBar { Placeholder = "Search Address" };
+
+ searchAddress.SearchButtonPressed += async (e, a) => {
+ var addressQuery = searchAddress.Text;
+ searchAddress.Text = "";
+ searchAddress.Unfocus ();
+
+ var positions = (await (new Geocoder ()).GetPositionsForAddressAsync (addressQuery)).ToList ();
+ if (!positions.Any ())
+ return;
+
+ var position = positions.First ();
+ map.MoveToRegion (MapSpan.FromCenterAndRadius (position,
+ Distance.FromMeters (4000)));
+ map.Pins.Add (new Pin {
+ Label = addressQuery,
+ Position = position,
+ Address = addressQuery
+ });
+ };
+
+ var buttonAddressFromPosition = new Button { Text = "Address From Position" };
+ buttonAddressFromPosition.Clicked += async (e, a) => {
+ var addresses = (await (new Geocoder ()).GetAddressesForPositionAsync (new Position (41.8902, 12.4923))).ToList ();
+ foreach (var ad in addresses)
+ Debug.WriteLine (ad);
+ };
+
+ var buttonZoomIn = new Button { Text = "Zoom In" };
+ buttonZoomIn.Clicked += (e, a) => map.MoveToRegion (map.VisibleRegion.WithZoom (5f));
+
+ var buttonZoomOut = new Button { Text = "Zoom Out" };
+ buttonZoomOut.Clicked += (e, a) => map.MoveToRegion (map.VisibleRegion.WithZoom (1 / 3f));
+
+ var mapTypeButton = new Button { Text = "Map Type" };
+ mapTypeButton.Clicked += async (e, a) => {
+ var result = await DisplayActionSheet ("Select Map Type", null, null, "Street", "Satellite", "Hybrid");
+ switch (result) {
+ case "Street":
+ map.MapType = MapType.Street;
+ break;
+ case "Satellite":
+ map.MapType = MapType.Satellite;
+ break;
+ case "Hybrid":
+ map.MapType = MapType.Hybrid;
+ break;
+ }
+ };
+
+ var buttonHome = new Button { Text = "Home" };
+ buttonHome.Clicked += (a, e) => {
+ map.MoveToRegion (MapSpan.FromCenterAndRadius (new Position (41.890202, 12.492049), Distance.FromMiles (0.5)));
+ };
+
+ _stack = new StackLayout {
+ Spacing = 0,
+ Padding = new Thickness (30, 0)
+ };
+ //stack.SetRowSpacing (1, 0);
+
+ Title = "Map Gallery";
+
+ var buttonZoomPin = new Button { Text = "Zoom Pin" };
+ buttonZoomPin.Clicked += (a, e) => {
+ var pos = new Position (41.011995, -8.642995);
+ map.Pins.Clear ();
+ map.Pins.Add (new Pin { Position = pos, Label = "Rui" });
+ map.MoveToRegion (MapSpan.FromCenterAndRadius (pos, Distance.FromMiles (0.5)));
+ };
+
+
+ map.VerticalOptions = LayoutOptions.FillAndExpand;
+ _stack.Children.Add (searchAddress);
+ _stack.Children.Add (map);
+ _stack.Children.Add (mapTypeButton);
+ _stack.Children.Add (buttonZoomIn);
+ _stack.Children.Add (buttonZoomOut);
+ _stack.Children.Add (buttonAddressFromPosition);
+ _stack.Children.Add (buttonHome);
+ _stack.Children.Add (buttonZoomPin);
+
+ Content = _stack;
+ }
+
+ public static Map MakeMap ()
+ {
+ Pin colosseum = null;
+ Pin pantheon = null;
+ Pin chapel = null;
+
+ var map = new Map {
+ IsShowingUser = false,
+ Pins = {
+ (colosseum = new Pin {
+ Type = PinType.Place,
+ Position = new Position (41.890202, 12.492049),
+ Label = "Colosseum",
+ Address = "Piazza del Colosseo, 00184 Rome, Province of Rome, Italy"
+ }),
+ (pantheon = new Pin {
+ Type = PinType.Place,
+ Position = new Position (41.898652, 12.476831),
+ Label = "Pantheon",
+ Address = "Piazza della Rotunda, 00186 Rome, Province of Rome, Italy"
+ }),
+ (chapel = new Pin {
+ Type = PinType.Place,
+ Position = new Position (41.903209, 12.454545),
+ Label = "Sistine Chapel",
+ Address = "Piazza della Rotunda, 00186 Rome, Province of Rome, Italy"
+ })
+ }
+ };
+
+ colosseum.Clicked += PinClicked;
+ pantheon.Clicked += PinClicked;
+ chapel.Clicked += PinClicked;
+ return map;
+ }
+
+ static void PinClicked (object sender, EventArgs e)
+ {
+ // yea!
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/MasterDetailPageTabletPage.cs b/Xamarin.Forms.Controls/GalleryPages/MasterDetailPageTabletPage.cs
new file mode 100644
index 00000000..f8aba26b
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/MasterDetailPageTabletPage.cs
@@ -0,0 +1,40 @@
+using System;
+
+namespace Xamarin.Forms.Controls
+{
+ public class MasterDetailPageTabletPage : ContentPage
+ {
+ public MasterDetailPageTabletPage ()
+ {
+ Title = "MasterDetail MasterBehavior Gallery";
+
+ var btn = new Button { Text = "Default (old behavior)" };
+ btn.Clicked += async (sender, e) => await Navigation.PushModalAsync (new Issue1461Page (MasterBehavior.Default,null));
+
+ var btn1 = new Button { Text = "Default (old behavior) but always hide toolbar button" };
+ btn1.Clicked += async (sender, e) => await Navigation.PushModalAsync (new Issue1461Page (MasterBehavior.Default,false));
+
+ var btn2 = new Button { Text = "Popover - (always show it as a popover) but hide toolbar button" };
+ btn2.Clicked += async (sender, e) => await Navigation.PushModalAsync (new Issue1461Page (MasterBehavior.Popover,false));
+
+ //there's never a time when to real hide the master i think, use a normal page for that..
+ //what the user wants is out of the screen, maybe we need a better namming
+ var btn3 = new Button { Text = "Popover - (always show it as a popover)" };
+ btn3.Clicked += async (sender, e) => await Navigation.PushModalAsync (new Issue1461Page (MasterBehavior.Popover, null));
+
+ //we throw an exception here if you try to toggle it
+ var btn4 = new Button { Text = "Split - (always show it as splitview , toogle master always visible, throws expception)" };
+ btn4.Clicked += async (sender, e) => await Navigation.PushModalAsync (new Issue1461Page (MasterBehavior.Split, null));
+
+ var btn5 = new Button { Text = "SplitOnPortrait Portrait - (always show it as splitview in Portrait, throws expception)" };
+ btn5.Clicked += async (sender, e) => await Navigation.PushModalAsync (new Issue1461Page (MasterBehavior.SplitOnPortrait, null));
+
+ var btn6 = new Button { Text = "SplitOnLandscape Landscape - (always show it as splitview in Landscape, throws expception))" };
+ btn6.Clicked += async (sender, e) => await Navigation.PushModalAsync (new Issue1461Page (MasterBehavior.SplitOnLandscape, null));
+
+ Content = new StackLayout { Padding= new Thickness(0,20,0,0) , Children = { btn, btn1, btn2, btn6, btn3, btn4, btn5 }, Spacing = 20 };
+
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls/GalleryPages/MinimumSizeGallery.cs b/Xamarin.Forms.Controls/GalleryPages/MinimumSizeGallery.cs
new file mode 100644
index 00000000..1ad90574
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/MinimumSizeGallery.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class MinimumSizeGallery : ContentPage
+ {
+ public MinimumSizeGallery ()
+ {
+ Content = new StackLayout {
+ Children = {
+ new Button { Text = "Big Button", HeightRequest = 300 },
+ new TableView {
+ Intent = TableIntent.Settings,
+ Root = new TableRoot {
+ new TableSection ("SECTION 1") {
+ new TextCell { Text = "Cell 1", Detail = "Red Text", TextColor = Color.Red },
+ new TextCell { Text = "Detail Red", Detail = "Detail", DetailColor = Color.Red },
+ new TextCell { Text = "Cell 3" },
+ new TextCell { Text = "Cell 4" }
+ },
+ new TableSection ("Section 2") {
+ new TextCell { Text = "Cell 1" },
+ new TextCell { Text = "Cell 2" },
+ new TextCell { Text = "Cell 3" },
+ new TextCell { Text = "Cell 4" }
+ },
+ new TableSection ("Section 3") {
+ new TextCell { Text = "Cell 1" },
+ new TextCell { Text = "Cell 2" },
+ new TextCell { Text = "Cell 3" },
+ new TextCell { Text = "Cell 4" }
+ },
+ new TableSection ("Section 4") {
+ new TextCell { Text = "Cell 1" },
+ new TextCell { Text = "Cell 2" },
+ new TextCell { Text = "Cell 3" },
+ new TextCell { Text = "Cell 4 Last" }
+ }
+ }
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/MultiGallery.cs b/Xamarin.Forms.Controls/GalleryPages/MultiGallery.cs
new file mode 100644
index 00000000..02ceab08
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/MultiGallery.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class MultiGallery : ContentPage
+ {
+ public MultiGallery ()
+ {
+ var button = new Button {Text = "Toggle Nav Bar"};
+ Content = new ScrollView {
+ Content = new StackLayout {
+ Children = {
+ button,
+ new Editor (),
+ new Entry (),
+ new Image {Source = ImageSource.FromFile ("cover1.jpg")},
+ new Label {Text = "Label"},
+ new ProgressBar (),
+ new ActivityIndicator (),
+ new Switch (),
+ new Stepper (),
+ new Slider (),
+ new ProgressBar (),
+ new ActivityIndicator (),
+ new Switch (),
+ new Stepper (),
+ new Slider ()
+ }
+ }
+ };
+
+ button.Clicked +=
+ (sender, args) => NavigationPage.SetHasNavigationBar (this, !NavigationPage.GetHasNavigationBar (this));
+
+ ToolbarItems.Add (new ToolbarItem ("Back", "bank.png", () => Navigation.PopAsync (), ToolbarItemOrder.Primary));
+ ToolbarItems.Add (new ToolbarItem ("It's", "bank.png", () => Navigation.PopAsync (), ToolbarItemOrder.Secondary));
+ ToolbarItems.Add (new ToolbarItem ("A", "bank.png", () => Navigation.PopAsync (), ToolbarItemOrder.Secondary));
+ ToolbarItems.Add (new ToolbarItem ("TARP!", "bank.png", () => Navigation.PopAsync (), ToolbarItemOrder.Secondary));
+ }
+
+ protected override void OnAppearing ()
+ {
+ Debug.WriteLine ("Appearing");
+ base.OnAppearing ();
+ }
+
+ protected override void OnDisappearing ()
+ {
+ Debug.WriteLine ("Disappearing");
+ base.OnDisappearing ();
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/NavigationBarGallery.cs b/Xamarin.Forms.Controls/GalleryPages/NavigationBarGallery.cs
new file mode 100644
index 00000000..dfbc342c
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/NavigationBarGallery.cs
@@ -0,0 +1,62 @@
+using System.Diagnostics;
+
+namespace Xamarin.Forms.Controls
+{
+ public class NavigationBarGallery : ContentPage
+ {
+ public NavigationBarGallery (NavigationPage rootNavPage)
+ {
+
+ int toggleBarTextColor = 0;
+ int toggleBarBackgroundColor = 0;
+
+ Content = new StackLayout {
+ Children = {
+ new Button {
+ Text = "Change BarTextColor",
+ Command = new Command (() => {
+ if (toggleBarTextColor % 2 == 0) {
+ rootNavPage.BarTextColor = Color.Teal;
+ } else {
+ rootNavPage.BarTextColor = Color.Default;
+ }
+ toggleBarTextColor++;
+ })
+ },
+ new Button {
+ Text = "Change BarBackgroundColor",
+ Command = new Command (() => {
+ if (toggleBarBackgroundColor % 2 == 0) {
+ rootNavPage.BarBackgroundColor = Color.Navy;
+ } else {
+ rootNavPage.BarBackgroundColor = Color.Default;
+ }
+ toggleBarBackgroundColor++;
+
+ })
+ },
+ new Button {
+ Text = "Change Both to default",
+ Command = new Command (() => {
+ rootNavPage.BarTextColor = Color.Default;
+ rootNavPage.BarBackgroundColor = Color.Default;
+ })
+ },
+ new Button {
+ Text = "Make sure Tint still works",
+ Command = new Command (() => {
+ rootNavPage.Tint = Color.Red;
+ })
+ },
+ new Button {
+ Text = "Black background, white text",
+ Command = new Command (() => {
+ rootNavPage.BarTextColor = Color.White;
+ rootNavPage.BarBackgroundColor = Color.Black;
+ })
+ }
+ }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/GalleryPages/NavigationMenuGallery.cs b/Xamarin.Forms.Controls/GalleryPages/NavigationMenuGallery.cs
new file mode 100644
index 00000000..d63745da
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/NavigationMenuGallery.cs
@@ -0,0 +1,38 @@
+using System.Diagnostics;
+
+namespace Xamarin.Forms.Controls
+{
+ public class NavigationMenuGallery : ContentPage
+ {
+ public NavigationMenuGallery ()
+ {
+ Content = new ScrollView {
+ Content = new NavigationMenu {
+ Targets = new[] {
+ new ContentPage {
+ Content =
+ new Label {
+ Text = "Test 1",
+ VerticalOptions = LayoutOptions.Center,
+ HorizontalOptions = LayoutOptions.Center
+ },
+ Title = "Testing 1",
+ Icon = "cover1.jpg"
+ },
+ new ContentPage { Content = new Label { Text = "Test 2" }, Title = "Testing 2", Icon = "cover1.jpg" },
+ new ContentPage { Content = new Label { Text = "Test 3" }, Title = "Testing 3", Icon = "cover1.jpg" },
+ new ContentPage { Content = new Label { Text = "Test 4" }, Title = "Testing 4", Icon = "cover1.jpg" },
+ new ContentPage { Content = new Label { Text = "Test 5" }, Title = "Testing 5", Icon = "cover1.jpg" },
+ new ContentPage { Content = new Label { Text = "Test 6" }, Title = "Testing 6", Icon = "cover1.jpg" },
+ new ContentPage { Content = new Label { Text = "Test 7" }, Title = "Testing 7", Icon = "cover1.jpg" },
+ new ContentPage { Content = new Label { Text = "Test 8" }, Title = "Testing 8", Icon = "cover1.jpg" },
+ new ContentPage { Content = new Label { Text = "Test 9" }, Title = "Testing 9", Icon = "cover1.jpg" },
+ new ContentPage { Content = new Label { Text = "Test 10" }, Title = "Testing 10", Icon = "cover1.jpg" },
+ new ContentPage { Content = new Label { Text = "Test 11" }, Title = "Testing 11", Icon = "cover1.jpg" },
+ new ContentPage { Content = new Label { Text = "Test 12" }, Title = "Testing 12", Icon = "cover1.jpg" }
+ }
+ }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/GalleryPages/NavigationPropertiesGallery.cs b/Xamarin.Forms.Controls/GalleryPages/NavigationPropertiesGallery.cs
new file mode 100644
index 00000000..0628cfa8
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/NavigationPropertiesGallery.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class NavigationPropertiesGallery
+ : ContentPage
+ {
+ public NavigationPropertiesGallery ()
+ {
+ var noBack = new ContentPage {
+ Title = "No back button",
+ };
+ NavigationPage.SetHasBackButton (noBack, false);
+ var toggleBackButton = new Button { Text = "Toggle Back Button" };
+ toggleBackButton.Clicked += (sender, e) => {
+ var hasBack = NavigationPage.GetHasBackButton (noBack);
+ if (hasBack)
+ NavigationPage.SetHasBackButton (noBack, false);
+ else
+ NavigationPage.SetHasBackButton (noBack, true);
+ };
+ noBack.Content = toggleBackButton;
+
+
+ var noBar = new ContentPage {
+ Title = "No bar",
+ Content = new Label {
+ Text = "No bar content",
+ Style = Device.Styles.TitleStyle
+ }
+ };
+
+ var backTitle = new ContentPage {
+ Title = "Back button title"
+ };
+
+ NavigationPage.SetHasNavigationBar (noBar, false);
+
+ Content = new ListView {
+ ItemsSource = new[] {
+ noBack,
+ noBar,
+ backTitle
+ },
+
+ ItemTemplate = new DataTemplate (typeof(TextCell)) {
+ Bindings = {
+ { TextCell.TextProperty, new Binding ("Title") }
+ }
+ }
+ };
+
+ ((ListView) Content).ItemTapped += async (sender, args) => {
+ await Navigation.PushAsync ((Page) args.Item);
+ };
+
+ NavigationPage.SetBackButtonTitle (this, "Back Title");
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/OpenGLGallery.cs b/Xamarin.Forms.Controls/GalleryPages/OpenGLGallery.cs
new file mode 100644
index 00000000..bb5ce8ab
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/OpenGLGallery.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+#if HAVE_OPENTK
+using OpenTK.Graphics;
+using OpenTK.Graphics.ES20;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+#if HAVE_OPENTK
+ public class OpenGLGallery : ContentPage
+ {
+ float red, green, blue;
+
+ public OpenGLGallery ()
+ {
+ var view = new OpenGLView {HasRenderLoop = true};
+ var toggle = new Switch {IsToggled = true};
+ var button = new Button {Text = "Display"};
+
+ view.HeightRequest = 300;
+ view.WidthRequest = 300;
+
+ view.OnDisplay = r =>{
+ /*
+ if (!inited) {
+ var shader = GL.CreateShader (All.VertexShader);
+ int length = 0;
+ GL.ShaderSource (shader, 1, new string [] { "void main() { gl_FragColor = vec4(0.6, 1.0, 0.0, 1.0); }"}, ref length);
+ GL.CompileShader (shader);
+ int status = 0;
+ GL.GetShader (shader, All.CompileStatus, ref status);
+ if (status == 0) {
+ GL.DeleteShader (shader);
+ throw new Exception();
+ }
+
+ inited = true;
+ }
+ */
+ GL.ClearColor (red, green, blue, 1.0f);
+ GL.Clear ((ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit));
+
+ red += 0.01f;
+ if (red >= 1.0f)
+ red -= 1.0f;
+ green += 0.02f;
+ if (green >= 1.0f)
+ green -= 1.0f;
+ blue += 0.03f;
+ if (blue >= 1.0f)
+ blue -= 1.0f;
+ };
+
+ toggle.Toggled += (s, a) => { view.HasRenderLoop = toggle.IsToggled; };
+ button.Activated += (s, a) => view.Display ();
+
+ var stack = new StackLayout {Padding = new Size (20, 20)};
+ stack.Add (view);
+ stack.Add (toggle);
+ stack.Add (button);
+
+ Content = stack;
+ }
+ }
+#endif
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/PickerGallery.cs b/Xamarin.Forms.Controls/GalleryPages/PickerGallery.cs
new file mode 100644
index 00000000..676c907a
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/PickerGallery.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class PickerGallery : ContentPage
+ {
+ public PickerGallery ()
+ {
+ var picker = new Picker {Title="Dismiss in one sec", Items = {"John", "Paul", "George", "Ringo"}};
+ picker.Focused += async (object sender, FocusEventArgs e) => {
+ await Task.Delay (1000);
+ picker.Unfocus ();
+ };
+
+ Label testLabel = new Label { Text = "", AutomationId="test", ClassId="test" };
+
+ Picker p1 = new Picker { Title = "Pick a number", Items = { "0", "1", "2", "3", "4", "5", "6" }};
+ p1.SelectedIndexChanged += (sender, e) => {
+ testLabel.Text = "Selected Index Changed";
+ };
+
+ Content = new ScrollView {
+ Content = new StackLayout {
+ Padding = new Thickness (20, 20),
+ Children = {
+ new DatePicker (),
+ new TimePicker (),
+ new DatePicker { Format = "D" },
+ new TimePicker { Format = "T" },
+ new Picker {Title = "Set your favorite Beatle", Items = {"John", "Paul", "George", "Ringo"}},
+ new Picker {Title = "Set your favorite Stone", Items = {"Mick", "Keith", "Charlie", "Ronnie"}, SelectedIndex = 1},
+ new Picker {Title = "Pick", Items = {"Jason Smith", "Rui Marinho", "Eric Maupin", "Chris King"}, HorizontalOptions = LayoutOptions.CenterAndExpand},
+ picker,
+ testLabel,
+ p1
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/ProgressBarGallery.cs b/Xamarin.Forms.Controls/GalleryPages/ProgressBarGallery.cs
new file mode 100644
index 00000000..3190a3cf
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/ProgressBarGallery.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class ProgressBarGallery : ContentPage
+ {
+ readonly StackLayout _stack;
+
+ public ProgressBarGallery ()
+ {
+ _stack = new StackLayout ();
+
+ var normal = new ProgressBar {
+ Progress = 0.24
+ };
+
+ Content = _stack;
+
+ _stack.Children.Add (normal);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/RelativeLayoutGallery.cs b/Xamarin.Forms.Controls/GalleryPages/RelativeLayoutGallery.cs
new file mode 100644
index 00000000..1feaafe6
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/RelativeLayoutGallery.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class RelativeLayoutGallery : ContentPage
+ {
+ public RelativeLayoutGallery()
+ {
+ var layout = new RelativeLayout ();
+
+ var box1 = new ContentView {
+ BackgroundColor = Color.Gray,
+ Content = new Label {
+ Text = "0"
+ }
+ };
+
+ double padding = 10;
+ layout.Children.Add (box1, () => new Rectangle (((layout.Width + padding) % 60) / 2, padding, 50, 50));
+
+ var last = box1;
+ for (int i = 0; i < 200; i++) {
+ var relativeTo = last; // local copy
+ var box = new ContentView {
+ BackgroundColor = Color.Gray,
+ Content = new Label {
+ Text = (i+1).ToString ()
+ }
+ };
+
+ Func<View, bool> pastBounds = view => relativeTo.Bounds.Right + padding + relativeTo.Width > layout.Width;
+ layout.Children.Add (box, () => new Rectangle (pastBounds (relativeTo) ? box1.X : relativeTo.Bounds.Right + padding,
+ pastBounds (relativeTo) ? relativeTo.Bounds.Bottom + padding : relativeTo.Y,
+ relativeTo.Width,
+ relativeTo.Height));
+
+ last = box;
+ }
+
+ Content = new ScrollView {Content = layout, Padding = new Thickness(50)};
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/ScaleRotate.cs b/Xamarin.Forms.Controls/GalleryPages/ScaleRotate.cs
new file mode 100644
index 00000000..e189f839
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/ScaleRotate.cs
@@ -0,0 +1,157 @@
+using System;
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class ScaleRotate : ContentPage
+ {
+ public ScaleRotate()
+ {
+ Label label = new Label
+ {
+ Text = "SCALE AND\nROTATE",
+ HorizontalTextAlignment = TextAlignment.Center,
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+
+ // Label and Slider for Scale property.
+ Label scaleSliderValue = new Label
+ {
+ VerticalTextAlignment = TextAlignment.Center
+ };
+ Grid.SetRow(scaleSliderValue, 0);
+ Grid.SetColumn(scaleSliderValue, 0);
+
+ Slider scaleSlider = new Slider
+ {
+ Maximum = 10
+ };
+ Grid.SetRow(scaleSlider, 0);
+ Grid.SetColumn(scaleSlider, 1);
+
+ // Set Bindings.
+ scaleSliderValue.BindingContext = scaleSlider;
+ scaleSliderValue.SetBinding(Label.TextProperty,
+ new Binding("Value", BindingMode.OneWay, null, null, "Scale = {0:F1}"));
+
+ scaleSlider.BindingContext = label;
+ scaleSlider.SetBinding(Slider.ValueProperty,
+ new Binding("Scale", BindingMode.TwoWay));
+
+ // Label and Slider for Rotation property.
+ Label rotationSliderValue = new Label
+ {
+ VerticalTextAlignment = TextAlignment.Center
+ };
+ Grid.SetRow(rotationSliderValue, 1);
+ Grid.SetColumn(rotationSliderValue, 0);
+
+ Slider rotationSlider = new Slider
+ {
+ Maximum = 360
+ };
+ Grid.SetRow(rotationSlider, 1);
+ Grid.SetColumn(rotationSlider, 1);
+
+ // Set Bindings.
+ rotationSliderValue.BindingContext = rotationSlider;
+ rotationSliderValue.SetBinding(Label.TextProperty,
+ new Binding("Value", BindingMode.OneWay, null, null, "Rotation = {0:F0}"));
+
+ rotationSlider.BindingContext = label;
+ rotationSlider.SetBinding(Slider.ValueProperty,
+ new Binding("Rotation", BindingMode.TwoWay));
+
+ // Label and Slider for AnchorX property.
+ Label anchorxStepperValue = new Label
+ {
+ VerticalTextAlignment = TextAlignment.Center
+ };
+ Grid.SetRow(anchorxStepperValue, 2);
+ Grid.SetColumn(anchorxStepperValue, 0);
+
+ Stepper anchorxStepper = new Stepper
+ {
+ Maximum = 2,
+ Minimum = -1,
+ Increment = 0.5
+ };
+ Grid.SetRow(anchorxStepper, 2);
+ Grid.SetColumn(anchorxStepper, 1);
+
+ // Set bindings.
+ anchorxStepperValue.BindingContext = anchorxStepper;
+ anchorxStepperValue.SetBinding(Label.TextProperty,
+ new Binding("Value", BindingMode.OneWay, null, null, "AnchorX = {0:F1}"));
+
+ anchorxStepper.BindingContext = label;
+ anchorxStepper.SetBinding(Stepper.ValueProperty,
+ new Binding("AnchorX", BindingMode.TwoWay));
+
+ // Label and Slider for AnchorY property.
+ Label anchoryStepperValue = new Label
+ {
+ VerticalTextAlignment = TextAlignment.Center
+ };
+ Grid.SetRow(anchoryStepperValue, 3);
+ Grid.SetColumn(anchoryStepperValue, 0);
+
+ Stepper anchoryStepper = new Stepper
+ {
+ Maximum = 2,
+ Minimum = -1,
+ Increment = 0.5
+ };
+ Grid.SetRow(anchoryStepper, 3);
+ Grid.SetColumn(anchoryStepper, 1);
+
+ // Set bindings.
+ anchoryStepperValue.BindingContext = anchoryStepper;
+ anchoryStepperValue.SetBinding(Label.TextProperty,
+ new Binding("Value", BindingMode.OneWay, null, null, "AnchorY = {0:F1}"));
+
+ anchoryStepper.BindingContext = label;
+ anchoryStepper.SetBinding(Stepper.ValueProperty,
+ new Binding("AnchorY", BindingMode.TwoWay));
+
+ // Assemble the page.
+ Content = new StackLayout
+ {
+ Children =
+ {
+ label,
+ new Grid
+ {
+ Padding = 10,
+ RowDefinitions =
+ {
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto },
+ },
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = GridLength.Auto },
+ new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star)}
+ },
+ Children =
+ {
+ scaleSliderValue,
+ scaleSlider,
+ rotationSliderValue,
+ rotationSlider,
+ anchorxStepperValue,
+ anchorxStepper,
+ anchoryStepperValue,
+ anchoryStepper
+ }
+ }
+ }
+ };
+ }
+ }
+}
+
+
diff --git a/Xamarin.Forms.Controls/GalleryPages/ScrollGallery.cs b/Xamarin.Forms.Controls/GalleryPages/ScrollGallery.cs
new file mode 100644
index 00000000..cf00482d
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/ScrollGallery.cs
@@ -0,0 +1,158 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class ScrollGallery : ContentPage
+ {
+ readonly ScrollView _scrollview;
+ readonly StackLayout _stack;
+ ScrollOrientation _orientation;
+ List<Button> _buttons = new List<Button> ();
+ Button _toNavigateTo;
+ public ScrollGallery (ScrollOrientation orientation = ScrollOrientation.Vertical)
+ {
+ _orientation = orientation;
+ var root = new Grid ();
+ root.RowDefinitions.Add (new RowDefinition () { Height = GridLength.Auto });
+ root.RowDefinitions.Add (new RowDefinition () { Height = GridLength.Auto });
+ root.RowDefinitions.Add (new RowDefinition () { Height = GridLength.Auto });
+ root.RowDefinitions.Add (new RowDefinition ());
+
+ var btnStack1 = new StackLayout { Orientation = StackOrientation.Horizontal };
+ var btnStack = new StackLayout { Orientation = StackOrientation.Horizontal };
+ var btn = new Button { Text = "Scroll to 100" };
+ var btn4 = new Button { Text = "Scroll to 100 no anim" };
+ var btn1 = new Button { Text = "Start" };
+ var btn2 = new Button { Text = "Center" };
+ var btn3 = new Button { Text = "End" };
+ var btn6 = new Button { Text = "MakeVisible", HorizontalOptions= LayoutOptions.CenterAndExpand, BackgroundColor = Color.Accent };
+
+ var label = new Label { Text = string.Format ("X: {0}, Y: {1}", 0, 0) };
+
+ root.Children.Add (label);
+ root.Children.Add (btnStack);
+ root.Children.Add (btnStack1);
+
+ btnStack.Children.Add (btn1);
+ btnStack.Children.Add (btn2);
+ btnStack.Children.Add (btn3);
+
+ btnStack1.Children.Add (btn);
+ btnStack1.Children.Add (btn4);
+
+ Grid.SetRow (btnStack, 1);
+ Grid.SetRow (btnStack1, 2);
+
+ var grid = new Grid ();
+ grid.RowDefinitions.Add (new RowDefinition { Height = GridLength.Auto });
+ grid.RowDefinitions.Add (new RowDefinition ());
+ _stack = new StackLayout ();
+ Grid.SetRow (_stack, 1);
+ grid.Children.Add (btn6);
+ grid.Children.Add (_stack);
+ _scrollview = new ScrollView {
+ AutomationId="thescroller",
+ BackgroundColor = Color.Aqua,
+ Content = grid
+ };
+ root.Children.Add (_scrollview);
+ Grid.SetRow (_scrollview, 3);
+
+ _scrollview.Scrolled+= (object sender, ScrolledEventArgs e) => {
+ label.Text = string.Format ("X: {0}, Y: {1}", e.ScrollX, e.ScrollY);
+ };
+
+ btn.Clicked += async (object sender, EventArgs e) => {
+ switch (orientation) {
+ case ScrollOrientation.Horizontal:
+ await _scrollview.ScrollToAsync (100, 0, true);
+ break;
+ case ScrollOrientation.Vertical:
+ await _scrollview.ScrollToAsync (0, 100, true);
+ break;
+ case ScrollOrientation.Both:
+ await _scrollview.ScrollToAsync (100, 100, true);
+ break;
+ }
+ };
+ btn4.Clicked += async (object sender, EventArgs e) => {
+ switch (orientation) {
+ case ScrollOrientation.Horizontal:
+ await _scrollview.ScrollToAsync (100, 0, false);
+ break;
+ case ScrollOrientation.Vertical:
+ await _scrollview.ScrollToAsync (0, 100, false);
+ break;
+ case ScrollOrientation.Both:
+ await _scrollview.ScrollToAsync (100, 100, true);
+ break;
+ }
+ };
+
+ btn1.Clicked += async (object sender, EventArgs e) => {
+ await _scrollview.ScrollToAsync (_toNavigateTo, ScrollToPosition.Start, true);
+ };
+ btn2.Clicked += async (object sender, EventArgs e) => {
+ await _scrollview.ScrollToAsync (_toNavigateTo, ScrollToPosition.Center, true);
+ };
+ btn3.Clicked += async (object sender, EventArgs e) => {
+ await _scrollview.ScrollToAsync (_toNavigateTo, ScrollToPosition.End, true);
+ };
+ btn6.Clicked += async (object sender, EventArgs e) => {
+ await _scrollview.ScrollToAsync (_toNavigateTo, ScrollToPosition.MakeVisible, true);
+ };
+
+ _stack.Padding = new Size (20, 60);
+
+ PopulateStack (_stack);
+
+ _scrollview.Orientation = _orientation;
+
+ if (orientation == ScrollOrientation.Horizontal || orientation == ScrollOrientation.Both) {
+ _stack.Orientation = StackOrientation.Horizontal;
+ }
+
+ if (orientation == ScrollOrientation.Both) {
+ var stack2 = new StackLayout ();
+ PopulateStack (stack2);
+ _stack.Children.Add (stack2);
+ }
+
+ Content = root;
+ }
+
+ void PopulateStack (StackLayout stack)
+ {
+ for (int i = 0; i < 100; i++) {
+
+ var newButton = new Button { Text = "Foo Bar", AutomationId =string.Format ("btn_{0}", i) };
+ if (i == 49)
+ newButton.Text = "the before";
+
+ if (i == 50) {
+ newButton.Text = "the scrollto button";
+ newButton.BackgroundColor = Color.Yellow;
+ newButton.TextColor = Color.Black;
+ _toNavigateTo = newButton;
+ }
+ if (i == 51)
+ newButton.Text = "the after";
+ if (i == 53) {
+ newButton.Text = "the make visible from start";
+ newButton.Clicked += async (object sender, EventArgs e) => {
+ await _scrollview.ScrollToAsync (_toNavigateTo, ScrollToPosition.MakeVisible, true);
+ };
+ }
+
+ _buttons.Add (newButton);
+ stack.Children.Add (newButton);
+ }
+
+ stack.Children.Add (new Button { Text = "Foo Bottom" });
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/SearchBarGallery.cs b/Xamarin.Forms.Controls/GalleryPages/SearchBarGallery.cs
new file mode 100644
index 00000000..c0b91e7e
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/SearchBarGallery.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class SearchBarGallery : ContentPage
+ {
+ Label _searchQueryLabel;
+
+ public SearchBarGallery ()
+ {
+ _searchQueryLabel = new Label {
+ Text = "Search Query"
+ };
+
+ var textChangedLabel = new Label {
+ Text = ""
+ };
+
+ var numCharsTyped = 0;
+
+ var noPlaceholder = new SearchBar();
+ noPlaceholder.SearchButtonPressed += OnSearchBarPressed;
+ noPlaceholder.TextChanged += (sender, e) => {
+ numCharsTyped++;
+ textChangedLabel.Text = numCharsTyped.ToString ();
+ };
+
+ var normal = new SearchBar { Placeholder = "Normal" };
+ normal.SearchButtonPressed += OnSearchBarPressed;
+ normal.TextChanged += (sender, e) => {
+ numCharsTyped++;
+ textChangedLabel.Text = numCharsTyped.ToString ();
+ };
+
+ var activation = new SearchBar { Placeholder = "Activation" };
+ activation.SearchButtonPressed += OnSearchBarPressed;
+ activation.TextChanged += (sender, e) => {
+ numCharsTyped++;
+ textChangedLabel.Text = numCharsTyped.ToString ();
+ };
+
+ var nextPageButton = new Button {
+ Text = "More SearchBars",
+ Command = new Command (async () => await Navigation.PushAsync (new SearchBarGalleryPageTwo ()))
+ };
+
+ int i = 1;
+ activation.SearchButtonPressed += (sender, e) => {
+ activation.Text = "";
+ activation.Placeholder = "Activated " + i++.ToString ();
+ };
+
+ Content = new ScrollView {
+ Content = new StackLayout {
+ Spacing = 0,
+ Children = {
+ noPlaceholder,
+ normal,
+ activation,
+ _searchQueryLabel,
+ textChangedLabel,
+ nextPageButton
+ }
+ }
+ };
+ }
+
+ void OnSearchBarPressed(object sender, EventArgs eventArgs)
+ {
+ var searchBar = (SearchBar)sender;
+ _searchQueryLabel.Text = searchBar.Text;
+ }
+ }
+
+ public class SearchBarGalleryPageTwo : ContentPage
+ {
+ Label _searchQueryLabel;
+
+ public SearchBarGalleryPageTwo ()
+ {
+ Title = "Search Bar Gallery Part 2";
+
+ _searchQueryLabel = new Label {
+ Text = "Search Query 2"
+ };
+
+ var disabled = new SearchBar { Placeholder = "Disabled", IsEnabled = false };
+ disabled.SearchButtonPressed += OnSearchBarPressed;
+ var transparent = new SearchBar { Placeholder = "Transparent", Opacity = 0.5 };
+ transparent.SearchButtonPressed += OnSearchBarPressed;
+
+ var toggleDisabledButton = new Button {
+ Text = "Toggle enabled",
+ Command = new Command (() => {
+ if (disabled.IsEnabled) {
+ disabled.IsEnabled = false;
+ disabled.Placeholder = "Disabled";
+ } else {
+ disabled.IsEnabled = true;
+ disabled.Placeholder = "Enabled";
+ }
+ })
+ };
+
+ Content = new ScrollView {
+ Content = new StackLayout {
+ Spacing = 0,
+ Children = {
+ disabled,
+ transparent,
+ _searchQueryLabel,
+ toggleDisabledButton
+ }
+ }
+ };
+ }
+
+ void OnSearchBarPressed(object sender, EventArgs eventArgs)
+ {
+ var searchBar = (SearchBar)sender;
+ _searchQueryLabel.Text = searchBar.Text;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/SettingsPage.cs b/Xamarin.Forms.Controls/GalleryPages/SettingsPage.cs
new file mode 100644
index 00000000..b60af114
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/SettingsPage.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class SettingsPage : ContentPage
+ {
+ SettingsScreen _settingsScreen;
+ public SettingsPage ()
+ {
+ _settingsScreen = new SettingsScreen ();
+ Content = _settingsScreen;
+ }
+ }
+
+ public class SettingsScreen : TableView
+ {
+ public SettingsScreen ()
+ {
+ Intent = TableIntent.Settings;
+ var cell = new TextCell { Text = "Coverflow", Detail = "Value 1" };
+
+ var boolCell = new SwitchCell { Text = "Off" };
+ boolCell.OnChanged += (sender, arg) => boolCell.Text = boolCell.On ? "On" : "Off";
+
+ var root = new TableRoot () {
+ new TableSection () {
+ cell,
+ new TextCell { Text = "Cell 2", Detail = "Value 2" },
+ new EntryCell {
+ Label = "Label",
+ Placeholder = "Placeholder 1",
+ HorizontalTextAlignment = TextAlignment.Center,
+ Keyboard = Keyboard.Numeric
+ },
+ new ImageCell { Text = "Hello", Detail = "World", ImageSource = "cover1.jpg" }
+ },
+ new TableSection ("Styles") {
+ boolCell,
+ new EntryCell {
+ Label = "Label2",
+ Placeholder = "Placeholder 2",
+ HorizontalTextAlignment = TextAlignment.Center,
+ Keyboard = Keyboard.Chat
+ },
+ },
+ new TableSection ("Custom Cells") {
+ new ViewCell { View = new Button (){ Text = "Hi" } },
+ }
+ };
+ Root = root;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/SliderGallery.cs b/Xamarin.Forms.Controls/GalleryPages/SliderGallery.cs
new file mode 100644
index 00000000..4fd9f20c
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/SliderGallery.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class SliderGallery : ContentPage
+ {
+ public SliderGallery ()
+ {
+ var normal = new Slider (20, 100, 20);
+ var disabled = new Slider (0, 1, 0);
+ var transparent = new Slider (0, 1, 0);
+ var valueLabel = new Label { Text = normal.Value.ToString () };
+
+ disabled.IsEnabled = false;
+ transparent.Opacity = .5;
+ normal.ValueChanged += (sender, e) => { valueLabel.Text = normal.Value.ToString (); };
+
+ Content = new StackLayout {
+ Padding = new Thickness (40),
+ Children = {
+ normal,
+ disabled,
+ transparent,
+ valueLabel
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/StackLayoutGallery.cs b/Xamarin.Forms.Controls/GalleryPages/StackLayoutGallery.cs
new file mode 100644
index 00000000..b08b5f35
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/StackLayoutGallery.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class StackLayoutGallery : ContentPage
+ {
+ public StackLayoutGallery ()
+ {
+ Device.OnPlatform (iOS: () => {
+ if (Device.Idiom == TargetIdiom.Tablet) {
+ Padding = new Thickness (0, 0, 0, 60);
+ }
+ });
+
+ var stack = new StackLayout { Orientation = StackOrientation.Vertical };
+ Button b1 = new Button { Text = "Boring", HeightRequest = 500, MinimumHeightRequest = 50 };
+ Button b2 = new Button {
+ Text = "Exciting!",
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.CenterAndExpand
+ };
+ Button b3 = new Button { Text = "Amazing!", VerticalOptions = LayoutOptions.FillAndExpand };
+ Button b4 = new Button { Text = "Meh", HeightRequest = 400, MinimumHeightRequest = 50 };
+ b1.Clicked += (sender, e) => {
+ b1.Text = "clicked1";
+ };
+ b2.Clicked += (sender, e) => {
+ b2.Text = "clicked2";
+ };
+ b3.Clicked += (sender, e) => {
+ b3.Text = "clicked3";
+ };
+ b4.Clicked += (sender, e) => {
+ b4.Text = "clicked4";
+ };
+ stack.Children.Add (b1);
+ stack.Children.Add (b2);
+ stack.Children.Add (b3);
+ stack.Children.Add (b4);
+ Content = stack;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/StepperGallery.cs b/Xamarin.Forms.Controls/GalleryPages/StepperGallery.cs
new file mode 100644
index 00000000..6da9bba4
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/StepperGallery.cs
@@ -0,0 +1,49 @@
+using System;
+
+namespace Xamarin.Forms.Controls
+{
+ public class StepperGallery : ContentPage
+ {
+ public StepperGallery ()
+ {
+ var stepper = new Stepper {
+ Minimum = 0,
+ Maximum = 100,
+ Increment = 10
+ };
+
+ var label = new Label {
+ Text = stepper.Value.ToString()
+ };
+
+ stepper.ValueChanged += (s, e) => {
+ label.Text = e.NewValue.ToString();
+ };
+
+ var stepperTwo = new Stepper {
+ Minimum = 0.0,
+ Maximum = 1.0,
+ Increment = 0.05
+ };
+
+ var labelTwo = new Label {
+ Text = stepperTwo.Value.ToString ()
+ };
+
+ stepperTwo.ValueChanged += (s, e) => {
+ labelTwo.Text = e.NewValue.ToString ();
+ };
+
+ Content = new StackLayout {
+ Padding = new Thickness (20),
+ Children = {
+ stepper,
+ label,
+ stepperTwo,
+ labelTwo
+ }
+ };
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls/GalleryPages/StyleGallery.cs b/Xamarin.Forms.Controls/GalleryPages/StyleGallery.cs
new file mode 100644
index 00000000..6ae2d846
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/StyleGallery.cs
@@ -0,0 +1,41 @@
+using System;
+
+namespace Xamarin.Forms.Controls
+{
+ public class StyleGallery:ContentPage
+ {
+ public StyleGallery ()
+ {
+ Content = new StackLayout {
+ Children = {
+ new Label {
+ Text = "This uses TitleStyle",
+ Style = Device.Styles.TitleStyle
+ },
+ new Label {
+ Text = "This uses SubtitleStyle",
+ Style = Device.Styles.SubtitleStyle
+ },
+ new Label {
+ Text = "This uses BodyStyle",
+ Style = Device.Styles.BodyStyle
+ },
+ new Label {
+ Text = "This uses CaptionStyle",
+ Style = Device.Styles.CaptionStyle
+ },
+ new Label {
+ Text = "This uses a custom style inherited dynamically from SubtitleStyle",
+ Style = new Style (typeof(Label)) {
+ BaseResourceKey = Device.Styles.SubtitleStyleKey,
+ Setters = {
+ new Setter {Property = Label.TextColorProperty, Value = Color.Pink}
+ }
+ }
+ },
+ }
+ };
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls/GalleryPages/StyleXamlGallery.xaml b/Xamarin.Forms.Controls/GalleryPages/StyleXamlGallery.xaml
new file mode 100644
index 00000000..524db152
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/StyleXamlGallery.xaml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Forms.Controls.StyleXamlGallery">
+<ContentPage.Resources>
+ <ResourceDictionary>
+ <Style x:Key="customStyle" TargetType="Label" BaseResourceKey="SubtitleStyle">
+ <Setter Property="Label.TextColor" Value="Color.Pink"/>
+ </Style>
+ </ResourceDictionary>
+</ContentPage.Resources>
+ <StackLayout>
+ <Label Text="This uses TitleStyle" Style="{DynamicResource TitleStyle}"/>
+ <Label Text="This uses SubtitleStyle" Style="{DynamicResource SubtitleStyle}"/>
+ <Label Text="This uses BodyStyle" Style="{DynamicResource BodyStyle}"/>
+ <Label Text="This uses CaptionStyle" Style="{DynamicResource CaptionStyle}"/>
+ <Label Text="This uses a custom style inherited from SubtitleStyle" Style="{StaticResource customStyle}"/>
+ </StackLayout>
+</ContentPage>
diff --git a/Xamarin.Forms.Controls/GalleryPages/StyleXamlGallery.xaml.cs b/Xamarin.Forms.Controls/GalleryPages/StyleXamlGallery.xaml.cs
new file mode 100644
index 00000000..39837222
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/StyleXamlGallery.xaml.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Controls
+{
+ public partial class StyleXamlGallery : ContentPage
+ {
+ public StyleXamlGallery ()
+ {
+ InitializeComponent ();
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls/GalleryPages/SwitchGallery.cs b/Xamarin.Forms.Controls/GalleryPages/SwitchGallery.cs
new file mode 100644
index 00000000..efdf623b
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/SwitchGallery.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class SwitchGallery : ContentPage
+ {
+ public SwitchGallery ()
+ {
+ var testLabel = new Label {
+ Text = "Test Label"
+ };
+
+ var normal = new Switch { IsToggled = true };
+ var disabled = new Switch ();
+ var transparent = new Switch ();
+ var stepper = new Stepper ();
+
+ normal.Toggled += (sender, e) => {
+ testLabel.Text = "Toggled normal switch";
+ };
+
+ disabled.Toggled += (sender, e) => {
+ testLabel.Text = "Toggled disabled switch (magic)";
+ };
+
+ transparent.Toggled += (sender, e) => {
+ testLabel.Text = "Toggled transparent switch";
+ };
+
+ stepper.ValueChanged += (sender, e) => {
+ testLabel.Text = stepper.Value.ToString ();
+ };
+
+ disabled.IsEnabled = false;
+ transparent.Opacity = 0.5;
+
+ Content = new StackLayout {
+ Padding = new Thickness (20),
+ Children = {
+ testLabel,
+ normal,
+ disabled,
+ transparent,
+ stepper,
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/TableViewGallery.cs b/Xamarin.Forms.Controls/GalleryPages/TableViewGallery.cs
new file mode 100644
index 00000000..92e5c1cc
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/TableViewGallery.cs
@@ -0,0 +1,24 @@
+namespace Xamarin.Forms.Controls
+{
+ internal class TableViewGallery : ContentPage
+ {
+ public TableViewGallery () {
+
+ var section = new TableSection ("Section One") {
+ new ViewCell { View = new Label { Text = "View Cell 1" } },
+ new ViewCell { View = new Label { Text = "View Cell 2" } }
+ };
+
+ var root = new TableRoot ("Table") {
+ section
+ };
+
+ var tableLayout = new TableView {
+ Root = root,
+ RowHeight = 100
+ };
+
+ Content = tableLayout;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/TemplatedCarouselGallery.cs b/Xamarin.Forms.Controls/GalleryPages/TemplatedCarouselGallery.cs
new file mode 100644
index 00000000..2d9cfe11
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/TemplatedCarouselGallery.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class TemplatedCarouselGallery
+ : CarouselPage
+ {
+ ObservableCollection<Item> _items;
+ int _count = 0;
+
+ public TemplatedCarouselGallery()
+ {
+ NavigationPage.SetHasNavigationBar (this, false);
+
+ _items = new ObservableCollection<Item> {
+ CreateItem(),
+ CreateItem(),
+ };
+
+ ItemsSource = _items;
+
+ ItemTemplate = new DataTemplate (() => {
+ var page = new ContentPage ();
+
+ page.Padding = new Thickness (0,30,0,0);
+ page.SetBinding (TitleProperty, "Title");
+
+ var layout = new StackLayout { Spacing = 0 };
+
+ var label = new Label();
+ label.SetBinding (Label.TextProperty, "Content");
+ layout.Children.Add (label);
+
+ var swipeHereLabel = new Label {
+ Text = "Swipe Here",
+ HeightRequest = 40
+ };
+
+ layout.Children.Add (swipeHereLabel);
+
+ var add = new Button ();
+ add.SetBinding (Button.TextProperty, "InsertTabText");
+ add.Clicked += (sender, args) => _items.Insert (_items.IndexOf ((Item)add.BindingContext) + 1, CreateItem());
+ layout.Children.Add (add);
+
+ var change = new Button ();
+ change.SetBinding (Button.TextProperty, "ChangeTitleText");
+ change.Clicked += (sender, args) => ((Item) change.BindingContext).Title = (new Random().Next().ToString());
+ layout.Children.Add (change);
+
+ var remove = new Button ();
+ remove.SetBinding (Button.TextProperty, "RemoveTabText");
+ remove.Clicked += (sender, args) => _items.Remove ((Item)remove.BindingContext);
+ layout.Children.Add (remove);
+
+ var reset = new Button ();
+ reset.SetBinding (Button.TextProperty, "ResetAllTabsText");
+ reset.Clicked += (sender, args) => {
+ _count = 0;
+ ItemsSource = _items = new ObservableCollection<Item> { CreateItem(), CreateItem() };
+ };
+ layout.Children.Add (reset);
+
+ var nextPage = new Button ();
+ nextPage.SetBinding (Button.TextProperty, "NextPageText");
+ nextPage.Clicked += (sender, args) => {
+ int index = _items.IndexOf ((Item) nextPage.BindingContext) + 1;
+ if (index == _items.Count)
+ index = 0;
+
+ SelectedItem = _items[index];
+ };
+ layout.Children.Add (nextPage);
+
+ var delayReset = new Button { Text = "Delayed reset" };
+ delayReset.SetBinding (Button.TextProperty, "DelayedResetText");
+ delayReset.Clicked += (sender, args) => {
+ ItemsSource = null;
+
+ Task.Delay (5000).ContinueWith (t => {
+ _count = 0;
+ ItemsSource = _items = new ObservableCollection<Item> { CreateItem(), CreateItem() };
+ }, TaskScheduler.FromCurrentSynchronizationContext());
+ };
+
+ layout.Children.Add (delayReset);
+
+ page.Content = new ScrollView {
+ Padding = new Thickness (60, 0),
+ Content = layout
+ };
+ return page;
+ });
+ }
+
+ Item CreateItem()
+ {
+ int x = _count++;
+ return new Item {
+ Title = "Page " + x,
+ Content = "Lorem ipsum dolor sit amet #" + x,
+ InsertTabText = "Insert Tab: " + x,
+ ChangeTitleText = "Change title: " + x,
+ MoveTabText = "Move Tab: " + x,
+ RemoveTabText = "Remove Tab: " + x,
+ ResetAllTabsText = "Reset all tabs: " + x,
+ NextPageText = "Next Page: " + x,
+ DelayedResetText = "Delayed reset: " + x
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/TemplatedTabbedGallery.cs b/Xamarin.Forms.Controls/GalleryPages/TemplatedTabbedGallery.cs
new file mode 100644
index 00000000..014b77e5
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/TemplatedTabbedGallery.cs
@@ -0,0 +1,169 @@
+using System;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ internal class Item
+ : INotifyPropertyChanged
+ {
+ string _title;
+ string _content;
+ public string InsertTabText { get; set; }
+ public string ChangeTitleText { get; set; }
+ public string MoveTabText { get; set; }
+ public string RemoveTabText { get; set; }
+ public string ResetAllTabsText { get; set; }
+ public string NextPageText { get; set; }
+ public string DelayedResetText { get; set; }
+
+ public string Icon { get; set; }
+
+ public string Title
+ {
+ get { return _title; }
+ set
+ {
+ if (_title == value)
+ return;
+
+ _title = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public string Content
+ {
+ get { return _content; }
+ set
+ {
+ if (_content == value)
+ return;
+
+ _content = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+
+ internal class TemplatedTabbedGallery : TabbedPage
+ {
+ ObservableCollection<Item> _items;
+ int _count = 0;
+
+ public TemplatedTabbedGallery()
+ {
+ Title = "Templated Tabbed Gallery";
+ _items = new ObservableCollection<Item> {
+ CreateItem(),
+ CreateItem()
+ };
+
+ ItemsSource = _items;
+
+ ItemTemplate = new DataTemplate (() => {
+ var page = new ContentPage();
+ page.SetBinding (TitleProperty, "Title");
+ page.SetBinding (IconProperty, "Icon");
+
+ var layout = new StackLayout();
+
+ var label = new Label();
+ label.SetBinding (Label.TextProperty, "Content");
+ layout.Children.Add (label);
+
+ var add = new Button ();
+ add.SetBinding (Button.TextProperty, "InsertTabText");
+ add.Clicked += (sender, args) => _items.Insert (_items.IndexOf ((Item)add.BindingContext) + 1, CreateItem());
+ layout.Children.Add (add);
+
+ var titleNum = 0;
+ var change = new Button ();
+ change.SetBinding (Button.TextProperty, "ChangeTitleText");
+ change.Clicked += (sender, args) => ((Item) change.BindingContext).Title = ("Title: " + titleNum++);
+ layout.Children.Add (change);
+
+ var move = new Button ();
+ move.SetBinding (Button.TextProperty, "MoveTabText");
+ move.Clicked += (sender, args) => {
+ int originalIndex = _items.IndexOf ((Item) add.BindingContext);
+ int index = originalIndex + 1;
+ if (index == _items.Count)
+ index = 0;
+
+ _items.Move (originalIndex, index);
+ };
+ layout.Children.Add (move);
+
+ var remove = new Button ();
+ remove.SetBinding (Button.TextProperty, "RemoveTabText");
+ remove.Clicked += (sender, args) => {
+ if (_items.Count == 0) {
+ layout.Children.Add (new Label {
+ Text = "No more tabs"
+ });
+ }
+ _items.Remove ((Item)remove.BindingContext);
+ };
+ layout.Children.Add (remove);
+
+ var reset = new Button ();
+ reset.SetBinding (Button.TextProperty, "ResetAllTabsText");
+ reset.Clicked += (sender, args) => {
+ _count = 0;
+ ItemsSource = _items = new ObservableCollection<Item> { CreateItem(), CreateItem() };
+ };
+ layout.Children.Add (reset);
+
+ var nextPage = new Button ();
+ nextPage.SetBinding (Button.TextProperty, "NextPageText");
+ nextPage.Clicked += (sender, args) => {
+ int index = _items.IndexOf ((Item) nextPage.BindingContext) + 1;
+ if (index == _items.Count)
+ index = 0;
+
+ SelectedItem = _items[index];
+ };
+ layout.Children.Add (nextPage);
+
+ page.Content = new ScrollView {
+ Padding = new Thickness (20, 0),
+ Content = layout
+ };
+
+ return page;
+ });
+ }
+
+ Item CreateItem()
+ {
+ int x = _count++;
+ var item = new Item {
+ Title = "Page " + x,
+ Content = "Lorem ipsum dolor sit amet #" + x ,
+ InsertTabText = "Insert Tab: " + x,
+ ChangeTitleText = "Change title: " + x,
+ MoveTabText = "Move Tab: " + x,
+ RemoveTabText = "Remove Tab: " + x,
+ ResetAllTabsText = "Reset all tabs: " + x,
+ NextPageText = "Next Page: " + x
+ };
+
+ if (x == 0)
+ item.Icon = "bank.png";
+
+ return item;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/ToolbarGallery.cs b/Xamarin.Forms.Controls/GalleryPages/ToolbarGallery.cs
new file mode 100644
index 00000000..b2be5f02
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/ToolbarGallery.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class ToolbarGallery : ContentPage
+ {
+ readonly Toolbar _toolbar;
+ readonly StackLayout _stack;
+
+ public ToolbarGallery ()
+ {
+ var label = new Label {
+ Text = "Click the toolbar"
+ };
+
+ Content = _stack = new StackLayout ();
+ _stack.Children.Add (label);
+
+ foreach (string name in new[] { "One", "Two", "Three", "Four" }) {
+ var toolbarItem = new ToolbarItem (name, null, delegate {
+ label.Text = "Activated: " + name;
+ }, ToolbarItemOrder.Secondary);
+ ToolbarItems.Add (toolbarItem);
+ }
+
+ var imagePrimaryItem = new ToolbarItem (null, "menuIcon.png", () => label.Text = "Activated: Primary Image 1", ToolbarItemOrder.Primary);
+ var imagePrimaryItemWithTitle = new ToolbarItem ("Primary", "menuIcon.png", () => label.Text = "Activated: Primary Image 2", ToolbarItemOrder.Primary);
+ var imageItem = new ToolbarItem (null, "seth.png", () => label.Text = "Activated: Secondary Image 1", ToolbarItemOrder.Secondary);
+ var imageItemWithTitle = new ToolbarItem ("Secondary", "seth.png", () => label.Text = "Activated: Secondary Image 2", ToolbarItemOrder.Secondary);
+ ToolbarItems.Add (imagePrimaryItem);
+ ToolbarItems.Add (imagePrimaryItemWithTitle);
+ ToolbarItems.Add (imageItem);
+ ToolbarItems.Add (imageItemWithTitle);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/UnevenListGallery.cs b/Xamarin.Forms.Controls/GalleryPages/UnevenListGallery.cs
new file mode 100644
index 00000000..1c8b16c4
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/UnevenListGallery.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class UnevenListGallery : ContentPage
+ {
+ public UnevenListGallery ()
+ {
+ Padding = new Thickness (0, 20, 0, 0);
+
+ var list = new ListView {
+ HasUnevenRows = true
+ };
+
+ bool next = true;
+ list.ItemTemplate = new DataTemplate (() => {
+ bool tall = next;
+ next = !next;
+
+ var cell = new TextCell {
+ Height = (tall) ? 88 : 44
+ };
+
+ cell.SetBinding (TextCell.TextProperty, ".");
+ return cell;
+ });
+
+ list.ItemsSource = new[] { "Tall", "Short", "Tall", "Short" };
+
+ var listViewCellDynamicHeight = new ListView {
+ HasUnevenRows = true,
+ AutomationId= "unevenCellListGalleryDynamic"
+ };
+
+ listViewCellDynamicHeight.ItemsSource = new [] {
+ @"That Flesh is heir to? 'Tis a consummation
+Devoutly to be wished. To die, to sleep,
+To sleep, perchance to Dream; Aye, there's the rub,
+For in that sleep of death, what dreams may come,That Flesh is heir to? 'Tis a consummation
+Devoutly to be wished. To die, to sleep,
+To sleep, perchance to Dream; Aye, there's the rub,
+For in that sleep of death, what dreams may come",
+ };
+
+ listViewCellDynamicHeight.ItemTemplate = new DataTemplate (typeof(UnevenRowsCell));
+
+ listViewCellDynamicHeight.ItemTapped += (sender, e) => {
+ if (e == null)
+ return; // has been set to null, do not 'process' tapped event
+ ((ListView)sender).SelectedItem = null; // de-select the row
+ };
+
+ var grd = new Grid ();
+
+ grd.RowDefinitions.Add (new RowDefinition ());
+ grd.RowDefinitions.Add (new RowDefinition ());
+
+ grd.Children.Add (listViewCellDynamicHeight);
+ grd.Children.Add (list);
+
+ Grid.SetRow (list, 1);
+
+ Content = grd;
+ }
+
+ public class UnevenRowsCell : ViewCell
+ {
+ public UnevenRowsCell ()
+ {
+ var label1 = new Label {
+ Text = "Label 1",
+ FontSize = Device.GetNamedSize (NamedSize.Small, typeof(Label))
+ };
+ label1.SetBinding (Label.TextProperty, new Binding ("."));
+
+ View = new StackLayout {
+ Orientation = StackOrientation.Vertical,
+ VerticalOptions = LayoutOptions.StartAndExpand,
+ Padding = new Thickness (15, 5, 5, 5),
+ Children = { label1 }
+ };
+ }
+ // This is the code used before and still works by setting the height of the cell
+ // const int avgCharsInRow = 35;
+ // const int defaultHeight = 44;
+ // const int extraLineHeight = 20;
+ // protected override void OnBindingContextChanged ()
+ // {
+ // base.OnBindingContextChanged ();
+ //
+ // if (Device.OS == TargetPlatform.iOS) {
+ // var text = (string)BindingContext;
+ //
+ // var len = text.Length;
+ //
+ // if (len < (avgCharsInRow * 2)) {
+ // // fits in one cell
+ // Height = defaultHeight;
+ // } else {
+ // len = len - (avgCharsInRow * 2);
+ // var extraRows = len / 35;
+ // Height = defaultHeight + extraRows * extraLineHeight;
+ // }
+ // }
+ // }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/WebViewGallery.cs b/Xamarin.Forms.Controls/GalleryPages/WebViewGallery.cs
new file mode 100644
index 00000000..c39e7777
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/WebViewGallery.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ public class WebViewGallery : ContentPage
+ {
+ class ViewModel
+ {
+ public string Html { get; set; } = "<html><body><p>This is a WebView!</p></body></html>";
+
+ public string Url { get; set; } = "http://xamarin.com";
+
+ }
+
+ public WebViewGallery ()
+ {
+ var htmlWebView = new WebView {
+ HeightRequest = 40,
+ //Source = new HtmlWebViewSource {Html ="<html><body><p>This is a WebView!</p></body></html>"}
+ };
+ var urlWebView = new WebView {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ //Source = new UrlWebViewSource {Url = "http://xamarin.com/"}
+ };
+
+ var htmlSource = new HtmlWebViewSource ();
+ htmlSource.SetBinding (HtmlWebViewSource.HtmlProperty, "HTML");
+ htmlWebView.Source = htmlSource;
+
+ var urlSource = new UrlWebViewSource ();
+ urlSource.SetBinding (UrlWebViewSource.UrlProperty, "URL");
+ urlWebView.Source = urlSource;
+
+ var viewModel = new ViewModel ();
+ BindingContext = viewModel;
+
+ Content = new StackLayout {
+ Padding = new Size (20, 20),
+ Children = {
+ htmlWebView,
+ urlWebView
+ }
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/GalleryPages/XamlPage.xaml b/Xamarin.Forms.Controls/GalleryPages/XamlPage.xaml
new file mode 100644
index 00000000..bbd6e334
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/XamlPage.xaml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Forms.Controls.XamlPage">
+ <Label Text="Hello, Xaml" VerticalOptions="Center" HorizontalOptions="CenterAndExpand"/>
+</ContentPage>
diff --git a/Xamarin.Forms.Controls/GalleryPages/XamlPage.xaml.cs b/Xamarin.Forms.Controls/GalleryPages/XamlPage.xaml.cs
new file mode 100644
index 00000000..636ef608
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/XamlPage.xaml.cs
@@ -0,0 +1,13 @@
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Controls
+{
+ public partial class XamlPage : ContentPage
+ {
+ public XamlPage ()
+ {
+ InitializeComponent ();
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls/GalleryPages/crimson.jpg b/Xamarin.Forms.Controls/GalleryPages/crimson.jpg
new file mode 100644
index 00000000..3db7bb21
--- /dev/null
+++ b/Xamarin.Forms.Controls/GalleryPages/crimson.jpg
Binary files differ
diff --git a/Xamarin.Forms.Controls/Helpers/ITestCloudService.cs b/Xamarin.Forms.Controls/Helpers/ITestCloudService.cs
new file mode 100644
index 00000000..41875368
--- /dev/null
+++ b/Xamarin.Forms.Controls/Helpers/ITestCloudService.cs
@@ -0,0 +1,12 @@
+namespace Xamarin.Forms.Controls
+{
+ public interface ITestCloudService
+ {
+ bool IsOnTestCloud ();
+
+ string GetTestCloudDeviceName ();
+
+ string GetTestCloudDevice ();
+ }
+}
+
diff --git a/Xamarin.Forms.Controls/LegacyRepro/Page1.xaml b/Xamarin.Forms.Controls/LegacyRepro/Page1.xaml
new file mode 100644
index 00000000..52990d9a
--- /dev/null
+++ b/Xamarin.Forms.Controls/LegacyRepro/Page1.xaml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:CustomViewCell="clr-namespace:App2;assembly=Xamarin.Forms.Controls"
+ x:Class="App2.Page1">
+ <ListView x:Name="itemListView" RowHeight="75" HeightRequest="700" SeparatorColor="#061018" BackgroundColor="Blue" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <CustomViewCell:SampleViewCell />
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/LegacyRepro/Page1.xaml.cs b/Xamarin.Forms.Controls/LegacyRepro/Page1.xaml.cs
new file mode 100644
index 00000000..8bed2771
--- /dev/null
+++ b/Xamarin.Forms.Controls/LegacyRepro/Page1.xaml.cs
@@ -0,0 +1,193 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms;
+
+namespace App2
+{
+ public partial class Page1 : ContentPage
+ {
+ public Page1()
+ {
+ InitializeComponent();
+
+ ObservableCollection<CheckListDetails> objlist = new ObservableCollection<CheckListDetails>();
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Completed });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Completed });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Completed });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Completed });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "ActionAction", ChecklistStatus = CheckListStatus.Completed });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Completed });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "ActionAction", ChecklistStatus = CheckListStatus.Completed });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.OverRide });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.OverRide });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.OverRide });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.OverRide });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "ActionAction", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "ActionAction", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Completed });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.OverRide });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "ActionAction", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "ActionAction", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.OverRide });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "ActionAction", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "Action", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "ActionAction", ChecklistStatus = CheckListStatus.Default });
+ objlist.Add(new CheckListDetails() { CallOut = "AAAAA", Action = "", ChecklistStatus = CheckListStatus.Default });
+
+
+ itemListView.ItemsSource = objlist;
+ }
+ }
+
+ public class CheckListDetails
+ {
+ string _callout;
+ string _action;
+ string _currentStatusD;
+
+ CheckListStatus _checklistStatus = CheckListStatus.Default;
+
+ public CheckListDetails()
+ {
+ _currentStatusD = string.Empty;
+ }
+
+ public CheckListStatus ChecklistStatus
+ {
+ get { return _checklistStatus; }
+ set
+ {
+ if (value == CheckListStatus.Default)
+ {
+
+ }
+
+ SetProperty(ref _checklistStatus, value);
+ }
+ }
+
+ public string CurrentStatusD
+ {
+ get { return _currentStatusD; }
+ set { SetProperty(ref _currentStatusD, value); }
+ }
+
+ public string Action
+ {
+ get { return _action; }
+ set { SetProperty(ref _action, value); }
+ }
+
+ public string CallOut
+ {
+ get { return _callout; }
+ set { SetProperty(ref _callout, value); }
+ }
+
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
+ {
+ if (Equals(storage, value))
+ {
+ return false;
+ }
+
+ storage = value;
+ OnPropertyChanged(propertyName);
+ return true;
+ }
+
+ protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ var handler = PropertyChanged;
+
+ if (handler != null)
+ {
+ PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+ }
+
+ public enum CheckListStatus
+ {
+ Default,
+ Completed,
+ Pending,
+ OverRide
+ }
+}
diff --git a/Xamarin.Forms.Controls/LegacyRepro/SampleViewCell.xaml b/Xamarin.Forms.Controls/LegacyRepro/SampleViewCell.xaml
new file mode 100644
index 00000000..f360b4d8
--- /dev/null
+++ b/Xamarin.Forms.Controls/LegacyRepro/SampleViewCell.xaml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="App2.SampleViewCell">
+ <ViewCell.View>
+ <Grid x:Name="OuterGrid" HeightRequest="75" HorizontalOptions="FillAndExpand" VerticalOptions="Start" BackgroundColor="Red" Padding="20,0,30,0">
+ <!--<Grid.Resources>
+ <ResourceDictionary>
+ <FormsLib:StringToColorConverter x:Key="StringToColorConverter" />
+ </ResourceDictionary>
+ </Grid.Resources>-->
+ <Grid.GestureRecognizers>
+ <TapGestureRecognizer Tapped="Checklist_tapped" />
+ </Grid.GestureRecognizers>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="50" />
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="Auto" />
+ </Grid.ColumnDefinitions>
+
+ <Image x:Name="completedimg" HorizontalOptions="Start" VerticalOptions="Center" Grid.Row="0" Grid.Column="0" IsVisible="true"/>
+
+ <Label Text="{Binding CallOut}" TextColor="Yellow" FontSize="17" FontFamily="Roboto" XAlign="Start" HorizontalOptions="Start" VerticalOptions="Center" Grid.Row="0" Grid.Column="1" />
+ <Label Text="........................................................................................................................................................................." LineBreakMode ="NoWrap" TextColor="Yellow" HorizontalOptions="FillAndExpand" VerticalOptions="Center" Grid.Row="0" Grid.Column="2" />
+ <Label Text="{Binding Action}" FontSize="17" TextColor="Yellow" FontFamily="Roboto" XAlign="End" HorizontalOptions="End" VerticalOptions="Center" Grid.Row="0" Grid.Column="3" />
+
+ </Grid>
+
+ </ViewCell.View>
+</ViewCell> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/LegacyRepro/SampleViewCell.xaml.cs b/Xamarin.Forms.Controls/LegacyRepro/SampleViewCell.xaml.cs
new file mode 100644
index 00000000..f7808d1b
--- /dev/null
+++ b/Xamarin.Forms.Controls/LegacyRepro/SampleViewCell.xaml.cs
@@ -0,0 +1,149 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.Forms;
+
+
+namespace App2
+{
+
+ public partial class SampleViewCell : ViewCell
+ {
+ MenuItem _overRideItemmenuitem = null;
+ public SampleViewCell()
+ {
+ try
+ {
+ InitializeComponent();
+
+ _overRideItemmenuitem = new MenuItem();
+ _overRideItemmenuitem.Text = "Over Ride";
+ _overRideItemmenuitem.IsDestructive = true;
+ _overRideItemmenuitem.Clicked += OverRide_Clicked;
+
+ //this.ContextActions.Add(OverRideItemmenuitem);
+
+ //Height = 300;
+ }
+ catch (Exception ex)
+ {
+ throw ex;
+ }
+ }
+
+ void OverRide_Clicked(object sender, EventArgs e)
+ {
+ try
+ {
+ var obj = (CheckListDetails)((MenuItem)sender).BindingContext;
+ obj.ChecklistStatus = CheckListStatus.OverRide;
+
+ SetContextActions();
+ }
+ catch (Exception ex)
+ {
+ throw ex;
+ }
+ }
+
+ void Checklist_tapped(object sender, EventArgs e)
+ {
+ try
+ {
+ var selectItem = (CheckListDetails)((Grid)sender).BindingContext;
+
+ if (selectItem != null && selectItem.ChecklistStatus != CheckListStatus.OverRide)
+ {
+ selectItem.ChecklistStatus = CheckListStatus.Completed;
+
+ SetContextActions();
+ }
+ }
+ catch (Exception ex)
+ {
+ throw ex;
+ }
+ }
+
+ //protected override void OnPropertyChanged(string propertyName = null)
+ //{
+ // base.OnPropertyChanged(propertyName);
+ // if(propertyName == ViewCell.BindingContextProperty.PropertyName)
+ // {
+ // setContextActions();
+ // }
+ //}
+ protected override void OnBindingContextChanged()
+ {
+ base.OnBindingContextChanged();
+ SetContextActions();
+ }
+
+ void SetContextActions()
+ {
+ try
+ {
+ if (BindingContext != null)
+ {
+ var obj = (CheckListDetails)BindingContext;
+
+ if (obj.ChecklistStatus == CheckListStatus.Default)
+ {
+ if (ContextActions.Count == 0)
+ {
+ ContextActions.Add(_overRideItemmenuitem);
+ }
+ }
+ else if (obj.ChecklistStatus == CheckListStatus.Completed)
+ {
+ if (ContextActions.Count > 0)
+ {
+
+ ContextActions.Remove(_overRideItemmenuitem);
+ if (_overRideItemmenuitem != null)
+ {
+ _overRideItemmenuitem.Clicked -= OverRide_Clicked;
+ _overRideItemmenuitem = null;
+ }
+ }
+
+
+ }
+ else if (obj.ChecklistStatus == CheckListStatus.Pending)
+ {
+ if (ContextActions.Count == 0)
+ {
+ ContextActions.Add(_overRideItemmenuitem);
+ }
+
+
+ }
+ else if (obj.ChecklistStatus == CheckListStatus.OverRide)
+ {
+ if (ContextActions.Count > 0)
+ {
+ ContextActions.Remove(_overRideItemmenuitem);
+ if (_overRideItemmenuitem != null)
+ {
+ _overRideItemmenuitem.Clicked -= OverRide_Clicked;
+ _overRideItemmenuitem = null;
+ }
+
+ }
+ }
+
+ }
+
+
+ }
+ catch (Exception ex)
+ {
+ throw ex;
+ }
+ }
+
+ }
+}
diff --git a/Xamarin.Forms.Controls/Properties/AssemblyInfo.cs b/Xamarin.Forms.Controls/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..2a99acbf
--- /dev/null
+++ b/Xamarin.Forms.Controls/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("Xamarin.Forms.Controls")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Xamarin Inc.")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Xamarin Inc.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
+[assembly: InternalsVisibleTo ("Xamarin.Forms.Core.WP8")]
+
+// The control gallary needs to add code references to internals to prevent the linker from
+// removing the references. Remove this once the [PreserveAttribute] can be applied at the class
+// and member level.
+[assembly: InternalsVisibleTo ("Xamarin.Forms.ControlGallery.Android")]
diff --git a/Xamarin.Forms.Controls/RootPages/CaseTenPage.cs b/Xamarin.Forms.Controls/RootPages/CaseTenPage.cs
new file mode 100644
index 00000000..98527c46
--- /dev/null
+++ b/Xamarin.Forms.Controls/RootPages/CaseTenPage.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ // May not behave
+ // NavigationPage with multiple tabbed pages
+ public class CaseTenPage : MasterDetailPage
+ {
+ public CaseTenPage ()
+ {
+ var btn = new Button {Text = "Click Me"};
+ btn.Clicked += (sender, args) => btn.Navigation.PushModalAsync (new NavigationPage (new ContentPage ()));
+
+ var detail = new ContentPage {Content = btn};
+
+ NavigationPage.SetHasNavigationBar (detail, false);
+
+ Master = new ListPage (){Title = "Master"};
+ Detail = detail;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/RootPages/Issue465Page.cs b/Xamarin.Forms.Controls/RootPages/Issue465Page.cs
new file mode 100644
index 00000000..84cfa956
--- /dev/null
+++ b/Xamarin.Forms.Controls/RootPages/Issue465Page.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ //Issue 465
+ public class Issue465Page : TabbedPage
+ {
+ public Issue465Page ()
+ {
+ var popModalButton = new Button {
+ Text = "PopModalAsync",
+ HorizontalOptions = LayoutOptions.CenterAndExpand,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+ var splashPage = new ContentPage { Content = popModalButton };
+
+ Navigation.PushModalAsync (splashPage);
+
+ popModalButton.Clicked += (s, e) => Navigation.PopModalAsync ();
+
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/RootPages/RootContentPage.cs b/Xamarin.Forms.Controls/RootPages/RootContentPage.cs
new file mode 100644
index 00000000..0e4e004a
--- /dev/null
+++ b/Xamarin.Forms.Controls/RootPages/RootContentPage.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+
+ public class RootContentPage : ContentPage
+ {
+ public RootContentPage (string hierarchy)
+ {
+ AutomationId = hierarchy + "PageId";
+ Content = new SwapHierachyStackLayout (hierarchy);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/RootPages/RootMDPNavigationContentPage.cs b/Xamarin.Forms.Controls/RootPages/RootMDPNavigationContentPage.cs
new file mode 100644
index 00000000..2a7de4ba
--- /dev/null
+++ b/Xamarin.Forms.Controls/RootPages/RootMDPNavigationContentPage.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ //MasterDetailPage -> NavigationPage -> ContentPage
+ public class RootMDPNavigationContentPage : MasterDetailPage
+ {
+
+ public RootMDPNavigationContentPage (string hierarchy)
+ {
+ AutomationId = hierarchy + "PageId";
+
+ Master = new ContentPage {
+ Title = "Testing 123",
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = "Master" },
+ new AbsoluteLayout {
+ BackgroundColor = Color.Red,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand
+ },
+ new Button { Text = "Button" }
+ }
+ }
+ };
+
+ Detail = new NavigationPage (new ContentPage {
+ Title = "Md->Nav->Con",
+ Content = new SwapHierachyStackLayout (hierarchy)
+ });
+
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/RootPages/RootMDPNavigationTabbedContentPage.cs b/Xamarin.Forms.Controls/RootPages/RootMDPNavigationTabbedContentPage.cs
new file mode 100644
index 00000000..096b776c
--- /dev/null
+++ b/Xamarin.Forms.Controls/RootPages/RootMDPNavigationTabbedContentPage.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ // MasterDetailPage -> NavigationPage -> TabbedPage -> ContentPage
+ public class RootMDPNavigationTabbedContentPage : MasterDetailPage {
+
+ public RootMDPNavigationTabbedContentPage (string hierarchy)
+ {
+ AutomationId = hierarchy + "PageId";
+
+
+ var tabbedPage = new TabbedPage ();
+
+ var firstTab = new ContentPage {
+ //BackgroundColor = Color.Yellow,
+ Title = "Testing 123",
+ Content = new SwapHierachyStackLayout (hierarchy)
+ };
+
+ tabbedPage.Children.Add (firstTab);
+
+ NavigationPage.SetHasNavigationBar (firstTab, false);
+
+ Detail = new NavigationPage (tabbedPage);
+ Master = new NavigationPage (new ContentPage {
+ Title = "Testing 345",
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = "Hello" },
+ new AbsoluteLayout {
+ BackgroundColor = Color.Red,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand
+ },
+ new Button { Text = "Button" }
+ }
+ }
+ }) {
+ Title = "Testing 345"
+ };
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/RootPages/RootNavigationContentPage.cs b/Xamarin.Forms.Controls/RootPages/RootNavigationContentPage.cs
new file mode 100644
index 00000000..8a3d450f
--- /dev/null
+++ b/Xamarin.Forms.Controls/RootPages/RootNavigationContentPage.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ // NavigationPage -> ContentPage
+ public class RootNavigationContentPage : NavigationPage {
+
+ public RootNavigationContentPage (string hierarchy)
+ {
+ AutomationId = hierarchy + "PageId";
+
+ var content = new ContentPage {
+ BackgroundColor = Color.Yellow,
+ Title = "Testing 123",
+ Content = new SwapHierachyStackLayout (hierarchy)
+ };
+
+ PushAsync (content);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/RootPages/RootNavigationManyTabbedPage.cs b/Xamarin.Forms.Controls/RootPages/RootNavigationManyTabbedPage.cs
new file mode 100644
index 00000000..fdce27d1
--- /dev/null
+++ b/Xamarin.Forms.Controls/RootPages/RootNavigationManyTabbedPage.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ // May not behave
+ // NavigationPage with multiple tabbed pages
+ public class RootNavigationManyTabbedPage : NavigationPage
+ {
+ public RootNavigationManyTabbedPage (string hierarchy)
+ {
+ AutomationId = hierarchy + "PageId";
+
+ var content = new TabbedPage {
+ Children = {
+ new ContentPage {
+ Title = "Page 1",
+ Content = new SwapHierachyStackLayout (hierarchy)
+ },
+ new ContentPage {
+ Title = "Page 2",
+ Content = new Label {
+ Text = "Page 2"
+ }
+ },
+ new ContentPage {
+ Title = "Page 3",
+ Content = new Label {
+ Text = "Page 3"
+ }
+ },
+ new ContentPage {
+ Title = "Page 4",
+ Content = new Label {
+ Text = "Page 4"
+ }
+ },
+ new ContentPage {
+ Title = "Page 5",
+ Content = new Label {
+ Text = "Page 5"
+ }
+ },
+ new ContentPage {
+ Title = "Page 6",
+ Content = new Label {
+ Text = "Page 6"
+ }
+ },
+
+ new ContentPage {
+ Title = "Go Home",
+ },
+ }
+ };
+ PushAsync (content);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/RootPages/RootNavigationTabbedContentPage.cs b/Xamarin.Forms.Controls/RootPages/RootNavigationTabbedContentPage.cs
new file mode 100644
index 00000000..25c2987e
--- /dev/null
+++ b/Xamarin.Forms.Controls/RootPages/RootNavigationTabbedContentPage.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ // NavigationPage -> TabbedPage -> ContentPage
+ // Not recommended
+ public class RootNavigationTabbedContentPage : NavigationPage
+ {
+ public RootNavigationTabbedContentPage (string hierarchy)
+ {
+ AutomationId = hierarchy + "PageId";
+
+ var tabbedPage = new TabbedPage {
+ Children = {
+ new ContentPage {
+ Title = "Page 1",
+ Content = new SwapHierachyStackLayout (hierarchy)
+ },
+ new ContentPage {
+ Title = "Page 2",
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = "Page Two" },
+ new BoxView {
+ Color = Color.Gray,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand
+ },
+ new Button { Text = "Click me" },
+ }
+ }
+ }
+ }
+ };
+
+ PushAsync (tabbedPage);
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/RootPages/RootTabbedContentPage.cs b/Xamarin.Forms.Controls/RootPages/RootTabbedContentPage.cs
new file mode 100644
index 00000000..fdcfb921
--- /dev/null
+++ b/Xamarin.Forms.Controls/RootPages/RootTabbedContentPage.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ // TabbedPage -> ContentPage
+ public class RootTabbedContentPage : TabbedPage
+ {
+ public RootTabbedContentPage (string hierarchy)
+ {
+ AutomationId = hierarchy + "PageId";
+
+ var tabOne = new ContentPage {
+ Title = "Testing 123",
+ Content = new SwapHierachyStackLayout (hierarchy)
+ };
+
+ var tabTwo = new ContentPage {
+ Title = "Testing 345",
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = "Hello" },
+ new AbsoluteLayout {
+ BackgroundColor = Color.Red,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand
+ },
+ new Button { Text = "Button" },
+ }
+ }
+ };
+
+ Children.Add (tabOne);
+ Children.Add (tabTwo);
+
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls/RootPages/RootTabbedMDPNavigationContentPage.cs b/Xamarin.Forms.Controls/RootPages/RootTabbedMDPNavigationContentPage.cs
new file mode 100644
index 00000000..14bf7cf1
--- /dev/null
+++ b/Xamarin.Forms.Controls/RootPages/RootTabbedMDPNavigationContentPage.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ //TabbedPage -> MasterDetailPage -> NavigationPage -> ContentPage
+ public class RootTabbedMDPNavigationContentPage : TabbedPage
+ {
+ public RootTabbedMDPNavigationContentPage (string hierarchy)
+ {
+ AutomationId = hierarchy + "PageId";
+
+ var tabOne = new MasterDetailPage {
+ Title = "Testing 123",
+ Master = new ContentPage {
+ Title = "Testing 123",
+ Content = new StackLayout {
+ Children = {
+ new Label {Text = "Master"},
+ new AbsoluteLayout {
+ BackgroundColor = Color.Red,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand
+ },
+ new Button {Text = "Button"}
+ }
+ }
+ },
+ Detail = new NavigationPage (new ContentPage {
+ Title = "Testing 123",
+ Content = new SwapHierachyStackLayout (hierarchy)
+ })
+ };
+
+ var tabTwo = new ContentPage {
+ Title = "Testing 345",
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = "Hello" },
+ new AbsoluteLayout {
+ BackgroundColor = Color.Red,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand
+ }
+ }
+ }
+ };
+
+ Children.Add (tabOne);
+ Children.Add (tabTwo);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/RootPages/RootTabbedManyNavigationContentPage.cs b/Xamarin.Forms.Controls/RootPages/RootTabbedManyNavigationContentPage.cs
new file mode 100644
index 00000000..e0a565a1
--- /dev/null
+++ b/Xamarin.Forms.Controls/RootPages/RootTabbedManyNavigationContentPage.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+
+ public class RootTabbedManyNavigationContentPage : TabbedPage
+ {
+ public RootTabbedManyNavigationContentPage (string hierarchy)
+ {
+ AutomationId = hierarchy + "PageId";
+
+ var page1 = new NavigationPage (new ContentPage {
+ Content = new SwapHierachyStackLayout (hierarchy)
+ }) {Title = "P 1"};
+
+ var page2 = new NavigationPage (new ContentPage {
+ Title = "Page 2",
+ Content = new Label {
+ Text = "Page 2"
+ }
+ }) {Title = "P 2"};
+
+ var page3 = new NavigationPage (new ContentPage {
+ Title = "Page 3",
+ Content = new Label {
+ Text = "Page 3"
+ }
+
+ }) {Title = "P 3"};
+
+ var page4 = new NavigationPage (new ContentPage {
+ Title = "Page 4",
+ Content = new Label {
+ Text = "Page 4"
+ }
+
+ }) {Title = "P 4"};
+
+ var page5 = new NavigationPage (new ContentPage {
+ Title = "Page 5",
+ Content = new Label {
+ Text = "Page 5"
+ }
+
+ }) {Title = "P 5"};
+
+ var page6 = new NavigationPage (new ContentPage {
+ Title = "Page 6",
+ Content = new Label {
+ Text = "Page 6"
+ }
+
+ }) {Title = "P 6"};
+
+ var page7 = new NavigationPage (new ContentPage {
+ Title = "Page 7",
+ Content = new Label {
+ Text = "Page 7"
+ }
+
+ }) {Title = "Home"};
+
+ Children.Add (page1);
+ Children.Add (page2);
+ Children.Add (page3);
+ Children.Add (page4);
+ Children.Add (page5);
+ Children.Add (page6);
+ Children.Add (page7);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/RootPages/RootTabbedNavigationContentPage.cs b/Xamarin.Forms.Controls/RootPages/RootTabbedNavigationContentPage.cs
new file mode 100644
index 00000000..3f14a07f
--- /dev/null
+++ b/Xamarin.Forms.Controls/RootPages/RootTabbedNavigationContentPage.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Resources;
+using System.Text;
+using System.Threading.Tasks;
+#if HAVE_OPENTK
+using OpenTK.Graphics;
+using OpenTK.Graphics.ES20;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ public class RootTabbedNavigationContentPage : TabbedPage
+ {
+ public RootTabbedNavigationContentPage (string hierarchy)
+ {
+ AutomationId = hierarchy + "PageId";
+
+ var tabOne = new NavigationPage (new ContentPage {
+ Title = "Nav title",
+ Content = new SwapHierachyStackLayout (hierarchy)
+ }) { Title = "Tab 123", };
+
+ var tabTwo = new ContentPage {
+ Title = "Testing 345",
+ Content = new StackLayout {
+ Children = {
+ new Label { Text = "Hello" },
+ new AbsoluteLayout {
+ BackgroundColor = Color.Red,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HorizontalOptions = LayoutOptions.FillAndExpand
+ },
+ new Button { Text = "Button" },
+ }
+ }
+ };
+
+ Children.Add (tabOne);
+ Children.Add (tabTwo);
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Controls/RootPages/SwapHierachyStackLayout.cs b/Xamarin.Forms.Controls/RootPages/SwapHierachyStackLayout.cs
new file mode 100644
index 00000000..de363575
--- /dev/null
+++ b/Xamarin.Forms.Controls/RootPages/SwapHierachyStackLayout.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ internal sealed class SwapRootButton : Button
+ {
+
+ public string PageStyleId { get; private set; }
+
+ public SwapRootButton (string hierarchyDescription, Command command)
+ {
+ AutomationId = hierarchyDescription + "ButtonId";
+ Text = hierarchyDescription;
+
+ Command = command;
+ }
+ }
+
+ internal class SwapHierachyStackLayout : ScrollView
+ {
+ public SwapHierachyStackLayout (string heirarchy)
+ {
+ AutomationId = "ChoosePageScrollView";
+
+ BackgroundColor = Color.Blue;
+
+ var buttons = new [] {
+ new SwapRootButton ("Content", new Command (() => Application.Current.MainPage = new RootContentPage ("Content"))),
+ new SwapRootButton ("Nav->Content", new Command (() => Application.Current.MainPage = new RootNavigationContentPage ("Nav->Content"))),
+ new SwapRootButton ("MDP->Nav->Content", new Command (() => Application.Current.MainPage = new RootMDPNavigationContentPage ("MDP->Nav->Content"))),
+ new SwapRootButton ("Tab->Content", new Command (() => Application.Current.MainPage = new RootTabbedContentPage ("Tab->Content"))),
+ new SwapRootButton ("Tab->MDP->Nav->Content", new Command (() => Application.Current.MainPage = new RootTabbedMDPNavigationContentPage ("Tab->MDP->Nav->Content"))),
+ new SwapRootButton ("Tab->Nav->Content", new Command (() => Application.Current.MainPage = new RootTabbedNavigationContentPage ("Tab->Nav->Content"))),
+ new SwapRootButton ("Tab(Many)->Nav->Content", new Command (() => Application.Current.MainPage = new RootTabbedManyNavigationContentPage ("Tab(Many)->Nav->Content"))),
+ // tsk tsk
+ new SwapRootButton ("Nav->Tab->Content(BAD IDEA)", new Command (() => Application.Current.MainPage = new RootNavigationTabbedContentPage ("Nav->Tab->Content(BAD IDEA)"))),
+ new SwapRootButton ("Nav->Tab(Many)->Content(BAD IDEA)", new Command (() => Application.Current.MainPage = new RootNavigationManyTabbedPage ("Nav->Tab(Many)->Content(BAD IDEA)"))),
+ new SwapRootButton ("MDP->Nav->Tab->Content(BAD IDEA)", new Command (() => Application.Current.MainPage = new RootMDPNavigationTabbedContentPage ("MDP->Nav->Tab->Content(BAD IDEA)"))),
+ // modals
+ new SwapRootButton ("(Modal)Content", new Command (async () => await Application.Current.MainPage.Navigation.PushModalAsync(new RootContentPage ("(Modal)Content")))),
+ new SwapRootButton ("(Modal)Nav->Content", new Command (async () => await Application.Current.MainPage.Navigation.PushModalAsync(new RootNavigationContentPage ("(Modal)Nav->Content")))),
+ new SwapRootButton ("(Modal)MDP->Nav->Content", new Command (async () => await Application.Current.MainPage.Navigation.PushModalAsync(new RootMDPNavigationContentPage ("(Modal)MDP->Nav->Content")))),
+ new SwapRootButton ("(Modal)Tab->Content", new Command (async () => await Application.Current.MainPage.Navigation.PushModalAsync(new RootTabbedContentPage ("(Modal)Tab->Content")))),
+ new SwapRootButton ("(Modal)Tab->MDP->Nav->Content", new Command (async () => await Application.Current.MainPage.Navigation.PushModalAsync(new RootTabbedMDPNavigationContentPage ("(Modal)Tab->MDP->Nav->Content")))),
+ new SwapRootButton ("(Modal)Tab->Nav->Content", new Command (async () => await Application.Current.MainPage.Navigation.PushModalAsync(new RootTabbedNavigationContentPage ("(Modal)Tab->Nav->Content")))),
+ new SwapRootButton ("(Modal)Tab(Many)->Nav->Content", new Command (async () => await Application.Current.MainPage.Navigation.PushModalAsync(new RootTabbedManyNavigationContentPage ("(Modal)Tab(Many)->Nav->Content")))),
+ // tsk tsk
+ new SwapRootButton ("(Modal)Nav->Tab->Content(BAD IDEA)", new Command (async () => await Application.Current.MainPage.Navigation.PushModalAsync(new RootNavigationTabbedContentPage ("(Modal)Nav->Tab->Content(BAD IDEA)")))),
+ new SwapRootButton ("(Modal)Nav->Tab(Many)->Content(BAD IDEA)", new Command (async () => await Application.Current.MainPage.Navigation.PushModalAsync(new RootNavigationManyTabbedPage ("(Modal)Nav->Tab(Many)->Content(BAD IDEA)")))),
+ new SwapRootButton ("(Modal)MDP->Nav->Tab->Content(BAD IDEA)", new Command (async () => await Application.Current.MainPage.Navigation.PushModalAsync(new RootMDPNavigationTabbedContentPage ("(Modal)MDP->Nav->Tab->Content(BAD IDEA)")))),
+ new SwapRootButton ("(Modal)CoreGallery", new Command (() => Application.Current.MainPage = CoreGallery.GetMainPage ()))
+ };
+
+ var layout = new StackLayout ();
+
+ layout.Children.Add (new Label { Text = heirarchy });
+
+ foreach (var button in buttons) {
+ layout.Children.Add (button);
+ }
+
+ Content = layout;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Controls/RootPages/TabbedNavPage.cs b/Xamarin.Forms.Controls/RootPages/TabbedNavPage.cs
new file mode 100644
index 00000000..e33d5aec
--- /dev/null
+++ b/Xamarin.Forms.Controls/RootPages/TabbedNavPage.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Controls
+{
+ // TabbedPage -> NavigationPage
+ public class TabbedNavPage : MasterDetailPage
+ {
+ public TabbedNavPage ()
+ {
+ NavigationPage navpage = null;
+ navpage = new NavigationPage (new ContentPage {
+ Title = "Content0",
+ Content = new Button {
+ Text = "Button",
+ Command = new Command (() => {
+ Debug.WriteLine ("k");
+ navpage.PushAsync (new ContentPage () {Title = "Content1"});
+ })
+ }
+ }) {
+ Title = "Page0",
+ };
+
+ Children.add(navpage);
+ Children.add(new HomeButton ());
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/TestCases.cs b/Xamarin.Forms.Controls/TestCases.cs
new file mode 100644
index 00000000..fc601024
--- /dev/null
+++ b/Xamarin.Forms.Controls/TestCases.cs
@@ -0,0 +1,213 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Threading.Tasks;
+using Xamarin.Forms.Controls.TestCasesPages;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Controls
+{
+ public static class TestCases
+ {
+ public class TestCaseScreen : TableView
+ {
+ public static Dictionary<string, Action> PageToAction = new Dictionary<string, Action> ();
+
+ static TextCell MakeIssueCell (string text, string detail, Action tapped)
+ {
+ PageToAction[text] = tapped;
+ if (detail != null)
+ PageToAction[detail] = tapped;
+
+ var cell = new TextCell { Text = text, Detail = detail };
+ cell.Tapped += (s, e) => tapped();
+ return cell;
+ }
+
+ Action ActivatePageAndNavigate (IssueAttribute issueAttribute, Type type)
+ {
+ Action navigationAction = null;
+
+ if (issueAttribute.NavigationBehavior == NavigationBehavior.PushAsync) {
+ return async () => {
+ var page = ActivatePage (type);
+ TrackOnInsights (page);
+ await Navigation.PushAsync (page);
+ };
+ }
+
+ if (issueAttribute.NavigationBehavior == NavigationBehavior.PushModalAsync) {
+ return async () => {
+ var page = ActivatePage (type);
+ TrackOnInsights (page);
+ await Navigation.PushModalAsync (page);
+ };
+ }
+
+ if (issueAttribute.NavigationBehavior == NavigationBehavior.Default) {
+ return async () => {
+ var page = ActivatePage (type);
+ TrackOnInsights (page);
+ if (page is ContentPage || page is CarouselPage) {
+
+ await Navigation.PushAsync (page);
+
+ } else {
+ await Navigation.PushModalAsync (page);
+ }
+ };
+ }
+
+ if (issueAttribute.NavigationBehavior == NavigationBehavior.SetApplicationRoot) {
+ return () => {
+ var page = ActivatePage (type);
+ TrackOnInsights (page);
+ Application.Current.MainPage = page;
+ };
+ }
+
+ return navigationAction;
+ }
+
+ static void TrackOnInsights (Page page)
+ {
+ if (Insights.IsInitialized) {
+ Insights.Track ("Navigation", new Dictionary<string, string> {
+ {
+ "Pushing",
+ page.GetType ().Name
+ }
+ });
+ }
+ }
+
+ Page ActivatePage (Type type)
+ {
+ var page = Activator.CreateInstance (type) as Page;
+ if (page == null) {
+ throw new InvalidCastException ("Issue must be of type Page");
+ }
+ return page;
+ }
+
+ public TestCaseScreen ()
+ {
+ AutomationId = "TestCasesIssueList";
+
+ Intent = TableIntent.Settings;
+
+ var assembly = typeof (TestCases).GetTypeInfo ().Assembly;
+
+ var issueModels =
+ from typeInfo in assembly.DefinedTypes.Select (o => o.AsType ().GetTypeInfo ())
+ where typeInfo.GetCustomAttribute<IssueAttribute> () != null
+ let attribute = (IssueAttribute)typeInfo.GetCustomAttribute<IssueAttribute> ()
+ select new {
+ IssueTracker = attribute.IssueTracker,
+ IssueNumber = attribute.IssueNumber,
+ Name = attribute.IssueTracker.ToString ().Substring(0, 1) + attribute.IssueNumber.ToString (),
+ Description = attribute.Description,
+ Action = ActivatePageAndNavigate (attribute, typeInfo.AsType ())
+ };
+
+ var root = new TableRoot ();
+ var section = new TableSection ("Bug Repro");
+ root.Add (section);
+
+ var duplicates = new HashSet<string> ();
+ issueModels.ForEach (im => {
+ if (duplicates.Contains (im.Name) && !IsExempt (im.Name)) {
+ throw new NotSupportedException ("Please provide unique tracker + issue number combo: " + im.IssueTracker.ToString () + im.IssueNumber.ToString ());
+ } else {
+ duplicates.Add (im.Name);
+ }
+ });
+
+ var githubIssueCells =
+ from issueModel in issueModels
+ where issueModel.IssueTracker == IssueTracker.Github
+ orderby issueModel.IssueNumber descending
+ select MakeIssueCell (issueModel.Name, issueModel.Description, issueModel.Action);
+
+ var bugzillaIssueCells =
+ from issueModel in issueModels
+ where issueModel.IssueTracker == IssueTracker.Bugzilla
+ orderby issueModel.IssueNumber descending
+ select MakeIssueCell (issueModel.Name, issueModel.Description, issueModel.Action);
+
+ var untrackedIssueCells =
+ from issueModel in issueModels
+ where issueModel.IssueTracker == IssueTracker.None
+ orderby issueModel.Description
+ select MakeIssueCell (issueModel.Name, issueModel.Description, issueModel.Action);
+
+ var issueCells = bugzillaIssueCells.Concat (githubIssueCells).Concat (untrackedIssueCells);
+
+ foreach (var issueCell in issueCells) {
+ section.Add (issueCell);
+ }
+
+ Root = root;
+ }
+
+ // Legacy reasons, do not add to this list
+ // Going forward, make sure only one Issue attribute exist for a Tracker + Issue number pair
+ bool IsExempt (string name)
+ {
+ if (name == "G1461" ||
+ name == "G342" ||
+ name == "G1305" ||
+ name == "G1653" ||
+ name == "N0")
+ return true;
+ else
+ return false;
+ }
+ }
+
+ public static NavigationPage GetTestCases ()
+ {
+ var rootLayout = new StackLayout ();
+
+ var testCasesRoot = new ContentPage {
+ Title = "Bug Repro's",
+ Content = rootLayout
+ };
+
+ var searchBar = new SearchBar() {
+ AutomationId = "SearchBarGo"
+ };
+
+ var searchButton = new Button () {
+ Text = "Search And Go To Issue",
+ AutomationId = "SearchButton",
+ Command = new Command (() => {
+ try {
+ TestCaseScreen.PageToAction[searchBar.Text] ();
+ } catch (Exception e) {
+ System.Diagnostics.Debug.WriteLine (e.Message);
+ }
+
+ })
+ };
+
+ var leaveTestCasesButton = new Button {
+ AutomationId = "GoBackToGalleriesButton",
+ Text = "Go Back to Galleries",
+ Command = new Command (() => testCasesRoot.Navigation.PopModalAsync ())
+ };
+
+ rootLayout.Children.Add (leaveTestCasesButton);
+ rootLayout.Children.Add (searchBar);
+ rootLayout.Children.Add (searchButton);
+ rootLayout.Children.Add (new TestCaseScreen ());
+
+ return new NavigationPage (testCasesRoot) {
+ Title = Device.OnPlatform ("Test Cases", "Test Cases", "Tests")
+ };
+ }
+ }
+
+}
diff --git a/Xamarin.Forms.Controls/ViewContainers/EventViewContainer.cs b/Xamarin.Forms.Controls/ViewContainers/EventViewContainer.cs
new file mode 100644
index 00000000..2095c037
--- /dev/null
+++ b/Xamarin.Forms.Controls/ViewContainers/EventViewContainer.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class EventViewContainer<T> : ViewContainer<T>
+ where T : View
+ {
+ string _formsMember;
+ Label _eventLabel;
+ int _numberOfTimesFired;
+
+ public EventViewContainer (Enum formsMember, T view) : base (formsMember, view)
+ {
+ _numberOfTimesFired = 0;
+
+ _formsMember = formsMember.ToString ();
+
+ _eventLabel = new Label {
+ AutomationId = formsMember + "EventLabel",
+ Text = "Event: " + _formsMember + " (none)"
+ };
+
+ ContainerLayout.Children.Add (_eventLabel);
+ }
+
+ public void EventFired ()
+ {
+ _numberOfTimesFired++;
+ _eventLabel.Text = "Event: " + _formsMember + " (fired " + _numberOfTimesFired + ")";
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/ViewContainers/LayeredViewContainer.cs b/Xamarin.Forms.Controls/ViewContainers/LayeredViewContainer.cs
new file mode 100644
index 00000000..e22ecfb6
--- /dev/null
+++ b/Xamarin.Forms.Controls/ViewContainers/LayeredViewContainer.cs
@@ -0,0 +1,38 @@
+using System;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class LayeredViewContainer<T> : ViewContainer<T>
+ where T : View
+ {
+ public LayeredViewContainer (Enum formsMember, T view) : base (formsMember, view)
+ {
+ var layout = new AbsoluteLayout ();
+
+ var hiddenButton = new Button {
+ AutomationId = formsMember + "LayeredHiddenButton",
+ Text = "Covered Up"
+ };
+
+ layout.Children.Add (hiddenButton);
+ AbsoluteLayout.SetLayoutFlags (hiddenButton, AbsoluteLayoutFlags.All);
+ AbsoluteLayout.SetLayoutBounds (hiddenButton, new Rectangle (0, 0, 1, 1));
+ layout.Children.Add (view);
+ AbsoluteLayout.SetLayoutBounds (view, new Rectangle (0, 0, 1, 1));
+ AbsoluteLayout.SetLayoutFlags (view, AbsoluteLayoutFlags.All);
+
+ var hiddenLabel = new Label {
+ AutomationId = formsMember + "LayeredLabel",
+ Text = "Hidden Button (Not Clicked)"
+ };
+
+ hiddenButton.Clicked += (sender, args) => { hiddenLabel.Text = "Hidden Button (Clicked)"; };
+
+ ContainerLayout = new StackLayout {
+ AutomationId = formsMember + "Container",
+ Padding = 10,
+ Children = { TitleLabel, BoundsLabel, layout, hiddenLabel }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/ViewContainers/MultiBindingHack.cs b/Xamarin.Forms.Controls/ViewContainers/MultiBindingHack.cs
new file mode 100644
index 00000000..4853fd14
--- /dev/null
+++ b/Xamarin.Forms.Controls/ViewContainers/MultiBindingHack.cs
@@ -0,0 +1,47 @@
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ internal class MultiBindingHack : INotifyPropertyChanged
+ {
+ string _labelWithBounds;
+
+ public MultiBindingHack (VisualElement element)
+ {
+ LabelWithBounds = string.Format("{{X={0:0.00} Y={1:0.00} Width={2:0.00} Height={3:0.00}}}", element.X, element.Y, element.Width, element.Height);
+
+ element.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "X" ||
+ args.PropertyName == "Y" ||
+ args.PropertyName == "Width" ||
+ args.PropertyName == "Height" ||
+ args.PropertyName == "Rotation") {
+ LabelWithBounds = string.Format("{{X={0:0.00} Y={1:0.00} Width={2:0.00} Height={3:0.00}}}", element.X, element.Y, element.Width, element.Height); // super hack
+ }
+ };
+ }
+
+ public string LabelWithBounds
+ {
+ get { return _labelWithBounds; }
+ set
+ {
+ if (_labelWithBounds == value)
+ return;
+ _labelWithBounds = value;
+ OnPropertyChanged ();
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/ViewContainers/StateViewContainer.cs b/Xamarin.Forms.Controls/ViewContainers/StateViewContainer.cs
new file mode 100644
index 00000000..b08cc306
--- /dev/null
+++ b/Xamarin.Forms.Controls/ViewContainers/StateViewContainer.cs
@@ -0,0 +1,48 @@
+using System;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class StateViewContainer<T> : ViewContainer<T>
+ where T : View
+ {
+ public Button StateChangeButton { get; private set; }
+ public Label ViewInteractionLabel { get; private set; }
+
+ public StateViewContainer (Enum formsMember, T view) : base (formsMember, view)
+ {
+ var name = formsMember.ToString ();
+
+ var stateTitleLabel = new Label {
+ Text = name + "?"
+ };
+
+ ViewInteractionLabel = new Label {
+ Text = "Interacted? : False"
+ };
+
+ var stateValueLabel = new Label {
+ BindingContext = view,
+ AutomationId = name + "StateLabel"
+ };
+ if (name != "Focus")
+ stateValueLabel.SetBinding (Label.TextProperty, name, converter: new GenericValueConverter (o => o.ToString()));
+
+ StateChangeButton = new Button {
+ Text = "Change State: " + name,
+ AutomationId = name + "StateButton"
+ };
+
+ var labelLayout = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ stateTitleLabel,
+ stateValueLabel
+ }
+ };
+
+ ContainerLayout.Children.Add (ViewInteractionLabel);
+ ContainerLayout.Children.Add (labelLayout);
+ ContainerLayout.Children.Add (StateChangeButton);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/ViewContainers/ValueViewContainer.cs b/Xamarin.Forms.Controls/ViewContainers/ValueViewContainer.cs
new file mode 100644
index 00000000..08dcc166
--- /dev/null
+++ b/Xamarin.Forms.Controls/ViewContainers/ValueViewContainer.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Xamarin.Forms.Controls
+{
+ internal class ValueViewContainer<T> : ViewContainer<T> where T : View
+ {
+ public ValueViewContainer (Enum formsMember, T view, string bindingPath, Func<object, object> converterAction) : base (formsMember, view)
+ {
+
+ var valueLabel = new Label { BindingContext = View };
+ valueLabel.SetBinding (Label.TextProperty, bindingPath, converter: new GenericValueConverter (converterAction));
+
+ ContainerLayout.Children.Add (valueLabel);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/ViewContainers/ViewContainer.cs b/Xamarin.Forms.Controls/ViewContainers/ViewContainer.cs
new file mode 100644
index 00000000..f12a0030
--- /dev/null
+++ b/Xamarin.Forms.Controls/ViewContainers/ViewContainer.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Linq.Expressions;
+
+namespace Xamarin.Forms.Controls
+{
+ internal enum ViewLayoutType
+ {
+ Normal,
+ Layered
+ }
+
+ internal class ViewContainer<T>
+ where T : View
+ {
+
+ public Label TitleLabel { get; private set; }
+ public Label BoundsLabel { get; private set; }
+ public T View { get; private set; }
+
+ // May want to override the container layout in subclasses
+ public StackLayout ContainerLayout { get; protected set; }
+
+ public ViewContainer (Enum formsMember, T view)
+ {
+ view.AutomationId = formsMember + "VisualElement";
+ View = view;
+
+ TitleLabel = new Label {
+ Text = formsMember + " View"
+ };
+
+ BoundsLabel = new Label {
+ BindingContext = new MultiBindingHack (view)
+ };
+ BoundsLabel.SetBinding (Label.TextProperty, "LabelWithBounds");
+
+ ContainerLayout = new StackLayout {
+ AutomationId = formsMember + "Container",
+ Padding = 10,
+ Children = { TitleLabel, BoundsLabel, view }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/Xamarin.Forms.Controls.csproj b/Xamarin.Forms.Controls/Xamarin.Forms.Controls.csproj
new file mode 100644
index 00000000..c56b1436
--- /dev/null
+++ b/Xamarin.Forms.Controls/Xamarin.Forms.Controls.csproj
@@ -0,0 +1,285 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Controls</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Controls</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ <NuGetPackageImportStamp>
+ </NuGetPackageImportStamp>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;PERF;APP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;APP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;PERF;APP</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .NET Framework is automatically included -->
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Build.Tasks\Xamarin.Forms.Build.Tasks.csproj">
+ <Project>{96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}</Project>
+ <Name>Xamarin.Forms.Build.Tasks</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.CustomAttributes\Xamarin.Forms.CustomAttributes.csproj">
+ <Project>{4dcd0420-1168-4b77-86db-6196ee4bd491}</Project>
+ <Name>Xamarin.Forms.CustomAttributes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7d13bac2-c6a4-416a-b07e-c169b199e52b}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Xaml\Xamarin.Forms.Xaml.csproj">
+ <Project>{9db2f292-8034-4e06-89ad-98bbda4306b9}</Project>
+ <Name>Xamarin.Forms.Xaml</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="App.cs" />
+ <Compile Include="ControlGalleryPages\CellForceUpdateSizeGalleryPage.cs" />
+ <Compile Include="ControlGalleryPages\LayoutAddPerformance.xaml.cs">
+ <DependentUpon>LayoutAddPerformance.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="ControlGalleryPages\ListScrollTo.cs" />
+ <Compile Include="ControlGalleryPages\NavBarTitleTestPage.cs" />
+ <Compile Include="ControlGalleryPages\NestedNativeControlGalleryPage.cs" />
+ <Compile Include="ControlGalleryPages\PanGestureGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\KeyboardCoreGalleryPage.cs" />
+ <Compile Include="GalleryPages\BackgroundImageGallery.cs" />
+ <Compile Include="GalleryPages\CarouselViewGallery.cs" />
+ <Compile Include="GalleryPages\ControlTemplatePage.cs" />
+ <Compile Include="GalleryPages\ControlTemplateXamlPage.xaml.cs">
+ <DependentUpon>ControlTemplateXamlPage.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="GalleryPages\LayoutPerformanceGallery.cs" />
+ <Compile Include="GalleryPages\NavigationPropertiesGallery.cs" />
+ <Compile Include="ControlGalleryPages\ListViewSelectionColor.cs" />
+ <Compile Include="LegacyRepro\Page1.xaml.cs">
+ <DependentUpon>Page1.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="RootPages\RootContentPage.cs" />
+ <Compile Include="RootPages\SwapHierachyStackLayout.cs" />
+ <Compile Include="GalleryPages\EditableList.cs" />
+ <Compile Include="CoreGalleryPages\EditorCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\EntryCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\FrameCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\ImageCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\LabelCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\ListViewCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\OpenGLViewCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\PickerCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\ProgressBarCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\SearchBarCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\SliderCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\StepperCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\SwitchCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\TableViewCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\TimePickerCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\WebViewCoreGalleryPage.cs" />
+ <Compile Include="LegacyRepro\SampleViewCell.xaml.cs">
+ <DependentUpon>SampleViewCell.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="ViewContainers\EventViewContainer.cs" />
+ <Compile Include="ViewContainers\LayeredViewContainer.cs" />
+ <Compile Include="ViewContainers\MultiBindingHack.cs" />
+ <Compile Include="ViewContainers\StateViewContainer.cs" />
+ <Compile Include="ViewContainers\ValueViewContainer.cs" />
+ <Compile Include="ViewContainers\ViewContainer.cs" />
+ <Compile Include="CoreGalleryPages\ActivityIndicatorCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\CoreBoxViewGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\ButtonCoreGalleryPage.cs" />
+ <Compile Include="CoreGallery.cs" />
+ <Compile Include="CoreGalleryPages\DatePickerCoreGalleryPage.cs" />
+ <Compile Include="CoreGalleryPages\CoreGalleryPage.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="TestCases.cs" />
+ <Compile Include="GalleryPages\GridGallery.cs" />
+ <Compile Include="GalleryPages\PickerGallery.cs" />
+ <Compile Include="GalleryPages\ImageLoadingGallery.cs" />
+ <Compile Include="GalleryPages\CarouselPageGallery.cs" />
+ <Compile Include="GalleryPages\StepperGallery.cs" />
+ <Compile Include="GalleryPages\ScaleRotate.cs" />
+ <Compile Include="GalleryPages\LineBreakModeGallery.cs" />
+ <Compile Include="GalleryPages\ActionSheetGallery.cs" />
+ <Compile Include="GalleryPages\XamlPage.xaml.cs">
+ <DependentUpon>XamlPage.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="RootPages\RootTabbedContentPage.cs" />
+ <Compile Include="RootPages\RootTabbedNavigationContentPage.cs" />
+ <Compile Include="RootPages\RootNavigationContentPage.cs" />
+ <Compile Include="RootPages\RootNavigationTabbedContentPage.cs" />
+ <Compile Include="RootPages\RootMDPNavigationContentPage.cs" />
+ <Compile Include="RootPages\RootTabbedMDPNavigationContentPage.cs" />
+ <Compile Include="RootPages\RootTabbedManyNavigationContentPage.cs" />
+ <Compile Include="RootPages\RootNavigationManyTabbedPage.cs" />
+ <Compile Include="ControlGalleryPages\BehaviorsAndTriggers.xaml.cs">
+ <DependentUpon>BehaviorsAndTriggers.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="GalleryPages\CellsGalleries\EntryCellListPage.cs" />
+ <Compile Include="GalleryPages\CellsGalleries\EntryCellTablePage.cs" />
+ <Compile Include="GalleryPages\CellsGalleries\ImageCellListPage.cs" />
+ <Compile Include="GalleryPages\CellsGalleries\ImageCellTablePage.cs" />
+ <Compile Include="GalleryPages\CellsGalleries\ProductViewCell.cs" />
+ <Compile Include="GalleryPages\CellsGalleries\SwitchCellListPage.cs" />
+ <Compile Include="GalleryPages\CellsGalleries\SwitchCellTablePage.cs" />
+ <Compile Include="GalleryPages\CellsGalleries\TextCellListPage.cs" />
+ <Compile Include="GalleryPages\CellsGalleries\TextCellTablePage.cs" />
+ <Compile Include="GalleryPages\CellsGalleries\UnEvenViewCellGallery.cs" />
+ <Compile Include="GalleryPages\CellsGalleries\ViewCellGallery.cs" />
+ <Compile Include="GalleryPages\AbsoluteLayoutGallery.cs" />
+ <Compile Include="GalleryPages\BoundContentPage.cs" />
+ <Compile Include="GalleryPages\ButtonGallery.cs" />
+ <Compile Include="GalleryPages\CellTypeList.cs" />
+ <Compile Include="GalleryPages\ClipToBoundsGallery.cs" />
+ <Compile Include="GalleryPages\DisposeGallery.cs" />
+ <Compile Include="GalleryPages\EditorGallery.cs" />
+ <Compile Include="GalleryPages\EntryGallery.cs" />
+ <Compile Include="GalleryPages\FrameGallery.cs" />
+ <Compile Include="GalleryPages\GroupedListActionsGallery.cs" />
+ <Compile Include="GalleryPages\GroupedListContactsGallery.cs" />
+ <Compile Include="GalleryPages\ImageGallery.cs" />
+ <Compile Include="GalleryPages\InputIntentGallery.cs" />
+ <Compile Include="GalleryPages\LabelGallery.cs" />
+ <Compile Include="GalleryPages\LayoutOptionsGallery.cs" />
+ <Compile Include="GalleryPages\ListPage.cs" />
+ <Compile Include="GalleryPages\ListViewDemoPage.cs" />
+ <Compile Include="GalleryPages\MapGallery.cs" />
+ <Compile Include="GalleryPages\MinimumSizeGallery.cs" />
+ <Compile Include="GalleryPages\MultiGallery.cs" />
+ <Compile Include="GalleryPages\NavigationBarGallery.cs" />
+ <Compile Include="GalleryPages\NavigationMenuGallery.cs" />
+ <Compile Include="GalleryPages\OpenGLGallery.cs" />
+ <Compile Include="GalleryPages\ProgressBarGallery.cs" />
+ <Compile Include="GalleryPages\RelativeLayoutGallery.cs" />
+ <Compile Include="GalleryPages\ScrollGallery.cs" />
+ <Compile Include="GalleryPages\SearchBarGallery.cs" />
+ <Compile Include="GalleryPages\SettingsPage.cs" />
+ <Compile Include="GalleryPages\SliderGallery.cs" />
+ <Compile Include="GalleryPages\StackLayoutGallery.cs" />
+ <Compile Include="GalleryPages\SwitchGallery.cs" />
+ <Compile Include="GalleryPages\TableViewGallery.cs" />
+ <Compile Include="GalleryPages\TemplatedCarouselGallery.cs" />
+ <Compile Include="GalleryPages\TemplatedTabbedGallery.cs" />
+ <Compile Include="GalleryPages\ToolbarGallery.cs" />
+ <Compile Include="GalleryPages\UnevenListGallery.cs" />
+ <Compile Include="GalleryPages\WebViewGallery.cs" />
+ <Compile Include="GalleryPages\StyleGallery.cs" />
+ <Compile Include="GalleryPages\StyleXamlGallery.xaml.cs">
+ <DependentUpon>StyleXamlGallery.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="GalleryPages\MasterDetailPageTabletPage.cs" />
+ <Compile Include="Helpers\ITestCloudService.cs" />
+ <Compile Include="ControlGalleryPages\ToolbarItems.cs" />
+ <Compile Include="GalleryPages\AlertGallery.cs" />
+ <Compile Include="RootPages\RootMDPNavigationTabbedContentPage.cs" />
+ <Compile Include="Controls\Issue3076Button.cs" />
+ <Compile Include="ControlGalleryPages\ListRefresh.cs" />
+ <Compile Include="ControlGalleryPages\PinchGestureTestPage.cs" />
+ <Compile Include="ControlGalleryPages\AppearingGalleryPage.cs" />
+ <Compile Include="ControlGalleryPages\AutomationIDGallery.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+ <Import Project="..\.nuspec\Xamarin.Forms.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ItemGroup>
+ <EmbeddedResource Include="GalleryPages\crimson.jpg" />
+ <EmbeddedResource Include="GalleryPages\XamlPage.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="ControlGalleryPages\BehaviorsAndTriggers.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="GalleryPages\StyleXamlGallery.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ </ItemGroup>
+ <Import Project="..\Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Xamarin.Forms.Controls.Issues.Shared.projitems" Label="Shared" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Import Project="..\packages\Xamarin.Insights.1.11.1\build\portable-win+net45+wp80+windows8+wpa+MonoAndroid10+MonoTouch10\Xamarin.Insights.targets" Condition="Exists('..\packages\Xamarin.Insights.1.11.1\build\portable-win+net45+wp80+windows8+wpa+MonoAndroid10+MonoTouch10\Xamarin.Insights.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+ <Error Condition="!Exists('..\packages\Xamarin.Insights.1.11.4\build\portable-win+net45+wp80+windows8+wpa+MonoAndroid10+MonoTouch10\Xamarin.Insights.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Insights.1.11.4\build\portable-win+net45+wp80+windows8+wpa+MonoAndroid10+MonoTouch10\Xamarin.Insights.targets'))" />
+ </Target>
+ <ItemGroup>
+ <EmbeddedResource Include="ControlGalleryPages\LayoutAddPerformance.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="GalleryPages\ControlTemplateXamlPage.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="Xamarin.Insights, Version=1.11.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.Insights.1.11.4\lib\portable-win+net45+wp80+windows8+wpa+MonoAndroid10+MonoTouch10\Xamarin.Insights.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.config" />
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="LegacyRepro\Page1.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ <EmbeddedResource Include="LegacyRepro\SampleViewCell.xaml">
+ <Generator>MSBuild:UpdateDeisgnTimeXaml</Generator>
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="secrets.txt" />
+ </ItemGroup>
+ <Import Project="..\packages\Xamarin.Insights.1.11.4\build\portable-win+net45+wp80+windows8+wpa+MonoAndroid10+MonoTouch10\Xamarin.Insights.targets" Condition="Exists('..\packages\Xamarin.Insights.1.11.4\build\portable-win+net45+wp80+windows8+wpa+MonoAndroid10+MonoTouch10\Xamarin.Insights.targets')" />
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/app.config b/Xamarin.Forms.Controls/app.config
new file mode 100644
index 00000000..b1d2a5a3
--- /dev/null
+++ b/Xamarin.Forms.Controls/app.config
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="Mono.Cecil" publicKeyToken="0738eb9f132ed756" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-0.9.6.0" newVersion="0.9.6.0" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls/packages.config b/Xamarin.Forms.Controls/packages.config
new file mode 100644
index 00000000..7692cf94
--- /dev/null
+++ b/Xamarin.Forms.Controls/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Xamarin.Insights" version="1.11.4" targetFramework="portable45-net45+win8+wp8+wpa81" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.Core.Android.UITests/App.cs b/Xamarin.Forms.Core.Android.UITests/App.cs
new file mode 100644
index 00000000..76c94d86
--- /dev/null
+++ b/Xamarin.Forms.Core.Android.UITests/App.cs
@@ -0,0 +1,22 @@
+using NUnit.Framework;
+
+using Xamarin.UITest;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Configuration;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal static class RunningApp
+ {
+ public static AndroidApp App;
+
+ public static void Restart ()
+ {
+ App = ConfigureApp
+ .Android
+ .Debug ()
+ .ApkFile ("../../../Xamarin.Forms.ControlGallery.Android/bin/Debug/AndroidControlGallery.AndroidControlGallery-Signed.apk")
+ .StartApp ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.Android.UITests/Makefile b/Xamarin.Forms.Core.Android.UITests/Makefile
new file mode 100644
index 00000000..6f123c31
--- /dev/null
+++ b/Xamarin.Forms.Core.Android.UITests/Makefile
@@ -0,0 +1,2 @@
+console:
+ calabash-android console ../Xamarin.Forms.ControlGallery.Android/bin/Debug/AndroidControlGallery.AndroidControlGallery-Signed.apk
diff --git a/Xamarin.Forms.Core.Android.UITests/PlatformQueries.cs b/Xamarin.Forms.Core.Android.UITests/PlatformQueries.cs
new file mode 100644
index 00000000..01a27aac
--- /dev/null
+++ b/Xamarin.Forms.Core.Android.UITests/PlatformQueries.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal static class AndroidLoaderIdentifier {}
+
+ internal static class PlatformMethodQueries
+ {
+ public static readonly Dictionary<BindableProperty, Tuple<string[], bool>> PropertyPlatformMethodDictionary = new Dictionary<BindableProperty, Tuple<string[], bool>> {
+ { ActivityIndicator.ColorProperty, Tuple.Create (new[] { "getProgressDrawable", "getColor" }, false) },
+ { ActivityIndicator.IsRunningProperty, Tuple.Create (new[] { "isIndeterminate" }, false) },
+ { Button.BorderColorProperty, Tuple.Create (new[] { "getBackground" }, false) },
+ { Button.BorderRadiusProperty, Tuple.Create (new[] { "getBackground" }, false) },
+ { Button.BorderWidthProperty, Tuple.Create (new[] { "getBackground" }, false) },
+ { Button.ImageProperty, Tuple.Create (new[] { "getBackground" }, false) },
+ { Button.FontProperty, Tuple.Create (new[] { "getTypeface", "isBold" }, false) },
+ { Button.TextProperty, Tuple.Create (new[] { "getText" }, false) },
+ { Button.TextColorProperty, Tuple.Create (new[] { "getCurrentTextColor" }, false) },
+ { View.AnchorXProperty, Tuple.Create (new[] { "getPivotX" }, true) },
+ { View.AnchorYProperty, Tuple.Create (new[] { "getPivotY" }, true) },
+ { View.BackgroundColorProperty, Tuple.Create (new[] { "getBackground", "getColor" }, true) },
+ { View.IsEnabledProperty, Tuple.Create (new[] { "isEnabled" }, false) },
+ { View.OpacityProperty, Tuple.Create (new[] { "getAlpha" }, true) },
+ { View.RotationProperty, Tuple.Create (new[] { "getRotation" }, true) },
+ { View.RotationXProperty, Tuple.Create (new[] { "getRotationX" }, true) },
+ { View.RotationYProperty, Tuple.Create (new[] { "getRotationY" }, true) },
+ { View.ScaleProperty, Tuple.Create (new[] { "getScaleX", "getScaleY" }, true) },
+ };
+ }
+
+ internal static class PlatformViews
+ {
+ public static readonly string ActivityIndicator = "android.widget.ProgressBar";
+ public static readonly string BoxView = "xamarin.forms.platform.android.BoxRenderer";
+ public static readonly string Button = "android.widget.Button";
+ public static readonly string DatePicker = "android.widget.EditText";
+ public static readonly string Editor = "xamarin.forms.platform.android.EditorEditText";
+ public static readonly string Entry = "xamarin.forms.platform.android.EntryEditText";
+ public static readonly string Frame = "xamarin.forms.platform.android.appcompat.FrameRenderer";
+ public static readonly string Image = "android.widget.ImageView";
+ public static readonly string Label = "android.widget.TextView";
+ public static readonly string ListView = "android.widget.ListView";
+ public static readonly string OpenGLView = "android.widget.GLSurfaceView";
+ public static readonly string Picker = "android.widget.EditText";
+ public static readonly string ProgressBar = "android.widget.ProgressBar";
+ public static readonly string SearchBar = "android.widget.SearchView";
+ public static readonly string Slider = "android.widget.SeekBar";
+ public static readonly string Stepper = "button marked:'+'";
+ public static readonly string Switch = "android.widget.Switch";
+ public static readonly string TableView = "android.widget.ListView";
+ public static readonly string TimePicker = "android.widget.EditText";
+ public static readonly string WebView = "android.widget.WebView";
+ }
+
+ internal static class PlatformQueries
+ {
+ public static readonly Func<AppQuery, AppQuery> Root = q => q.Id ("content");
+ public static readonly Func<AppQuery, AppQuery> RootPageListView = q => q.Raw ("ListViewRenderer index:0");
+ public static readonly Func<AppQuery, AppQuery> GalleryListView = q => q.Raw ("ListViewRenderer index:1");
+ public static readonly Func<AppQuery, AppQuery> PageWithoutNavigationBar = q => q.Raw ("* id:'content' index:0");
+ public static readonly Func<AppQuery, AppQuery> NavigationBarBackButton = q => q.Class ("android.support.v7.widget.Toolbar").Child ("android.widget.ImageButton");
+
+ // Views
+ public static readonly Func<AppQuery, AppQuery> ActivityIndicator = q => q.ClassFull (PlatformViews.ActivityIndicator);
+ public static readonly Func<AppQuery, AppQuery> Button = q => q.ClassFull (PlatformViews.Button);
+
+ public static Func<AppQuery, AppQuery> EntryWithPlaceholder (string text) {
+ return q => q.Raw (string.Format ("EntryEditText hint:'{0}'", text));
+ }
+ public static Func<AppQuery, AppQuery> EntryCellWithPlaceholder (string text) {
+ return q => q.Raw (string.Format ("EntryCellEditText hint:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryWithText (string text) {
+ return q => q.Raw (string.Format ("EntryEditText text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryCellWithText (string text) {
+ return q => q.Raw (string.Format ("EntryCellEditText text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EditorsWithText (string text) {
+ return q => q.Raw (string.Format ("EditorEditText text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryWithIndex (int index) {
+ return q => q.Raw (string.Format ("EntryEditText index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> SearchBarWithIndex (int index) {
+ return q => q.Raw (string.Format ("SearchView index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> LabelWithIndex (int index) {
+ return q => q.Raw (string.Format ("TextView index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> LabelWithText (string text) {
+ return q => q.Raw (string.Format ("TextView text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> LabelWithId (string id) {
+ return q => q.Raw (string.Format ("TextView id:'{0}'", id));
+ }
+
+ public static Func<AppQuery, AppQuery> PickerEntryWithIndex (int index) {
+ return q => q.Raw (string.Format ("EditText index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> PickerEntryWithPlaceholder (string placeholder) {
+ return q => q.Raw (string.Format ("EditText hint:'{0}'", placeholder));
+ }
+
+ public static Func<AppQuery, AppQuery> PickerEntryWithText (string text) {
+ return q => q.Raw (string.Format ("EditText text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> SwitchWithIndex (int index) {
+ return q => q.Raw (string.Format ("Switch index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> StepperWithIndex (int index) {
+ return q => q.Raw (string.Format ("button marked:'+' index:{0}", index));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.Android.UITests/PlatformTests/DisplayAlertUITestsAndroid.cs b/Xamarin.Forms.Core.Android.UITests/PlatformTests/DisplayAlertUITestsAndroid.cs
new file mode 100644
index 00000000..f0075576
--- /dev/null
+++ b/Xamarin.Forms.Core.Android.UITests/PlatformTests/DisplayAlertUITestsAndroid.cs
@@ -0,0 +1,27 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("DisplayAlert")]
+ internal class DisplayAlertUITestsAndroid : BaseTestFixture
+ {
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.DisplayAlertGallery);
+ }
+
+ [Test]
+ public void TestTapOff ()
+ {
+ App.Tap (c => c.Marked ("Alert Override2"));
+ App.Screenshot ("Display Alert");
+ App.TapCoordinates (100, 100);
+ App.WaitForElement (c => c.Marked ("Result: False"));
+ App.Screenshot ("Alert Dismissed");
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Core.Android.UITests/Properties/AssemblyInfo.cs b/Xamarin.Forms.Core.Android.UITests/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..8b4da046
--- /dev/null
+++ b/Xamarin.Forms.Core.Android.UITests/Properties/AssemblyInfo.cs
@@ -0,0 +1,40 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Xamarin.Forms.Core.Android.UITests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Forms.Core.Android.UITests")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("8668ccc3-4b09-4cb5-8f2d-61e2f820c887")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+
+[assembly: InternalsVisibleTo ("Xamarin.Forms.Loader")]
+[assembly: InternalsVisibleTo ("Xamarin.Forms.UITest.Validator")]
+
diff --git a/Xamarin.Forms.Core.Android.UITests/Xamarin.Forms.Core.Android.UITests.csproj b/Xamarin.Forms.Core.Android.UITests/Xamarin.Forms.Core.Android.UITests.csproj
new file mode 100644
index 00000000..e7041e95
--- /dev/null
+++ b/Xamarin.Forms.Core.Android.UITests/Xamarin.Forms.Core.Android.UITests.csproj
@@ -0,0 +1,313 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{A34EBE01-25BF-4E69-A2DC-2288DC625541}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Core.UITests</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Core.Android.UITests</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;__ANDROID__;UITEST</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;__ANDROID__;UITEST</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;__ANDROID__;UITEST</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ <Reference Include="nunit.framework">
+ <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="Xamarin.UITest, Version=1.3.3.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.UITest.1.3.3\lib\Xamarin.UITest.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\BaseTestFixture.cs">
+ <Link>BaseTestFixture.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Queries.cs">
+ <Link>Queries.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Remotes\BaseViewContainerRemote.cs">
+ <Link>Remotes\BaseViewContainerRemote.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Remotes\EventViewContainerRemote.cs">
+ <Link>Remotes\EventViewContainerRemote.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Remotes\LayeredViewContainerRemote.cs">
+ <Link>Remotes\LayeredViewContainerRemote.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Remotes\StateViewContainerRemote.cs">
+ <Link>Remotes\StateViewContainerRemote.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Remotes\ViewContainerRemote.cs">
+ <Link>Remotes\ViewContainerRemote.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ActivityIndicatorUITests.cs">
+ <Link>Tests\ActivityIndicatorUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\BoxViewUITests.cs">
+ <Link>Tests\BoxViewUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ButtonUITests.cs">
+ <Link>Tests\ButtonUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ContextActionsUITests.cs">
+ <Link>Tests\ContextActionsUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\DatePickerUITests.cs">
+ <Link>Tests\DatePickerUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\EditorUITests.cs">
+ <Link>Tests\EditorUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\EntryUITests.cs">
+ <Link>Tests\EntryUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\FrameUITests.cs">
+ <Link>Tests\FrameUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ImageUITests.cs">
+ <Link>Tests\ImageUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\LabelUITests.cs">
+ <Link>Tests\LabelUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-AbsoluteLayoutGalleryTest.cs">
+ <Link>Tests\Legacy-AbsoluteLayoutGalleryTest.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-BoundViewUITest.cs">
+ <Link>Tests\Legacy-BoundViewUITest.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-ButtonUITests.cs">
+ <Link>Tests\Legacy-ButtonUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-CarouselPageUITests.cs">
+ <Link>Tests\Legacy-CarouselPageUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-CellsUITests.cs">
+ <Link>Tests\Legacy-CellsUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-ClipToBoundsUITests.cs">
+ <Link>Tests\Legacy-ClipToBoundsUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-EditorUITests.cs">
+ <Link>Tests\Legacy-EditorUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-EntryUITests.cs">
+ <Link>Tests\Legacy-EntryUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-GridGalleryUITests.cs">
+ <Link>Tests\Legacy-GridGalleryUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-GroupedListActionsUITests.cs">
+ <Link>Tests\Legacy-GroupedListActionsUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-InputIntentUITests.cs">
+ <Link>Tests\Legacy-InputIntentUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-ListUITests.cs">
+ <Link>Tests\Legacy-ListUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-MapUITests.cs">
+ <Link>Tests\Legacy-MapUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-MinimumSizeUITest.cs">
+ <Link>Tests\Legacy-MinimumSizeUITest.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-NavigationBarUITests.cs">
+ <Link>Tests\Legacy-NavigationBarUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-RelativeLayoutUITest.cs">
+ <Link>Tests\Legacy-RelativeLayoutUITest.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-SearchBarUITests.cs">
+ <Link>Tests\Legacy-SearchBarUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-SliderUITests.cs">
+ <Link>Tests\Legacy-SliderUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-StackLayoutUITest.cs">
+ <Link>Tests\Legacy-StackLayoutUITest.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-StepperUITests.cs">
+ <Link>Tests\Legacy-StepperUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-SwitchUITests.cs">
+ <Link>Tests\Legacy-SwitchUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-TableViewUITests.cs">
+ <Link>Tests\Legacy-TableViewUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-TemplatedCarouselPageUITests.cs">
+ <Link>Tests\Legacy-TemplatedCarouselPageUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-TemplatedTabPageUITests.cs">
+ <Link>Tests\Legacy-TemplatedTabPageUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-ToolbarGalleryUITests.cs">
+ <Link>Tests\Legacy-ToolbarGalleryUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-UnevenViewCellUITests.cs">
+ <Link>Tests\Legacy-UnevenViewCellUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-ViewCellUITests.cs">
+ <Link>Tests\Legacy-ViewCellUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\PickerUITests.cs">
+ <Link>Tests\PickerUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ProgressBarUITests.cs">
+ <Link>Tests\ProgressBarUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\SearchBarUITests.cs">
+ <Link>Tests\SearchBarUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\SliderUITests.cs">
+ <Link>Tests\SliderUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\StepperUITests.cs">
+ <Link>Tests\StepperUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\SwitchUITests.cs">
+ <Link>Tests\SwitchUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\TimePickerUITests.cs">
+ <Link>Tests\TimePickerUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ViewUITests.cs">
+ <Link>Tests\ViewUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\WebViewUITests.cs">
+ <Link>Tests\WebViewUITests.cs</Link>
+ </Compile>
+ <Compile Include="App.cs" />
+ <Compile Include="PlatformQueries.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Remotes\RemoteFactory.cs">
+ <Link>Remotes\RemoteFactory.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\AppExtensions.cs">
+ <Link>Utilities\AppExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\Drag.cs">
+ <Link>Utilities\Drag.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\Gestures.cs">
+ <Link>Utilities\Gestures.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\Logger.cs">
+ <Link>Utilities\Logger.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\NumericExtensions.cs">
+ <Link>Utilities\NumericExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\ParsingUtils.cs">
+ <Link>Utilities\ParsingUtils.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\UITestCustomExceptions.cs">
+ <Link>Utilities\UITestCustomExceptions.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\ViewInspector.cs">
+ <Link>Utilities\ViewInspector.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\DisplayAlertUITests.cs">
+ <Link>Tests\DisplayAlertUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ActionSheetUITests.cs">
+ <Link>Tests\ActionSheetUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ToolbarItemTests.cs">
+ <Link>Tests\ToolbarItemTests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ScrollViewUITests.cs">
+ <Link>Tests\ScrollViewUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\RootGalleryUITests.cs">
+ <Link>Tests\RootGalleryUITests.cs</Link>
+ </Compile>
+ <Compile Include="PlatformTests\DisplayAlertUITestsAndroid.cs" />
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\AppearingUITests.cs">
+ <Link>Tests\AppearingUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\AutomationIDUITests.cs">
+ <Link>Tests\AutomationIDUITests.cs</Link>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.CustomAttributes\Xamarin.Forms.CustomAttributes.csproj">
+ <Project>{4DCD0420-1168-4B77-86DB-6196EE4BD491}</Project>
+ <Name>Xamarin.Forms.CustomAttributes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7d13bac2-c6a4-416a-b07e-c169b199e52b}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform\Xamarin.Forms.Platform.csproj">
+ <Project>{67f9d3a8-f71e-4428-913f-c37ae82cdb24}</Project>
+ <Name>Xamarin.Forms.Platform</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="..\Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Xamarin.Forms.Controls.Issues.Shared.projitems" Label="Shared" />
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+ </Target>
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ItemGroup />
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Core.Android.UITests/packages.config b/Xamarin.Forms.Core.Android.UITests/packages.config
new file mode 100644
index 00000000..031fa54c
--- /dev/null
+++ b/Xamarin.Forms.Core.Android.UITests/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit" version="2.6.4" targetFramework="net45" />
+ <package id="Xamarin.UITest" version="1.3.3" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.Core.Design/AttributeTableBuilder.cs b/Xamarin.Forms.Core.Design/AttributeTableBuilder.cs
new file mode 100644
index 00000000..07571d4c
--- /dev/null
+++ b/Xamarin.Forms.Core.Design/AttributeTableBuilder.cs
@@ -0,0 +1,74 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using System.Windows.Markup;
+using Microsoft.Windows.Design;
+
+namespace Xamarin.Forms.Core.Design
+{
+ internal class AttributeTableBuilder : Microsoft.Windows.Design.Metadata.AttributeTableBuilder
+ {
+ public AttributeTableBuilder ()
+ {
+ // Turn off validation of values, which doesn't work for OnPlatform/OnIdiom
+ AddCustomAttributes (typeof (AbsoluteLayout).Assembly,
+ new XmlnsSupportsValidationAttribute ("http://xamarin.com/schemas/2014/forms", false));
+
+ // Style isn't a view, make it visible
+ AddCallback (typeof(Style), builder => builder.AddCustomAttributes(
+ new EditorBrowsableAttribute (EditorBrowsableState.Always),
+ new System.Windows.Markup.ContentPropertyAttribute("Setters"),
+ // Since the class doesn't have a public parameterless ctor, we need to provide a converter
+ new System.ComponentModel.TypeConverterAttribute(typeof(StringConverter))));
+
+ // The Setter.Value can actually come from an <OnPlatform />, so enable it as Content.
+ AddCallback (typeof (Setter), builder => builder.AddCustomAttributes (
+ new EditorBrowsableAttribute (EditorBrowsableState.Always),
+ new System.Windows.Markup.ContentPropertyAttribute("Value")));
+
+ // Special case for FontSize which isn't an enum.
+ var fontElements = typeof(View).Assembly.ExportedTypes.Where(t => typeof(IFontElement).IsAssignableFrom(t));
+ foreach (var fontElement in fontElements) {
+ AddCallback (fontElement, builder => builder.AddCustomAttributes (
+ "FontSize",
+ new System.ComponentModel.TypeConverterAttribute (typeof (EnumConverter<NamedSize>))));
+ }
+
+ // TODO: OnPlatform/OnIdiom
+ // These two should be proper markup extensions, to follow WPF syntax for those.
+ // That would allow us to turn on XAML validation, which otherwise fails.
+ // NOTE: the two also need to provide a non-generic, object-based T so that
+ // the language service can find the type by its name. That class can be internal
+ // though, since its visibility in the markup is controlled by the EditorBrowsableAttribute.
+ // Make OnPlatform/OnIdiom visible for intellisense, and set as markup extension.
+ AddCallback (typeof (OnPlatform<>), builder => builder.AddCustomAttributes (new Attribute[] {
+ new EditorBrowsableAttribute (EditorBrowsableState.Always),
+ //new System.ComponentModel.TypeConverterAttribute(typeof(AnythingConverter)),
+ //new System.Windows.Markup.MarkupExtensionReturnTypeAttribute (),
+ }));
+ AddCallback (typeof (OnIdiom<>), builder => builder.AddCustomAttributes (new Attribute[] {
+ new EditorBrowsableAttribute (EditorBrowsableState.Always),
+ //new System.ComponentModel.TypeConverterAttribute(typeof(AnythingConverter)),
+ //new System.Windows.Markup.MarkupExtensionReturnTypeAttribute (),
+ }));
+ }
+ }
+
+ internal class AnythingConverter : System.ComponentModel.TypeConverter
+ {
+ public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
+ {
+ return true;
+ }
+
+ public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
+ {
+ return true;
+ }
+
+ public override bool IsValid (ITypeDescriptorContext context, object value)
+ {
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.Design/EnumConverter.cs b/Xamarin.Forms.Core.Design/EnumConverter.cs
new file mode 100644
index 00000000..21deabcd
--- /dev/null
+++ b/Xamarin.Forms.Core.Design/EnumConverter.cs
@@ -0,0 +1,14 @@
+using System.ComponentModel;
+
+namespace Xamarin.Forms.Core.Design
+{
+ /// <summary>
+ /// Generic version of the <see cref="EnumConverter"/> for reuse.
+ /// </summary>
+ internal class EnumConverter<T> : EnumConverter
+ {
+ public EnumConverter () : base(typeof(T))
+ {
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.Design/Properties/AssemblyInfo.cs b/Xamarin.Forms.Core.Design/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..1c6cce84
--- /dev/null
+++ b/Xamarin.Forms.Core.Design/Properties/AssemblyInfo.cs
@@ -0,0 +1,7 @@
+using System.Reflection;
+using Microsoft.Windows.Design.Metadata;
+
+[assembly: AssemblyTitle ("Xamarin.Forms.Core.Design")]
+[assembly: AssemblyDescription ("Provides the design-time metadata for the XAML language service.")]
+
+[assembly: ProvideMetadata (typeof (Xamarin.Forms.Core.Design.RegisterMetadata))] \ No newline at end of file
diff --git a/Xamarin.Forms.Core.Design/RegisterMetadata.cs b/Xamarin.Forms.Core.Design/RegisterMetadata.cs
new file mode 100644
index 00000000..59a2a095
--- /dev/null
+++ b/Xamarin.Forms.Core.Design/RegisterMetadata.cs
@@ -0,0 +1,9 @@
+using Microsoft.Windows.Design.Metadata;
+
+namespace Xamarin.Forms.Core.Design
+{
+ internal class RegisterMetadata : IProvideAttributeTable
+ {
+ public AttributeTable AttributeTable { get { return new AttributeTableBuilder ().CreateTable (); } }
+ }
+}
diff --git a/Xamarin.Forms.Core.Design/Xamarin.Forms.Core.Design.csproj b/Xamarin.Forms.Core.Design/Xamarin.Forms.Core.Design.csproj
new file mode 100644
index 00000000..7b02ea45
--- /dev/null
+++ b/Xamarin.Forms.Core.Design/Xamarin.Forms.Core.Design.csproj
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{98637471-8E5C-4DDE-89CA-2EAA664FB0EF}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Core.Design</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Core.Design</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <NuGetPackageImportStamp>
+ </NuGetPackageImportStamp>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup Condition=" '$(OS)' != 'Unix' ">
+ <Reference Include="Microsoft.Windows.Design.Extensibility, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\lib\Microsoft.Windows.Design.Extensibility.dll</HintPath>
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Xaml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup Condition=" '$(OS)' != 'Unix' ">
+ <Compile Include="AttributeTableBuilder.cs" />
+ <Compile Include="EnumConverter.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="RegisterMetadata.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ <GenerateDesignMetadata>true</GenerateDesignMetadata>
+ <Private>False</Private>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup Condition=" '$(OS)' != 'Unix' ">
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets') And '$(OS)' != 'Unix' " />
+ <Import Project="..\packages\Xamarin.Forms.Design.1.0.14-pre\build\Xamarin.Forms.Design.targets" Condition="Exists('..\packages\Xamarin.Forms.Design.1.0.14-pre\build\Xamarin.Forms.Design.targets') And '$(OS)' != 'Unix'" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild" Condition=" '$(OS)' != 'Unix' ">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('..\packages\Xamarin.Forms.Design.1.0.14-pre\build\Xamarin.Forms.Design.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Forms.Design.1.0.14-pre\build\Xamarin.Forms.Design.targets'))" />
+ </Target>
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Core.Design/packages.config b/Xamarin.Forms.Core.Design/packages.config
new file mode 100644
index 00000000..6e99fb80
--- /dev/null
+++ b/Xamarin.Forms.Core.Design/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Xamarin.Forms.Design" version="1.0.14-pre" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/AbsoluteLayoutTests.cs b/Xamarin.Forms.Core.UnitTests/AbsoluteLayoutTests.cs
new file mode 100644
index 00000000..3faec22e
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/AbsoluteLayoutTests.cs
@@ -0,0 +1,265 @@
+using System;
+using NUnit.Framework;
+using NUnit.Framework.Constraints;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class AbsoluteLayoutTests : BaseTestFixture
+ {
+
+ [Test]
+ public void Constructor ()
+ {
+ var abs = new AbsoluteLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ Assert.That (abs.Children, Is.Empty);
+
+ var sizeReq = abs.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+ Assert.AreEqual (Size.Zero, sizeReq.Request);
+ Assert.AreEqual (Size.Zero, sizeReq.Minimum);
+ }
+
+ [Test]
+ public void AbsolutePositionAndSize ()
+ {
+ var abs = new AbsoluteLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new View {IsPlatformEnabled = true};
+
+ abs.Children.Add (child, new Rectangle (10, 20, 30, 40));
+
+ abs.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (10, 20, 30, 40), child.Bounds);
+ }
+
+ [Test]
+ public void AbsolutePositionRelativeSize ()
+ {
+ var abs = new AbsoluteLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new View {IsPlatformEnabled = true};
+
+
+ abs.Children.Add (child, new Rectangle (10, 20, 0.4, 0.5), AbsoluteLayoutFlags.SizeProportional);
+
+ abs.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.That (child.X, Is.EqualTo (10));
+ Assert.That (child.Y, Is.EqualTo (20));
+ Assert.That (child.Width, Is.EqualTo (40).Within (0.0001));
+ Assert.That (child.Height, Is.EqualTo (50).Within (0.0001));
+ }
+
+ [TestCase (30, 40, 0.2, 0.3)]
+ [TestCase (35, 45, 0.5, 0.5)]
+ [TestCase (35, 45, 0, 0)]
+ [TestCase (35, 45, 1, 1)]
+ public void RelativePositionAbsoluteSize (double width, double height, double relX, double relY)
+ {
+ var abs = new AbsoluteLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new View {IsPlatformEnabled = true};
+
+ abs.Children.Add (child, new Rectangle (relX, relY, width, height), AbsoluteLayoutFlags.PositionProportional);
+
+ abs.Layout (new Rectangle (0, 0, 100, 100));
+
+ double expectedX = Math.Round ((100 - width) * relX);
+ double expectedY = Math.Round ((100 - height) * relY);
+ Assert.That (child.X, Is.EqualTo (expectedX).Within (0.0001));
+ Assert.That (child.Y, Is.EqualTo (expectedY).Within (0.0001));
+ Assert.That (child.Width, Is.EqualTo (width));
+ Assert.That (child.Height, Is.EqualTo (height));
+ }
+
+ [Test]
+ public void RelativePositionRelativeSize ([Values (0.0, 0.2, 0.5, 1.0)] double relX, [Values (0.0, 0.2, 0.5, 1.0)] double relY, [Values (0.0, 0.2, 0.5, 1.0)] double relHeight, [Values (0.0, 0.2, 0.5, 1.0)] double relWidth)
+ {
+ var abs = new AbsoluteLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new View {
+ IsPlatformEnabled = true
+ };
+ abs.Children.Add (child, new Rectangle(relX, relY, relWidth, relHeight), AbsoluteLayoutFlags.All);
+ abs.Layout (new Rectangle(0, 0, 100, 100));
+
+ double expectedWidth = Math.Round (100 * relWidth);
+ double expectedHeight = Math.Round (100 * relHeight);
+ double expectedX = Math.Round ((100 - expectedWidth) * relX);
+ double expectedY = Math.Round ((100 - expectedHeight) * relY);
+ Assert.That (child.X, Is.EqualTo (expectedX).Within (0.0001));
+ Assert.That (child.Y, Is.EqualTo (expectedY).Within (0.0001));
+ Assert.That (child.Width, Is.EqualTo (expectedWidth).Within (0.0001));
+ Assert.That (child.Height, Is.EqualTo (expectedHeight).Within (0.0001));
+ }
+
+ [Test]
+ public void SizeRequestWithNormalChild ()
+ {
+ var abs = new AbsoluteLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new View ();
+
+ // ChildSizeReq == 100x20
+ abs.Children.Add (child, new Rectangle (10, 20, 30, 40));
+
+ var sizeReq = abs.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+
+ Assert.AreEqual (new Size (40, 60), sizeReq.Request);
+ Assert.AreEqual (new Size (40, 60), sizeReq.Minimum);
+ }
+
+ [Test]
+ public void SizeRequestWithRelativePositionChild ()
+ {
+ var abs = new AbsoluteLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new View ();
+
+ // ChildSizeReq == 100x20
+ abs.Children.Add (child, new Rectangle(0.5, 0.5, 30, 40), AbsoluteLayoutFlags.PositionProportional);
+
+ var sizeReq = abs.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+
+ Assert.AreEqual (new Size (30, 40), sizeReq.Request);
+ Assert.AreEqual (new Size (30, 40), sizeReq.Minimum);
+ }
+
+ [Test]
+ public void SizeRequestWithRelativeChild ()
+ {
+ var abs = new AbsoluteLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new View {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ // ChildSizeReq == 100x20
+ abs.Children.Add (child, new Rectangle(0.5, 0.5, 0.5, 0.5), AbsoluteLayoutFlags.All);
+
+ var sizeReq = abs.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+
+ Assert.AreEqual (new Size (200, 40), sizeReq.Request);
+ Assert.AreEqual (new Size (0, 0), sizeReq.Minimum);
+ }
+
+ [Test]
+ public void SizeRequestWithRelativeSizeChild ()
+ {
+ var abs = new AbsoluteLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new View {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ // ChildSizeReq == 100x20
+ abs.Children.Add (child, new Rectangle(10, 20, 0.5, 0.5), AbsoluteLayoutFlags.SizeProportional);
+
+ var sizeReq = abs.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+
+ Assert.AreEqual (new Size (210, 60), sizeReq.Request);
+ Assert.AreEqual (new Size (10, 20), sizeReq.Minimum);
+ }
+
+ [Test]
+ public void MeasureInvalidatedFiresWhenFlagsChanged ()
+ {
+ var abs = new AbsoluteLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new View {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ abs.Children.Add (child, new Rectangle (1, 1, 100, 100));
+
+ bool fired = false;
+ abs.MeasureInvalidated += (sender, args) => fired = true;
+
+ AbsoluteLayout.SetLayoutFlags (child, AbsoluteLayoutFlags.PositionProportional);
+
+ Assert.True (fired);
+ }
+
+ [Test]
+ public void MeasureInvalidatedFiresWhenBoundsChanged ()
+ {
+ var abs = new AbsoluteLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new View {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ abs.Children.Add (child, new Rectangle (1, 1, 100, 100));
+
+ bool fired = false;
+ abs.MeasureInvalidated += (sender, args) => fired = true;
+
+ AbsoluteLayout.SetLayoutBounds (child, new Rectangle (2, 2, 200, 200));
+
+ Assert.True (fired);
+ }
+
+ [Test]
+ public void TestBoundsTypeConverter ()
+ {
+ var converter = new BoundsTypeConverter ();
+
+ Assert.IsTrue (converter.CanConvertFrom (typeof(string)));
+ Assert.AreEqual (new Rectangle (3, 4, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize), converter.ConvertFromInvariantString ("3, 4"));
+ Assert.AreEqual (new Rectangle (3, 4, 20, 30), converter.ConvertFromInvariantString ("3, 4, 20, 30"));
+ Assert.AreEqual (new Rectangle (3, 4, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize), converter.ConvertFromInvariantString ("3, 4, AutoSize, AutoSize"));
+ Assert.AreEqual (new Rectangle (3, 4, AbsoluteLayout.AutoSize, 30), converter.ConvertFromInvariantString ("3, 4, AutoSize, 30"));
+ Assert.AreEqual (new Rectangle (3, 4, 20, AbsoluteLayout.AutoSize), converter.ConvertFromInvariantString ("3, 4, 20, AutoSize"));
+ }
+
+ [Test]
+ public void TurkeyTestBoundsTypeConverter ()
+ {
+ var converter = new BoundsTypeConverter ();
+
+ var autoSize = "AutoSize";
+
+ Assert.AreEqual (new Rectangle (3.3, 4.4, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize), converter.ConvertFromInvariantString ("3.3, 4.4, " + autoSize + ", AutoSize"));
+ Assert.AreEqual (new Rectangle (3.3, 4.4, 5.5, 6.6), converter.ConvertFromInvariantString ("3.3, 4.4, 5.5, 6.6"));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/AnimatableKeyTests.cs b/Xamarin.Forms.Core.UnitTests/AnimatableKeyTests.cs
new file mode 100644
index 00000000..385ab1fc
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/AnimatableKeyTests.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class AnimatableKeyTests
+ {
+ class FakeAnimatable : IAnimatable
+ {
+ public void BatchBegin ()
+ {
+
+ }
+
+ public void BatchCommit ()
+ {
+
+ }
+ }
+
+ [Test]
+ public void KeysWithDifferentHandlesAreNotEqual ()
+ {
+ var animatable = new FakeAnimatable();
+
+ var key1 = new AnimatableKey(animatable, "handle1");
+ var key2 = new AnimatableKey(animatable, "handle2");
+
+ Assert.AreNotEqual (key1, key2);
+ }
+
+ [Test]
+ public void KeysWithDifferentAnimatablesAreNotEqual ()
+ {
+ var animatable1 = new FakeAnimatable();
+ var animatable2 = new FakeAnimatable();
+
+ var key1 = new AnimatableKey(animatable1, "handle");
+ var key2 = new AnimatableKey(animatable2, "handle");
+
+ Assert.AreNotEqual (key1, key2);
+ }
+
+ [Test]
+ public void KeysWithSameAnimatableAndHandleAreEqual ()
+ {
+ var animatable = new FakeAnimatable();
+
+ var key1 = new AnimatableKey(animatable, "handle");
+ var key2 = new AnimatableKey(animatable, "handle");
+
+ Assert.AreEqual (key1, key2);
+ }
+
+ [Test]
+ public void ThrowsWhenKeysWithSameAnimatableAdded ()
+ {
+ var animatable = new FakeAnimatable();
+
+ var key1 = new AnimatableKey(animatable, "handle");
+ var key2 = new AnimatableKey(animatable, "handle");
+
+ var dict = new Dictionary<AnimatableKey, object> { { key1, new object () } };
+
+ Assert.Throws<ArgumentException> (() => {
+ dict.Add (key2, new object ());
+ });
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/BaseTestFixture.cs b/Xamarin.Forms.Core.UnitTests/BaseTestFixture.cs
new file mode 100644
index 00000000..d3a57ea3
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/BaseTestFixture.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Globalization;
+using System.Threading;
+
+using NUnit.Framework;
+using NUnit.Framework.Constraints;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ public class BaseTestFixture
+ {
+ [SetUp]
+ public virtual void Setup ()
+ {
+#if !WINDOWS_PHONE
+ var culture = Environment.GetEnvironmentVariable ("UNIT_TEST_CULTURE");
+
+ if (!string.IsNullOrEmpty (culture)) {
+ var thead = Thread.CurrentThread;
+ thead.CurrentCulture = new CultureInfo (culture);
+ }
+#endif
+ Console.WriteLine ("Current culture: {0}", Thread.CurrentThread.CurrentCulture.Name);
+ }
+
+ [TearDown]
+ public virtual void TearDown ()
+ {
+
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/BehaviorTest.cs b/Xamarin.Forms.Core.UnitTests/BehaviorTest.cs
new file mode 100644
index 00000000..78e0cfb0
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/BehaviorTest.cs
@@ -0,0 +1,110 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ internal class MockBehavior<T> : Behavior<T> where T:BindableObject
+ {
+ public bool attached;
+ public bool detached;
+
+ protected override void OnAttachedTo (BindableObject bindable)
+ {
+ base.OnAttachedTo (bindable);
+ attached = true;
+ AssociatedObject = bindable;
+ }
+
+ protected override void OnDetachingFrom (BindableObject bindable)
+ {
+ detached = true;
+ base.OnDetachingFrom (bindable);
+ AssociatedObject = null;
+ }
+
+ public BindableObject AssociatedObject {get;set;}
+ }
+
+ [TestFixture]
+ public class BehaviorTest : BaseTestFixture
+ {
+ [Test]
+ public void AttachAndDetach ()
+ {
+ var behavior = new MockBehavior<MockBindable> ();
+ var bindable = new MockBindable ();
+
+ Assert.False (behavior.attached);
+ Assert.False (behavior.detached);
+ Assert.Null (behavior.AssociatedObject);
+
+ ((IAttachedObject)behavior).AttachTo (bindable);
+
+ Assert.True (behavior.attached);
+ Assert.False (behavior.detached);
+ Assert.AreSame (bindable, behavior.AssociatedObject);
+
+ ((IAttachedObject)behavior).DetachFrom (bindable);
+
+ Assert.True (behavior.attached);
+ Assert.True (behavior.detached);
+ Assert.Null (behavior.AssociatedObject);
+ }
+
+ [Test]
+ public void AttachToTypeCompatibleWithTargetType ()
+ {
+ var behavior = new MockBehavior<MockBindable> ();
+ var bindable = new View ();
+
+ Assert.Throws<InvalidOperationException> (() => ((IAttachedObject)behavior).AttachTo (bindable));
+ }
+
+ [Test]
+ public void BehaviorsInCollectionAreAttachedWhenCollectionIsAttached ()
+ {
+ var behavior = new MockBehavior<MockBindable> ();
+ var collection = new AttachedCollection<Behavior> ();
+ var bindable = new MockBindable ();
+ collection.Add (behavior);
+ Assert.Null (behavior.AssociatedObject);
+
+ ((IAttachedObject)collection).AttachTo (bindable);
+ Assert.AreSame (bindable, behavior.AssociatedObject);
+
+ ((IAttachedObject)collection).DetachFrom (bindable);
+ Assert.Null (behavior.AssociatedObject);
+ }
+
+ [Test]
+ public void BehaviorsAddedToAttachedCollectionAreAttached ()
+ {
+ var behavior = new MockBehavior<MockBindable> ();
+ var collection = new AttachedCollection<Behavior> ();
+ var bindable = new MockBindable ();
+ ((IAttachedObject)collection).AttachTo (bindable);
+ Assert.Null (behavior.AssociatedObject);
+
+ collection.Add (behavior);
+ Assert.AreSame (bindable, behavior.AssociatedObject);
+
+ collection.Remove (behavior);
+ Assert.Null (behavior.AssociatedObject);
+ }
+
+ [Test]
+ public void TestBehaviorsAttachedDP ()
+ {
+ var behavior = new MockBehavior<MockBindable> ();
+ var bindable = new MockBindable ();
+ var collection = bindable.Behaviors;
+ Assert.Null (behavior.AssociatedObject);
+
+ collection.Add (behavior);
+ Assert.AreSame (bindable, behavior.AssociatedObject);
+
+ collection.Remove (behavior);
+ Assert.Null (behavior.AssociatedObject);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/BindableObjectExtensionTests.cs b/Xamarin.Forms.Core.UnitTests/BindableObjectExtensionTests.cs
new file mode 100644
index 00000000..06a24c7f
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/BindableObjectExtensionTests.cs
@@ -0,0 +1,72 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class BindableObjectExtensionTests : BaseTestFixture
+ {
+ [Test]
+ public void SetBindingNull()
+ {
+ Assert.That (() => BindableObjectExtensions.SetBinding (null, MockBindable.TextProperty, "Name"),
+ Throws.InstanceOf<ArgumentNullException>());
+ Assert.That (() => BindableObjectExtensions.SetBinding (new MockBindable(), null, "Name"),
+ Throws.InstanceOf<ArgumentNullException>());
+ Assert.That (() => BindableObjectExtensions.SetBinding (new MockBindable(), MockBindable.TextProperty, null),
+ Throws.InstanceOf<ArgumentNullException>());
+
+ Assert.That (() => BindableObjectExtensions.SetBinding<MockViewModel> (null, MockBindable.TextProperty, vm => vm.Text),
+ Throws.InstanceOf<ArgumentNullException>());
+ Assert.That (() => BindableObjectExtensions.SetBinding<MockViewModel> (new MockBindable(), null, vm => vm.Text),
+ Throws.InstanceOf<ArgumentNullException>());
+ Assert.That (() => BindableObjectExtensions.SetBinding<MockViewModel> (new MockBindable(), MockBindable.TextProperty, null),
+ Throws.InstanceOf<ArgumentNullException>());
+ }
+
+ [Test]
+ public void Issue2643()
+ {
+ Label labelTempoDiStampa = new Label();
+ labelTempoDiStampa.BindingContext = new { Name = "1", Company = "Xamarin" };
+ labelTempoDiStampa.SetBinding (Label.TextProperty, "Name", stringFormat: "Hi: {0}");
+
+ Assert.That (labelTempoDiStampa.Text, Is.EqualTo ("Hi: 1"));
+ }
+
+ class Bz27229ViewModel
+ {
+ public object Member { get; private set; }
+ public Bz27229ViewModel ()
+ {
+ Member = new Generic<Label> (new Label {Text="foo"});
+ }
+ }
+
+ class Generic<TResult>
+ {
+ public Generic (TResult result)
+ {
+ Result = result;
+ }
+
+ public TResult Result { get; set; }
+ }
+
+ [Test]
+ public void Bz27229 ()
+ {
+ var totalCheckTime = new TextCell { Text = "Total Check Time" };
+ totalCheckTime.BindingContext = new Bz27229ViewModel ();
+ totalCheckTime.SetBinding(TextCell.DetailProperty,"Member.Result.Text");
+ Assert.AreEqual ("foo", totalCheckTime.Detail);
+
+ totalCheckTime = new TextCell { Text = "Total Check Time" };
+ totalCheckTime.BindingContext = new Bz27229ViewModel ();
+ totalCheckTime.SetBinding<Bz27229ViewModel>(TextCell.DetailProperty, vm =>
+ ((Generic<Label>)vm.Member).Result.Text);
+
+ Assert.AreEqual ("foo", totalCheckTime.Detail);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/BindableObjectUnitTests.cs b/Xamarin.Forms.Core.UnitTests/BindableObjectUnitTests.cs
new file mode 100644
index 00000000..7c4bac7a
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/BindableObjectUnitTests.cs
@@ -0,0 +1,1326 @@
+using System;
+using System.Globalization;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TypeConverter (typeof(ToBarConverter))]
+ internal class Bar
+ {
+
+ }
+
+ internal class Baz
+ {
+
+ }
+
+ internal class MockBindable
+ : VisualElement
+ {
+ public static readonly BindableProperty TextProperty = BindableProperty.Create<MockBindable, string> (
+ b => b.Text, "default", BindingMode.TwoWay);
+
+ public string Text
+ {
+ get { return (string)GetValue (TextProperty); }
+ set { SetValue (TextProperty, value); }
+ }
+
+ public string Foo { get; set; }
+
+ public int TargetInt { get; set; }
+
+ public static readonly BindableProperty BarProperty =
+ BindableProperty.Create<MockBindable, Bar> (w => w.Bar, default(Bar));
+
+ public Bar Bar {
+ get { return (Bar)GetValue (BarProperty); }
+ set { SetValue (BarProperty, value); }
+ }
+
+ public static readonly BindableProperty BazProperty =
+ BindableProperty.Create<MockBindable, Baz> (w => w.Baz, default(Baz));
+
+ [TypeConverter (typeof (ToBazConverter))]
+ public Baz Baz {
+ get { return (Baz)GetValue (BazProperty); }
+ set { SetValue (BazProperty, value); }
+ }
+
+ public static readonly BindableProperty QuxProperty =
+ BindableProperty.Create<MockBindable, Baz> (w => w.Qux, default(Baz));
+
+ public Baz Qux {
+ get { return (Baz)GetValue (QuxProperty); }
+ set { SetValue (QuxProperty, value); }
+ }
+ }
+
+ internal class ToBarConverter : TypeConverter
+ {
+ public override object ConvertFrom (System.Globalization.CultureInfo culture, object value)
+ {
+ return new Bar ();
+ }
+ }
+
+ internal class ToBazConverter : TypeConverter
+ {
+ public override object ConvertFrom (System.Globalization.CultureInfo culture, object value)
+ {
+ return new Baz ();
+ }
+ }
+
+ [TestFixture]
+ public class BindableObjectUnitTests : BaseTestFixture
+ {
+ [SetUp]
+ public void Setup()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void BindingContext()
+ {
+ var mock = new MockBindable();
+ Assert.IsNull (mock.BindingContext);
+
+ object obj = new object();
+ mock.BindingContext = obj;
+ Assert.AreSame (obj, mock.BindingContext);
+ }
+
+ [Test]
+ public void BindingContextChangedEvent()
+ {
+ var mock = new MockBindable();
+ mock.BindingContextChanged += (sender, args) => Assert.Pass();
+
+ mock.BindingContext = new object();
+
+ Assert.Fail ("The BindingContextChanged event was not fired.");
+ }
+
+ [Test]
+ [Description ("When the BindingContext changes, any bindings should be immediately applied.")]
+ public void BindingContextChangedBindingsApplied()
+ {
+ var mock = new MockBindable();
+ mock.SetBinding (MockBindable.TextProperty, new Binding ("."));
+ mock.BindingContext = "Test";
+
+ Assert.AreEqual ("Test", mock.GetValue (MockBindable.TextProperty));
+
+ mock.BindingContext = "Testing";
+
+ Assert.AreEqual ("Testing", mock.GetValue (MockBindable.TextProperty),
+ "Bindings were not reapplied to the new binding context");
+ }
+
+ [Test]
+ [Description ("When the BindingContext changes, the new context needs to listen for updates.")]
+ public void BindingContextChangedBindingsListening()
+ {
+ var mock = new MockBindable();
+ mock.SetBinding (MockBindable.TextProperty, new Binding ("Text"));
+
+ var vm = new MockViewModel();
+ mock.BindingContext = vm;
+
+ mock.BindingContext = (vm = new MockViewModel());
+
+ vm.Text = "test";
+
+ Assert.AreEqual ("test", mock.GetValue (MockBindable.TextProperty),
+ "The new ViewModel was not being listened to after being set");
+ }
+
+ [Test]
+ [Description ("When an INPC implementer is unset as the BindingContext, its changes shouldn't be listened to any further.")]
+ public void BindingContextUnsetStopsListening()
+ {
+ var mock = new MockBindable();
+ mock.SetBinding (MockBindable.TextProperty, new Binding ("Text"));
+
+ var vm = new MockViewModel();
+ mock.BindingContext = vm;
+
+ mock.BindingContext = null;
+
+ vm.Text = "test";
+
+ Assert.IsNull (mock.GetValue (Entry.TextProperty), "ViewModel was still being listened to after set to null");
+ }
+
+ [Test]
+ public void PropertyChanging()
+ {
+ var mock = new MockBindable();
+ mock.PropertyChanging += (sender, args) => {
+ Assert.AreEqual (MockBindable.TextProperty.PropertyName, args.PropertyName);
+ Assert.AreEqual (MockBindable.TextProperty.DefaultValue, mock.GetValue (MockBindable.TextProperty));
+ Assert.Pass();
+ };
+
+ mock.SetValue (MockBindable.TextProperty, "foo");
+
+ Assert.Fail ("The PropertyChanging event was not fired.");
+ }
+
+ [Test]
+ public void PropertyChangingSameValue()
+ {
+ const string value = "foo";
+
+ var mock = new MockBindable();
+ mock.SetValue (MockBindable.TextProperty, value);
+ mock.PropertyChanging += (s,e) => Assert.Fail();
+
+ mock.SetValue (MockBindable.TextProperty, value);
+
+ Assert.Pass();
+ }
+
+ [Test]
+ public void PropertyChangingDefaultValue()
+ {
+ var prop = BindableProperty.Create<MockBindable, string> (w => w.Foo, "DefaultValue");
+
+ var mock = new MockBindable();
+ mock.PropertyChanging += (s,e) => Assert.Fail();
+ mock.SetValue (prop, prop.DefaultValue);
+
+ Assert.Pass();
+ }
+
+ [Test]
+ public void PropertyChanged()
+ {
+ const string value = "foo";
+
+ var mock = new MockBindable();
+ mock.PropertyChanged += (sender, args) => {
+ Assert.AreEqual (MockBindable.TextProperty.PropertyName, args.PropertyName);
+ Assert.AreEqual (value, mock.GetValue (MockBindable.TextProperty));
+ Assert.Pass();
+ };
+
+ mock.SetValue (MockBindable.TextProperty, value);
+
+ Assert.Fail ("The PropertyChanged event was not fired.");
+ }
+
+ [Test]
+ public void PropertyChangedSameValue()
+ {
+ const string value = "foo";
+
+ var mock = new MockBindable();
+ mock.SetValue (MockBindable.TextProperty, value);
+ mock.PropertyChanged += (s,e) => Assert.Fail();
+
+ mock.SetValue (MockBindable.TextProperty, value);
+
+ Assert.Pass();
+ }
+
+ [Test]
+ public void PropertyChangedDefaultValue()
+ {
+ var prop = BindableProperty.Create<MockBindable, string> (w => w.Foo, "DefaultValue");
+
+ var mock = new MockBindable();
+ mock.PropertyChanged += (s,e) => Assert.Fail();
+
+ mock.SetValue (prop, prop.DefaultValue);
+
+ Assert.Pass();
+ }
+
+ [Test]
+ public void GetSetValue()
+ {
+ const string value = "foo";
+ var mock = new MockBindable();
+ mock.SetValue (MockBindable.TextProperty, value);
+
+ Assert.AreEqual (value, mock.GetValue (MockBindable.TextProperty));
+ }
+
+ [Test]
+ public void GetValueDefault()
+ {
+ var nulldefault = BindableProperty.Create<MockBindable, string> (w => w.Foo, null);
+ TestGetValueDefault (nulldefault);
+
+ var foodefault = BindableProperty.Create<MockBindable, string> (w => w.Foo, "Foo");
+ TestGetValueDefault (foodefault);
+ }
+
+ void TestGetValueDefault (BindableProperty property)
+ {
+ var mock = new MockBindable();
+ object value = mock.GetValue (property);
+ Assert.AreEqual (property.DefaultValue, value);
+ }
+
+ [Test]
+ public void SetValueInvalid()
+ {
+ var mock = new MockBindable();
+ Assert.Throws<ArgumentNullException> (() => mock.SetValue ((BindableProperty)null, "null"));
+ }
+
+ [Test]
+ public void GetValueInvalid()
+ {
+ var mock = new MockBindable();
+ Assert.Throws<ArgumentNullException> (() => mock.GetValue (null));
+ }
+
+ [Test]
+ public void ClearValueInvalid()
+ {
+ var mock = new MockBindable();
+ Assert.Throws<ArgumentNullException> (() => mock.ClearValue ((BindableProperty)null));
+ }
+
+ [Test]
+ public void ClearValue()
+ {
+ const string value = "foo";
+ var mock = new MockBindable();
+ mock.SetValue (MockBindable.TextProperty, value);
+ Assert.AreEqual (value, mock.GetValue (MockBindable.TextProperty));
+
+ mock.ClearValue (MockBindable.TextProperty);
+ TestGetValueDefault (MockBindable.TextProperty);
+ }
+
+ [Test]
+ public void ClearValueTriggersINPC ()
+ {
+ var bindable = new MockBindable ();
+ bool changingfired = false;
+ bool changedfired = false;
+ bool changingdelegatefired = false;
+ bool changeddelegatefired = false;
+ var property = BindableProperty.Create ("Foo", typeof(string), typeof(MockBindable), "foo",
+ propertyChanged: (b, o, n) => changeddelegatefired = true,
+ propertyChanging: (b, o, n) => changingdelegatefired = true
+ );
+ bindable.PropertyChanged += (sender, e) => { changedfired |= e.PropertyName == "Foo"; };
+ bindable.PropertyChanging += (sender, e) => { changingfired |= e.PropertyName == "Foo"; };
+
+ bindable.SetValue (property, "foobar");
+ changingfired = changedfired = changeddelegatefired = changingdelegatefired = false;
+
+ bindable.ClearValue (property);
+ Assert.True (changingfired);
+ Assert.True (changedfired);
+ Assert.True (changingdelegatefired);
+ Assert.True (changeddelegatefired);
+ }
+
+ [Test]
+ public void ClearValueDoesNotTriggersINPCOnSameValues ()
+ {
+ var bindable = new MockBindable ();
+ bool changingfired = false;
+ bool changedfired = false;
+ bool changingdelegatefired = false;
+ bool changeddelegatefired = false;
+ var property = BindableProperty.Create ("Foo", typeof(string), typeof(MockBindable), "foo",
+ propertyChanged: (b, o, n) => changeddelegatefired = true,
+ propertyChanging: (b, o, n) => changingdelegatefired = true
+ );
+ bindable.PropertyChanged += (sender, e) => { changedfired |= e.PropertyName == "Foo"; };
+ bindable.PropertyChanging += (sender, e) => { changingfired |= e.PropertyName == "Foo"; };
+
+ bindable.SetValue (property, "foobar");
+ bindable.SetValue (property, "foo");
+ changingfired = changedfired = changeddelegatefired = changingdelegatefired = false;
+
+ bindable.ClearValue (property);
+ Assert.False (changingfired);
+ Assert.False (changedfired);
+ Assert.False (changingdelegatefired);
+ Assert.False (changeddelegatefired);
+ }
+
+ [Test]
+ public void SetBindingInvalid()
+ {
+ var mock = new MockBindable();
+ Assert.Throws<ArgumentNullException> (() => mock.SetBinding (null, new Binding (".")));
+ Assert.Throws<ArgumentNullException> (() => mock.SetBinding (MockBindable.TextProperty, null));
+ }
+
+ [Test]
+ public void RemoveUnaddedBinding()
+ {
+ var mock = new MockBindable();
+ Assert.That (() => mock.RemoveBinding (MockBindable.TextProperty), Throws.Nothing);
+ }
+
+ [Test]
+ public void RemoveBindingInvalid()
+ {
+ var mock = new MockBindable();
+ Assert.Throws<ArgumentNullException> (() => mock.RemoveBinding (null));
+ }
+
+ [Test]
+ public void RemovedBindingDoesNotUpdate()
+ {
+ const string newvalue = "New Value";
+ var viewmodel = new MockViewModel {
+ Text = "Foo"
+ };
+
+ var binding = new Binding ("Text");
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (MockBindable.TextProperty, binding);
+
+ string original = (string)bindable.GetValue (MockBindable.TextProperty);
+
+ bindable.RemoveBinding (MockBindable.TextProperty);
+
+ viewmodel.Text = newvalue;
+ Assert.AreEqual (original, bindable.GetValue (MockBindable.TextProperty),
+ "Property updated from a removed binding");
+ }
+
+ [Test]
+ public void CoerceValue()
+ {
+ var property = BindableProperty.Create<MockBindable, string> (w => w.Foo, null,
+ coerceValue: (bo, o) => o.ToUpper());
+
+ const string value = "value";
+ var mock = new MockBindable();
+ mock.SetValue (property, value);
+ Assert.AreEqual (value.ToUpper(), mock.GetValue (property));
+ }
+
+ [Test]
+ public void ValidateValue()
+ {
+ var property = BindableProperty.Create<MockBindable, string> (w => w.Foo, null,
+ validateValue: (b, v) => false);
+
+ var mock = new MockBindable();
+ Assert.Throws<ArgumentException> (() => mock.SetValue (property, null));
+ }
+
+ [Test]
+ public void BindablePropertyChanged()
+ {
+ bool changed = false;
+
+ string oldv = "bar";
+ string newv = "foo";
+
+ var property = BindableProperty.Create<MockBindable, string> (w => w.Foo, oldv,
+ propertyChanged: (b, ov, nv) => {
+ Assert.AreSame (oldv, ov);
+ Assert.AreSame (newv, nv);
+ changed = true;
+ });
+
+ var mock = new MockBindable();
+ mock.SetValue (property, newv);
+
+ Assert.IsTrue (changed, "PropertyChanged was not called");
+ }
+
+ [Test]
+ public void RecursiveChange ()
+ {
+ bool changedA1 = false, changedA2 = false, changedB1 = false, changedB2 = false;
+
+ var mock = new MockBindable ();
+ mock.PropertyChanged += (sender, args) => {
+ if (!changedA1) {
+ Assert.AreEqual ("1", mock.GetValue (MockBindable.TextProperty));
+ Assert.IsFalse (changedA2);
+ Assert.IsFalse (changedB1);
+ Assert.IsFalse (changedB2);
+ mock.SetValue (MockBindable.TextProperty, "2");
+ changedA1 = true;
+ } else {
+ Assert.AreEqual ("2", mock.GetValue (MockBindable.TextProperty));
+ Assert.IsFalse (changedA2);
+ Assert.IsTrue (changedB1);
+ Assert.IsFalse (changedB2);
+ changedA2 = true;
+ }
+ };
+ mock.PropertyChanged += (sender, args) => {
+ if (!changedB1) {
+ Assert.AreEqual ("1", mock.GetValue (MockBindable.TextProperty));
+ Assert.IsTrue (changedA1);
+ Assert.IsFalse (changedA2);
+ Assert.IsFalse (changedB2);
+ changedB1 = true;
+ } else {
+ Assert.AreEqual ("2", mock.GetValue (MockBindable.TextProperty));
+ Assert.IsTrue (changedA1);
+ Assert.IsTrue (changedA2);
+ Assert.IsFalse (changedB2);
+ changedB2 = true;
+ }
+ };
+ mock.SetValue (MockBindable.TextProperty, "1");
+ Assert.AreEqual ("2", mock.GetValue (MockBindable.TextProperty));
+ Assert.IsTrue (changedA1);
+ Assert.IsTrue (changedA2);
+ Assert.IsTrue (changedB1);
+ Assert.IsTrue (changedB2);
+ }
+
+ [Test]
+ public void RaiseOnEqual()
+ {
+ string foo = "foo";
+ var mock = new MockBindable();
+ mock.SetValue (MockBindable.TextProperty, foo);
+
+ bool changing = false;
+ mock.PropertyChanging += (o, e) => {
+ Assert.That (e.PropertyName, Is.EqualTo (MockBindable.TextProperty.PropertyName));
+ changing = true;
+ };
+
+ bool changed = true;
+ mock.PropertyChanged += (o, e) => {
+ Assert.That (e.PropertyName, Is.EqualTo (MockBindable.TextProperty.PropertyName));
+ changed = true;
+ };
+
+ mock.SetValueCore (MockBindable.TextProperty, foo,
+ BindableObject.SetValueFlags.ClearOneWayBindings | BindableObject.SetValueFlags.ClearDynamicResource | BindableObject.SetValueFlags.RaiseOnEqual);
+
+ Assert.That (changing, Is.True, "PropertyChanging event did not fire");
+ Assert.That (changed, Is.True, "PropertyChanged event did not fire");
+ }
+
+ [Test]
+ public void BindingContextGetter ()
+ {
+ var label = new Label ();
+ var view = new StackLayout { Children = {label} };
+
+ view.BindingContext = new {item0 = "Foo", item1 = "Bar"};
+ label.SetBinding (BindableObject.BindingContextProperty, "item0");
+ label.SetBinding (Label.TextProperty, Binding.SelfPath);
+
+ Assert.AreSame (label.BindingContext, label.GetValue (BindableObject.BindingContextProperty));
+ }
+
+ [Test]
+ public void BoundBindingContextUpdate ()
+ {
+ var label = new Label ();
+ var view = new StackLayout { Children = {label} };
+ var vm = new MockViewModel { Text = "FooBar" };
+
+ view.BindingContext = vm;
+ label.SetBinding (BindableObject.BindingContextProperty, "Text");
+ label.SetBinding (Label.TextProperty, Binding.SelfPath);
+
+ Assert.AreEqual ("FooBar", label.BindingContext);
+
+ vm.Text = "Baz";
+ Assert.AreEqual ("Baz", label.BindingContext);
+ }
+
+ [Test]
+ public void BoundBindingContextChange ()
+ {
+ var label = new Label ();
+ var view = new StackLayout { Children = {label} };
+
+ view.BindingContext = new MockViewModel { Text = "FooBar" };;
+ label.SetBinding (BindableObject.BindingContextProperty, "Text");
+ label.SetBinding (Label.TextProperty, Binding.SelfPath);
+
+ Assert.AreEqual ("FooBar", label.BindingContext);
+
+ view.BindingContext = new MockViewModel { Text = "Baz" };;
+ Assert.AreEqual ("Baz", label.BindingContext);
+ }
+
+ [Test]
+ public void TestReadOnly ()
+ {
+ var bindablePropertyKey = BindableProperty.CreateReadOnly<MockBindable, string> (w => w.Foo, "DefaultValue");
+ var bindableProperty = bindablePropertyKey.BindableProperty;
+
+ var bindable = new MockBindable ();
+ Assert.AreEqual ("DefaultValue", bindable.GetValue (bindableProperty));
+
+ bindable.SetValue (bindablePropertyKey, "Bar");
+ Assert.AreEqual ("Bar", bindable.GetValue (bindableProperty));
+
+ Assert.Throws<InvalidOperationException> (() => bindable.SetValue (bindableProperty, "Baz"));
+ Assert.AreEqual ("Bar", bindable.GetValue (bindableProperty));
+
+ Assert.Throws<InvalidOperationException> (() => bindable.ClearValue (bindableProperty));
+
+ bindable.ClearValue (bindablePropertyKey);
+ Assert.AreEqual ("DefaultValue", bindable.GetValue (bindableProperty));
+ }
+
+ [Test]
+ public void TestBindingTwoWayOnReadOnly ()
+ {
+ var bindablePropertyKey = BindableProperty.CreateReadOnly<MockBindable, string> (w => w.Foo, "DefaultValue", BindingMode.OneWayToSource);
+ var bindableProperty = bindablePropertyKey.BindableProperty;
+
+ var bindable = new MockBindable ();
+ var vm = new MockViewModel ();
+
+ bindable.SetBinding (bindableProperty, new Binding ("Text", BindingMode.TwoWay));
+ Assert.DoesNotThrow (() => bindable.BindingContext = vm);
+
+ Assert.AreEqual ("DefaultValue", bindable.GetValue (bindableProperty));
+ }
+
+ [Test]
+ public void DefaultValueCreator ()
+ {
+ int invoked = 0;
+ object defaultValue = new object ();
+ var bindableProperty = BindableProperty.Create ("Foo", typeof(object), typeof(MockBindable), defaultValue, defaultValueCreator: o => {
+ invoked++;
+ return new object ();
+ });
+ var bindable = new MockBindable ();
+
+ Assert.AreSame (defaultValue, bindableProperty.DefaultValue);
+ var newvalue = bindable.GetValue (bindableProperty);
+ Assert.AreNotSame (defaultValue, newvalue);
+ Assert.NotNull (newvalue);
+ Assert.AreEqual (1, invoked);
+ }
+
+ [Test]
+ public void DefaultValueCreatorIsInvokedOnlyAtFirstTime ()
+ {
+ int invoked = 0;
+ var bindableProperty = BindableProperty.Create ("Foo", typeof(object), typeof(MockBindable), null, defaultValueCreator: o => {
+ invoked++;
+ return new object ();
+ });
+ var bindable = new MockBindable ();
+
+ var value0 = bindable.GetValue (bindableProperty);
+ var value1 = bindable.GetValue (bindableProperty);
+ Assert.NotNull (value0);
+ Assert.NotNull (value1);
+ Assert.AreSame (value0, value1);
+ Assert.AreEqual (1, invoked);
+ }
+
+ [Test]
+ public void DefaultValueCreatorNotSharedAccrossInstances ()
+ {
+ int invoked = 0;
+ var bindableProperty = BindableProperty.Create ("Foo", typeof(object), typeof(MockBindable), null, defaultValueCreator: o=> {
+ invoked++;
+ return new object ();
+ });
+ var bindable0 = new MockBindable ();
+ var bindable1 = new MockBindable ();
+ var value0 = bindable0.GetValue (bindableProperty);
+ var value1 = bindable1.GetValue (bindableProperty);
+
+ Assert.AreNotSame (value0, value1);
+ Assert.AreEqual (2, invoked);
+ }
+
+ [Test]
+ public void DefaultValueCreatorInvokedAfterClearValue ()
+ {
+ int invoked = 0;
+ var bindableProperty = BindableProperty.Create ("Foo", typeof(object), typeof(MockBindable), null, defaultValueCreator: o => {
+ invoked++;
+ return new object ();
+ });
+ var bindable = new MockBindable ();
+
+ Assert.AreEqual (0, invoked);
+
+ var value0 = bindable.GetValue (bindableProperty);
+ Assert.NotNull (value0);
+ Assert.AreEqual (1, invoked);
+ bindable.ClearValue (bindableProperty);
+
+ var value1 = bindable.GetValue (bindableProperty);
+ Assert.NotNull (value1);
+ Assert.AreEqual (2, invoked);
+ Assert.AreNotSame (value0, value1);
+ }
+
+ [Test]
+ public void DefaultValueCreatorOnlyInvokedOnGetValue ()
+ {
+ int invoked = 0;
+ var bindableProperty = BindableProperty.Create ("Foo", typeof(object), typeof(MockBindable), null, defaultValueCreator: o => {
+ invoked++;
+ return new object ();
+ });
+ var bindable = new MockBindable ();
+
+ Assert.AreEqual (0, invoked);
+
+ var newvalue = bindable.GetValue (bindableProperty);
+ Assert.NotNull (newvalue);
+ Assert.AreEqual (1, invoked);
+ }
+
+ [Test]
+ public void DefaultValueCreatorDoesNotTriggerINPC ()
+ {
+ int invoked = 0;
+ int propertychanged = 0;
+ int changedfired = 0;
+ var bindableProperty = BindableProperty.Create ("Foo", typeof(object), typeof(MockBindable), null,
+ propertyChanged: (bindable,oldvalue,newvalue) =>{
+ propertychanged ++;
+ },
+ defaultValueCreator: o => {
+ invoked++;
+ return new object ();
+ });
+
+ var bp = new MockBindable ();
+ bp.PropertyChanged += (sender, e) => {
+ if (e.PropertyName == "Foo")
+ changedfired++;
+ };
+ var value0 = bp.GetValue (bindableProperty);
+ Assert.NotNull (value0);
+ Assert.AreEqual (1, invoked);
+ Assert.AreEqual (0, propertychanged);
+ Assert.AreEqual (0, changedfired);
+
+ }
+
+ [Test]
+ public void StyleValueIsOverridenByValue ()
+ {
+ var label = new Label ();
+ label.SetValue (Label.TextProperty, "Foo", true);
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetValue (Label.TextProperty, "Bar");
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleBindingIsOverridenByValue ()
+ {
+ var label = new Label ();
+ label.SetBinding (Label.TextProperty, new Binding ("foo"), true);
+ label.BindingContext = new {foo = "Foo"};
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetValue (Label.TextProperty, "Bar");
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleDynResourceIsOverridenByValue ()
+ {
+ var label = new Label ();
+ label.SetDynamicResource (Label.TextProperty, "foo", true);
+ label.Resources = new ResourceDictionary {
+ {"foo", "Foo"}
+ };
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetValue (Label.TextProperty, "Bar");
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleValueIsOverridenByBinding ()
+ {
+ var label = new Label ();
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetValue (Label.TextProperty, "Foo", true);
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetBinding (Label.TextProperty, "bar");
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleBindingIsOverridenByBinding ()
+ {
+ var label = new Label ();
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetBinding (Label.TextProperty, new Binding ("foo"), true);
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetBinding (Label.TextProperty, "bar");
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleDynResourceIsOverridenByBinding ()
+ {
+ var label = new Label ();
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetDynamicResource (Label.TextProperty, "foo", true);
+ label.Resources = new ResourceDictionary {
+ {"foo", "Foo"},
+ };
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetBinding (Label.TextProperty, "bar");
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleValueIsOverridenByDynResource ()
+ {
+ var label = new Label ();
+ label.Resources = new ResourceDictionary {
+ {"foo", "Foo"},
+ {"bar", "Bar"}
+ };
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetValue (Label.TextProperty, "Foo", true);
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetDynamicResource (Label.TextProperty, "bar");
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleBindingIsOverridenByDynResource ()
+ {
+ var label = new Label ();
+ label.Resources = new ResourceDictionary {
+ {"foo", "Foo"},
+ {"bar", "Bar"}
+ };
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetBinding (Label.TextProperty, new Binding ("foo"), true);
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetDynamicResource (Label.TextProperty, "bar");
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleDynResourceIsOverridenByDynResource ()
+ {
+ var label = new Label ();
+ label.Resources = new ResourceDictionary {
+ {"foo", "Foo"},
+ {"bar", "Bar"}
+ };
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetDynamicResource (Label.TextProperty, "foo", true);
+
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetDynamicResource (Label.TextProperty, "bar");
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void ValueIsPreservedOnStyleValue ()
+ {
+ var label = new Label ();
+ label.SetValue (Label.TextProperty, "Foo");
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetValue (Label.TextProperty, "Bar", true);
+ Assert.AreEqual ("Foo", label.Text);
+ }
+ [Test]
+ public void BindingIsPreservedOnStyleValue ()
+ {
+ var label = new Label ();
+ label.SetBinding (Label.TextProperty, new Binding ("foo"));
+ label.BindingContext = new {foo = "Foo"};
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetValue (Label.TextProperty, "Bar", true);
+ Assert.AreEqual ("Foo", label.Text);
+ }
+ [Test]
+ public void DynResourceIsPreservedOnStyleValue ()
+ {
+ var label = new Label ();
+ label.SetDynamicResource (Label.TextProperty, "foo");
+ label.Resources = new ResourceDictionary {
+ {"foo", "Foo"}
+ };
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetValue (Label.TextProperty, "Bar", true);
+ Assert.AreEqual ("Foo", label.Text);
+ }
+
+ [Test]
+ public void ValueIsPreservedOnStyleBinding ()
+ {
+ var label = new Label ();
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetValue (Label.TextProperty, "Foo");
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetBinding (Label.TextProperty, new Binding ("bar"), true);
+ Assert.AreEqual ("Foo", label.Text);
+ }
+
+ [Test]
+ public void BindingIsPreservedOnStyleBinding ()
+ {
+ var label = new Label ();
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetBinding (Label.TextProperty, new Binding ("foo"));
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetBinding (Label.TextProperty, new Binding ("bar"), true);
+ Assert.AreEqual ("Foo", label.Text);
+ }
+
+ [Test]
+ public void DynResourceIsPreservedOnStyleBinding ()
+ {
+ var label = new Label ();
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetDynamicResource (Label.TextProperty, "foo");
+ label.Resources = new ResourceDictionary {
+ {"foo", "Foo"},
+ };
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetBinding (Label.TextProperty, new Binding ("bar"), true);
+ Assert.AreEqual ("Foo", label.Text);
+ }
+
+ [Test]
+ public void ValueIsPreservedOnStyleDynResource ()
+ {
+ var label = new Label ();
+ label.Resources = new ResourceDictionary {
+ {"foo", "Foo"},
+ {"bar", "Bar"}
+ };
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetValue (Label.TextProperty, "Foo");
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetDynamicResource (Label.TextProperty, "bar", true);
+ Assert.AreEqual ("Foo", label.Text);
+ }
+
+ [Test]
+ public void BindingIsPreservedOnStyleDynResource ()
+ {
+ var label = new Label ();
+ label.Resources = new ResourceDictionary {
+ {"foo", "Foo"},
+ {"bar", "Bar"}
+ };
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetBinding (Label.TextProperty, new Binding ("foo"));
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetDynamicResource (Label.TextProperty, "bar", true);
+ Assert.AreEqual ("Foo", label.Text);
+ }
+
+ [Test]
+ public void DynResourceIsPreservedOnStyleDynResource ()
+ {
+ var label = new Label ();
+ label.Resources = new ResourceDictionary {
+ {"foo", "Foo"},
+ {"bar", "Bar"}
+ };
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetDynamicResource (Label.TextProperty, "foo");
+
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetDynamicResource (Label.TextProperty, "bar", true);
+ Assert.AreEqual ("Foo", label.Text);
+ }
+
+ [Test]
+ public void StyleValueIsOverridenByStyleValue ()
+ {
+ var label = new Label ();
+ label.SetValue (Label.TextProperty, "Foo", true);
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetValue (Label.TextProperty, "Bar", true);
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleBindingIsOverridenByStyleValue ()
+ {
+ var label = new Label ();
+ label.SetBinding (Label.TextProperty, new Binding ("foo"), true);
+ label.BindingContext = new {foo = "Foo"};
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetValue (Label.TextProperty, "Bar", true);
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleDynResourceIsOverridenByStyleValue ()
+ {
+ var label = new Label ();
+ label.SetDynamicResource (Label.TextProperty, "foo", true);
+ label.Resources = new ResourceDictionary {
+ {"foo", "Foo"}
+ };
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetValue (Label.TextProperty, "Bar", true);
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleValueIsOverridenByStyleBinding ()
+ {
+ var label = new Label ();
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetValue (Label.TextProperty, "Foo", true);
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetBinding (Label.TextProperty, new Binding("bar"), true);
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleBindingIsOverridenByStyleBinding ()
+ {
+ var label = new Label ();
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetBinding (Label.TextProperty, new Binding ("foo"), true);
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetBinding (Label.TextProperty, new Binding("bar"), true);
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleDynResourceIsOverridenByStyleBinding ()
+ {
+ var label = new Label ();
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetDynamicResource (Label.TextProperty, "foo", true);
+ label.Resources = new ResourceDictionary {
+ {"foo", "Foo"},
+ };
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetBinding (Label.TextProperty, new Binding("bar"), true);
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleValueIsOverridenByStyleDynResource ()
+ {
+ var label = new Label ();
+ label.Resources = new ResourceDictionary {
+ {"foo", "Foo"},
+ {"bar", "Bar"}
+ };
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetValue (Label.TextProperty, "Foo", true);
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetDynamicResource (Label.TextProperty, "bar", true);
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleBindingIsOverridenByStyleDynResource ()
+ {
+ var label = new Label ();
+ label.Resources = new ResourceDictionary {
+ {"foo", "Foo"},
+ {"bar", "Bar"}
+ };
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetBinding (Label.TextProperty, new Binding ("foo"), true);
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetDynamicResource (Label.TextProperty, "bar", true);
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void StyleDynResourceIsOverridenByStyleDynResource ()
+ {
+ var label = new Label ();
+ label.Resources = new ResourceDictionary {
+ {"foo", "Foo"},
+ {"bar", "Bar"}
+ };
+ label.BindingContext = new {foo = "Foo", bar = "Bar"};
+ label.SetDynamicResource (Label.TextProperty, "foo", true);
+
+ Assert.AreEqual ("Foo", label.Text);
+
+ label.SetDynamicResource (Label.TextProperty, "bar", true);
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void SetValueCoreImplicitelyCastBasicType ()
+ {
+ var prop = BindableProperty.Create ("Foo", typeof(int), typeof(MockBindable), 0);
+ var bindable = new MockBindable ();
+
+ Assert.DoesNotThrow (() => bindable.SetValue (prop, (object)(short)42));
+ Assert.AreEqual (42, bindable.GetValue (prop));
+
+ bindable.SetValue (prop, (object)(long)-42);
+ Assert.AreNotEqual (-42, bindable.GetValue (prop));
+ }
+
+ class CastFromString
+ {
+ public string Result { get; private set; }
+ public static implicit operator CastFromString (string source)
+ {
+ var o = new CastFromString ();
+ o.Result = source;
+ return o;
+ }
+ }
+
+ [Test]
+ public void SetValueCoreInvokesOpImplicitOnPropertyType ()
+ {
+ var prop = BindableProperty.Create ("Foo", typeof(CastFromString), typeof(MockBindable), null);
+ var bindable = new MockBindable ();
+
+ Assert.Null (bindable.GetValue (prop));
+ bindable.SetValue (prop, "foo");
+
+ Assert.AreEqual ("foo", ((CastFromString)bindable.GetValue (prop)).Result);
+ }
+
+ class CastToString
+ {
+ string Result { get; set; }
+
+ public CastToString (string result)
+ {
+ Result = result;
+ }
+
+ public static implicit operator string (CastToString source)
+ {
+ return source.Result;
+ }
+
+ public override string ToString ()
+ {
+ throw new InvalidOperationException ();
+ }
+ }
+
+ [Test]
+ public void SetValueCoreInvokesOpImplicitOnValue ()
+ {
+ var prop = BindableProperty.Create ("Foo", typeof(string), typeof(MockBindable), null);
+ var bindable = new MockBindable ();
+
+ Assert.Null (bindable.GetValue (prop));
+ bindable.SetValue (prop, new CastToString ("foo"));
+
+ Assert.AreEqual ("foo", bindable.GetValue (prop));
+ }
+
+ [Test]
+ public void DefaultValueCreatorCalledForChangeDelegates ()
+ {
+ int changedOld = -1;
+ int changedNew = -1;
+
+ int changingOld = -1;
+ int changingNew = -1;
+ var prop = BindableProperty.Create ("Foo", typeof (int), typeof (MockBindable), 0, defaultValueCreator: b => 10,
+ propertyChanged: (b, value, newValue) => {
+ changedOld = (int) value;
+ changedNew = (int) newValue;
+ },
+ propertyChanging: (b, value, newValue) => {
+ changingOld = (int) value;
+ changingNew = (int) newValue;
+ });
+
+ var bindable = new MockBindable ();
+
+
+ var defaultValue = (int) bindable.GetValue (prop);
+
+ Assert.AreEqual (10, defaultValue);
+
+ bindable.SetValue (prop, 5);
+
+ bindable.ClearValue (prop);
+
+ Assert.AreEqual (5, changedOld);
+ Assert.AreEqual (5, changingOld);
+ Assert.AreEqual (10, changedNew);
+ Assert.AreEqual (10, changingNew);
+ }
+
+ [Test]
+ public void GetValuesDefaults()
+ {
+ var prop = BindableProperty.Create ("Foo", typeof(int), typeof(MockBindable), 0);
+ var prop1 = BindableProperty.Create ("Foo1", typeof(int), typeof(MockBindable), 1);
+ var prop2 = BindableProperty.Create ("Foo2", typeof(int), typeof(MockBindable), 2);
+ var bindable = new MockBindable ();
+
+
+ object[] values = bindable.GetValues (prop, prop1, prop2);
+ Assert.That (values.Length == 3);
+ Assert.That (values[0], Is.EqualTo (0));
+ Assert.That (values[1], Is.EqualTo (1));
+ Assert.That (values[2], Is.EqualTo (2));
+ }
+
+ [Test]
+ public void GetValues()
+ {
+ var prop = BindableProperty.Create ("Foo", typeof(int), typeof(MockBindable), 0);
+ var prop1 = BindableProperty.Create ("Foo1", typeof(int), typeof(MockBindable), 1);
+ var prop2 = BindableProperty.Create ("Foo2", typeof(int), typeof(MockBindable), 2);
+ var bindable = new MockBindable ();
+ bindable.SetValue (prop, 3);
+ bindable.SetValue (prop2, 5);
+
+
+ object[] values = bindable.GetValues (prop, prop1, prop2);
+ Assert.That (values.Length == 3);
+ Assert.That (values[0], Is.EqualTo (3));
+ Assert.That (values[1], Is.EqualTo (1));
+ Assert.That (values[2], Is.EqualTo (5));
+ }
+
+ class BindingContextConverter
+ : IValueConverter
+ {
+ public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return new MockViewModel { Text = value + "Converted" };
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ [Test]
+ //https://bugzilla.xamarin.com/show_bug.cgi?id=24485
+ public void BindingContextBoundThroughConverter()
+ {
+ var bindable = new MockBindable();
+ bindable.BindingContext = "test";
+ bindable.SetBinding (BindableObject.BindingContextProperty, new Binding (".", converter: new BindingContextConverter()));
+ bindable.SetBinding (MockBindable.TextProperty, "Text");
+
+ Assert.That (() => bindable.Text, Is.EqualTo ("testConverted"));
+ }
+
+ public class VMLocator
+ {
+ public event EventHandler Invoked;
+ public int Count;
+ public object VM {
+ get {
+ Count++;
+ var eh = Invoked;
+ if (eh != null)
+ eh (this, EventArgs.Empty);
+ return new object ();
+ }
+ }
+ }
+
+ [Test]
+ //https://bugzilla.xamarin.com/show_bug.cgi?id=27299
+ public void BindingOnBindingContextDoesntReapplyBindingContextBinding ()
+ {
+ var bindable = new MockBindable ();
+ var locator = new VMLocator ();
+ Assert.AreEqual (0, locator.Count);
+ locator.Invoked += (sender, e) => Assert.IsTrue (locator.Count <= 1);
+ bindable.SetBinding (BindableObject.BindingContextProperty, new Binding ("VM", source: locator));
+ Assert.IsTrue (locator.Count == 1);
+ }
+
+ [Test]
+ public void BindingsEditableAfterUnapplied()
+ {
+ var bindable = new MockBindable();
+
+ var binding = new Binding (".");
+ bindable.SetBinding (MockBindable.TextProperty, binding);
+ bindable.BindingContext = "foo";
+
+ Assume.That (bindable.Text, Is.EqualTo (bindable.BindingContext));
+
+ bindable.RemoveBinding (MockBindable.TextProperty);
+
+ Assert.That (() => binding.Path = "foo", Throws.Nothing);
+ }
+
+ [Test]
+ // https://bugzilla.xamarin.com/show_bug.cgi?id=24054
+ public void BindingsAppliedUnappliedWithNullContext()
+ {
+ var bindable = new MockBindable();
+
+ var binding = new Binding (".");
+ bindable.SetBinding (MockBindable.TextProperty, binding);
+ bindable.BindingContext = "foo";
+
+ Assume.That (bindable.Text, Is.EqualTo (bindable.BindingContext));
+
+ bindable.BindingContext = null;
+
+ Assume.That (bindable.Text, Is.EqualTo (bindable.BindingContext));
+
+ bindable.BindingContext = "bar";
+
+ Assume.That (bindable.Text, Is.EqualTo (bindable.BindingContext));
+
+ bindable.RemoveBinding (MockBindable.TextProperty);
+
+ Assert.That (() => binding.Path = "Foo", Throws.Nothing);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/BindablePropertyUnitTests.cs b/Xamarin.Forms.Core.UnitTests/BindablePropertyUnitTests.cs
new file mode 100644
index 00000000..1d006a6d
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/BindablePropertyUnitTests.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Linq;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class BindablePropertyUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void Create()
+ {
+ const BindingMode mode = BindingMode.OneWayToSource;
+ const string dvalue = "default";
+ BindableProperty.CoerceValueDelegate<string> coerce = (bindable, value) => value;
+ BindableProperty.ValidateValueDelegate<string> validate = (b, v) => true;
+ BindableProperty.BindingPropertyChangedDelegate<string> changed = (b, ov, nv) => { };
+ BindableProperty.BindingPropertyChangingDelegate<string> changing = (b, ov, nv) => { };
+
+ var prop = BindableProperty.Create<Button, string> (b => b.Text, dvalue, mode, validate, changed, changing, coerce);
+ Assert.AreEqual ("Text", prop.PropertyName);
+ Assert.AreEqual (typeof (Button), prop.DeclaringType);
+ Assert.AreEqual (typeof (string), prop.ReturnType);
+ Assert.AreEqual (dvalue, prop.DefaultValue);
+ Assert.AreEqual (mode, prop.DefaultBindingMode);
+ }
+
+ [Test]
+ public void CreateWithDefaultMode ()
+ {
+ const BindingMode mode = BindingMode.Default;
+ var prop = BindableProperty.Create<Button, string> (b => b.Text, null, defaultBindingMode: mode);
+ Assert.AreEqual (BindingMode.OneWay, prop.DefaultBindingMode);
+ }
+
+ [Test]
+ public void CreateCasted()
+ {
+ var prop = BindableProperty.Create<Cell, bool> (c => c.IsEnabled, true);
+
+ Assert.AreEqual ("IsEnabled", prop.PropertyName);
+ Assert.AreEqual (typeof (Cell), prop.DeclaringType);
+ Assert.AreEqual (typeof (bool), prop.ReturnType);
+ }
+
+ [Test]
+ public void CreateNonGeneric()
+ {
+ const BindingMode mode = BindingMode.OneWayToSource;
+ const string dvalue = "default";
+ BindableProperty.CoerceValueDelegate coerce = (bindable, value) => value;
+ BindableProperty.ValidateValueDelegate validate = (b, v) => true;
+ BindableProperty.BindingPropertyChangedDelegate changed = (b, ov, nv) => { };
+ BindableProperty.BindingPropertyChangingDelegate changing = (b, ov, nv) => { };
+
+ var prop = BindableProperty.Create ("Text", typeof(string), typeof(Button), dvalue, mode, validate, changed, changing, coerce);
+ Assert.AreEqual ("Text", prop.PropertyName);
+ Assert.AreEqual (typeof (Button), prop.DeclaringType);
+ Assert.AreEqual (typeof (string), prop.ReturnType);
+ Assert.AreEqual (dvalue, prop.DefaultValue);
+ Assert.AreEqual (mode, prop.DefaultBindingMode);
+ }
+
+ class GenericView<T> : View
+ {
+ public string Text
+ {
+ get;
+ set;
+ }
+ }
+
+ [Test]
+ public void CreateForGeneric()
+ {
+ const BindingMode mode = BindingMode.OneWayToSource;
+ const string dvalue = "default";
+ BindableProperty.CoerceValueDelegate coerce = (bindable, value) => value;
+ BindableProperty.ValidateValueDelegate validate = (b, v) => true;
+ BindableProperty.BindingPropertyChangedDelegate changed = (b, ov, nv) => { };
+ BindableProperty.BindingPropertyChangingDelegate changing = (b, ov, nv) => { };
+
+ var prop = BindableProperty.Create ("Text", typeof(string), typeof(GenericView<>), dvalue, mode, validate, changed, changing, coerce);
+ Assert.AreEqual ("Text", prop.PropertyName);
+ Assert.AreEqual (typeof (GenericView<>), prop.DeclaringType);
+ Assert.AreEqual (typeof (string), prop.ReturnType);
+ Assert.AreEqual (dvalue, prop.DefaultValue);
+ Assert.AreEqual (mode, prop.DefaultBindingMode);
+ }
+
+ [Test]
+ public void ChangingBeforeChanged ()
+ {
+ bool changingfired = false;
+ bool changedfired = false;
+ BindableProperty.BindingPropertyChangedDelegate<string> changed = (b, ov, nv) => {
+ Assert.True (changingfired);
+ changedfired = true;
+ };
+ BindableProperty.BindingPropertyChangingDelegate<string> changing = (b, ov, nv) => {
+ Assert.False (changedfired);
+ changingfired = true;
+ };
+
+ var prop = BindableProperty.Create<Button, string> (b => b.Text, "Foo",
+ propertyChanging: changing,
+ propertyChanged: changed);
+
+ Assert.False (changingfired);
+ Assert.False (changedfired);
+
+ (new View ()).SetValue (prop, "Bar");
+
+ Assert.True (changingfired);
+ Assert.True (changedfired);
+ }
+
+ [Test]
+ public void NullableProperty ()
+ {
+ var prop = BindableProperty.Create ("foo", typeof(DateTime?), typeof(MockBindable), null);
+ Assert.AreEqual (typeof(DateTime?), prop.ReturnType);
+
+ var bindable = new MockBindable ();
+ Assert.AreEqual (null, bindable.GetValue (prop));
+
+ var now = DateTime.Now;
+ bindable.SetValue (prop, now);
+ Assert.AreEqual (now, bindable.GetValue (prop));
+
+ bindable.SetValue (prop, null);
+ Assert.AreEqual (null, bindable.GetValue (prop));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/BindingBaseUnitTests.cs b/Xamarin.Forms.Core.UnitTests/BindingBaseUnitTests.cs
new file mode 100644
index 00000000..dd0d2244
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/BindingBaseUnitTests.cs
@@ -0,0 +1,227 @@
+using System;
+using System.Linq;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ public abstract class BindingBaseUnitTests : BaseTestFixture
+ {
+ protected abstract BindingBase CreateBinding (BindingMode mode, string stringFormat = null);
+
+ [Test]
+ public void CloneMode()
+ {
+ var binding = CreateBinding (BindingMode.Default);
+ var clone = binding.Clone();
+
+ Assert.AreEqual (binding.Mode, clone.Mode);
+ }
+
+ [Test]
+ public void StringFormat()
+ {
+ var property = BindableProperty.Create<MockBindable, string> (w => w.Foo, null);
+
+ var binding = CreateBinding (BindingMode.Default, "Foo {0}");
+
+ var vm = new MockViewModel { Text = "Bar" };
+ var bo = new MockBindable { BindingContext = vm };
+ bo.SetBinding (property, binding);
+
+ Assert.That (bo.GetValue (property), Is.EqualTo ("Foo Bar"));
+ }
+
+ [Test]
+ public void StringFormatOnUpdate()
+ {
+ var property = BindableProperty.Create<MockBindable, string> (w => w.Foo, null);
+
+ var binding = CreateBinding (BindingMode.Default, "Foo {0}");
+
+ var vm = new MockViewModel { Text = "Bar" };
+ var bo = new MockBindable { BindingContext = vm };
+ bo.SetBinding (property, binding);
+
+ vm.Text = "Baz";
+
+ Assert.That (bo.GetValue (property), Is.EqualTo ("Foo Baz"));
+ }
+
+ [Test]
+ [Description ("StringFormat should not be applied to OneWayToSource bindings")]
+ public void StringFormatOneWayToSource()
+ {
+ var property = BindableProperty.Create<MockBindable, string> (w => w.Foo, null);
+
+ var binding = CreateBinding (BindingMode.OneWayToSource, "Foo {0}");
+
+ var vm = new MockViewModel { Text = "Bar" };
+ var bo = new MockBindable { BindingContext = vm };
+ bo.SetBinding (property, binding);
+
+ bo.SetValue (property, "Bar");
+
+ Assert.That (vm.Text, Is.EqualTo ("Bar"));
+ }
+
+ [Test]
+ [Description ("StringFormat should only be applied from from source in TwoWay bindings")]
+ public void StringFormatTwoWay()
+ {
+ var property = BindableProperty.Create<MockBindable, string> (w => w.Foo, null);
+
+ var binding = CreateBinding (BindingMode.TwoWay, "Foo {0}");
+
+ var vm = new MockViewModel { Text = "Bar" };
+ var bo = new MockBindable { BindingContext = vm };
+ bo.SetBinding (property, binding);
+
+ bo.SetValue (property, "Baz");
+
+ Assert.That (vm.Text, Is.EqualTo ("Baz"));
+ Assert.That (bo.GetValue (property), Is.EqualTo ("Foo Baz"));
+ }
+
+ [Test]
+ [Description ("You should get an exception when trying to change a binding after it's been applied")]
+ public void ChangeAfterApply()
+ {
+ var property = BindableProperty.Create<MockBindable, string> (w => w.Foo, null);
+
+ var binding = CreateBinding (BindingMode.OneWay);
+
+ var vm = new MockViewModel { Text = "Bar" };
+ var bo = new MockBindable { BindingContext = vm };
+ bo.SetBinding (property, binding);
+
+ Assert.That (() => binding.Mode = BindingMode.OneWayToSource, Throws.InvalidOperationException);
+ Assert.That (() => binding.StringFormat = "{0}", Throws.InvalidOperationException);
+ }
+ }
+
+ [TestFixture]
+ public class BindingBaseTests : BaseTestFixture
+ {
+ [Test]
+ public void EnableCollectionSynchronizationInvalid()
+ {
+ Assert.That (() => BindingBase.EnableCollectionSynchronization (null, new object(),
+ (collection, context, method, access) => { }), Throws.InstanceOf<ArgumentNullException>());
+ Assert.That (() => BindingBase.EnableCollectionSynchronization (new string[0], new object(),
+ null), Throws.InstanceOf<ArgumentNullException>());
+ Assert.That (() => BindingBase.EnableCollectionSynchronization (new string[0], null,
+ (collection, context, method, access) => { }), Throws.Nothing);
+ }
+
+ [Test]
+ public void EnableCollectionSynchronization()
+ {
+ string[] stuff = new[] {"foo", "bar"};
+ object context = new object();
+ CollectionSynchronizationCallback callback = (collection, o, method, access) => { };
+
+ BindingBase.EnableCollectionSynchronization (stuff, context, callback);
+
+ CollectionSynchronizationContext syncContext;
+ Assert.IsTrue (BindingBase.TryGetSynchronizedCollection (stuff, out syncContext));
+ Assert.That (syncContext, Is.Not.Null);
+ Assert.AreSame (syncContext.Callback, callback);
+ Assert.That (syncContext.ContextReference, Is.Not.Null);
+ Assert.That (syncContext.ContextReference.Target, Is.SameAs (context));
+ }
+
+ [Test]
+ public void DisableCollectionSynchronization()
+ {
+ string[] stuff = new[] {"foo", "bar"};
+ object context = new object();
+ CollectionSynchronizationCallback callback = (collection, o, method, access) => { };
+
+ BindingBase.EnableCollectionSynchronization (stuff, context, callback);
+
+ BindingBase.DisableCollectionSynchronization (stuff);
+
+ CollectionSynchronizationContext syncContext;
+ Assert.IsFalse (BindingBase.TryGetSynchronizedCollection (stuff, out syncContext));
+ Assert.IsNull (syncContext);
+ }
+
+ [Test]
+ public void CollectionAndContextAreHeldWeakly()
+ {
+ WeakReference weakCollection = null, weakContext = null;
+
+ int i = 0;
+ Action create = null;
+ create = () => {
+ if (i++ < 1024) {
+ create();
+ return;
+ }
+
+ string[] collection = new[] {"foo", "bar"};
+ weakCollection = new WeakReference (collection);
+
+ object context = new object();
+ weakContext = new WeakReference (context);
+
+ BindingBase.EnableCollectionSynchronization (collection, context, (enumerable, o, method, access) => { });
+ };
+
+ create();
+
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+
+ Assert.IsFalse (weakCollection.IsAlive);
+ Assert.IsFalse (weakContext.IsAlive);
+ }
+
+ [Test]
+ public void CollectionAndContextAreHeldWeaklyClosingOverCollection()
+ {
+ WeakReference weakCollection = null, weakContext = null;
+
+ int i = 0;
+ Action create = null;
+ create = () => {
+ if (i++ < 1024) {
+ create();
+ return;
+ }
+
+ string[] collection = new[] {"foo", "bar"};
+ weakCollection = new WeakReference (collection);
+
+ object context = new object();
+ weakContext = new WeakReference (context);
+
+ BindingBase.EnableCollectionSynchronization (collection, context, (enumerable, o, method, access) => {
+ collection[0] = "baz";
+ });
+ };
+
+ create();
+
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+
+ Assert.IsFalse (weakCollection.IsAlive);
+ Assert.IsFalse (weakContext.IsAlive);
+ }
+
+ [Test]
+ public void DisableCollectionSynchronizationInvalid()
+ {
+ Assert.That (() => BindingBase.DisableCollectionSynchronization (null), Throws.InstanceOf<ArgumentNullException>());
+ }
+
+ [Test]
+ public void TryGetSynchronizedCollectionInvalid()
+ {
+ CollectionSynchronizationContext context;
+ Assert.That (() => BindingBase.TryGetSynchronizedCollection (null, out context),
+ Throws.InstanceOf<ArgumentNullException>());
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/BindingExpressionTests.cs b/Xamarin.Forms.Core.UnitTests/BindingExpressionTests.cs
new file mode 100644
index 00000000..b3f0198d
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/BindingExpressionTests.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class BindingExpressionTests : BaseTestFixture
+ {
+ [Test]
+ public void Ctor()
+ {
+ string path = "Foo.Bar";
+ var binding = new Binding (path);
+
+ var be = new BindingExpression (binding, path);
+
+ Assert.AreSame (binding, be.Binding);
+ Assert.AreEqual (path, be.Path);
+ }
+
+ [Test]
+ public void CtorInvalid()
+ {
+ string path = "Foo.Bar";
+ var binding = new Binding (path);
+
+ Assert.Throws<ArgumentNullException> (() => new BindingExpression (binding, null),
+ "Allowed the path to eb null");
+
+ Assert.Throws<ArgumentNullException> (() => new BindingExpression (null, path),
+ "Allowed the binding to be null");
+ }
+
+ [Test]
+ public void ApplyNull()
+ {
+ const string path = "Foo.Bar";
+ var binding = new Binding (path);
+ var be = new BindingExpression (binding, path);
+ Assert.DoesNotThrow (() => be.Apply (null, new MockBindable(), TextCell.TextProperty));
+ }
+
+ // We only throw on invalid path features, if they give an invalid property
+ // name, it won't have compiled in the first place or they misstyped.
+ [TestCase ("Foo.")]
+ [TestCase ("Foo[]")]
+ [TestCase ("Foo.Bar[]")]
+ [TestCase ("Foo[1")]
+ public void InvalidPaths (string path)
+ {
+ var fex = Assert.Throws<FormatException> (() => {
+ var binding = new Binding (path);
+ new BindingExpression (binding, path);
+ });
+
+ Assert.IsFalse (String.IsNullOrWhiteSpace (fex.Message),
+ "FormatException did not contain an explanation");
+ }
+
+ [Test]
+ public void ValidPaths (
+ [Values (
+ ".", "[1]", "[1 ]", ".[1]", ". [1]",
+ "Foo", "Foo.Bar", "Foo. Bar", "Foo.Bar[1]",
+ "Foo.Bar [1]")]
+ string path,
+ [Values (true, false)] bool spaceBefore,
+ [Values (true, false)] bool spaceAfter)
+ {
+ if (spaceBefore)
+ path = " " + path;
+ if (spaceAfter)
+ path = path + " ";
+
+ var binding = new Binding (path);
+ Assert.DoesNotThrow (() => new BindingExpression (binding, path));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/BindingTests.cs b/Xamarin.Forms.Core.UnitTests/BindingTests.cs
new file mode 100644
index 00000000..d586a6dd
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/BindingTests.cs
@@ -0,0 +1,75 @@
+using NUnit.Framework;
+using System.Collections.Generic;
+using System;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ internal class BindingSystemTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ class BindableViewCell : ViewCell
+ {
+ public static readonly BindableProperty NameProperty =
+ BindableProperty.Create<BindableViewCell, string> (w => w.Name, "");
+
+ public Label NameLabel { get; set; }
+
+ public string Name
+ {
+ get { return (string) GetValue (NameProperty); }
+ set { SetValue (NameProperty, value); }
+ }
+
+ public BindableViewCell ()
+ {
+ NameLabel = new Label {BindingContext = this};
+ NameLabel.SetBinding (Label.TextProperty, new Binding ("Name"));
+ View = NameLabel;
+ }
+ }
+
+ [Test]
+ public void RecursiveSettingInSystem ()
+ {
+ var tempObjects = new[] {
+ new {Name = "Test1"},
+ new {Name = "Test2"}
+ };
+
+ var template = new DataTemplate (typeof (BindableViewCell)) {
+ Bindings = { {BindableViewCell.NameProperty, new Binding ("Name")} }
+ };
+
+ var cell1 = (Cell)template.CreateContent ();
+ cell1.BindingContext = tempObjects[0];
+ cell1.Parent = new ListView ();
+
+ var cell2 = (Cell)template.CreateContent ();
+ cell2.BindingContext = tempObjects[1];
+ cell2.Parent = new ListView ();
+
+ var viewCell1 = (BindableViewCell) cell1;
+ var viewCell2 = (BindableViewCell) cell2;
+
+ Assert.AreEqual ("Test1", viewCell1.Name);
+ Assert.AreEqual ("Test2", viewCell2.Name);
+
+ Assert.AreEqual ("Test1", viewCell1.NameLabel.Text);
+ Assert.AreEqual ("Test2", viewCell2.NameLabel.Text);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/BindingTypeConverterTests.cs b/Xamarin.Forms.Core.UnitTests/BindingTypeConverterTests.cs
new file mode 100644
index 00000000..e6d97d24
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/BindingTypeConverterTests.cs
@@ -0,0 +1,27 @@
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class BindingTypeConverterTests : BaseTestFixture
+ {
+ [Test]
+ public void CanConvertFrom()
+ {
+ var c = new BindingTypeConverter();
+ Assert.That (c.CanConvertFrom (typeof (string)), Is.True);
+ Assert.That (c.CanConvertFrom (typeof (int)), Is.False);
+ }
+
+ [Test]
+ public void Convert()
+ {
+ var c = new BindingTypeConverter();
+ var binding = c.ConvertFromInvariantString ("Path");
+
+ Assert.That (binding, Is.InstanceOf<Binding>());
+ Assert.That (((Binding) binding).Path, Is.EqualTo ("Path"));
+ Assert.That (((Binding) binding).Mode, Is.EqualTo (BindingMode.Default));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/BindingUnitTests.cs b/Xamarin.Forms.Core.UnitTests/BindingUnitTests.cs
new file mode 100644
index 00000000..c520e929
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/BindingUnitTests.cs
@@ -0,0 +1,2649 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using NUnit.Framework;
+using CategoryAttribute=NUnit.Framework.CategoryAttribute;
+using DescriptionAttribute=NUnit.Framework.DescriptionAttribute;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class BindingUnitTests
+ : BindingBaseUnitTests
+ {
+ class Logger
+ : LogListener
+ {
+ public IReadOnlyList<string> Messages
+ {
+ get { return messages; }
+ }
+
+ public override void Warning (string category, string message)
+ {
+ messages.Add ("[" + category + "] " + message);
+ }
+
+ readonly List<string> messages = new List<string>();
+ }
+
+ Logger log;
+
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ log = new Logger();
+
+ Device.PlatformServices = new MockPlatformServices ();
+ Log.Listeners.Add (log);
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ Log.Listeners.Remove (log);
+ }
+
+ protected override BindingBase CreateBinding (BindingMode mode, string stringFormat = null)
+ {
+ return new Binding ("Text", mode, stringFormat: stringFormat);
+ }
+
+ [Test]
+ public void Ctor()
+ {
+ const string path = "Foo";
+
+ var binding = new Binding (path, BindingMode.OneWayToSource);
+ Assert.AreEqual (path, binding.Path);
+ Assert.AreEqual (BindingMode.OneWayToSource, binding.Mode);
+ }
+
+ [Test]
+ public void InvalidCtor()
+ {
+ Assert.Throws<ArgumentNullException> (() => new Binding (null),
+ "Allowed null Path");
+
+ Assert.Throws<ArgumentException> (() => new Binding (String.Empty),
+ "Allowed empty path");
+
+ Assert.Throws<ArgumentException> (() => new Binding (" "),
+ "Allowed whitespace path");
+
+ Assert.Throws<ArgumentException> (() => new Binding ("Path", (BindingMode)Int32.MaxValue),
+ "Allowed invalid value for BindingMode");
+ }
+
+ [Test]
+ [Description ("You should get an exception when trying to change a binding after it's been applied")]
+ public void ChangeBindingAfterApply()
+ {
+ var property = BindableProperty.Create<MockBindable, string> (w => w.Foo, null);
+
+ var binding = new Binding { Path = "Text" };
+
+ var vm = new MockViewModel { Text = "Bar" };
+ var bo = new MockBindable { BindingContext = vm };
+ bo.SetBinding (property, binding);
+
+ Assert.That (() => binding.Path = "path", Throws.InvalidOperationException);
+ Assert.That (() => binding.Converter = null, Throws.InvalidOperationException);
+ Assert.That (() => binding.ConverterParameter = new object(), Throws.InvalidOperationException);
+ }
+
+ [Test]
+ public void NullPathIsSelf()
+ {
+ var property = BindableProperty.Create<MockBindable, string> (w => w.Foo, null);
+
+ var binding = new Binding();
+
+ var bo = new MockBindable { BindingContext = "Foo" };
+ bo.SetBinding (property, binding);
+
+ Assert.That (bo.GetValue (property), Is.EqualTo ("Foo"));
+ }
+
+ class DoubleViewModel
+ : MockViewModel
+ {
+ public double Value
+ {
+ get;
+ set;
+ }
+ }
+
+ [Test]
+ public void StringFormatNonStringType()
+ {
+ var property = BindableProperty.Create<MockBindable, string> (w => w.Foo, null);
+
+ var binding = new Binding ("Value", stringFormat: "{0:P2}");
+
+ var vm = new DoubleViewModel { Value = 0.95 };
+ var bo = new MockBindable { BindingContext = vm };
+ bo.SetBinding (property, binding);
+
+ if (System.Threading.Thread.CurrentThread.CurrentCulture.Name == "tr-TR")
+ Assert.That (bo.GetValue (property), Is.EqualTo ("%95,00"));
+ else
+ Assert.That (bo.GetValue (property), Is.EqualTo ("95.00 %"));
+ }
+
+ [Test]
+ public void ReuseBindingInstance()
+ {
+ var vm = new MockViewModel();
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = vm;
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, null);
+ var binding = new Binding ("Text");
+ bindable.SetBinding (property, binding);
+
+ var bindable2 = new MockBindable();
+ bindable2.BindingContext = new MockViewModel();
+ Assert.Throws<InvalidOperationException> (() => bindable2.SetBinding (property, binding),
+ "Binding allowed reapplication with a different context");
+ }
+
+ class ComplexPropertyNamesViewModel
+ : MockViewModel
+ {
+ public string Foo_Bar
+ {
+ get;
+ set;
+ }
+
+ public string @if
+ {
+ get;
+ set;
+ }
+
+ /*public string P̀ः०‿
+ {
+ get;
+ set;
+ }*/
+
+ public string _UnderscoreStart
+ {
+ get;
+ set;
+ }
+ }
+
+ [Category ("[Binding] Complex paths")]
+ [TestCase ("Foo_Bar")]
+ [TestCase ("if")]
+ //TODO FIXME [TestCase ("P̀ः०‿")]
+ [TestCase ("_UnderscoreStart")]
+ public void ComplexPropertyNames (string propertyName)
+ {
+ var vm = new ComplexPropertyNamesViewModel();
+ vm.GetType().GetProperty (propertyName).SetValue (vm, "Value");
+
+ var binding = new Binding (propertyName);
+
+ var bindable = new MockBindable { BindingContext = vm };
+ bindable.SetBinding (MockBindable.TextProperty, binding);
+
+ Assert.That (bindable.Text, Is.EqualTo ("Value"));
+ }
+
+ [Test, Category ("[Binding] Simple paths")]
+ public void ValueSetOnOneWayWithSimplePathBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ const string value = "Foo";
+ var viewmodel = new MockViewModel {
+ Text = value
+ };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, null, propertyDefault);
+
+ var binding = new Binding ("Text", bindingMode);
+
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = viewmodel;
+ }
+
+ Assert.AreEqual (value, viewmodel.Text,
+ "BindingContext property changed");
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Simple paths")]
+ public void ValueSetOnOneWayToSourceWithSimplePathBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ const string value = "Foo";
+ var viewmodel = new MockViewModel();
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWayToSource;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWayToSource;
+ bindingMode = BindingMode.Default;
+ }
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text,
+ defaultValue: value, defaultBindingMode: propertyDefault);
+
+ var binding = new Binding ("Text", bindingMode);
+
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = viewmodel;
+ }
+
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property changed");
+ Assert.AreEqual (value, viewmodel.Text,
+ "BindingContext property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Simple paths")]
+ public void ValueSetOnTwoWayWithSimplePathBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ const string value = "Foo";
+ var viewmodel = new MockViewModel {
+ Text = value
+ };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.TwoWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.TwoWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var binding = new Binding ("Text", bindingMode);
+
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = viewmodel;
+ }
+
+ Assert.AreEqual (value, viewmodel.Text,
+ "BindingContext property changed");
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test]
+ [Category ("[Binding] Complex paths")]
+ public void ValueSetOnOneWayWithComplexPathBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ const string value = "Foo";
+ var viewmodel = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Text = value
+ }
+ }
+ };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, null, propertyDefault);
+
+ var binding = new Binding ("Model.Model.Text", bindingMode);
+
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = viewmodel;
+ }
+
+ Assert.AreEqual (value, viewmodel.Model.Model.Text,
+ "BindingContext property changed");
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Complex paths")]
+ public void ValueSetOnOneWayToSourceWithComplexPathBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ const string value = "Foo";
+ var viewmodel = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ }
+ }
+ };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWayToSource;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWayToSource;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text,
+ defaultValue: value, defaultBindingMode: propertyDefault);
+
+ var binding = new Binding ("Model.Model.Text", bindingMode);
+
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = viewmodel;
+ }
+
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property changed");
+ Assert.AreEqual (value, viewmodel.Model.Model.Text,
+ "BindingContext property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Complex paths")]
+ public void ValueSetOnTwoWayWithComplexPathBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ const string value = "Foo";
+ var viewmodel = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Text = value
+ }
+ }
+ };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.TwoWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.TwoWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var binding = new Binding ("Model.Model.Text", bindingMode);
+
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = viewmodel;
+ }
+
+ Assert.AreEqual (value, viewmodel.Model.Model.Text,
+ "BindingContext property changed");
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ class Outer {
+ public Outer (Inner inner)
+ {
+ PropertyWithPublicSetter = inner;
+ PropertyWithPrivateSetter = inner;
+ }
+
+ public Inner PropertyWithPublicSetter { get; set; }
+ public Inner PropertyWithPrivateSetter { get; private set; }
+ }
+
+ class Inner {
+ public Inner (string property)
+ {
+ GetSetProperty = property;
+ }
+
+ public string GetSetProperty { get; set; }
+ }
+
+ [Test, Category ("[Binding] Complex paths")]
+ public void BindingWithNoPublicSetterOnParent (
+ [Values (true, false)] bool setContextFirst,
+ [Values (BindingMode.OneWay, BindingMode.TwoWay)] BindingMode bindingmode,
+ [Values (true, false)] bool usePrivateSetter)
+ {
+ var value = "FooBar";
+ var property = BindableProperty.Create<MockBindable, string> (w => w.Text, "default value", BindingMode.Default);
+ var binding = new Binding (usePrivateSetter? "PropertyWithPrivateSetter.GetSetProperty": "PropertyWithPublicSetter.GetSetProperty", bindingmode);
+ var viewmodel = new Outer (new Inner (value));
+ var bindable = new MockBindable ();
+
+ if (setContextFirst) {
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = viewmodel;
+ }
+
+ Assert.AreEqual (value, viewmodel.PropertyWithPublicSetter.GetSetProperty);
+ Assert.AreEqual (value, bindable.GetValue (property));
+
+ if (bindingmode == BindingMode.TwoWay) {
+ var updatedValue = "Qux";
+ bindable.SetValue (property, updatedValue);
+ Assert.AreEqual (updatedValue, bindable.GetValue (property));
+ Assert.AreEqual (updatedValue, viewmodel.PropertyWithPublicSetter.GetSetProperty);
+ }
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Indexed paths")]
+ public void ValueSetOnOneWayWithIndexedPathBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ const string value = "Foo";
+ var viewmodel = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel()
+ }
+ };
+ viewmodel.Model.Model[1] = value;
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, null, propertyDefault);
+
+ var binding = new Binding ("Model.Model[1]", bindingMode);
+
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = viewmodel;
+ }
+
+ Assert.AreEqual (value, viewmodel.Model.Model[1],
+ "BindingContext property changed");
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Indexed paths")]
+ public void ValueSetOnOneWayWithSelfIndexedPathBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ const string value = "Foo";
+ var viewmodel = new ComplexMockViewModel();
+ viewmodel[1] = value;
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, null, propertyDefault);
+
+ var binding = new Binding (".[1]", bindingMode);
+
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = viewmodel;
+ }
+
+ Assert.AreEqual (value, viewmodel[1],
+ "BindingContext property changed");
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Indexed paths")]
+ public void ValueSetOnOneWayWithIndexedPathArrayBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ const string value = "Bar";
+ var viewmodel = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Array = new [] { "Foo", "Bar" }
+ }
+ };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, null, propertyDefault);
+
+ var binding = new Binding ("Model.Array[1]", bindingMode);
+
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = viewmodel;
+ }
+
+ Assert.AreEqual (value, viewmodel.Model.Array[1],
+ "BindingContext property changed");
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Indexed paths")]
+ public void ValueSetOnOneWayWithIndexedSelfPathArrayBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ const string value = "bar";
+ string[] context = new[] { "foo", value };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, null, propertyDefault);
+
+ var binding = new Binding (".[1]", bindingMode);
+
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = context;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = context;
+ }
+
+ Assert.AreEqual (value, context[1],
+ "BindingContext property changed");
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Indexed paths")]
+ public void ValueSetOnOneWayToSourceWithIndexedPathBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ const string value = "Foo";
+ var viewmodel = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel()
+ }
+ };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWayToSource;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWayToSource;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, defaultValue: value, defaultBindingMode: propertyDefault);
+
+ var binding = new Binding ("Model.Model[1]", bindingMode);
+
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = viewmodel;
+ }
+
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property changed");
+ Assert.AreEqual (value, viewmodel.Model.Model[1],
+ "BindingContext property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Indexed paths")]
+ public void ValueSetOnTwoWayWithIndexedPathBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ const string value = "Foo";
+ var viewmodel = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel()
+ }
+ };
+ viewmodel.Model.Model[1] = value;
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.TwoWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.TwoWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var binding = new Binding ("Model.Model[1]", bindingMode);
+
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = viewmodel;
+ }
+
+ Assert.AreEqual (value, viewmodel.Model.Model[1],
+ "BindingContext property changed");
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Indexed paths")]
+ public void ValueSetOnTwoWayWithIndexedArrayPathBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ const string value = "Foo";
+ var viewmodel = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Array = new string[2]
+ }
+ };
+ viewmodel.Model.Array[1] = value;
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.TwoWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.TwoWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var binding = new Binding ("Model.Array[1]", bindingMode);
+
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = viewmodel;
+ }
+
+ Assert.AreEqual (value, viewmodel.Model.Array[1],
+ "BindingContext property changed");
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Indexed paths")]
+ public void ValueSetOnTwoWayWithIndexedArraySelfPathBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ const string value = "Foo";
+ string[] viewmodel = new [] { "bar", value };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.TwoWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.TwoWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var binding = new Binding (".[1]", bindingMode);
+
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = viewmodel;
+ }
+
+ Assert.AreEqual (value, viewmodel[1],
+ "BindingContext property changed");
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Self paths")]
+ public void ValueSetOnOneWayWithSelfPathBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, null, propertyDefault);
+
+ var binding = new Binding (".", bindingMode);
+
+ const string value = "value";
+
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = value;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = value;
+ }
+
+ Assert.AreEqual (value, bindable.BindingContext,
+ "BindingContext property changed");
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Self paths")]
+ public void ValueNotSetOnOneWayToSourceWithSelfPathBinding (
+ [Values (true, false)] bool isDefault)
+ {
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWayToSource;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWayToSource;
+ bindingMode = BindingMode.Default;
+ }
+
+ const string value = "Foo";
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, defaultValue: value, defaultBindingMode: propertyDefault);
+
+ var binding = new Binding (".", bindingMode);
+
+ var bindable = new MockBindable();
+ Assert.IsNull (bindable.BindingContext);
+
+ bindable.SetBinding (property, binding);
+
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property changed");
+ Assert.IsNull (bindable.BindingContext,
+ "BindingContext changed with self-path binding");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Self paths")]
+ public void ValueSetOnTwoWayWithSelfPathBinding (
+ [Values (true, false)] bool setContextFirst,
+ [Values (true, false)] bool isDefault)
+ {
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.TwoWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.TwoWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var binding = new Binding (".", bindingMode);
+
+ const string value = "Foo";
+ var bindable = new MockBindable();
+ if (setContextFirst) {
+ bindable.BindingContext = value;
+ bindable.SetBinding (property, binding);
+ } else {
+ bindable.SetBinding (property, binding);
+ bindable.BindingContext = value;
+ }
+
+ Assert.AreEqual (value, bindable.BindingContext,
+ "BindingContext property changed");
+ Assert.AreEqual (value, bindable.GetValue (property),
+ "Target property did not change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Category ("[Binding] Simple paths")]
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueUpdatedWithSimplePathOnOneWayBinding (bool isDefault)
+ {
+ const string newvalue = "New Value";
+ var viewmodel = new MockViewModel {
+ Text = "Foo"
+ };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, new Binding ("Text", bindingMode));
+
+ viewmodel.Text = newvalue;
+ Assert.AreEqual (newvalue, bindable.GetValue (property),
+ "Bindable did not update on binding context property change");
+ Assert.AreEqual (newvalue, viewmodel.Text,
+ "Source property changed when it shouldn't");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Category ("[Binding] Simple paths")]
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueUpdatedWithSimplePathOnOneWayToSourceBinding (bool isDefault)
+ {
+ const string newvalue = "New Value";
+ var viewmodel = new MockViewModel {
+ Text = "Foo"
+ };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWayToSource;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWayToSource;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, new Binding ("Text", bindingMode));
+
+ string original = (string)bindable.GetValue (property);
+ const string value = "value";
+ viewmodel.Text = value;
+ Assert.AreEqual (original, bindable.GetValue (property),
+ "Target updated from Source on OneWayToSource");
+
+ bindable.SetValue (property, newvalue);
+ Assert.AreEqual (newvalue, bindable.GetValue (property),
+ "Bindable did not update on binding context property change");
+ Assert.AreEqual (newvalue, viewmodel.Text,
+ "Source property changed when it shouldn't");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Category ("[Binding] Simple paths")]
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueUpdatedWithSimplePathOnTwoWayBinding (bool isDefault)
+ {
+ const string newvalue = "New Value";
+ var viewmodel = new MockViewModel {
+ Text = "Foo"
+ };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.TwoWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.TwoWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, new Binding ("Text", bindingMode));
+
+ viewmodel.Text = newvalue;
+ Assert.AreEqual (newvalue, bindable.GetValue (property),
+ "Target property did not update change");
+ Assert.AreEqual (newvalue, viewmodel.Text,
+ "Source property changed from what it was set to");
+
+ const string newvalue2 = "New Value in the other direction";
+
+ bindable.SetValue (property, newvalue2);
+ Assert.AreEqual (newvalue2, viewmodel.Text,
+ "Source property did not update with Target's change");
+ Assert.AreEqual (newvalue2, bindable.GetValue (property),
+ "Target property changed from what it was set to");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Category ("[Binding] Complex paths")]
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueUpdatedWithComplexPathOnOneWayBinding (bool isDefault)
+ {
+ const string newvalue = "New Value";
+ var viewmodel = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Text = "Foo"
+ }
+ }
+ };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, new Binding ("Model.Model.Text", bindingMode));
+
+ viewmodel.Model.Model.Text = newvalue;
+ Assert.AreEqual (newvalue, bindable.GetValue (property),
+ "Bindable did not update on binding context property change");
+ Assert.AreEqual (newvalue, viewmodel.Model.Model.Text,
+ "Source property changed when it shouldn't");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Category ("[Binding] Complex paths")]
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueUpdatedWithComplexPathOnOneWayToSourceBinding (bool isDefault)
+ {
+ const string newvalue = "New Value";
+ var viewmodel = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Text = "Foo"
+ }
+ }
+ };;
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWayToSource;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWayToSource;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, new Binding ("Model.Model.Text", bindingMode));
+
+ string original = (string)bindable.GetValue (property);
+ const string value = "value";
+ viewmodel.Model.Model.Text = value;
+ Assert.AreEqual (original, bindable.GetValue (property),
+ "Target updated from Source on OneWayToSource");
+
+ bindable.SetValue (property, newvalue);
+ Assert.AreEqual (newvalue, bindable.GetValue (property),
+ "Bindable did not update on binding context property change");
+ Assert.AreEqual (newvalue, viewmodel.Model.Model.Text,
+ "Source property changed when it shouldn't");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Category ("[Binding] Complex paths")]
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueUpdatedWithComplexPathOnTwoWayBinding (bool isDefault)
+ {
+ const string newvalue = "New Value";
+ var viewmodel = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Text = "Foo"
+ }
+ }
+ };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.TwoWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.TwoWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, new Binding ("Model.Model.Text", bindingMode));
+
+ viewmodel.Model.Model.Text = newvalue;
+ Assert.AreEqual (newvalue, bindable.GetValue (property),
+ "Target property did not update change");
+ Assert.AreEqual (newvalue, viewmodel.Model.Model.Text,
+ "Source property changed from what it was set to");
+
+ const string newvalue2 = "New Value in the other direction";
+
+ bindable.SetValue (property, newvalue2);
+ Assert.AreEqual (newvalue2, viewmodel.Model.Model.Text,
+ "Source property did not update with Target's change");
+ Assert.AreEqual (newvalue2, bindable.GetValue (property),
+ "Target property changed from what it was set to");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Category ("[Binding] Indexed paths")]
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueUpdatedWithIndexedPathOnOneWayBinding (bool isDefault)
+ {
+ const string newvalue = "New Value";
+ var viewmodel = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel()
+ }
+ };
+ viewmodel.Model.Model[1] = "Foo";
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, new Binding ("Model.Model[1]", bindingMode));
+
+ viewmodel.Model.Model[1] = newvalue;
+ Assert.AreEqual (newvalue, bindable.GetValue (property),
+ "Bindable did not update on binding context property change");
+ Assert.AreEqual (newvalue, viewmodel.Model.Model[1],
+ "Source property changed when it shouldn't");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Category ("[Binding] Indexed paths")]
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueUpdatedWithIndexedPathOnOneWayToSourceBinding (bool isDefault)
+ {
+ const string newvalue = "New Value";
+ var viewmodel = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel()
+ }
+ };
+ viewmodel.Model.Model[1] = "Foo";
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWayToSource;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWayToSource;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, new Binding ("Model.Model[1]", bindingMode));
+
+ string original = (string)bindable.GetValue (property);
+ const string value = "value";
+ viewmodel.Model.Model[1] = value;
+ Assert.AreEqual (original, bindable.GetValue (property),
+ "Target updated from Source on OneWayToSource");
+
+ bindable.SetValue (property, newvalue);
+ Assert.AreEqual (newvalue, bindable.GetValue (property),
+ "Bindable did not update on binding context property change");
+ Assert.AreEqual (newvalue, viewmodel.Model.Model[1],
+ "Source property changed when it shouldn't");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Category ("[Binding] Indexed paths")]
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueUpdatedWithIndexedPathOnTwoWayBinding (bool isDefault)
+ {
+ const string newvalue = "New Value";
+ var viewmodel = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel()
+ }
+ };
+ viewmodel.Model.Model[1] = "Foo";
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.TwoWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.TwoWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, new Binding ("Model.Model[1]", bindingMode));
+
+ viewmodel.Model.Model[1] = newvalue;
+ Assert.AreEqual (newvalue, bindable.GetValue (property),
+ "Target property did not update change");
+ Assert.AreEqual (newvalue, viewmodel.Model.Model[1],
+ "Source property changed from what it was set to");
+
+ const string newvalue2 = "New Value in the other direction";
+
+ bindable.SetValue (property, newvalue2);
+ Assert.AreEqual (newvalue2, viewmodel.Model.Model[1],
+ "Source property did not update with Target's change");
+ Assert.AreEqual (newvalue2, bindable.GetValue (property),
+ "Target property changed from what it was set to");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Category ("[Binding] Indexed paths")]
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueUpdatedWithIndexedArrayPathOnTwoWayBinding (bool isDefault)
+ {
+ var viewmodel = new ComplexMockViewModel {
+ Array = new string[2]
+ };
+ viewmodel.Array[1] = "Foo";
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.TwoWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.TwoWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, new Binding ("Array[1]", bindingMode));
+
+ const string newvalue2 = "New Value in the other direction";
+
+ bindable.SetValue (property, newvalue2);
+ Assert.AreEqual (newvalue2, viewmodel.Array[1],
+ "Source property did not update with Target's change");
+ Assert.AreEqual (newvalue2, bindable.GetValue (property),
+ "Target property changed from what it was set to");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Category ("[Binding] Self paths")]
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueUpdatedWithSelfPathOnOneWayBinding (bool isDefault)
+ {
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ const string value = "foo";
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = value;
+ bindable.SetBinding (property, new Binding (".", bindingMode));
+
+ const string newvalue = "value";
+ bindable.SetValue (property, newvalue);
+ Assert.AreEqual (value, bindable.BindingContext,
+ "Source was updated from Target on OneWay binding");
+
+ bindable.BindingContext = newvalue;
+ Assert.AreEqual (newvalue, bindable.GetValue (property),
+ "Bindable did not update on binding context property change");
+ Assert.AreEqual (newvalue, bindable.BindingContext,
+ "Source property changed when it shouldn't");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Category ("[Binding] Self paths")]
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueDoesNotUpdateWithSelfPathOnOneWayToSourceBinding (bool isDefault)
+ {
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWayToSource;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWayToSource;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var binding = new Binding (".", bindingMode);
+
+ var bindable = new MockBindable();
+ bindable.SetBinding (property, binding);
+
+ const string newvalue = "new value";
+
+ string original = (string)bindable.GetValue (property);
+ bindable.BindingContext = newvalue;
+ Assert.AreEqual (original, bindable.GetValue (property),
+ "Target updated from Source on OneWayToSource with self path");
+
+ const string newvalue2 = "new value 2";
+ bindable.SetValue (property, newvalue2);
+ Assert.AreEqual (newvalue2, bindable.GetValue (property),
+ "Target property changed on OneWayToSource with self path");
+ Assert.AreEqual (newvalue, bindable.BindingContext,
+ "Source property changed on OneWayToSource with self path");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Category ("[Binding] Self paths")]
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueUpdatedWithSelfPathOnTwoWayBinding (bool isDefault)
+ {
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.TwoWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.TwoWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var binding = new Binding (".", bindingMode);
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = "value";
+ bindable.SetBinding (property, binding);
+
+ const string newvalue = "New Value";
+ bindable.BindingContext = newvalue;
+ Assert.AreEqual (newvalue, bindable.GetValue (property),
+ "Target property did not update change");
+ Assert.AreEqual (newvalue, bindable.BindingContext,
+ "Source property changed from what it was set to");
+
+ const string newvalue2 = "New Value in the other direction";
+
+ bindable.SetValue (property, newvalue2);
+ Assert.AreEqual (newvalue, bindable.BindingContext,
+ "Self-path Source changed with Target's change");
+ Assert.AreEqual (newvalue2, bindable.GetValue (property),
+ "Target property changed from what it was set to");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueUpdatedWithOldContextDoesNotUpdateWithOneWayBinding (bool isDefault)
+ {
+ const string newvalue = "New Value";
+ var viewmodel = new MockViewModel {
+ Text = "Foo"
+ };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var binding = new Binding ("Text", bindingMode);
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+
+ bindable.BindingContext = new MockViewModel();
+ Assert.AreEqual (null, bindable.GetValue (property));
+
+ viewmodel.Text = newvalue;
+ Assert.AreEqual (null, bindable.GetValue (property),
+ "Target updated from old Source property change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueUpdatedWithOldContextDoesNotUpdateWithTwoWayBinding (bool isDefault)
+ {
+ const string newvalue = "New Value";
+ var viewmodel = new MockViewModel {
+ Text = "Foo"
+ };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.TwoWay;
+ if (isDefault) {
+ propertyDefault = BindingMode.TwoWay;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var binding = new Binding ("Text", bindingMode);
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+
+ bindable.BindingContext = new MockViewModel();
+ Assert.AreEqual (null, bindable.GetValue (property));
+
+ viewmodel.Text = newvalue;
+ Assert.AreEqual (null, bindable.GetValue (property),
+ "Target updated from old Source property change");
+
+ string original = viewmodel.Text;
+
+ bindable.SetValue (property, newvalue);
+ Assert.AreEqual (original, viewmodel.Text,
+ "Source updated from old Target property change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [TestCase (true)]
+ [TestCase (false)]
+ public void ValueUpdatedWithOldContextDoesNotUpdateWithOneWayToSourceBinding (bool isDefault)
+ {
+ const string newvalue = "New Value";
+ var viewmodel = new MockViewModel {
+ Text = "Foo"
+ };
+
+ BindingMode propertyDefault = BindingMode.OneWay;
+ BindingMode bindingMode = BindingMode.OneWayToSource;
+ if (isDefault) {
+ propertyDefault = BindingMode.OneWayToSource;
+ bindingMode = BindingMode.Default;
+ }
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", propertyDefault);
+
+ var binding = new Binding ("Text", bindingMode);
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+
+ bindable.BindingContext = new MockViewModel();
+ Assert.AreEqual (property.DefaultValue, bindable.GetValue (property));
+
+ viewmodel.Text = newvalue;
+ Assert.AreEqual (property.DefaultValue, bindable.GetValue (property),
+ "Target updated from old Source property change");
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test]
+ public void BindingStaysOnUpdateValueFromBinding()
+ {
+ const string newvalue = "New Value";
+ var viewmodel = new MockViewModel {
+ Text = "Foo"
+ };
+
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, null);
+
+ var binding = new Binding ("Text");
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+
+ viewmodel.Text = newvalue;
+ Assert.AreEqual (newvalue, bindable.GetValue (property));
+
+ const string newValue2 = "new value 2";
+ viewmodel.Text = newValue2;
+ Assert.AreEqual (newValue2, bindable.GetValue (property));
+
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test]
+ public void OneWayToSourceContextSetToNull()
+ {
+ var binding = new Binding ("Text", BindingMode.OneWayToSource);
+
+ MockBindable bindable = new MockBindable {
+ BindingContext = new MockViewModel()
+ };
+ bindable.SetBinding (MockBindable.TextProperty, binding);
+
+ Assert.That (() => bindable.BindingContext = null, Throws.Nothing);
+ }
+
+ [Category ("[Binding] Simple paths")]
+ [TestCase (BindingMode.OneWay)]
+ [TestCase (BindingMode.OneWayToSource)]
+ [TestCase (BindingMode.TwoWay)]
+ public void SourceAndTargetAreWeakWeakSimplePath (BindingMode mode)
+ {
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value", BindingMode.OneWay);
+
+ var binding = new Binding ("Text", mode);
+
+ WeakReference weakViewModel = null, weakBindable = null;
+
+ int i = 0;
+ Action create = null;
+ create = () => {
+ if (i++ < 1024) {
+ create();
+ return;
+ }
+
+ MockBindable bindable = new MockBindable();
+ weakBindable = new WeakReference (bindable);
+
+ MockViewModel viewmodel = new MockViewModel();
+ weakViewModel = new WeakReference (viewmodel);
+
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+
+ Assume.That (() => bindable.BindingContext = null, Throws.Nothing);
+ };
+
+ create();
+
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+
+ if (mode == BindingMode.TwoWay || mode == BindingMode.OneWay)
+ Assert.IsFalse (weakViewModel.IsAlive, "ViewModel wasn't collected");
+
+ if (mode == BindingMode.TwoWay || mode == BindingMode.OneWayToSource)
+ Assert.IsFalse (weakBindable.IsAlive, "Bindable wasn't collected");
+ }
+
+ internal class ComplexMockViewModel
+ : MockViewModel
+ {
+ public ComplexMockViewModel Model
+ {
+ get { return model; }
+ set
+ {
+ if (model == value)
+ return;
+
+ model = value;
+ OnPropertyChanged ("Model");
+ }
+ }
+
+ internal int count;
+ public int QueryCount
+ {
+ get { return count++; }
+ }
+
+ [IndexerName ("Indexer")]
+ public string this [int v]
+ {
+ get { return values[v]; }
+ set
+ {
+ if (values[v] == value)
+ return;
+
+ values[v] = value;
+ OnPropertyChanged ("Indexer[" + v + "]");
+ }
+ }
+
+ public string[] Array
+ {
+ get;
+ set;
+ }
+
+ public object DoStuff()
+ {
+ return null;
+ }
+
+ public object DoStuff (object argument)
+ {
+ return null;
+ }
+
+ string[] values = new string[5];
+ ComplexMockViewModel model;
+ }
+
+ [Category ("[Binding] Complex paths")]
+ [TestCase (BindingMode.OneWay)]
+ [TestCase (BindingMode.OneWayToSource)]
+ [TestCase (BindingMode.TwoWay)]
+ public void SourceAndTargetAreWeakComplexPath (BindingMode mode)
+ {
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "default value");
+
+ var binding = new Binding ("Model.Model[1]");
+
+ WeakReference weakViewModel = null, weakBindable = null;
+
+ HackAroundMonoSucking (0, property, binding, out weakViewModel, out weakBindable);
+
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+
+ if (mode == BindingMode.TwoWay || mode == BindingMode.OneWay)
+ Assert.IsFalse (weakViewModel.IsAlive, "ViewModel wasn't collected");
+
+ if (mode == BindingMode.TwoWay || mode == BindingMode.OneWayToSource)
+ Assert.IsFalse (weakBindable.IsAlive, "Bindable wasn't collected");
+ }
+
+ // Mono doesn't handle the GC properly until the stack frame where the object is created is popped.
+ // This means calling another method and not just using lambda as works in real .NET
+ void HackAroundMonoSucking (int i, BindableProperty property, Binding binding, out WeakReference weakViewModel, out WeakReference weakBindable)
+ {
+ if (i++ < 1024) {
+ HackAroundMonoSucking (i, property, binding, out weakViewModel, out weakBindable);
+ return;
+ }
+
+ MockBindable bindable = new MockBindable();
+
+ weakBindable = new WeakReference (bindable);
+
+ ComplexMockViewModel viewmodel = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel()
+ }
+ };
+
+ weakViewModel = new WeakReference (viewmodel);
+
+ bindable.BindingContext = viewmodel;
+ bindable.SetBinding (property, binding);
+
+ bindable.BindingContext = null;
+ }
+
+ class TestConverter<TSource,TTarget>
+ : IValueConverter
+ {
+ public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ Assert.AreEqual (typeof (TTarget), targetType);
+ return System.Convert.ChangeType (value, targetType, CultureInfo.CurrentUICulture);
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ Assert.AreEqual (typeof (TSource), targetType);
+ return System.Convert.ChangeType (value, targetType, CultureInfo.CurrentUICulture);
+ }
+ }
+
+ [Test]
+ public void ValueConverter()
+ {
+ var converter = new TestConverter<string, int>();
+
+ var vm = new MockViewModel { Text = "1" };
+ var property = BindableProperty.Create<MockBindable, int> (w=>w.TargetInt, 0);
+
+ var bindable = new MockBindable();
+ bindable.SetBinding (property, new Binding ("Text", converter: converter));
+ bindable.BindingContext = vm;
+
+ Assert.AreEqual (1, bindable.GetValue (property));
+
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test]
+ public void ValueConverterBack()
+ {
+ var converter = new TestConverter<string, int>();
+
+ var vm = new MockViewModel();
+ var property = BindableProperty.Create<MockBindable, int> (w=>w.TargetInt, 1, BindingMode.OneWayToSource);
+ var bindable = new MockBindable();
+ bindable.SetBinding (property, new Binding ("Text", converter: converter));
+ bindable.BindingContext = vm;
+
+ Assert.AreEqual ("1", vm.Text);
+
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+
+ class TestConverterParameter : IValueConverter
+ {
+ public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return parameter;
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return parameter;
+ }
+ }
+
+ [Test]
+ public void ValueConverterParameter ()
+ {
+ var converter = new TestConverterParameter ();
+
+ var vm = new MockViewModel ();
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "Bar", BindingMode.OneWayToSource);
+ var bindable = new MockBindable();
+ bindable.SetBinding (property, new Binding ("Text", converter: converter, converterParameter: "Foo"));
+ bindable.BindingContext = vm;
+
+ Assert.AreEqual ("Foo", vm.Text);
+
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ class TestConverterCulture : IValueConverter
+ {
+ public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return culture.ToString ();
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return culture.ToString ();
+ }
+ }
+
+ #if !WINDOWS_PHONE
+ [Test]
+ [SetUICulture ("pt-PT")]
+ public void ValueConverterCulture ()
+ {
+ var converter = new TestConverterCulture ();
+ var vm = new MockViewModel ();
+ var property = BindableProperty.Create<MockBindable, string> (w=>w.Text, "Bar", BindingMode.OneWayToSource);
+ var bindable = new MockBindable();
+ bindable.SetBinding (property, new Binding ("Text", converter: converter));
+ bindable.BindingContext = vm;
+
+ Assert.AreEqual ("pt-PT", vm.Text);
+ }
+ #endif
+
+ [Test]
+ public void SelfBindingConverter()
+ {
+ var converter = new TestConverter<int, string> ();
+
+ var property = BindableProperty.Create<MockBindable, string> (w => w.Text, "0");
+ var bindable = new MockBindable ();
+ bindable.BindingContext = 1;
+ bindable.SetBinding (property, new Binding (Binding.SelfPath, converter:converter));
+ Assert.AreEqual ("1", bindable.GetValue (property));
+
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ internal class MultiplePropertyViewModel
+ : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ int done;
+ public int Done
+ {
+ get { return done; }
+ set
+ {
+ done = value;
+ OnPropertyChanged();
+ OnPropertyChanged ("Progress");
+ }
+ }
+
+ int total = 100;
+ public int Total
+ {
+ get { return total; }
+ set
+ {
+ if (total == value)
+ return;
+
+ total = value;
+ OnPropertyChanged();
+ OnPropertyChanged ("Progress");
+ }
+ }
+
+ public float Progress
+ {
+ get { return (float)done / total; }
+ }
+
+ protected virtual void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+
+ internal class MultiplePropertyBindable
+ : BindableObject
+ {
+ public static readonly BindableProperty ValueProperty =
+ BindableProperty.Create<MultiplePropertyBindable, float> (b => b.Value, 0f);
+
+ public float Value
+ {
+ get { return (float)GetValue (ValueProperty); }
+ set { SetValue (ValueProperty, value); }
+ }
+
+ public static readonly BindableProperty DoneProperty =
+ BindableProperty.Create<MultiplePropertyBindable, int> (b => b.Done, 0);
+
+ public int Done
+ {
+ get { return (int)GetValue (DoneProperty); }
+ set { SetValue (DoneProperty, value); }
+ }
+ }
+
+ [Test]
+ public void MultiplePropertyUpdates()
+ {
+ var mpvm = new MultiplePropertyViewModel();
+
+ var bindable = new MultiplePropertyBindable();
+ bindable.SetBinding (MultiplePropertyBindable.ValueProperty, new Binding ("Progress", BindingMode.OneWay));
+ bindable.SetBinding (MultiplePropertyBindable.DoneProperty, new Binding ("Done", BindingMode.OneWayToSource));
+ bindable.BindingContext = mpvm;
+
+ bindable.Done = 5;
+
+ Assert.AreEqual (5, mpvm.Done);
+ Assert.AreEqual (0.05f, mpvm.Progress);
+ Assert.AreEqual (5, bindable.Done);
+ Assert.AreEqual (0.05f, bindable.Value);
+
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Complex paths")]
+ [Description ("When part of a complex path can not be evaluated during an update, bindables should return to their default value.")]
+ public void NullInPathUsesDefaultValue()
+ {
+ var vm = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel()
+ };
+
+ var property = BindableProperty.Create<MockBindable, string> (w => w.Text, "foo bar");
+
+ var bindable = new MockBindable();
+ bindable.SetBinding (property, new Binding ("Model.Text", BindingMode.OneWay));
+ bindable.BindingContext = vm;
+
+ vm.Model = null;
+
+ Assert.AreEqual (property.DefaultValue, bindable.GetValue (property));
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test, Category ("[Binding] Complex paths")]
+ [Description ("When part of a complex path can not be evaluated during an update, bindables should return to their default value.")]
+ public void NullContextUsesDefaultValue()
+ {
+ var vm = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel {
+ Text = "vm value"
+ }
+ };
+
+ var property = BindableProperty.Create<MockBindable, string> (w => w.Text, "foo bar");
+
+ var bindable = new MockBindable();
+ bindable.SetBinding (property, new Binding ("Model.Text", BindingMode.OneWay));
+ bindable.BindingContext = vm;
+
+ Assume.That (bindable.GetValue (property), Is.EqualTo (vm.Model.Text));
+
+ bindable.BindingContext = null;
+
+ Assert.AreEqual (property.DefaultValue, bindable.GetValue (property));
+ Assert.That (log.Messages.Count, Is.EqualTo (0),
+ "An error was logged: " + log.Messages.FirstOrDefault());
+ }
+
+ [Test]
+ [Description ("OneWay bindings should not double apply on source updates.")]
+ public void OneWayBindingsDontDoubleApplyOnSourceUpdates()
+ {
+ var vm = new ComplexMockViewModel();
+
+ var bindable = new MockBindable();
+ bindable.SetBinding (MultiplePropertyBindable.DoneProperty, new Binding ("QueryCount", BindingMode.OneWay));
+ bindable.BindingContext = vm;
+
+ Assert.AreEqual (1, vm.count);
+
+ bindable.BindingContext = null;
+
+ Assert.AreEqual (1, vm.count, "Source property was queried on an unset");
+
+ bindable.BindingContext = vm;
+
+ Assert.AreEqual (2, vm.count, "Source property was queried multiple times on a reapply");
+ }
+
+ [Test]
+ [Description ("When there are multiple bindings, an update in one should not cause the other to udpate.")]
+ public void BindingsShouldNotTriggerOtherBindings()
+ {
+ var vm = new ComplexMockViewModel();
+
+ var bindable = new MockBindable();
+ bindable.SetBinding (MultiplePropertyBindable.DoneProperty, new Binding ("QueryCount", BindingMode.OneWay));
+ bindable.SetBinding (MockBindable.TextProperty, new Binding ("Text", BindingMode.OneWay));
+ bindable.BindingContext = vm;
+
+ Assert.AreEqual (1, vm.count);
+
+ vm.Text = "update";
+
+ Assert.AreEqual (1, vm.count, "Source property was queried due to a different binding update.");
+ }
+
+ internal class DerivedViewModel
+ : MockViewModel
+ {
+ public override string Text
+ {
+ get { return base.Text + "2"; }
+ set { base.Text = value; }
+ }
+ }
+
+ [Test]
+ [Description ("The most derived version of a property should always be called.")]
+ public void MostDerviedPropertyOnContextSwitchOfSimilarType()
+ {
+ var vm = new MockViewModel { Text = "text" };
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = vm;
+ bindable.SetBinding (MockBindable.TextProperty, new Binding ("Text"));
+
+ Assert.AreEqual (vm.Text, bindable.GetValue (MockBindable.TextProperty));
+
+ bindable.BindingContext = vm = new DerivedViewModel { Text = "text" };
+
+ Assert.AreEqual (vm.Text, bindable.GetValue (MockBindable.TextProperty));
+ }
+
+ internal class EmptyViewModel
+ {
+ }
+
+ internal class DifferentViewModel
+ : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ string text = "foo";
+
+ public string Text
+ {
+ get { return text; }
+ }
+
+ public string Text2
+ {
+ set { text = value; }
+ }
+
+ public string PrivateSetter
+ {
+ get;
+ private set;
+ }
+ }
+
+ [Test]
+ [Description ("Paths should not distinguish types, a context change to a completely different type should work.")]
+ public void DifferentContextTypeAccessedCorrectlyWithSamePath()
+ {
+ var vm = new MockViewModel { Text = "text" };
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = vm;
+ bindable.SetBinding (MockBindable.TextProperty, new Binding ("Text"));
+
+ Assert.AreEqual (vm.Text, bindable.GetValue (MockBindable.TextProperty));
+
+ var dvm = new DifferentViewModel();
+ bindable.BindingContext = dvm;
+
+ Assert.AreEqual (dvm.Text, bindable.GetValue (MockBindable.TextProperty));
+ }
+
+ [Test]
+ public void PropertyChangeBindingsOccurThroughMainThread()
+ {
+ var vm = new MockViewModel { Text = "text" };
+
+ var bindable = new MockBindable();
+ bindable.BindingContext = vm;
+ bindable.SetBinding (MockBindable.TextProperty, new Binding ("Text"));
+
+ bool mainThread = false;
+ Device.PlatformServices = new MockPlatformServices (invokeOnMainThread: a => mainThread = true);
+
+ vm.Text = "updated";
+
+ Assert.IsTrue (mainThread, "Binding did not occur on main thread");
+ Assert.AreNotEqual (vm.Text, bindable.GetValue (MockBindable.TextProperty), "Binding was applied anyway through other means");
+ }
+
+ [Test]
+ public void Clone()
+ {
+ object param = new object();
+ var binding = new Binding (".", converter: new TestConverter<string, int>(), converterParameter: param, stringFormat: "{0}");
+ var clone = (Binding)binding.Clone();
+
+ Assert.AreSame (binding.Converter, clone.Converter);
+ Assert.AreSame (binding.ConverterParameter, clone.ConverterParameter);
+ Assert.AreEqual (binding.Mode, clone.Mode);
+ Assert.AreEqual (binding.Path, clone.Path);
+ Assert.AreEqual (binding.StringFormat, clone.StringFormat);
+ }
+
+ [Test]
+ public void PropertyMissingOneWay()
+ {
+ var bindable = new MockBindable { BindingContext = new MockViewModel() };
+ bindable.Text = "foo";
+
+ Assert.That (() => bindable.SetBinding (MockBindable.TextProperty, new Binding ("Monkeys", BindingMode.OneWay)), Throws.Nothing);
+ Assert.That (log.Messages.Count, Is.EqualTo (1), "An error was not logged");
+ Assert.That (bindable.Text, Is.EqualTo (MockBindable.TextProperty.DefaultValue));
+ }
+
+ [Test]
+ public void PropertyMissingOneWayToSource()
+ {
+ var bindable = new MockBindable { BindingContext = new MockViewModel() };
+ bindable.Text = "foo";
+
+ Assert.That (() => bindable.SetBinding (MockBindable.TextProperty, new Binding ("Monkeys", BindingMode.OneWayToSource)), Throws.Nothing);
+ Assert.That (log.Messages.Count, Is.EqualTo (1), "An error was not logged");
+ Assert.That (bindable.Text, Is.EqualTo (bindable.Text));
+ }
+
+ [Test]
+ public void PropertyMissingTwoWay()
+ {
+ var bindable = new MockBindable { BindingContext = new MockViewModel() };
+ bindable.Text = "foo";
+
+ Assert.That (() => bindable.SetBinding (MockBindable.TextProperty, new Binding ("Monkeys")), Throws.Nothing);
+ // The first error is for the initial binding, the second is for reflecting the update back to the default value
+ Assert.That (log.Messages.Count, Is.EqualTo (2), "An error was not logged");
+ Assert.That (bindable.Text, Is.EqualTo (MockBindable.TextProperty.DefaultValue));
+ }
+
+ [Test]
+ public void GetterMissingTwoWay()
+ {
+ var bindable = new MockBindable { BindingContext = new DifferentViewModel() };
+ bindable.Text = "foo";
+
+ Assert.That (() => bindable.SetBinding (MockBindable.TextProperty, new Binding ("Text2")), Throws.Nothing);
+ Assert.That (bindable.Text, Is.EqualTo (MockBindable.TextProperty.DefaultValue));
+ Assert.That (log.Messages.Count, Is.EqualTo (1), "An error was not logged");
+ Assert.That (log.Messages[0], Is.StringContaining (String.Format (BindingExpression.PropertyNotFoundErrorMessage,
+ "Text2",
+ "Xamarin.Forms.Core.UnitTests.BindingUnitTests+DifferentViewModel",
+ "Xamarin.Forms.Core.UnitTests.MockBindable",
+ "Text")));
+
+ Assert.That (((DifferentViewModel) bindable.BindingContext).Text, Is.EqualTo (MockBindable.TextProperty.DefaultValue));
+ }
+
+ [Test]
+ public void BindingAppliesAfterGetterPreviouslyMissing()
+ {
+ var bindable = new MockBindable { BindingContext = new EmptyViewModel() };
+ bindable.SetBinding (MockBindable.TextProperty, new Binding ("Text"));
+
+ bindable.BindingContext = new MockViewModel { Text = "Foo" };
+ Assert.That (bindable.Text, Is.EqualTo ("Foo"));
+
+ Assert.That (log.Messages.Count, Is.Not.GreaterThan (1), "Too many errors were logged");
+ Assert.That (log.Messages[0], Is.StringContaining (String.Format (BindingExpression.PropertyNotFoundErrorMessage,
+ "Text",
+ "Xamarin.Forms.Core.UnitTests.BindingUnitTests+EmptyViewModel",
+ "Xamarin.Forms.Core.UnitTests.MockBindable",
+ "Text")));
+ }
+
+ [Test]
+ public void SetterMissingTwoWay()
+ {
+ var bindable = new MockBindable { BindingContext = new DifferentViewModel() };
+ Assert.That (() => bindable.SetBinding (MockBindable.TextProperty, new Binding ("Text")), Throws.Nothing);
+
+ Assert.That (log.Messages.Count, Is.EqualTo (1), "An error was not logged");
+ Assert.That (log.Messages[0], Is.StringContaining (String.Format (BindingExpression.PropertyNotFoundErrorMessage,
+ "Text",
+ "Xamarin.Forms.Core.UnitTests.BindingUnitTests+DifferentViewModel",
+ "Xamarin.Forms.Core.UnitTests.MockBindable",
+ "Text")));
+
+ Assert.That (() => bindable.SetValueCore (MockBindable.TextProperty, "foo"), Throws.Nothing);
+ }
+
+ [Test]
+ public void PrivateSetterTwoWay()
+ {
+ var bindable = new MockBindable { BindingContext = new DifferentViewModel() };
+ Assert.That (() => bindable.SetBinding (MockBindable.TextProperty, new Binding ("PrivateSetter")), Throws.Nothing);
+
+ Assert.That (log.Messages.Count, Is.EqualTo (1), "An error was not logged");
+ Assert.That (log.Messages[0], Is.StringContaining (String.Format (BindingExpression.PropertyNotFoundErrorMessage,
+ "PrivateSetter",
+ "Xamarin.Forms.Core.UnitTests.BindingUnitTests+DifferentViewModel",
+ "Xamarin.Forms.Core.UnitTests.MockBindable",
+ "Text")));
+
+ Assert.That (() => bindable.SetValueCore (MockBindable.TextProperty, "foo"), Throws.Nothing);
+
+ Assert.That (log.Messages.Count, Is.EqualTo (2), "An error was not logged");
+ Assert.That (log.Messages[1], Is.StringContaining (String.Format (BindingExpression.PropertyNotFoundErrorMessage,
+ "PrivateSetter",
+ "Xamarin.Forms.Core.UnitTests.BindingUnitTests+DifferentViewModel",
+ "Xamarin.Forms.Core.UnitTests.MockBindable",
+ "Text")));
+ }
+
+ [Test]
+ public void PropertyNotFound()
+ {
+ var bindable = new MockBindable { BindingContext = new MockViewModel() };
+ Assert.That (() => bindable.SetBinding (MockBindable.TextProperty, new Binding ("MissingProperty")), Throws.Nothing);
+
+ Assert.That (log.Messages.Count, Is.EqualTo (1), "An error was not logged");
+ Assert.That (log.Messages[0], Is.StringContaining (String.Format (BindingExpression.PropertyNotFoundErrorMessage,
+ "MissingProperty",
+ "Xamarin.Forms.Core.UnitTests.MockViewModel",
+ "Xamarin.Forms.Core.UnitTests.MockBindable",
+ "Text")));
+ }
+
+ [Test]
+ [Description ("When binding with a multi-part path and part is null, no error should be thrown or logged")]
+ public void ChainedPartNull()
+ {
+ var bindable = new MockBindable { BindingContext = new ComplexMockViewModel() };
+ Assert.That (() => bindable.SetBinding (MockBindable.TextProperty, new Binding ("Model.Text")), Throws.Nothing);
+ Assert.That (log.Messages.Count, Is.EqualTo (0), "An error was logged");
+ }
+
+ [Test]
+ public void PropertyNotFoundChained()
+ {
+ var bindable = new MockBindable {
+ BindingContext = new ComplexMockViewModel {
+ Model = new ComplexMockViewModel()
+ }
+
+ };
+ Assert.That (() => bindable.SetBinding (MockBindable.TextProperty, new Binding ("Model.MissingProperty")), Throws.Nothing);
+
+ Assert.That (log.Messages.Count, Is.EqualTo (1), "An error was not logged");
+ Assert.That (log.Messages[0], Is.StringContaining (String.Format (BindingExpression.PropertyNotFoundErrorMessage,
+ "MissingProperty",
+ "Xamarin.Forms.Core.UnitTests.BindingUnitTests+ComplexMockViewModel",
+ "Xamarin.Forms.Core.UnitTests.MockBindable",
+ "Text")));
+
+ Assert.That (bindable.Text, Is.EqualTo (MockBindable.TextProperty.DefaultValue));
+ }
+
+ [Test]
+ public void CreateBindingNull()
+ {
+ Assert.That (() => Binding.Create<MockViewModel> (null), Throws.InstanceOf<ArgumentNullException>());
+ }
+
+ [Test]
+ public void CreateBindingSimple()
+ {
+ Binding binding = Binding.Create<MockViewModel> (mvm => mvm.Text);
+ Assert.IsNotNull (binding);
+ Assert.AreEqual ("Text", binding.Path);
+ }
+
+ [Test]
+ public void CreateBindingComplex()
+ {
+ Binding binding = Binding.Create<ComplexMockViewModel> (vm => vm.Model.Model.Text);
+ Assert.IsNotNull (binding);
+ Assert.AreEqual ("Model.Model.Text", binding.Path);
+ }
+
+ [Test]
+ public void CreateBindingIndexed()
+ {
+ Binding binding = Binding.Create<ComplexMockViewModel> (vm => vm.Model.Model[5]);
+ Assert.IsNotNull (binding);
+ Assert.AreEqual ("Model.Model[5]", binding.Path);
+ }
+
+ [Test]
+ public void CreateBindingIndexedNonConstant()
+ {
+ int x = 5;
+ Assert.That (
+ () => Binding.Create<ComplexMockViewModel> (vm => vm.Model.Model[x]),
+ Throws.ArgumentException);
+ }
+
+ internal class ReferenceTypeIndexerViewModel
+ : MockViewModel
+ {
+ public string this [string value]
+ {
+ get { return value; }
+ }
+ }
+
+ [Test]
+ public void CreateBindingNullToIndexer()
+ {
+ Assert.That (
+ () => Binding.Create<ReferenceTypeIndexerViewModel> (vm => vm[null]),
+ Throws.Nothing);
+ }
+
+ [Test]
+ public void CreateBindingWithMethod()
+ {
+ Assert.That (
+ () => Binding.Create<ComplexMockViewModel> (vm => vm.DoStuff()),
+ Throws.ArgumentException);
+ }
+
+ [Test]
+ [Description ("Indexers are seen as methods, we don't want to get them confused with real methods.")]
+ public void CreateBindingWithMethodArgument()
+ {
+ Assert.That (
+ () => Binding.Create<ComplexMockViewModel> (vm => vm.DoStuff (null)),
+ Throws.ArgumentException);
+ }
+
+ object Method (MockViewModel vm)
+ {
+ return vm.Text;
+ }
+
+ [Test]
+ public void CreateBindingMethod()
+ {
+ Func<MockViewModel, object> func = vm => vm.Text;
+ Assert.That (() => Binding.Create<MockViewModel> (vm => func (vm)),
+ Throws.ArgumentException);
+
+ Assert.That (() => Binding.Create<MockViewModel> (vm => Method (vm)),
+ Throws.ArgumentException);
+ }
+
+ [Test]
+ public void CreateBindingPrivateIndexer()
+ {
+ Assert.That (() => Binding.Create<InternalIndexerViewModel> (vm => vm[5]),
+ Throws.ArgumentException);
+ }
+
+ class InternalIndexerViewModel
+ {
+ internal int this [int x]
+ {
+ get { return x; }
+ }
+ }
+
+ [Test]
+ public void CreateBindingInvalidExpression()
+ {
+ Assert.That (() => Binding.Create<MockViewModel> (vm => vm.Text + vm.Text),
+ Throws.ArgumentException);
+
+ Assert.That (() => Binding.Create<MockViewModel> (vm => 5),
+ Throws.ArgumentException);
+
+ Assert.That (() => Binding.Create<MockViewModel> (vm => null),
+ Throws.ArgumentException);
+ }
+
+ [Test]
+ public void SetBindingContextBeforeContextBindingAndInnerBindings ()
+ {
+ var label = new Label ();
+ var view = new StackLayout { Children = {label} };
+
+ view.BindingContext = new {item0 = "Foo", item1 = "Bar"};
+ label.SetBinding (BindableObject.BindingContextProperty, "item0");
+ label.SetBinding (Label.TextProperty, Binding.SelfPath);
+
+ Assert.AreEqual ("Foo", label.Text);
+ }
+
+ [Test]
+ public void SetBindingContextAndInnerBindingBeforeContextBinding ()
+ {
+ var label = new Label ();
+ var view = new StackLayout { Children = {label} };
+
+ view.BindingContext = new {item0 = "Foo", item1 = "Bar"};
+ label.SetBinding (Label.TextProperty, Binding.SelfPath);
+ label.SetBinding (BindableObject.BindingContextProperty, "item0");
+
+ Assert.AreEqual ("Foo", label.Text);
+ }
+
+ [Test]
+ public void SetBindingContextAfterContextBindingAndInnerBindings ()
+ {
+ var label = new Label ();
+ var view = new StackLayout { Children = {label} };
+
+ label.SetBinding (BindableObject.BindingContextProperty, "item0");
+ label.SetBinding (Label.TextProperty, Binding.SelfPath);
+ view.BindingContext = new {item0 = "Foo", item1 = "Bar"};
+
+ Assert.AreEqual ("Foo", label.Text);
+ }
+
+ [Test]
+ public void SetBindingContextAfterInnerBindingsAndContextBinding ()
+ {
+ var label = new Label ();
+ var view = new StackLayout { Children = {label} };
+
+ label.SetBinding (Label.TextProperty, Binding.SelfPath);
+ label.SetBinding (BindableObject.BindingContextProperty, "item0");
+ view.BindingContext = new {item0 = "Foo", item1 = "Bar"};
+
+ Assert.AreEqual ("Foo", label.Text);
+ }
+
+ [Test]
+ public void Convert ()
+ {
+ var slider = new Slider ();
+ var vm = new MockViewModel { Text = "0.5" };
+ slider.BindingContext = vm;
+ slider.SetBinding (Slider.ValueProperty, "Text", BindingMode.TwoWay);
+
+ Assert.That (slider.Value, Is.EqualTo (0.5));
+
+ slider.Value = 0.9;
+
+ Assert.That (vm.Text, Is.EqualTo ("0.9"));
+ }
+
+ #if !WINDOWS_PHONE
+ [Test]
+ [SetCulture ("pt-PT")]
+ [SetUICulture ("pt-PT")]
+ public void ConvertIsCultureInvariant ()
+ {
+ var slider = new Slider ();
+ var vm = new MockViewModel { Text = "0.5" };
+ slider.BindingContext = vm;
+ slider.SetBinding (Slider.ValueProperty, "Text", BindingMode.TwoWay);
+
+ Assert.That (slider.Value, Is.EqualTo (0.5));
+
+ slider.Value = 0.9;
+
+ Assert.That (vm.Text, Is.EqualTo ("0.9"));
+ }
+ #endif
+
+ [Test]
+ public void FailToConvert ()
+ {
+ var slider = new Slider ();
+ slider.BindingContext = new ComplexMockViewModel { Model = new ComplexMockViewModel() };
+
+ Assert.That (() => {
+ slider.SetBinding (Slider.ValueProperty, "Model");
+ }, Throws.Nothing);
+
+ Assert.That (slider.Value, Is.EqualTo (Slider.ValueProperty.DefaultValue));
+ }
+
+ class NullViewModel : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public string Foo
+ {
+ get;
+ set;
+ }
+
+ public string Bar
+ {
+ get;
+ set;
+ }
+
+ public void SignalAllPropertiesChanged (bool useNull)
+ {
+ var changed = PropertyChanged;
+ if (changed != null)
+ changed (this, new PropertyChangedEventArgs ((useNull) ? null : String.Empty));
+ }
+ }
+
+ class MockBindable2 : MockBindable
+ {
+ public static readonly BindableProperty Text2Property = BindableProperty.Create<MockBindable2, string> (
+ b => b.Text2, "default", BindingMode.TwoWay);
+
+ public string Text2
+ {
+ get { return (string)GetValue (Text2Property); }
+ set { SetValue (Text2Property, value); }
+ }
+ }
+
+ [TestCase (true)]
+ [TestCase (false)]
+ public void NullPropertyUpdatesAllBindings (bool useStringEmpty)
+ {
+ var vm = new NullViewModel();
+ var bindable = new MockBindable2();
+ bindable.BindingContext = vm;
+ bindable.SetBinding (MockBindable.TextProperty, "Foo");
+ bindable.SetBinding (MockBindable2.Text2Property, "Bar");
+
+ vm.Foo = "Foo";
+ vm.Bar = "Bar";
+ Assert.That (() => vm.SignalAllPropertiesChanged (useNull: !useStringEmpty), Throws.Nothing);
+
+ Assert.That (bindable.Text, Is.EqualTo ("Foo"));
+ Assert.That (bindable.Text2, Is.EqualTo ("Bar"));
+ }
+
+ [TestCase]
+ public void BindingSourceOverContext ()
+ {
+ var label = new Label ();
+ label.BindingContext = "bindingcontext";
+ label.SetBinding (Label.TextProperty, Binding.SelfPath);
+ Assert.AreEqual ("bindingcontext", label.Text);
+
+ label.SetBinding (Label.TextProperty, new Binding (Binding.SelfPath, source: "bindingsource"));
+ Assert.AreEqual ("bindingsource", label.Text);
+ }
+
+ class TestViewModel : INotifyPropertyChanged
+ {
+ event PropertyChangedEventHandler PropertyChanged;
+
+ event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
+ {
+ add { PropertyChanged += value; }
+ remove { PropertyChanged -= value; }
+ }
+
+ public string Foo { get; set; }
+
+ public int InvocationListSize ()
+ {
+ if (PropertyChanged == null)
+ return 0;
+ return PropertyChanged.GetInvocationList ().Length;
+ }
+
+ public virtual void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChanged?.Invoke (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+
+ [Test]
+ public void BindingUnsubscribesForDeadTarget ()
+ {
+ TestViewModel viewmodel = new TestViewModel();
+
+ int i = 0;
+ Action create = null;
+ create = () => {
+ if (i++ < 1024) {
+ create();
+ return;
+ }
+
+ var button = new Button ();
+ button.SetBinding (Button.TextProperty, "Foo");
+ button.BindingContext = viewmodel;
+ };
+
+ create();
+
+ Assume.That (viewmodel.InvocationListSize (), Is.EqualTo (1));
+
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+ GC.Collect ();
+
+ viewmodel.OnPropertyChanged ("Foo");
+
+ Assert.AreEqual (0, viewmodel.InvocationListSize ());
+ }
+
+ [Test]
+ public void BindingCreatesSingleSubscription ()
+ {
+ TestViewModel viewmodel = new TestViewModel();
+
+ var button = new Button ();
+ button.SetBinding (Button.TextProperty, "Foo");
+ button.BindingContext = viewmodel;
+
+ Assert.That (viewmodel.InvocationListSize (), Is.EqualTo (1));
+ }
+
+ public class IndexedViewModel : INotifyPropertyChanged
+ {
+ Dictionary<string, object> dict = new Dictionary<string, object> ();
+
+ public object this [string index]
+ {
+ get { return dict[index]; }
+ set
+ {
+ dict[index] = value;
+ OnPropertyChanged ("Item[" + index + "]");
+
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChanged?.Invoke (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+
+ [Test]
+ public void IndexedViewModelPropertyChanged ()
+ {
+ var label = new Label ();
+ var viewModel = new IndexedViewModel ();
+ //viewModel["Foo"] = "Bar";
+
+ label.BindingContext = new {
+ Data = viewModel
+ };
+ label.SetBinding (Label.TextProperty, "Data[Foo]");
+
+
+ Assert.AreEqual (null, label.Text);
+
+ viewModel["Foo"] = "Baz";
+
+ Assert.AreEqual ("Baz", label.Text);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/BoxViewUnitTests.cs b/Xamarin.Forms.Core.UnitTests/BoxViewUnitTests.cs
new file mode 100644
index 00000000..6d26af45
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/BoxViewUnitTests.cs
@@ -0,0 +1,42 @@
+using System;
+using NUnit.Framework;
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class BoxViewUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestConstructor ()
+ {
+ var box = new BoxView {
+ Color = new Color (0.2, 0.3, 0.4),
+ WidthRequest=20,
+ HeightRequest=30,
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ Assert.AreEqual (new Color (0.2, 0.3, 0.4), box.Color);
+ var request = box.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request;
+ Assert.AreEqual (20, request.Width);
+ Assert.AreEqual (30, request.Height);
+ }
+
+ [Test]
+ public void DefaultSize ()
+ {
+ var box = new BoxView {
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ var request = box.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request;
+ Assert.AreEqual (40, request.Width);
+ Assert.AreEqual (40, request.Height);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ButtonUnitTest.cs b/Xamarin.Forms.Core.UnitTests/ButtonUnitTest.cs
new file mode 100644
index 00000000..29ad2d0e
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ButtonUnitTest.cs
@@ -0,0 +1,181 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ButtonUnitTest
+ : CommandSourceTests<Button>
+ {
+ [SetUp]
+ public override void Setup ()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown ()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void MeasureInvalidatedOnTextChange ()
+ {
+ var button = new Button ();
+
+ bool fired = false;
+ button.MeasureInvalidated += (sender, args) => fired = true;
+
+ button.Text = "foo";
+ Assert.True (fired);
+ }
+
+ [Test]
+ public void TestTappedEvent ()
+ {
+ var view = new Button ();
+
+ bool activated = false;
+ view.Clicked += (sender, e) => activated = true;
+
+ ((IButtonController) view).SendClicked ();
+
+ Assert.True (activated);
+ }
+
+ protected override Button CreateSource()
+ {
+ return new Button();
+ }
+
+ protected override void Activate (Button source)
+ {
+ ((IButtonController) source).SendClicked();
+ }
+
+ protected override BindableProperty IsEnabledProperty
+ {
+ get { return Button.IsEnabledProperty; }
+ }
+
+ protected override BindableProperty CommandProperty
+ {
+ get { return Button.CommandProperty; }
+ }
+
+ protected override BindableProperty CommandParameterProperty
+ {
+ get { return Button.CommandParameterProperty; }
+ }
+
+
+ [Test]
+ public void TestBindingContextPropagation ()
+ {
+ var context = new object ();
+ var button = new Button ();
+ button.BindingContext = context;
+ var source = new FileImageSource ();
+ button.Image = source;
+ Assert.AreSame (context, source.BindingContext);
+
+ button = new Button ();
+ source = new FileImageSource ();
+ button.Image = source;
+ button.BindingContext = context;
+ Assert.AreSame (context, source.BindingContext);
+ }
+
+ [Test]
+ public void TestImageSourcePropertiesChangedTriggerResize ()
+ {
+ var source = new FileImageSource ();
+ var button = new Button { Image = source };
+ bool fired = false;
+ button.MeasureInvalidated += (sender, e) => fired = true;
+ Assert.Null (source.File);
+ source.File = "foo.png";
+ Assert.NotNull (source.File);
+ Assert.True (fired);
+ }
+
+ [Test]
+ public void AssignToFontStructUpdatesFontFamily (
+ [Values (NamedSize.Default, NamedSize.Large, NamedSize.Medium, NamedSize.Small, NamedSize.Micro)] NamedSize size,
+ [Values (FontAttributes.None, FontAttributes.Bold, FontAttributes.Italic, FontAttributes.Bold | FontAttributes.Italic)] FontAttributes attributes)
+ {
+ var button = new Button {Platform = new UnitPlatform ()};
+ double startSize = button.FontSize;
+ var startAttributes = button.FontAttributes;
+
+ bool firedSizeChanged = false;
+ bool firedAttributesChanged = false;
+ button.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == Label.FontSizeProperty.PropertyName)
+ firedSizeChanged = true;
+ if (args.PropertyName == Label.FontAttributesProperty.PropertyName)
+ firedAttributesChanged = true;
+ };
+
+ button.Font = Font.OfSize ("Testing123", size).WithAttributes (attributes);
+
+ Assert.AreEqual (Device.GetNamedSize (size, typeof (Label), true), button.FontSize);
+ Assert.AreEqual (attributes, button.FontAttributes);
+ Assert.AreEqual (startSize != button.FontSize, firedSizeChanged);
+ Assert.AreEqual (startAttributes != button.FontAttributes, firedAttributesChanged);
+ }
+
+ [Test]
+ public void AssignToFontFamilyUpdatesFont ()
+ {
+ var button = new Button {Platform = new UnitPlatform ()};
+
+ button.FontFamily = "CrazyFont";
+ Assert.AreEqual (button.Font, Font.OfSize ("CrazyFont", button.FontSize));
+ }
+
+ [Test]
+ public void AssignToFontSizeUpdatesFont ()
+ {
+ var button = new Button {Platform = new UnitPlatform ()};
+
+ button.FontSize = 1000;
+ Assert.AreEqual (button.Font, Font.SystemFontOfSize (1000));
+ }
+
+ [Test]
+ public void AssignToFontAttributesUpdatesFont ()
+ {
+ var button = new Button {Platform = new UnitPlatform ()};
+
+ button.FontAttributes = FontAttributes.Italic | FontAttributes.Bold;
+ Assert.AreEqual (button.Font, Font.SystemFontOfSize (button.FontSize, FontAttributes.Bold | FontAttributes.Italic));
+ }
+
+ [Test]
+ public void CommandCanExecuteUpdatesEnabled ()
+ {
+ var button = new Button ();
+
+ bool result = false;
+
+ var bindingContext = new {
+ Command = new Command (() => { }, () => result)
+ };
+
+ button.SetBinding (Button.CommandProperty, "Command");
+ button.BindingContext = bindingContext;
+
+ Assert.False (button.IsEnabled);
+
+ result = true;
+
+ bindingContext.Command.ChangeCanExecute ();
+
+ Assert.True (button.IsEnabled);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/CarouselPageTests.cs b/Xamarin.Forms.Core.UnitTests/CarouselPageTests.cs
new file mode 100644
index 00000000..553d67ce
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/CarouselPageTests.cs
@@ -0,0 +1,29 @@
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ public class CarouselPageTests : MultiPageTests<ContentPage>
+ {
+ protected override MultiPage<ContentPage> CreateMultiPage()
+ {
+ return new CarouselPage();
+ }
+
+ protected override ContentPage CreateContainedPage()
+ {
+ return new ContentPage { Content = new View() };
+ }
+
+ protected override int GetIndex (ContentPage page)
+ {
+ return CarouselPage.GetIndex (page);
+ }
+
+ [Test]
+ public void TestConstructor()
+ {
+ var page = new CarouselPage();
+ Assert.That (page.Children, Is.Empty);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/CellTests.cs b/Xamarin.Forms.Core.UnitTests/CellTests.cs
new file mode 100644
index 00000000..0006b4cf
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/CellTests.cs
@@ -0,0 +1,190 @@
+using NUnit.Framework;
+using System;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class CellTests : BaseTestFixture
+ {
+ internal class TestCell : Cell
+ {
+ public bool OnAppearingSent { get; set; }
+ public bool OnDisappearingSent { get; set; }
+
+ protected override void OnAppearing ()
+ {
+ base.OnAppearing ();
+ OnAppearingSent = true;
+ }
+
+ protected override void OnDisappearing ()
+ {
+ base.OnDisappearing ();
+ OnDisappearingSent = true;
+ }
+ }
+
+ [Test]
+ public void Selected ()
+ {
+ var cell = new TestCell ();
+
+ bool tapped = false;
+ cell.Tapped += (sender, args) => tapped = true;
+
+ cell.OnTapped();
+ Assert.IsTrue (tapped);
+ }
+
+ [Test]
+ public void AppearingEvent ()
+ {
+ var cell = new TestCell ();
+
+ bool emitted = false;
+ cell.Appearing += (sender, args) => emitted = true;
+
+ cell.SendAppearing ();
+ Assert.True (emitted);
+ Assert.True (cell.OnAppearingSent);
+ Assert.False (cell.OnDisappearingSent);
+ }
+
+ [Test]
+ public void DisappearingEvent ()
+ {
+ var cell = new TestCell ();
+
+ bool emitted = false;
+ cell.Disappearing += (sender, args) => emitted = true;
+
+ cell.SendDisappearing ();
+ Assert.True (emitted);
+ Assert.False (cell.OnAppearingSent);
+ Assert.True (cell.OnDisappearingSent);
+ }
+
+ [Test]
+ public void TestBindingContextPropagationOnImageCell ()
+ {
+ var context = new object ();
+ var cell = new ImageCell ();
+ cell.BindingContext = context;
+ var source = new FileImageSource ();
+ cell.ImageSource = source;
+ Assert.AreSame (context, source.BindingContext);
+
+ cell = new ImageCell ();
+ source = new FileImageSource ();
+ cell.ImageSource = source;
+ cell.BindingContext = context;
+ Assert.AreSame (context, source.BindingContext);
+ }
+
+ [Test]
+ public void HasContextActions()
+ {
+ bool changed = false;
+
+ var cell = new TextCell();
+ cell.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "HasContextActions")
+ changed = true;
+ };
+
+ Assert.That (cell.HasContextActions, Is.False);
+ Assert.That (changed, Is.False);
+
+ var collection = cell.ContextActions;
+
+ Assert.That (cell.HasContextActions, Is.False);
+ Assert.That (changed, Is.False);
+
+ collection.Add (new MenuItem());
+
+ Assert.That (cell.HasContextActions, Is.True);
+ Assert.That (changed, Is.True);
+ }
+
+ [Test]
+ public void MenuItemsGetBindingContext()
+ {
+ var cell = new TextCell {
+ ContextActions = {
+ new MenuItem ()
+ }
+ };
+
+ object bc = new object ();
+
+ cell.BindingContext = bc;
+ Assert.That (cell.ContextActions [0].BindingContext, Is.SameAs (bc));
+
+ cell = new TextCell { BindingContext = new object () };
+ cell.ContextActions.Add (new MenuItem ());
+
+ Assert.That (cell.ContextActions [0].BindingContext, Is.SameAs (cell.BindingContext));
+ }
+
+ [Test]
+ public void RenderHeightINPCFromParent()
+ {
+ var lv = new ListView();
+ var cell = new TextCell();
+ cell.Parent = lv;
+
+ int changing = 0, changed = 0;
+ cell.PropertyChanging += (sender, args) => {
+ if (args.PropertyName == "RenderHeight")
+ changing++;
+ };
+
+ cell.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "RenderHeight")
+ changed++;
+ };
+
+ lv.RowHeight = 5;
+
+ Assume.That (cell.RenderHeight, Is.EqualTo (5));
+
+ Assert.That (changing, Is.EqualTo (1));
+ Assert.That (changed, Is.EqualTo (1));
+ }
+
+ [Test]
+ public async void ForceUpdateSizeCallsAreRateLimited()
+ {
+ var lv = new ListView { HasUnevenRows = true };
+ var cell = new ViewCell { Parent = lv };
+
+ int numberOfCalls = 0;
+ cell.ForceUpdateSizeRequested += (object sender, System.EventArgs e) => { numberOfCalls++; };
+
+ cell.ForceUpdateSize ();
+ cell.ForceUpdateSize ();
+ cell.ForceUpdateSize ();
+ cell.ForceUpdateSize ();
+
+ await System.Threading.Tasks.Task.Delay (TimeSpan.FromMilliseconds (150));
+
+ Assert.AreEqual (1, numberOfCalls);
+ }
+
+ [Test]
+ public async void ForceUpdateSizeWillNotBeCalledIfParentIsNotAListViewWithUnevenRows ()
+ {
+ var lv = new ListView { HasUnevenRows = false };
+ var cell = new ViewCell { Parent = lv };
+
+ int numberOfCalls = 0;
+ cell.ForceUpdateSizeRequested += (object sender, System.EventArgs e) => { numberOfCalls++; };
+
+ cell.ForceUpdateSize ();
+
+ await System.Threading.Tasks.Task.Delay (TimeSpan.FromMilliseconds (16));
+
+ Assert.AreEqual (0, numberOfCalls);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ColorUnitTests.cs b/Xamarin.Forms.Core.UnitTests/ColorUnitTests.cs
new file mode 100644
index 00000000..b29a9680
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ColorUnitTests.cs
@@ -0,0 +1,268 @@
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ColorUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestHSLPostSetEquality ()
+ {
+ var color = new Color (1, 0.5, 0.2);
+ var color2 = color;
+
+ color2 = color.WithLuminosity (.2);
+ Assert.False (color == color2);
+ }
+
+ [Test]
+ public void TestHSLPostSetInequality ()
+ {
+ var color = new Color (1, 0.5, 0.2);
+ var color2 = color;
+
+ color2 = color.WithLuminosity (.2);
+
+ Assert.True (color != color2);
+ }
+
+ [Test]
+ public void TestHSLSetToDefaultValue ()
+ {
+ var color = new Color (0.2, 0.5, 0.8);
+
+ // saturation is initialized to 0, make sure we still update
+ color = color.WithSaturation (0);
+
+ Assert.AreEqual (color.R, color.G);
+ Assert.AreEqual (color.R, color.B);
+ }
+
+ [Test]
+ public void TestHSLModifiers ()
+ {
+ var color = Color.Default;
+ Assert.Throws<InvalidOperationException> (()=> color.WithHue (.1));
+ Assert.Throws<InvalidOperationException> (()=> color.WithLuminosity (.1));
+ Assert.Throws<InvalidOperationException> (()=> color.WithSaturation (.1));
+
+ color = Color.FromHsla (.8, .6, .2);
+ Assert.AreEqual (Color.FromHsla (.1, .6, .2), color.WithHue (.1));
+ Assert.AreEqual (Color.FromHsla (.8, .1, .2), color.WithSaturation (.1));
+ Assert.AreEqual (Color.FromHsla (.8, .6, .1), color.WithLuminosity (.1));
+ }
+
+ [Test]
+ public void TestMultiplyAlpha ()
+ {
+ var color = new Color (1, 1, 1, 1);
+ color = color.MultiplyAlpha (0.25);
+ Assert.AreEqual (.25, color.A);
+
+ color = Color.Default;
+ Assert.Throws<InvalidOperationException>(()=>color = color.MultiplyAlpha (0.25));
+
+ color = Color.FromHsla (1, 1, 1, 1);
+ color = color.MultiplyAlpha (0.25);
+ Assert.AreEqual (.25, color.A);
+ }
+
+ [Test]
+ public void TestClamping ()
+ {
+ var color = new Color (2, 2, 2, 2);
+
+ Assert.AreEqual (1, color.R);
+ Assert.AreEqual (1, color.G);
+ Assert.AreEqual (1, color.B);
+ Assert.AreEqual (1, color.A);
+
+ color = new Color (-1, -1, -1, -1);
+
+ Assert.AreEqual (0, color.R);
+ Assert.AreEqual (0, color.G);
+ Assert.AreEqual (0, color.B);
+ Assert.AreEqual (0, color.A);
+ }
+
+ [Test]
+ public void TestRGBToHSL ()
+ {
+ var color = new Color (.5, .1, .1);
+
+ Assert.That (color.Hue, Is.EqualTo (1).Within (0.001));
+ Assert.That (color.Saturation, Is.EqualTo (0.662).Within (0.01));
+ Assert.That (color.Luminosity, Is.EqualTo (0.302).Within (0.01));
+ }
+
+ [Test]
+ public void TestHSLToRGB ()
+ {
+ var color = Color.FromHsla (0, .662, .302);
+
+ Assert.That (color.R, Is.EqualTo (0.5).Within (0.01));
+ Assert.That (color.G, Is.EqualTo (0.1).Within (0.01));
+ Assert.That (color.B, Is.EqualTo (0.1).Within (0.01));
+ }
+
+ [Test]
+ public void TestColorFromValue ()
+ {
+ var color = new Color (0.2);
+
+ Assert.AreEqual (new Color (0.2, 0.2, 0.2, 1), color);
+ }
+
+ [Test]
+ public void TestAddLuminosity ()
+ {
+ var color = new Color (0.2);
+ var brighter = color.AddLuminosity (0.2);
+ Assert.That (brighter.Luminosity, Is.EqualTo (color.Luminosity + 0.2).Within (0.001));
+
+ color = Color.Default;
+ Assert.Throws<InvalidOperationException> (() => color.AddLuminosity (0.2));
+ }
+
+ [Test]
+ public void TestZeroLuminosity ()
+ {
+ var color = new Color (0.1, 0.2, 0.3);
+ color = color.AddLuminosity (-1);
+
+ Assert.AreEqual (0, color.Luminosity);
+ Assert.AreEqual (0, color.R);
+ Assert.AreEqual (0, color.G);
+ Assert.AreEqual (0, color.B);
+ }
+
+ [Test]
+ public void TestHashCode ()
+ {
+ var color1 = new Color (0.1);
+ var color2 = new Color (0.1);
+
+ Assert.True (color1.GetHashCode () == color2.GetHashCode ());
+ color2 = Color.FromHsla (color2.Hue, color2.Saturation, .5);
+
+ Assert.False (color1.GetHashCode () == color2.GetHashCode ());
+ }
+
+ [Test]
+ public void TestHashCodeNamedColors ()
+ {
+ Color red = Color.Red; //R=1, G=0, B=0, A=1
+ int hashRed = red.GetHashCode();
+
+ Color blue = Color.Blue; //R=0, G=0, B=1, A=1
+ int hashBlue = blue.GetHashCode();
+
+ Assert.False (hashRed == hashBlue);
+ }
+
+ [Test]
+ public void TestHashCodeAll ()
+ {
+ Dictionary<int,Color> colorsAndHashes = new Dictionary<int,Color> ();
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Transparent.GetHashCode (), Color.Transparent));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Aqua.GetHashCode (), Color.Aqua));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Black.GetHashCode (), Color.Black));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Blue.GetHashCode (), Color.Blue));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Fuchsia.GetHashCode (), Color.Fuchsia));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Gray.GetHashCode (), Color.Gray));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Green.GetHashCode (), Color.Green));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Lime.GetHashCode (), Color.Lime));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Maroon.GetHashCode (), Color.Maroon));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Navy.GetHashCode (), Color.Navy));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Olive.GetHashCode (), Color.Olive));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Purple.GetHashCode (), Color.Purple));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Pink.GetHashCode (), Color.Pink));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Red.GetHashCode (), Color.Red));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Silver.GetHashCode (), Color.Silver));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Teal.GetHashCode (), Color.Teal));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.White.GetHashCode (), Color.White));
+ Assert.DoesNotThrow (() => colorsAndHashes.Add (Color.Yellow.GetHashCode (), Color.Yellow));
+ }
+
+ [Test]
+ public void TestSetHue ()
+ {
+ var color = new Color (0.2, 0.5, 0.7);
+ color = Color.FromHsla (.2, color.Saturation, color.Luminosity);
+
+ Assert.That (color.R, Is.EqualTo (0.6).Within (0.001));
+ Assert.That (color.G, Is.EqualTo (0.7).Within (0.001));
+ Assert.That (color.B, Is.EqualTo (0.2).Within (0.001));
+ }
+
+ [Test]
+ public void ZeroLuminToRGB ()
+ {
+ var color = new Color (0);
+ Assert.AreEqual (0, color.Luminosity);
+ Assert.AreEqual (0, color.Hue);
+ Assert.AreEqual (0, color.Saturation);
+ }
+
+ [Test]
+ public void TestToString ()
+ {
+ var color = new Color (1, 1, 1, 0.5);
+ Assert.AreEqual ("[Color: A=0.5, R=1, G=1, B=1, Hue=0, Saturation=0, Luminosity=1]", color.ToString ());
+ }
+
+ [Test]
+ public void TestFromHex ()
+ {
+ var color = Color.FromRgb(138, 43, 226);
+ Assert.AreEqual(color, Color.FromHex("8a2be2"));
+
+ Assert.AreEqual (Color.FromRgba (138, 43, 226, 128), Color.FromHex ("#808a2be2"));
+ Assert.AreEqual (Color.FromHex ("#aabbcc"), Color.FromHex ("#abc"));
+ Assert.AreEqual (Color.FromHex ("#aabbccdd"), Color.FromHex ("#abcd"));
+ }
+
+ [Test]
+ public void FromRGBDouble ()
+ {
+ var color = Color.FromRgb (0.2, 0.3, 0.4);
+
+ Assert.AreEqual (new Color (0.2, 0.3, 0.4), color);
+ }
+
+ [Test]
+ public void FromRGBADouble ()
+ {
+ var color = Color.FromRgba (0.2, 0.3, 0.4, 0.5);
+
+ Assert.AreEqual (new Color (0.2, 0.3, 0.4, 0.5), color);
+ }
+
+ [Test]
+ public void TestColorTypeConverter ()
+ {
+ var converter = new ColorTypeConverter ();
+ Assert.True (converter.CanConvertFrom (typeof(string)));
+ Assert.AreEqual (Color.Blue, converter.ConvertFromInvariantString ("Color.Blue"));
+ Assert.AreEqual (Color.Blue, converter.ConvertFromInvariantString ("Blue"));
+ Assert.AreEqual (Color.Blue, converter.ConvertFromInvariantString ("#0000ff"));
+ Assert.AreEqual (Color.Default, converter.ConvertFromInvariantString ("Color.Default"));
+ Assert.AreEqual (Color.Accent, converter.ConvertFromInvariantString ("Accent"));
+ var hotpink = Color.FromHex ("#FF69B4");
+ Color.Accent = hotpink;
+ Assert.AreEqual (Color.Accent, converter.ConvertFromInvariantString ("Accent"));
+ Assert.Throws<InvalidOperationException> (() => converter.ConvertFromInvariantString (""));
+ }
+
+ [Test]
+ public void TestDefault ()
+ {
+ Assert.AreEqual (Color.Default, default(Color));
+ Assert.AreEqual (Color.Default, new Color ());
+ }
+
+
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/CommandSourceTests.cs b/Xamarin.Forms.Core.UnitTests/CommandSourceTests.cs
new file mode 100644
index 00000000..f544a297
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/CommandSourceTests.cs
@@ -0,0 +1,184 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ public abstract class CommandSourceTests<T> : BaseTestFixture
+ where T : BindableObject
+ {
+ [Test]
+ public void TestCommand ()
+ {
+ var source = CreateSource();
+
+ bool executed = false;
+ source.SetValue (CommandProperty, new Command (o => {
+ executed = true;
+ Assert.AreEqual (source, o);
+ }));
+
+ source.SetValue (CommandParameterProperty, source);
+
+ Activate (source);
+
+ Assert.True (executed);
+ }
+
+ [Test]
+ public void CommandCanExecuteModifiesEnabled ([Values(true, false)] bool initial)
+ {
+ bool canExecute = initial;
+ Command command;
+ var source = CreateSource();
+ source.SetValue (CommandProperty, command = new Command (() => { }, () => canExecute));
+
+ Assert.AreEqual (canExecute, source.GetValue (IsEnabledProperty));
+
+ canExecute = !initial;
+ command.ChangeCanExecute ();
+
+ Assert.AreEqual (canExecute, source.GetValue (IsEnabledProperty));
+ }
+
+ [Test]
+ public void ReenabledAfterCommandRemoved()
+ {
+ var source = CreateSource();
+ source.SetValue (CommandProperty, new Command (() => { }, () => false));
+
+ Assert.That (source.GetValue (IsEnabledProperty), Is.False);
+
+ source.SetValue (CommandProperty, null);
+
+ Assert.That (source.GetValue (IsEnabledProperty), Is.True);
+ }
+
+ [Test]
+ public void CommandUnhooksOnNull ()
+ {
+ bool canExecute = false;
+ Command command;
+ var source = CreateSource();
+
+ bool raised = false;
+ source.SetValue (CommandProperty, command = new Command (() => { }, () => {
+ raised = true;
+ return canExecute;
+ }));
+
+ raised = false;
+ source.SetValue (CommandProperty, null);
+
+ canExecute = true;
+ command.ChangeCanExecute ();
+
+ Assert.False (raised);
+ }
+
+ [Test]
+ public void CommandCanExecuteInvokedOnCommandSet ()
+ {
+ bool fired = false;
+ Func<bool> canExecute = () => {
+ fired = true;
+ return true;
+ };
+
+ Assert.IsFalse (fired);
+ var source = CreateSource();
+ source.SetValue (CommandProperty, new Command (() => { }, canExecute));
+
+ Assert.True (fired);
+ }
+
+ [Test]
+ public void CommandCanExecuteInvokedOnCommandParameterSet ()
+ {
+ bool fired;
+ Func<bool> canExecute = () => {
+ fired = true;
+ return true;
+ };
+
+ var source = CreateSource();
+ source.SetValue (CommandProperty, new Command (() => { }, canExecute));
+
+ fired = false;
+ Assert.IsFalse (fired);
+ source.SetValue (CommandParameterProperty, new object ());
+ Assert.True (fired);
+ }
+
+ [Test]
+ public void CommandCanExecuteInvokedOnChange()
+ {
+ bool fired;
+ Func<bool> canExecute = () => {
+ fired = true;
+ return true;
+ };
+
+ var cmd = new Command (() => { }, canExecute);
+ var source = CreateSource();
+ source.SetValue (CommandProperty, cmd);
+
+ fired = false;
+
+ cmd.ChangeCanExecute();
+
+ Assert.That (fired, Is.True, "CanExecute was not called when the event was raised");
+ }
+
+ class BoolViewModel
+ : MockViewModel
+ {
+ bool toggle;
+
+ public bool Toggle
+ {
+ get { return toggle; }
+ set
+ {
+ if (toggle == value)
+ return;
+
+ toggle = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ [Test]
+ public void EnabledUpdatesDoNotRemoveBindings()
+ {
+ var vm = new BoolViewModel { Toggle = true };
+ var source = CreateSource();
+ source.BindingContext = vm;
+ source.SetBinding (IsEnabledProperty, "Toggle");
+
+ Assert.That (source.GetValue (IsEnabledProperty), Is.True);
+
+ source.SetValue (CommandProperty, new Command (() => { }));
+
+ Assert.That (source.GetIsBound (IsEnabledProperty), Is.True);
+ }
+
+ protected abstract T CreateSource();
+ protected abstract void Activate (T source);
+
+ protected abstract BindableProperty IsEnabledProperty
+ {
+ get;
+ }
+
+ protected abstract BindableProperty CommandProperty
+ {
+ get;
+ }
+
+ protected abstract BindableProperty CommandParameterProperty
+ {
+ get;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/CommandTests.cs b/Xamarin.Forms.Core.UnitTests/CommandTests.cs
new file mode 100644
index 00000000..1182fe40
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/CommandTests.cs
@@ -0,0 +1,155 @@
+using System;
+using NUnit.Framework;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class CommandTests : BaseTestFixture
+ {
+ [Test]
+ public void Constructor ()
+ {
+ var cmd = new Command (() => { });
+ Assert.True (cmd.CanExecute (null));
+ }
+
+ [Test]
+ public void ThrowsWithNullConstructor ()
+ {
+ Assert.Throws<ArgumentNullException> (() => new Command ((Action)null));
+ }
+
+ [Test]
+ public void ThrowsWithNullParameterizedConstructor ()
+ {
+ Assert.Throws<ArgumentNullException> (() => new Command ((Action<object>)null));
+ }
+
+ [Test]
+ public void ThrowsWithNullCanExecute ()
+ {
+ Assert.Throws<ArgumentNullException> (() => new Command (() => { }, null));
+ }
+
+ [Test]
+ public void ThrowsWithNullParameterizedCanExecute ()
+ {
+ Assert.Throws<ArgumentNullException> (() => new Command (o => { }, null));
+ }
+
+ [Test]
+ public void ThrowsWithNullExecuteValidCanExecute ()
+ {
+ Assert.Throws<ArgumentNullException> (() => new Command (null, () => true));
+ }
+
+ [Test]
+ public void Execute ()
+ {
+ bool executed = false;
+ var cmd = new Command (() => executed = true);
+
+ cmd.Execute (null);
+ Assert.True (executed);
+ }
+
+ [Test]
+ public void ExecuteParameterized ()
+ {
+ object executed = null;
+ var cmd = new Command (o => executed = o);
+
+ var expected = new object ();
+ cmd.Execute (expected);
+
+ Assert.AreEqual (expected, executed);
+ }
+
+ [Test]
+ public void ExecuteWithCanExecute ()
+ {
+ bool executed = false;
+ var cmd = new Command (() => executed = true, () => true);
+
+ cmd.Execute (null);
+ Assert.True (executed);
+ }
+
+ [Test]
+ public void CanExecute ([Values (true, false)] bool expected)
+ {
+ bool canExecuteRan = false;
+ var cmd = new Command (() => { }, () => {
+ canExecuteRan = true;
+ return expected;
+ });
+
+ Assert.AreEqual(expected, cmd.CanExecute (null));
+ Assert.True (canExecuteRan);
+ }
+
+ [Test]
+ public void ChangeCanExecute ()
+ {
+ bool signaled = false;
+ var cmd = new Command (() => { });
+
+ cmd.CanExecuteChanged += (sender, args) => signaled = true;
+
+ cmd.ChangeCanExecute ();
+ Assert.True (signaled);
+ }
+
+ [Test]
+ public void GenericThrowsWithNullExecute ()
+ {
+ Assert.Throws<ArgumentNullException> (() => new Command<string> (null));
+ }
+
+ [Test]
+ public void GenericThrowsWithNullExecuteAndCanExecuteValid ()
+ {
+ Assert.Throws<ArgumentNullException> (() => new Command<string> (null, s => true));
+ }
+
+ [Test]
+ public void GenericThrowsWithValidExecuteAndCanExecuteNull ()
+ {
+ Assert.Throws<ArgumentNullException> (() => new Command<string> (s => { }, null));
+ }
+
+ [Test]
+ public void GenericExecute ()
+ {
+ string result = null;
+ var cmd = new Command<string> (s => result = s);
+
+ cmd.Execute ("Foo");
+ Assert.AreEqual ("Foo", result);
+ }
+
+ [Test]
+ public void GenericExecuteWithCanExecute ()
+ {
+ string result = null;
+ var cmd = new Command<string> (s => result = s, s => true);
+
+ cmd.Execute ("Foo");
+ Assert.AreEqual ("Foo", result);
+ }
+
+ [Test]
+ public void GenericCanExecute ([Values (true, false)] bool expected)
+ {
+ string result = null;
+ var cmd = new Command<string> (s => { }, s => {
+ result = s;
+ return expected;
+ });
+
+ Assert.AreEqual (expected, cmd.CanExecute ("Foo"));
+ Assert.AreEqual ("Foo", result);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ContentFormUnitTests.cs b/Xamarin.Forms.Core.UnitTests/ContentFormUnitTests.cs
new file mode 100644
index 00000000..5b6f3e60
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ContentFormUnitTests.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Linq;
+using NUnit.Framework;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ContentPageUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void PropagateBindingContextBefore()
+ {
+ var stack = new StackLayout();
+
+ var content = new ContentPage();
+ content.Content = stack;
+
+ object context = new object();
+ content.BindingContext = context;
+
+ Assert.AreSame (context, stack.BindingContext);
+ }
+
+ [Test]
+ public void PropagateBindingContextAfter()
+ {
+ var stack = new StackLayout();
+
+ var content = new ContentPage();
+
+ object context = new object();
+ content.BindingContext = context;
+
+ content.Content = stack;
+
+ Assert.AreSame (context, stack.BindingContext);
+ }
+
+ [Test]
+ public void PropagateToolbarItemBindingContextPreAdd ()
+ {
+ var page = new ContentPage ();
+ object context = "hello";
+
+ var toolbarItem = new ToolbarItem ();
+ page.ToolbarItems.Add (toolbarItem);
+
+ page.BindingContext = context;
+
+ Assert.AreEqual (context, toolbarItem.BindingContext);
+ }
+
+ [Test]
+ public void PropagateToolbarItemBindingContextPostAdd ()
+ {
+ var page = new ContentPage ();
+ object context = "hello";
+
+ var toolbarItem = new ToolbarItem ();
+ page.BindingContext = context;
+
+ page.ToolbarItems.Add (toolbarItem);
+
+ Assert.AreEqual (context, toolbarItem.BindingContext);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ContentViewUnitTest.cs b/Xamarin.Forms.Core.UnitTests/ContentViewUnitTest.cs
new file mode 100644
index 00000000..9d7a12e0
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ContentViewUnitTest.cs
@@ -0,0 +1,393 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ContentViewUnitTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void TestConstructor ()
+ {
+ var contentView = new ContentView ();
+
+ Assert.Null (contentView.Content);
+ Assert.AreEqual (Color.Default, contentView.BackgroundColor);
+ Assert.AreEqual (new Thickness (0), contentView.Padding);
+ }
+
+ [Test]
+ public void TestSetChild ()
+ {
+ var contentView = new ContentView ();
+
+ var child1 = new Label ();
+
+ bool added = false;
+
+ contentView.ChildAdded += (sender, e) => added = true;
+
+ contentView.Content = child1;
+
+ Assert.True (added);
+ Assert.AreEqual (child1, contentView.Content);
+
+ added = false;
+ contentView.Content = child1;
+
+ Assert.False (added);
+ }
+
+ [Test]
+ public void TestReplaceChild ()
+ {
+ var contentView = new ContentView ();
+
+ var child1 = new Label ();
+ var child2 = new Label ();
+
+ contentView.Content = child1;
+
+ bool removed = false;
+ bool added = false;
+
+ contentView.ChildRemoved += (sender, e) => removed = true;
+ contentView.ChildAdded += (sender, e) => added = true;
+
+ contentView.Content = child2;
+
+ Assert.True (removed);
+ Assert.True (added);
+ Assert.AreEqual (child2, contentView.Content);
+ }
+
+ [Test]
+ public void TestFrameLayout ()
+ {
+ View child;
+
+ var contentView = new ContentView {
+ Padding = new Thickness (10),
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 200,
+ IsPlatformEnabled = true
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ Assert.AreEqual (new Size (120, 220), contentView.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request);
+
+ contentView.Layout (new Rectangle (0, 0, 300, 300));
+
+ Assert.AreEqual (new Rectangle (10, 10, 280, 280), child.Bounds);
+ }
+
+ [Test]
+ public void WidthRequest ()
+ {
+ View child;
+
+ var contentView = new ContentView {
+ Padding = new Thickness (10),
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 200,
+ IsPlatformEnabled = true
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform (),
+ WidthRequest = 20
+ };
+
+ Assert.AreEqual (new Size (40, 220), contentView.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request);
+ }
+
+ [Test]
+ public void HeightRequest ()
+ {
+ View child;
+
+ var contentView = new ContentView {
+ Padding = new Thickness (10),
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 200,
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform (),
+ HeightRequest = 20
+ };
+
+ Assert.AreEqual (new Size (120, 40), contentView.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request);
+ }
+
+ [Test]
+ public void LayoutVerticallyCenter()
+ {
+ View child;
+
+ var contentView = new ContentView {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 100,
+ IsPlatformEnabled = true,
+ VerticalOptions = LayoutOptions.Center
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ contentView.Layout (new Rectangle(0,0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (0, 50, 200, 100), child.Bounds);
+ }
+
+ [Test]
+ public void LayoutVerticallyBegin()
+ {
+ View child;
+
+ var contentView = new ContentView {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 100,
+ IsPlatformEnabled = true,
+ VerticalOptions = LayoutOptions.Start
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ contentView.Layout (new Rectangle(0,0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (0, 0, 200, 100), child.Bounds);
+ }
+
+ [Test]
+ public void LayoutVerticallyEnd()
+ {
+ View child;
+
+ var contentView = new ContentView {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 100,
+ IsPlatformEnabled = true,
+ VerticalOptions = LayoutOptions.End
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ contentView.Layout (new Rectangle(0,0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (0, 100, 200, 100), child.Bounds);
+ }
+
+ [Test]
+ public void LayoutHorizontallyCenter()
+ {
+ View child;
+
+ var contentView = new ContentView {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 100,
+ IsPlatformEnabled = true,
+ HorizontalOptions = LayoutOptions.Center
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ contentView.Layout (new Rectangle(0,0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (50, 0, 100, 200), child.Bounds);
+ }
+
+ [Test]
+ public void LayoutHorizontallyBegin()
+ {
+ View child;
+
+ var contentView = new ContentView {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 100,
+ IsPlatformEnabled = true,
+ HorizontalOptions = LayoutOptions.Start
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ contentView.Layout (new Rectangle(0,0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (0, 0, 100, 200), child.Bounds);
+ }
+
+ [Test]
+ public void LayoutHorizontallyEnd()
+ {
+ View child;
+
+ var contentView = new ContentView {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 100,
+ IsPlatformEnabled = true,
+ HorizontalOptions = LayoutOptions.End
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ contentView.Layout (new Rectangle(0,0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (100, 0, 100, 200), child.Bounds);
+ }
+
+ [Test]
+ public void NullTemplateDirectlyHosts ()
+ {
+ // order of setting properties carefully picked to emulate running on real backend
+ var platform = new UnitPlatform ();
+
+ var contentView = new ContentView ();
+ var child = new View ();
+
+ contentView.Content = child;
+ contentView.Platform = platform;
+
+ Assert.AreEqual (child, contentView.LogicalChildren[0]);
+ }
+
+ class SimpleTemplate : StackLayout
+ {
+ public SimpleTemplate ()
+ {
+ Children.Add (new Label ());
+ Children.Add (new ContentPresenter ());
+ }
+ }
+
+
+ [Test]
+ public void TemplateInflates ()
+ {
+ var platform = new UnitPlatform ();
+
+ var contentView = new ContentView ();
+
+ contentView.ControlTemplate = new ControlTemplate (typeof (SimpleTemplate));
+ contentView.Platform = platform;
+
+ Assert.That (contentView.LogicalChildren[0], Is.TypeOf<SimpleTemplate> ());
+ }
+
+ [Test]
+ public void PacksContent ()
+ {
+ var platform = new UnitPlatform ();
+
+ var contentView = new ContentView ();
+ var child = new View ();
+
+ contentView.ControlTemplate = new ControlTemplate (typeof (SimpleTemplate));
+ contentView.Content = child;
+ contentView.Platform = platform;
+
+ Assume.That (contentView.LogicalChildren[0], Is.TypeOf<SimpleTemplate> ());
+ Assert.That (contentView.Descendants (), Contains.Item (child));
+ }
+
+ [Test]
+ public void DoesNotInheritBindingContextToTemplate ()
+ {
+ var platform = new UnitPlatform ();
+
+ var contentView = new ContentView ();
+ var child = new View ();
+
+ contentView.ControlTemplate = new ControlTemplate (typeof (SimpleTemplate));
+ contentView.Content = child;
+ contentView.Platform = platform;
+
+ var bc = "Test";
+ contentView.BindingContext = bc;
+
+ Assert.AreNotEqual (bc, contentView.LogicalChildren[0].BindingContext);
+ Assert.IsNull (contentView.LogicalChildren[0].BindingContext);
+ }
+
+ [Test]
+ public void ContentDoesGetBindingContext ()
+ {
+ var platform = new UnitPlatform ();
+
+ var contentView = new ContentView ();
+ var child = new View ();
+
+ contentView.ControlTemplate = new ControlTemplate (typeof (SimpleTemplate));
+ contentView.Content = child;
+ contentView.Platform = platform;
+
+ var bc = "Test";
+ contentView.BindingContext = bc;
+
+ Assert.AreEqual (bc, child.BindingContext);
+ }
+
+ [Test]
+ public void ContentParentIsNotInsideTempalte ()
+ {
+ var platform = new UnitPlatform ();
+
+ var contentView = new ContentView ();
+ var child = new View ();
+
+ contentView.ControlTemplate = new ControlTemplate (typeof (SimpleTemplate));
+ contentView.Content = child;
+ contentView.Platform = platform;
+
+ Assert.AreEqual (contentView, child.Parent);
+ }
+
+ [Test]
+ public void NonTemplatedContentInheritsBindingContext ()
+ {
+ var platform = new UnitPlatform ();
+
+ var contentView = new ContentView ();
+ var child = new View ();
+
+ contentView.Content = child;
+ contentView.Platform = platform;
+ contentView.BindingContext = "Foo";
+
+ Assert.AreEqual ("Foo", child.BindingContext);
+ }
+ }
+
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ContraintTypeConverterTests.cs b/Xamarin.Forms.Core.UnitTests/ContraintTypeConverterTests.cs
new file mode 100644
index 00000000..e34f9a4a
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ContraintTypeConverterTests.cs
@@ -0,0 +1,16 @@
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ContraintTypeConverterTests : BaseTestFixture
+ {
+ [Test]
+ public void ConvertFrom ()
+ {
+ var converter = new ConstraintTypeConverter ();
+ Assert.AreEqual (Constraint.Constant (1.0).Compute (null), ((Constraint)converter.ConvertFromInvariantString ("1.0")).Compute (null));
+ Assert.AreEqual (Constraint.Constant (1.3).Compute (null), ((Constraint)converter.ConvertFromInvariantString ("1.3")).Compute (null));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/ControlTemplateTests.cs b/Xamarin.Forms.Core.UnitTests/ControlTemplateTests.cs
new file mode 100644
index 00000000..ffced2d2
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ControlTemplateTests.cs
@@ -0,0 +1,181 @@
+using System;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using NUnit.Framework;
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ControlTemplateTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ public class ContentControl : StackLayout
+ {
+ public ContentControl ()
+ {
+ var label = new Label ();
+ label.SetBinding (Label.TextProperty, new TemplateBinding ("Name"));
+
+ Children.Add (label);
+ Children.Add (new ContentPresenter ());
+ }
+ }
+
+ public class PresenterWrapper : ContentView
+ {
+ public PresenterWrapper ()
+ {
+ Content = new ContentPresenter ();
+ }
+ }
+
+ public class TestView : ContentView
+ {
+ public static readonly BindableProperty NameProperty =
+ BindableProperty.Create (nameof (Name), typeof (string), typeof (TestView), default(string));
+
+ public string Name
+ {
+ get { return (string)GetValue (NameProperty); }
+ set { SetValue (NameProperty, value); }
+ }
+
+ public TestView ()
+ {
+ ControlTemplate = new ControlTemplate(typeof (ContentControl));
+ }
+ }
+
+ [Test]
+ public void ResettingControlTemplateNullsPresenterContent ()
+ {
+ var testView = new TestView {
+ Platform = new UnitPlatform (),
+ ControlTemplate = new ControlTemplate (typeof (PresenterWrapper))
+ };
+
+ var label = new Label ();
+ testView.Content = label;
+ var originalPresenter = (ContentPresenter)testView.LogicalChildren[0].LogicalChildren[0];
+
+ Assert.AreEqual (label, originalPresenter.Content);
+
+ testView.ControlTemplate = new ControlTemplate (typeof (PresenterWrapper));
+
+ Assert.IsNull (originalPresenter.Content);
+ }
+
+ [Test]
+ public void NestedTemplateBindings ()
+ {
+ var testView = new TestView ();
+ var label = (Label)testView.LogicalChildren[0].LogicalChildren[0];
+
+ testView.Platform = new UnitPlatform ();
+ Assert.IsNull (label.Text);
+
+ testView.Name = "Bar";
+ Assert.AreEqual ("Bar", label.Text);
+ }
+
+ [Test]
+ public void ParentControlTemplateDoesNotClearChildTemplate ()
+ {
+ var parentView = new TestView ();
+ var childView = new TestView ();
+ parentView.Platform = new UnitPlatform ();
+
+ parentView.Content = childView;
+ childView.Content = new Button ();
+ var childPresenter = (ContentPresenter)childView.LogicalChildren[0].LogicalChildren[1];
+
+ parentView.ControlTemplate = new ControlTemplate (typeof (ContentControl));
+ Assert.IsNotNull (childPresenter.Content);
+ }
+
+ [Test]
+ public void NullConstructor ()
+ {
+ Assert.Throws<ArgumentNullException> (() => new ControlTemplate (null));
+ }
+
+ class TestPage : ContentPage
+ {
+ public static readonly BindableProperty NameProperty =
+ BindableProperty.Create (nameof (Name), typeof (string), typeof (TestPage), null);
+
+ public string Name
+ {
+ get { return (string)GetValue (NameProperty); }
+ set { SetValue (NameProperty, value); }
+ }
+ }
+
+ class TestContent : ContentView
+ {
+ public TestContent ()
+ {
+ Content = new Entry ();
+ Content.SetBinding (Entry.TextProperty, new TemplateBinding ("Name", BindingMode.TwoWay));
+ }
+ }
+
+ class ViewModel : INotifyPropertyChanged
+ {
+ string name;
+
+ public string Name
+ {
+ get { return name; }
+ set
+ {
+ if (name == value)
+ return;
+ name = value;
+ OnPropertyChanged ();
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChanged?.Invoke (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+
+ [Test]
+ public void DoubleTwoWayBindingWorks ()
+ {
+ var page = new TestPage ();
+ page.Platform = new UnitPlatform ();
+ var viewModel = new ViewModel {
+ Name = "Jason"
+ };
+ page.BindingContext = viewModel;
+
+ page.ControlTemplate = new ControlTemplate (typeof (TestContent));
+ page.SetBinding (TestPage.NameProperty, "Name");
+
+ var entry = ((ContentView)page.LogicalChildren[0]).Content as Entry;
+ ((IElementController)entry).SetValueFromRenderer (Entry.TextProperty, "Bar");
+ viewModel.Name = "Raz";
+
+ Assert.AreEqual ("Raz", entry.Text);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/DataTemplateSelectorTests.cs b/Xamarin.Forms.Core.UnitTests/DataTemplateSelectorTests.cs
new file mode 100644
index 00000000..85779956
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/DataTemplateSelectorTests.cs
@@ -0,0 +1,79 @@
+using System;
+using NUnit.Framework;
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class DataTemplateSelectorTests : BaseTestFixture
+ {
+ class TemplateOne : DataTemplate
+ {
+ public TemplateOne () : base (typeof (ViewCell))
+ {
+
+ }
+ }
+
+ class TemplateTwo : DataTemplate
+ {
+ public TemplateTwo () : base (typeof (EntryCell))
+ {
+
+ }
+ }
+
+ class TestDTS : DataTemplateSelector
+ {
+ public TestDTS ()
+ {
+ templateOne = new TemplateOne ();
+ templateTwo = new TemplateTwo ();
+ }
+
+ protected override DataTemplate OnSelectTemplate (object item, BindableObject container)
+ {
+ if (item is double)
+ return templateOne;
+ if (item is byte)
+ return new TestDTS ();
+ return templateTwo;
+ }
+
+ readonly DataTemplate templateOne;
+ readonly DataTemplate templateTwo;
+ }
+
+ [Test]
+ public void Constructor ()
+ {
+ var dts = new TestDTS ();
+ }
+
+ [Test]
+ public void ReturnsCorrectType ()
+ {
+ var dts = new TestDTS ();
+ Assert.IsInstanceOf<TemplateOne> (dts.SelectTemplate (1d, null));
+ Assert.IsInstanceOf<TemplateTwo> (dts.SelectTemplate ("test", null));
+ }
+
+ [Test]
+ public void ListViewSupport ()
+ {
+ var listView = new ListView(ListViewCachingStrategy.RecycleElement);
+ listView.ItemsSource = new object[] { 0d, "test" };
+
+ listView.ItemTemplate = new TestDTS ();
+ Assert.IsInstanceOf<ViewCell> (listView.TemplatedItems[0]);
+ Assert.IsInstanceOf<EntryCell> (listView.TemplatedItems[1]);
+ }
+
+ [Test]
+ public void NestingThrowsException ()
+ {
+ var dts = new TestDTS ();
+ Assert.Throws<NotSupportedException> (() => dts.SelectTemplate ((byte)0, null));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/DataTemplateTests.cs b/Xamarin.Forms.Core.UnitTests/DataTemplateTests.cs
new file mode 100644
index 00000000..24bf6a06
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/DataTemplateTests.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections.Generic;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class DataTemplateTests : BaseTestFixture
+ {
+ [Test]
+ public void CtorInvalid()
+ {
+ Assert.Throws<ArgumentNullException> (() => new DataTemplate ((Func<object>)null),
+ "Allowed null creator delegate");
+
+ Assert.Throws<ArgumentNullException> (() => new DataTemplate ((Type)null),
+ "Allowed null type");
+ }
+
+ [Test]
+ public void CreateContent()
+ {
+ var template = new DataTemplate (() => new MockBindable());
+ object obj = template.CreateContent();
+
+ Assert.IsNotNull (obj);
+ Assert.That (obj, Is.InstanceOf<MockBindable>());
+ }
+
+ [Test]
+ public void CreateContentType()
+ {
+ var template = new DataTemplate (typeof (MockBindable));
+ object obj = template.CreateContent();
+
+ Assert.IsNotNull (obj);
+ Assert.That (obj, Is.InstanceOf<MockBindable>());
+ }
+
+ [Test]
+ public void CreateContentValues()
+ {
+ var template = new DataTemplate (typeof (MockBindable)) {
+ Values = { { MockBindable.TextProperty, "value" } }
+ };
+
+ MockBindable bindable = (MockBindable)template.CreateContent();
+ Assert.That (bindable.GetValue (MockBindable.TextProperty), Is.EqualTo ("value"));
+ }
+
+ [Test]
+ public void CreateContentBindings()
+ {
+ var template = new DataTemplate (() => new MockBindable()) {
+ Bindings = { { MockBindable.TextProperty, new Binding (".") } }
+ };
+
+ MockBindable bindable = (MockBindable)template.CreateContent();
+ bindable.BindingContext = "text";
+ Assert.That (bindable.GetValue (MockBindable.TextProperty), Is.EqualTo ("text"));
+ }
+
+ [Test]
+ public void SetBindingInvalid()
+ {
+ var template = new DataTemplate (typeof (MockBindable));
+ Assert.That (() => template.SetBinding (null, new Binding (".")), Throws.InstanceOf<ArgumentNullException>());
+ Assert.That (() => template.SetBinding (MockBindable.TextProperty, null), Throws.InstanceOf<ArgumentNullException>());
+ }
+
+ [Test]
+ public void SetBindingOverridesValue()
+ {
+ var template = new DataTemplate (typeof (MockBindable));
+ template.SetValue (MockBindable.TextProperty, "value");
+ template.SetBinding (MockBindable.TextProperty, new Binding ("."));
+
+ MockBindable bindable = (MockBindable) template.CreateContent();
+ Assume.That (bindable.GetValue (MockBindable.TextProperty), Is.EqualTo (bindable.BindingContext));
+
+ bindable.BindingContext = "binding";
+ Assert.That (bindable.GetValue (MockBindable.TextProperty), Is.EqualTo ("binding"));
+ }
+
+ [Test]
+ public void SetValueOverridesBinding()
+ {
+ var template = new DataTemplate (typeof (MockBindable));
+ template.SetBinding (MockBindable.TextProperty, new Binding ("."));
+ template.SetValue (MockBindable.TextProperty, "value");
+
+ MockBindable bindable = (MockBindable) template.CreateContent();
+ Assert.That (bindable.GetValue (MockBindable.TextProperty), Is.EqualTo ("value"));
+ bindable.BindingContext = "binding";
+ Assert.That (bindable.GetValue (MockBindable.TextProperty), Is.EqualTo ("value"));
+ }
+
+ [Test]
+ public void SetValueInvalid()
+ {
+ var template = new DataTemplate (typeof (MockBindable));
+ Assert.That (() => template.SetValue (null, "string"), Throws.InstanceOf<ArgumentNullException>());
+ }
+
+ [Test]
+ public void SetValueAndBinding ()
+ {
+ var template = new DataTemplate (typeof (TextCell)) {
+ Bindings = {
+ {TextCell.TextProperty, new Binding ("Text")}
+ },
+ Values = {
+ {TextCell.TextProperty, "Text"}
+ }
+ };
+ Assert.That (() => template.CreateContent (), Throws.InstanceOf<InvalidOperationException> ());
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/DataTriggerTests.cs b/Xamarin.Forms.Core.UnitTests/DataTriggerTests.cs
new file mode 100644
index 00000000..585bebcf
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/DataTriggerTests.cs
@@ -0,0 +1,146 @@
+using NUnit.Framework;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class DataTriggerTests : BaseTestFixture
+ {
+ class MockElement : VisualElement
+ {
+ }
+
+ [Test]
+ public void SettersAppliedOnAttachIfConditionIsTrue ()
+ {
+ var setterbp = BindableProperty.Create ("bar", typeof(string), typeof(BindableObject), null);
+ var element = new MockElement ();
+ var datatrigger = new DataTrigger (typeof(VisualElement)) {
+ Binding = new Binding ("foo"),
+ Value = "foobar",
+ Setters = {
+ new Setter { Property = setterbp, Value = "qux" },
+ }
+ };
+
+ element.SetValue (setterbp, "default");
+ element.BindingContext = new {foo = "foobar"};
+ Assert.AreEqual ("default", element.GetValue (setterbp));
+ element.Triggers.Add (datatrigger);
+ Assert.AreEqual ("qux", element.GetValue (setterbp));
+ }
+
+ [Test]
+ public void SettersUnappliedOnDetach ()
+ {
+ var setterbp = BindableProperty.Create ("bar", typeof(string), typeof(BindableObject), null);
+ var element = new MockElement ();
+ var datatrigger = new DataTrigger (typeof(VisualElement)) {
+ Binding = new Binding ("foo"),
+ Value = "foobar",
+ Setters = {
+ new Setter { Property = setterbp, Value = "qux" },
+ }
+ };
+
+ element.SetValue (setterbp, "default");
+ element.Triggers.Add (datatrigger);
+
+ Assert.AreEqual ("default", element.GetValue (setterbp));
+ element.BindingContext = new {foo = "foobar"};
+ Assert.AreEqual ("qux", element.GetValue (setterbp));
+ element.Triggers.Remove (datatrigger);
+ Assert.AreEqual ("default", element.GetValue (setterbp));
+ }
+
+ [Test]
+ public void SettersAppliedOnConditionChanged ()
+ {
+ var setterbp = BindableProperty.Create ("bar", typeof(string), typeof(BindableObject), null);
+ var element = new MockElement ();
+ var trigger = new DataTrigger (typeof (VisualElement)){
+ Binding = new Binding ("foo"),
+ Value = "foobar",
+ Setters = {
+ new Setter { Property = setterbp, Value = "qux" },
+ }
+ };
+
+ element.SetValue (setterbp, "default");
+ element.Triggers.Add (trigger);
+
+ Assert.AreEqual ("default", element.GetValue (setterbp));
+ element.BindingContext = new {foo = "foobar"};
+ Assert.AreEqual ("qux", element.GetValue (setterbp));
+ element.BindingContext = new {foo = ""};
+ Assert.AreEqual ("default", element.GetValue (setterbp));
+ }
+
+ [Test]
+ public void TriggersAppliedOnMultipleElements ()
+ {
+ var setterbp = BindableProperty.Create ("bar", typeof(string), typeof(BindableObject), null);
+ var trigger = new DataTrigger (typeof(VisualElement)) {
+ Binding = new Binding ("foo"),
+ Value = "foobar",
+ Setters = {
+ new Setter { Property = setterbp, Value = "qux" },
+ }
+ };
+ var element0 = new MockElement { Triggers = { trigger } };
+ var element1 = new MockElement { Triggers = { trigger } };
+
+ element0.BindingContext = element1.BindingContext = new {foo = "foobar"};
+ Assert.AreEqual ("qux", element0.GetValue (setterbp));
+ Assert.AreEqual ("qux", element1.GetValue (setterbp));
+ }
+
+ [Test]
+ //https://bugzilla.xamarin.com/show_bug.cgi?id=30074
+ public void AllTriggersUnappliedBeforeApplying ()
+ {
+ var boxview = new BoxView {
+ Triggers = {
+ new DataTrigger (typeof(BoxView)) {
+ Binding = new Binding ("."),
+ Value = "Complete",
+ Setters = {
+ new Setter { Property = BoxView.ColorProperty, Value = Color.Green },
+ new Setter { Property = VisualElement.OpacityProperty, Value = .5 },
+ }
+ },
+ new DataTrigger (typeof(BoxView)) {
+ Binding = new Binding ("."),
+ Value = "MissingInfo",
+ Setters = {
+ new Setter { Property = BoxView.ColorProperty, Value = Color.Yellow },
+ }
+ },
+ new DataTrigger (typeof(BoxView)) {
+ Binding = new Binding ("."),
+ Value = "Error",
+ Setters = {
+ new Setter { Property = BoxView.ColorProperty, Value = Color.Red },
+ }
+ },
+ }
+ };
+
+ boxview.BindingContext = "Complete";
+ Assert.AreEqual (Color.Green, boxview.Color);
+ Assert.AreEqual (.5, boxview.Opacity);
+
+ boxview.BindingContext = "MissingInfo";
+ Assert.AreEqual (Color.Yellow, boxview.Color);
+ Assert.AreEqual (1, boxview.Opacity);
+
+ boxview.BindingContext = "Error";
+ Assert.AreEqual (Color.Red, boxview.Color);
+ Assert.AreEqual (1, boxview.Opacity);
+
+ boxview.BindingContext = "Complete";
+ Assert.AreEqual (Color.Green, boxview.Color);
+ Assert.AreEqual (.5, boxview.Opacity);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/DatePickerUnitTest.cs b/Xamarin.Forms.Core.UnitTests/DatePickerUnitTest.cs
new file mode 100644
index 00000000..97bbf410
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/DatePickerUnitTest.cs
@@ -0,0 +1,178 @@
+using System;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class DatePickerUnitTest : BaseTestFixture
+ {
+ [Test]
+ public void TestMinimumDateException ()
+ {
+ DatePicker picker = new DatePicker ();
+
+ picker.MinimumDate = new DateTime (1950, 1, 1);
+
+ Assert.AreEqual (new DateTime (1950, 1, 1), picker.MinimumDate);
+
+ Assert.That (() => picker.MinimumDate = new DateTime (2200, 1, 1), Throws.ArgumentException);
+ }
+
+ [Test]
+ public void TestMaximumDateException ()
+ {
+ DatePicker picker = new DatePicker ();
+
+ picker.MaximumDate = new DateTime (2050, 1, 1);
+
+ Assert.AreEqual (new DateTime (2050, 1, 1), picker.MaximumDate);
+
+ Assert.That (() => picker.MaximumDate = new DateTime (1800, 1, 1), Throws.ArgumentException);
+ }
+
+ [Test]
+ public void TestMaximumDateClamping ()
+ {
+ DatePicker picker = new DatePicker ();
+
+ picker.Date = new DateTime (2050, 1, 1);
+
+ Assert.AreEqual (new DateTime (2050, 1, 1), picker.Date);
+
+ bool dateChanged = false;
+ bool maximumDateChanged = false;
+ picker.PropertyChanged += (sender, e) => {
+ switch (e.PropertyName) {
+ case "MaximumDate":
+ maximumDateChanged = true;
+ break;
+ case "Date":
+ dateChanged = true;
+ Assert.IsFalse (maximumDateChanged);
+ break;
+ }
+ };
+
+ var newDate = new DateTime (2000, 1, 1);
+ picker.MaximumDate = newDate;
+
+ Assert.IsTrue (maximumDateChanged);
+ Assert.IsTrue (dateChanged);
+
+ Assert.AreEqual (newDate, picker.MaximumDate);
+ Assert.AreEqual (newDate, picker.Date);
+ Assert.AreEqual (picker.MaximumDate, picker.Date);
+ }
+
+ [Test]
+ public void TestMinimumDateClamping ()
+ {
+ DatePicker picker = new DatePicker ();
+
+ picker.Date = new DateTime (1950, 1, 1);
+
+ Assert.AreEqual (new DateTime (1950, 1, 1), picker.Date);
+
+ bool dateChanged = false;
+ bool minimumDateChanged = false;
+ picker.PropertyChanged += (sender, e) => {
+ switch (e.PropertyName) {
+ case "MinimumDate":
+ minimumDateChanged = true;
+ break;
+ case "Date":
+ dateChanged = true;
+ Assert.IsFalse (minimumDateChanged);
+ break;
+ }
+ };
+
+ var newDate = new DateTime (2000, 1, 1);
+ picker.MinimumDate = newDate;
+
+ Assert.IsTrue (minimumDateChanged);
+ Assert.IsTrue (dateChanged);
+
+ Assert.AreEqual (newDate, picker.MinimumDate);
+ Assert.AreEqual (newDate, picker.Date);
+ Assert.AreEqual (picker.MinimumDate, picker.Date);
+ }
+
+ [Test]
+ public void TestDateClamping ()
+ {
+ DatePicker picker = new DatePicker ();
+
+ picker.Date = new DateTime (1500, 1, 1);
+
+ Assert.AreEqual (picker.MinimumDate, picker.Date);
+
+ picker.Date = new DateTime (2500, 1, 1);
+
+ Assert.AreEqual (picker.MaximumDate, picker.Date);
+ }
+
+ [Test]
+ public void TestDateSelected ()
+ {
+ var picker = new DatePicker ();
+
+ bool selected = false;
+ picker.DateSelected += (sender, arg) => selected = true;
+
+ // we can be fairly sure it wont ever be 2008 again
+ picker.Date = new DateTime (2008, 5, 5);
+
+ Assert.True (selected);
+ }
+
+ static object[] DateTimes = {
+ new object[] { new DateTime (2006, 12, 20), new DateTime (2011, 11, 30) },
+ new object[] { new DateTime (1900, 1, 1), new DateTime (1999, 01, 15) }, // Minimum Date
+ new object[] { new DateTime (2006, 12, 20), new DateTime (2100, 12, 31) } // Maximum Date
+ };
+
+ [Test, TestCaseSource("DateTimes")]
+ public void DatePickerSelectedEventArgs (DateTime initialDate, DateTime finalDate)
+ {
+ var datePicker = new DatePicker ();
+ datePicker.Date = initialDate;
+
+ DatePicker pickerFromSender = null;
+ DateTime oldDate = new DateTime ();
+ DateTime newDate = new DateTime ();
+
+ datePicker.DateSelected += (s, e) => {
+ pickerFromSender = (DatePicker)s;
+ oldDate = e.OldDate;
+ newDate = e.NewDate;
+ };
+
+ datePicker.Date = finalDate;
+
+ Assert.AreEqual (datePicker, pickerFromSender);
+ Assert.AreEqual (initialDate, oldDate);
+ Assert.AreEqual (finalDate, newDate);
+ }
+
+ [Test]
+ //https://bugzilla.xamarin.com/show_bug.cgi?id=32144
+ public void SetNullValueDoesNotThrow ()
+ {
+ var datePicker = new DatePicker ();
+ Assert.DoesNotThrow (() => datePicker.SetValue (DatePicker.DateProperty, null));
+ Assert.AreEqual (DatePicker.DateProperty.DefaultValue, datePicker.Date);
+ }
+
+ [Test]
+ public void SetNullableDateTime ()
+ {
+ var datePicker = new DatePicker ();
+ var dateTime = new DateTime (2015, 7, 21);
+ DateTime? nullableDateTime = dateTime;
+ datePicker.SetValue (DatePicker.DateProperty, nullableDateTime);
+ Assert.AreEqual (dateTime, datePicker.Date);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/DependencyServiceTests.cs b/Xamarin.Forms.Core.UnitTests/DependencyServiceTests.cs
new file mode 100644
index 00000000..30e38b62
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/DependencyServiceTests.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NUnit.Framework;
+using Xamarin.Forms;
+using Xamarin.Forms.Core.UnitTests;
+
+[assembly: Dependency(typeof (DependencyTestImpl))]
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ public interface IDependencyTest
+ {
+ bool Works { get; }
+ }
+
+ public interface IDependencyTestRegister
+ {
+ bool Works { get; }
+ }
+
+ public interface IUnsatisfied
+ {
+ bool Broken { get; }
+ }
+
+ public class DependencyTestImpl : IDependencyTest
+ {
+ public bool Works { get { return true; } }
+ }
+
+ public class DependencyTestRegisterImpl : IDependencyTestRegister
+ {
+ public bool Works { get { return true; } }
+ }
+
+ public class DependencyTestRegisterImpl2 : IDependencyTestRegister
+ {
+ public bool Works { get { return false; } }
+ }
+
+ public class DependencyServiceTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void GetGlobalInstance ()
+ {
+ var global = DependencyService.Get<IDependencyTest> ();
+
+ Assert.NotNull (global);
+
+ var secondFetch = DependencyService.Get<IDependencyTest> ();
+
+ Assert.True (ReferenceEquals (global, secondFetch));
+ }
+
+ [Test]
+ public void NewInstanceIsNotGlobalInstance ()
+ {
+ var global = DependencyService.Get<IDependencyTest> ();
+
+ Assert.NotNull (global);
+
+ var secondFetch = DependencyService.Get<IDependencyTest> (DependencyFetchTarget.NewInstance);
+
+ Assert.False (ReferenceEquals (global, secondFetch));
+ }
+
+ [Test]
+ public void NewInstanceIsAlwaysNew ()
+ {
+ var firstFetch = DependencyService.Get<IDependencyTest> (DependencyFetchTarget.NewInstance);
+
+ Assert.NotNull (firstFetch);
+
+ var secondFetch = DependencyService.Get<IDependencyTest> (DependencyFetchTarget.NewInstance);
+
+ Assert.False (ReferenceEquals (firstFetch, secondFetch));
+ }
+
+ [Test]
+ public void UnsatisfiedReturnsNull ()
+ {
+ Assert.Null (DependencyService.Get<IUnsatisfied> ());
+ }
+
+ [Test]
+ public void RegisterTypeImplementation ()
+ {
+ DependencyService.Register<DependencyTestRegisterImpl> ();
+ var global = DependencyService.Get<DependencyTestRegisterImpl> ();
+ Assert.NotNull (global);
+ }
+
+
+ [Test]
+ public void RegisterInterfaceAndImplementations ()
+ {
+ DependencyService.Register<IDependencyTestRegister, DependencyTestRegisterImpl2> ();
+ var global = DependencyService.Get<IDependencyTestRegister> ();
+ Assert.IsInstanceOf<DependencyTestRegisterImpl2> (global);
+ }
+
+ [Test]
+ public void RegisterInterfaceAndOverrideImplementations ()
+ {
+ DependencyService.Register<IDependencyTestRegister, DependencyTestRegisterImpl> ();
+ DependencyService.Register<IDependencyTestRegister, DependencyTestRegisterImpl2> ();
+ var global = DependencyService.Get<IDependencyTestRegister> ();
+ Assert.IsInstanceOf<DependencyTestRegisterImpl2> (global);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/DistanceTests.cs b/Xamarin.Forms.Core.UnitTests/DistanceTests.cs
new file mode 100644
index 00000000..829bf957
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/DistanceTests.cs
@@ -0,0 +1,197 @@
+using System;
+using NUnit.Framework;
+using Xamarin.Forms.Maps;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class DistanceTests : BaseTestFixture
+ {
+ [Test]
+ public void Constructor ()
+ {
+ var distance = new Distance (25);
+ Assert.AreEqual (25, distance.Meters);
+ }
+
+ [Test]
+ public void ConstructFromKilometers()
+ {
+ const double EPSILON = 0.001;
+
+ Distance distance = Distance.FromKilometers(2);
+
+ Assert.True(Math.Abs(distance.Kilometers - 2) < EPSILON);
+ Assert.True(Math.Abs(distance.Meters - 2000) < EPSILON);
+ Assert.True(Math.Abs(distance.Miles - 1.24274) < EPSILON);
+ }
+
+ [Test]
+ public void ConstructFromMeters()
+ {
+ const double EPSILON = 0.001;
+
+ Distance distance = Distance.FromMeters(10560);
+
+ Assert.True(Math.Abs(distance.Meters - 10560) < EPSILON);
+ Assert.True(Math.Abs(distance.Miles - 6.5616798) < EPSILON);
+ Assert.True(Math.Abs(distance.Kilometers - 10.56) < EPSILON);
+ }
+
+ [Test]
+ public void ConstructFromMiles()
+ {
+ const double EPSILON = 0.001;
+
+ // Reached the limit of double precision using the number
+ // of miles of the earth's circumference
+ const double EPSILON_FOR_LARGE_MILES_TO_METERS = 16;
+
+ // Reached the limit of double precision
+ const double EPSILON_FOR_LARGE_MILES_TO_KM = 0.1;
+
+ Distance distance = Distance.FromMiles(3963.1676);
+
+ Assert.True(Math.Abs(distance.Miles - 3963.1676) < EPSILON);
+ Assert.True(Math.Abs(distance.Meters - 6378099.99805) < EPSILON_FOR_LARGE_MILES_TO_METERS);
+ Assert.True(Math.Abs(distance.Kilometers - 6378.09999805) < EPSILON_FOR_LARGE_MILES_TO_KM);
+ }
+
+ [Test]
+ public void EqualityOp([Range(5, 9)] double x, [Range(5, 9)] double y)
+ {
+ bool result = Distance.FromMeters(x) == Distance.FromMeters(y);
+
+ if (x == y)
+ Assert.True(result);
+ else
+ Assert.False(result);
+ }
+
+ [Test]
+ public void Equals([Range(3, 7)] double x, [Range(3, 7)] double y)
+ {
+ bool result = Distance.FromMiles(x).Equals(Distance.FromMiles(y));
+ if (x == y)
+ Assert.True(result);
+ else
+ Assert.False(result);
+ }
+
+ [Test]
+ public void EqualsNull()
+ {
+ Assert.False(Distance.FromMeters(5).Equals(null));
+ }
+
+ [Test]
+ public void GettingAndSettingKilometers()
+ {
+ const double EPSILON = 0.001;
+
+ Distance distance = Distance.FromKilometers(1891);
+ Assert.True(Math.Abs(distance.Kilometers - 1891) < EPSILON);
+ }
+
+ [Test]
+ public void GettingAndSettingMeters()
+ {
+ const double EPSILON = 0.001;
+
+ Distance distance = Distance.FromMeters(123434);
+ Assert.True(Math.Abs(distance.Meters - 123434) < EPSILON);
+ }
+
+ [Test]
+ public void GettingAndSettingMiles()
+ {
+ const double EPSILON = 0.001;
+
+ Distance distance = Distance.FromMiles(515);
+ Assert.True(Math.Abs(distance.Miles - 515) < EPSILON);
+ }
+
+ [Test]
+ public void HashCode([Range(4, 5)] double x, [Range(4, 5)] double y)
+ {
+ Distance distance1 = Distance.FromMiles(x);
+ Distance distance2 = Distance.FromMiles(y);
+
+ bool result = distance1.GetHashCode() == distance2.GetHashCode();
+
+ if (x == y)
+ Assert.True(result);
+ else
+ Assert.False(result);
+ }
+
+ [Test]
+ public void InequalityOp([Range(5, 9)] double x, [Range(5, 9)] double y)
+ {
+ bool result = Distance.FromMeters(x) != Distance.FromMeters(y);
+
+ if (x != y)
+ Assert.True(result);
+ else
+ Assert.False(result);
+ }
+
+ [Test]
+ public void ObjectInitializerKilometers()
+ {
+ const double EPSILON = 0.001;
+
+ Distance distance = Distance.FromKilometers(10);
+ Assert.True(Math.Abs(distance.Meters - 10000) < EPSILON);
+ }
+
+ [Test]
+ public void ObjectInitializerMeters()
+ {
+ const double EPSILON = 0.001;
+
+ Distance distance = Distance.FromMeters(1057);
+ Assert.True(Math.Abs(distance.Kilometers - 1.057) < EPSILON);
+ }
+
+ [Test]
+ public void ObjectInitializerMiles()
+ {
+ const double EPSILON = 0.001;
+
+ Distance distance = Distance.FromMiles(100);
+ Assert.True(Math.Abs(distance.Meters - 160934.4) < EPSILON);
+ }
+
+ [Test]
+ public void ClampFromMeters ()
+ {
+ var distance = Distance.FromMeters (-1);
+
+ Assert.AreEqual (0, distance.Meters);
+ }
+
+ [Test]
+ public void ClampFromMiles ()
+ {
+ var distance = Distance.FromMiles (-1);
+
+ Assert.AreEqual (0, distance.Meters);
+ }
+
+ [Test]
+ public void ClampFromKilometers ()
+ {
+ var distance = Distance.FromKilometers (-1);
+
+ Assert.AreEqual (0, distance.Meters);
+ }
+
+ [Test]
+ public void Equals ()
+ {
+ Assert.True (Distance.FromMiles (2).Equals ((object) Distance.FromMiles (2)));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/DynamicBindingContextTests.cs b/Xamarin.Forms.Core.UnitTests/DynamicBindingContextTests.cs
new file mode 100644
index 00000000..53618909
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/DynamicBindingContextTests.cs
@@ -0,0 +1,314 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class DynamicBindingContextTests
+ {
+ [Test]
+ public void BindingTwoWayToDynamicModel ()
+ {
+ var view = new MockBindable ();
+ var model = new DynamicModel
+ {
+ Properties =
+ {
+ { "Title", "Foo" },
+ }
+ };
+
+ view.SetBinding (MockBindable.TextProperty, "Title");
+ view.BindingContext = model;
+
+ Assert.AreEqual ("Foo", view.Text);
+
+ view.Text = "Bar";
+
+ Assert.AreEqual ("Bar", model.Properties["Title"]);
+ }
+
+ // This whole class and inner types is just a very simple
+ // dictionary-based dynamic model that proves that the
+ // approach works. It implements just the bare minimum of
+ // the base types to get our bindings to work properly and
+ // pass the tests.
+ class DynamicModel : IReflectableType
+ {
+ public DynamicModel ()
+ {
+ Properties = new Dictionary<string, object> ();
+ }
+
+ public TypeInfo GetTypeInfo ()
+ {
+ return new DynamicTypeInfo (Properties);
+ }
+
+ public IDictionary<string, object> Properties { get; private set; }
+
+ class DynamicTypeInfo : TypeDelegator
+ {
+ IDictionary<string, object> properties;
+
+ public DynamicTypeInfo (IDictionary<string, object> properties)
+ : base (typeof(object))
+ {
+ this.properties = properties;
+ }
+
+ public override PropertyInfo GetDeclaredProperty (string name)
+ {
+ if (!properties.ContainsKey (name))
+ return null;
+
+ return new DynamicPropertyInfo (properties, name);
+ }
+
+ internal class DynamicPropertyInfo : PropertyInfo
+ {
+ IDictionary<string, object> properties;
+ string name;
+
+ public DynamicPropertyInfo (IDictionary<string, object> properties, string name)
+ {
+ this.properties = properties;
+ this.name = name;
+ }
+
+ public override bool CanRead
+ {
+ get { return true; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return true; }
+ }
+
+ public override MethodInfo GetGetMethod (bool nonPublic)
+ {
+ return new DynamicPropertyGetterInfo (this, properties);
+ }
+
+ public override MethodInfo GetSetMethod (bool nonPublic)
+ {
+ return new DynamicPropertySetterInfo (this, properties);
+ }
+
+ public override Type PropertyType
+ {
+ get { return properties[name].GetType (); }
+ }
+
+ public override string Name
+ {
+ get { return name; }
+ }
+
+ public override PropertyAttributes Attributes
+ {
+ get { return PropertyAttributes.None; }
+ }
+
+ public override MethodInfo[] GetAccessors (bool nonPublic)
+ {
+ return new[] { GetGetMethod (nonPublic), GetSetMethod (nonPublic) };
+ }
+
+ public override ParameterInfo[] GetIndexParameters ()
+ {
+ return new ParameterInfo[0];
+ }
+
+ public override object GetValue (object obj, BindingFlags invokeAttr, Binder binder, object[] index, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override void SetValue (object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override Type DeclaringType
+ {
+ get { throw new NotImplementedException (); }
+ }
+
+ public override object[] GetCustomAttributes (Type attributeType, bool inherit)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override object[] GetCustomAttributes (bool inherit)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override bool IsDefined (Type attributeType, bool inherit)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override Type ReflectedType
+ {
+ get { throw new NotImplementedException (); }
+ }
+ }
+
+ internal class DynamicPropertyGetterInfo : DynamicPropertyMethodInfo
+ {
+ public DynamicPropertyGetterInfo (PropertyInfo property, IDictionary<string, object> properties)
+ : base (property, properties)
+ {
+ }
+
+ public override object Invoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
+ {
+ return Properties[Property.Name];
+ }
+
+ public override ParameterInfo[] GetParameters ()
+ {
+ return new[] { new DynamicParameterInfo (Property, Property.PropertyType, "value") };
+ }
+
+ public override Type ReturnType
+ {
+ get { return Property.PropertyType; }
+ }
+ }
+
+ internal class DynamicPropertySetterInfo : DynamicPropertyMethodInfo
+ {
+ public DynamicPropertySetterInfo (PropertyInfo property, IDictionary<string, object> properties)
+ : base (property, properties)
+ {
+ }
+
+ public override object Invoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
+ {
+ Properties[Property.Name] = parameters[0];
+ return null;
+ }
+
+ public override ParameterInfo[] GetParameters ()
+ {
+ return new[] {
+ new DynamicParameterInfo (Property, typeof(DynamicTypeInfo), "this"),
+ new DynamicParameterInfo (Property, Property.PropertyType, "value")
+ };
+ }
+
+ public override Type ReturnType
+ {
+ get { return typeof(void); }
+ }
+ }
+
+ internal abstract class DynamicPropertyMethodInfo : MethodInfo
+ {
+ public DynamicPropertyMethodInfo (PropertyInfo property, IDictionary<string, object> properties)
+ {
+ Property = property;
+ Properties = properties;
+ }
+
+ protected PropertyInfo Property { get; private set; }
+
+ protected IDictionary<string, object> Properties { get; private set; }
+
+ public override MethodInfo GetBaseDefinition ()
+ {
+ return null;
+ }
+
+ public override ICustomAttributeProvider ReturnTypeCustomAttributes
+ {
+ get { return null; }
+ }
+
+ public override MethodAttributes Attributes
+ {
+ get { return MethodAttributes.Public; }
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags ()
+ {
+ return MethodImplAttributes.IL;
+ }
+
+ public override ParameterInfo[] GetParameters ()
+ {
+ return new ParameterInfo[0];
+ }
+
+ public override RuntimeMethodHandle MethodHandle
+ {
+ get { throw new NotImplementedException (); }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return typeof(DynamicModel); }
+ }
+
+ public override object[] GetCustomAttributes (Type attributeType, bool inherit)
+ {
+ return new object[0];
+ }
+
+ public override object[] GetCustomAttributes (bool inherit)
+ {
+ return new object[0];
+ }
+
+ public override bool IsDefined (Type attributeType, bool inherit)
+ {
+ return false;
+ }
+
+ public override string Name
+ {
+ get { return Property.Name; }
+ }
+
+ public override Type ReflectedType
+ {
+ get { return typeof(DynamicModel); }
+ }
+ }
+
+ internal class DynamicParameterInfo : ParameterInfo
+ {
+ MemberInfo member;
+ Type type;
+
+ public DynamicParameterInfo (MemberInfo member, Type type, string name)
+ {
+ this.member = member;
+ this.type = type;
+ }
+
+ public override MemberInfo Member
+ {
+ get { return member; }
+ }
+
+ public override Type ParameterType
+ {
+ get { return type; }
+ }
+ }
+ }
+
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/DynamicResourceTests.cs b/Xamarin.Forms.Core.UnitTests/DynamicResourceTests.cs
new file mode 100644
index 00000000..faea9963
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/DynamicResourceTests.cs
@@ -0,0 +1,153 @@
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class DynamicResourceTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup ()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [Test]
+ public void TestDynamicResource ()
+ {
+ var label = new Label ();
+ label.SetDynamicResource (Label.TextProperty, "foo");
+ var layout = new StackLayout {
+ Children = {
+ label
+ }
+ };
+
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label.Text);
+
+ layout.Resources = new ResourceDictionary {
+ { "foo", "FOO" }
+ };
+ Assert.AreEqual ("FOO", label.Text);
+ }
+
+ [Test]
+ public void SetResourceTriggerSetValue ()
+ {
+ var label = new Label ();
+ label.SetDynamicResource (Label.TextProperty, "foo");
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label.Text);
+ label.Resources = new ResourceDictionary {
+ {"foo", "FOO"}
+ };
+ Assert.AreEqual ("FOO", label.Text);
+ }
+
+ [Test]
+ public void SetResourceOnParentTriggerSetValue ()
+ {
+ var label = new Label ();
+ var layout = new StackLayout { Children = {label}};
+ label.SetDynamicResource (Label.TextProperty, "foo");
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label.Text);
+ layout.Resources = new ResourceDictionary {
+ {"foo", "FOO"}
+ };
+ Assert.AreEqual ("FOO", label.Text);
+ }
+
+ [Test]
+ public void SettingResourceTriggersValueChanged ()
+ {
+ var label = new Label ();
+ label.SetDynamicResource (Label.TextProperty, "foo");
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label.Text);
+ label.Resources = new ResourceDictionary ();
+ label.Resources.Add ("foo", "FOO");
+ Assert.AreEqual ("FOO", label.Text);
+ }
+
+ [Test]
+ public void AddingAResourceDictionaryTriggersValueChangedForExistingValues ()
+ {
+ var label = new Label ();
+ label.SetDynamicResource (Label.TextProperty, "foo");
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label.Text);
+ var rd = new ResourceDictionary { {"foo","FOO"}};
+ label.Resources = rd;
+ Assert.AreEqual ("FOO", label.Text);
+ }
+
+ [Test]
+ public void ValueChangedTriggeredOnSubscribeIfKeyAlreadyExists ()
+ {
+ var label = new Label ();
+ label.Resources = new ResourceDictionary { {"foo","FOO"}};
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label.Text);
+ label.SetDynamicResource (Label.TextProperty, "foo");
+ Assert.AreEqual ("FOO", label.Text);
+ }
+
+ [Test]
+ public void RemoveDynamicResourceStopsUpdating ()
+ {
+ var label = new Label ();
+ label.Resources = new ResourceDictionary { {"foo","FOO"}};
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label.Text);
+ label.SetDynamicResource (Label.TextProperty, "foo");
+ Assert.AreEqual ("FOO", label.Text);
+ label.RemoveDynamicResource (Label.TextProperty);
+ label.Resources ["foo"] = "BAR";
+ Assert.AreEqual ("FOO", label.Text);
+ }
+
+ [Test]
+ public void ReparentResubscribe ()
+ {
+ var layout0 = new ContentView { Resources = new ResourceDictionary {{"foo","FOO"}}};
+ var layout1 = new ContentView { Resources = new ResourceDictionary {{"foo","BAR"}}};
+
+ var label = new Label ();
+ label.SetDynamicResource (Label.TextProperty, "foo");
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label.Text);
+
+ layout0.Content = label;
+ Assert.AreEqual ("FOO", label.Text);
+
+ layout0.Content = null;
+ layout1.Content = label;
+ Assert.AreEqual ("BAR", label.Text);
+ }
+
+ [Test]
+ public void ClearedResourcesDoesNotClearValues ()
+ {
+ var layout0 = new ContentView { Resources = new ResourceDictionary {{"foo","FOO"}}};
+ var label = new Label ();
+ label.SetDynamicResource (Label.TextProperty, "foo");
+ layout0.Content = label;
+
+ Assert.AreEqual ("FOO", label.Text);
+
+ layout0.Resources.Clear ();
+ Assert.AreEqual ("FOO", label.Text);
+ }
+
+ [Test]
+ //Issue 2608
+ public void ResourcesCanBeChanged ()
+ {
+ var label = new Label ();
+ label.BindingContext = new MockViewModel ();
+ label.SetBinding (Label.TextProperty, "Text", BindingMode.TwoWay);
+ label.SetDynamicResource (Label.TextProperty, "foo");
+ label.Resources = new ResourceDictionary { {"foo","FOO"}};
+
+ Assert.AreEqual ("FOO", label.Text);
+
+ label.Resources ["foo"] = "BAR";
+
+ Assert.AreEqual ("BAR", label.Text);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/EasingTests.cs b/Xamarin.Forms.Core.UnitTests/EasingTests.cs
new file mode 100644
index 00000000..be491ed8
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/EasingTests.cs
@@ -0,0 +1,32 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class EasingTests : BaseTestFixture
+ {
+ [Test]
+ public void Linear ([Range (0, 10)] double input)
+ {
+ Assert.AreEqual (input, Easing.Linear.Ease (input));
+ }
+
+ [Test]
+ public void AllRunFromZeroToOne ([Values (0.0, 1.0)] double val)
+ {
+ const double epsilon = 0.001;
+ Assert.True (Math.Abs (val - Easing.Linear.Ease (val)) < epsilon);
+ Assert.True (Math.Abs (val - Easing.BounceIn.Ease (val)) < epsilon);
+ Assert.True (Math.Abs (val - Easing.BounceOut.Ease (val)) < epsilon);
+ Assert.True (Math.Abs (val - Easing.CubicIn.Ease (val)) < epsilon);
+ Assert.True (Math.Abs (val - Easing.CubicInOut.Ease (val)) < epsilon);
+ Assert.True (Math.Abs (val - Easing.CubicOut.Ease (val)) < epsilon);
+ Assert.True (Math.Abs (val - Easing.SinIn.Ease (val)) < epsilon);
+ Assert.True (Math.Abs (val - Easing.SinInOut.Ease (val)) < epsilon);
+ Assert.True (Math.Abs (val - Easing.SinOut.Ease (val)) < epsilon);
+ Assert.True (Math.Abs (val - Easing.SpringIn.Ease (val)) < epsilon);
+ Assert.True (Math.Abs (val - Easing.SpringOut.Ease (val)) < epsilon);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/EditorTests.cs b/Xamarin.Forms.Core.UnitTests/EditorTests.cs
new file mode 100644
index 00000000..c16f1d2a
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/EditorTests.cs
@@ -0,0 +1,34 @@
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class EditorTests : BaseTestFixture
+ {
+ [TestCase ("Hi", "My text has changed")]
+ [TestCase (null, "My text has changed")]
+ [TestCase ("Hi", null)]
+ public void EditorTextChangedEventArgs (string initialText, string finalText)
+ {
+ var editor = new Editor {
+ Text = initialText
+ };
+
+ Editor editorFromSender = null;
+ string oldText = null;
+ string newText = null;
+
+ editor.TextChanged += (s, e) => {
+ editorFromSender = (Editor)s;
+ oldText = e.OldTextValue;
+ newText = e.NewTextValue;
+ };
+
+ editor.Text = finalText;
+
+ Assert.AreEqual (editor, editorFromSender);
+ Assert.AreEqual (initialText, oldText);
+ Assert.AreEqual (finalText, newText);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/EffectTests.cs b/Xamarin.Forms.Core.UnitTests/EffectTests.cs
new file mode 100644
index 00000000..66399bc8
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/EffectTests.cs
@@ -0,0 +1,121 @@
+using System;
+using NUnit.Framework;
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class EffectTests : BaseTestFixture
+ {
+ [Test]
+ public void ResolveSetsId ()
+ {
+ string id = "Unknown";
+ var effect = Effect.Resolve (id);
+ Assert.AreEqual (id, effect.ResolveId);
+ }
+
+ [Test]
+ public void UnknownIdReturnsNullEffect ()
+ {
+ var effect = Effect.Resolve ("Foo");
+ Assert.IsInstanceOf<NullEffect> (effect);
+ }
+
+ [Test]
+ public void SendAttachedSetsFlag ()
+ {
+ var effect = Effect.Resolve ("Foo");
+ effect.SendAttached ();
+ Assert.True (effect.IsAttached);
+ }
+
+ [Test]
+ public void SendDetachedUnsetsFlag ()
+ {
+ var effect = Effect.Resolve ("Foo");
+ effect.SendAttached ();
+ effect.SendDetached ();
+ Assert.False (effect.IsAttached);
+ }
+
+ [Test]
+ public void EffectLifecyclePreProvider ()
+ {
+ var effect = new CustomEffect ();
+ var element = new Label ();
+
+ element.Effects.Add (effect);
+ ((IVisualElementController)element).EffectControlProvider = new EffectControlProvider ();
+
+ Assert.True (effect.IsAttached);
+ Assert.True (effect.OnAttachedCalled);
+ Assert.True (effect.Registered);
+ Assert.False (effect.OnDetachedCalled);
+
+ element.Effects.Remove (effect);
+ Assert.True (effect.OnDetachedCalled);
+ }
+
+ [Test]
+ public void EffectLifecyclePostProvider ()
+ {
+ var effect = new CustomEffect ();
+ var element = new Label ();
+
+ ((IVisualElementController)element).EffectControlProvider = new EffectControlProvider ();
+ element.Effects.Add (effect);
+
+ Assert.True (effect.IsAttached);
+ Assert.True (effect.OnAttachedCalled);
+ Assert.True (effect.Registered);
+ Assert.False (effect.OnDetachedCalled);
+
+ element.Effects.Remove (effect);
+ Assert.True (effect.OnDetachedCalled);
+ }
+
+ [Test]
+ public void EffectsClearDetachesEffect ()
+ {
+ var effect = new CustomEffect ();
+ var element = new Label ();
+
+ ((IVisualElementController)element).EffectControlProvider = new EffectControlProvider ();
+ element.Effects.Add (effect);
+
+ element.Effects.Clear ();
+
+ Assert.True (effect.OnDetachedCalled);
+ }
+
+ class EffectControlProvider : IEffectControlProvider
+ {
+ public void RegisterEffect (Effect effect)
+ {
+ var e = effect as CustomEffect;
+ if (e != null)
+ e.Registered = true;
+ }
+ }
+
+ class CustomEffect : Effect
+ {
+ public bool OnAttachedCalled;
+ public bool OnDetachedCalled;
+ public bool Registered;
+
+ protected override void OnAttached ()
+ {
+ OnAttachedCalled = true;
+ }
+
+ protected override void OnDetached ()
+ {
+ OnDetachedCalled = true;
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ElementTests.cs b/Xamarin.Forms.Core.UnitTests/ElementTests.cs
new file mode 100644
index 00000000..6bffe338
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ElementTests.cs
@@ -0,0 +1,176 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ public class TestElement
+ : Element
+ {
+ public TestElement ()
+ {
+ internalChildren.CollectionChanged += OnChildrenChanged;
+ }
+
+ void OnChildrenChanged (object sender, NotifyCollectionChangedEventArgs e)
+ {
+ if (e.NewItems != null) {
+ foreach (Element element in e.NewItems)
+ OnChildAdded (element);
+ }
+
+ if (e.OldItems != null) {
+ foreach (Element element in e.OldItems)
+ OnChildRemoved (element);
+ }
+ }
+
+ public IList<Element> Children
+ {
+ get { return internalChildren; }
+ }
+
+ internal override ReadOnlyCollection<Element> LogicalChildren
+ {
+ get { return new ReadOnlyCollection<Element> (internalChildren); }
+ }
+
+ readonly ObservableCollection<Element> internalChildren = new ObservableCollection<Element> ();
+ }
+
+ [TestFixture]
+ public class ElementTests
+ : BaseTestFixture
+ {
+ [Test]
+ public void DescendantAddedLevel1 ()
+ {
+ var root = new TestElement();
+
+ var child = new TestElement();
+
+ bool added = false;
+ root.DescendantAdded += (sender, args) => {
+ Assert.That (args.Element, Is.SameAs (child));
+ added = true;
+ };
+
+ root.Children.Add (child);
+ }
+
+ [Test]
+ public void DescendantAddedLevel2 ()
+ {
+ var root = new TestElement();
+
+ var child = new TestElement();
+ root.Children.Add (child);
+
+ var child2 = new TestElement();
+
+ bool added = false;
+ root.DescendantAdded += (sender, args) => {
+ Assert.That (args.Element, Is.SameAs (child2));
+ added = true;
+ };
+
+ child.Children.Add (child2);
+ }
+
+ [Test]
+ public void DescendantAddedExistingChildren ()
+ {
+ var root = new TestElement();
+
+ var tier2 = new TestElement();
+
+ var child = new TestElement {
+ Children = {
+ tier2
+ }
+ };
+
+ bool tier1added = false;
+ bool tier2added = false;
+ root.DescendantAdded += (sender, args) => {
+ if (!tier1added)
+ tier1added = ReferenceEquals (child, args.Element);
+ if (!tier2added)
+ tier2added = ReferenceEquals (tier2, args.Element);
+ };
+
+ root.Children.Add (child);
+
+ Assert.That (tier1added, Is.True);
+ Assert.That (tier2added, Is.True);
+ }
+
+ [Test]
+ public void DescendantRemovedLevel1 ()
+ {
+ var root = new TestElement();
+
+ var child = new TestElement();
+ root.Children.Add (child);
+
+ bool removed = false;
+ root.DescendantRemoved += (sender, args) => {
+ Assert.That (args.Element, Is.SameAs (child));
+ removed = true;
+ };
+
+ root.Children.Remove (child);
+ }
+
+ [Test]
+ public void DescendantRemovedLevel2 ()
+ {
+ var root = new TestElement();
+
+ var child = new TestElement();
+ root.Children.Add (child);
+
+ var child2 = new TestElement();
+ child.Children.Add (child2);
+
+ bool removed = false;
+ root.DescendantRemoved += (sender, args) => {
+ Assert.That (args.Element, Is.SameAs (child2));
+ removed = true;
+ };
+
+ child.Children.Remove (child2);
+ }
+
+ [Test]
+ public void DescendantRemovedWithChildren ()
+ {
+ var root = new TestElement();
+
+ var tier2 = new TestElement();
+
+ var child = new TestElement {
+ Children = {
+ tier2
+ }
+ };
+
+ root.Children.Add (child);
+
+ bool tier1removed = false;
+ bool tier2removed = false;
+ root.DescendantRemoved += (sender, args) => {
+ if (!tier1removed)
+ tier1removed = ReferenceEquals (child, args.Element);
+ if (!tier2removed)
+ tier2removed = ReferenceEquals (tier2, args.Element);
+ };
+
+ root.Children.Remove (child);
+
+ Assert.That (tier1removed, Is.True);
+ Assert.That (tier2removed, Is.True);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/EntryCellTests.cs b/Xamarin.Forms.Core.UnitTests/EntryCellTests.cs
new file mode 100644
index 00000000..34b7b663
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/EntryCellTests.cs
@@ -0,0 +1,82 @@
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class EntryCellTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [Test]
+ public void ChangingHorizontalTextAlignmentFiresXAlignChanged ()
+ {
+ var entryCell = new EntryCell { HorizontalTextAlignment = TextAlignment.Center };
+
+ var xAlignFired = false;
+ var horizontalTextAlignmentFired = false;
+
+ entryCell.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "XAlign") {
+ xAlignFired = true;
+ } else if (args.PropertyName == EntryCell.HorizontalTextAlignmentProperty.PropertyName) {
+ horizontalTextAlignmentFired = true;
+ }
+ };
+
+ entryCell.HorizontalTextAlignment = TextAlignment.End;
+
+ Assert.True(xAlignFired);
+ Assert.True(horizontalTextAlignmentFired);
+ }
+
+ [Test]
+ public void EntryCellXAlignBindingMatchesHorizontalTextAlignmentBinding ()
+ {
+ var vm = new ViewModel ();
+ vm.Alignment = TextAlignment.Center;
+
+ var entryCellXAlign = new EntryCell () { BindingContext = vm };
+ entryCellXAlign.SetBinding (EntryCell.XAlignProperty, new Binding ("Alignment"));
+
+ var entryCellHorizontalTextAlignment = new EntryCell () { BindingContext = vm };
+ entryCellHorizontalTextAlignment.SetBinding (EntryCell.HorizontalTextAlignmentProperty, new Binding ("Alignment"));
+
+ Assert.AreEqual (TextAlignment.Center, entryCellXAlign.XAlign);
+ Assert.AreEqual (TextAlignment.Center, entryCellHorizontalTextAlignment.HorizontalTextAlignment);
+
+ vm.Alignment = TextAlignment.End;
+
+ Assert.AreEqual (TextAlignment.End, entryCellXAlign.XAlign);
+ Assert.AreEqual (TextAlignment.End, entryCellHorizontalTextAlignment.HorizontalTextAlignment);
+ }
+
+ sealed class ViewModel : INotifyPropertyChanged
+ {
+ TextAlignment alignment;
+
+ public TextAlignment Alignment
+ {
+ get { return alignment; }
+ set
+ {
+ alignment = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChanged?.Invoke (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/EntryUnitTests.cs b/Xamarin.Forms.Core.UnitTests/EntryUnitTests.cs
new file mode 100644
index 00000000..83f71b9a
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/EntryUnitTests.cs
@@ -0,0 +1,55 @@
+using System.Diagnostics;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class EntryUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void ValueChangedFromSetValue()
+ {
+ var entry = new Entry();
+
+ const string value = "Foo";
+
+ bool signaled = false;
+ entry.TextChanged += (sender, args) => {
+ signaled = true;
+ Assert.AreEqual (value, args.NewTextValue);
+ };
+
+ entry.SetValue (Entry.TextProperty, value);
+
+ Assert.IsTrue (signaled, "ValueChanged did not fire");
+ }
+
+ [TestCase (null, "foo")]
+ [TestCase ("foo", "bar")]
+ [TestCase ("foo", null)]
+ public void ValueChangedArgs (string initial, string final)
+ {
+ var entry = new Entry {
+ Text = initial
+ };
+
+ string oldValue = null;
+ string newValue = null;
+
+ Entry entryFromSender = null;
+
+ entry.TextChanged += (s, e) => {
+ entryFromSender = (Entry)s;
+ oldValue = e.OldTextValue;
+ newValue = e.NewTextValue;
+ };
+
+ entry.Text = final;
+
+ Assert.AreEqual (entry, entryFromSender);
+ Assert.AreEqual (initial, oldValue);
+ Assert.AreEqual (final, newValue);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/EventTriggerTest.cs b/Xamarin.Forms.Core.UnitTests/EventTriggerTest.cs
new file mode 100644
index 00000000..89034a03
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/EventTriggerTest.cs
@@ -0,0 +1,73 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ internal class MockTriggerAction : TriggerAction<BindableObject>
+ {
+ public bool Invoked { get; set;}
+
+ protected override void Invoke (BindableObject sender)
+ {
+ Invoked = true;
+ }
+ }
+
+ internal class MockBindableWithEvent : VisualElement
+ {
+ public void FireEvent ()
+ {
+ if (MockEvent != null)
+ MockEvent (this, EventArgs.Empty);
+ }
+
+ public void FireEvent2 ()
+ {
+ if (MockEvent2 != null)
+ MockEvent2 (this, EventArgs.Empty);
+ }
+
+ public event EventHandler MockEvent;
+ public event EventHandler MockEvent2;
+ }
+
+ [TestFixture]
+ public class EventTriggerTest : BaseTestFixture
+ {
+ [Test]
+ public void TestTriggerActionInvoked ()
+ {
+ var bindable = new MockBindableWithEvent ();
+ var triggeraction = new MockTriggerAction ();
+ var eventtrigger = new EventTrigger () { Event = "MockEvent", Actions = { triggeraction } };
+ var collection = bindable.Triggers;
+ collection.Add (eventtrigger);
+
+ Assert.False (triggeraction.Invoked);
+ bindable.FireEvent ();
+ Assert.True (triggeraction.Invoked);
+ }
+
+ [Test]
+ public void TestChangeEventOnEventTrigger ()
+ {
+ var bindable = new MockBindableWithEvent ();
+ var triggeraction = new MockTriggerAction ();
+ var eventtrigger = new EventTrigger { Event = "MockEvent", Actions = { triggeraction } };
+ var collection = bindable.Triggers;
+ collection.Add (eventtrigger);
+
+ triggeraction.Invoked = false;
+ Assert.False (triggeraction.Invoked);
+ bindable.FireEvent ();
+ Assert.True (triggeraction.Invoked);
+
+ triggeraction.Invoked = false;
+ Assert.False (triggeraction.Invoked);
+ bindable.FireEvent2 ();
+ Assert.False (triggeraction.Invoked);
+
+ Assert.Throws<InvalidOperationException>(()=> eventtrigger.Event = "MockEvent2");
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/FluentTests.cs b/Xamarin.Forms.Core.UnitTests/FluentTests.cs
new file mode 100644
index 00000000..b8780adb
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/FluentTests.cs
@@ -0,0 +1,8 @@
+using System.Linq;
+using NUnit.Framework;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+
+}
diff --git a/Xamarin.Forms.Core.UnitTests/FontUnitTests.cs b/Xamarin.Forms.Core.UnitTests/FontUnitTests.cs
new file mode 100644
index 00000000..dcf972f9
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/FontUnitTests.cs
@@ -0,0 +1,129 @@
+using System.Globalization;
+
+using NUnit.Framework;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class FontUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestFontForSize ()
+ {
+ var font = Font.OfSize ("Foo", 12);
+ Assert.AreEqual ("Foo", font.FontFamily);
+ Assert.AreEqual (12, font.FontSize);
+ Assert.AreEqual ((NamedSize)0, font.NamedSize);
+ }
+
+ [Test]
+ public void TestFontForSizeDouble ()
+ {
+ var font = Font.OfSize ("Foo", 12.7);
+ Assert.AreEqual ("Foo", font.FontFamily);
+ Assert.AreEqual (12.7, font.FontSize);
+ Assert.AreEqual ((NamedSize)0, font.NamedSize);
+ }
+
+ [Test]
+ public void TestFontForNamedSize ()
+ {
+ var font = Font.OfSize ("Foo", NamedSize.Large);
+ Assert.AreEqual ("Foo", font.FontFamily);
+ Assert.AreEqual (0, font.FontSize);
+ Assert.AreEqual (NamedSize.Large, font.NamedSize);
+ }
+
+ [Test]
+ public void TestSystemFontOfSize ()
+ {
+ var font = Font.SystemFontOfSize (12);
+ Assert.AreEqual (null, font.FontFamily);
+ Assert.AreEqual (12, font.FontSize);
+ Assert.AreEqual ((NamedSize)0, font.NamedSize);
+
+ font = Font.SystemFontOfSize (NamedSize.Medium);
+ Assert.AreEqual (null, font.FontFamily);
+ Assert.AreEqual (0, font.FontSize);
+ Assert.AreEqual (NamedSize.Medium, font.NamedSize);
+ }
+
+ [Test]
+ public void CultureTestSystemFontOfSizeDouble ()
+ {
+ var font = Font.SystemFontOfSize (12.7);
+ Assert.AreEqual (null, font.FontFamily);
+ Assert.AreEqual (12.7, font.FontSize);
+ Assert.AreEqual ((NamedSize)0, font.NamedSize);
+
+ font = Font.SystemFontOfSize (NamedSize.Medium);
+ Assert.AreEqual (null, font.FontFamily);
+ Assert.AreEqual (0, font.FontSize);
+ Assert.AreEqual (NamedSize.Medium, font.NamedSize);
+ }
+
+ [Test]
+ public void TestEquality ()
+ {
+ var font1 = Font.SystemFontOfSize (12);
+ var font2 = Font.SystemFontOfSize (12);
+
+ Assert.True (font1 == font2);
+ Assert.False (font1 != font2);
+
+ font2 = Font.SystemFontOfSize (13);
+
+ Assert.False (font1 == font2);
+ Assert.True (font1 != font2);
+ }
+
+ [Test]
+ public void TestHashCode ()
+ {
+ var font1 = Font.SystemFontOfSize (12);
+ var font2 = Font.SystemFontOfSize (12);
+
+ Assert.True (font1.GetHashCode () == font2.GetHashCode ());
+
+ font2 = Font.SystemFontOfSize (13);
+
+ Assert.False (font1.GetHashCode () == font2.GetHashCode ());
+ }
+
+ [Test]
+ public void TestEquals ()
+ {
+ var font = Font.SystemFontOfSize (12);
+
+ Assert.False (font.Equals (null));
+ Assert.True (font.Equals (font));
+ Assert.False (font.Equals ("Font"));
+ Assert.True (font.Equals (Font.SystemFontOfSize (12)));
+ }
+
+ [Test]
+ public void TestFontConverter ()
+ {
+ var converter = new FontTypeConverter ();
+ Assert.True (converter.CanConvertFrom (typeof(string)));
+ Assert.AreEqual (Font.SystemFontOfSize (NamedSize.Medium), converter.ConvertFromInvariantString ("Medium"));
+ Assert.AreEqual (Font.SystemFontOfSize (42), converter.ConvertFromInvariantString ("42"));
+ Assert.AreEqual (Font.OfSize ("Foo", NamedSize.Micro), converter.ConvertFromInvariantString ("Foo, Micro"));
+ Assert.AreEqual (Font.OfSize ("Foo", 42), converter.ConvertFromInvariantString ("Foo, 42"));
+ Assert.AreEqual (Font.OfSize ("Foo", 12.7), converter.ConvertFromInvariantString ("Foo, 12.7"));
+ Assert.AreEqual (Font.SystemFontOfSize (NamedSize.Large, FontAttributes.Bold), converter.ConvertFromInvariantString ("Bold, Large"));
+ Assert.AreEqual (Font.SystemFontOfSize (42, FontAttributes.Bold), converter.ConvertFromInvariantString ("Bold, 42"));
+ Assert.AreEqual (Font.OfSize ("Foo", NamedSize.Medium), converter.ConvertFromInvariantString ("Foo"));
+ Assert.AreEqual (Font.OfSize ("Foo", NamedSize.Large).WithAttributes (FontAttributes.Bold), converter.ConvertFromInvariantString ("Foo, Bold, Large"));
+ Assert.AreEqual (Font.OfSize ("Foo", NamedSize.Large).WithAttributes (FontAttributes.Italic), converter.ConvertFromInvariantString ("Foo, Italic, Large"));
+ Assert.AreEqual (Font.OfSize ("Foo", NamedSize.Large).WithAttributes (FontAttributes.Bold | FontAttributes.Italic), converter.ConvertFromInvariantString ("Foo, Bold, Italic, Large"));
+ Assert.AreEqual (Font.OfSize ("Foo", 12).WithAttributes (FontAttributes.Bold), converter.ConvertFromInvariantString ("Foo, Bold, 12"));
+ Assert.AreEqual (Font.OfSize ("Foo", 12.7).WithAttributes (FontAttributes.Bold), converter.ConvertFromInvariantString ("Foo, Bold, 12.7"));
+ Assert.AreEqual (Font.OfSize ("Foo", 12).WithAttributes (FontAttributes.Italic), converter.ConvertFromInvariantString ("Foo, Italic, 12"));
+ Assert.AreEqual (Font.OfSize ("Foo", 12.7).WithAttributes (FontAttributes.Italic), converter.ConvertFromInvariantString ("Foo, Italic, 12.7"));
+ Assert.AreEqual (Font.OfSize ("Foo", 12).WithAttributes (FontAttributes.Bold | FontAttributes.Italic), converter.ConvertFromInvariantString ("Foo, Bold, Italic, 12"));
+ Assert.AreEqual (Font.OfSize ("Foo", 12.7).WithAttributes (FontAttributes.Bold | FontAttributes.Italic), converter.ConvertFromInvariantString ("Foo, Bold, Italic, 12.7"));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/FormattedStringTests.cs b/Xamarin.Forms.Core.UnitTests/FormattedStringTests.cs
new file mode 100644
index 00000000..7c247bda
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/FormattedStringTests.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.ObjectModel;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class FormattedStringTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup ()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown ()
+ {
+ base.Setup ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void NullSpansNotAllowed()
+ {
+ var fs = new FormattedString();
+ Assert.That (() => fs.Spans.Add (null), Throws.InstanceOf<ArgumentNullException>());
+
+ fs = new FormattedString();
+ fs.Spans.Add (new Span());
+
+ Assert.That (() => {
+ fs.Spans[0] = null;
+ }, Throws.InstanceOf<ArgumentNullException>());
+ }
+
+ [Test]
+ public void SpanChangeTriggersSpansPropertyChange()
+ {
+ var span = new Span();
+ var fs = new FormattedString();
+ fs.Spans.Add (span);
+
+ bool spansChanged = false;
+ fs.PropertyChanged += (s, e) => {
+ if (e.PropertyName == "Spans")
+ spansChanged = true;
+ };
+
+ span.Text = "New text";
+
+ Assert.That (spansChanged, Is.True);
+ }
+
+ [Test]
+ public void SpanChangesUnsubscribes()
+ {
+ var span = new Span();
+ var fs = new FormattedString();
+ fs.Spans.Add (span);
+ fs.Spans.Remove (span);
+
+ bool spansChanged = false;
+ fs.PropertyChanged += (s, e) => {
+ if (e.PropertyName == "Spans")
+ spansChanged = true;
+ };
+
+ span.Text = "New text";
+
+ Assert.That (spansChanged, Is.False);
+ }
+
+ [Test]
+ public void AddingSpanTriggersSpansPropertyChange()
+ {
+ var span = new Span();
+ var fs = new FormattedString();
+
+ bool spansChanged = false;
+ fs.PropertyChanged += (s, e) => {
+ if (e.PropertyName == "Spans")
+ spansChanged = true;
+ };
+
+ fs.Spans.Add (span);
+
+ Assert.That (spansChanged, Is.True);
+ }
+
+ [Test]
+ public void ImplicitStringConversion()
+ {
+ string original = "fubar";
+ FormattedString fs = original;
+ Assert.That (fs, Is.Not.Null);
+ Assert.That (fs.Spans.Count, Is.EqualTo (1));
+ Assert.That (fs.Spans[0], Is.Not.Null);
+ Assert.That (fs.Spans[0].Text, Is.EqualTo (original));
+ }
+
+ [Test]
+ public void ImplicitStringConversionNull()
+ {
+ string original = null;
+ FormattedString fs = original;
+ Assert.That (fs, Is.Not.Null);
+ Assert.That (fs.Spans.Count, Is.EqualTo (1));
+ Assert.That (fs.Spans[0], Is.Not.Null);
+ Assert.That (fs.Spans[0].Text, Is.EqualTo (original));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/FrameUnitTests.cs b/Xamarin.Forms.Core.UnitTests/FrameUnitTests.cs
new file mode 100644
index 00000000..e7bf5974
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/FrameUnitTests.cs
@@ -0,0 +1,291 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class FrameUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestConstructor ()
+ {
+ Frame frame = new Frame ();
+
+ Assert.Null (frame.Content);
+ Assert.AreEqual (new Thickness (20, 20, 20, 20), frame.Padding);
+ }
+
+ [Test]
+ public void TestPackWithoutChild ()
+ {
+ Frame frame = new Frame ();
+
+ var parent = new NaiveLayout ();
+
+ bool thrown = false;
+ try {
+ parent.Children.Add (frame);
+ } catch {
+ thrown = true;
+ }
+
+ Assert.False (thrown);
+ }
+
+ [Test]
+ public void TestPackWithChild ()
+ {
+ Frame frame = new Frame {
+ Content = new View ()
+ };
+
+ var parent = new NaiveLayout ();
+
+ bool thrown = false;
+ try {
+ parent.Children.Add (frame);
+ } catch {
+ thrown = true;
+ }
+
+ Assert.False (thrown);
+ }
+
+ [Test]
+ public void TestSetChild ()
+ {
+ Frame frame = new Frame ();
+
+ var child1 = new Label ();
+
+ bool added = false;
+
+ frame.ChildAdded += (sender, e) => added = true;
+
+ frame.Content = child1;
+
+ Assert.True (added);
+ Assert.AreEqual (child1, frame.Content);
+
+ added = false;
+ frame.Content = child1;
+
+ Assert.False (added);
+ }
+
+ [Test]
+ public void TestReplaceChild ()
+ {
+ Frame frame = new Frame ();
+
+ var child1 = new Label ();
+ var child2 = new Label ();
+
+ frame.Content = child1;
+
+ bool removed = false;
+ bool added = false;
+
+ frame.ChildRemoved += (sender, e) => removed = true;
+ frame.ChildAdded += (sender, e) => added = true;
+
+ frame.Content = child2;
+
+ Assert.True (removed);
+ Assert.True (added);
+ Assert.AreEqual (child2, frame.Content);
+ }
+
+ [Test]
+ public void TestFrameLayout ()
+ {
+ View child;
+
+ var frame = new Frame {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 200,
+ IsPlatformEnabled = true
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ Assert.AreEqual (new Size (140, 240), frame.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request);
+
+ frame.Layout (new Rectangle (0, 0, 300, 300));
+
+ Assert.AreEqual (new Rectangle (20, 20, 260, 260), child.Bounds);
+ }
+
+ [Test]
+ public void TestDoesNotThrowOnSetNullChild ()
+ {
+ Assert.DoesNotThrow (() => new Frame {Content = null});
+ }
+
+ [Test]
+ public void WidthRequest ()
+ {
+ var frame = new Frame {
+ Content = new View {
+ WidthRequest = 100,
+ HeightRequest = 200,
+ IsPlatformEnabled = true
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform (),
+ WidthRequest = 20
+ };
+
+ Assert.AreEqual (new Size (60, 240), frame.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request);
+ }
+
+ [Test]
+ public void HeightRequest ()
+ {
+ var frame = new Frame {
+ Content = new View {
+ WidthRequest = 100,
+ HeightRequest = 200,
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform (),
+ HeightRequest = 20
+ };
+
+ Assert.AreEqual (new Size (140, 60), frame.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request);
+ }
+
+ [Test]
+ public void LayoutVerticallyCenter ()
+ {
+ View child;
+
+ var frame = new Frame {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 100,
+ IsPlatformEnabled = true,
+ VerticalOptions = LayoutOptions.Center
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ frame.Layout (new Rectangle (0, 0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (20, 50, 160, 100), child.Bounds);
+ }
+
+ [Test]
+ public void LayoutVerticallyBegin()
+ {
+ View child;
+
+ var frame = new Frame {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 100,
+ IsPlatformEnabled = true,
+ VerticalOptions = LayoutOptions.Start
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ frame.Layout (new Rectangle (0, 0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (20, 20, 160, 100), child.Bounds);
+ }
+
+ [Test]
+ public void LayoutVerticallyEnd()
+ {
+ View child;
+
+ var frame = new Frame {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 100,
+ IsPlatformEnabled = true,
+ VerticalOptions = LayoutOptions.End
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ frame.Layout (new Rectangle (0, 0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (20, 80, 160, 100), child.Bounds);
+ }
+
+ [Test]
+ public void LayoutHorizontallyCenter()
+ {
+ View child;
+
+ var frame = new Frame {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 100,
+ IsPlatformEnabled = true,
+ HorizontalOptions = LayoutOptions.Center
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ frame.Layout (new Rectangle (0, 0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (50, 20, 100, 160), child.Bounds);
+ }
+
+ [Test]
+ public void LayoutHorizontallyBegin()
+ {
+ View child;
+
+ var frame = new Frame {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 100,
+ IsPlatformEnabled = true,
+ HorizontalOptions = LayoutOptions.Start
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ frame.Layout (new Rectangle (0, 0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (20, 20, 100, 160), child.Bounds);
+ }
+
+ [Test]
+ public void LayoutHorizontallyEnd()
+ {
+ View child;
+
+ var frame = new Frame {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 100,
+ IsPlatformEnabled = true,
+ HorizontalOptions = LayoutOptions.End
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ frame.Layout (new Rectangle (0, 0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (80, 20, 100, 160), child.Bounds);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/GeocoderUnitTests.cs b/Xamarin.Forms.Core.UnitTests/GeocoderUnitTests.cs
new file mode 100644
index 00000000..414c49de
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/GeocoderUnitTests.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using NUnit.Framework;
+using Xamarin.Forms.Maps;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class GeocoderUnitTests : BaseTestFixture
+ {
+ [Test]
+ public async void AddressesForPosition ()
+ {
+ Geocoder.GetAddressesForPositionFuncAsync = GetAddressesForPositionFuncAsync;
+ var geocoder = new Geocoder ();
+ var result = await geocoder.GetAddressesForPositionAsync (new Position (1, 2));
+ Assert.AreEqual (new String[] { "abc", "def" }, result);
+ }
+
+ async Task<IEnumerable<string>> GetAddressesForPositionFuncAsync (Position position)
+ {
+ Assert.AreEqual (new Position (1, 2), position);
+ return new string[] {"abc", "def"};
+ }
+
+ [Test]
+ public async void PositionsForAddress () {
+ Geocoder.GetPositionsForAddressAsyncFunc = GetPositionsForAddressAsyncFunc ;
+ var geocoder = new Geocoder ();
+ var result = await geocoder.GetPositionsForAddressAsync ("quux");
+ Assert.AreEqual (new Position [] { new Position (1, 2), new Position (3, 4) }, result);
+ }
+
+ async Task<IEnumerable<Position>> GetPositionsForAddressAsyncFunc (string address)
+ {
+ Assert.AreEqual ("quux", address);
+ return new Position[] {new Position (1, 2), new Position (3, 4)};
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/GridLengthTypeConverterTests.cs b/Xamarin.Forms.Core.UnitTests/GridLengthTypeConverterTests.cs
new file mode 100644
index 00000000..4c1f21f7
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/GridLengthTypeConverterTests.cs
@@ -0,0 +1,53 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class GridLengthTypeConverterTests : BaseTestFixture
+ {
+ [Test]
+ public void TestAbsolute ()
+ {
+ var converter = new GridLengthTypeConverter ();
+
+ Assert.AreEqual (new GridLength (42), converter.ConvertFromInvariantString ("42"));
+ Assert.AreEqual (new GridLength (42.2), converter.ConvertFromInvariantString ("42.2"));
+
+ Assert.Throws<FormatException> (() => converter.ConvertFromInvariantString ("foo"));
+ }
+
+ [Test]
+ public void TestAuto ()
+ {
+ var converter = new GridLengthTypeConverter ();
+
+ Assert.AreEqual (GridLength.Auto, converter.ConvertFromInvariantString ("auto"));
+ Assert.AreEqual (GridLength.Auto, converter.ConvertFromInvariantString (" AuTo "));
+ }
+
+ [Test]
+ public void TestStar ()
+ {
+ var converter = new GridLengthTypeConverter ();
+
+ Assert.AreEqual (new GridLength (1, GridUnitType.Star), converter.ConvertFromInvariantString ("*"));
+ Assert.AreEqual (new GridLength (42, GridUnitType.Star), converter.ConvertFromInvariantString ("42*"));
+
+ }
+
+ [Test]
+ public void TestValue ()
+ {
+ var converter = new GridLengthTypeConverter ();
+ Assert.AreEqual (new GridLength(3.3), converter.ConvertFromInvariantString("3.3"));
+ }
+
+ [Test]
+ public void TestValueStar ()
+ {
+ var converter = new GridLengthTypeConverter ();
+ Assert.AreEqual (new GridLength(32.3, GridUnitType.Star), converter.ConvertFromInvariantString("32.3*"));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/GridTests.cs b/Xamarin.Forms.Core.UnitTests/GridTests.cs
new file mode 100644
index 00000000..203d3b64
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/GridTests.cs
@@ -0,0 +1,1569 @@
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class GridTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void ThrowsOnNullAdd ()
+ {
+ var layout = new Grid ();
+
+ Assert.Throws<ArgumentNullException> (() => layout.Children.Add (null));
+ }
+
+ [Test]
+ public void ThrowsOnNullRemove ()
+ {
+ var layout = new Grid ();
+
+ Assert.Throws<ArgumentNullException> (() => layout.Children.Remove (null));
+ }
+
+ [Test]
+ public void TestBasicVerticalLayout ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label3 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.Children.AddVertical (new View[] {
+ label1,
+ label2,
+ label3
+ });
+
+ layout.Layout (new Rectangle (0, 0, 912, 912));
+
+ Assert.AreEqual (912, layout.Width);
+ Assert.AreEqual (912, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 912, 300), label1.Bounds);
+ Assert.AreEqual (new Rectangle (0, 306, 912, 300), label2.Bounds);
+ Assert.AreEqual (new Rectangle (0, 612, 912, 300), label3.Bounds);
+ }
+
+ [Test]
+ public void TestBasicHorizontalLayout ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label3 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.Children.AddHorizontal (new View[] {
+ label1,
+ label2,
+ label3
+ });
+
+ layout.Layout (new Rectangle (0, 0, 912, 912));
+
+ Assert.AreEqual (912, layout.Width);
+ Assert.AreEqual (912, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 300, 912), label1.Bounds);
+ Assert.AreEqual (new Rectangle (306, 0, 300, 912), label2.Bounds);
+ Assert.AreEqual (new Rectangle (612, 0, 300, 912), label3.Bounds);
+ }
+
+ [Test]
+ public void TestVerticalExpandStart ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition { Height = new GridLength (1, GridUnitType.Star) },
+ new RowDefinition { Height = GridLength.Auto},
+ };
+ layout.Children.Add (label1, 0, 0);
+ layout.Children.Add (label2, 0, 1);
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (1000, layout.Width);
+ Assert.AreEqual (1000, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 1000, 1000 - 20 - layout.RowSpacing), label1.Bounds);
+ Assert.AreEqual (new Rectangle (0, 1000 - 20, 1000, 20), label2.Bounds);
+ }
+
+ [Test]
+ public void TestHorizontalExpandStart ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label { Platform = platform, IsPlatformEnabled = true };
+ var label2 = new Label { Platform = platform, IsPlatformEnabled = true };
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition { Width = GridLength.Auto },
+ };
+ layout.Children.Add (label1, 0, 0);
+ layout.Children.Add (label2, 1, 0);
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (1000, layout.Width);
+ Assert.AreEqual (1000, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 1000 - 106, 1000), label1.Bounds);
+ Assert.AreEqual (new Rectangle (1000 - 100, 0, 100, 1000), label2.Bounds);
+ }
+
+ [Test]
+ public void TestVerticalExpandEnd ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition { Height = GridLength.Auto},
+ new RowDefinition { Height = new GridLength (1, GridUnitType.Star) },
+ };
+ layout.Children.Add (label1, 0, 0);
+ layout.Children.Add (label2, 0, 1);
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (1000, layout.Width);
+ Assert.AreEqual (1000, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 1000, 20), label1.Bounds);
+ Assert.AreEqual (new Rectangle (0, 26, 1000, 1000 - 26), label2.Bounds);
+ }
+
+ [Test]
+ public void TestHorizontalExpandEnd ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label { Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition { Width = GridLength.Auto },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ };
+
+ layout.Children.Add (label1, 0, 0);
+ layout.Children.Add (label2, 1, 0);
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (1000, layout.Width);
+ Assert.AreEqual (1000, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 100, 1000), label1.Bounds);
+ Assert.AreEqual (new Rectangle (106, 0, 1000 - 106, 1000), label2.Bounds);
+ }
+
+ [Test]
+ public void TestVerticalExpandMiddle ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label3 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition { Height = GridLength.Auto},
+ new RowDefinition { Height = new GridLength (1, GridUnitType.Star) },
+ new RowDefinition { Height = GridLength.Auto}
+ };
+ layout.Children.Add (label1, 0, 0);
+ layout.Children.Add (label2, 0, 1);
+ layout.Children.Add (label3, 0, 2);
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (1000, layout.Width);
+ Assert.AreEqual (1000, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 1000, 20), label1.Bounds);
+ Assert.AreEqual (new Rectangle (0, 26, 1000, 1000 - 52), label2.Bounds);
+ Assert.AreEqual (new Rectangle (0, 980, 1000, 20), label3.Bounds);
+ }
+
+ [Test]
+ public void TestHorizontalExpandMiddle ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label3 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition { Width = GridLength.Auto },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition { Width = GridLength.Auto },
+ };
+
+ layout.Children.Add (label1, 0, 0);
+ layout.Children.Add (label2, 1, 0);
+ layout.Children.Add (label3, 2, 0);
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (1000, layout.Width);
+ Assert.AreEqual (1000, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 100, 1000), label1.Bounds);
+ Assert.AreEqual (new Rectangle (106, 0, 1000 - 212, 1000), label2.Bounds);
+ Assert.AreEqual (new Rectangle (900, 0, 100, 1000), label3.Bounds);
+ }
+
+ [Test]
+ public void TestTableNoExpand ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label3 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label4 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.Children.Add (label1, 0, 0);
+ layout.Children.Add (label2, 1, 0);
+ layout.Children.Add (label3, 0, 1);
+ layout.Children.Add (label4, 1, 1);
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition { Width = GridLength.Auto },
+ new ColumnDefinition { Width = GridLength.Auto },
+ };
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition { Height = GridLength.Auto},
+ new RowDefinition { Height = GridLength.Auto}
+ };
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (1000, layout.Width);
+ Assert.AreEqual (1000, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 100, 20), label1.Bounds);
+ Assert.AreEqual (new Rectangle (106, 0, 100, 20), label2.Bounds);
+ Assert.AreEqual (new Rectangle (0, 26, 100, 20), label3.Bounds);
+ Assert.AreEqual (new Rectangle (106, 26, 100, 20), label4.Bounds);
+ }
+
+ [Test]
+ public void TestTableExpand ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label3 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label4 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition { Width = GridLength.Auto },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ };
+
+ layout.Children.Add (label1, 0, 0);
+ layout.Children.Add (label2, 1, 0);
+ layout.Children.Add (label3, 0, 1);
+ layout.Children.Add (label4, 1, 1);
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (1000, layout.Width);
+ Assert.AreEqual (1000, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 100, 497), label1.Bounds);
+ Assert.AreEqual (new Rectangle (106, 0, 894, 497), label2.Bounds);
+ Assert.AreEqual (new Rectangle (0, 503, 100, 497), label3.Bounds);
+ Assert.AreEqual (new Rectangle (106, 503, 894, 497), label4.Bounds);
+ }
+
+ [Test]
+ public void TestTableSpan ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label3 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.Children.Add (label1, 0, 2, 0, 1);
+ layout.Children.Add (label2, 0, 1, 1, 2);
+ layout.Children.Add (label3, 1, 2, 1, 2);
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition { Width = GridLength.Auto },
+ new ColumnDefinition { Width = GridLength.Auto },
+ };
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition { Height = GridLength.Auto},
+ new RowDefinition { Height = GridLength.Auto}
+ };
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (1000, layout.Width);
+ Assert.AreEqual (1000, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 206, 20), label1.Bounds);
+ Assert.AreEqual (new Rectangle (0, 26, 100, 20), label2.Bounds);
+ Assert.AreEqual (new Rectangle (106, 26, 100, 20), label3.Bounds);
+ }
+
+ [Test]
+ public void TestTableExpandedSpan ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label3 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ };
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition { Height = GridLength.Auto},
+ new RowDefinition { Height = GridLength.Auto}
+ };
+
+ layout.Children.Add (label1, 0, 2, 0, 1);
+ layout.Children.Add (label2, 0, 1, 1, 2);
+ layout.Children.Add (label3, 1, 2, 1, 2);
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (1000, layout.Width);
+ Assert.AreEqual (1000, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 1000, 20), label1.Bounds);
+ Assert.AreEqual (new Rectangle (0, 26, 497, 20), label2.Bounds);
+ Assert.AreEqual (new Rectangle (503, 26, 497, 20), label3.Bounds);
+ }
+
+ [Test]
+ public void TestInvalidSet ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ bool thrown = false;
+
+ try {
+ layout.Children.Add (label1, 2, 1, 0, 1);
+ } catch (ArgumentOutOfRangeException) {
+ thrown = true;
+ }
+
+ Assert.True (thrown);
+ }
+
+ [Test]
+ public void TestCentering ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true, HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center };
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition () {Width = new GridLength (1, GridUnitType.Star)},
+ };
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition () {Height = new GridLength (1,GridUnitType.Star)},
+ };
+
+ layout.Children.Add (label1);
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (new Rectangle (450, 490, 100, 20), label1.Bounds);
+ }
+
+ [Test]
+ public void TestStart ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label { Platform = platform, IsPlatformEnabled = true, HorizontalOptions = LayoutOptions.Start, VerticalOptions = LayoutOptions.StartAndExpand };
+
+ layout.Children.AddVertical (label1);
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition () {Width = new GridLength (1, GridUnitType.Star)},
+ };
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition () {Height = new GridLength (1,GridUnitType.Star)},
+ };
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (new Rectangle (0, 0, 100, 20), label1.Bounds);
+ }
+
+ [Test]
+ public void TestEnd ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label { Platform = platform, IsPlatformEnabled = true, HorizontalOptions = LayoutOptions.End, VerticalOptions = LayoutOptions.EndAndExpand };
+
+ layout.Children.AddVertical (label1);
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition () {Width = new GridLength (1, GridUnitType.Star)},
+ };
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition () {Height = new GridLength (1,GridUnitType.Star)},
+ };
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (new Rectangle (900, 980, 100, 20), label1.Bounds);
+ }
+
+ [Test]
+ public void TestDefaultRowSpacing ()
+ {
+ var layout = new Grid ();
+
+ bool preferredSizeChanged = false;
+ layout.MeasureInvalidated += (sender, args) => {
+ preferredSizeChanged = true;
+ };
+
+ layout.RowSpacing = layout.RowSpacing;
+
+ Assert.False (preferredSizeChanged);
+
+ layout.RowSpacing = 10;
+
+ Assert.True (preferredSizeChanged);
+ }
+
+ [Test]
+ public void TestDefaultColumnSpacing ()
+ {
+ var layout = new Grid ();
+
+ bool preferredSizeChanged = false;
+ layout.MeasureInvalidated += (sender, args) => {
+ preferredSizeChanged = true;
+ };
+
+ layout.ColumnSpacing = layout.ColumnSpacing;
+
+ Assert.False (preferredSizeChanged);
+
+ layout.ColumnSpacing = 10;
+
+ Assert.True (preferredSizeChanged);
+ }
+
+ [Test]
+ public void TestAddCell ()
+ {
+ var layout = new Grid ();
+ bool preferredSizeChanged = false;
+ layout.MeasureInvalidated += (sender, args) => preferredSizeChanged = true;
+
+ Assert.False (preferredSizeChanged);
+
+ layout.Children.Add (new Label (), 0, 0);
+
+ Assert.True (preferredSizeChanged);
+ }
+
+ [Test]
+ public void TestMoveCell ()
+ {
+ var layout = new Grid ();
+ var label = new Label ();
+ layout.Children.Add (label, 0, 0);
+
+ bool preferredSizeChanged = false;
+ layout.MeasureInvalidated += (sender, args) => {
+ preferredSizeChanged = true;
+ };
+
+ Assert.False (preferredSizeChanged);
+ Grid.SetRow (label, 2);
+ Assert.True (preferredSizeChanged);
+
+ preferredSizeChanged = false;
+ Assert.False (preferredSizeChanged);
+ Grid.SetColumn (label, 2);
+ Assert.True (preferredSizeChanged);
+
+ preferredSizeChanged = false;
+ Assert.False (preferredSizeChanged);
+ Grid.SetRowSpan (label, 2);
+ Assert.True (preferredSizeChanged);
+
+ preferredSizeChanged = false;
+ Assert.False (preferredSizeChanged);
+ Grid.SetColumnSpan (label, 2);
+ Assert.True (preferredSizeChanged);
+ }
+
+ [Test]
+ public void TestInvalidBottomAdd ()
+ {
+ var layout = new Grid ();
+
+ Assert.Throws<ArgumentOutOfRangeException> (() => layout.Children.Add (new View (), 0, 1, 1, 0));
+ }
+
+ [Test]
+ public void TestZeroSizeConstraints ()
+ {
+ var layout = new Grid {Platform = new UnitPlatform ()};
+
+ Assert.AreEqual (new Size (0, 0), layout.GetSizeRequest (0, 0).Request);
+ Assert.AreEqual (new Size (0, 0), layout.GetSizeRequest (0, 10).Request);
+ Assert.AreEqual (new Size (0, 0), layout.GetSizeRequest (10, 0).Request);
+ }
+
+ [Test]
+ public void TestSizeRequest ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid {Platform = platform, IsPlatformEnabled = true};
+ layout.Children.AddVertical (new[] {
+ new View {Platform = platform, IsPlatformEnabled = true},
+ new View {Platform = platform, IsPlatformEnabled = true},
+ new View {Platform = platform, IsPlatformEnabled = true}
+ });
+
+ var result = layout.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request;
+ Assert.AreEqual (new Size (100, 72), result);
+ }
+
+ [Test]
+ public void TestLimitedSizeRequest ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid {Platform = platform, IsPlatformEnabled = true};
+ layout.Children.AddVertical (new[] {
+ new View {Platform = platform, IsPlatformEnabled = true},
+ new View {Platform = platform, IsPlatformEnabled = true},
+ new View {Platform = platform, IsPlatformEnabled = true}
+ });
+
+ var result = layout.GetSizeRequest (10, 10).Request;
+ Assert.AreEqual (new Size (100, 72), result);
+ }
+
+ [Test]
+ public void TestLimitedWidthSizeRequest ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid {Platform = platform, IsPlatformEnabled = true};
+ layout.Children.AddVertical (new[] {
+ new View {Platform = platform, IsPlatformEnabled = true},
+ new View {Platform = platform, IsPlatformEnabled = true},
+ new View {Platform = platform, IsPlatformEnabled = true}
+ });
+
+ var result = layout.GetSizeRequest (10, double.PositiveInfinity).Request;
+ Assert.AreEqual (new Size (100, 72), result);
+ }
+
+ [Test]
+ public void TestLimitedHeightSizeRequest ()
+ {
+
+ var platform = new UnitPlatform ();
+ var layout = new Grid {Platform = platform, IsPlatformEnabled = true};
+ layout.Children.AddVertical (new[] {
+ new View {Platform = platform, IsPlatformEnabled = true},
+ new View {Platform = platform, IsPlatformEnabled = true},
+ new View {Platform = platform, IsPlatformEnabled = true}
+ });
+
+ var result = layout.GetSizeRequest (double.PositiveInfinity, 10).Request;
+ Assert.AreEqual (new Size (100, 72), result);
+ }
+
+ [Test]
+ public void IgnoresInvisibleChildren ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid {Platform = platform};
+
+ var label1 = new Label { Platform = platform, IsVisible = false, IsPlatformEnabled = true, VerticalOptions = LayoutOptions.FillAndExpand };
+ var label2 = new Label { Platform = platform, IsPlatformEnabled = true};
+
+ layout.Children.AddVertical (label1);
+ layout.Children.AddVertical (label2);
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition { Width = GridLength.Auto },
+ };
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition { Height = GridLength.Auto},
+ new RowDefinition { Height = GridLength.Auto},
+ };
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (1000, layout.Width);
+ Assert.AreEqual (1000, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, -1, -1), label1.Bounds);
+ Assert.AreEqual (new Rectangle (0, 6, 100, 20), label2.Bounds);
+ }
+
+ [Test]
+ public void TestSizeRequestWithPadding ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid {Platform = platform, IsPlatformEnabled = true, Padding = new Thickness(20, 10, 15, 5)};
+ layout.Children.AddVertical (new[] {
+ new View {Platform = platform, IsPlatformEnabled = true},
+ new View {Platform = platform, IsPlatformEnabled = true},
+ new View {Platform = platform, IsPlatformEnabled = true}
+ });
+
+ var result = layout.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request;
+ Assert.AreEqual (new Size (135, 87), result);
+ }
+
+ [Test]
+ public void InvalidCallsToStaticMethods ()
+ {
+ Assert.Throws<ArgumentException> (() => Grid.SetRow (new Label (), -1));
+ Assert.Throws<ArgumentException> (() => Grid.SetColumn (new Label (), -1));
+ Assert.Throws<ArgumentException> (() => Grid.SetRowSpan (new Label (), 0));
+ Assert.Throws<ArgumentException> (() => Grid.SetColumnSpan (new Label (), 0));
+ }
+
+ [Test]
+ public void TestAddedBP ()
+ {
+ var platform = new UnitPlatform ();
+
+ var labela0 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var labela1 = new Label { Platform = platform, IsPlatformEnabled = true };
+ Grid.SetColumn (labela1, 1);
+ var labelb1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ Grid.SetRow (labelb1, 1);
+ Grid.SetColumn (labelb1, 1);
+ var labelc = new Label {Platform = platform, IsPlatformEnabled = true};
+ Grid.SetRow (labelc, 2);
+ Grid.SetColumnSpan (labelc, 2);
+
+ var layout = new Grid {
+ Platform = platform,
+ Children = {
+ labela0,
+ labela1,
+ labelb1,
+ labelc
+ }
+ };
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition { Width = GridLength.Auto },
+ new ColumnDefinition { Width = GridLength.Auto },
+ };
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition { Height = GridLength.Auto},
+ new RowDefinition { Height = GridLength.Auto},
+ new RowDefinition { Height = GridLength.Auto},
+ };
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (1000, layout.Width);
+ Assert.AreEqual (1000, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 100, 20), labela0.Bounds);
+ Assert.AreEqual (new Rectangle (106, 0, 100, 20), labela1.Bounds);
+ Assert.AreEqual (new Rectangle (106, 26, 100, 20), labelb1.Bounds);
+ Assert.AreEqual (new Rectangle (0, 52, 206, 20), labelc.Bounds);
+ }
+
+ [Test]
+ public void Remove ()
+ {
+ var platform = new UnitPlatform();
+
+ var labela0 = new Label { Platform = platform, IsPlatformEnabled = true };
+ var labela1 = new Label { Platform = platform, IsPlatformEnabled = true };
+ Grid.SetColumn(labela1, 1);
+ var labelb1 = new Label { Platform = platform, IsPlatformEnabled = true };
+ Grid.SetRow(labelb1, 1);
+ Grid.SetColumn(labelb1, 1);
+ var labelc = new Label { Platform = platform, IsPlatformEnabled = true };
+ Grid.SetRow(labelc, 2);
+ Grid.SetColumnSpan(labelc, 2);
+
+ var layout = new Grid {
+ Platform = platform,
+ Children = {
+ labela0,
+ labela1,
+ labelb1,
+ labelc
+ }
+ };
+
+ layout.Children.Remove (labela0);
+ Assert.False (layout.LogicalChildren.Contains (labela0));
+ }
+
+ [Test]
+ public void TestAbsoluteLayout ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label3 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition {Width = new GridLength (150)},
+ new ColumnDefinition {Width = new GridLength (150)},
+ new ColumnDefinition {Width = new GridLength (150)},
+ };
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition {Height = new GridLength (30)},
+ new RowDefinition {Height = new GridLength (30)},
+ new RowDefinition {Height = new GridLength (30)},
+ };
+ layout.Children.Add (label1, 0, 0);
+ layout.Children.Add (label2, 1, 1);
+ layout.Children.Add (label3, 2, 2);
+
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (1000, layout.Width);
+ Assert.AreEqual (1000, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 150, 30), label1.Bounds);
+ Assert.AreEqual (new Rectangle (156, 36, 150, 30), label2.Bounds);
+ Assert.AreEqual (new Rectangle (312, 72, 150, 30), label3.Bounds);
+ }
+
+ [Test]
+ public void TestAbsoluteLayoutWithSpans ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label3 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition {Width = new GridLength (150)},
+ new ColumnDefinition {Width = new GridLength (150)},
+ new ColumnDefinition {Width = new GridLength (150)},
+ };
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition {Height = new GridLength (30)},
+ new RowDefinition {Height = new GridLength (30)},
+ new RowDefinition {Height = new GridLength (30)},
+ };
+ layout.Children.Add (label1, 0, 2, 0, 1);
+ layout.Children.Add (label2, 2, 3, 0, 2);
+ layout.Children.Add (label3, 1, 2);
+
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (1000, layout.Width);
+ Assert.AreEqual (1000, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 306, 30), label1.Bounds);
+ Assert.AreEqual (new Rectangle (312, 0, 150, 66), label2.Bounds);
+ Assert.AreEqual (new Rectangle (156, 72, 150, 30), label3.Bounds);
+ }
+
+ [Test]
+ public void TestStarLayout ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label3 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition {Width = new GridLength (1, GridUnitType.Star)},
+ new ColumnDefinition {Width = new GridLength (1, GridUnitType.Star)},
+ new ColumnDefinition {Width = new GridLength (1, GridUnitType.Star)},
+ };
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition {Height = new GridLength (1, GridUnitType.Star)},
+ new RowDefinition {Height = new GridLength (1, GridUnitType.Star)},
+ new RowDefinition {Height = new GridLength (1, GridUnitType.Star)},
+ };
+ layout.Children.Add (label1, 0, 0);
+ layout.Children.Add (label2, 1, 1);
+ layout.Children.Add (label3, 2, 2);
+
+ var request = layout.GetSizeRequest (1002, 462);
+ Assert.AreEqual (312, request.Request.Width);
+ Assert.AreEqual (72, request.Request.Height);
+
+ layout.Layout (new Rectangle (0, 0, 1002, 462));
+ Assert.AreEqual (1002, layout.Width);
+ Assert.AreEqual (462, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 330, 150), label1.Bounds);
+ Assert.AreEqual (new Rectangle (336, 156, 330, 150), label2.Bounds);
+ Assert.AreEqual (new Rectangle (672, 312, 330, 150), label3.Bounds);
+ }
+
+ [Test]
+ public void TestStarLayoutWithSpans ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label3 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition {Width = new GridLength (1, GridUnitType.Star)},
+ new ColumnDefinition {Width = new GridLength (1, GridUnitType.Star)},
+ new ColumnDefinition {Width = new GridLength (1, GridUnitType.Star)},
+ };
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition {Height = new GridLength (1, GridUnitType.Star)},
+ new RowDefinition {Height = new GridLength (1, GridUnitType.Star)},
+ new RowDefinition {Height = new GridLength (1, GridUnitType.Star)},
+ };
+ layout.Children.Add (label1, 0, 2, 0, 1);
+ layout.Children.Add (label2, 2, 3, 0, 2);
+ layout.Children.Add (label3, 1, 2);
+
+ layout.Layout (new Rectangle (0, 0, 1002, 462));
+
+ Assert.AreEqual (1002, layout.Width);
+ Assert.AreEqual (462, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 666, 150), label1.Bounds);
+ Assert.AreEqual (new Rectangle (672, 0, 330, 306), label2.Bounds);
+ Assert.AreEqual (new Rectangle (336, 312, 330, 150), label3.Bounds);
+ }
+
+ [Test]
+ public void TestAutoLayout ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label3 = new Label {Platform = platform, IsPlatformEnabled = true};
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition {Width = GridLength.Auto},
+ new ColumnDefinition {Width = GridLength.Auto},
+ new ColumnDefinition {Width = GridLength.Auto},
+ };
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition {Height = GridLength.Auto},
+ new RowDefinition {Height = GridLength.Auto},
+ new RowDefinition {Height = GridLength.Auto},
+ };
+ layout.Children.Add (label1, 0, 0);
+ layout.Children.Add (label2, 1, 1);
+ layout.Children.Add (label3, 2, 2);
+
+
+ layout.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (1000, layout.Width);
+ Assert.AreEqual (1000, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 100, 20), label1.Bounds);
+ Assert.AreEqual (new Rectangle (106, 26, 100, 20), label2.Bounds);
+ Assert.AreEqual (new Rectangle (212, 52, 100, 20), label3.Bounds);
+ }
+
+ [Test]
+ public void TestAutoLayoutWithSpans ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label { Platform = platform, IsPlatformEnabled = true, WidthRequest = 150, Text = "label1" };
+ var label2 = new Label { Platform = platform, IsPlatformEnabled = true, HeightRequest = 50, Text = "label2" };
+ var label3 = new Label { Platform = platform, IsPlatformEnabled = true, Text = "label3" };
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition {Width = GridLength.Auto},
+ new ColumnDefinition {Width = GridLength.Auto},
+ new ColumnDefinition {Width = GridLength.Auto},
+ };
+ layout.RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition {Height = GridLength.Auto},
+ new RowDefinition {Height = GridLength.Auto},
+ new RowDefinition {Height = GridLength.Auto},
+ };
+ layout.Children.Add (label1, 0, 2, 0, 1);
+ layout.Children.Add (label2, 2, 3, 0, 2);
+ layout.Children.Add (label3, 1, 2);
+
+ layout.Layout (new Rectangle (0, 0, 1002, 462));
+
+ Assert.AreEqual (1002, layout.Width);
+ Assert.AreEqual (462, layout.Height);
+
+ Assert.AreEqual (new Rectangle (0, 0, 150, 20), label1.Bounds);
+ Assert.AreEqual (new Rectangle (156, 0, 100, 50), label2.Bounds);
+ Assert.AreEqual (new Rectangle (50, 56, 100, 20), label3.Bounds);
+ }
+
+ [Test]
+ public void AutoLayoutWithComplexSpans ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label3 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label4 = new Label {Platform = platform, IsPlatformEnabled = true, WidthRequest = 206};
+ var label5 = new Label {Platform = platform, IsPlatformEnabled = true, WidthRequest = 312};
+ var label6 = new Label {Platform = platform, IsPlatformEnabled = true, WidthRequest = 312};
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition {Width = GridLength.Auto},
+ new ColumnDefinition {Width = GridLength.Auto},
+ new ColumnDefinition {Width = GridLength.Auto},
+ new ColumnDefinition {Width = GridLength.Auto},
+ new ColumnDefinition {Width = GridLength.Auto},
+ };
+
+ layout.Children.Add (label1, 0, 0);
+ layout.Children.Add (label2, 1, 0);
+ layout.Children.Add (label3, 4, 0);
+ layout.Children.Add (label4, 2, 4, 0, 1);
+ layout.Children.Add (label5, 0, 3, 0, 1);
+ layout.Children.Add (label6, 2, 6, 0, 1);
+
+ layout.Layout (new Rectangle (0, 0, 1000, 500));
+
+ Assert.AreEqual (100, layout.ColumnDefinitions [0].ActualWidth);
+ Assert.AreEqual (100, layout.ColumnDefinitions [1].ActualWidth);
+ Assert.AreEqual (100, layout.ColumnDefinitions [2].ActualWidth);
+ Assert.AreEqual (100, layout.ColumnDefinitions [3].ActualWidth);
+ Assert.AreEqual (100, layout.ColumnDefinitions [4].ActualWidth);
+ }
+
+ [Test]
+ public void AutoLayoutExpandColumns ()
+ {
+ var platform = new UnitPlatform ();
+ var layout = new Grid ();
+ layout.Platform = platform;
+
+ var label1 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label2 = new Label {Platform = platform, IsPlatformEnabled = true};
+ var label3 = new Label {Platform = platform, IsPlatformEnabled = true, WidthRequest = 300};
+
+ layout.ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition { Width = GridLength.Auto },
+ new ColumnDefinition { Width = GridLength.Auto },
+ };
+
+ layout.Children.Add (label1, 0, 0);
+ layout.Children.Add (label2, 1, 0);
+ layout.Children.Add (label3, 0, 2, 0, 1);
+
+ layout.Layout (new Rectangle (0, 0, 1000, 500));
+
+ Assert.AreEqual (100, layout.ColumnDefinitions [0].ActualWidth);
+ Assert.AreEqual (194, layout.ColumnDefinitions [1].ActualWidth);
+ }
+
+ [Test]
+ public void GridHasDefaultDefinitions ()
+ {
+ var grid = new Grid ();
+ Assert.NotNull (grid.ColumnDefinitions);
+ Assert.NotNull (grid.RowDefinitions);
+ }
+
+ [Test]
+ public void DefaultDefinitionsArentSharedAccrossInstances ()
+ {
+ var grid0 = new Grid ();
+ var coldefs = grid0.ColumnDefinitions;
+ var rowdefs = grid0.RowDefinitions;
+
+ var grid1 = new Grid ();
+ Assert.AreNotSame (grid0, grid1);
+ Assert.AreNotSame (coldefs, grid1.ColumnDefinitions);
+ Assert.AreNotSame (rowdefs, grid1.RowDefinitions);
+ }
+
+ [Test]
+ public void ChildrenLayoutRespectAlignment ()
+ {
+ var platform = new UnitPlatform ();
+ var grid = new Grid {
+ ColumnDefinitions = { new ColumnDefinition { Width = new GridLength (300) } },
+ RowDefinitions = { new RowDefinition { Height = new GridLength (100) } },
+ Platform = platform,
+ };
+ var label = new Label {
+ Platform = platform,
+ IsPlatformEnabled = true,
+ VerticalOptions = LayoutOptions.Center,
+ HorizontalOptions = LayoutOptions.End,
+ };
+
+ grid.Children.Add (label);
+ grid.Layout (new Rectangle (0, 0, 500, 500));
+
+ Assert.AreEqual (new Rectangle (200, 40, 100, 20), label.Bounds);
+ }
+
+ [Test]
+ public void BothChildrenPropertiesUseTheSameBackendStore ()
+ {
+ var view = new View ();
+ var grid = new Grid ();
+ Assert.AreEqual (0, grid.Children.Count);
+ (grid as Layout<View>).Children.Add (view);
+ Assert.AreEqual (1, grid.Children.Count);
+ Assert.AreEqual (1, (grid as Layout<View>).Children.Count);
+ Assert.AreSame (view, (grid as Layout<View>).Children.First ());
+ Assert.AreSame (view, grid.Children.First ());
+ }
+
+ [Test]
+ //Issue 1384
+ public void ImageInAutoCellIsProperlyConstrained ()
+ {
+ var platform = new UnitPlatform ();
+
+ var content = new Image {
+ Aspect= Aspect.AspectFit,
+ Platform = platform,
+ IsPlatformEnabled = true
+ };
+ var grid = new Grid {
+ Platform = platform,
+ IsPlatformEnabled = true,
+ BackgroundColor = Color.Red,
+ VerticalOptions=LayoutOptions.Start,
+ Children = {
+ content
+ },
+ RowDefinitions = { new RowDefinition { Height = GridLength.Auto} },
+ ColumnDefinitions = { new ColumnDefinition { Width = GridLength.Auto } }
+ };
+ var view = new ContentView {
+ Platform = platform,
+ IsPlatformEnabled = true,
+ Content = grid,
+ };
+ view.Layout (new Rectangle (0, 0, 100, 100));
+ Assert.AreEqual (100, grid.Width);
+ Assert.AreEqual (20, grid.Height);
+
+ view.Layout (new Rectangle (0, 0, 50, 50));
+ Assert.AreEqual (50, grid.Width);
+ Assert.AreEqual (10, grid.Height);
+ }
+
+ [Test]
+ //Issue 1384
+ public void ImageInStarCellIsProperlyConstrained ()
+ {
+ var platform = new UnitPlatform ();
+
+ var content = new Image {
+ Aspect= Aspect.AspectFit,
+ Platform = platform,
+ MinimumHeightRequest = 10,
+ MinimumWidthRequest = 50,
+ IsPlatformEnabled = true
+ };
+ var grid = new Grid {
+ Platform = platform,
+ IsPlatformEnabled = true,
+ BackgroundColor = Color.Red,
+ VerticalOptions=LayoutOptions.Start,
+ Children = {
+ content
+ }
+ };
+ var view = new ContentView {
+ Platform = platform,
+ IsPlatformEnabled = true,
+ Content = grid,
+ };
+ view.Layout (new Rectangle (0, 0, 100, 100));
+ Assert.AreEqual (100, grid.Width);
+ Assert.AreEqual (20, grid.Height);
+
+ view.Layout (new Rectangle (0, 0, 50, 50));
+ Assert.AreEqual (50, grid.Width);
+ Assert.AreEqual (10, grid.Height);
+ }
+
+ [Test]
+ public void SizeRequestForStar ()
+ {
+ var platform = new UnitPlatform ();
+
+ var grid = new Grid{
+ RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition {Height = new GridLength (1, GridUnitType.Star)},
+ new RowDefinition {Height = GridLength.Auto},
+ },
+ ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition {Width = new GridLength (1, GridUnitType.Star)},
+ new ColumnDefinition {Width = GridLength.Auto},
+ }
+ };
+ grid.Children.Add (new Label {BackgroundColor = Color.Lime, Text="Foo", Platform = platform, IsPlatformEnabled = true});
+ grid.Children.Add (new Label {Text = "Bar", Platform = platform, IsPlatformEnabled = true},0,1);
+ grid.Children.Add (new Label {Text="Baz",XAlign = TextAlignment.End, Platform = platform, IsPlatformEnabled = true},1,0);
+ grid.Children.Add (new Label {Text="Qux", XAlign = TextAlignment.End, Platform = platform, IsPlatformEnabled = true},1,1);
+
+ var request = grid.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+ Assert.AreEqual (206, request.Request.Width);
+ Assert.AreEqual (46, request.Request.Height);
+
+ Assert.AreEqual (106, request.Minimum.Width);
+ Assert.AreEqual (26, request.Minimum.Height);
+ //
+ }
+
+ [Test]
+ //Issue 1497
+ public void StarRowsShouldOccupyTheSpace ()
+ {
+ var platform = new UnitPlatform ();
+ var label = new Label {
+ Platform = platform,
+ IsPlatformEnabled = true,
+ };
+ var Button = new Button {
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.EndAndExpand,
+ Platform = platform,
+ IsPlatformEnabled = true,
+ };
+ var grid = new Grid {
+ RowDefinitions = new RowDefinitionCollection {
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = new GridLength (1, GridUnitType.Star) },
+ },
+ ColumnDefinitions = new ColumnDefinitionCollection {
+ new ColumnDefinition {Width = new GridLength(1, GridUnitType.Star)},
+ },
+ Platform = platform,
+ IsPlatformEnabled = true,
+ };
+
+ grid.Children.Add (label);
+ grid.Children.Add (Button, 0, 1);
+
+ grid.Layout (new Rectangle (0, 0, 300, 300));
+ Assert.AreEqual (new Rectangle (0, 280, 300, 20), Button.Bounds);
+ }
+
+ [Test]
+ public void StarColumnsWithSpansDoNotExpandAutos ()
+ {
+ var grid = new Grid {
+ RowDefinitions = {
+ new RowDefinition {Height = GridLength.Auto},
+ new RowDefinition {Height = GridLength.Auto},
+ },
+ ColumnDefinitions = {
+ new ColumnDefinition {Width = new GridLength (1, GridUnitType.Auto)},
+ new ColumnDefinition {Width = new GridLength (1, GridUnitType.Auto)},
+ new ColumnDefinition {Width = new GridLength (1, GridUnitType.Star)}
+ },
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var spanBox = new BoxView {WidthRequest = 70, HeightRequest = 20, IsPlatformEnabled = true};
+ var box1 = new BoxView {WidthRequest = 20, HeightRequest = 20, IsPlatformEnabled = true};
+ var box2 = new BoxView {WidthRequest = 20, HeightRequest = 20, IsPlatformEnabled = true};
+ var box3 = new BoxView {WidthRequest = 20, HeightRequest = 20, IsPlatformEnabled = true};
+
+ grid.Children.Add (spanBox, 0, 3, 0, 1);
+ grid.Children.Add (box1, 0, 1);
+ grid.Children.Add (box2, 1, 1);
+ grid.Children.Add (box3, 2, 1);
+
+ grid.Layout (new Rectangle(0, 0, 300, 46));
+
+ Assert.AreEqual (new Rectangle (0, 0, 300, 20), spanBox.Bounds);
+ Assert.AreEqual (new Rectangle (0, 26, 20, 20), box1.Bounds);
+ Assert.AreEqual (new Rectangle (26, 26, 20, 20), box2.Bounds);
+ Assert.AreEqual (new Rectangle (52, 26, 248, 20), box3.Bounds);
+ }
+
+ static SizeRequest GetResizableSize (VisualElement view, double widthconstraint, double heightconstraint)
+ {
+ if (!(view is Editor))
+ return new SizeRequest(new Size (100, 20));
+ if (widthconstraint < 100)
+ return new SizeRequest(new Size (widthconstraint, 2000/widthconstraint));
+ if (heightconstraint < 20)
+ return new SizeRequest(new Size (2000/heightconstraint, heightconstraint));
+ return new SizeRequest(new Size (100, 20));
+ }
+
+ [Test]
+ //Issue 1893
+ public void EditorSpanningOnMultipleAutoRows ()
+ {
+ var grid0 = new Grid {
+ ColumnDefinitions = {
+ new ColumnDefinition { Width = GridLength.Auto },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ },
+ RowDefinitions = {
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto },
+ },
+ Platform = new UnitPlatform (GetResizableSize),
+ IsPlatformEnabled = true,
+ };
+
+ var label0 = new Label { IsPlatformEnabled = true };
+ var editor0 = new Editor { IsPlatformEnabled = true };
+ grid0.Children.Add (label0, 0, 0);
+ grid0.Children.Add (editor0, 1, 2, 0, 2);
+
+ grid0.Layout (new Rectangle (0, 0, 156, 200));
+ Assert.AreEqual (new Rectangle (106, 0, 50, 40), editor0.Bounds);
+
+ var grid1 = new Grid {
+ ColumnDefinitions = {
+ new ColumnDefinition { Width = GridLength.Auto },
+ new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) },
+ },
+ RowDefinitions = {
+ new RowDefinition { Height = GridLength.Auto },
+ },
+ Platform = new UnitPlatform (GetResizableSize),
+ IsPlatformEnabled = true,
+ };
+
+ var label1 = new Label { IsPlatformEnabled = true };
+ var editor1 = new Editor { IsPlatformEnabled = true };
+ grid1.Children.Add (label1, 0, 0);
+ grid1.Children.Add (editor1, 1, 0);
+
+ grid1.Layout (new Rectangle (0, 0, 156, 200));
+ Assert.AreEqual (new Rectangle (106, 0, 50, 40), editor1.Bounds);
+ }
+
+ [Test]
+ public void WidthBoundRequestRespected ()
+ {
+ var grid = new Grid {
+ ColumnDefinitions = {
+ new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }
+ },
+ RowDefinitions = {
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto },
+ },
+ Platform = new UnitPlatform (GetResizableSize),
+ IsPlatformEnabled = true,
+ RowSpacing = 0,
+ ColumnSpacing = 0,
+ };
+
+ var topLabel = new Editor {IsPlatformEnabled = true};
+ var leftLabel = new Label {IsPlatformEnabled = true, WidthRequest = 10};
+ var rightLabel = new Label {IsPlatformEnabled = true, WidthRequest = 10};
+
+ grid.Children.Add (topLabel, 0, 2, 0, 1);
+ grid.Children.Add (leftLabel, 0, 1);
+ grid.Children.Add (rightLabel, 1, 1);
+
+ var unboundRequest = grid.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+ var widthBoundRequest = grid.GetSizeRequest (50, double.PositiveInfinity);
+
+ Assert.AreEqual (new SizeRequest (new Size (20, 120), new Size (0, 120)), unboundRequest);
+ Assert.AreEqual (new SizeRequest (new Size (50, 60), new Size (0, 60)), widthBoundRequest);
+ }
+
+ [Test]
+ //https://bugzilla.xamarin.com/show_bug.cgi?id=31608
+ public void ColAndRowDefinitionsAreActuallyBindable ()
+ {
+ var rowdef = new RowDefinition ();
+ rowdef.SetBinding (RowDefinition.HeightProperty, "Height");
+ var grid = new Grid {
+ RowDefinitions = new RowDefinitionCollection { rowdef },
+ };
+ Assert.AreEqual (RowDefinition.HeightProperty.DefaultValue, rowdef.Height);
+ grid.BindingContext = new {Height = 32};
+ Assert.AreEqual (new GridLength(32), rowdef.Height);
+ }
+
+ [Test]
+ //https://bugzilla.xamarin.com/show_bug.cgi?id=31967
+ public void ChangingRowHeightViaBindingTriggersRedraw ()
+ {
+ var rowdef = new RowDefinition ();
+ rowdef.SetBinding (RowDefinition.HeightProperty, "Height");
+ var grid = new Grid {
+// RowDefinitions = new RowDefinitionCollection {
+// new RowDefinition { Height = GridLength.Auto },
+// rowdef
+// },
+ RowSpacing = 0,
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ };
+ grid.RowDefinitions.Add (new RowDefinition { Height = GridLength.Auto });
+ grid.RowDefinitions.Add (rowdef);
+
+ var label0 = new Label { IsPlatformEnabled = true };
+ Grid.SetRow (label0, 0);
+ var label1 = new Label { IsPlatformEnabled = true };
+ Grid.SetRow (label1, 1);
+
+ grid.BindingContext = new {Height = 0};
+ grid.Children.Add (label0);
+ grid.Children.Add (label1);
+
+ Assert.AreEqual (new SizeRequest (new Size (100, 20), new Size (0, 20)), grid.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity));
+ grid.BindingContext = new {Height = 42};
+ Assert.AreEqual (new SizeRequest (new Size (100, 62), new Size (0, 62)), grid.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity));
+ }
+
+ [Test]
+ public void InvalidationBlockedForAbsoluteCell ()
+ {
+ var grid = new Grid () {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ RowDefinitions = {
+ new RowDefinition { Height = new GridLength (100, GridUnitType.Absolute) }
+ },
+ ColumnDefinitions = {
+ new ColumnDefinition { Width = new GridLength (200, GridUnitType.Absolute) }
+ }
+ };
+
+ var label = new Label { IsPlatformEnabled = true };
+ grid.Children.Add (label);
+
+ bool invalidated = false;
+ grid.MeasureInvalidated += (sender, args) => {
+ invalidated = true;
+ };
+
+ label.Text = "Testing";
+
+ Assert.False (invalidated);
+ }
+
+ // because the constraint is internal, we need this
+ public enum HackLayoutConstraint
+ {
+ None = LayoutConstraint.None,
+ VerticallyFixed = LayoutConstraint.VerticallyFixed,
+ HorizontallyFixed = LayoutConstraint.HorizontallyFixed,
+ Fixed = LayoutConstraint.Fixed
+ }
+
+ [TestCase (HackLayoutConstraint.None, GridUnitType.Absolute, GridUnitType.Absolute, ExpectedResult = true)]
+ [TestCase (HackLayoutConstraint.None, GridUnitType.Star, GridUnitType.Absolute, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.None, GridUnitType.Absolute, GridUnitType.Star, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.None, GridUnitType.Auto, GridUnitType.Absolute, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.None, GridUnitType.Absolute, GridUnitType.Auto, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.None, GridUnitType.Star, GridUnitType.Star, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.None, GridUnitType.Auto, GridUnitType.Star, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.None, GridUnitType.Star, GridUnitType.Auto, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.None, GridUnitType.Auto, GridUnitType.Auto, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.VerticallyFixed, GridUnitType.Absolute, GridUnitType.Absolute, ExpectedResult = true)]
+ [TestCase (HackLayoutConstraint.VerticallyFixed, GridUnitType.Star, GridUnitType.Absolute, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.VerticallyFixed, GridUnitType.Absolute, GridUnitType.Star, ExpectedResult = true)]
+ [TestCase (HackLayoutConstraint.VerticallyFixed, GridUnitType.Auto, GridUnitType.Absolute, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.VerticallyFixed, GridUnitType.Absolute, GridUnitType.Auto, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.VerticallyFixed, GridUnitType.Star, GridUnitType.Star, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.VerticallyFixed, GridUnitType.Auto, GridUnitType.Star, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.VerticallyFixed, GridUnitType.Star, GridUnitType.Auto, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.VerticallyFixed, GridUnitType.Auto, GridUnitType.Auto, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.HorizontallyFixed, GridUnitType.Absolute, GridUnitType.Absolute, ExpectedResult = true)]
+ [TestCase (HackLayoutConstraint.HorizontallyFixed, GridUnitType.Star, GridUnitType.Absolute, ExpectedResult = true)]
+ [TestCase (HackLayoutConstraint.HorizontallyFixed, GridUnitType.Absolute, GridUnitType.Star, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.HorizontallyFixed, GridUnitType.Auto, GridUnitType.Absolute, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.HorizontallyFixed, GridUnitType.Absolute, GridUnitType.Auto, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.HorizontallyFixed, GridUnitType.Star, GridUnitType.Star, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.HorizontallyFixed, GridUnitType.Auto, GridUnitType.Star, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.HorizontallyFixed, GridUnitType.Star, GridUnitType.Auto, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.HorizontallyFixed, GridUnitType.Auto, GridUnitType.Auto, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.Fixed, GridUnitType.Absolute, GridUnitType.Absolute, ExpectedResult = true)]
+ [TestCase (HackLayoutConstraint.Fixed, GridUnitType.Star, GridUnitType.Absolute, ExpectedResult = true)]
+ [TestCase (HackLayoutConstraint.Fixed, GridUnitType.Absolute, GridUnitType.Star, ExpectedResult = true)]
+ [TestCase (HackLayoutConstraint.Fixed, GridUnitType.Auto, GridUnitType.Absolute, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.Fixed, GridUnitType.Absolute, GridUnitType.Auto, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.Fixed, GridUnitType.Star, GridUnitType.Star, ExpectedResult = true)]
+ [TestCase (HackLayoutConstraint.Fixed, GridUnitType.Auto, GridUnitType.Star, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.Fixed, GridUnitType.Star, GridUnitType.Auto, ExpectedResult = false)]
+ [TestCase (HackLayoutConstraint.Fixed, GridUnitType.Auto, GridUnitType.Auto, ExpectedResult = false)]
+ public bool InvalidationPropogationTests (HackLayoutConstraint gridConstraint, GridUnitType horizontalType, GridUnitType verticalType)
+ {
+ var grid = new Grid {
+ ComputedConstraint = (LayoutConstraint) gridConstraint,
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ RowDefinitions = {
+ new RowDefinition { Height = new GridLength (1, verticalType) }
+ },
+ ColumnDefinitions = {
+ new ColumnDefinition { Width = new GridLength (1, horizontalType) }
+ }
+ };
+
+ var label = new Label { IsPlatformEnabled = true };
+ grid.Children.Add (label);
+
+ bool invalidated = false;
+ grid.MeasureInvalidated += (sender, args) => {
+ invalidated = true;
+ };
+
+ label.Text = "Testing";
+
+ return !invalidated;
+ }
+ }
+
+ [TestFixture]
+ public class GridMeasureTests : BaseTestFixture
+ {
+ static List<Action> delayActions = new List<Action> ();
+
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices (invokeOnMainThread: a => { delayActions.Add (a); });
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void NestedInvalidateMeasureDoesNotCrash ()
+ {
+ var grid = new Grid {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new Label {
+ IsPlatformEnabled = true
+ };
+ grid.Children.Add (child);
+
+ var child2 = new Label {
+ IsPlatformEnabled = true
+ };
+ grid.Children.Add (child2);
+
+ bool fire = true;
+ child.SizeChanged += (sender, args) => {
+ if (fire)
+ child.InvalidateMeasure (InvalidationTrigger.Undefined);
+ fire = false;
+ };
+
+ grid.Layout (new Rectangle (0, 0, 100, 100));
+
+ foreach (var delayAction in delayActions) {
+ delayAction ();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/GroupViewUnitTests.cs b/Xamarin.Forms.Core.UnitTests/GroupViewUnitTests.cs
new file mode 100644
index 00000000..61e38cf1
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/GroupViewUnitTests.cs
@@ -0,0 +1,292 @@
+using System;
+using System.Collections;
+using System.Linq;
+using NUnit.Framework;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ internal class NaiveLayout : Layout<View>
+ {
+ protected override void LayoutChildren (double x, double y, double width, double height)
+ {
+ foreach (var child in LogicalChildren.Cast<View>()) {
+ var result = new Rectangle (x, y, 0, 0);
+ var request = child.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+ result.Width = request.Request.Width;
+ result.Height = request.Request.Height;
+
+ child.Layout (result);
+ }
+ }
+ }
+
+ [TestFixture]
+ public class LayoutUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestRaiseChild ()
+ {
+ var view = new NaiveLayout ();
+
+ var child1 = new View ();
+ var child2 = new View ();
+ var child3 = new View ();
+
+ view.Children.Add (child1);
+ view.Children.Add (child2);
+ view.Children.Add (child3);
+
+ bool reordered = false;
+ view.ChildrenReordered += (sender, args) => reordered = true;
+
+ view.RaiseChild (child1);
+
+ Assert.AreEqual (child1, view.LogicalChildren [2]);
+ Assert.True (reordered);
+
+ view.RaiseChild (child2);
+ Assert.AreEqual (child2, view.LogicalChildren [2]);
+ }
+
+ [Test]
+ public void TestRaiseUnownedChild ()
+ {
+ var view = new NaiveLayout ();
+
+ var child1 = new View ();
+ var child2 = new View ();
+ var child3 = new View ();
+
+ view.Children.Add (child1);
+ view.Children.Add (child3);
+
+ bool reordered = false;
+ view.ChildrenReordered += (sender, args) => reordered = true;
+
+ view.RaiseChild (child2);
+
+ Assert.False (reordered);
+ }
+
+ [Test]
+ public void TestLowerChild ()
+ {
+ var view = new NaiveLayout ();
+
+ var child1 = new View ();
+ var child2 = new View ();
+ var child3 = new View ();
+
+ view.Children.Add (child1);
+ view.Children.Add (child2);
+ view.Children.Add (child3);
+
+ bool reordered = false;
+ view.ChildrenReordered += (sender, args) => reordered = true;
+
+ view.LowerChild (child3);
+
+ Assert.AreEqual (child3, view.LogicalChildren [0]);
+ Assert.True (reordered);
+
+ view.LowerChild (child2);
+ Assert.AreEqual (child2, view.LogicalChildren [0]);
+ }
+
+ [Test]
+ public void TestLowerUnownedChild ()
+ {
+ var view = new NaiveLayout ();
+
+ var child1 = new View ();
+ var child2 = new View ();
+ var child3 = new View ();
+
+ view.Children.Add (child1);
+ view.Children.Add (child3);
+
+ bool reordered = false;
+ view.ChildrenReordered += (sender, args) => reordered = true;
+
+ view.LowerChild (child2);
+
+ Assert.False (reordered);
+ }
+
+ [Test]
+ public void TestAdd ()
+ {
+ var view = new NaiveLayout ();
+ var child1 = new View ();
+
+ bool added = false;
+ view.ChildAdded += (sender, args) => added = true;
+
+ view.Children.Add (child1);
+
+ Assert.True (added);
+ Assert.AreEqual (child1, view.LogicalChildren [0]);
+ }
+
+ [Test]
+ public void TestDoubleAdd ()
+ {
+ var view = new NaiveLayout ();
+ var child1 = new View ();
+ view.Children.Add (child1);
+
+ bool added = false;
+ view.ChildAdded += (sender, args) => added = true;
+
+ view.Children.Add (child1);
+
+ Assert.False (added);
+ Assert.AreEqual (child1, view.LogicalChildren [0]);
+ }
+
+ [Test]
+ public void TestRemove ()
+ {
+ var view = new NaiveLayout ();
+ var child1 = new View ();
+
+ view.Children.Add (child1);
+
+ bool removed = false;
+ view.ChildRemoved += (sender, args) => removed = true;
+
+ view.Children.Remove (child1);
+
+ Assert.True (removed);
+ Assert.False (view.LogicalChildren.Any ());
+ }
+
+ [Test]
+ public void TestGenericEnumerator ()
+ {
+ var view = new NaiveLayout ();
+
+ var children = new[] {
+ new View (),
+ new View (),
+ new View ()
+ };
+
+ foreach (var child in children)
+ view.Children.Add (child);
+
+ int i = 0;
+ foreach (var child in view.LogicalChildren) {
+ Assert.AreEqual (children[i], child);
+ i++;
+ }
+ }
+
+ [Test]
+ public void TestEnumerator ()
+ {
+ var view = new NaiveLayout ();
+
+ var children = new [] {
+ new View (),
+ new View (),
+ new View ()
+ };
+
+ foreach (var child in children)
+ view.Children.Add (child);
+
+ int i = 0;
+ var enumerator = (view.LogicalChildren as IEnumerable).GetEnumerator ();
+ while (enumerator.MoveNext ()) {
+ Assert.AreEqual (children [i], enumerator.Current as View);
+ i++;
+ }
+ }
+
+ [Test]
+ public void TestInitializerSyntax ()
+ {
+ View view1, view2;
+ var group = new NaiveLayout {
+ Children = {
+ (view1 = new View ()),
+ (view2 = new View ())
+ }
+ };
+
+ Assert.AreEqual (2, group.LogicalChildren.Count);
+ Assert.IsTrue (group.LogicalChildren.Contains (view1));
+ Assert.IsTrue (group.LogicalChildren.Contains (view2));
+ Assert.AreEqual (view1, group.LogicalChildren[0]);
+ }
+
+ [Test]
+ public void TestChildren ()
+ {
+ View view1, view2;
+ var group = new NaiveLayout {
+ Children = {
+ (view1 = new View ()),
+ (view2 = new View ())
+ }
+ };
+
+ Assert.AreEqual (2, group.Children.Count);
+ Assert.IsTrue (group.Children.Contains (view1));
+ Assert.IsTrue (group.Children.Contains (view2));
+ Assert.AreEqual (view1, group.Children[0]);
+ }
+
+ [Test]
+ public void TestDefaultLayout ()
+ {
+ View view;
+ var group = new NaiveLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Children = {
+ (view = new View {
+ WidthRequest = 50,
+ HeightRequest = 20,
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ })
+ }
+ };
+
+ group.Layout (new Rectangle (0, 0, 400, 400));
+
+ Assert.AreEqual (new Rectangle (0, 0, 50, 20), view.Bounds);
+ }
+
+ [Test]
+ public void ThrowsInvalidOperationOnSelfAdd ()
+ {
+ var group = new NaiveLayout ();
+ Assert.Throws<InvalidOperationException> (() => group.Children.Add (group));
+ }
+
+ [Test]
+ public void ReorderChildrenDoesNotRaiseChildAddedOrRemoved ()
+ {
+ var child1 = new BoxView ();
+ var child2 = new BoxView ();
+ var layout = new NaiveLayout {
+ Children = {child1, child2}
+ };
+
+ var added = false;
+ var removed = false;
+
+ layout.ChildAdded += (sender, args) => added = true;
+ layout.ChildRemoved += (sender, args) => removed = true;
+
+ layout.RaiseChild (child1);
+
+ Assert.False (added);
+ Assert.False (removed);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ImageSourceTests.cs b/Xamarin.Forms.Core.UnitTests/ImageSourceTests.cs
new file mode 100644
index 00000000..95aa5131
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ImageSourceTests.cs
@@ -0,0 +1,151 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using NUnit.Framework;
+using System.IO;
+using System.Threading.Tasks;
+using System.Threading;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ImageSourceTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup ()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [Test]
+ public void TestConstructors ()
+ {
+ var filesource = new FileImageSource { File = "File.png" };
+ Assert.AreEqual ("File.png", filesource.File);
+
+ Func<CancellationToken, Task<Stream>> stream = token => new Task<Stream> (() => new FileStream ("Foo", System.IO.FileMode.Open), token);
+ var streamsource = new StreamImageSource { Stream = stream };
+ Assert.AreEqual (stream, streamsource.Stream);
+ }
+
+ [Test]
+ public void TestHelpers ()
+ {
+ var imagesource = ImageSource.FromFile ("File.png");
+ Assert.That (imagesource, Is.TypeOf<FileImageSource> ());
+ Assert.AreEqual ("File.png", ((FileImageSource)imagesource).File);
+
+ Func<Stream> stream = () => new System.IO.FileStream ("Foo", System.IO.FileMode.Open);
+ var streamsource = ImageSource.FromStream (stream);
+ Assert.That (streamsource, Is.TypeOf<StreamImageSource> ());
+
+ var urisource = ImageSource.FromUri (new Uri ("http://xamarin.com/img.png"));
+ Assert.That (urisource, Is.TypeOf<UriImageSource> ());
+ Assert.AreEqual ("http://xamarin.com/img.png", ((UriImageSource)(urisource)).Uri.AbsoluteUri);
+ }
+
+ [Test]
+ public void TestImplicitFileConversion ()
+ {
+ var image = new Image { Source = "File.png" };
+ Assert.IsTrue (image.Source != null);
+ Assert.That (image.Source, Is.InstanceOf<FileImageSource> ());
+ Assert.AreEqual ("File.png", ((FileImageSource)(image.Source)).File);
+ }
+
+ [Test]
+ public void TestImplicitUriConversion ()
+ {
+ var image = new Image { Source = new Uri ("http://xamarin.com/img.png") };
+ Assert.IsTrue (image.Source != null);
+ Assert.That (image.Source, Is.InstanceOf<UriImageSource> ());
+ Assert.AreEqual ("http://xamarin.com/img.png", ((UriImageSource)(image.Source)).Uri.AbsoluteUri);
+ }
+
+ [Test]
+ public void TestImplicitStringUriConversion ()
+ {
+ var image = new Image { Source = "http://xamarin.com/img.png" };
+ Assert.IsTrue (image.Source != null);
+ Assert.That (image.Source, Is.InstanceOf<UriImageSource> ());
+ Assert.AreEqual ("http://xamarin.com/img.png", ((UriImageSource)(image.Source)).Uri.AbsoluteUri);
+ }
+
+ [Test]
+ public void TestSetStringValue ()
+ {
+ var image = new Image ();
+ image.SetValue (Image.SourceProperty, "foo.png");
+ Assert.IsNotNull (image.Source);
+ Assert.That (image.Source, Is.InstanceOf<FileImageSource> ());
+ Assert.AreEqual ("foo.png", ((FileImageSource)(image.Source)).File);
+ }
+
+ [Test]
+ public void TextBindToStringValue ()
+ {
+ var image = new Image ();
+ image.SetBinding (Image.SourceProperty, ".");
+ Assert.IsNull (image.Source);
+ image.BindingContext = "foo.png";
+ Assert.IsNotNull (image.Source);
+ Assert.That (image.Source, Is.InstanceOf<FileImageSource> ());
+ Assert.AreEqual ("foo.png", ((FileImageSource)(image.Source)).File);
+ }
+
+ [Test]
+ public void TextBindToStringUriValue ()
+ {
+ var image = new Image ();
+ image.SetBinding (Image.SourceProperty, ".");
+ Assert.IsNull (image.Source);
+ image.BindingContext = "http://xamarin.com/img.png";
+ Assert.IsNotNull (image.Source);
+ Assert.That (image.Source, Is.InstanceOf<UriImageSource> ());
+ Assert.AreEqual ("http://xamarin.com/img.png", ((UriImageSource)(image.Source)).Uri.AbsoluteUri);
+ }
+
+ [Test]
+ public void TextBindToUriValue ()
+ {
+ var image = new Image ();
+ image.SetBinding (Image.SourceProperty, ".");
+ Assert.IsNull (image.Source);
+ image.BindingContext = new Uri("http://xamarin.com/img.png");
+ Assert.IsNotNull (image.Source);
+ Assert.That (image.Source, Is.InstanceOf<UriImageSource> ());
+ Assert.AreEqual ("http://xamarin.com/img.png", ((UriImageSource)(image.Source)).Uri.AbsoluteUri);
+ }
+
+ class MockImageSource : ImageSource
+ {
+ }
+
+ [Test]
+ public void TestBindingContextPropagation ()
+ {
+ var context = new object ();
+ var image = new Image ();
+ image.BindingContext = context;
+ var source = new MockImageSource ();
+ image.Source = source;
+ Assert.AreSame (context, source.BindingContext);
+
+ image = new Image ();
+ source = new MockImageSource ();
+ image.Source = source;
+ image.BindingContext = context;
+ Assert.AreSame (context, source.BindingContext);
+ }
+
+ [Test]
+ public void ImplicitCastOnAbsolutePathsShouldCreateAFileImageSource ()
+ {
+ var path = "/private/var/mobile/Containers/Data/Application/B1E5AB19-F815-4B4A-AB97-BD4571D53743/Documents/temp/IMG_20140603_150614_preview.jpg";
+ var image = new Image { Source = path };
+ Assert.That (image.Source, Is.TypeOf<FileImageSource> ());
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ImageTests.cs b/Xamarin.Forms.Core.UnitTests/ImageTests.cs
new file mode 100644
index 00000000..1e2546db
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ImageTests.cs
@@ -0,0 +1,261 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using NUnit.Framework;
+using System.IO;
+using System.Threading.Tasks;
+using System.Threading;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ImageTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup ()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices (getStreamAsync: GetStreamAsync);
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void TestSizing ()
+ {
+ var image = new Image {Source = ImageSource.FromFile ("File.png"), Platform = new UnitPlatform (), IsPlatformEnabled = true};
+
+ var result = image.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+
+ Assert.AreEqual (100, result.Request.Width);
+ Assert.AreEqual (20, result.Request.Height);
+ }
+
+ [Test]
+ public void TestAspectSizingWithConstrainedHeight ()
+ {
+ var image = new Image {Source = ImageSource.FromFile ("File.png"), Platform = new UnitPlatform (), IsPlatformEnabled = true};
+
+ var result = image.GetSizeRequest (double.PositiveInfinity, 10);
+
+ Assert.AreEqual (50, result.Request.Width);
+ Assert.AreEqual (10, result.Request.Height);
+ }
+
+ [Test]
+ public void TestAspectSizingWithConstrainedWidth ()
+ {
+ var image = new Image {Source = ImageSource.FromFile ("File.png"), Platform = new UnitPlatform (), IsPlatformEnabled = true};
+
+ var result = image.GetSizeRequest (25, double.PositiveInfinity);
+
+ Assert.AreEqual (25, result.Request.Width);
+ Assert.AreEqual (5, result.Request.Height);
+ }
+
+ [Test]
+ public void TestAspectFillSizingWithConstrainedHeight ()
+ {
+ var image = new Image {Source = ImageSource.FromFile ("File.png"), Platform = new UnitPlatform (), IsPlatformEnabled = true};
+
+ image.Aspect = Aspect.AspectFill;
+ var result = image.GetSizeRequest (double.PositiveInfinity, 10);
+
+ Assert.AreEqual (50, result.Request.Width);
+ Assert.AreEqual (10, result.Request.Height);
+ }
+
+ [Test]
+ public void TestAspectFillSizingWithConstrainedWidth ()
+ {
+ var image = new Image {Source = ImageSource.FromFile ("File.png"), Platform = new UnitPlatform (), IsPlatformEnabled = true};
+
+ image.Aspect = Aspect.AspectFill;
+ var result = image.GetSizeRequest (25, double.PositiveInfinity);
+
+ Assert.AreEqual (25, result.Request.Width);
+ Assert.AreEqual (5, result.Request.Height);
+ }
+
+ [Test]
+ public void TestFillSizingWithConstrainedHeight ()
+ {
+ var image = new Image {Source = ImageSource.FromFile ("File.png"), Platform = new UnitPlatform (), IsPlatformEnabled = true};
+
+ image.Aspect = Aspect.AspectFill;
+ var result = image.GetSizeRequest (double.PositiveInfinity, 10);
+
+ Assert.AreEqual (50, result.Request.Width);
+ Assert.AreEqual (10, result.Request.Height);
+ }
+
+ [Test]
+ public void TestFillSizingWithConstrainedWidth ()
+ {
+ var image = new Image {Source = ImageSource.FromFile ("File.png"), Platform = new UnitPlatform (), IsPlatformEnabled = true};
+
+ image.Aspect = Aspect.AspectFill;
+ var result = image.GetSizeRequest (25, double.PositiveInfinity);
+
+ Assert.AreEqual (25, result.Request.Width);
+ Assert.AreEqual (5, result.Request.Height);
+ }
+
+ [Test]
+ public void TestSizeChanged ()
+ {
+ var image = new Image { Source = "File0.png" };
+ Assert.AreEqual ("File0.png", ((FileImageSource)image.Source).File);
+
+ var preferredSizeChanged = false;
+ image.MeasureInvalidated += (sender, args) => preferredSizeChanged = true;
+
+ image.Source = "File1.png";
+ Assert.AreEqual ("File1.png", ((FileImageSource)image.Source).File);
+ Assert.True (preferredSizeChanged);
+ }
+
+ [Test]
+ public void TestSource ()
+ {
+ var image = new Image ();
+
+ Assert.IsNull (image.Source);
+
+ bool signaled = false;
+ image.PropertyChanged += (sender, e) => {
+ if (e.PropertyName == "Source")
+ signaled = true;
+ };
+
+ var source = ImageSource.FromFile ("File.png");
+ image.Source = source;
+
+ Assert.AreEqual (source, image.Source);
+ Assert.True (signaled);
+ }
+
+ [Test]
+ public void TestSourceDoubleSet ()
+ {
+ var image = new Image {Source = ImageSource.FromFile ("File.png")};
+
+ bool signaled = false;
+ image.PropertyChanged += (sender, e) => {
+ if (e.PropertyName == "Source")
+ signaled = true;
+ };
+
+ image.Source = image.Source;
+
+ Assert.False (signaled);
+ }
+
+ [Test]
+ public void TestFileImageSourceChanged ()
+ {
+ var source = (FileImageSource)ImageSource.FromFile ("File.png");
+
+ bool signaled = false;
+ source.SourceChanged += (sender, e) => {
+ signaled = true;
+ };
+
+ source.File = "Other.png";
+ Assert.AreEqual ("Other.png", source.File);
+
+ Assert.True (signaled);
+ }
+
+ [Test]
+ public void TestFileImageSourcePropertiesChangedTriggerResize ()
+ {
+ var source = new FileImageSource ();
+ var image = new Image { Source = source };
+ bool fired = false;
+ image.MeasureInvalidated += (sender, e) => fired = true;
+ Assert.Null (source.File);
+ source.File = "foo.png";
+ Assert.NotNull (source.File);
+ Assert.True (fired);
+ }
+
+ [Test]
+ public void TestStreamImageSourcePropertiesChangedTriggerResize ()
+ {
+ var source = new StreamImageSource ();
+ var image = new Image { Source = source };
+ bool fired = false;
+ image.MeasureInvalidated += (sender, e) => fired = true;
+ Assert.Null (source.Stream);
+ source.Stream = token => Task.FromResult<Stream> (null);
+ Assert.NotNull (source.Stream);
+ Assert.True (fired);
+ }
+
+ [Test]
+ public void TestImageSourceToNullCancelsLoading ()
+ {
+ var image = new Image ();
+ var mockImageRenderer = new MockImageRenderer (image);
+ var loader = new UriImageSource { Uri = new Uri ("http://www.public-domain-image.com/free-images/miscellaneous/big-high-border-fence.jpg") };
+ image.Source = loader;
+ Assert.IsTrue (image.IsLoading);
+ image.Source = null;
+ Assert.IsFalse (image.IsLoading);
+ Assert.IsTrue (cancelled);
+ }
+
+ static bool cancelled;
+
+ static async Task<Stream> GetStreamAsync (Uri uri, CancellationToken cancellationToken)
+ {
+ try {
+ await Task.Delay (5000, cancellationToken);
+ } catch (TaskCanceledException ex) {
+ cancelled = true;
+ throw ex;
+ }
+
+ if (cancellationToken.IsCancellationRequested) {
+ cancelled = true;
+ throw new TaskCanceledException ();
+ }
+
+ var stream = typeof(ImageTests).Assembly.GetManifestResourceStream (uri.LocalPath.Substring (1));
+ return stream;
+ }
+
+ class MockImageRenderer
+ {
+ public MockImageRenderer (Image element)
+ {
+ Element = element;
+ Element.PropertyChanged += ( sender, e) => {
+ if (e.PropertyName == nameof (Image.Source))
+ Load ();
+ };
+ }
+
+ public Image Element { get; set; }
+
+ public async void Load ()
+ {
+ if (initialLoad && Element.Source != null) {
+ initialLoad = false;
+ ((IElementController)Element).SetValueFromRenderer (Image.IsLoadingPropertyKey, true);
+ await (Element.Source as UriImageSource).GetStreamAsync ();
+ ((IElementController)Element).SetValueFromRenderer (Image.IsLoadingPropertyKey, false);
+ }
+ }
+
+ bool initialLoad = true;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/Images/crimson.jpg b/Xamarin.Forms.Core.UnitTests/Images/crimson.jpg
new file mode 100644
index 00000000..3db7bb21
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/Images/crimson.jpg
Binary files differ
diff --git a/Xamarin.Forms.Core.UnitTests/KeyboardTests.cs b/Xamarin.Forms.Core.UnitTests/KeyboardTests.cs
new file mode 100644
index 00000000..773f0903
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/KeyboardTests.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ internal class KeyboardTests : BaseTestFixture
+ {
+ [Test]
+ public void KeyboardTypesAreCorrect ()
+ {
+ Assert.True (Keyboard.Chat is ChatKeyboard);
+ Assert.True (Keyboard.Email is EmailKeyboard);
+ Assert.True (Keyboard.Numeric is NumericKeyboard);
+ Assert.True (Keyboard.Telephone is TelephoneKeyboard);
+ Assert.True (Keyboard.Text is TextKeyboard);
+ Assert.True (Keyboard.Url is UrlKeyboard);
+ }
+ }
+
+ [TestFixture]
+ internal class KeyboardTypeConverterTests : BaseTestFixture
+ {
+ [Test]
+ public void ConversionConvert ()
+ {
+
+ var converter = new KeyboardTypeConverter ();
+ Assert.True (converter.CanConvertFrom (typeof(string)));
+ foreach (var kvp in new Dictionary<string, Keyboard> {
+ {"Keyboard.Default", Keyboard.Default},
+ {"Keyboard.Email", Keyboard.Email},
+ {"Keyboard.Text", Keyboard.Text},
+ {"Keyboard.Url", Keyboard.Url},
+ {"Keyboard.Telephone", Keyboard.Telephone},
+ {"Keyboard.Chat", Keyboard.Chat},
+ })
+ Assert.AreSame (kvp.Value, converter.ConvertFromInvariantString (kvp.Key));
+ }
+
+ [Test]
+ public void ConversionFail ()
+ {
+ var converter = new KeyboardTypeConverter ();
+ Assert.Throws<InvalidOperationException> (() => converter.ConvertFromInvariantString ("Foo"));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/LabelTests.cs b/Xamarin.Forms.Core.UnitTests/LabelTests.cs
new file mode 100644
index 00000000..f56f792d
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/LabelTests.cs
@@ -0,0 +1,296 @@
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using NUnit.Framework;
+using NUnit.Framework.Constraints;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class LabelTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup ()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown ()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void TextAndAttributedTextMutuallyExclusive ()
+ {
+ var label = new Label ();
+ Assert.IsNull (label.Text);
+ Assert.IsNull (label.FormattedText);
+
+ label.Text = "Foo";
+ Assert.AreEqual ("Foo", label.Text);
+ Assert.IsNull (label.FormattedText);
+
+ var fs = new FormattedString ();
+ label.FormattedText = fs;
+ Assert.IsNull (label.Text);
+ Assert.AreSame (fs, label.FormattedText);
+
+ label.Text = "Foo";
+ Assert.AreEqual ("Foo", label.Text);
+ Assert.IsNull (label.FormattedText);
+ }
+
+ [Test]
+ public void AssignToFontStructUpdatesFontFamily (
+ [Values (NamedSize.Default, NamedSize.Large, NamedSize.Medium, NamedSize.Small, NamedSize.Micro)] NamedSize size,
+ [Values (FontAttributes.None, FontAttributes.Bold, FontAttributes.Italic, FontAttributes.Bold | FontAttributes.Italic)] FontAttributes attributes)
+ {
+ var label = new Label {Platform = new UnitPlatform ()};
+ double startSize = label.FontSize;
+ var startAttributes = label.FontAttributes;
+
+ bool firedSizeChanged = false;
+ bool firedAttributesChanged = false;
+ label.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == Label.FontSizeProperty.PropertyName)
+ firedSizeChanged = true;
+ if (args.PropertyName == Label.FontAttributesProperty.PropertyName)
+ firedAttributesChanged = true;
+ };
+
+ label.Font = Font.OfSize ("Testing123", size).WithAttributes (attributes);
+
+ Assert.AreEqual (Device.GetNamedSize (size, typeof (Label), true), label.FontSize);
+ Assert.AreEqual (attributes, label.FontAttributes);
+ Assert.AreEqual (startSize != label.FontSize, firedSizeChanged);
+ Assert.AreEqual (startAttributes != label.FontAttributes, firedAttributesChanged);
+ }
+
+ [Test]
+ public void AssignToFontFamilyUpdatesFont ()
+ {
+ var label = new Label {Platform = new UnitPlatform ()};
+
+ label.FontFamily = "CrazyFont";
+ Assert.AreEqual (label.Font, Font.OfSize ("CrazyFont", label.FontSize));
+ }
+
+ [Test]
+ public void AssignToFontSizeUpdatesFont ()
+ {
+ var label = new Label {Platform = new UnitPlatform ()};
+
+ label.FontSize = 1000;
+ Assert.AreEqual (label.Font, Font.SystemFontOfSize (1000));
+ }
+
+ [Test]
+ public void AssignedToFontSizeUpdatesFontDouble ()
+ {
+ var label = new Label {Platform = new UnitPlatform ()};
+
+ label.FontSize = 10.7;
+ Assert.AreEqual (label.Font, Font.SystemFontOfSize (10.7));
+ }
+
+ [Test]
+ public void AssignedToFontSizeDouble ()
+ {
+ var label = new Label {Platform = new UnitPlatform ()};
+
+ label.FontSize = 10.7;
+ Assert.AreEqual (label.FontSize, 10.7);
+ }
+
+
+ [Test]
+ public void AssignToFontAttributesUpdatesFont ()
+ {
+ var label = new Label {Platform = new UnitPlatform ()};
+
+ label.FontAttributes = FontAttributes.Italic | FontAttributes.Bold;
+ Assert.AreEqual (label.Font, Font.SystemFontOfSize (label.FontSize, FontAttributes.Bold | FontAttributes.Italic));
+ }
+
+ [Test]
+ public void LabelResizesWhenFontChanges ()
+ {
+ var label = new Label {Platform = new UnitPlatform ((ve, w, h) => {
+ var l = (Label) ve;
+ return new SizeRequest(new Size(l.Font.FontSize, l.Font.FontSize));
+ }), IsPlatformEnabled = true};
+
+ Assert.AreEqual (label.Font.FontSize, label.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request.Width);
+
+ bool fired = false;
+
+ label.MeasureInvalidated += (sender, args) => {
+ Assert.AreEqual (25, label.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request.Width);
+ fired = true;
+ };
+
+
+ label.FontSize = 25;
+
+ Assert.True (fired);
+ }
+
+ [Test]
+ public void FontSizeConverterTests ()
+ {
+ var converter = new FontSizeConverter ();
+ Assert.AreEqual (12, converter.ConvertFromInvariantString ("12"));
+ Assert.AreEqual (10.7, converter.ConvertFromInvariantString ("10.7"));
+ }
+
+ [Test]
+ public void FontSizeCanBeSetFromStyle ()
+ {
+ var label = new Label ();
+
+ Assert.AreEqual (10.0, label.FontSize);
+
+ label.SetValue (Label.FontSizeProperty, 1.0, true);
+ Assert.AreEqual (1.0, label.FontSize);
+ }
+
+ [Test]
+ public void ManuallySetFontSizeNotOverridenByStyle ()
+ {
+ var label = new Label ();
+
+ Assert.AreEqual (10.0, label.FontSize);
+
+ label.SetValue (Label.FontSizeProperty, 2.0, false);
+ Assert.AreEqual (2.0, label.FontSize);
+
+ label.SetValue (Label.FontSizeProperty, 1.0, true);
+ Assert.AreEqual (2.0, label.FontSize);
+ }
+
+ [Test]
+ public void ChangingHorizontalTextAlignmentFiresXAlignChanged ()
+ {
+ var label = new Label () { HorizontalTextAlignment = TextAlignment.Center };
+
+ var xAlignFired = false;
+ var horizontalTextAlignmentFired = false;
+
+ label.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "XAlign") {
+ xAlignFired = true;
+ } else if (args.PropertyName == Label.HorizontalTextAlignmentProperty.PropertyName) {
+ horizontalTextAlignmentFired = true;
+ }
+ };
+
+ label.HorizontalTextAlignment = TextAlignment.End;
+
+ Assert.True(xAlignFired);
+ Assert.True(horizontalTextAlignmentFired);
+ }
+
+ [Test]
+ public void ChangingVerticalTextAlignmentFiresYAlignChanged ()
+ {
+ var label = new Label () { VerticalTextAlignment = TextAlignment.Center };
+
+ var yAlignFired = false;
+ var verticalTextAlignmentFired = false;
+
+ label.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "YAlign") {
+ yAlignFired = true;
+ } else if (args.PropertyName == Label.VerticalTextAlignmentProperty.PropertyName) {
+ verticalTextAlignmentFired = true;
+ }
+ };
+
+ label.VerticalTextAlignment = TextAlignment.End;
+
+ Assert.True (yAlignFired);
+ Assert.True (verticalTextAlignmentFired);
+ }
+
+ [Test]
+ public void EntryCellXAlignBindingMatchesHorizontalTextAlignmentBinding ()
+ {
+ var vm = new ViewModel ();
+ vm.HorizontalAlignment = TextAlignment.Center;
+
+ var labelXAlign = new Label () { BindingContext = vm };
+ labelXAlign.SetBinding (Label.XAlignProperty, new Binding ("HorizontalAlignment"));
+
+ var labelHorizontalTextAlignment = new Label () { BindingContext = vm };
+ labelHorizontalTextAlignment.SetBinding (Label.HorizontalTextAlignmentProperty, new Binding ("HorizontalAlignment"));
+
+ Assert.AreEqual (TextAlignment.Center, labelXAlign.XAlign);
+ Assert.AreEqual (TextAlignment.Center, labelHorizontalTextAlignment.HorizontalTextAlignment);
+
+ vm.HorizontalAlignment = TextAlignment.End;
+
+ Assert.AreEqual (TextAlignment.End, labelXAlign.XAlign);
+ Assert.AreEqual (TextAlignment.End, labelHorizontalTextAlignment.HorizontalTextAlignment);
+ }
+
+ [Test]
+ public void EntryCellYAlignBindingMatchesVerticalTextAlignmentBinding ()
+ {
+ var vm = new ViewModel ();
+ vm.VerticalAlignment = TextAlignment.Center;
+
+ var labelYAlign = new Label () { BindingContext = vm };
+ labelYAlign.SetBinding (Label.YAlignProperty, new Binding ("VerticalAlignment"));
+
+ var labelVerticalTextAlignment = new Label () { BindingContext = vm };
+ labelVerticalTextAlignment.SetBinding (Label.VerticalTextAlignmentProperty, new Binding ("VerticalAlignment"));
+
+ Assert.AreEqual (TextAlignment.Center, labelYAlign.YAlign);
+ Assert.AreEqual (TextAlignment.Center, labelVerticalTextAlignment.VerticalTextAlignment);
+
+ vm.VerticalAlignment = TextAlignment.End;
+
+ Assert.AreEqual (TextAlignment.End, labelYAlign.YAlign);
+ Assert.AreEqual (TextAlignment.End, labelVerticalTextAlignment.VerticalTextAlignment);
+ }
+
+ sealed class ViewModel : INotifyPropertyChanged
+ {
+ TextAlignment horizontalAlignment;
+ TextAlignment verticalAlignment;
+
+ public TextAlignment HorizontalAlignment
+ {
+ get { return horizontalAlignment; }
+ set
+ {
+ horizontalAlignment = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public TextAlignment VerticalAlignment
+ {
+ get { return verticalAlignment; }
+ set
+ {
+ verticalAlignment = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChanged?.Invoke (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Core.UnitTests/LayoutOptionsUnitTests.cs b/Xamarin.Forms.Core.UnitTests/LayoutOptionsUnitTests.cs
new file mode 100644
index 00000000..476cf73c
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/LayoutOptionsUnitTests.cs
@@ -0,0 +1,22 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class LayoutOptionsUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestTypeConverter ()
+ {
+ var converter = new LayoutOptionsConverter ();
+ Assert.True (converter.CanConvertFrom (typeof(string)));
+ Assert.AreEqual (LayoutOptions.Center, converter.ConvertFromInvariantString ("LayoutOptions.Center"));
+ Assert.AreEqual (LayoutOptions.Center, converter.ConvertFromInvariantString ("Center"));
+ Assert.AreNotEqual (LayoutOptions.CenterAndExpand, converter.ConvertFromInvariantString ("Center"));
+ Assert.Throws<InvalidOperationException> (() => converter.ConvertFromInvariantString ("foo"));
+ Assert.Throws<InvalidOperationException> (() => converter.ConvertFromInvariantString ("foo.bar"));
+ Assert.Throws<InvalidOperationException> (() => converter.ConvertFromInvariantString ("foo.bar.baz"));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/ListProxyTests.cs b/Xamarin.Forms.Core.UnitTests/ListProxyTests.cs
new file mode 100644
index 00000000..6fa85d2c
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ListProxyTests.cs
@@ -0,0 +1,426 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ListProxyTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void ListCount()
+ {
+ var list = new List<string> { "foo", "bar" };
+ var proxy = new ListProxy (list);
+
+ Assert.AreEqual (list.Count, proxy.Count);
+ list.Add ("baz");
+ Assert.AreEqual (list.Count, proxy.Count);
+ }
+
+ [Test]
+ public void CollectionCount()
+ {
+ var list = new Collection<string> { "foo", "bar" };
+ var proxy = new ListProxy (list);
+
+ Assert.AreEqual (list.Count, proxy.Count);
+ list.Add ("baz");
+ Assert.AreEqual (list.Count, proxy.Count);
+ }
+
+ [Test]
+ [Description ("Count should ensure that the window is created if neccessary")]
+ public void EnumerableInitialCount()
+ {
+ var enumerable = Enumerable.Range (0, 100);
+ var proxy = new ListProxy (enumerable, 10);
+
+ Assert.AreEqual (10, proxy.Count);
+ }
+
+ [Test]
+ public void EnumerableCount()
+ {
+ var enumerable = Enumerable.Range (0, 100);
+ var proxy = new ListProxy (enumerable, 10);
+
+ int changed = 0;
+ proxy.CountChanged += (o, e) => changed++;
+
+ var enumerator = proxy.GetEnumerator();
+ enumerator.MoveNext();
+
+ Assert.AreEqual (10, proxy.Count);
+ Assert.AreEqual (1, changed);
+
+ enumerator.MoveNext();
+
+ Assert.AreEqual (10, proxy.Count);
+ Assert.AreEqual (1, changed);
+
+ while (enumerator.MoveNext()) {
+ }
+
+ enumerator.Dispose();
+
+ Assert.AreEqual (100, proxy.Count);
+ Assert.AreEqual (19, changed);
+
+ using (enumerator = proxy.GetEnumerator()) {
+
+ Assert.AreEqual (100, proxy.Count);
+
+ while (enumerator.MoveNext())
+ Assert.AreEqual (100, proxy.Count);
+
+ Assert.AreEqual (100, proxy.Count);
+ }
+
+ Assert.AreEqual (19, changed);
+ }
+
+ [Test]
+ public void InsideWindowSize()
+ {
+ var numbers = Enumerable.Range (0, 100);
+ var proxy = new ListProxy (numbers, 10);
+
+ int i = (int)proxy[5];
+ Assert.That (i, Is.EqualTo (5));
+ }
+
+ [Test]
+ public void IndexOutsideWindowSize()
+ {
+ var numbers = Enumerable.Range (0, 100);
+ var proxy = new ListProxy (numbers, 10);
+
+ int i = (int)proxy[50];
+ Assert.That (i, Is.EqualTo (50));
+ }
+
+ [Test]
+ public void IndexInsideToOutsideWindowSize()
+ {
+ var numbers = Enumerable.Range (0, 100);
+ var proxy = new ListProxy (numbers, 10);
+
+ int i = (int)proxy[5];
+ Assert.That (i, Is.EqualTo (5));
+
+ i = (int)proxy[50];
+ Assert.That (i, Is.EqualTo (50));
+ }
+
+ [Test]
+ public void IndexOutsideToPreWindowSize()
+ {
+ var numbers = Enumerable.Range (0, 100);
+ var proxy = new ListProxy (numbers, 10);
+
+ int i = (int)proxy[50];
+ Assert.That (i, Is.EqualTo (50));
+
+ i = (int)proxy[5];
+ Assert.That (i, Is.EqualTo (5));
+ }
+
+ [Test]
+ public void EnumerableIndexOutOfRange()
+ {
+ var numbers = Enumerable.Range (0, 100);
+ var proxy = new ListProxy (numbers);
+
+ Assert.That (() => proxy[100], Throws.InstanceOf<ArgumentOutOfRangeException>());
+ }
+
+ class IntCollection
+ : ICollection
+ {
+ readonly List<int> ints;
+
+ public IntCollection (IEnumerable<int> ints)
+ {
+ this.ints = ints.ToList();
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return ints.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public void CopyTo (Array array, int index)
+ {
+ throw new NotImplementedException();
+ }
+
+ public int Count { get { return ints.Count; }}
+
+ public object SyncRoot
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public bool IsSynchronized
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public bool IsReadOnly { get { return true; } }
+ }
+
+ [Test]
+ public void CollectionIndexOutOfRange()
+ {
+ var numbers = new IntCollection (Enumerable.Range (0, 100));
+ var proxy = new ListProxy (numbers);
+
+ Assert.That (() => proxy[100], Throws.InstanceOf<ArgumentOutOfRangeException>());
+ }
+
+ [Test]
+ public void ListIndexOutOfRange()
+ {
+ var numbers = Enumerable.Range (0, 100).ToList();
+ var proxy = new ListProxy (numbers);
+
+ Assert.That (() => proxy[100], Throws.InstanceOf<ArgumentOutOfRangeException>());
+ }
+
+ [Test]
+ public void CollectionChangedWhileEnumerating()
+ {
+ var c = new ObservableCollection<string> { "foo", "bar" };
+ var p = new ListProxy (c);
+
+ IEnumerator<object> e = p.GetEnumerator();
+ Assert.IsTrue (e.MoveNext(), "Initial MoveNext() failed, test can't continue");
+
+ c.Add ("baz");
+
+ Assert.That (() => e.MoveNext(), Throws.InvalidOperationException,
+ "MoveNext did not throw an exception when the underlying collection had changed");
+ }
+
+ [Test]
+ public void SynchronizedCollectionAccess()
+ {
+ var collection = new ObservableCollection<string> { "foo" };
+ var context = new object();
+
+ var list = new ListProxy (collection);
+
+ bool executed = false;
+ BindingBase.EnableCollectionSynchronization (collection, context, (enumerable, o, method, access) => {
+ executed = true;
+ Assert.AreSame (collection, enumerable);
+ Assert.AreSame (context, o);
+ Assert.IsNotNull (method);
+ Assert.IsFalse (access);
+
+ lock (enumerable)
+ method();
+ });
+
+ object value = list[0];
+
+ Assert.IsTrue (executed, "Callback was not executed");
+ }
+
+ [Test]
+ public void SynchronizedCollectionAdd()
+ {
+ bool invoked = false;
+ Device.PlatformServices = new MockPlatformServices (invokeOnMainThread: action => {
+ invoked = true;
+ action();
+ });
+
+ var collection = new ObservableCollection<string> { "foo" };
+ var context = new object();
+
+ var list = new ListProxy (collection);
+
+ Assert.IsFalse (invoked, "An invoke shouldn't be executed just setting up ListProxy");
+
+ bool executed = false;
+ BindingBase.EnableCollectionSynchronization (collection, context, (enumerable, o, method, access) => {
+ executed = true;
+ Assert.AreSame (collection, enumerable);
+ Assert.AreSame (context, o);
+ Assert.IsNotNull (method);
+ Assert.IsFalse (access);
+
+ lock (enumerable)
+ method();
+ });
+
+ var mre = new ManualResetEvent (false);
+
+ Task.Factory.StartNew (() => {
+ lock (collection)
+ collection.Add ("foo");
+
+ mre.Set();
+ }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
+
+ mre.WaitOne (5000);
+
+ Assert.IsTrue (executed, "Callback was not executed");
+ Assert.IsTrue (invoked, "Callback was not executed on the UI thread");
+ }
+
+ [Test]
+ public void ClearEnumerable()
+ {
+ var proxy = new ListProxy (Enumerable.Range (0, 100));
+ var enumerator = proxy.GetEnumerator();
+ enumerator.MoveNext();
+ enumerator.MoveNext();
+
+ proxy.Clear();
+
+ Assert.AreEqual (100, proxy.Count);
+ Assert.That (() => enumerator.MoveNext(), Throws.InvalidOperationException);
+ }
+
+ [Test]
+ public void ClearCollection()
+ {
+ var proxy = new ListProxy (new IntCollection (Enumerable.Range (0, 100)));
+ var enumerator = proxy.GetEnumerator();
+ enumerator.MoveNext();
+ enumerator.MoveNext();
+
+ proxy.Clear();
+
+ Assert.AreEqual (100, proxy.Count);
+ Assert.That (() => enumerator.MoveNext(), Throws.InvalidOperationException);
+ }
+
+ [Test]
+ public void ClearList()
+ {
+ var proxy = new ListProxy (Enumerable.Range (0, 100).ToList());
+ var enumerator = proxy.GetEnumerator();
+ enumerator.MoveNext();
+ enumerator.MoveNext();
+
+ proxy.Clear();
+
+ Assert.AreEqual (100, proxy.Count);
+ Assert.That (() => enumerator.MoveNext(), Throws.InvalidOperationException);
+ }
+
+ [Test]
+ public void IndexOfValueTypeNonList()
+ {
+ var proxy = new ListProxy (Enumerable.Range (0, 100));
+ Assert.AreEqual (1, proxy.IndexOf (1));
+ }
+
+ [Test]
+ public void EnumeratorForEnumerable()
+ {
+ var proxy = new ListProxy (Enumerable.Range (0, 2));
+
+ var enumerator = proxy.GetEnumerator();
+ Assert.That (enumerator.Current, Is.Null);
+ Assert.That (enumerator.MoveNext(), Is.True);
+ Assert.That (enumerator.Current, Is.EqualTo (0));
+ Assert.That (enumerator.MoveNext(), Is.True);
+ Assert.That (enumerator.Current, Is.EqualTo (1));
+ Assert.That (enumerator.MoveNext(), Is.False);
+ }
+
+ [Test]
+ public void ProxyIsWeaklyHeldByINotifyCollectionChanged()
+ {
+ ObservableCollection<string> collection = new ObservableCollection<string>();
+
+ WeakReference weakProxy = null;
+
+ int i = 0;
+ Action create = null;
+ create = () => {
+ if (i++ < 1024) {
+ create();
+ return;
+ }
+
+ var proxy = new ListProxy (collection);
+ weakProxy = new WeakReference (proxy);
+ };
+
+ create();
+
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+ GC.Collect();
+
+ Assert.That (weakProxy.IsAlive, Is.False);
+ }
+
+ [Test]
+ public void IEnumerableAddDoesNotReport0()
+ {
+ var custom = new CustomINCC();
+ custom.Add ("test");
+ custom.Add ("test2");
+
+ var proxy = new ListProxy (custom);
+ Assert.That (proxy.Count, Is.EqualTo (2));
+
+ custom.Add ("testing");
+ Assert.That (proxy.Count, Is.EqualTo (3));
+ }
+
+ class CustomINCC : IEnumerable<string>, INotifyCollectionChanged
+ {
+ public event NotifyCollectionChangedEventHandler CollectionChanged;
+ List<string> Items = new List<string> ();
+
+ public void Add (string s)
+ {
+ Items.Add(s);
+ if (CollectionChanged != null)
+ CollectionChanged (this, new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Add, s));
+ }
+
+ public IEnumerator<string> GetEnumerator ()
+ {
+ return Items.GetEnumerator ();
+ }
+ IEnumerator IEnumerable.GetEnumerator ()
+ {
+ return Items.GetEnumerator ();
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ListViewTests.cs b/Xamarin.Forms.Core.UnitTests/ListViewTests.cs
new file mode 100644
index 00000000..d5672f77
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ListViewTests.cs
@@ -0,0 +1,1490 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Input;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ListViewTests : BaseTestFixture
+ {
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ Device.Info = null;
+ }
+
+ [SetUp]
+ public override void Setup ()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ Device.Info = new TestDeviceInfo ();
+ }
+
+ [Test]
+ public void TestConstructor ()
+ {
+ var listView = new ListView ();
+
+ Assert.Null (listView.ItemsSource);
+ Assert.Null (listView.ItemTemplate);
+ Assert.AreEqual (LayoutOptions.FillAndExpand, listView.HorizontalOptions);
+ Assert.AreEqual (LayoutOptions.FillAndExpand, listView.VerticalOptions);
+ }
+
+ internal class ListItem
+ {
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+
+ [Test]
+ public void TestTemplating ()
+ {
+ var cellTemplate = new DataTemplate (typeof (TextCell));
+ cellTemplate.SetBinding (TextCell.TextProperty, new Binding ("Name"));
+ cellTemplate.SetBinding (TextCell.DetailProperty, new Binding ("Description"));
+
+ var listView = new ListView {
+ ItemsSource = new[] {
+ new ListItem {Name = "Foo", Description = "Bar"},
+ new ListItem {Name = "Baz", Description = "Raz"}
+ },
+ ItemTemplate = cellTemplate
+ };
+
+ var cell = (Cell)listView.ItemTemplate.CreateContent ();
+
+ var textCell = (TextCell)cell;
+ cell.BindingContext = listView.ItemsSource.OfType<ListItem> ().First ();
+
+ Assert.AreEqual ("Foo", textCell.Text);
+ Assert.AreEqual ("Bar", textCell.Detail);
+ }
+
+ [Test]
+ public void TemplateNullObject()
+ {
+ var listView = new ListView {
+ ItemsSource = new object[] {
+ null
+ }
+ };
+
+ Cell cell = listView.TemplatedItems[0];
+
+ Assert.That (cell, Is.Not.Null);
+ Assert.That (cell, Is.InstanceOf<TextCell>());
+ Assert.That (((TextCell) cell).Text, Is.Null);
+ }
+
+ [Test]
+ [Description ("Setting GroupDisplayBinding or GroupHeaderTemplate when the other is set should set the other one to null.")]
+ public void SettingGroupHeaderTemplateSetsDisplayBindingToNull()
+ {
+ var listView = new ListView {
+ GroupDisplayBinding = new Binding ("Path")
+ };
+
+ listView.GroupHeaderTemplate = new DataTemplate (typeof (TextCell));
+
+ Assert.That (listView.GroupDisplayBinding, Is.Null);
+ }
+
+ [Test]
+ [Description ("Setting GroupDisplayBinding or GroupHeaderTemplate when the other is set should set the other one to null.")]
+ public void SettingGroupDisplayBindingSetsHeaderTemplateToNull()
+ {
+ var listView = new ListView {
+ GroupHeaderTemplate = new DataTemplate (typeof (TextCell))
+ };
+
+ listView.GroupDisplayBinding = new Binding ("Path");
+
+ Assert.That (listView.GroupHeaderTemplate, Is.Null);
+ }
+
+ [Test]
+ [Description ("You should be able to set ItemsSource without having set the other properties first without issue")]
+ public void SettingItemsSourceWithoutBindingsOrItemsSource()
+ {
+ var listView = new ListView {
+ IsGroupingEnabled = true
+ };
+
+ Assert.That (() => listView.ItemsSource = new[] { new[] { new object() } }, Throws.Nothing);
+ }
+
+ [Test]
+ public void DefaultGroupHeaderTemplates()
+ {
+ var items = new[] { new[] { new object() } };
+
+ var listView = new ListView {
+ IsGroupingEnabled = true,
+ ItemsSource = items
+ };
+
+ var til = (TemplatedItemsList<ItemsView<Cell>, Cell>)((IList)listView.TemplatedItems)[0];
+ Cell cell = til.HeaderContent;
+
+ Assert.That (cell, Is.Not.Null);
+ Assert.That (cell, Is.InstanceOf<TextCell>());
+ Assert.That (((TextCell) cell).Text, Is.EqualTo (items[0].ToString()));
+ }
+
+ [Test]
+ [Description ("Tapping a different item (row) that is equal to the current item selection should still raise ItemSelected")]
+ public void NotifyRowTappedDifferentIndex()
+ {
+ string item = "item";
+
+ var listView = new ListView {
+ ItemsSource = new[] {
+ item,
+ item
+ }
+ };
+
+ listView.NotifyRowTapped (0);
+
+ bool raised = false;
+ listView.ItemSelected += (sender, arg) => raised = true;
+
+ listView.NotifyRowTapped (1);
+ Assert.That (raised, Is.True, "ItemSelected was not raised");
+ }
+
+ [Test]
+ public void DoesNotCrashWhenAddingToSource ()
+ {
+ var items = new ObservableCollection<string> {
+ "Foo",
+ "Bar",
+ "Baz"
+ };
+
+ var listView = new ListView {
+ ItemsSource = items,
+ ItemTemplate = new DataTemplate(typeof(TextCell))
+ };
+
+ Assert.DoesNotThrow (() => items.Add ("Blah"));
+ }
+
+ [Test]
+ public void DoesNotThrowWhenMovingInSource ()
+ {
+ var items = new ObservableCollection<string> {
+ "Foo",
+ "Bar",
+ "Baz"
+ };
+
+ var listView = new ListView {
+ ItemsSource = items,
+ ItemTemplate = new DataTemplate (typeof (TextCell))
+ };
+
+ Assert.DoesNotThrow (() => items.Move (0, 1));
+ }
+
+ [Test]
+ [Description ("A cell being tapped from the UI should raise both tapped events, but not change ItemSelected")]
+ public void NotifyTappedSameItem()
+ {
+ int cellTapped = 0;
+ int itemTapped = 0;
+ int itemSelected = 0;
+
+ var listView = new ListView {
+ ItemsSource = new[] { "item" },
+ ItemTemplate = new DataTemplate (() => {
+ var cell = new TextCell();
+ cell.Tapped += (s, e) => {
+ cellTapped++;
+ };
+ return cell;
+ })
+ };
+
+ listView.ItemTapped += (sender, arg) => itemTapped++;
+ listView.ItemSelected += (sender, arg) => itemSelected++;
+
+ listView.NotifyRowTapped (0);
+
+ Assert.That (cellTapped, Is.EqualTo (1), "Cell.Tapped was not raised");
+ Assert.That (itemTapped, Is.EqualTo (1), "ListView.ItemTapped was not raised");
+ Assert.That (itemSelected, Is.EqualTo (1), "ListView.ItemSelected was not raised");
+
+ listView.NotifyRowTapped (0);
+
+ Assert.That (cellTapped, Is.EqualTo (2), "Cell.Tapped was not raised a second time");
+ Assert.That (itemTapped, Is.EqualTo (2), "ListView.ItemTapped was not raised a second time");
+ Assert.That (itemSelected, Is.EqualTo (1), "ListView.ItemSelected was raised a second time");
+ }
+
+ [Test]
+ public void ScrollTo()
+ {
+ var listView = new ListView {
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform()
+ };
+
+ object item = new object();
+
+ bool requested = false;
+ listView.ScrollToRequested += (sender, args) => {
+ requested = true;
+
+ Assert.That (args.Item, Is.SameAs (item));
+ Assert.That (args.Group, Is.Null);
+ Assert.That (args.Position, Is.EqualTo (ScrollToPosition.Center));
+ Assert.That (args.ShouldAnimate, Is.EqualTo (true));
+ };
+
+ listView.ScrollTo (item, ScrollToPosition.Center, animated: true);
+ Assert.That (requested, Is.True);
+ }
+
+ [Test]
+ public void ScrollToDelayed()
+ {
+ var listView = new ListView();
+
+ object item = new object();
+
+ bool requested = false;
+ listView.ScrollToRequested += (sender, args) => {
+ requested = true;
+
+ Assert.That (args.Item, Is.SameAs (item));
+ Assert.That (args.Group, Is.Null);
+ Assert.That (args.Position, Is.EqualTo (ScrollToPosition.Center));
+ Assert.That (args.ShouldAnimate, Is.EqualTo (true));
+ };
+
+ listView.ScrollTo (item, ScrollToPosition.Center, animated: true);
+ Assert.That (requested, Is.False);
+
+ listView.IsPlatformEnabled = true;
+ listView.Platform = new UnitPlatform();
+
+ Assert.That (requested, Is.True);
+ }
+
+ [Test]
+ public void ScrollToGroup()
+ {
+ // Fake a renderer so we pass along messages right away
+ var listView = new ListView {
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform(),
+ IsGroupingEnabled = true
+ };
+
+ object item = new object();
+ object group = new object();
+
+ bool requested = false;
+ listView.ScrollToRequested += (sender, args) => {
+ requested = true;
+
+ Assert.That (args.Item, Is.SameAs (item));
+ Assert.That (args.Group, Is.SameAs (group));
+ Assert.That (args.Position, Is.EqualTo (ScrollToPosition.Center));
+ Assert.That (args.ShouldAnimate, Is.EqualTo (true));
+ };
+
+ listView.ScrollTo (item, group, ScrollToPosition.Center, animated: true);
+ Assert.That (requested, Is.True);
+ }
+
+ [Test]
+ public void ScrollToInvalid()
+ {
+ var listView = new ListView {
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform()
+ };
+
+ Assert.That (() => listView.ScrollTo (new object(), (ScrollToPosition) 500, true), Throws.ArgumentException);
+ Assert.That (() => listView.ScrollTo (new object(), new object(), ScrollToPosition.Start, true), Throws.InvalidOperationException);
+
+ listView.IsGroupingEnabled = true;
+ Assert.That (() => listView.ScrollTo (new object(), new object(), (ScrollToPosition) 500, true), Throws.ArgumentException);
+ }
+
+ [Test]
+ public void GetSizeRequest ()
+ {
+ var listView = new ListView {
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform (),
+ HasUnevenRows = false,
+ RowHeight = 50,
+ ItemsSource = Enumerable.Range (0, 20).ToList ()
+ };
+
+
+ var sizeRequest = listView.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+ Assert.AreEqual (40, sizeRequest.Minimum.Width);
+ Assert.AreEqual (40, sizeRequest.Minimum.Height);
+ Assert.AreEqual (50, sizeRequest.Request.Width);
+ Assert.AreEqual (50 * 20, sizeRequest.Request.Height);
+ }
+
+ [Test]
+ public void GetSizeRequestUneven ()
+ {
+ var listView = new ListView {
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform (),
+ HasUnevenRows = true,
+ RowHeight = 50,
+ ItemsSource = Enumerable.Range (0, 20).ToList ()
+ };
+
+
+ var sizeRequest = listView.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+ Assert.AreEqual (40, sizeRequest.Minimum.Width);
+ Assert.AreEqual (40, sizeRequest.Minimum.Height);
+ Assert.AreEqual (50, sizeRequest.Request.Width);
+ Assert.AreEqual (100, sizeRequest.Request.Height);
+ }
+
+ public class ListItemValue : IComparable<ListItemValue>
+ {
+ public string Name { get; private set; }
+
+ public ListItemValue (string name)
+ {
+ Name = name;
+ }
+
+ int IComparable<ListItemValue>.CompareTo (ListItemValue value)
+ {
+ return Name.CompareTo (value.Name);
+ }
+
+ public string Label
+ {
+ get { return Name[0].ToString (); }
+ }
+ }
+
+ public class ListItemCollection : ObservableCollection<ListItemValue>
+ {
+ public string Title { get; private set; }
+
+ public ListItemCollection (string title)
+ {
+ Title = title;
+ }
+
+ public static List<ListItemValue> GetSortedData ()
+ {
+ var items = ListItems;
+ items.Sort ();
+ return items;
+ }
+
+ // Data used to populate our list.
+ static readonly List<ListItemValue> ListItems = new List<ListItemValue> () {
+ new ListItemValue ("Babbage"),
+ new ListItemValue ("Boole"),
+ new ListItemValue ("Berners-Lee"),
+ new ListItemValue ("Atanasoff"),
+ new ListItemValue ("Allen"),
+ new ListItemValue ("Cormack"),
+ new ListItemValue ("Cray"),
+ new ListItemValue ("Dijkstra"),
+ new ListItemValue ("Dix"),
+ new ListItemValue ("Dewey"),
+ new ListItemValue ("Erdos"),
+ };
+ }
+
+ public class TestCell : TextCell
+ {
+ public static int NumberOfCells = 0;
+
+ public TestCell ()
+ {
+ Interlocked.Increment (ref NumberOfCells);
+ }
+
+ ~TestCell ()
+ {
+ Interlocked.Decrement (ref NumberOfCells);
+ }
+ }
+
+ ObservableCollection<ListItemCollection> SetupList ()
+ {
+ var allListItemGroups = new ObservableCollection<ListItemCollection> ();
+
+ foreach (var item in ListItemCollection.GetSortedData ()) {
+ // Attempt to find any existing groups where theg group title matches the first char of our ListItem's name.
+ var listItemGroup = allListItemGroups.FirstOrDefault (g => g.Title == item.Label);
+
+ // If the list group does not exist, we create it.
+ if (listItemGroup == null) {
+ listItemGroup = new ListItemCollection (item.Label) { item };
+ allListItemGroups.Add (listItemGroup);
+ } else {
+ // If the group does exist, we simply add the demo to the existing group.
+ listItemGroup.Add (item);
+ }
+ }
+ return allListItemGroups;
+ }
+
+ [Test]
+ public void UncollectableHeaderReferences ()
+ {
+ var list = new ListView {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ ItemTemplate = new DataTemplate (typeof (TextCell)) {
+ Bindings = {
+ {TextCell.TextProperty, new Binding ("Name")}
+ }
+ },
+ GroupHeaderTemplate = new DataTemplate (typeof (TestCell)) {
+ Bindings = {
+ {TextCell.TextProperty, new Binding ("Title")}
+ }
+ },
+ IsGroupingEnabled = true,
+ ItemsSource = SetupList (),
+ };
+
+ Assert.AreEqual (5, TestCell.NumberOfCells);
+
+ var newList1 = SetupList ();
+ var newList2 = SetupList ();
+
+ for (var i = 0; i < 400; i++) {
+ list.ItemsSource = i % 2 > 0 ? newList1 : newList2;
+
+ // grab a header just so we can be sure its reailized
+ var header = list.TemplatedItems.GetGroup (0).HeaderContent;
+ }
+
+ GC.Collect ();
+ GC.WaitForPendingFinalizers ();
+
+ // use less or equal because mono will keep the last header var alive no matter what
+ Assert.True (TestCell.NumberOfCells <= 6);
+
+ var keepAlive = list.ToString ();
+ }
+
+ [Test]
+ public void CollectionChangedMultipleFires ()
+ {
+ var source = new ObservableCollection<string> {
+ "Foo",
+ "Bar"
+ };
+
+ var list = new ListView {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ ItemsSource = source,
+ ItemTemplate = new DataTemplate (typeof (TextCell))
+ };
+
+ int fireCount = 0;
+ list.TemplatedItems.CollectionChanged += (sender, args) => {
+ fireCount++;
+ };
+
+ source.Add ("Baz");
+
+ Assert.AreEqual (1, fireCount);
+ }
+
+ [Test]
+ public void GroupedCollectionChangedMultipleFires ()
+ {
+ var source = new ObservableCollection<ObservableCollection <string>> {
+ new ObservableCollection<string> {"Foo"},
+ new ObservableCollection<string> {"Bar"}
+ };
+
+ var list = new ListView {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ IsGroupingEnabled = true,
+ ItemsSource = source,
+ ItemTemplate = new DataTemplate (typeof (TextCell)) {
+ Bindings = {
+ {TextCell.TextProperty, new Binding (".") }
+ }
+ }
+ };
+
+ int fireCount = 0;
+ list.TemplatedItems.GroupedCollectionChanged += (sender, args) => {
+ fireCount++;
+ };
+
+ source[0].Add ("Baz");
+
+ Assert.AreEqual (1, fireCount);
+ }
+
+ [Test]
+ public void HeaderAsView()
+ {
+ var label = new Label { Text = "header" };
+ var lv = new ListView {
+ Header = label
+ };
+
+ IListViewController controller = lv;
+ Assert.That (controller.HeaderElement, Is.SameAs (label));
+ }
+
+ [Test]
+ public void HeaderTemplated()
+ {
+ var lv = new ListView {
+ Header = "header",
+ HeaderTemplate = new DataTemplate(typeof(Label)) {
+ Bindings = {
+ { Label.TextProperty, new Binding (".") }
+ }
+ }
+ };
+
+ IListViewController controller = lv;
+ Assert.That (controller.HeaderElement, Is.Not.Null);
+ Assert.That (controller.HeaderElement, Is.InstanceOf<Label>());
+ Assert.That (((Label) controller.HeaderElement).Text, Is.EqualTo (lv.Header));
+ }
+
+ [Test]
+ public void HeaderTemplateThrowsIfCell ()
+ {
+ var lv = new ListView ();
+
+ Assert.Throws<ArgumentException> (() => lv.HeaderTemplate = new DataTemplate (typeof (TextCell)));
+ }
+
+ [Test]
+ public void FooterTemplateThrowsIfCell ()
+ {
+ var lv = new ListView ();
+
+ Assert.Throws<ArgumentException> (() => lv.FooterTemplate = new DataTemplate (typeof (TextCell)));
+ }
+
+ [Test]
+ public void HeaderObjectTemplatedChanged()
+ {
+ var lv = new ListView {
+ Header = "header",
+ HeaderTemplate = new DataTemplate (typeof (Label)) {
+ Bindings = {
+ { Label.TextProperty, new Binding (".") }
+ }
+ }
+ };
+
+ bool changed = false, changing = false;
+ lv.PropertyChanging += (sender, args) => {
+ if (args.PropertyName == "HeaderElement")
+ changing = true;
+ };
+ lv.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "HeaderElement")
+ changed = true;
+ };
+
+ lv.Header = "newheader";
+
+ Assert.That (changing, Is.False);
+ Assert.That (changed, Is.False);
+
+ IListViewController controller = lv;
+ Assert.That (controller.HeaderElement, Is.Not.Null);
+ Assert.That (controller.HeaderElement, Is.InstanceOf<Label>());
+ Assert.That (((Label) controller.HeaderElement).Text, Is.EqualTo (lv.Header));
+ }
+
+ [Test]
+ public void HeaderViewChanged()
+ {
+ var lv = new ListView {
+ Header = new Label { Text = "header" }
+ };
+
+ bool changed = false, changing = false;
+ lv.PropertyChanging += (sender, args) => {
+ if (args.PropertyName == "HeaderElement")
+ changing = true;
+ };
+ lv.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "HeaderElement")
+ changed = true;
+ };
+
+ Label label = new Label { Text = "header" };
+ lv.Header = label;
+
+ Assert.That (changing, Is.True);
+ Assert.That (changed, Is.True);
+
+ IListViewController controller = lv;
+ Assert.That (controller.HeaderElement, Is.SameAs (label));
+ }
+
+
+ [Test]
+ public void HeaderTemplateChanged()
+ {
+ var lv = new ListView {
+ Header = "header",
+ HeaderTemplate = new DataTemplate(typeof(Label)) {
+ Bindings = {
+ { Label.TextProperty, new Binding (".") }
+ }
+ }
+ };
+
+ bool changed = false, changing = false;
+ lv.PropertyChanging += (sender, args) => {
+ if (args.PropertyName == "HeaderElement")
+ changing = true;
+ };
+ lv.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "HeaderElement")
+ changed = true;
+ };
+
+ lv.HeaderTemplate = new DataTemplate (typeof (Entry)) {
+ Bindings = {
+ { Entry.TextProperty, new Binding (".") }
+ }
+ };
+
+ Assert.That (changing, Is.True);
+ Assert.That (changed, Is.True);
+
+ IListViewController controller = lv;
+ Assert.That (controller.HeaderElement, Is.Not.Null);
+ Assert.That (controller.HeaderElement, Is.InstanceOf<Entry>());
+ Assert.That (((Entry) controller.HeaderElement).Text, Is.EqualTo (lv.Header));
+ }
+
+ [Test]
+ public void HeaderTemplateChangedNoObject()
+ {
+ var lv = new ListView {
+ HeaderTemplate = new DataTemplate(typeof(Label)) {
+ Bindings = {
+ { Label.TextProperty, new Binding (".") }
+ }
+ }
+ };
+
+ bool changed = false, changing = false;
+ lv.PropertyChanging += (sender, args) => {
+ if (args.PropertyName == "HeaderElement")
+ changing = true;
+ };
+ lv.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "HeaderElement")
+ changed = true;
+ };
+
+ lv.HeaderTemplate = new DataTemplate (typeof (Entry)) {
+ Bindings = {
+ { Entry.TextProperty, new Binding (".") }
+ }
+ };
+
+ Assert.That (changing, Is.False);
+ Assert.That (changed, Is.False);
+
+ IListViewController controller = lv;
+ Assert.That (controller.HeaderElement, Is.Null);
+ }
+
+ [Test]
+ public void HeaderNoTemplate()
+ {
+ var lv = new ListView {
+ Header = "foo"
+ };
+
+ IListViewController controller = lv;
+ Assert.That (controller.HeaderElement, Is.Not.Null);
+ Assert.That (controller.HeaderElement, Is.InstanceOf<Label>());
+ Assert.That (((Label) controller.HeaderElement).Text, Is.EqualTo (lv.Header));
+ }
+
+ [Test]
+ public void HeaderChangedNoTemplate()
+ {
+ var lv = new ListView {
+ Header = "foo"
+ };
+
+ bool changed = false, changing = false;
+ lv.PropertyChanging += (sender, args) => {
+ if (args.PropertyName == "HeaderElement")
+ changing = true;
+ };
+ lv.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "HeaderElement")
+ changed = true;
+ };
+
+ lv.Header = "bar";
+
+ Assert.That (changing, Is.True);
+ Assert.That (changed, Is.True);
+
+ IListViewController controller = lv;
+ Assert.That (controller.HeaderElement, Is.Not.Null);
+ Assert.That (controller.HeaderElement, Is.InstanceOf<Label>());
+ Assert.That (((Label) controller.HeaderElement).Text, Is.EqualTo (lv.Header));
+ }
+
+ [Test]
+ public void HeaderViewButTemplated()
+ {
+ var lv = new ListView {
+ Header = new Entry { Text = "foo" },
+ HeaderTemplate = new DataTemplate (typeof(Label)) {
+ Bindings = {
+ { Label.TextProperty, new Binding ("Text") }
+ }
+ }
+ };
+
+ IListViewController controller = lv;
+ Assert.That (controller.HeaderElement, Is.Not.Null);
+ Assert.That (controller.HeaderElement, Is.InstanceOf<Label>());
+ Assert.That (((Label) controller.HeaderElement).Text, Is.EqualTo (((Entry)lv.Header).Text));
+ }
+
+ [Test]
+ public void HeaderTemplatedChangedToView()
+ {
+ var lv = new ListView {
+ Header = new Entry { Text = "foo" },
+ HeaderTemplate = new DataTemplate (typeof(Label)) {
+ Bindings = {
+ { Label.TextProperty, new Binding ("Text") }
+ }
+ }
+ };
+
+ bool changed = false, changing = false;
+ lv.PropertyChanging += (sender, args) => {
+ if (args.PropertyName == "HeaderElement")
+ changing = true;
+ };
+ lv.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "HeaderElement")
+ changed = true;
+ };
+
+ lv.HeaderTemplate = null;
+
+ Assert.That (changing, Is.True);
+ Assert.That (changed, Is.True);
+
+ IListViewController controller = lv;
+ Assert.That (controller.HeaderElement, Is.Not.Null);
+ Assert.That (controller.HeaderElement, Is.InstanceOf<Entry>());
+ Assert.That (((Entry) controller.HeaderElement).Text, Is.EqualTo (((Entry)lv.Header).Text));
+ }
+
+ [Test]
+ public void HeaderTemplatedSetToNull()
+ {
+ var lv = new ListView {
+ Header = "header",
+ HeaderTemplate = new DataTemplate(typeof(Label)) {
+ Bindings = {
+ { Label.TextProperty, new Binding (".") }
+ }
+ }
+ };
+
+ bool changed = false, changing = false;
+ lv.PropertyChanging += (sender, args) => {
+ if (args.PropertyName == "HeaderElement")
+ changing = true;
+ };
+ lv.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "HeaderElement")
+ changed = true;
+ };
+
+ lv.Header = null;
+
+ Assert.That (changing, Is.True);
+ Assert.That (changed, Is.True);
+
+ IListViewController controller = lv;
+ Assert.That (controller.HeaderElement, Is.Null);
+ }
+
+ [Test]
+ public void FooterAsView()
+ {
+ var label = new Label { Text = "footer" };
+ var lv = new ListView {
+ Footer = label
+ };
+
+ IListViewController controller = lv;
+ Assert.That (controller.FooterElement, Is.SameAs (label));
+ }
+
+ [Test]
+ public void FooterTemplated()
+ {
+ var lv = new ListView {
+ Footer = "footer",
+ FooterTemplate = new DataTemplate(typeof(Label)) {
+ Bindings = {
+ { Label.TextProperty, new Binding (".") }
+ }
+ }
+ };
+
+ IListViewController controller = lv;
+ Assert.That (controller.FooterElement, Is.Not.Null);
+ Assert.That (controller.FooterElement, Is.InstanceOf<Label>());
+ Assert.That (((Label) controller.FooterElement).Text, Is.EqualTo (lv.Footer));
+ }
+
+ [Test]
+ public void FooterObjectTemplatedChanged()
+ {
+ var lv = new ListView {
+ Footer = "footer",
+ FooterTemplate = new DataTemplate (typeof (Label)) {
+ Bindings = {
+ { Label.TextProperty, new Binding (".") }
+ }
+ }
+ };
+
+ bool changed = false, changing = false;
+ lv.PropertyChanging += (sender, args) => {
+ if (args.PropertyName == "FooterElement")
+ changing = true;
+ };
+ lv.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "FooterElement")
+ changed = true;
+ };
+
+ lv.Footer = "newfooter";
+
+ Assert.That (changing, Is.False);
+ Assert.That (changed, Is.False);
+
+ IListViewController controller = lv;
+ Assert.That (controller.FooterElement, Is.Not.Null);
+ Assert.That (controller.FooterElement, Is.InstanceOf<Label>());
+ Assert.That (((Label) controller.FooterElement).Text, Is.EqualTo (lv.Footer));
+ }
+
+ [Test]
+ public void FooterViewChanged()
+ {
+ var lv = new ListView {
+ Footer = new Label { Text = "footer" }
+ };
+
+ bool changed = false, changing = false;
+ lv.PropertyChanging += (sender, args) => {
+ if (args.PropertyName == "FooterElement")
+ changing = true;
+ };
+ lv.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "FooterElement")
+ changed = true;
+ };
+
+ Label label = new Label { Text = "footer" };
+ lv.Footer = label;
+
+ Assert.That (changing, Is.True);
+ Assert.That (changed, Is.True);
+
+ IListViewController controller = lv;
+ Assert.That (controller.FooterElement, Is.SameAs (label));
+ }
+
+
+ [Test]
+ public void FooterTemplateChanged()
+ {
+ var lv = new ListView {
+ Footer = "footer",
+ FooterTemplate = new DataTemplate(typeof(Label)) {
+ Bindings = {
+ { Label.TextProperty, new Binding (".") }
+ }
+ }
+ };
+
+ bool changed = false, changing = false;
+ lv.PropertyChanging += (sender, args) => {
+ if (args.PropertyName == "FooterElement")
+ changing = true;
+ };
+ lv.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "FooterElement")
+ changed = true;
+ };
+
+ lv.FooterTemplate = new DataTemplate (typeof (Entry)) {
+ Bindings = {
+ { Entry.TextProperty, new Binding (".") }
+ }
+ };
+
+ Assert.That (changing, Is.True);
+ Assert.That (changed, Is.True);
+
+ IListViewController controller = lv;
+ Assert.That (controller.FooterElement, Is.Not.Null);
+ Assert.That (controller.FooterElement, Is.InstanceOf<Entry>());
+ Assert.That (((Entry) controller.FooterElement).Text, Is.EqualTo (lv.Footer));
+ }
+
+ [Test]
+ public void FooterTemplateChangedNoObject()
+ {
+ var lv = new ListView {
+ FooterTemplate = new DataTemplate(typeof(Label)) {
+ Bindings = {
+ { Label.TextProperty, new Binding (".") }
+ }
+ }
+ };
+
+ bool changed = false, changing = false;
+ lv.PropertyChanging += (sender, args) => {
+ if (args.PropertyName == "FooterElement")
+ changing = true;
+ };
+ lv.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "FooterElement")
+ changed = true;
+ };
+
+ lv.FooterTemplate = new DataTemplate (typeof (Entry)) {
+ Bindings = {
+ { Entry.TextProperty, new Binding (".") }
+ }
+ };
+
+ Assert.That (changing, Is.False);
+ Assert.That (changed, Is.False);
+
+ IListViewController controller = lv;
+ Assert.That (controller.FooterElement, Is.Null);
+ }
+
+ [Test]
+ public void FooterNoTemplate()
+ {
+ var lv = new ListView {
+ Footer = "foo"
+ };
+
+ IListViewController controller = lv;
+ Assert.That (controller.FooterElement, Is.Not.Null);
+ Assert.That (controller.FooterElement, Is.InstanceOf<Label>());
+ Assert.That (((Label) controller.FooterElement).Text, Is.EqualTo (lv.Footer));
+ }
+
+ [Test]
+ public void FooterChangedNoTemplate()
+ {
+ var lv = new ListView {
+ Footer = "foo"
+ };
+
+ bool changed = false, changing = false;
+ lv.PropertyChanging += (sender, args) => {
+ if (args.PropertyName == "FooterElement")
+ changing = true;
+ };
+ lv.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "FooterElement")
+ changed = true;
+ };
+
+ lv.Footer = "bar";
+
+ Assert.That (changing, Is.True);
+ Assert.That (changed, Is.True);
+
+ IListViewController controller = lv;
+ Assert.That (controller.FooterElement, Is.Not.Null);
+ Assert.That (controller.FooterElement, Is.InstanceOf<Label>());
+ Assert.That (((Label) controller.FooterElement).Text, Is.EqualTo (lv.Footer));
+ }
+
+ [Test]
+ public void FooterViewButTemplated()
+ {
+ var lv = new ListView {
+ Footer = new Entry { Text = "foo" },
+ FooterTemplate = new DataTemplate (typeof(Label)) {
+ Bindings = {
+ { Label.TextProperty, new Binding ("Text") }
+ }
+ }
+ };
+
+ IListViewController controller = lv;
+ Assert.That (controller.FooterElement, Is.Not.Null);
+ Assert.That (controller.FooterElement, Is.InstanceOf<Label>());
+ Assert.That (((Label) controller.FooterElement).Text, Is.EqualTo (((Entry)lv.Footer).Text));
+ }
+
+ [Test]
+ public void FooterTemplatedChangedToView()
+ {
+ var lv = new ListView {
+ Footer = new Entry { Text = "foo" },
+ FooterTemplate = new DataTemplate (typeof(Label)) {
+ Bindings = {
+ { Label.TextProperty, new Binding ("Text") }
+ }
+ }
+ };
+
+ bool changed = false, changing = false;
+ lv.PropertyChanging += (sender, args) => {
+ if (args.PropertyName == "FooterElement")
+ changing = true;
+ };
+ lv.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "FooterElement")
+ changed = true;
+ };
+
+ lv.FooterTemplate = null;
+
+ Assert.That (changing, Is.True);
+ Assert.That (changed, Is.True);
+
+ IListViewController controller = lv;
+ Assert.That (controller.FooterElement, Is.Not.Null);
+ Assert.That (controller.FooterElement, Is.InstanceOf<Entry>());
+ Assert.That (((Entry) controller.FooterElement).Text, Is.EqualTo (((Entry)lv.Footer).Text));
+ }
+
+ [Test]
+ public void FooterTemplatedSetToNull()
+ {
+ var lv = new ListView {
+ Footer = "footer",
+ FooterTemplate = new DataTemplate(typeof(Label)) {
+ Bindings = {
+ { Label.TextProperty, new Binding (".") }
+ }
+ }
+ };
+
+ bool changed = false, changing = false;
+ lv.PropertyChanging += (sender, args) => {
+ if (args.PropertyName == "FooterElement")
+ changing = true;
+ };
+ lv.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "FooterElement")
+ changed = true;
+ };
+
+ lv.Footer = null;
+
+ Assert.That (changing, Is.True);
+ Assert.That (changed, Is.True);
+
+ IListViewController controller = lv;
+ Assert.That (controller.FooterElement, Is.Null);
+ }
+
+ [Test]
+ public void BeginRefresh()
+ {
+ var lv = new ListView();
+
+ bool refreshing = false;
+ lv.Refreshing += (sender, args) => {
+ refreshing = true;
+ };
+
+ lv.BeginRefresh();
+
+ Assert.That (refreshing, Is.True);
+ Assert.That (lv.IsRefreshing, Is.True);
+ }
+
+ [Test]
+ public void SendRefreshing()
+ {
+ var lv = new ListView();
+
+ bool refreshing = false;
+ lv.Refreshing += (sender, args) => {
+ refreshing = true;
+ };
+
+ IListViewController controller = lv;
+ controller.SendRefreshing();
+
+ Assert.That (refreshing, Is.True);
+ Assert.That (lv.IsRefreshing, Is.True);
+ }
+
+ [Test]
+ public void RefreshCommand()
+ {
+ var lv = new ListView();
+
+ bool commandExecuted = false;
+
+ Command refresh = new Command (() => commandExecuted = true);
+
+ lv.RefreshCommand = refresh;
+
+ IListViewController controller = lv;
+ controller.SendRefreshing();
+
+ Assert.That (commandExecuted, Is.True);
+ }
+
+ [TestCase (true)]
+ [TestCase (false)]
+ public void RefreshCommandCanExecute (bool initial)
+ {
+ var lv = new ListView { IsPullToRefreshEnabled = initial };
+
+ bool commandExecuted = false;
+
+ Command refresh = new Command (() => commandExecuted = true,
+ () => !initial);
+
+ lv.RefreshCommand = refresh;
+
+ Assert.That ((lv as IListViewController).RefreshAllowed, Is.EqualTo (!initial));
+ }
+
+ [TestCase (true)]
+ [TestCase (false)]
+ public void RefreshCommandCanExecuteChanges (bool initial)
+ {
+ var lv = new ListView { IsPullToRefreshEnabled = initial };
+
+ bool commandExecuted = false;
+
+ Command refresh = new Command (() => commandExecuted = true,
+ () => initial);
+
+ lv.RefreshCommand = refresh;
+
+ Assert.That ((lv as IListViewController).RefreshAllowed, Is.EqualTo (initial));
+
+ initial = !initial;
+ refresh.ChangeCanExecute();
+
+ Assert.That ((lv as IListViewController).RefreshAllowed, Is.EqualTo (initial));
+ }
+
+ [Test]
+ public void BeginRefreshDoesNothingWhenCannotExecute()
+ {
+ var lv = new ListView();
+
+ bool commandExecuted = false, eventFired = false;
+
+ lv.Refreshing += (sender, args) => eventFired = true;
+
+ Command refresh = new Command (() => commandExecuted = true,
+ () => false);
+
+ lv.RefreshCommand = refresh;
+ lv.BeginRefresh();
+
+ Assert.That (lv.IsRefreshing, Is.False);
+ Assert.That (eventFired, Is.False);
+ Assert.That (commandExecuted, Is.False);
+ }
+
+ [Test]
+ public void SendRefreshingDoesNothingWhenCannotExecute()
+ {
+ var lv = new ListView();
+
+ bool commandExecuted = false, eventFired = false;
+
+ lv.Refreshing += (sender, args) => eventFired = true;
+
+ Command refresh = new Command (() => commandExecuted = true,
+ () => false);
+
+ lv.RefreshCommand = refresh;
+
+ ((IListViewController)lv).SendRefreshing();
+
+ Assert.That (lv.IsRefreshing, Is.False);
+ Assert.That (eventFired, Is.False);
+ Assert.That (commandExecuted, Is.False);
+ }
+
+ [Test]
+ public void SettingIsRefreshingDoesntFireEvent()
+ {
+ var lv = new ListView();
+
+ bool refreshing = false;
+ lv.Refreshing += (sender, args) => {
+ refreshing = true;
+ };
+
+ lv.IsRefreshing = true;
+
+ Assert.That (refreshing, Is.False);
+ }
+
+ [Test]
+ public void EndRefresh()
+ {
+ var lv = new ListView { IsRefreshing = true };
+
+ Assert.That (lv.IsRefreshing, Is.True);
+
+ lv.EndRefresh();
+
+ Assert.That (lv.IsRefreshing, Is.False);
+ }
+
+ [Test]
+ public void CanRefreshAfterCantExecuteCommand()
+ {
+ var lv = new ListView();
+
+ bool commandExecuted = false, eventFired = false;
+
+ lv.Refreshing += (sender, args) => eventFired = true;
+
+ Command refresh = new Command (() => commandExecuted = true,
+ () => false);
+
+ lv.RefreshCommand = refresh;
+ lv.RefreshCommand = null;
+
+ ((IListViewController)lv).SendRefreshing();
+
+ Assert.That (lv.IsRefreshing, Is.True);
+ Assert.That (eventFired, Is.True);
+ Assert.That (commandExecuted, Is.False);
+ }
+
+ [Test]
+ public void StopsListeningToCommandAfterCleared()
+ {
+ var lv = new ListView();
+
+ bool commandExecuted = false, canExecuteRequested = false;
+
+ Command refresh = new Command (() => commandExecuted = true,
+ () => canExecuteRequested = true);
+
+ lv.RefreshCommand = refresh;
+ canExecuteRequested = false;
+
+ lv.RefreshCommand = null;
+
+ Assert.That (() => refresh.ChangeCanExecute(), Throws.Nothing);
+ Assert.That (canExecuteRequested, Is.False);
+
+ lv.BeginRefresh();
+
+ Assert.That (commandExecuted, Is.False);
+ }
+
+ [Test]
+ [Description ("We should be able to set selected item when using ReadOnlyList")]
+ public void SetItemSelectedOnReadOnlyList()
+ {
+ var source = new ReadOnlySource ();
+ var listView = new ListView {
+ ItemsSource = source
+ };
+
+ bool raised = false;
+ listView.ItemSelected += (sender, arg) => raised = true;
+
+ listView.SelectedItem = source [0];
+ Assert.That (raised, Is.True, "ItemSelected was raised on ReadOnlySource");
+ }
+
+ internal class ReadOnlySource : IReadOnlyList<ListItem>
+ {
+ List<ListItem> items;
+ public ReadOnlySource ()
+ {
+ items = new List<ListItem> ();
+
+ for (int i = 0; i < 100; i++) {
+ items.Add (new ListItem { Name="person " + i } );
+ }
+
+ }
+ #region IEnumerable implementation
+ public IEnumerator<ListItem> GetEnumerator ()
+ {
+ return items.GetEnumerator ();
+ }
+ #endregion
+ #region IEnumerable implementation
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
+ {
+ return items.GetEnumerator ();
+ }
+ #endregion
+ #region IReadOnlyList implementation
+ public ListItem this [int index] {
+ get {
+ return items [index];
+ }
+ }
+ #endregion
+ #region IReadOnlyCollection implementation
+ public int Count {
+ get {
+ return items.Count;
+ }
+ }
+ #endregion
+
+ }
+
+ [Test]
+ public void ChildElementsParentIsNulledWhenReset()
+ {
+ var list = new ListView();
+ list.ItemsSource = new[] { "Hi", "Bye" };
+
+ var cell = list.TemplatedItems[0];
+ Assume.That (cell.Parent, Is.SameAs (list));
+
+ list.ItemsSource = null;
+ Assert.That (cell.Parent, Is.Null);
+ }
+
+ [Test]
+ public void ChildElementsParentIsNulledWhenRemoved()
+ {
+ var collection = new ObservableCollection<string> {
+ "Hi", "Bye"
+ };
+
+ var list = new ListView();
+ list.ItemsSource = collection;
+
+ var cell = list.TemplatedItems[0];
+ Assume.That (cell.Parent, Is.SameAs (list));
+
+ collection.Remove (collection[0]);
+ Assert.That (cell.Parent, Is.Null);
+ }
+
+ [Test]
+ public void ChildElementsParentIsNulledWhenCleared()
+ {
+ var collection = new ObservableCollection<string> {
+ "Hi", "Bye"
+ };
+
+ var list = new ListView();
+ list.ItemsSource = collection;
+
+ var cell = list.TemplatedItems[0];
+ Assume.That (cell.Parent, Is.SameAs (list));
+
+ collection.Clear();
+ Assert.That (cell.Parent, Is.Null);
+ }
+
+ [TestCase (TargetPlatform.Android, ListViewCachingStrategy.RecycleElement)]
+ [TestCase (TargetPlatform.iOS, ListViewCachingStrategy.RecycleElement)]
+ [TestCase (TargetPlatform.Windows, ListViewCachingStrategy.RetainElement)]
+ [TestCase (TargetPlatform.Other, ListViewCachingStrategy.RetainElement)]
+ [TestCase (TargetPlatform.WinPhone, ListViewCachingStrategy.RetainElement)]
+ public void EnforcesCachingStrategy (TargetPlatform platform, ListViewCachingStrategy expected)
+ {
+ var oldOS = Device.OS;
+ // we need to do this because otherwise we cant set the caching strategy
+ Device.OS = platform;
+ var listView = new ListView (ListViewCachingStrategy.RecycleElement);
+
+ Assert.AreEqual (expected, listView.CachingStrategy);
+ Device.OS = oldOS;
+ }
+
+ [Test]
+ public void DefaultCacheStrategy ()
+ {
+ var listView = new ListView ();
+
+ Assert.AreEqual (ListViewCachingStrategy.RetainElement, listView.CachingStrategy);
+ }
+
+ [Test]
+ public void DoesNotRetainInRecycleMode ()
+ {
+ var items = new ObservableCollection<string> {
+ "Foo",
+ "Bar"
+ };
+
+ var oldOS = Device.OS;
+ // we need to do this because otherwise we cant set the caching strategy
+ Device.OS = TargetPlatform.Android;
+
+ var bindable = new ListView (ListViewCachingStrategy.RecycleElement);
+ bindable.ItemTemplate = new DataTemplate (typeof (TextCell)) {
+ Bindings = {
+ { TextCell.TextProperty, new Binding (".") }
+ }
+ };
+
+ bindable.ItemsSource = items;
+ var item1 = bindable.TemplatedItems[0];
+ var item2 = bindable.TemplatedItems[0];
+
+ Assert.False(ReferenceEquals (item1, item2));
+
+ Device.OS = oldOS;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/MapSpanTests.cs b/Xamarin.Forms.Core.UnitTests/MapSpanTests.cs
new file mode 100644
index 00000000..68645116
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/MapSpanTests.cs
@@ -0,0 +1,44 @@
+using NUnit.Framework;
+using Xamarin.Forms.Maps;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class MapSpanTests : BaseTestFixture
+ {
+ [Test]
+ public void Constructor ()
+ {
+ var span = new MapSpan (new Position(0, 0), 1, 1);
+
+ Assert.AreEqual (new Position (0, 0), span.Center);
+ Assert.AreEqual (1, span.LatitudeDegrees);
+ Assert.AreEqual (1, span.LongitudeDegrees);
+ Assert.IsTrue (span.Radius.Kilometers > 54 && span.Radius.Kilometers < 56);
+ }
+
+ [Test]
+ public void Equals ()
+ {
+ Assert.True (new MapSpan (new Position (1, 2), 3, 4) == new MapSpan (new Position (1, 2), 3, 4));
+ Assert.True (new MapSpan (new Position (1, 2), 3, 4) != new MapSpan (new Position (2, 3), 4, 5));
+ Assert.True (new MapSpan (new Position (1, 2), 3, 4).Equals (new MapSpan (new Position (1, 2), 3, 4)));
+ Assert.False (new MapSpan (new Position (1, 2), 3, 4).Equals ("MapSpan"));
+ Assert.False (new MapSpan (new Position (1, 2), 3, 4).Equals (null));
+ }
+
+ [Test]
+ public void HashCode ()
+ {
+ Assert.AreEqual (new MapSpan (new Position (1, 2), 3, 4).GetHashCode (), new MapSpan (new Position (1, 2), 3, 4).GetHashCode ());
+ }
+
+ [Test]
+ public void RangeClamping ()
+ {
+ var span = new MapSpan (new Position (0, 0), -1, -2);
+ Assert.IsTrue (span.LatitudeDegrees > 0);
+ Assert.IsTrue (span.LongitudeDegrees > 0);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/MapTests.cs b/Xamarin.Forms.Core.UnitTests/MapTests.cs
new file mode 100644
index 00000000..7c798b33
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/MapTests.cs
@@ -0,0 +1,147 @@
+using System;
+using NUnit.Framework;
+using Xamarin.Forms.Maps;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class MapTests : BaseTestFixture
+ {
+ [Test]
+ public void AddPin ()
+ {
+ var map = new Map ();
+
+ var home = new Pin {
+ Label = "Home",
+ Position = new Position (88, 2),
+ Type = PinType.Place,
+ Address = "123 My Place"
+ };
+
+ map.Pins.Add (home);
+
+ Assert.AreEqual (map.Pins.Count, 1);
+ Assert.AreEqual (map.Pins[0].Label, "Home");
+ var mall = new Pin {
+ Label = "Mall",
+ Position = new Position (-12, -67),
+ Type = PinType.Place,
+ Address = "123 Fun"
+ };
+
+ map.Pins.Add (mall);
+
+ Assert.AreEqual (map.Pins.Count, 2);
+ Assert.AreEqual (map.Pins[1].Position.Latitude, -12);
+ }
+
+ [Test]
+ public void AddPinWithoutName ()
+ {
+ var map = new Map ();
+ var noNamePin = new Pin {
+ Position = new Position (50, 50),
+ Type = PinType.Generic,
+ Address = "123 Fun"
+ };
+
+ var exception = Assert.Throws<ArgumentException> (() => map.Pins.Add (noNamePin));
+ Assert.That (exception.Message, Is.EqualTo ("Pin must have a Label to be added to a map"));
+ }
+
+ [Test]
+ public void AddPinWithoutAddress ()
+ {
+ var map = new Map ();
+ var noAddressPin = new Pin {
+ Position = new Position (37.9, -20.87),
+ Label = "I have no address",
+ Type = PinType.SearchResult
+ };
+
+ map.Pins.Add (noAddressPin);
+ Assert.AreEqual (map.Pins.Count, 1);
+ Assert.AreEqual (map.Pins[0].Label, "I have no address");
+ Assert.AreEqual (map.Pins[0].Address, null);
+ }
+
+ [Test]
+ public void Constructor ()
+ {
+ var center = new Position (15.5, 176);
+ var span = new MapSpan (center, 1, 2);
+ var map = new Map (span);
+
+ Assert.AreEqual (1, map.LastMoveToRegion.LatitudeDegrees);
+ Assert.AreEqual (2, map.LastMoveToRegion.LongitudeDegrees);
+ var position = new Position (15.5, 176);
+ Assert.AreEqual (position, map.LastMoveToRegion.Center);
+ }
+
+ [Test]
+ public void RemovePin ()
+ {
+ var map = new Map ();
+ var genericPlace = new Pin {
+ Label = "Generic",
+ Position = new Position (-12, -67),
+ Type = PinType.Generic,
+ Address = "XXX"
+ };
+
+ var mall = new Pin {
+ Label = "Mall",
+ Position = new Position (-29, -87),
+ Type = PinType.Place,
+ Address = "123 Fun"
+ };
+
+ map.Pins.Add (genericPlace);
+ Assert.AreEqual (map.Pins.Count, 1);
+
+ map.Pins.Add (mall);
+ Assert.AreEqual (map.Pins.Count, 2);
+
+ map.Pins.Remove (genericPlace);
+ Assert.AreEqual (map.Pins.Count, 1);
+
+ Assert.True (map.Pins.Contains (mall));
+ Assert.False (map.Pins.Contains (genericPlace));
+ }
+
+ [Test]
+ public void VisibleRegion ()
+ {
+ var map = new Map (new MapSpan (new Position (), 0, 0));
+ map.MoveToRegion (new MapSpan (new Position (1, 2), 3, 4));
+ Assert.AreEqual (null, map.VisibleRegion);
+
+ bool signaled = false;
+ MessagingCenter.Subscribe<Map, MapSpan> (this, "MapMoveToRegion", (s, a) => {
+ signaled = true;
+ map.VisibleRegion = a;
+ }, map);
+
+ map.MoveToRegion (new MapSpan (new Position (1, 2), 3, 4));
+ Assert.AreEqual (new MapSpan (new Position (1, 2), 3, 4), map.LastMoveToRegion);
+ Assert.True (signaled);
+ }
+
+ [Test]
+ public void VisibleRegionDoubleSet ()
+ {
+ var map = new Map ();
+
+ bool signaled = false;
+ map.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "VisibleRegion")
+ signaled = true;
+ };
+
+ map.VisibleRegion = map.VisibleRegion;
+
+ Assert.False (signaled);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/MarginTests.cs b/Xamarin.Forms.Core.UnitTests/MarginTests.cs
new file mode 100644
index 00000000..fd5debfa
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/MarginTests.cs
@@ -0,0 +1,134 @@
+using NUnit.Framework;
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ public class MarginTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void GetSizeRequestIncludesMargins ()
+ {
+ var platform = new UnitPlatform ((b, d, e) => new SizeRequest(new Size(100,50)));
+
+ var parent = new ContentView {
+ Platform = platform,
+ IsPlatformEnabled = true,
+ };
+ var child = new Button {
+ Text = "Test",
+ Platform = platform,
+ IsPlatformEnabled = true,
+ };
+
+
+ child.Margin = new Thickness (10, 20, 30, 40);
+ parent.Content = child;
+
+ var result = parent.Measure (double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.IncludeMargins);
+ Assert.AreEqual (new Size (140, 110), result.Request);
+ }
+
+ [Test]
+ public void MarginsAffectPositionInContentView ()
+ {
+ var platform = new UnitPlatform ((b, d, e) => new SizeRequest(new Size(100,50)));
+
+ var parent = new ContentView {
+ Platform = platform,
+ IsPlatformEnabled = true,
+ };
+ var child = new Button {
+ Text = "Test",
+ Platform = platform,
+ IsPlatformEnabled = true,
+ };
+
+
+ child.Margin = new Thickness (10, 20, 30, 40);
+ parent.Content = child;
+
+ parent.Layout (new Rectangle (0, 0, 140, 110));
+ Assert.AreEqual (new Rectangle (10, 20, 100, 50), child.Bounds);
+ }
+
+ [Test]
+ public void ChangingMarginCausesRelayout ()
+ {
+ var platform = new UnitPlatform ((b, d, e) => new SizeRequest(new Size(100,50)));
+
+ var parent = new ContentView {
+ Platform = platform,
+ IsPlatformEnabled = true,
+ };
+ var child = new Button {
+ Text = "Test",
+ VerticalOptions = LayoutOptions.Start,
+ HorizontalOptions = LayoutOptions.Start,
+ Platform = platform,
+ IsPlatformEnabled = true,
+ };
+
+
+ child.Margin = new Thickness (10, 20, 30, 40);
+ parent.Content = child;
+
+ parent.Layout (new Rectangle (0, 0, 1000, 1000));
+ Assert.AreEqual (new Rectangle (10, 20, 100, 50), child.Bounds);
+ }
+
+ [Test]
+ public void IntegrationTest ()
+ {
+ var platform = new UnitPlatform ((b, d, e) => new SizeRequest(new Size(100,50)));
+
+ var parent = new StackLayout {
+ Platform = platform,
+ Spacing = 0,
+ IsPlatformEnabled = true,
+ };
+
+ var child1 = new Button {
+ Text = "Test",
+ VerticalOptions = LayoutOptions.Start,
+ HorizontalOptions = LayoutOptions.Start,
+ Platform = platform,
+ IsPlatformEnabled = true,
+ };
+
+ var child2 = new Button {
+ Text = "Test",
+ Platform = platform,
+ IsPlatformEnabled = true,
+ };
+
+ child2.Margin = new Thickness (5, 10, 15, 20);
+
+ parent.Children.Add (child1);
+ parent.Children.Add (child2);
+
+ parent.Layout (new Rectangle (0, 0, 1000, 1000));
+
+ Assert.AreEqual (new Rectangle (0, 0, 100, 50), child1.Bounds);
+ Assert.AreEqual (new Rectangle (5, 60, 980, 50), child2.Bounds);
+
+ child1.Margin = new Thickness (10, 20, 30, 40);
+
+ Assert.AreEqual (new Rectangle (10, 20, 100, 50), child1.Bounds);
+ Assert.AreEqual (new Rectangle (5, 120, 980, 50), child2.Bounds);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/MasterDetailFormUnitTests.cs b/Xamarin.Forms.Core.UnitTests/MasterDetailFormUnitTests.cs
new file mode 100644
index 00000000..3c1e27ad
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/MasterDetailFormUnitTests.cs
@@ -0,0 +1,415 @@
+using System;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ internal class TestDeviceInfo : DeviceInfo
+ {
+ public TestDeviceInfo ()
+ {
+ CurrentOrientation = DeviceOrientation.Portrait;
+ }
+ public override Size PixelScreenSize
+ {
+ get { return new Size (100, 200); }
+ }
+
+ public override Size ScaledScreenSize
+ {
+ get { return new Size (50, 100); }
+ }
+
+ public override double ScalingFactor
+ {
+ get { return 2; }
+ }
+ }
+
+ [TestFixture]
+ public class MasterDetailPageUnitTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ var mockDeviceInfo = new TestDeviceInfo ();
+ Device.Info = mockDeviceInfo;
+ }
+
+ [Test]
+ public void TestConstructor ()
+ {
+
+ MasterDetailPage page = new MasterDetailPage ();
+
+ Assert.Null (page.Master);
+ Assert.Null (page.Detail);
+ }
+
+ [Test]
+ public void TestMasterSetter ()
+ {
+ MasterDetailPage page = new MasterDetailPage ();
+ var child = new ContentPage {Content = new Label (), Title = "Foo"};
+ page.Master = child;
+
+ Assert.AreEqual (child, page.Master);
+ }
+
+ [Test]
+ public void TestMasterSetNull ()
+ {
+ MasterDetailPage page = new MasterDetailPage ();
+ var child = new ContentPage {Content = new Label (), Title = "Foo"};
+ page.Master = child;
+
+ Assert.Throws<ArgumentNullException> (() => { page.Master = null; });
+ }
+
+ [Test]
+ public void TestMasterChanged ()
+ {
+ MasterDetailPage page = new MasterDetailPage ();
+ var child = new ContentPage {Content = new Label (), Title = "Foo"};
+
+ bool changed = false;
+ page.PropertyChanged += (sender, e) => {
+ if (e.PropertyName == "Master")
+ changed = true;
+ };
+
+ page.Master = child;
+
+ Assert.True (changed);
+ }
+
+ [Test]
+ public void TestDetailSetter ()
+ {
+ MasterDetailPage page = new MasterDetailPage ();
+ var child = new ContentPage {Content = new Label ()};
+ page.Detail = child;
+
+ Assert.AreEqual (child, page.Detail);
+ }
+
+ [Test]
+ public void TestDetailSetNull ()
+ {
+ MasterDetailPage page = new MasterDetailPage ();
+ var child = new ContentPage {Content = new Label ()};
+ page.Detail = child;
+
+ Assert.Throws<ArgumentNullException> ( () => { page.Detail = null; });
+ }
+
+ [Test]
+ public void TestDetailChanged ()
+ {
+ MasterDetailPage page = new MasterDetailPage ();
+ var child = new ContentPage {Content = new Label ()};
+
+ bool changed = false;
+ page.PropertyChanged += (sender, e) => {
+ if (e.PropertyName == "Detail")
+ changed = true;
+ };
+
+ page.Detail = child;
+
+ Assert.True (changed);
+ }
+
+ [Test]
+ public void ThrowsWhenMasterSetWithoutValidTitle ([Values (null, "")] string title)
+ {
+ var page = new MasterDetailPage ();
+ Assert.Throws<InvalidOperationException> (() => page.Master = new ContentPage {Title = title});
+ }
+
+ [Test]
+ public void TestThrowsWhenPackedWithoutSetting ()
+ {
+ MasterDetailPage page = new MasterDetailPage ();
+ Assert.Throws<InvalidOperationException> (() => new TabbedPage {Children = {page}});
+ }
+
+ [Test]
+ public void TestDoesNotThrowWhenPackedWithSetting ()
+ {
+ MasterDetailPage page = new MasterDetailPage {
+ Master = new ContentPage {Content = new View (), Title = "Foo"},
+ Detail = new ContentPage {Content = new View ()}
+ };
+ Assert.DoesNotThrow (() => new TabbedPage {Children = {page}});
+ }
+
+ [Test]
+ public void TestMasterVisible ()
+ {
+ var page = new MasterDetailPage ();
+
+ Assert.AreEqual (false, page.IsPresented);
+
+ bool signaled = false;
+ page.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == MasterDetailPage.IsPresentedProperty.PropertyName)
+ signaled = true;
+ };
+
+ page.IsPresented = true;
+
+ Assert.AreEqual (true, page.IsPresented);
+ Assert.True (signaled);
+ }
+
+ [Test]
+ public void TestMasterVisibleDoubleSet ()
+ {
+ var page = new MasterDetailPage ();
+
+ bool signaled = false;
+ page.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == MasterDetailPage.IsPresentedProperty.PropertyName)
+ signaled = true;
+ };
+
+ page.IsPresented = page.IsPresented;
+
+ Assert.False (signaled);
+ }
+
+ [Test]
+ public void TestSetMasterBounds ()
+ {
+ var page = new MasterDetailPage {
+ Master = new ContentPage {Content = new View (), Title = "Foo"},
+ Detail = new ContentPage {Content = new View ()}
+ };
+
+ page.MasterBounds = new Rectangle (0, 0, 100, 100);
+ Assert.AreEqual (new Rectangle (0, 0, 100, 100), page.Master.Bounds);
+ Assert.AreEqual (new Rectangle (0, 0, 100, 100), page.MasterBounds);
+ }
+
+ [Test]
+ public void TestSetDetailBounds ()
+ {
+ var page = new MasterDetailPage {
+ Master = new ContentPage {Content = new View (), Title = "Foo"},
+ Detail = new ContentPage {Content = new View ()}
+ };
+
+ page.DetailBounds = new Rectangle (0, 0, 100, 100);
+ Assert.AreEqual (new Rectangle (0, 0, 100, 100), page.Detail.Bounds);
+ Assert.AreEqual (new Rectangle (0, 0, 100, 100), page.DetailBounds);
+ }
+
+ [Test]
+ public void TestLayoutChildren ()
+ {
+ var page = new MasterDetailPage {
+ Master = new ContentPage { Content = new View (), IsPlatformEnabled = true, Title = "Foo" },
+ Detail = new ContentPage { Content = new View (), IsPlatformEnabled = true },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ page.MasterBounds = new Rectangle (0, 0, 100, 200);
+ page.DetailBounds = new Rectangle (0, 0, 100, 100);
+
+ page.Master.Layout (new Rectangle(0, 0, 1, 1));
+ page.Detail.Layout (new Rectangle(0, 0, 1, 1));
+
+ page.Layout (new Rectangle (0, 0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (0, 0, 100, 200), page.Master.Bounds);
+ Assert.AreEqual (new Rectangle (0, 0, 100, 100), page.Detail.Bounds);
+ }
+
+ [Test]
+ public void ThorwsInLayoutChildrenWithNullDetail ()
+ {
+ var page = new MasterDetailPage {
+ Master = new ContentPage { Content = new View (), IsPlatformEnabled = true, Title = "Foo" },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ Assert.Throws<InvalidOperationException> (() => page.Layout (new Rectangle (0, 0, 200, 200)));
+ }
+
+ [Test]
+ public void ThorwsInLayoutChildrenWithNullMaster ()
+ {
+ var page = new MasterDetailPage {
+ Detail = new ContentPage { Content = new View (), IsPlatformEnabled = true },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ Assert.Throws<InvalidOperationException> (() => page.Layout (new Rectangle(0, 0, 200, 200)));
+ }
+
+ [Test]
+ public void ThorwsInSetDetailBoundsWithNullDetail ()
+ {
+ var page = new MasterDetailPage {
+ Master = new ContentPage {Content = new View (), Title = "Foo"},
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ Assert.Throws<InvalidOperationException> (() => page.DetailBounds = new Rectangle(0, 0, 200, 200));
+ }
+
+ [Test]
+ public void ThrowsInSetMasterBoundsWithNullMaster ()
+ {
+ var page = new MasterDetailPage {
+ Detail = new ContentPage {Content = new View ()},
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ Assert.Throws<InvalidOperationException> (() => page.MasterBounds = new Rectangle(0, 0, 200, 200));
+ }
+
+ [Test]
+ public void ThrowsInSetIsPresentOnSplitModeOnTablet ()
+ {
+ Device.Idiom = TargetIdiom.Tablet;
+ var page = new MasterDetailPage {
+ Master = new ContentPage { Content = new View (), IsPlatformEnabled = true, Title = "Foo" },
+ Detail = new ContentPage { Content = new View (), IsPlatformEnabled = true },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform (),
+ MasterBehavior = MasterBehavior.Split
+ };
+
+ Assert.Throws<InvalidOperationException> (() => page.IsPresented = false);
+ }
+
+ [Test]
+ public void ThorwsInSetIsPresentOnSplitPortraitModeOnTablet ()
+ {
+ Device.Idiom = TargetIdiom.Tablet;
+ Device.Info.CurrentOrientation = DeviceOrientation.Portrait;
+
+ var page = new MasterDetailPage {
+ Master = new ContentPage { Content = new View (), IsPlatformEnabled = true, Title = "Foo" },
+ Detail = new ContentPage { Content = new View (), IsPlatformEnabled = true },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform (),
+ MasterBehavior = MasterBehavior.SplitOnPortrait
+ };
+
+ Assert.Throws<InvalidOperationException> (() => page.IsPresented = false);
+ }
+
+ [Test]
+ public void TestSetIsPresentedOnPopoverMode ()
+ {
+ Device.Info.CurrentOrientation = DeviceOrientation.Landscape;
+
+ var page = new MasterDetailPage {
+ Master = new ContentPage { Content = new View (), IsPlatformEnabled = true, Title = "Foo" },
+ Detail = new ContentPage { Content = new View (), IsPlatformEnabled = true },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform (),
+ MasterBehavior = MasterBehavior.Popover
+ };
+ page.IsPresented = true;
+
+ Assert.AreEqual (true, page.IsPresented);
+ }
+
+ [Test]
+ public void SendsBackEventToPresentedMasterFirst ()
+ {
+ var detail = new BackButtonPage () {Handle = true};
+ var master = new BackButtonPage () {Title = "Master"};
+ var mdp = new MasterDetailPage () {
+ Detail = detail,
+ Master = master,
+ IsPresented = true,
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ mdp.BackButtonPressed += (sender, args) => {
+ args.Handled = mdp.IsPresented;
+ mdp.IsPresented = false;
+ };
+
+ var detailEmitted = false;
+ var masterEmitted = false;
+
+ detail.BackPressed += (sender, args) => detailEmitted = true;
+ master.BackPressed += (sender, args) => masterEmitted = true;
+
+ var result = mdp.SendBackButtonPressed ();
+
+ Assert.True (masterEmitted);
+ Assert.False (detailEmitted);
+ Assert.True (result);
+ }
+
+ [Test]
+ public void EmitsCorrectlyWhenPresentedOnBackPressed ()
+ {
+ var detail = new BackButtonPage ();
+ var master = new BackButtonPage { Title = "Master" };
+ var mdp = new MasterDetailPage {
+ Detail = detail,
+ Master = master,
+ IsPresented = true,
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ mdp.BackButtonPressed += (sender, args) => {
+ args.Handled = mdp.IsPresented;
+ mdp.IsPresented = false;
+ };
+
+ var detailEmitted = false;
+ var masterEmitted = false;
+
+ detail.BackPressed += (sender, args) => detailEmitted = true;
+ master.BackPressed += (sender, args) => masterEmitted = true;
+
+ var result = mdp.SendBackButtonPressed ();
+
+ Assert.True (masterEmitted);
+ Assert.False (detailEmitted);
+ Assert.True (result);
+ }
+
+ [Test]
+ public void ThrowsExceptionWhenAddingAlreadyParentedDetail ()
+ {
+ var detail = new ContentPage {};
+
+ // give detail a parent
+ var nav = new NavigationPage (detail);
+
+ var mdp = new MasterDetailPage ();
+ Assert.Throws<InvalidOperationException> (() => mdp.Detail = detail);
+ }
+
+ [Test]
+ public void ThrowsExceptionWhenAddingAlreadyParentedMaster ()
+ {
+ var master = new ContentPage { Title = "Foo" };
+
+ // give master a parent
+ var nav = new NavigationPage (master);
+
+ var mdp = new MasterDetailPage ();
+ Assert.Throws<InvalidOperationException> (() => mdp.Master = master);
+ }
+ }
+
+}
diff --git a/Xamarin.Forms.Core.UnitTests/MenuItemTests.cs b/Xamarin.Forms.Core.UnitTests/MenuItemTests.cs
new file mode 100644
index 00000000..d6163058
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/MenuItemTests.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ public class MenuItemTests
+ : MenuItemTests<MenuItem>
+ {
+ }
+
+ [TestFixture]
+ public abstract class MenuItemTests<T>
+ : CommandSourceTests<T>
+ where T : MenuItem, new()
+ {
+ [Test]
+ public void Activated()
+ {
+ var item = new MenuItem();
+
+ bool activated = false;
+ item.Clicked += (sender, args) => activated = true;
+
+ item.Activate();
+
+ Assert.That (activated, Is.True);
+ }
+
+ [Test]
+ public void Command()
+ {
+ bool executed = false;
+ var param = new object();
+
+ var c = new Command (o => {
+ Assert.That (o, Is.SameAs (param));
+ executed = true;
+ });
+
+ var item = new MenuItem { Command = c, CommandParameter = param };
+ item.Activate();
+
+ Assert.That (executed, Is.True);
+ }
+
+ protected override T CreateSource()
+ {
+ return new T();
+ }
+
+ protected override void Activate (T source)
+ {
+ source.Activate();
+ }
+
+ protected override BindableProperty IsEnabledProperty
+ {
+ get { return MenuItem.IsEnabledProperty; }
+ }
+
+ protected override BindableProperty CommandProperty
+ {
+ get { return MenuItem.CommandProperty; }
+ }
+
+ protected override BindableProperty CommandParameterProperty
+ {
+ get { return MenuItem.CommandParameterProperty; }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/MessagingCenterTests.cs b/Xamarin.Forms.Core.UnitTests/MessagingCenterTests.cs
new file mode 100644
index 00000000..46dfdcdb
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/MessagingCenterTests.cs
@@ -0,0 +1,191 @@
+using System;
+using NUnit.Framework;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class MessagingCenterTests : BaseTestFixture
+ {
+ [Test]
+ public void SingleSubscriber ()
+ {
+ string sentMessage = null;
+ MessagingCenter.Subscribe<MessagingCenterTests, string> (this, "SimpleTest", (sender, args) => sentMessage = args);
+
+ MessagingCenter.Send (this, "SimpleTest", "My Message");
+
+ Assert.That (sentMessage, Is.EqualTo ("My Message"));
+
+ MessagingCenter.Unsubscribe<MessagingCenterTests, string> (this, "SimpleTest");
+ }
+
+ [Test]
+ public void Filter ()
+ {
+ string sentMessage = null;
+ MessagingCenter.Subscribe<MessagingCenterTests, string> (this, "SimpleTest", (sender, args) => sentMessage = args, this);
+
+ MessagingCenter.Send (new MessagingCenterTests (), "SimpleTest", "My Message");
+
+ Assert.That (sentMessage, Is.Null);
+
+ MessagingCenter.Send (this, "SimpleTest", "My Message");
+
+ Assert.That (sentMessage, Is.EqualTo ("My Message"));
+
+ MessagingCenter.Unsubscribe<MessagingCenterTests, string> (this, "SimpleTest");
+ }
+
+ [Test]
+ public void MultiSubscriber ()
+ {
+ var sub1 = new object ();
+ var sub2 = new object ();
+ string sentMessage1 = null;
+ string sentMessage2 = null;
+ MessagingCenter.Subscribe<MessagingCenterTests, string> (sub1, "SimpleTest", (sender, args) => sentMessage1 = args);
+ MessagingCenter.Subscribe<MessagingCenterTests, string> (sub2, "SimpleTest", (sender, args) => sentMessage2 = args);
+
+ MessagingCenter.Send (this, "SimpleTest", "My Message");
+
+ Assert.That (sentMessage1, Is.EqualTo ("My Message"));
+ Assert.That (sentMessage2, Is.EqualTo ("My Message"));
+
+ MessagingCenter.Unsubscribe<MessagingCenterTests, string> (sub1, "SimpleTest");
+ MessagingCenter.Unsubscribe<MessagingCenterTests, string> (sub2, "SimpleTest");
+ }
+
+ [Test]
+ public void Unsubscribe ()
+ {
+ string sentMessage = null;
+ MessagingCenter.Subscribe<MessagingCenterTests, string> (this, "SimpleTest", (sender, args) => sentMessage = args);
+ MessagingCenter.Unsubscribe<MessagingCenterTests, string> (this, "SimpleTest");
+
+ MessagingCenter.Send (this, "SimpleTest", "My Message");
+
+ Assert.That (sentMessage, Is.EqualTo (null));
+ }
+
+ [Test]
+ public void SendWithoutSubscribers ()
+ {
+ Assert.DoesNotThrow (() => MessagingCenter.Send (this, "SimpleTest", "My Message"));
+ }
+
+ [Test]
+ public void NoArgSingleSubscriber ()
+ {
+ bool sentMessage = false;
+ MessagingCenter.Subscribe<MessagingCenterTests> (this, "SimpleTest", sender => sentMessage = true);
+
+ MessagingCenter.Send (this, "SimpleTest");
+
+ Assert.That (sentMessage, Is.True);
+
+ MessagingCenter.Unsubscribe<MessagingCenterTests> (this, "SimpleTest");
+ }
+
+ [Test]
+ public void NoArgFilter ()
+ {
+ bool sentMessage = false;
+ MessagingCenter.Subscribe (this, "SimpleTest", (sender) => sentMessage = true, this);
+
+ MessagingCenter.Send (new MessagingCenterTests (), "SimpleTest");
+
+ Assert.That (sentMessage, Is.False);
+
+ MessagingCenter.Send (this, "SimpleTest");
+
+ Assert.That (sentMessage, Is.True);
+
+ MessagingCenter.Unsubscribe<MessagingCenterTests> (this, "SimpleTest");
+ }
+
+ [Test]
+ public void NoArgMultiSubscriber ()
+ {
+ var sub1 = new object ();
+ var sub2 = new object ();
+ bool sentMessage1 = false;
+ bool sentMessage2 = false;
+ MessagingCenter.Subscribe<MessagingCenterTests> (sub1, "SimpleTest", (sender) => sentMessage1 = true);
+ MessagingCenter.Subscribe<MessagingCenterTests> (sub2, "SimpleTest", (sender) => sentMessage2 = true);
+
+ MessagingCenter.Send (this, "SimpleTest");
+
+ Assert.That (sentMessage1, Is.True);
+ Assert.That (sentMessage2, Is.True);
+
+ MessagingCenter.Unsubscribe<MessagingCenterTests> (sub1, "SimpleTest");
+ MessagingCenter.Unsubscribe<MessagingCenterTests> (sub2, "SimpleTest");
+ }
+
+ [Test]
+ public void NoArgUnsubscribe ()
+ {
+ bool sentMessage = false;
+ MessagingCenter.Subscribe<MessagingCenterTests> (this, "SimpleTest", (sender) => sentMessage = true);
+ MessagingCenter.Unsubscribe<MessagingCenterTests> (this, "SimpleTest");
+
+ MessagingCenter.Send (this, "SimpleTest", "My Message");
+
+ Assert.That (sentMessage, Is.False);
+ }
+
+ [Test]
+ public void NoArgSendWithoutSubscribers ()
+ {
+ Assert.DoesNotThrow (() => MessagingCenter.Send (this, "SimpleTest"));
+ }
+
+ [Test]
+ public void ThrowOnNullArgs ()
+ {
+ Assert.Throws<ArgumentNullException> (() => MessagingCenter.Subscribe<MessagingCenterTests, string> (null, "Foo", (sender, args) => { }));
+ Assert.Throws<ArgumentNullException> (() => MessagingCenter.Subscribe<MessagingCenterTests, string> (this, null, (sender, args) => { }));
+ Assert.Throws<ArgumentNullException> (() => MessagingCenter.Subscribe<MessagingCenterTests, string> (this, "Foo", null));
+
+ Assert.Throws<ArgumentNullException> (() => MessagingCenter.Subscribe<MessagingCenterTests> (null, "Foo", (sender) => { }));
+ Assert.Throws<ArgumentNullException> (() => MessagingCenter.Subscribe<MessagingCenterTests> (this, null, (sender) => { }));
+ Assert.Throws<ArgumentNullException> (() => MessagingCenter.Subscribe<MessagingCenterTests> (this, "Foo", null));
+
+ Assert.Throws<ArgumentNullException> (() => MessagingCenter.Send<MessagingCenterTests, string> (null, "Foo", "Bar"));
+ Assert.Throws<ArgumentNullException> (() => MessagingCenter.Send<MessagingCenterTests, string> (this, null, "Bar"));
+
+ Assert.Throws<ArgumentNullException> (() => MessagingCenter.Send<MessagingCenterTests> (null, "Foo"));
+ Assert.Throws<ArgumentNullException> (() => MessagingCenter.Send<MessagingCenterTests> (this, null));
+
+ Assert.Throws<ArgumentNullException> (() => MessagingCenter.Unsubscribe<MessagingCenterTests> (null, "Foo"));
+ Assert.Throws<ArgumentNullException> (() => MessagingCenter.Unsubscribe<MessagingCenterTests> (this, null));
+
+ Assert.Throws<ArgumentNullException> (() => MessagingCenter.Unsubscribe<MessagingCenterTests, string> (null, "Foo"));
+ Assert.Throws<ArgumentNullException> (() => MessagingCenter.Unsubscribe<MessagingCenterTests, string> (this, null));
+ }
+
+ [Test]
+ public void UnsubscribeInCallback ()
+ {
+ int messageCount = 0;
+
+ var subscriber1 = new object ();
+ var subscriber2 = new object ();
+
+ MessagingCenter.Subscribe<MessagingCenterTests> (subscriber1, "SimpleTest", (sender) => {
+ messageCount++;
+ MessagingCenter.Unsubscribe<MessagingCenterTests> (subscriber2, "SimpleTest");
+ });
+
+ MessagingCenter.Subscribe<MessagingCenterTests> (subscriber2, "SimpleTest", (sender) => {
+ messageCount++;
+ MessagingCenter.Unsubscribe<MessagingCenterTests> (subscriber1, "SimpleTest");
+ });
+
+ MessagingCenter.Send (this, "SimpleTest");
+
+ Assert.AreEqual (1, messageCount);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/MockPlatformServices.cs b/Xamarin.Forms.Core.UnitTests/MockPlatformServices.cs
new file mode 100644
index 00000000..7d2317b3
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/MockPlatformServices.cs
@@ -0,0 +1,270 @@
+using System;
+using System.Threading.Tasks;
+using System.IO;
+using System.Threading;
+using System.Reflection;
+using System.IO.IsolatedStorage;
+using System.Collections.Generic;
+using Xamarin.Forms;
+using Xamarin.Forms.Core.UnitTests;
+using System.Security.Cryptography;
+using System.Text;
+#if WINDOWS_PHONE
+using Xamarin.Forms.Platform.WinPhone;
+#endif
+
+[assembly:Dependency (typeof(MockDeserializer))]
+[assembly:Dependency (typeof(MockResourcesProvider))]
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ internal class MockPlatformServices : IPlatformServices
+ {
+ Action<Action> invokeOnMainThread;
+ Action<Uri> openUriAction;
+ Func<Uri, CancellationToken, Task<Stream>> getStreamAsync;
+ public MockPlatformServices (Action<Action> invokeOnMainThread = null, Action<Uri> openUriAction = null, Func<Uri, CancellationToken, Task<Stream>> getStreamAsync = null)
+ {
+ this.invokeOnMainThread = invokeOnMainThread;
+ this.openUriAction = openUriAction;
+ this.getStreamAsync = getStreamAsync;
+ }
+
+ static MD5CryptoServiceProvider checksum = new MD5CryptoServiceProvider ();
+
+ public string GetMD5Hash (string input)
+ {
+ var bytes = checksum.ComputeHash (Encoding.UTF8.GetBytes (input));
+ var ret = new char [32];
+ for (int i = 0; i < 16; i++){
+ ret [i*2] = (char)hex (bytes [i] >> 4);
+ ret [i*2+1] = (char)hex (bytes [i] & 0xf);
+ }
+ return new string (ret);
+ }
+ static int hex (int v)
+ {
+ if (v < 10)
+ return '0' + v;
+ return 'a' + v-10;
+ }
+
+ public double GetNamedSize (NamedSize size, Type targetElement, bool useOldSizes)
+ {
+ switch (size) {
+ case NamedSize.Default:
+ return 10;
+ case NamedSize.Micro:
+ return 4;
+ case NamedSize.Small:
+ return 8;
+ case NamedSize.Medium:
+ return 12;
+ case NamedSize.Large:
+ return 16;
+ default:
+ throw new ArgumentOutOfRangeException ("size");
+ }
+ }
+
+ public void OpenUriAction (Uri uri)
+ {
+ if (openUriAction != null)
+ openUriAction (uri);
+ else
+ throw new NotImplementedException ();
+ }
+
+ public bool IsInvokeRequired
+ {
+ get { return false; }
+ }
+
+ public void BeginInvokeOnMainThread (Action action)
+ {
+ if (invokeOnMainThread == null)
+ action ();
+ else
+ invokeOnMainThread (action);
+ }
+
+ public void StartTimer (TimeSpan interval, Func<bool> callback)
+ {
+ Timer timer = null;
+ TimerCallback onTimeout = o => BeginInvokeOnMainThread (() => {
+ if (callback ())
+ return;
+
+ timer.Dispose ();
+ });
+ timer = new Timer (onTimeout, null, interval, interval);
+ }
+
+ public Task<Stream> GetStreamAsync (Uri uri, CancellationToken cancellationToken)
+ {
+ if (getStreamAsync == null)
+ throw new NotImplementedException ();
+ return getStreamAsync (uri, cancellationToken);
+ }
+
+ public Assembly[] GetAssemblies ()
+ {
+ return AppDomain.CurrentDomain.GetAssemblies ();
+ }
+
+ public ITimer CreateTimer (Action<object> callback)
+ {
+ return new MockTimer (new Timer (o => callback(o)));
+ }
+
+ public ITimer CreateTimer (Action<object> callback, object state, int dueTime, int period)
+ {
+ return new MockTimer (new Timer (o => callback(o), state, dueTime, period));
+ }
+
+ public ITimer CreateTimer (Action<object> callback, object state, long dueTime, long period)
+ {
+ return new MockTimer (new Timer (o => callback(o), state, dueTime, period));
+ }
+
+ public ITimer CreateTimer (Action<object> callback, object state, TimeSpan dueTime, TimeSpan period)
+ {
+ return new MockTimer (new Timer (o => callback(o), state, dueTime, period));
+ }
+
+ public ITimer CreateTimer (Action<object> callback, object state, uint dueTime, uint period)
+ {
+ return new MockTimer (new Timer (o => callback(o), state, dueTime, period));
+ }
+
+ public class MockTimer : ITimer
+ {
+ readonly Timer timer;
+ public MockTimer (Timer timer)
+ {
+ this.timer = timer;
+ }
+
+ public void Change (int dueTime, int period)
+ {
+ timer.Change (dueTime, period);
+ }
+ public void Change (long dueTime, long period)
+ {
+ timer.Change (dueTime, period);
+ }
+ public void Change (TimeSpan dueTime, TimeSpan period)
+ {
+ timer.Change (dueTime, period);
+ }
+ public void Change (uint dueTime, uint period)
+ {
+ timer.Change (dueTime, period);
+ }
+ }
+
+ public IIsolatedStorageFile GetUserStoreForApplication ()
+ {
+#if WINDOWS_PHONE
+ return new MockIsolatedStorageFile (IsolatedStorageFile.GetUserStoreForApplication ());
+#else
+ return new MockIsolatedStorageFile (IsolatedStorageFile.GetUserStoreForAssembly ());
+#endif
+ }
+
+ public class MockIsolatedStorageFile : IIsolatedStorageFile
+ {
+ readonly IsolatedStorageFile isolatedStorageFile;
+ public MockIsolatedStorageFile (IsolatedStorageFile isolatedStorageFile)
+ {
+ this.isolatedStorageFile = isolatedStorageFile;
+ }
+
+ public Task<bool> GetDirectoryExistsAsync (string path)
+ {
+ return Task.FromResult (isolatedStorageFile.DirectoryExists (path));
+ }
+
+ public Task CreateDirectoryAsync (string path)
+ {
+ isolatedStorageFile.CreateDirectory (path);
+ return Task.FromResult (true);
+ }
+
+ public Task<Stream> OpenFileAsync (string path, FileMode mode, FileAccess access)
+ {
+ Stream stream = isolatedStorageFile.OpenFile (path, (System.IO.FileMode)mode, (System.IO.FileAccess)access);
+ return Task.FromResult (stream);
+ }
+
+ public Task<Stream> OpenFileAsync (string path, FileMode mode, FileAccess access, FileShare share)
+ {
+ Stream stream = isolatedStorageFile.OpenFile (path, (System.IO.FileMode)mode, (System.IO.FileAccess)access, (System.IO.FileShare)share);
+ return Task.FromResult (stream);
+ }
+
+ public Task<bool> GetFileExistsAsync (string path)
+ {
+ return Task.FromResult (isolatedStorageFile.FileExists (path));
+ }
+
+ public Task<DateTimeOffset> GetLastWriteTimeAsync (string path)
+ {
+ return Task.FromResult (isolatedStorageFile.GetLastWriteTime (path));
+ }
+ }
+ }
+
+ internal class MockDeserializer : IDeserializer
+ {
+ public Task<IDictionary<string, object>> DeserializePropertiesAsync ()
+ {
+ return Task.FromResult<IDictionary<string, object>> (new Dictionary<string,object> ());
+ }
+
+ public Task SerializePropertiesAsync (IDictionary<string, object> properties)
+ {
+ return Task.FromResult (false);
+ }
+ }
+
+ internal class MockResourcesProvider : ISystemResourcesProvider
+ {
+ public IResourceDictionary GetSystemResources ()
+ {
+ var dictionary = new ResourceDictionary ();
+ Style style;
+ style = new Style (typeof(Label));
+ dictionary [Device.Styles.BodyStyleKey] = style;
+
+ style = new Style (typeof(Label));
+ style.Setters.Add (Label.FontSizeProperty, 50);
+ dictionary [Device.Styles.TitleStyleKey] = style;
+
+ style = new Style (typeof(Label));
+ style.Setters.Add (Label.FontSizeProperty, 40);
+ dictionary [Device.Styles.SubtitleStyleKey] = style;
+
+ style = new Style (typeof(Label));
+ style.Setters.Add (Label.FontSizeProperty, 30);
+ dictionary [Device.Styles.CaptionStyleKey] = style;
+
+ style = new Style (typeof(Label));
+ style.Setters.Add (Label.FontSizeProperty, 20);
+ dictionary [Device.Styles.ListItemTextStyleKey] = style;
+
+ style = new Style (typeof(Label));
+ style.Setters.Add (Label.FontSizeProperty, 10);
+ dictionary [Device.Styles.ListItemDetailTextStyleKey] = style;
+
+ return dictionary;
+ }
+ }
+
+ public class MockApplication : Application
+ {
+ public MockApplication ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/MockViewModel.cs b/Xamarin.Forms.Core.UnitTests/MockViewModel.cs
new file mode 100644
index 00000000..da2f6f96
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/MockViewModel.cs
@@ -0,0 +1,30 @@
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ internal class MockViewModel
+ : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ string text;
+ public virtual string Text {
+ get { return text; }
+ set {
+ if (text == value)
+ return;
+
+ text = value;
+ OnPropertyChanged ("Text");
+ }
+ }
+
+ protected void OnPropertyChanged ([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler (this, new PropertyChangedEventArgs (propertyName));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/MotionTests.cs b/Xamarin.Forms.Core.UnitTests/MotionTests.cs
new file mode 100644
index 00000000..acb764d7
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/MotionTests.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Collections.Generic;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ internal class BlockingTicker : Ticker
+ {
+ bool enabled;
+
+ protected override void EnableTimer ()
+ {
+ enabled = true;
+
+ while (enabled) {
+ SendSignals (16);
+ }
+ }
+
+ protected override void DisableTimer ()
+ {
+ enabled = false;
+ }
+ }
+
+ [TestFixture]
+ public class MotionTests : BaseTestFixture
+ {
+ [TestFixtureSetUp]
+ public void Init ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ Ticker.Default = new BlockingTicker ();
+ }
+
+ [TestFixtureTearDown]
+ public void End ()
+ {
+ Device.PlatformServices = null;
+ Ticker.Default = null;
+ }
+
+ [Test]
+ public void TestLinearTween ()
+ {
+ var tweener = new Tweener (250);
+
+ double value = 0;
+ int updates = 0;
+ tweener.ValueUpdated += (sender, args) => {
+ Assert.That (tweener.Value, Is.GreaterThanOrEqualTo (value));
+ value = tweener.Value;
+ updates++;
+ };
+ tweener.Start ();
+
+ Assert.That (updates, Is.GreaterThanOrEqualTo (10));
+ }
+
+ [Test]
+ public void ThrowsWithNullCallback ()
+ {
+ Assert.Throws<ArgumentNullException> (() => new View().Animate ("Test", (Action<double>) null));
+ }
+
+ [Test]
+ public void ThrowsWithNullTransform ()
+ {
+ Assert.Throws<ArgumentNullException> (() => new View().Animate<float> ("Test", null, f => { }));
+ }
+
+ [Test]
+ public void ThrowsWithNullSelf ()
+ {
+ Assert.Throws<ArgumentNullException> (() => AnimationExtensions.Animate (null, "Foo", d => (float)d, f => { }));
+ }
+
+ [Test]
+ public void Kinetic ()
+ {
+ var view = new View ();
+ var resultList = new List<Tuple<double, double>> ();
+ view.AnimateKinetic (
+ name: "Kinetics",
+ callback: (distance, velocity) => {
+ resultList.Add (new Tuple<double, double> (distance, velocity));
+ return true;
+ },
+ velocity: 100,
+ drag: 1);
+
+ Assert.That (resultList, Is.Not.Empty);
+ int checkVelo = 100;
+ int dragStep = 16;
+
+ foreach (var item in resultList) {
+ checkVelo -= dragStep;
+ Assert.AreEqual (checkVelo, item.Item2);
+ Assert.AreEqual (checkVelo * dragStep, item.Item1);
+ }
+ }
+
+ [Test]
+ public void KineticFinished ()
+ {
+ var view = new View ();
+ bool finished = false;
+ view.AnimateKinetic (
+ name: "Kinetics",
+ callback: (distance, velocity) => true,
+ velocity: 100,
+ drag: 1,
+ finished: () => finished = true);
+
+ Assert.True (finished);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/MultiPageTests.cs b/Xamarin.Forms.Core.UnitTests/MultiPageTests.cs
new file mode 100644
index 00000000..3d9faad5
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/MultiPageTests.cs
@@ -0,0 +1,805 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ public abstract class MultiPageTests<T> : BaseTestFixture
+ where T : Page
+ {
+ protected abstract MultiPage<T> CreateMultiPage();
+ protected abstract T CreateContainedPage();
+ protected abstract int GetIndex (T page);
+
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void TestSetChildren ()
+ {
+ var container = CreateMultiPage();
+ var page = (Page) container;
+
+ int childCount = 0;
+ page.ChildAdded += (sender, args) => childCount++;
+
+ int pagesAdded = 0;
+ container.PagesChanged += (sender, args) => {
+ if (args.Action == NotifyCollectionChangedAction.Add)
+ pagesAdded++;
+ };
+
+ container.Children.Add (CreateContainedPage());
+ container.Children.Add (CreateContainedPage());
+
+ Assert.AreEqual (2, childCount);
+ Assert.AreEqual (2, page.LogicalChildren.Count);
+ Assert.AreEqual (2, pagesAdded);
+ }
+
+ [Test]
+ public void TestOverwriteChildren()
+ {
+ var page = CreateMultiPage();
+ page.Children.Add (CreateContainedPage());
+ page.Children.Add (CreateContainedPage());
+
+ int childCount = 0;
+ int removeCount = 0;
+ page.ChildAdded += (sender, args) => childCount++;
+ page.ChildRemoved += (sender, args) => removeCount++;
+
+ foreach (var child in page.Children.ToArray())
+ page.Children.Remove ((T)child);
+
+ page.Children.Add (CreateContainedPage());
+ page.Children.Add (CreateContainedPage());
+
+ Assert.AreEqual (2, removeCount);
+ Assert.AreEqual (2, childCount);
+ Assert.AreEqual (2, page.LogicalChildren.Count);
+ }
+
+ [Test]
+ public void CurrentPageSetAfterAdd()
+ {
+ var page = CreateMultiPage();
+ Assert.That (page.CurrentPage, Is.Null);
+
+ var child = CreateContainedPage();
+
+ bool property = false;
+ page.PropertyChanged += (o, e) => {
+ if (e.PropertyName == "CurrentPage")
+ property = true;
+ };
+
+ page.Children.Add (child);
+
+ Assert.That (page.CurrentPage, Is.SameAs (child));
+ Assert.That (property, Is.True, "CurrentPage property change did not fire");
+ }
+
+ [Test]
+ public void CurrentPageChangedAfterRemove()
+ {
+ var page = CreateMultiPage();
+ var child = CreateContainedPage();
+ var child2 = CreateContainedPage();
+ page.Children.Add (child);
+ page.Children.Add (child2);
+
+ bool property = false;
+ page.PropertyChanged += (o, e) => {
+ if (e.PropertyName == "CurrentPage")
+ property = true;
+ };
+
+ page.Children.Remove (child);
+
+ Assert.That (page.CurrentPage, Is.SameAs (child2), "MultiPage.CurrentPage is not set to a new page after current was removed");
+ Assert.That (property, Is.True, "CurrentPage property change did not fire");
+ }
+
+ [Test]
+ public void CurrentPageNullAfterRemove()
+ {
+ var page = CreateMultiPage();
+ var child = CreateContainedPage();
+ page.Children.Add (child);
+
+ bool property = false;
+ page.PropertyChanged += (o, e) => {
+ if (e.PropertyName == "CurrentPage")
+ property = true;
+ };
+
+ page.Children.Remove (child);
+
+ Assert.That (page.CurrentPage, Is.Null, "MultiPage.CurrentPage is still set after that page was removed");
+ Assert.That (property, Is.True, "CurrentPage property change did not fire");
+ }
+
+ [Test]
+ public void TemplatedPage()
+ {
+ var page = CreateMultiPage();
+
+ page.ItemTemplate = new DataTemplate (() => {
+ var p = new ContentPage();
+ p.Content = new Label();
+ p.Content.SetBinding (Label.TextProperty, new Binding ("."));
+ return p;
+ });
+
+ page.ItemsSource = new[] { "Foo", "Bar" };
+
+ Action<Page, string> assertPage = (p, s) => {
+ Assert.That (p, Is.InstanceOf<ContentPage>());
+
+ var cp = (ContentPage) p;
+ Assert.That (cp.Content, Is.InstanceOf<Label>());
+ Assert.That (((Label)cp.Content).Text, Is.EqualTo (s));
+ };
+
+ var pages = page.Children.ToArray();
+ Assert.That (pages.Length, Is.EqualTo (2));
+ assertPage ((Page)pages[0], "Foo");
+ assertPage ((Page)pages[1], "Bar");
+ }
+
+ [Test]
+ public void SelectedItemSetAfterAdd()
+ {
+ var page = CreateMultiPage();
+ Assert.That (page.CurrentPage, Is.Null);
+
+ var items = new ObservableCollection<string>();
+
+ page.ItemsSource = items;
+
+ bool selected = false;
+ bool current = false;
+ page.PropertyChanged += (o, e) => {
+ if (e.PropertyName == "CurrentPage")
+ current = true;
+ else if (e.PropertyName == "SelectedItem")
+ selected = true;
+ };
+
+ items.Add ("foo");
+
+ Assert.That (page.SelectedItem, Is.SameAs (items.First()));
+ Assert.That (page.CurrentPage.BindingContext, Is.SameAs (page.SelectedItem));
+ Assert.That (current, Is.True, "CurrentPage property change did not fire");
+ Assert.That (selected, Is.True, "SelectedItem property change did not fire");
+ }
+
+ [Test]
+ public void SelectedItemNullAfterRemove()
+ {
+ var page = CreateMultiPage();
+ Assert.That (page.CurrentPage, Is.Null);
+
+ var items = new ObservableCollection<string> { "foo" };
+ page.ItemsSource = items;
+
+ bool selected = false;
+ bool current = false;
+ page.PropertyChanged += (o, e) => {
+ if (e.PropertyName == "CurrentPage")
+ current = true;
+ else if (e.PropertyName == "SelectedItem")
+ selected = true;
+ };
+
+ items.Remove ("foo");
+
+ Assert.That (page.SelectedItem, Is.Null, "MultiPage.SelectedItem is still set after that page was removed");
+ Assert.That (page.CurrentPage, Is.Null, "MultiPage.CurrentPage is still set after that page was removed");
+ Assert.That (current, Is.True, "CurrentPage property change did not fire");
+ Assert.That (selected, Is.True, "SelectedItem property change did not fire");
+ }
+
+ [Test]
+ [Description ("When ItemsSource is set with items, the first item should automatically be selected")]
+ public void SelectedItemSetAfterItemsSourceSet()
+ {
+ var page = CreateMultiPage();
+
+ bool selected = false;
+ bool current = false;
+ page.PropertyChanged += (o, e) => {
+ if (e.PropertyName == "CurrentPage")
+ current = true;
+ else if (e.PropertyName == "SelectedItem")
+ selected = true;
+ };
+
+ page.ItemsSource = new[] { "foo" };
+
+ Assert.That (page.SelectedItem, Is.SameAs (((string[]) page.ItemsSource)[0]));
+ Assert.That (page.CurrentPage.BindingContext, Is.SameAs (page.SelectedItem));
+ Assert.That (current, Is.True, "CurrentPage property change did not fire");
+ Assert.That (selected, Is.True, "SelectedItem property change did not fire");
+ }
+
+ [Test]
+ public void SelectedItemNoLongerPresent()
+ {
+ var page = CreateMultiPage();
+
+ string[] items = new[] { "foo", "bar" };
+ page.ItemsSource = items;
+ page.SelectedItem = items[1];
+
+ items = new[] { "fad", "baz" };
+ page.ItemsSource = items;
+
+ Assert.That (page.SelectedItem, Is.SameAs (items[0]));
+ }
+
+ [Test]
+ public void SelectedItemAfterMove()
+ {
+ var page = CreateMultiPage();
+
+ var items = new ObservableCollection<string> { "foo", "bar" };
+ page.ItemsSource = items;
+
+ Assert.That (page.SelectedItem, Is.SameAs (items[0]));
+ Assert.That (page.CurrentPage, Is.Not.Null);
+ Assert.That (page.CurrentPage.BindingContext, Is.SameAs (items[0]));
+
+ page.SelectedItem = items[1];
+ Assert.That (page.CurrentPage.BindingContext, Is.SameAs (items[1]));
+
+ items.Move (1, 0);
+
+ Assert.That (page.SelectedItem, Is.SameAs (items[0]));
+ Assert.That (page.CurrentPage, Is.Not.Null);
+ Assert.That (page.CurrentPage.BindingContext, Is.SameAs (items[0]));
+ }
+
+ [Test]
+ public void UntemplatedItemsSourcePage()
+ {
+ var page = CreateMultiPage();
+
+ page.ItemsSource = new[] { "Foo", "Bar" };
+
+ var pages = page.Children.ToArray();
+ Assert.That (pages.Length, Is.EqualTo (2));
+ Assert.That (((Page)pages[0]).Title, Is.EqualTo ("Foo"));
+ Assert.That (((Page)pages[1]).Title, Is.EqualTo ("Bar"));
+ }
+
+ [Test]
+ public void TemplatePagesAdded()
+ {
+ var page = CreateMultiPage();
+
+ page.ItemTemplate = new DataTemplate (() => {
+ var p = new ContentPage();
+ p.Content = new Label();
+ p.Content.SetBinding (Label.TextProperty, new Binding ("."));
+ return p;
+ });
+
+ var items = new ObservableCollection<string> { "Foo", "Bar" };
+ page.ItemsSource = items;
+
+ Action<IList<Element>, int, string> assertPage = (ps, index, s) => {
+ Page p = (Page)ps[index];
+ Assert.That (p, Is.InstanceOf<ContentPage>());
+ Assert.That (GetIndex ((T) p), Is.EqualTo (index));
+
+ var cp = (ContentPage) p;
+ Assert.That (cp.Content, Is.InstanceOf<Label>());
+ Assert.That (((Label)cp.Content).Text, Is.EqualTo (s));
+ };
+
+ items.Add ("Baz");
+
+ var pages = page.Children.ToArray();
+ Assert.That (pages.Length, Is.EqualTo (3), "Children should have 3 pages");
+ assertPage (pages, 0, "Foo");
+ assertPage (pages, 1, "Bar");
+ assertPage (pages, 2, "Baz");
+ }
+
+ [Test]
+ public void TemplatePagesRangeAdded()
+ {
+ var page = CreateMultiPage();
+
+ page.ItemTemplate = new DataTemplate (() => {
+ var p = new ContentPage();
+ p.Content = new Label();
+ p.Content.SetBinding (Label.TextProperty, new Binding ("."));
+ return p;
+ });
+
+ var items = new ObservableList<string> { "Foo", "Bar" };
+ page.ItemsSource = items;
+
+ Action<IList<Element>, int, string> assertPage = (ps, index, s) => {
+ Page p = (Page)ps[index];
+ Assert.That (p, Is.InstanceOf<ContentPage>());
+ Assert.That (GetIndex ((T) p), Is.EqualTo (index));
+
+ var cp = (ContentPage) p;
+ Assert.That (cp.Content, Is.InstanceOf<Label>());
+ Assert.That (((Label)cp.Content).Text, Is.EqualTo (s));
+ };
+
+ int addedCount = 0;
+ page.PagesChanged += (sender, e) => {
+ if (e.Action != NotifyCollectionChangedAction.Add)
+ return;
+
+ addedCount++;
+ Assert.That (e.NewItems.Count, Is.EqualTo (2));
+ };
+
+ items.AddRange (new[] { "Baz", "Bam" });
+
+ Assert.That (addedCount, Is.EqualTo (1));
+
+ var pages = page.Children.ToArray();
+ Assert.That (pages.Length, Is.EqualTo (4));
+ assertPage (pages, 0, "Foo");
+ assertPage (pages, 1, "Bar");
+ assertPage (pages, 2, "Baz");
+ assertPage (pages, 3, "Bam");
+ }
+
+ [Test]
+ public void TemplatePagesInserted()
+ {
+ var page = CreateMultiPage();
+
+ page.ItemTemplate = new DataTemplate (() => {
+ var p = new ContentPage();
+ p.Content = new Label();
+ p.Content.SetBinding (Label.TextProperty, new Binding ("."));
+ return p;
+ });
+
+ var items = new ObservableCollection<string> { "Foo", "Bar" };
+ page.ItemsSource = items;
+
+ Action<IList<Element>, int, string> assertPage = (ps, index, s) => {
+ Page p = (Page)ps[index];
+ Assert.That (p, Is.InstanceOf<ContentPage>());
+ Assert.That (GetIndex ((T) p), Is.EqualTo (index));
+
+ var cp = (ContentPage) p;
+ Assert.That (cp.Content, Is.InstanceOf<Label>());
+ Assert.That (((Label)cp.Content).Text, Is.EqualTo (s));
+ };
+
+ items.Insert (1, "Baz");
+
+ var pages = page.Children.ToArray();
+ Assert.That (pages.Length, Is.EqualTo (3));
+ assertPage (pages, 0, "Foo");
+ assertPage (pages, 1, "Baz");
+ assertPage (pages, 2, "Bar");
+ }
+
+ [Test]
+ public void TemplatePagesRangeInserted()
+ {
+ var page = CreateMultiPage();
+
+ page.ItemTemplate = new DataTemplate (() => {
+ var p = new ContentPage();
+ p.Content = new Label();
+ p.Content.SetBinding (Label.TextProperty, new Binding ("."));
+ return p;
+ });
+
+ var items = new ObservableList<string> { "Foo", "Bar" };
+ page.ItemsSource = items;
+
+ Action<IList<Element>, int, string> assertPage = (ps, index, s) => {
+ Page p = (Page)ps[index];
+ Assert.That (p, Is.InstanceOf<ContentPage>());
+ Assert.That (GetIndex ((T) p), Is.EqualTo (index));
+
+ var cp = (ContentPage) p;
+ Assert.That (cp.Content, Is.InstanceOf<Label>());
+ Assert.That (((Label)cp.Content).Text, Is.EqualTo (s));
+ };
+
+ items.InsertRange (1, new[] { "Baz", "Bam" });
+
+ var pages = page.Children.ToArray();
+ Assert.That (pages.Length, Is.EqualTo (4));
+ assertPage (pages, 0, "Foo");
+ assertPage (pages, 1, "Baz");
+ assertPage (pages, 2, "Bam");
+ assertPage (pages, 3, "Bar");
+ }
+
+ [Test]
+ public void TemplatePagesRemoved()
+ {
+ var page = CreateMultiPage();
+
+ page.ItemTemplate = new DataTemplate (() => {
+ var p = new ContentPage();
+ p.Content = new Label();
+ p.Content.SetBinding (Label.TextProperty, new Binding ("."));
+ return p;
+ });
+
+ var items = new ObservableCollection<string> { "Foo", "Bar" };
+ page.ItemsSource = items;
+
+ Action<IList<Element>, int, string> assertPage = (ps, index, s) => {
+ Page p = (Page)ps[index];
+ Assert.That (p, Is.InstanceOf<ContentPage>());
+ Assert.That (GetIndex ((T) p), Is.EqualTo (index));
+
+ var cp = (ContentPage) p;
+ Assert.That (cp.Content, Is.InstanceOf<Label>());
+ Assert.That (((Label)cp.Content).Text, Is.EqualTo (s));
+ };
+
+ items.Remove ("Foo");
+
+ var pages = page.Children.ToArray();
+ Assert.That (pages.Length, Is.EqualTo (1));
+ assertPage (pages, 0, "Bar");
+ }
+
+ [Test]
+ public void TemplatePagesRangeRemoved()
+ {
+ var page = CreateMultiPage();
+
+ page.ItemTemplate = new DataTemplate (() => {
+ var p = new ContentPage();
+ p.Content = new Label();
+ p.Content.SetBinding (Label.TextProperty, new Binding ("."));
+ return p;
+ });
+
+ var items = new ObservableList<string> { "Foo", "Bar", "Baz", "Bam", "Who" };
+ page.ItemsSource = items;
+
+ Action<IList<Element>, int, string> assertPage = (ps, index, s) => {
+ Page p = (Page)ps[index];
+ Assert.That (p, Is.InstanceOf<ContentPage>());
+ Assert.That (GetIndex ((T) p), Is.EqualTo (index));
+
+ var cp = (ContentPage) p;
+ Assert.That (cp.Content, Is.InstanceOf<Label>());
+ Assert.That (((Label)cp.Content).Text, Is.EqualTo (s));
+ };
+
+ items.RemoveAt (1, 2);
+
+ var pages = page.Children.ToArray();
+ Assert.That (pages.Length, Is.EqualTo (3));
+ assertPage (pages, 0, "Foo");
+ assertPage (pages, 1, "Bam");
+ assertPage (pages, 2, "Who");
+ }
+
+ [Test]
+ public void TemplatePagesReordered()
+ {
+ var page = CreateMultiPage();
+
+ page.ItemTemplate = new DataTemplate (() => {
+ var p = new ContentPage();
+ p.Content = new Label();
+ p.Content.SetBinding (Label.TextProperty, new Binding ("."));
+ return p;
+ });
+
+ var items = new ObservableCollection<string> { "Foo", "Bar" };
+ page.ItemsSource = items;
+
+ Action<IList<Element>, int, string> assertPage = (ps, index, s) => {
+ Page p = (Page)ps[index];
+ Assert.That (p, Is.InstanceOf<ContentPage>());
+ Assert.That (GetIndex ((T) p), Is.EqualTo (index));
+
+ var cp = (ContentPage) p;
+ Assert.That (cp.Content, Is.InstanceOf<Label>());
+ Assert.That (((Label)cp.Content).Text, Is.EqualTo (s));
+ };
+
+ items.Move (0, 1);
+
+ var pages = page.Children.ToArray();
+ Assert.That (pages.Length, Is.EqualTo (2));
+ assertPage (pages, 0, "Bar");
+ assertPage (pages, 1, "Foo");
+ }
+
+ [Test]
+ public void TemplatePagesRangeReorderedForward()
+ {
+ var page = CreateMultiPage();
+
+ page.ItemTemplate = new DataTemplate (() => {
+ var p = new ContentPage();
+ p.Content = new Label();
+ p.Content.SetBinding (Label.TextProperty, new Binding ("."));
+ return p;
+ });
+
+ var items = new ObservableList<string> { "Foo", "Bar", "Baz", "Bam", "Who", "Where" };
+ page.ItemsSource = items;
+
+ Action<IList<Element>, int, string> assertPage = (ps, index, s) => {
+ Page p = (Page)ps[index];
+ Assert.That (p, Is.InstanceOf<ContentPage>());
+ Assert.That (GetIndex ((T) p), Is.EqualTo (index));
+
+ var cp = (ContentPage) p;
+ Assert.That (cp.Content, Is.InstanceOf<Label>());
+ Assert.That (((Label)cp.Content).Text, Is.EqualTo (s));
+ };
+
+ items.Move (1, 4, 2);
+
+ var pages = page.Children.ToArray();
+ Assert.That (pages.Length, Is.EqualTo (6));
+ assertPage (pages, 0, "Foo");
+ assertPage (pages, 1, "Bam");
+ assertPage (pages, 2, "Who");
+ assertPage (pages, 3, "Bar");
+ assertPage (pages, 4, "Baz");
+ assertPage (pages, 5, "Where");
+ }
+
+ [Test]
+ public void TemplatePagesRangeReorderedBackward()
+ {
+ var page = CreateMultiPage();
+
+ page.ItemTemplate = new DataTemplate (() => {
+ var p = new ContentPage();
+ p.Content = new Label();
+ p.Content.SetBinding (Label.TextProperty, new Binding ("."));
+ return p;
+ });
+
+ var items = new ObservableList<string> { "Foo", "Bar", "Baz", "Bam", "Who", "Where", "When" };
+ page.ItemsSource = items;
+
+ Action<IList<Element>, int, string> assertPage = (ps, index, s) => {
+ Page p = (Page)ps[index];
+ Assert.That (p, Is.InstanceOf<ContentPage>());
+ Assert.That (GetIndex ((T) p), Is.EqualTo (index));
+
+ var cp = (ContentPage) p;
+ Assert.That (cp.Content, Is.InstanceOf<Label>());
+ Assert.That (((Label)cp.Content).Text, Is.EqualTo (s));
+ };
+
+ items.Move (4, 1, 2);
+
+ var pages = page.Children.ToArray();
+ Assert.That (pages.Length, Is.EqualTo (7));
+ assertPage (pages, 0, "Foo");
+ assertPage (pages, 1, "Who");
+ assertPage (pages, 2, "Where");
+ assertPage (pages, 3, "Bar");
+ assertPage (pages, 4, "Baz");
+ assertPage (pages, 5, "Bam");
+ assertPage (pages, 6, "When");
+ }
+
+ [Test]
+ public void TemplatePagesReplaced()
+ {
+ var page = CreateMultiPage();
+
+ page.ItemTemplate = new DataTemplate (() => {
+ var p = new ContentPage();
+ p.Content = new Label();
+ p.Content.SetBinding (Label.TextProperty, new Binding ("."));
+ return p;
+ });
+
+ var items = new ObservableCollection<string> { "Foo", "Bar" };
+ page.ItemsSource = items;
+
+ Action<IList<Element>, int, string> assertPage = (ps, index, s) => {
+ Page p = (Page)ps[index];
+ Assert.That (p, Is.InstanceOf<ContentPage>());
+ Assert.That (GetIndex ((T) p), Is.EqualTo (index));
+
+ var cp = (ContentPage) p;
+ Assert.That (cp.Content, Is.InstanceOf<Label>());
+ Assert.That (((Label)cp.Content).Text, Is.EqualTo (s));
+ };
+
+ items[0] = "Baz";
+
+ var pages = page.Children.ToArray();
+ Assert.That (pages.Length, Is.EqualTo (2));
+ assertPage (pages, 0, "Baz");
+ assertPage (pages, 1, "Bar");
+ }
+
+ [Test]
+ public void TemplatedPagesSourceReplaced()
+ {
+ var page = CreateMultiPage();
+
+ page.ItemTemplate = new DataTemplate (() => {
+ var p = new ContentPage();
+ p.Content = new Label();
+ p.Content.SetBinding (Label.TextProperty, new Binding ("."));
+ return p;
+ });
+
+ page.ItemsSource = new ObservableCollection<string> { "Foo", "Bar" };
+
+ Action<Page, string> assertPage = (p, s) => {
+ Assert.That (p, Is.InstanceOf<ContentPage>());
+
+ var cp = (ContentPage) p;
+ Assert.That (cp.Content, Is.InstanceOf<Label>());
+ Assert.That (((Label)cp.Content).Text, Is.EqualTo (s));
+ };
+
+ page.ItemsSource = new ObservableCollection<string> { "Baz", "Bar" };
+
+ var pages = page.Children.ToArray();
+ Assert.That (pages.Length, Is.EqualTo (2));
+ assertPage ((Page)pages[0], "Baz");
+ assertPage ((Page)pages[1], "Bar");
+ }
+
+ [Test]
+ [Description ("If you have a templated set of items, setting CurrentPage (usually from renderers) should update SelectedItem properly")]
+ public void SettingCurrentPageWithTemplatesUpdatesSelectedItem()
+ {
+ var page = CreateMultiPage();
+
+ var items = new[] { "Foo", "Bar" };
+ page.ItemsSource = items;
+
+ // If these aren't correct, the rest of the test is invalid
+ Assert.That (page.CurrentPage, Is.SameAs (page.Children[0]));
+ Assert.That (page.SelectedItem, Is.SameAs (items[0]));
+
+ page.CurrentPage = (T)page.Children[1];
+
+ Assert.That (page.SelectedItem, Is.SameAs (items[1]));
+ }
+
+ [Test]
+ public void PagesChangedOnItemsSourceChange()
+ {
+ var page = CreateMultiPage();
+
+ page.ItemsSource = new[] { "Baz", "Bam" };
+
+ int fail = 0;
+ int reset = 0;
+ page.PagesChanged += (sender, args) => {
+ if (args.Action == NotifyCollectionChangedAction.Reset)
+ reset++;
+ else
+ fail++;
+ };
+
+ page.ItemsSource = new[] { "Foo", "Bar" };
+
+ Assert.That (reset, Is.EqualTo (1), "PagesChanged wasn't raised or was raised too many times for Reset");
+ Assert.That (fail, Is.EqualTo (0), "PagesChanged was raised with an unexpected action");
+ }
+
+ [Test]
+ public void PagesChangedOnTemplateChange()
+ {
+ var page = CreateMultiPage();
+
+ page.ItemsSource = new[] { "Foo", "Bar" };
+
+ int fail = 0;
+ int reset = 0;
+ page.PagesChanged += (sender, args) => {
+ if (args.Action == NotifyCollectionChangedAction.Reset)
+ reset++;
+ else
+ fail++;
+ };
+
+ page.ItemTemplate = new DataTemplate (() => new ContentPage {
+ Content = new Label { Text = "Content" }
+ });
+
+ Assert.That (reset, Is.EqualTo (1), "PagesChanged wasn't raised or was raised too many times for Reset");
+ Assert.That (fail, Is.EqualTo (0), "PagesChanged was raised with an unexpected action");
+ }
+
+ [Test]
+ public void SelectedItemSetBeforeTemplate()
+ {
+ var page = CreateMultiPage();
+
+ string[] items = new[] { "foo", "bar" };
+ page.ItemsSource = items;
+ page.SelectedItem = items[1];
+
+ var template = new DataTemplate (typeof (ContentPage));
+ template.SetBinding (ContentPage.TitleProperty, ".");
+ page.ItemTemplate = template;
+
+ Assert.That (page.SelectedItem, Is.SameAs (items[1]));
+ }
+
+ [Test]
+ public void CurrentPageUpdatedWithTemplate()
+ {
+ var page = CreateMultiPage();
+ string[] items = new[] { "foo", "bar" };
+ page.ItemsSource = items;
+
+ var untemplated = page.CurrentPage;
+
+ bool raised = false;
+ page.PropertyChanged += (sender, e) => {
+ if (e.PropertyName == "CurrentPage")
+ raised = true;
+ };
+
+ var template = new DataTemplate(() => {
+ var p = new ContentPage { Content = new Label() };
+ p.Content.SetBinding (Label.TextProperty, ".");
+ return p;
+ });
+
+ page.ItemTemplate = template;
+
+ Assert.That (raised, Is.True, "CurrentPage did not change with the template");
+ Assert.That (page.CurrentPage, Is.Not.SameAs (untemplated));
+ }
+
+ [Test]
+ public void CurrentPageChanged()
+ {
+ var page = CreateMultiPage();
+ page.Children.Add (CreateContainedPage());
+ page.Children.Add (CreateContainedPage());
+
+ bool raised = false;
+ page.CurrentPageChanged += (sender, e) => {
+ raised = true;
+ };
+
+ page.CurrentPage = page.Children[0];
+
+ Assert.That (raised, Is.False);
+
+ page.CurrentPage = page.Children[1];
+
+ Assert.That (raised, Is.True);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/MultiTriggerTests.cs b/Xamarin.Forms.Core.UnitTests/MultiTriggerTests.cs
new file mode 100644
index 00000000..df253e76
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/MultiTriggerTests.cs
@@ -0,0 +1,134 @@
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class MultiTriggerTests : BaseTestFixture
+ {
+ class MockElement : VisualElement
+ {
+ }
+
+ [Test]
+ public void SettersAppliedOnAttachIfConditionIsTrue ()
+ {
+ var conditionbp = BindableProperty.Create ("foo", typeof(string), typeof(BindableObject), null);
+ var setterbp = BindableProperty.Create ("bar", typeof(string), typeof(BindableObject), null);
+ var element = new MockElement ();
+ var multiTrigger = new MultiTrigger (typeof(VisualElement)) {
+ Conditions = {
+ new PropertyCondition { Property = conditionbp, Value = "foobar" },
+ new BindingCondition { Binding = new Binding ("baz"), Value = "foobaz" },
+ },
+ Setters = {
+ new Setter { Property = setterbp, Value = "qux" },
+ }
+ };
+
+ element.SetValue (setterbp, "default");
+ element.SetValue (conditionbp, "foobar");
+ element.BindingContext = new {baz = "foobaz"};
+ Assert.AreEqual ("default", element.GetValue (setterbp));
+ element.Triggers.Add (multiTrigger);
+ Assert.AreEqual ("qux", element.GetValue (setterbp));
+ }
+
+ [Test]
+ public void SettersNotAppliedOnAttachIfOneConditionIsFalse ()
+ {
+ var conditionbp = BindableProperty.Create ("foo", typeof(string), typeof(BindableObject), null);
+ var setterbp = BindableProperty.Create ("bar", typeof(string), typeof(BindableObject), null);
+ var element = new MockElement ();
+ var multiTrigger = new MultiTrigger (typeof(VisualElement)) {
+ Conditions = {
+ new PropertyCondition { Property = conditionbp, Value = "foobar" },
+ new BindingCondition { Binding = new Binding ("baz"), Value = "foobaz" },
+ },
+ Setters = {
+ new Setter { Property = setterbp, Value = "qux" },
+ }
+ };
+
+ element.SetValue (setterbp, "default");
+ element.SetValue (conditionbp, "foobar");
+ element.BindingContext = new {baz = "foobazXX"};
+ Assert.AreEqual ("default", element.GetValue (setterbp));
+ element.Triggers.Add (multiTrigger);
+ Assert.AreEqual ("default", element.GetValue (setterbp));
+ }
+
+ [Test]
+ public void SettersUnappliedOnDetach ()
+ {
+ var conditionbp = BindableProperty.Create ("foo", typeof(string), typeof(BindableObject), null);
+ var setterbp = BindableProperty.Create ("bar", typeof(string), typeof(BindableObject), null);
+ var element = new MockElement ();
+ var multiTrigger = new MultiTrigger (typeof(VisualElement)) {
+ Conditions = {
+ new PropertyCondition { Property = conditionbp, Value = "foobar" },
+ new BindingCondition { Binding = new Binding ("baz"), Value = "foobaz" },
+ },
+ Setters = {
+ new Setter { Property = setterbp, Value = "qux" },
+ }
+ };
+
+ element.SetValue (setterbp, "default");
+ element.BindingContext = new {baz = "" };
+ element.Triggers.Add (multiTrigger);
+ Assert.AreEqual ("default", element.GetValue (setterbp)); //both conditions false
+
+ element.SetValue (conditionbp, "foobar");
+ Assert.AreEqual ("default", element.GetValue (setterbp)); //one condition false
+
+ element.BindingContext = new {baz = "foobaz"};
+ Assert.AreEqual ("qux", element.GetValue (setterbp)); //both condition true
+ element.Triggers.Remove (multiTrigger);
+ Assert.AreEqual ("default", element.GetValue (setterbp));
+ }
+
+ [Test]
+ public void SettersAppliedAndUnappliedOnConditionsChange ()
+ {
+ var conditionbp = BindableProperty.Create ("foo", typeof(string), typeof(BindableObject), null);
+ var setterbp = BindableProperty.Create ("bar", typeof(string), typeof(BindableObject), null);
+ var element = new MockElement ();
+ var multiTrigger = new MultiTrigger (typeof(VisualElement)) {
+ Conditions = {
+ new PropertyCondition { Property = conditionbp, Value = "foobar" },
+ new BindingCondition { Binding = new Binding ("baz"), Value = "foobaz" },
+ },
+ Setters = {
+ new Setter { Property = setterbp, Value = "qux" },
+ }
+ };
+
+ element.SetValue (setterbp, "default");
+ element.BindingContext = new {baz = "" };
+ element.Triggers.Add (multiTrigger);
+ Assert.AreEqual ("default", element.GetValue (setterbp)); //both conditions false
+
+ element.SetValue (conditionbp, "foobar");
+ Assert.AreEqual ("default", element.GetValue (setterbp)); //one condition false
+
+ element.BindingContext = new {baz = "foobaz"};
+ Assert.AreEqual ("qux", element.GetValue (setterbp)); //both condition true
+
+ element.BindingContext = new {baz = ""};
+ Assert.AreEqual ("default", element.GetValue (setterbp)); //one condition false
+
+ element.BindingContext = new {baz = "foobaz"};
+ Assert.AreEqual ("qux", element.GetValue (setterbp)); //both condition true
+
+ element.SetValue (conditionbp, "");
+ Assert.AreEqual ("default", element.GetValue (setterbp)); //one condition false
+
+ element.SetValue (conditionbp, "foobar");
+ Assert.AreEqual ("qux", element.GetValue (setterbp)); //both condition true
+
+ element.SetValue (conditionbp, "");
+ element.BindingContext = new {baz = "foobaz"};
+ Assert.AreEqual ("default", element.GetValue (setterbp)); //both conditions false
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/NavigationMenuUnitTests.cs b/Xamarin.Forms.Core.UnitTests/NavigationMenuUnitTests.cs
new file mode 100644
index 00000000..b91f0229
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/NavigationMenuUnitTests.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class NavigationMenuUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestTargets ()
+ {
+ var menu = new NavigationMenu ();
+
+ Assert.That (menu.Targets, Is.Empty);
+
+ bool signaled = false;
+ menu.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "Targets")
+ signaled = true;
+ };
+
+ var newArray = new[] {
+ new ContentPage { Content = new View (), Icon = "img1.jpg" },
+ new ContentPage { Content = new View (), Icon = "img2.jpg" }
+ };
+ menu.Targets = newArray;
+
+ Assert.AreEqual (newArray, menu.Targets);
+ Assert.True (signaled);
+ }
+
+ [Test]
+ public void TestTargetsDoubleSet ()
+ {
+ var menu = new NavigationMenu ();
+
+ bool signaled = false;
+ menu.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "Targets")
+ signaled = true;
+ };
+
+ menu.Targets = menu.Targets;
+
+ Assert.False (signaled);
+ }
+
+ [Test]
+ public void TestAdd ()
+ {
+ var menu = new NavigationMenu ();
+
+ bool signaled = false;
+ menu.PropertyChanged += (sender, args) => {
+ switch (args.PropertyName) {
+ case "Targets":
+ signaled = true;
+ break;
+ }
+ };
+
+ var child = new ContentPage {
+ Content = new View (),
+ Icon = "img.jpg"
+ };
+ menu.Add (child);
+ Assert.True (menu.Targets.Contains (child));
+ Assert.True (signaled);
+ }
+
+ [Test]
+ public void IconNotSet ()
+ {
+ var menu = new NavigationMenu ();
+ var childWithoutIcon = new ContentPage { Title = "I have no image" };
+
+ var ex = Assert.Throws<Exception> (() => menu.Add (childWithoutIcon));
+ Assert.That (ex.Message, Is.EqualTo ("Icon must be set for each page before adding them to a Navigation Menu"));
+ }
+
+ [Test]
+ public void TestDoubleAdd ()
+ {
+ var menu = new NavigationMenu ();
+
+ var child = new ContentPage {
+ Icon = "img.img",
+ Content = new View ()
+ };
+
+ menu.Add (child);
+
+ bool signaled = false;
+ menu.PropertyChanged += (sender, args) => {
+ switch (args.PropertyName) {
+ case "Targets":
+ signaled = true;
+ break;
+ }
+ };
+
+ menu.Add (child);
+
+ Assert.True (menu.Targets.Contains (child));
+ Assert.False (signaled);
+ }
+
+ [Test]
+ public void TestRemove ()
+ {
+ var menu = new NavigationMenu ();
+
+ var child = new ContentPage {
+ Icon = "img.img",
+ Content = new View ()
+ };
+ menu.Add (child);
+
+ bool signaled = false;
+ menu.PropertyChanged += (sender, args) => {
+ switch (args.PropertyName) {
+ case "Targets":
+ signaled = true;
+ break;
+ }
+ };
+
+ menu.Remove (child);
+
+ Assert.False (menu.Targets.Contains (child));
+ Assert.True (signaled);
+ }
+
+ [Test]
+ public void TestDoubleRemove ()
+ {
+ var menu = new NavigationMenu ();
+
+ var child = new ContentPage {
+ Icon = "jpg.jpg",
+ Content = new View ()
+ };
+ menu.Add (child);
+ menu.Remove (child);
+
+ bool signaled = false;
+ menu.PropertyChanged += (sender, args) => {
+ switch (args.PropertyName) {
+ case "Targets":
+ signaled = true;
+ break;
+ }
+ };
+
+ menu.Remove (child);
+
+ Assert.False (menu.Targets.Contains (child));
+ Assert.False (signaled);
+ }
+
+ [Test]
+ public async Task TestSendTargetSelected ()
+ {
+ var menu = new NavigationMenu ();
+ var navForm = new NavigationPage ();
+
+ await navForm.PushAsync (new ContentPage {
+ Title = "Menu",
+ Content = menu
+ });
+
+ bool pushed = false;
+ navForm.Pushed += (sender, arg) => pushed = true;
+
+ var child = new ContentPage {
+ Icon = "img.jpg",
+ Content = new View ()
+ };
+ menu.Add (child);
+
+ menu.SendTargetSelected (child);
+
+ Assert.True (pushed);
+ Assert.AreEqual (child, navForm.CurrentPage);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/NavigationModelTests.cs b/Xamarin.Forms.Core.UnitTests/NavigationModelTests.cs
new file mode 100644
index 00000000..ec3aaf5f
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/NavigationModelTests.cs
@@ -0,0 +1,304 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class NavigationModelTests : BaseTestFixture
+ {
+ [Test]
+ public void CurrentNullWhenEmpty ()
+ {
+ var navModel = new NavigationModel ();
+ Assert.Null (navModel.CurrentPage);
+ }
+
+ [Test]
+ public void CurrentGivesLastViewWithoutModal ()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+ var page2 = new ContentPage ();
+
+ navModel.Push (page1, null);
+ navModel.Push (page2, page1);
+
+ Assert.AreEqual (page2, navModel.CurrentPage);
+ }
+
+ [Test]
+ public void CurrentGivesLastViewWithModal()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+ var page2 = new ContentPage ();
+
+ var modal1 = new ContentPage ();
+ var modal2 = new ContentPage ();
+
+ navModel.Push (page1, null);
+ navModel.Push (page2, page1);
+
+ navModel.PushModal (modal1);
+ navModel.Push (modal2, modal1);
+
+ Assert.AreEqual (modal2, navModel.CurrentPage);
+ }
+
+ [Test]
+ public void Roots ()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+ var page2 = new ContentPage ();
+
+ var modal1 = new ContentPage ();
+ var modal2 = new ContentPage ();
+
+ navModel.Push (page1, null);
+ navModel.Push (page2, page1);
+
+ navModel.PushModal (modal1);
+ navModel.Push (modal2, modal1);
+
+ Assert.True (navModel.Roots.SequenceEqual (new[] {page1, modal1}));
+ }
+
+ [Test]
+ public void PushFirstItem ()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+ navModel.Push (page1, null);
+
+ Assert.AreEqual (page1, navModel.CurrentPage);
+ Assert.AreEqual (page1, navModel.Roots.First ());
+ }
+
+ [Test]
+ public void ThrowsWhenPushingWithoutAncestor ()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+ var page2 = new ContentPage ();
+
+ navModel.Push (page1, null);
+ Assert.Throws<InvalidNavigationException> (() => navModel.Push (page2, null));
+ }
+
+ [Test]
+ public void PushFromNonRootAncestor ()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+ var page2 = new ContentPage ();
+ var page3 = new ContentPage ();
+
+ page2.Parent = page1;
+ page3.Parent = page2;
+
+ navModel.Push (page1, null);
+ navModel.Push (page2, page1);
+ navModel.Push (page3, page2);
+
+ Assert.AreEqual (page3, navModel.CurrentPage);
+ }
+
+ [Test]
+ public void ThrowsWhenPushFromInvalidAncestor ()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+ var page2 = new ContentPage ();
+
+ Assert.Throws<InvalidNavigationException> (() => navModel.Push (page2, page1));
+ }
+
+ [Test]
+ public void Pop ()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+ var page2 = new ContentPage ();
+
+ navModel.Push (page1, null);
+ navModel.Push (page2, page1);
+
+ navModel.Pop (page1);
+
+ Assert.AreEqual (page1, navModel.CurrentPage);
+ }
+
+ [Test]
+ public void ThrowsPoppingRootItem ()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+
+ navModel.Push (page1, null);
+
+ Assert.Throws<InvalidNavigationException> (() => navModel.Pop (page1));
+ }
+
+ [Test]
+ public void ThrowsPoppingRootOfModal ()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+ var page2 = new ContentPage ();
+
+ var modal1 = new ContentPage ();
+
+ navModel.Push (page1, null);
+ navModel.Push (page2, page1);
+
+ navModel.PushModal (modal1);
+ Assert.Throws<InvalidNavigationException> (() => navModel.Pop (modal1));
+ }
+
+ [Test]
+ public void ThrowsPoppingWithInvalidAncestor ()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+
+ navModel.Push (page1, null);
+
+ Assert.Throws<InvalidNavigationException> (() => navModel.Pop (new ContentPage ()));
+ }
+
+ [Test]
+ public void PopToRoot ()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+ var page2 = new ContentPage ();
+ var page3 = new ContentPage ();
+
+ page2.Parent = page1;
+ page3.Parent = page2;
+
+ navModel.Push (page1, null);
+ navModel.Push (page2, page1);
+ navModel.Push (page3, page2);
+
+ navModel.PopToRoot (page2);
+
+ Assert.AreEqual (page1, navModel.CurrentPage);
+ }
+
+ [Test]
+ public void ThrowsWhenPopToRootOnRoot ()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+
+ navModel.Push (page1, null);
+ Assert.Throws<InvalidNavigationException> (() => navModel.PopToRoot (page1));
+ }
+
+ [Test]
+ public void ThrowsWhenPopToRootWithInvalidAncestor()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+ var page2 = new ContentPage ();
+
+ navModel.Push (page1, null);
+ navModel.Push (page2, page1);
+
+ Assert.Throws<InvalidNavigationException> (() => navModel.PopToRoot (new ContentPage ()));
+ }
+
+ [Test]
+ public void PopModal ()
+ {
+ var navModel = new NavigationModel ();
+
+ var child1 = new ContentPage ();
+ var modal1 = new ContentPage ();
+
+ navModel.Push (child1, null);
+ navModel.PushModal (modal1);
+
+ navModel.PopModal ();
+
+ Assert.AreEqual (child1, navModel.CurrentPage);
+ Assert.AreEqual (1, navModel.Roots.Count ());
+ }
+
+ [Test]
+ public void ReturnsCorrectModal ()
+ {
+ var navModel = new NavigationModel ();
+
+ var child1 = new ContentPage ();
+ var modal1 = new ContentPage ();
+ var modal2 = new ContentPage ();
+
+ navModel.Push (child1, null);
+ navModel.PushModal (modal1);
+ navModel.PushModal (modal2);
+
+ Assert.AreEqual (modal2, navModel.PopModal ());
+ }
+
+ [Test]
+ public void PopTopPageWithoutModals ()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+ var page2 = new ContentPage ();
+
+ navModel.Push (page1, null);
+ navModel.Push (page2, page1);
+
+ Assert.AreEqual (page2, navModel.PopTopPage ());
+ }
+
+ [Test]
+ public void PopTopPageWithSinglePage ()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+
+ navModel.Push (page1, null);
+
+ Assert.Null (navModel.PopTopPage ());
+ }
+
+ [Test]
+ public void PopTopPageWithModal ()
+ {
+ var navModel = new NavigationModel ();
+
+ var page1 = new ContentPage ();
+ var modal1 = new ContentPage ();
+
+ navModel.Push (page1, null);
+ navModel.PushModal (modal1);
+
+ Assert.AreEqual (modal1, navModel.PopTopPage ());
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/NavigationProxyTests.cs b/Xamarin.Forms.Core.UnitTests/NavigationProxyTests.cs
new file mode 100644
index 00000000..459f4cf4
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/NavigationProxyTests.cs
@@ -0,0 +1,188 @@
+using System.Collections.Generic;
+using System.Linq;
+using NUnit.Framework;
+using System.Threading.Tasks;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class NavigationProxyTests : BaseTestFixture
+ {
+ class NavigationTest : INavigation
+ {
+ public Page LastPushed { get; set; }
+ public Page LastPushedModal { get; set; }
+
+ public bool Popped { get; set; }
+ public bool PoppedModal { get; set; }
+
+ public Task PushAsync (Page root)
+ {
+ return PushAsync (root, true);
+ }
+
+ public Task<Page> PopAsync ()
+ {
+ return PopAsync (true);
+ }
+
+ public Task PopToRootAsync ()
+ {
+ return PopToRootAsync (true);
+ }
+
+ public Task PushModalAsync (Page root)
+ {
+ return PushModalAsync (root, true);
+ }
+
+ public Task<Page> PopModalAsync ()
+ {
+ return PopModalAsync (true);
+ }
+
+ public Task PushAsync (Page root, bool animated)
+ {
+ LastPushed = root;
+ return Task.FromResult (root);
+ }
+
+ public Task<Page> PopAsync (bool animated)
+ {
+ Popped = true;
+ return Task.FromResult (LastPushed);
+ }
+
+ public Task PopToRootAsync (bool animated)
+ {
+ return Task.FromResult<Page> (null);
+ }
+
+ public Task PushModalAsync (Page root, bool animated)
+ {
+ LastPushedModal = root;
+ return Task.FromResult<object> (null);
+ }
+
+ public Task<Page> PopModalAsync (bool animated)
+ {
+ PoppedModal = true;
+ return Task.FromResult<Page> (null);
+ }
+
+ public void RemovePage (Page page)
+ {
+ }
+
+ public void InsertPageBefore (Page page, Page before)
+ {
+ }
+
+ public System.Collections.Generic.IReadOnlyList<Page> NavigationStack
+ {
+ get { return new List<Page> (); }
+ }
+
+ public System.Collections.Generic.IReadOnlyList<Page> ModalStack
+ {
+ get { return new List<Page> (); }
+ }
+ }
+
+ [Test]
+ public void Constructor ()
+ {
+ var proxy = new NavigationProxy ();
+
+ Assert.Null (proxy.Inner);
+ }
+
+ [Test]
+ public async Task PushesIntoNextInner ()
+ {
+ var page = new ContentPage ();
+ var navProxy = new NavigationProxy ();
+
+ await navProxy.PushAsync (page);
+
+ var navTest = new NavigationTest ();
+ navProxy.Inner = navTest;
+
+ Assert.AreEqual (page, navTest.LastPushed);
+ }
+
+ [Test]
+ public async Task PushesModalIntoNextInner ()
+ {
+ var page = new ContentPage ();
+ var navProxy = new NavigationProxy ();
+
+ await navProxy.PushModalAsync (page);
+
+ var navTest = new NavigationTest ();
+ navProxy.Inner = navTest;
+
+ Assert.AreEqual (page, navTest.LastPushedModal);
+ }
+
+ [Test]
+ public async Task TestPushWithInner ()
+ {
+ var proxy = new NavigationProxy ();
+ var inner = new NavigationTest ();
+
+ proxy.Inner = inner;
+
+ var child = new ContentPage {Content = new View ()};
+ await proxy.PushAsync (child);
+
+ Assert.AreEqual (child, inner.LastPushed);
+ }
+
+ [Test]
+ public async Task TestPushModalWithInner ()
+ {
+ var proxy = new NavigationProxy ();
+ var inner = new NavigationTest ();
+
+ proxy.Inner = inner;
+
+ var child = new ContentPage {Content = new View ()};
+ await proxy.PushModalAsync (child);
+
+ Assert.AreEqual (child, inner.LastPushedModal);
+ }
+
+ [Test]
+ public async Task TestPopWithInner ()
+ {
+ var proxy = new NavigationProxy ();
+ var inner = new NavigationTest ();
+
+ proxy.Inner = inner;
+
+ var child = new ContentPage {Content = new View ()};
+ await proxy.PushAsync (child);
+
+ var result = await proxy.PopAsync ();
+ Assert.AreEqual (child, result);
+ Assert.True (inner.Popped, "Pop was never called on the inner proxy item");
+ }
+
+ [Test]
+ public async Task TestPopModalWithInner ()
+ {
+ var proxy = new NavigationProxy ();
+ var inner = new NavigationTest ();
+
+ proxy.Inner = inner;
+
+ var child = new ContentPage {Content = new View ()};
+ await proxy.PushModalAsync (child);
+
+ await proxy.PopModalAsync ();
+ Assert.True (inner.PoppedModal, "Pop was never called on the inner proxy item");
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/NavigationUnitTest.cs b/Xamarin.Forms.Core.UnitTests/NavigationUnitTest.cs
new file mode 100644
index 00000000..1d3d4bd2
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/NavigationUnitTest.cs
@@ -0,0 +1,393 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class NavigationUnitTest : BaseTestFixture
+ {
+ [Test]
+ public async Task TestNavigationImplPush ()
+ {
+ NavigationPage nav = new NavigationPage ();
+
+ Assert.IsNull (nav.CurrentPage);
+
+ Label child = new Label {Text = "Label"};
+ Page childRoot = new ContentPage {Content = child};
+
+ await nav.Navigation.PushAsync (childRoot);
+
+ Assert.AreSame (childRoot, nav.CurrentPage);
+ }
+
+ [Test]
+ public async Task TestNavigationImplPop ()
+ {
+ NavigationPage nav = new NavigationPage ();
+
+ Label child = new Label ();
+ Page childRoot = new ContentPage {Content = child};
+
+ Label child2 = new Label ();
+ Page childRoot2 = new ContentPage {Content = child2};
+
+ await nav.Navigation.PushAsync (childRoot);
+ await nav.Navigation.PushAsync (childRoot2);
+
+ bool fired = false;
+ nav.Popped += (sender, e) => fired = true;
+ var popped = await nav.Navigation.PopAsync ();
+
+ Assert.True (fired);
+ Assert.AreSame (childRoot, nav.CurrentPage);
+ Assert.AreEqual (childRoot2, popped);
+
+ await nav.PopAsync ();
+ var last = await nav.Navigation.PopAsync ();
+
+ Assert.IsNull (last);
+ }
+
+ [Test]
+ public async Task TestPushRoot ()
+ {
+ NavigationPage nav = new NavigationPage ();
+
+ Assert.IsNull (nav.CurrentPage);
+
+ Label child = new Label {Text = "Label"};
+ Page childRoot = new ContentPage {Content = child};
+
+ await nav.PushAsync (childRoot);
+
+ Assert.AreSame (childRoot, nav.CurrentPage);
+ }
+
+ [Test]
+ public async Task TestPushEvent ()
+ {
+ NavigationPage nav = new NavigationPage ();
+
+ Label child = new Label ();
+ Page childRoot = new ContentPage {Content = child};
+
+ bool fired = false;
+ nav.Pushed += (sender, e) => fired = true;
+
+ await nav.PushAsync (childRoot);
+
+ Assert.True (fired);
+ }
+
+ [Test]
+ public async Task TestDoublePush ()
+ {
+ NavigationPage nav = new NavigationPage ();
+
+ Label child = new Label ();
+ Page childRoot = new ContentPage {Content = child};
+
+ await nav.PushAsync (childRoot);
+
+ bool fired = false;
+ nav.Pushed += (sender, e) => fired = true;
+
+ await nav.PushAsync (childRoot);
+
+ Assert.False (fired);
+ Assert.AreEqual (childRoot, nav.CurrentPage);
+ }
+
+ [Test]
+ public async Task TestPop ()
+ {
+ NavigationPage nav = new NavigationPage ();
+
+ Label child = new Label ();
+ Page childRoot = new ContentPage {Content = child};
+
+ Label child2 = new Label ();
+ Page childRoot2 = new ContentPage {Content = child2};
+
+ await nav.PushAsync (childRoot);
+ await nav.PushAsync (childRoot2);
+
+ bool fired = false;
+ nav.Popped += (sender, e) => fired = true;
+ var popped = await nav.PopAsync ();
+
+ Assert.True (fired);
+ Assert.AreSame (childRoot, nav.CurrentPage);
+ Assert.AreEqual (childRoot2, popped);
+
+ await nav.PopAsync ();
+ var last = await nav.PopAsync ();
+
+ Assert.IsNull (last);
+ }
+
+ [Test]
+ public void TestTint ()
+ {
+ var nav = new NavigationPage ();
+
+ Assert.AreEqual (Color.Default, nav.Tint);
+
+ bool signaled = false;
+ nav.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "Tint")
+ signaled = true;
+ };
+
+ nav.Tint = new Color (1, 0, 0);
+
+ Assert.AreEqual (new Color (1, 0, 0), nav.Tint);
+ Assert.True (signaled);
+ }
+
+ [Test]
+ public void TestTintDoubleSet ()
+ {
+ var nav = new NavigationPage ();
+
+ bool signaled = false;
+ nav.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "Tint")
+ signaled = true;
+ };
+
+ nav.Tint = nav.Tint;
+
+ Assert.False (signaled);
+ }
+
+ [Test]
+ public async Task TestPopToRoot ()
+ {
+ var nav = new NavigationPage ();
+
+ bool signaled = false;
+ nav.PoppedToRoot += (sender, args) => signaled = true;
+
+ var root = new ContentPage {Content = new View ()};
+ var child1 = new ContentPage {Content = new View ()};
+ var child2 = new ContentPage {Content = new View ()};
+
+ await nav.PushAsync (root);
+ await nav.PushAsync (child1);
+ await nav.PushAsync (child2);
+
+ nav.PopToRootAsync ();
+
+ Assert.True (signaled);
+ Assert.AreEqual (root, nav.CurrentPage);
+ }
+
+ [Test]
+ public async Task TestStackCopy ()
+ {
+ var nav = new NavigationPage ();
+
+ bool signaled = false;
+ nav.PoppedToRoot += (sender, args) => signaled = true;
+
+ var root = new ContentPage {Content = new View ()};
+ var child1 = new ContentPage {Content = new View ()};
+ var child2 = new ContentPage {Content = new View ()};
+
+ await nav.PushAsync (root);
+ await nav.PushAsync (child1);
+ await nav.PushAsync (child2);
+
+ var copy = nav.StackCopy;
+
+ Assert.AreEqual (child2, copy.Pop ());
+ Assert.AreEqual (child1, copy.Pop ());
+ Assert.AreEqual (root, copy.Pop ());
+ }
+
+ [Test]
+ public void ConstructWithRoot ()
+ {
+ var root = new ContentPage ();
+ var nav = new NavigationPage (root);
+
+ Assert.AreEqual (root, nav.LogicalChildren[0]);
+ Assert.AreEqual (1, nav.StackDepth);
+ }
+
+ [Test]
+ public async Task NavigationChangedEventArgs ()
+ {
+ var rootPage = new ContentPage { Title = "Root" };
+ var navPage = new NavigationPage (rootPage);
+
+ var rootArg = new Page ();
+
+ navPage.Pushed += (s, e) => {
+ rootArg = e.Page;
+ };
+
+ var pushPage = new ContentPage {
+ Title = "Page 2"
+ };
+
+ await navPage.PushAsync (pushPage);
+
+ Assert.AreEqual (rootArg, pushPage);
+
+ var secondPushPage = new ContentPage {
+ Title = "Page 3"
+ };
+
+ await navPage.PushAsync (secondPushPage);
+
+ Assert.AreEqual (rootArg, secondPushPage);
+ }
+
+ [Test]
+ public async Task CurrentPageChanged()
+ {
+ var root = new ContentPage { Title = "Root" };
+ var navPage = new NavigationPage (root);
+
+ bool changing = false;
+ navPage.PropertyChanging += (object sender, PropertyChangingEventArgs e) => {
+ if (e.PropertyName == NavigationPage.CurrentPageProperty.PropertyName) {
+ Assert.That (navPage.CurrentPage, Is.SameAs (root));
+ changing = true;
+ }
+ };
+
+ var next = new ContentPage { Title = "Next" };
+
+ bool changed = false;
+ navPage.PropertyChanged += (sender, e) => {
+ if (e.PropertyName == NavigationPage.CurrentPageProperty.PropertyName) {
+ Assert.That (navPage.CurrentPage, Is.SameAs (next));
+ changed = true;
+ }
+ };
+
+ await navPage.PushAsync (next);
+
+ Assert.That (changing, Is.True, "PropertyChanging was not raised for 'CurrentPage'");
+ Assert.That (changed, Is.True, "PropertyChanged was not raised for 'CurrentPage'");
+ }
+
+ [Test]
+ public async void HandlesPopToRoot ()
+ {
+ var root = new ContentPage { Title = "Root" };
+ var navPage = new NavigationPage (root);
+
+ await navPage.PushAsync (new ContentPage ());
+ await navPage.PushAsync (new ContentPage ());
+
+ bool popped = false;
+ navPage.PoppedToRoot += (sender, args) => {
+ popped = true;
+ };
+
+ await navPage.Navigation.PopToRootAsync ();
+
+ Assert.True (popped);
+ }
+
+ [Test]
+ public void SendsBackButtonEventToCurrentPage ()
+ {
+ var current = new BackButtonPage ();
+ var navPage = new NavigationPage (current);
+
+ var emitted = false;
+ current.BackPressed += (sender, args) => emitted = true;
+
+ navPage.SendBackButtonPressed ();
+
+ Assert.True (emitted);
+ }
+
+ [Test]
+ public void DoesNotSendBackEventToNonCurrentPage ()
+ {
+ var current = new BackButtonPage ();
+ var navPage = new NavigationPage (current);
+ navPage.PushAsync (new ContentPage ());
+
+ var emitted = false;
+ current.BackPressed += (sender, args) => emitted = true;
+
+ navPage.SendBackButtonPressed ();
+
+ Assert.False (emitted);
+ }
+
+ [Test]
+ public async void NavigatesBackWhenBackButtonPressed ()
+ {
+ var root = new ContentPage { Title = "Root" };
+ var navPage = new NavigationPage (root);
+
+ await navPage.PushAsync (new ContentPage ());
+
+ var result = navPage.SendBackButtonPressed ();
+
+ Assert.AreEqual (root, navPage.CurrentPage);
+ Assert.True (result);
+ }
+
+ [Test]
+ public async void DoesNotNavigatesBackWhenBackButtonPressedIfHandled ()
+ {
+ var root = new BackButtonPage { Title = "Root" };
+ var second = new BackButtonPage () {Handle = true};
+ var navPage = new NavigationPage (root);
+
+ await navPage.PushAsync (second);
+
+ navPage.SendBackButtonPressed ();
+
+ Assert.AreEqual (second, navPage.CurrentPage);
+ }
+
+ [Test]
+ public void DoesNotHandleBackButtonWhenNoNavStack ()
+ {
+ var root = new ContentPage { Title = "Root" };
+ var navPage = new NavigationPage (root);
+
+ var result = navPage.SendBackButtonPressed ();
+ Assert.False (result);
+ }
+
+ [Test (Description = "CurrentPage should not be set to null when you attempt to pop the last page")]
+ [Property ("Bugzilla", 28335)]
+ public async Task CurrentPageNotNullPoppingRoot()
+ {
+ var root = new ContentPage { Title = "Root" };
+ var navPage = new NavigationPage (root);
+ var popped = await navPage.PopAsync ();
+ Assert.That (popped, Is.Null);
+ Assert.That (navPage.CurrentPage, Is.SameAs (root));
+ }
+ }
+
+ internal class BackButtonPage : ContentPage
+ {
+ public event EventHandler BackPressed;
+
+ public bool Handle = false;
+
+ protected override bool OnBackButtonPressed ()
+ {
+ if (BackPressed != null)
+ BackPressed (this, EventArgs.Empty);
+ return Handle;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/NotifiedPropertiesTests.cs b/Xamarin.Forms.Core.UnitTests/NotifiedPropertiesTests.cs
new file mode 100644
index 00000000..344606bf
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/NotifiedPropertiesTests.cs
@@ -0,0 +1,214 @@
+using System;
+using NUnit.Framework;
+using System.ComponentModel;
+using Xamarin.Forms.Maps;
+using System.Windows.Input;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class NotifiedPropertiesTests : BaseTestFixture
+ {
+ public abstract class PropertyTestCase
+ {
+ public string Name { get; set;}
+ public Func<INotifyPropertyChanged,object> PropertyGetter { get; set; }
+ public Action<INotifyPropertyChanged, object> PropertySetter { get; set; }
+ public object ExpectedDefaultValue { get; set; }
+ public object TestValue { get; set; }
+ public abstract INotifyPropertyChanged CreateView ();
+ public virtual string DebugName {
+ get { return Name; }
+ }
+ }
+
+ public class PropertyTestCase<TView, TProperty>:PropertyTestCase where TView : INotifyPropertyChanged
+ {
+ Func<TView> init;
+ Func<TProperty> expectedValueCreator;
+
+ public PropertyTestCase (string name, Func<TView,TProperty> propertyGetter, Action<TView, TProperty> propertySetter, Func<TProperty> expectedDefaultValue, TProperty testValue, Func<TView> init = null)
+ {
+ Name = name;
+ PropertyGetter = v => propertyGetter((TView)v);
+ PropertySetter = (v,o)=> propertySetter ((TView)v, (TProperty)o);
+ expectedValueCreator = expectedDefaultValue;
+ TestValue = testValue;
+ this.init = init;
+ }
+
+ public override INotifyPropertyChanged CreateView ()
+ {
+ ExpectedDefaultValue = expectedValueCreator ();
+ if (init != null)
+ return init ();
+ if (typeof(TView) == typeof(View))
+ return new View ();
+ return (TView)Activator.CreateInstance (typeof(TView), new object[]{ });
+ }
+
+ public override string DebugName {
+ get {
+ return typeof(TView).Name + "." + Name;
+ }
+ }
+ }
+
+ static PropertyTestCase[] Properties = {
+ new PropertyTestCase<View, ResourceDictionary> ("Resources", v => v.Resources, (v, o) => v.Resources = o, () => null, new ResourceDictionary ()),
+ new PropertyTestCase<View, bool> ("InputTransparent", v => v.InputTransparent, (v, o) => v.InputTransparent = o, () => false, true),
+ new PropertyTestCase<View, double> ("Scale", v => v.Scale, (v, o) => v.Scale = o, () => 1d, 2d),
+ new PropertyTestCase<View, double> ("Rotation", v => v.Rotation, (v, o) => v.Rotation = o, () => 0d, 90d),
+ new PropertyTestCase<View, double> ("RotationX", v => v.RotationX, (v, o) => v.RotationX = o, () => 0d, 90d),
+ new PropertyTestCase<View, double> ("RotationY", v => v.RotationY, (v, o) => v.RotationY = o, () => 0d, 90d),
+ new PropertyTestCase<View, double> ("AnchorX", v => v.AnchorX, (v, o) => v.AnchorX = o, () => 0.5d, 0d),
+ new PropertyTestCase<View, double> ("AnchorY", v => v.AnchorY, (v, o) => v.AnchorY = o, () => 0.5d, 0d),
+ new PropertyTestCase<View, double> ("TranslationX", v => v.TranslationX, (v, o) => v.TranslationX = o, () => 0d, 20d),
+ new PropertyTestCase<View, double> ("TranslationY", v => v.TranslationY, (v, o) => v.TranslationY = o, () => 0d, 20d),
+ new PropertyTestCase<View, double> ("Opacity", v => v.Opacity, (v, o) => v.Opacity = o, () => 1d, 0.5d),
+ new PropertyTestCase<View, bool> ("IsEnabled", v => v.IsEnabled, (v, o) => v.IsEnabled = o, () => true, false),
+ new PropertyTestCase<View, bool> ("IsVisible", v => v.IsVisible, (v, o) => v.IsVisible = o, () => true, false),
+ new PropertyTestCase<View, string> ("ClassId", v => v.ClassId, (v, o) => v.ClassId = o, () => null, "Foo"),
+ new PropertyTestCase<ActivityIndicator, bool> ("IsRunning", v => v.IsRunning, (v, o) => v.IsRunning = o, () => false, true),
+ new PropertyTestCase<ActivityIndicator, Color> ("Color", v => v.Color, (v, o) => v.Color = o, () => Color.Default, new Color (0, 1, 0)),
+ new PropertyTestCase<Button, string> ("Text", v => v.Text, (v, o) => v.Text = o, () => null, "Foo"),
+ new PropertyTestCase<Button, Color> ("TextColor", v => v.TextColor, (v, o) => v.TextColor = o, () => Color.Default, new Color (0, 1, 0)),
+ new PropertyTestCase<Button, Font> ("Font", v => v.Font, (v, o) => v.Font = o, () => default (Font), Font.SystemFontOfSize (20)),
+ new PropertyTestCase<Button, double> ("BorderWidth", v => v.BorderWidth, (v, o) => v.BorderWidth = o, () => 0d, 16d),
+ new PropertyTestCase<Button, int> ("BorderRadius", v => v.BorderRadius, (v, o) => v.BorderRadius = o, () => 5, 12),
+ new PropertyTestCase<Button, Color> ("BorderColor", v => v.BorderColor, (v, o) => v.BorderColor = o, () => Color.Default, new Color (0, 1, 0)),
+ new PropertyTestCase<Button, string> ("FontFamily", v => v.FontFamily, (v, o) => v.FontFamily = o, () => null, "TestingFace"),
+ new PropertyTestCase<Button, double> ("FontSize", v => v.FontSize, (v, o) => v.FontSize = o, () => Device.GetNamedSize (NamedSize.Default, typeof (Button), true), 123.0),
+ new PropertyTestCase<Button, FontAttributes> ("FontAttributes", v => v.FontAttributes, (v, o) => v.FontAttributes = o, () => FontAttributes.None, FontAttributes.Italic),
+ new PropertyTestCase<CellTests.TestCell, double> ("Height", v => v.Height, (v, o) => v.Height = o, () => -1, 10),
+ new PropertyTestCase<DatePicker, DateTime> ("MinimumDate", v => v.MinimumDate, (v, o) => v.MinimumDate = o, () => new DateTime (1900, 1, 1), new DateTime (2014, 02, 05)),
+ new PropertyTestCase<DatePicker, DateTime> ("MaximumDate", v => v.MaximumDate, (v, o) => v.MaximumDate = o, () => new DateTime (2100, 12, 31), new DateTime (2014, 02, 05)),
+ new PropertyTestCase<DatePicker, DateTime> ("Date", v => v.Date, (v, o) => v.Date = o, () => DateTime.Now.Date, new DateTime (2008, 5, 5)),
+ new PropertyTestCase<DatePicker, string> ("Format", v => v.Format, (v, o) => v.Format = o, () => "d", "D"),
+ new PropertyTestCase<Editor, string> ("Text", v => v.Text, (v, o) => v.Text = o, () => null, "Foo"),
+ new PropertyTestCase<Entry, string> ("Text", v => v.Text, (v, o) => v.Text = o, () => null, "Foo"),
+ new PropertyTestCase<Entry, string> ("Placeholder", v => v.Placeholder, (v, o) => v.Placeholder = o, () => null, "Foo"),
+ new PropertyTestCase<Entry, bool> ("IsPassword", v => v.IsPassword, (v, o) => v.IsPassword = o, () => false, true),
+ new PropertyTestCase<Entry, Color> ("TextColor", v => v.TextColor, (v, o) => v.TextColor = o, () => Color.Default, new Color (0, 1, 0)),
+ new PropertyTestCase<Frame, Color> ("BackgroundColor", v => v.BackgroundColor, (v, o) => v.BackgroundColor = o, () => Color.Default, new Color (0, 1, 0)),
+ new PropertyTestCase<Frame, Color> ("OutlineColor", v => v.OutlineColor, (v, o) => v.OutlineColor = o, () => Color.Default, new Color (0, 1, 0)),
+ new PropertyTestCase<Frame, bool> ("HasShadow", v => v.HasShadow, (v, o) => v.HasShadow = o, () => true, false),
+ new PropertyTestCase<Grid, double> ("RowSpacing", v => v.RowSpacing, (v, o) => v.RowSpacing = o, () => 6, 12),
+ new PropertyTestCase<Grid, double> ("ColumnSpacing", v => v.ColumnSpacing, (v, o) => v.ColumnSpacing = o, () => 6, 12),
+ new PropertyTestCase<NaiveLayout, Thickness> ("Padding", v => v.Padding, (v, o) => v.Padding = o, () => default(Thickness), new Thickness (20, 20, 10, 10)),
+ new PropertyTestCase<Image, ImageSource> ("Source", v => v.Source, (v, o) => v.Source = o, () => null, ImageSource.FromFile("Foo")),
+ new PropertyTestCase<Image, Aspect> ("Aspect", v => v.Aspect, (v, o) => v.Aspect = o, () => Aspect.AspectFit, Aspect.AspectFill),
+ new PropertyTestCase<Image, bool> ("IsOpaque", v => v.IsOpaque, (v, o) => v.IsOpaque = o, () => false, true),
+ new PropertyTestCase<Label, string> ("Text", v => v.Text, (v, o) => v.Text = o, () => null, "Foo"),
+ new PropertyTestCase<Label, TextAlignment> ("XAlign", v => v.XAlign, (v, o) => v.XAlign = o, () => TextAlignment.Start, TextAlignment.End),
+ new PropertyTestCase<Label, TextAlignment> ("YAlign", v => v.YAlign, (v, o) => v.YAlign = o, () => TextAlignment.Start, TextAlignment.End),
+ new PropertyTestCase<Label, Color> ("TextColor", v => v.TextColor, (v, o) => v.TextColor = o, () => Color.Default, new Color (0, 1, 0)),
+ new PropertyTestCase<Label, LineBreakMode> ("LineBreakMode", v => v.LineBreakMode, (v, o) => v.LineBreakMode = o, () => LineBreakMode.WordWrap, LineBreakMode.TailTruncation),
+ new PropertyTestCase<Label, Font> ("Font", v => v.Font, (v, o) => v.Font = o, () => default (Font), Font.SystemFontOfSize (12)),
+ new PropertyTestCase<Label, string> ("FontFamily", v => v.FontFamily, (v, o) => v.FontFamily = o, () => null, "TestingFace"),
+ new PropertyTestCase<Label, double> ("FontSize", v => v.FontSize, (v, o) => v.FontSize = o, () => Device.GetNamedSize (NamedSize.Default, typeof (Label), true), 123.0),
+ new PropertyTestCase<Label, FontAttributes> ("FontAttributes", v => v.FontAttributes, (v, o) => v.FontAttributes = o, () => FontAttributes.None, FontAttributes.Italic),
+ new PropertyTestCase<Label, FormattedString> ("FormattedText", v => v.FormattedText, (v, o) => v.FormattedText = o, () => default (FormattedString), new FormattedString()),
+ new PropertyTestCase<Map, MapType> ("MapType", v => v.MapType, (v, o) => v.MapType = o, () => MapType.Street, MapType.Satellite),
+ new PropertyTestCase<Map, bool> ("IsShowingUser", v => v.IsShowingUser, (v, o) => v.IsShowingUser = o, () => false, true),
+ new PropertyTestCase<Map, bool> ("HasScrollEnabled", v => v.HasScrollEnabled, (v, o) => v.HasScrollEnabled = o, () => true, false),
+ new PropertyTestCase<Map, bool> ("HasZoomEnabled", v => v.HasZoomEnabled, (v, o) => v.HasZoomEnabled = o, () => true, false),
+ new PropertyTestCase<OpenGLView, bool> ("HasRenderLoop", v => v.HasRenderLoop, (v, o) => v.HasRenderLoop = o, () => false, true),
+ new PropertyTestCase<Page, string> ("BackgroundImage", v => v.BackgroundImage, (v, o) => v.BackgroundImage = o, () => null, "Foo"),
+ new PropertyTestCase<Page, Color> ("BackgroundColor", v => v.BackgroundColor, (v, o) => v.BackgroundColor = o, () => default(Color), new Color (0, 1, 0)),
+ new PropertyTestCase<Page, string> ("Title", v => v.Title, (v, o) => v.Title = o, () => null, "Foo"),
+ new PropertyTestCase<Page, bool> ("IsBusy", v => v.IsBusy, (v, o) => v.IsBusy = o, () => false, true),
+ new PropertyTestCase<Page, bool> ("IgnoresContainerArea", v => v.IgnoresContainerArea, (v, o) => v.IgnoresContainerArea = o, () => false, true),
+ new PropertyTestCase<Page, Thickness> ("Padding", v => v.Padding, (v, o) => v.Padding = o, () => default(Thickness), new Thickness (12)),
+ new PropertyTestCase<Picker, string> ("Title", v=>v.Title, (v, o) =>v.Title = o, () => null, "FooBar"),
+ new PropertyTestCase<Picker, int> ("SelectedIndex", v=>v.SelectedIndex, (v, o) =>v.SelectedIndex = o, () => -1, 2, ()=>new Picker{Items= {"Foo", "Bar", "Baz", "Qux"}}),
+ new PropertyTestCase<ProgressBar, double> ("Progress", v => v.Progress, (v, o) => v.Progress = o, () => 0, .5),
+ new PropertyTestCase<SearchBar, string> ("Placeholder", v => v.Placeholder, (v, o) => v.Placeholder = o, () => null, "Foo"),
+ new PropertyTestCase<SearchBar, string> ("Text", v => v.Text, (v, o) => v.Text = o, () => null, "Foo"),
+ new PropertyTestCase<Slider, double> ("Minimum", v => v.Minimum, (v, o) => v.Minimum = o, () => 0, .5),
+ new PropertyTestCase<Slider, double> ("Maximum", v => v.Maximum, (v, o) => v.Maximum = o, () => 1, .5),
+ new PropertyTestCase<Slider, double> ("Value", v => v.Value, (v, o) => v.Value = o, () => 0, .5),
+ new PropertyTestCase<StackLayout, StackOrientation> ("Orientation", v => v.Orientation, (v, o) => v.Orientation = o, () => StackOrientation.Vertical, StackOrientation.Horizontal),
+ new PropertyTestCase<StackLayout, double> ("Spacing", v => v.Spacing, (v, o) => v.Spacing = o, () => 6, 12),
+ new PropertyTestCase<Stepper, double> ("Minimum", v => v.Minimum, (v, o) => v.Minimum = o, () => 0, 50),
+ new PropertyTestCase<Stepper, double> ("Maximum", v => v.Maximum, (v, o) => v.Maximum = o, () => 100, 50),
+ new PropertyTestCase<Stepper, double> ("Value", v => v.Value, (v, o) => v.Value = o, () => 0, 50),
+ new PropertyTestCase<Stepper, double> ("Increment", v => v.Increment, (v, o) => v.Increment = o, () => 1, 2),
+ new PropertyTestCase<TableRoot, string> ("Title", v => v.Title, (v, o) => v.Title = o, () => null, "Foo"),
+ new PropertyTestCase<TableView, int> ("RowHeight", v => v.RowHeight, (v, o) => v.RowHeight = o, () => -1, 20),
+ new PropertyTestCase<TableView, bool> ("HasUnevenRows", v => v.HasUnevenRows, (v, o) => v.HasUnevenRows = o, () => false, true),
+ new PropertyTestCase<TableView, TableIntent> ("Intent", v => v.Intent, (v, o) => v.Intent = o, () => TableIntent.Data, TableIntent.Menu),
+ new PropertyTestCase<TextCell, string> ("Text", v => v.Text, (v, o) => v.Text = o, () => null, "Foo"),
+ new PropertyTestCase<TextCell, string> ("Detail", v => v.Detail, (v, o) => v.Detail = o, () => null, "Foo"),
+ new PropertyTestCase<TextCell, Color> ("TextColor", v => v.TextColor, (v, o) => v.TextColor = o, () => Color.Default, new Color (0, 1, 0)),
+ new PropertyTestCase<TextCell, Color> ("DetailColor", v => v.DetailColor, (v, o) => v.DetailColor = o, () => Color.Default, new Color (0, 1, 0)),
+ new PropertyTestCase<TimePicker, TimeSpan> ("Time", v => v.Time, (v, o) => v.Time = o, () => default(TimeSpan), new TimeSpan (8, 0, 0)),
+ new PropertyTestCase<TimePicker, string> ("Format", v => v.Format, (v, o) => v.Format = o, () => "t", "T"),
+ new PropertyTestCase<ViewCell, View> ("View", v => v.View, (v, o) => v.View = o, () => null, new View ()),
+ new PropertyTestCase<WebView, WebViewSource> ("Source", v => v.Source, (v, o) => v.Source = o, () => null, new UrlWebViewSource { Url = "Foo" }),
+ new PropertyTestCase<TapGestureRecognizer, int> ("NumberOfTapsRequired", t => t.NumberOfTapsRequired, (t, o) => t.NumberOfTapsRequired = o, () => 1, 3),
+ new PropertyTestCase<TapGestureRecognizer, object> ("CommandParameter", t => t.CommandParameter, (t, o) => t.CommandParameter = o, () => null, "Test"),
+ new PropertyTestCase<TapGestureRecognizer, ICommand> ("Command", t => t.Command, (t, o) => t.Command = o, () => null, new Command(()=>{})),
+ new PropertyTestCase<MasterDetailPage, bool> ("IsGestureEnabled", md => md.IsGestureEnabled, (md, v) => md.IsGestureEnabled = v, () => true, false)
+ };
+
+ [SetUp]
+ public override void Setup ()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown ()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test, TestCaseSource ("Properties")]
+ public void DefaultValues (PropertyTestCase property)
+ {
+ var view = property.CreateView ();
+ Assert.AreEqual (property.ExpectedDefaultValue, property.PropertyGetter (view), property.DebugName);
+ }
+
+ [Test, TestCaseSource ("Properties")]
+ public void Set (PropertyTestCase property)
+ {
+ var view = property.CreateView ();
+
+ bool changed = false;
+ view.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == property.Name)
+ changed = true;
+ };
+
+ var testvalue = property.TestValue;
+ property.PropertySetter (view, testvalue);
+
+ Assert.True (changed, property.DebugName);
+ Assert.AreEqual (testvalue, property.PropertyGetter (view), property.DebugName);
+ }
+
+ [Test, TestCaseSource ("Properties")]
+ public void DoubleSet (PropertyTestCase property)
+ {
+ var view = property.CreateView ();
+
+ var testvalue = property.TestValue;
+ property.PropertySetter (view, testvalue);
+
+ bool changed = false;
+ view.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == property.Name)
+ changed = true;
+ };
+
+ property.PropertySetter (view, testvalue);
+
+ Assert.False (changed, property.DebugName);
+ Assert.AreEqual (testvalue, property.PropertyGetter (view), property.DebugName);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/NotifyCollectionChangedEventArgsExtensionsTests.cs b/Xamarin.Forms.Core.UnitTests/NotifyCollectionChangedEventArgsExtensionsTests.cs
new file mode 100644
index 00000000..e9acde45
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/NotifyCollectionChangedEventArgsExtensionsTests.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class NotifyCollectionChangedEventArgsExtensionsTests : BaseTestFixture
+ {
+ [Test]
+ public void Add()
+ {
+ List<string> applied = new List<string> { "foo", "bar", "baz" };
+
+ Action reset = () => Assert.Fail ("Reset should not be called");
+ Action<object, int, bool> insert = (o, i, create) => {
+ Assert.That (create, Is.True);
+ applied.Insert (i, (string) o);
+ };
+
+ Action<object, int> removeAt = (o, i) => applied.RemoveAt (i);
+
+ var items = new ObservableCollection<string> (applied);
+ items.CollectionChanged += (s, e) => e.Apply (insert, removeAt, reset);
+
+ items.Add ("monkey");
+
+ CollectionAssert.AreEqual (items, applied);
+ }
+
+ [Test]
+ public void Insert()
+ {
+ List<string> applied = new List<string> { "foo", "bar", "baz" };
+
+ Action reset = () => Assert.Fail ("Reset should not be called");
+ Action<object, int, bool> insert = (o, i, create) => {
+ Assert.That (create, Is.True);
+ applied.Insert (i, (string) o);
+ };
+ Action<object, int> removeAt = (o, i) => applied.RemoveAt (i);
+
+ var items = new ObservableCollection<string> (applied);
+ items.CollectionChanged += (s, e) => e.Apply (insert, removeAt, reset);
+
+ items.Insert (1, "monkey");
+
+ CollectionAssert.AreEqual (items, applied);
+ }
+
+ [Test]
+ public void Move()
+ {
+ List<string> applied = new List<string> { "foo", "bar", "baz" };
+
+ Action reset = () => Assert.Fail ("Reset should not be called");
+ Action<object, int, bool> insert = (o, i, create) => {
+ Assert.That (create, Is.False);
+ applied.Insert (i, (string) o);
+ };
+
+ Action<object, int> removeAt = (o, i) => applied.RemoveAt (i);
+
+ var items = new ObservableCollection<string> (applied);
+ items.CollectionChanged += (s, e) => e.Apply (insert, removeAt, reset);
+
+ items.Move (0, 2);
+
+ CollectionAssert.AreEqual (items, applied);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ObservableWrapperTests.cs b/Xamarin.Forms.Core.UnitTests/ObservableWrapperTests.cs
new file mode 100644
index 00000000..2dc8a58d
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ObservableWrapperTests.cs
@@ -0,0 +1,402 @@
+using System;
+using System.Collections.ObjectModel;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ObservableWrapperTests : BaseTestFixture
+ {
+ [Test]
+ public void Constructor ()
+ {
+ var observableCollection = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, Button> (observableCollection);
+
+ Assert.IsEmpty (wrapper);
+
+ Assert.Throws<ArgumentNullException> (() => new ObservableWrapper<View, View> (null));
+ }
+
+ [Test]
+ public void IgnoresInternallyAdded ()
+ {
+ var observableCollection = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, Button> (observableCollection);
+
+ var child = new View ();
+
+ observableCollection.Add (child);
+
+ Assert.IsEmpty (wrapper);
+ }
+
+ [Test]
+ public void TracksExternallyAdded ()
+ {
+ var observableCollection = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, Button> (observableCollection);
+
+ var child = new Button ();
+
+ wrapper.Add (child);
+
+ Assert.AreEqual (child, wrapper[0]);
+ Assert.AreEqual (child, observableCollection[0]);
+ }
+
+ [Test]
+ public void AddWithInternalItemsAlreadyAdded ()
+ {
+ var observableCollection = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, Button> (observableCollection);
+
+ var view = new View ();
+ observableCollection.Add (view);
+
+ var btn = new Button ();
+
+ wrapper.Add (btn);
+
+ Assert.AreEqual (btn, wrapper[0]);
+ Assert.AreEqual (1, wrapper.Count);
+
+ Assert.Contains (btn, observableCollection);
+ Assert.Contains (view, observableCollection);
+ Assert.AreEqual (2, observableCollection.Count);
+ }
+
+ [Test]
+ public void IgnoresInternallyAddedSameType ()
+ {
+ var observableCollection = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, View> (observableCollection);
+
+ var child = new View ();
+
+ observableCollection.Add (child);
+
+ Assert.IsEmpty (wrapper);
+ }
+
+ [Test]
+ public void TracksExternallyAddedSameType ()
+ {
+ var observableCollection = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, View> (observableCollection);
+
+ var child = new Button ();
+
+ wrapper.Add (child);
+
+ Assert.AreEqual (child, wrapper[0]);
+ Assert.AreEqual (child, observableCollection[0]);
+ }
+
+ [Test]
+ public void AddWithInternalItemsAlreadyAddedSameType ()
+ {
+ var observableCollection = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, View> (observableCollection);
+
+ var view = new View ();
+ observableCollection.Add (view);
+
+ var btn = new Button ();
+
+ wrapper.Add (btn);
+
+ Assert.AreEqual (btn, wrapper[0]);
+ Assert.AreEqual (1, wrapper.Count);
+
+ Assert.Contains (btn, observableCollection);
+ Assert.Contains (view, observableCollection);
+ Assert.AreEqual (2, observableCollection.Count);
+ }
+
+ [Test]
+ public void CannotRemoveInternalItem ()
+ {
+ var observableCollection = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, View> (observableCollection);
+
+ var child = new View ();
+
+ observableCollection.Add (child);
+
+ Assert.IsEmpty (wrapper);
+
+ Assert.False (wrapper.Remove (child));
+
+ Assert.Contains (child, observableCollection);
+ }
+
+ [Test]
+ public void ReadOnly ()
+ {
+ var observableCollection = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, Button> (observableCollection);
+
+ Assert.False (wrapper.IsReadOnly);
+
+ wrapper.Add (new Button ());
+
+ wrapper.IsReadOnly = true;
+
+ Assert.True (wrapper.IsReadOnly);
+
+ Assert.Throws<NotSupportedException> (() => wrapper.Remove (wrapper[0]));
+ Assert.Throws<NotSupportedException> (() => wrapper.Add (new Button ()));
+ Assert.Throws<NotSupportedException> (() => wrapper.RemoveAt (0));
+ Assert.Throws<NotSupportedException> (() => wrapper.Insert (0, new Button ()));
+ Assert.Throws<NotSupportedException> (wrapper.Clear);
+ }
+
+ [Test]
+ public void Indexer ()
+ {
+ var observableCollection = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, Button> (observableCollection);
+
+ wrapper.Add (new Button ());
+
+ var newButton = new Button ();
+
+ wrapper[0] = newButton;
+
+ Assert.AreEqual (newButton, wrapper[0]);
+ }
+
+ [Test]
+ public void IndexerSameType ()
+ {
+ var observableCollection = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, View> (observableCollection);
+
+ wrapper.Add (new Button ());
+
+ var newButton = new Button ();
+
+ wrapper[0] = newButton;
+
+ Assert.AreEqual (newButton, wrapper[0]);
+ }
+
+ [Test]
+ public void CopyTo ()
+ {
+ var observableCollection = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, View> (observableCollection);
+
+ var child1 = new Button ();
+ var child2 = new Button ();
+ var child3 = new Button ();
+ var child4 = new Button ();
+ var child5 = new Button ();
+
+ observableCollection.Add (new Stepper ());
+ wrapper.Add (child1);
+ observableCollection.Add (new Button ());
+ wrapper.Add (child2);
+ wrapper.Add (child3);
+ wrapper.Add (child4);
+ wrapper.Add (child5);
+ observableCollection.Add (new Button ());
+
+ var target = new View[30];
+ wrapper.CopyTo (target, 2);
+
+ Assert.AreEqual (target[2], child1);
+ Assert.AreEqual (target[3], child2);
+ Assert.AreEqual (target[4], child3);
+ Assert.AreEqual (target[5], child4);
+ Assert.AreEqual (target[6], child5);
+ }
+
+ [Test]
+ public void INCCSimpleAdd ()
+ {
+ var oc = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, View> (oc);
+
+ var child = new Button ();
+
+ Button addedResult = null;
+ int addIndex = -1;
+ wrapper.CollectionChanged += (sender, args) => {
+ addedResult = args.NewItems[0] as Button;
+ addIndex = args.NewStartingIndex;
+ };
+
+ wrapper.Add (child);
+
+ Assert.AreEqual (0, addIndex);
+ Assert.AreEqual (child, addedResult);
+ }
+
+ [Test]
+ public void INCCSimpleAddToInner ()
+ {
+ var oc = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, View> (oc);
+
+ var child = new Button ();
+
+ Button addedResult = null;
+ int addIndex = -1;
+ wrapper.CollectionChanged += (sender, args) => {
+ addedResult = args.NewItems[0] as Button;
+ addIndex = args.NewStartingIndex;
+ };
+
+ oc.Add (child);
+
+ Assert.AreEqual (-1, addIndex);
+ Assert.AreEqual (null, addedResult);
+ }
+
+ [Test]
+ public void INCCComplexAdd ()
+ {
+ var oc = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, Button> (oc);
+
+ oc.Add (new Stepper ());
+
+ var child = new Button ();
+
+ Button addedResult = null;
+ int addIndex = -1;
+ wrapper.CollectionChanged += (sender, args) => {
+ addedResult = args.NewItems[0] as Button;
+ addIndex = args.NewStartingIndex;
+ };
+
+ wrapper.Add (child);
+
+ Assert.AreEqual (0, addIndex);
+ Assert.AreEqual (child, addedResult);
+ }
+
+ [Test]
+ public void INCCSimpleRemove ()
+ {
+ var oc = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, Button> (oc);
+
+ var child = new Button ();
+ wrapper.Add (child);
+
+ Button removedResult = null;
+ int removeIndex = -1;
+ wrapper.CollectionChanged += (sender, args) => {
+ removedResult = args.OldItems[0] as Button;
+ removeIndex = args.OldStartingIndex;
+ };
+
+ wrapper.Remove (child);
+
+ Assert.AreEqual (0, removeIndex);
+ Assert.AreEqual (child, removedResult);
+ }
+
+ [Test]
+ public void INCCSimpleRemoveFromInner ()
+ {
+ var oc = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, Button> (oc);
+
+ var child = new Button ();
+ oc.Add (child);
+
+ Button addedResult = null;
+ int addIndex = -1;
+ wrapper.CollectionChanged += (sender, args) => {
+ addedResult = args.OldItems[0] as Button;
+ addIndex = args.OldStartingIndex;
+ };
+
+ oc.Remove (child);
+
+ Assert.AreEqual (-1, addIndex);
+ Assert.AreEqual (null, addedResult);
+ }
+
+ [Test]
+ public void INCCComplexRemove ()
+ {
+ var oc = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, Button> (oc);
+
+ oc.Add (new Stepper ());
+
+ var child = new Button ();
+ wrapper.Add (child);
+
+ Button removedResult = null;
+ int removeIndex = -1;
+ wrapper.CollectionChanged += (sender, args) => {
+ removedResult = args.OldItems[0] as Button;
+ removeIndex = args.OldStartingIndex;
+ };
+
+ wrapper.Remove (child);
+
+ Assert.AreEqual (child, removedResult);
+ Assert.AreEqual (0, removeIndex);
+ }
+
+ [Test]
+ public void INCCComplexRemoveLast ()
+ {
+ var oc = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, Button> (oc);
+
+ oc.Add (new Stepper ());
+
+ wrapper.Add (new Button ());
+ wrapper.Add (new Button ());
+ var child = new Button ();
+ wrapper.Add (child);
+
+ Button removedResult = null;
+ int removeIndex = -1;
+ wrapper.CollectionChanged += (sender, args) => {
+ removedResult = args.OldItems[0] as Button;
+ removeIndex = args.OldStartingIndex;
+ };
+
+ wrapper.Remove (child);
+
+ Assert.AreEqual (child, removedResult);
+ Assert.AreEqual (2, removeIndex);
+ }
+
+ [Test]
+ public void INCCReplace ()
+ {
+ var oc = new ObservableCollection<View> ();
+ var wrapper = new ObservableWrapper<View, Button> (oc);
+
+ var child1 = new Button ();
+ var child2 = new Button ();
+
+ wrapper.Add (child1);
+
+ int index = -1;
+ Button oldItem = null;
+ Button newItem = null;
+ wrapper.CollectionChanged += (sender, args) => {
+ index = args.NewStartingIndex;
+ oldItem = args.OldItems[0] as Button;
+ newItem = args.NewItems[0] as Button;
+ };
+
+ wrapper[0] = child2;
+
+ Assert.AreEqual (0, index);
+ Assert.AreEqual (child1, oldItem);
+ Assert.AreEqual (child2, newItem);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/OpenGLViewUnitTests.cs b/Xamarin.Forms.Core.UnitTests/OpenGLViewUnitTests.cs
new file mode 100644
index 00000000..e095914c
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/OpenGLViewUnitTests.cs
@@ -0,0 +1,20 @@
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class OpenGLViewUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void Display ()
+ {
+ var view = new OpenGLView ();
+ bool displayed = false;
+
+ ((IOpenGlViewController)view).DisplayRequested += (s, o) => displayed = true;
+
+ view.Display ();
+ Assert.True (displayed);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/PageTests.cs b/Xamarin.Forms.Core.UnitTests/PageTests.cs
new file mode 100644
index 00000000..f44d004f
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/PageTests.cs
@@ -0,0 +1,498 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class PageTests : BaseTestFixture
+ {
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ MessagingCenter.ClearSubscribers();
+ }
+
+ [Test]
+ public void TestConstructor ()
+ {
+ var child = new Label ();
+ Page root = new ContentPage {Content = child};
+
+ Assert.AreEqual (root.LogicalChildren.Count, 1);
+ Assert.AreSame (root.LogicalChildren.First (), child);
+ }
+
+ [Test]
+ public void TestChildFillBehavior ()
+ {
+ var child = new Label ();
+ Page root = new ContentPage {Content = child};
+ root.IsPlatformEnabled = child.IsPlatformEnabled = true;
+
+ root.Layout (new Rectangle (0, 0, 200, 500));
+
+ Assert.AreEqual (child.Width, 200);
+ Assert.AreEqual (child.Height, 500);
+ }
+
+ [Test]
+ public void TestSizedChildBehavior ()
+ {
+ var plat = new UnitPlatform ();
+ var child = new Label {Platform = plat, IsPlatformEnabled = true, WidthRequest = 100, HorizontalOptions = LayoutOptions.Center};
+ var root = new ContentPage {Platform = plat, IsPlatformEnabled = true, Content = child};
+
+ root.Layout (new Rectangle (0, 0, 200, 500));
+
+ Assert.AreEqual (50, child.X);
+ Assert.AreEqual (100, child.Width);
+ Assert.AreEqual (500, child.Height);
+
+ child = new Label () {
+ Platform = plat, IsPlatformEnabled = true,
+ HeightRequest = 100,
+ VerticalOptions = LayoutOptions.Center
+ };
+
+ root = new ContentPage {
+ Platform = plat, IsPlatformEnabled = true,
+ Content = child
+ };
+
+ root.Layout (new Rectangle (0, 0, 200, 500));
+
+ Assert.AreEqual (0, child.X);
+ Assert.AreEqual (200, child.Y);
+ Assert.AreEqual (200, child.Width);
+ Assert.AreEqual (100, child.Height);
+
+ child = new Label ();
+ child.IsPlatformEnabled = true;
+ child.HeightRequest = 100;
+
+ root = new ContentPage {
+ Content = child,
+ Platform = plat, IsPlatformEnabled = true
+ };
+
+ root.Layout (new Rectangle (0, 0, 200, 500));
+
+ Assert.AreEqual (0, child.X);
+ Assert.AreEqual (0, child.Y);
+ Assert.AreEqual (200, child.Width);
+ Assert.AreEqual (500, child.Height);
+ }
+
+ [Test]
+ public void NativeSizedChildBehavior ()
+ {
+ var plat = new UnitPlatform ();
+ var child = new Label {Platform = plat, IsPlatformEnabled = true, HorizontalOptions = LayoutOptions.Center};
+ var root = new ContentPage {Platform = plat, IsPlatformEnabled = true, Content = child};
+
+ root.Layout (new Rectangle (0, 0, 200, 500));
+
+ Assert.AreEqual (50, child.X);
+ Assert.AreEqual (100, child.Width);
+ Assert.AreEqual (500, child.Height);
+
+ child = new Label () {
+ Platform = plat, IsPlatformEnabled = true,
+ VerticalOptions = LayoutOptions.Center
+ };
+
+ root = new ContentPage {
+ Platform = plat, IsPlatformEnabled = true,
+ Content = child
+ };
+
+ root.Layout (new Rectangle (0, 0, 200, 500));
+
+ Assert.AreEqual (0, child.X);
+ Assert.AreEqual (240, child.Y);
+ Assert.AreEqual (200, child.Width);
+ Assert.AreEqual (20, child.Height);
+ }
+
+ [Test]
+ public void TestContentPageSetContent ()
+ {
+ View child;
+ var page = new ContentPage {Content = child = new View ()};
+
+ Assert.AreEqual (child, page.Content);
+
+ bool fired = false;
+ page.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "Content")
+ fired = true;
+ };
+
+ page.Content = child;
+ Assert.False (fired);
+
+ page.Content = new View ();
+ Assert.True (fired);
+
+ page.Content = null;
+ Assert.Null (page.Content);
+ }
+
+ [Test]
+ public void TestLayoutChildrenFill ()
+ {
+ View child;
+ var page = new ContentPage {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 200,
+ IsPlatformEnabled = true
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ page.Layout (new Rectangle (0, 0, 800, 800));
+
+ Assert.AreEqual (new Rectangle (0, 0, 800, 800), child.Bounds);
+
+ page.Layout (new Rectangle (0, 0, 50, 50));
+
+ Assert.AreEqual (new Rectangle (0, 0, 50, 50), child.Bounds);
+ }
+
+ [Test]
+ public void TestLayoutChildrenStart ()
+ {
+ View child;
+ var page = new ContentPage {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 200,
+ HorizontalOptions = LayoutOptions.Start,
+ VerticalOptions = LayoutOptions.Start,
+ IsPlatformEnabled = true
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ page.Layout (new Rectangle (0, 0, 800, 800));
+
+ Assert.AreEqual (new Rectangle (0, 0, 100, 200), child.Bounds);
+
+ page.Layout (new Rectangle (0, 0, 50, 50));
+
+ Assert.AreEqual (new Rectangle (0, 0, 50, 50), child.Bounds);
+ }
+
+ [Test]
+ public void TestLayoutChildrenEnd ()
+ {
+ View child;
+ var page = new ContentPage {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 200,
+ HorizontalOptions = LayoutOptions.End,
+ VerticalOptions = LayoutOptions.End,
+ IsPlatformEnabled = true
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ page.Layout (new Rectangle (0, 0, 800, 800));
+
+ Assert.AreEqual (new Rectangle (700, 600, 100, 200), child.Bounds);
+
+ page.Layout (new Rectangle (0, 0, 50, 50));
+
+ Assert.AreEqual (new Rectangle (0, 0, 50, 50), child.Bounds);
+ }
+
+ [Test]
+ public void TestLayoutChildrenCenter ()
+ {
+ View child;
+ var page = new ContentPage {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 200,
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.Center,
+ IsPlatformEnabled = true
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ page.Layout (new Rectangle (0, 0, 800, 800));
+
+ Assert.AreEqual (new Rectangle (350, 300, 100, 200), child.Bounds);
+
+ page.Layout (new Rectangle (0, 0, 50, 50));
+
+ Assert.AreEqual (new Rectangle (0, 0, 50, 50), child.Bounds);
+ }
+
+ [Test]
+ public void TestLayoutWithContainerArea ()
+ {
+ View child;
+ var page = new ContentPage {
+ Content = child = new View {
+ WidthRequest = 100,
+ HeightRequest = 200,
+ IsPlatformEnabled = true
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ page.Layout (new Rectangle (0, 0, 800, 800));
+
+ Assert.AreEqual (new Rectangle (0, 0, 800, 800), child.Bounds);
+
+ page.ContainerArea = new Rectangle (10, 10, 30, 30);
+
+ Assert.AreEqual (new Rectangle (10, 10, 30, 30), child.Bounds);
+
+ page.Layout (new Rectangle (0, 0, 50, 50));
+
+ Assert.AreEqual (new Rectangle (10, 10, 30, 30), child.Bounds);
+ }
+
+ [Test]
+ public void TestThrowOnInvalidAlignment ()
+ {
+ bool thrown = false;
+
+ try {
+ new ContentPage {
+ Content = new View {
+ WidthRequest = 100,
+ HeightRequest = 200,
+ HorizontalOptions = new LayoutOptions((LayoutAlignment) int.MaxValue, false),
+ VerticalOptions = LayoutOptions.Center,
+ IsPlatformEnabled = true
+ },
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+ } catch (ArgumentOutOfRangeException) {
+ thrown = true;
+ }
+
+ Assert.True (thrown);
+ }
+
+ [Test]
+ public void BusyNotSentWhenNotVisible ()
+ {
+ var sent = false;
+ MessagingCenter.Subscribe<Page, bool> (this, Page.BusySetSignalName, (p, b) => sent = true);
+
+ new ContentPage { IsBusy = true };
+
+ Assert.That (sent, Is.False, "Busy message sent while not visible");
+ }
+
+ [Test]
+ public void BusySentWhenBusyPageAppears()
+ {
+ var sent = false;
+ MessagingCenter.Subscribe<Page, bool> (this, Page.BusySetSignalName, (p, b) => {
+ Assert.That (b, Is.True);
+ sent = true;
+ });
+
+ var page = new ContentPage { IsBusy = true };
+
+ Assert.That (sent, Is.False, "Busy message sent while not visible");
+
+ page.SendAppearing();
+
+ Assert.That (sent, Is.True, "Busy message not sent when visible");
+ }
+
+ [Test]
+ public void BusySentWhenBusyPageDisappears()
+ {
+ var page = new ContentPage { IsBusy = true };
+ page.SendAppearing();
+
+ var sent = false;
+ MessagingCenter.Subscribe<Page, bool> (this, Page.BusySetSignalName, (p, b) => {
+ Assert.That (b, Is.False);
+ sent = true;
+ });
+
+ page.SendDisappearing();
+
+ Assert.That (sent, Is.True, "Busy message not sent when visible");
+ }
+
+ [Test]
+ public void BusySentWhenVisiblePageSetToBusy()
+ {
+ var sent = false;
+ MessagingCenter.Subscribe<Page, bool> (this, Page.BusySetSignalName, (p, b) => sent = true);
+
+ var page = new ContentPage();
+ page.SendAppearing();
+
+ Assert.That (sent, Is.False, "Busy message sent appearing while not busy");
+
+ page.IsBusy = true;
+
+ Assert.That (sent, Is.True, "Busy message not sent when visible");
+ }
+
+ [Test]
+ public void DisplayAlert ()
+ {
+ var page = new ContentPage ();
+
+ AlertArguments args = null;
+ MessagingCenter.Subscribe (this, Page.AlertSignalName, (Page sender, AlertArguments e) => args = e);
+
+ var task = page.DisplayAlert ("Title", "Message", "Accept", "Cancel");
+
+ Assert.AreEqual ("Title", args.Title);
+ Assert.AreEqual ("Message", args.Message);
+ Assert.AreEqual ("Accept", args.Accept);
+ Assert.AreEqual ("Cancel", args.Cancel);
+
+ bool completed = false;
+ var continueTask = task.ContinueWith (t => completed = true);
+
+ args.SetResult (true);
+ continueTask.Wait ();
+ Assert.True (completed);
+ }
+
+ [Test]
+ public void DisplayActionSheet ()
+ {
+ var page = new ContentPage ();
+
+ ActionSheetArguments args = null;
+ MessagingCenter.Subscribe (this, Page.ActionSheetSignalName, (Page sender, ActionSheetArguments e) => args = e);
+
+ var task = page.DisplayActionSheet ("Title", "Cancel", "Destruction", "Other 1", "Other 2");
+
+ Assert.AreEqual ("Title", args.Title);
+ Assert.AreEqual ("Destruction", args.Destruction);
+ Assert.AreEqual ("Cancel", args.Cancel);
+ Assert.AreEqual ("Other 1", args.Buttons.First());
+ Assert.AreEqual ("Other 2", args.Buttons.Skip (1).First());
+
+ bool completed = false;
+ var continueTask = task.ContinueWith (t => completed = true);
+
+ args.SetResult ("Cancel");
+ continueTask.Wait ();
+ Assert.True (completed);
+ }
+
+ [Test]
+ public void SendAppearing ()
+ {
+ var page = new ContentPage ();
+
+ bool sent = false;
+ page.Appearing += (sender, args) => sent = true;
+
+ page.SendAppearing ();
+
+ Assert.True (sent);
+ }
+
+ [Test]
+ public void SendDisappearing ()
+ {
+ var page = new ContentPage ();
+
+ page.SendAppearing ();
+
+ bool sent = false;
+ page.Disappearing += (sender, args) => sent = true;
+
+ page.SendDisappearing ();
+
+ Assert.True (sent);
+ }
+
+ [Test]
+ public void SendAppearingDoesntGetCalledMultipleTimes ()
+ {
+ var page = new ContentPage ();
+
+ int countAppearing = 0;
+ page.Appearing += (sender, args) => countAppearing++;
+
+ page.SendAppearing ();
+ page.SendAppearing ();
+
+ Assert.That (countAppearing, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void IsVisibleWorks ()
+ {
+ var page = new ContentPage ();
+ page.IsVisible = false;
+ Assert.False (page.IsVisible);
+ }
+
+ [Test]
+ public void SendAppearingToChildrenAfter ()
+ {
+ var page = new ContentPage ();
+
+ var navPage = new NavigationPage (page);
+
+ bool sentNav = false;
+ bool sent = false;
+ page.Appearing += (sender, args) => {
+ if (sentNav)
+ sent = true;
+ };
+ navPage.Appearing += (sender, e) => sentNav = true;
+
+ navPage.SendAppearing ();
+
+ Assert.True (sentNav);
+ Assert.True (sent);
+
+ }
+
+ [Test]
+ public void SendDisappearingToChildrenPageFirst ()
+ {
+ var page = new ContentPage ();
+
+ var navPage = new NavigationPage (page);
+ navPage.SendAppearing ();
+
+ bool sentNav = false;
+ bool sent = false;
+ page.Disappearing += (sender, args) => {
+ sent = true;
+ };
+ navPage.Disappearing += (sender, e) => {
+ if (sent)
+ sentNav = true;
+ };
+ navPage.SendDisappearing ();
+
+ Assert.True (sentNav);
+ Assert.True (sent);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/PanGestureRecognizerUnitTests.cs b/Xamarin.Forms.Core.UnitTests/PanGestureRecognizerUnitTests.cs
new file mode 100644
index 00000000..c0207d69
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/PanGestureRecognizerUnitTests.cs
@@ -0,0 +1,99 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+
+ public class PanGestureRecognizerUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void PanRaisesStartedEventTest ()
+ {
+ var view = new View ();
+ var pan = new PanGestureRecognizer ();
+
+ GestureStatus target = GestureStatus.Canceled;
+ pan.PanUpdated += (object sender, PanUpdatedEventArgs e) => {
+ target = e.StatusType;
+ };
+
+ ((IPanGestureController)pan).SendPanStarted (view, 0);
+ Assert.AreEqual (GestureStatus.Started, target);
+ }
+
+ [Test]
+ public void PanRaisesRunningEventTest ()
+ {
+ var view = new View ();
+ var pan = new PanGestureRecognizer ();
+
+ GestureStatus target = GestureStatus.Canceled;
+ pan.PanUpdated += (object sender, PanUpdatedEventArgs e) => {
+ target = e.StatusType;
+ };
+
+ ((IPanGestureController)pan).SendPan (view, gestureId: 0, totalX: 5, totalY: 10);
+ Assert.AreEqual (GestureStatus.Running, target);
+ }
+
+ [Test]
+ public void PanRunningEventContainsTotalXTest ()
+ {
+ var view = new View ();
+ var pan = new PanGestureRecognizer ();
+
+ double target = 0;
+ pan.PanUpdated += (object sender, PanUpdatedEventArgs e) => {
+ target = e.TotalX;
+ };
+
+ ((IPanGestureController)pan).SendPan (view, gestureId: 0, totalX: 5, totalY: 10);
+ Assert.AreEqual (5, target);
+ }
+
+ [Test]
+ public void PanRunningEventContainsTotalYTest ()
+ {
+ var view = new View ();
+ var pan = new PanGestureRecognizer ();
+
+ double target = 0;
+ pan.PanUpdated += (object sender, PanUpdatedEventArgs e) => {
+ target = e.TotalY;
+ };
+
+ ((IPanGestureController)pan).SendPan (view, gestureId: 0, totalX: 5, totalY: 10);
+ Assert.AreEqual (10, target);
+ }
+
+ [Test]
+ public void PanRaisesCompletedEventTest ()
+ {
+ var view = new View ();
+ var pan = new PanGestureRecognizer ();
+
+ GestureStatus target = GestureStatus.Canceled;
+ pan.PanUpdated += (object sender, PanUpdatedEventArgs e) => {
+ target = e.StatusType;
+ };
+
+ ((IPanGestureController)pan).SendPanCompleted (view, 0);
+ Assert.AreEqual (GestureStatus.Completed, target);
+ }
+
+ [Test]
+ public void PanRaisesCanceledEventTest ()
+ {
+ var view = new View ();
+ var pan = new PanGestureRecognizer ();
+
+ GestureStatus target = GestureStatus.Started;
+ pan.PanUpdated += (object sender, PanUpdatedEventArgs e) => {
+ target = e.StatusType;
+ };
+
+ ((IPanGestureController)pan).SendPanCanceled (view, 0);
+ Assert.AreEqual (GestureStatus.Canceled, target);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/PickerTests.cs b/Xamarin.Forms.Core.UnitTests/PickerTests.cs
new file mode 100644
index 00000000..859f9025
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/PickerTests.cs
@@ -0,0 +1,59 @@
+using System;
+
+using NUnit.Framework;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class PickerTests : BaseTestFixture
+ {
+ [Test]
+ public void TestSetSelectedIndexOnNullRows()
+ {
+ var picker = new Picker ();
+
+ Assert.IsEmpty (picker.Items);
+ Assert.AreEqual (-1, picker.SelectedIndex);
+
+ picker.SelectedIndex = 2;
+
+ Assert.AreEqual (-1, picker.SelectedIndex);
+ }
+
+ [Test]
+ public void TestSelectedIndexInRange ()
+ {
+ var picker = new Picker { Items = { "John", "Paul", "George", "Ringo" } };
+
+ picker.SelectedIndex = 2;
+ Assert.AreEqual (2, picker.SelectedIndex);
+
+ picker.SelectedIndex = 42;
+ Assert.AreEqual (3, picker.SelectedIndex);
+
+ picker.SelectedIndex = -1;
+ Assert.AreEqual (-1, picker.SelectedIndex);
+
+ picker.SelectedIndex = -42;
+ Assert.AreEqual (-1, picker.SelectedIndex);
+ }
+
+ [Test]
+ public void TestSelectedIndexChangedOnCollectionShrink()
+ {
+ var picker = new Picker { Items = { "John", "Paul", "George", "Ringo" }, SelectedIndex = 3 };
+
+ Assert.AreEqual (3, picker.SelectedIndex);
+
+ picker.Items.RemoveAt (3);
+ picker.Items.RemoveAt (2);
+
+
+ Assert.AreEqual (1, picker.SelectedIndex);
+
+ picker.Items.Clear ();
+ Assert.AreEqual (-1, picker.SelectedIndex);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/PinTests.cs b/Xamarin.Forms.Core.UnitTests/PinTests.cs
new file mode 100644
index 00000000..6ee7af64
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/PinTests.cs
@@ -0,0 +1,105 @@
+using NUnit.Framework;
+using Xamarin.Forms.Maps;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class PinTests : BaseTestFixture
+ {
+ [Test]
+ public void Constructor ()
+ {
+ Pin pin = new Pin {
+ Type = PinType.SavedPin,
+ Position = new Position (-92, 178),
+ Label = "My Desktop",
+ Address = "123 Hello World Street"
+ };
+
+ Assert.AreEqual (pin.Type, PinType.SavedPin);
+ Assert.AreEqual (pin.Position.Latitude, -90);
+ Assert.AreEqual (pin.Label, "My Desktop");
+ Assert.AreEqual (pin.Address, "123 Hello World Street");
+ }
+
+ [Test]
+ public void Equals ()
+ {
+ Pin pin1 = new Pin ();
+ Pin pin2 = new Pin ();
+ Pin pin3 = new Pin {
+ Type = PinType.Place,
+ Position = new Position (12, -24),
+ Label = "Test",
+ Address = "123 Test street"
+ };
+
+ Pin pin4 = new Pin {
+ Type = PinType.Place,
+ Position = new Position (12, -24),
+ Label = "Test",
+ Address = "123 Test street"
+ };
+
+ Assert.True (pin1.Equals (pin2));
+ Assert.True (pin3.Equals (pin4));
+ Assert.False (pin1.Equals (pin3));
+ }
+
+ [Test]
+ public void EqualsOp () {
+ var pin1 = new Pin {
+ Type = PinType.Place,
+ Position = new Position (12, -24),
+ Label = "Test",
+ Address = "123 Test street"
+ };
+
+ var pin2 = new Pin {
+ Type = PinType.Place,
+ Position = new Position (12, -24),
+ Label = "Test",
+ Address = "123 Test street"
+ };
+
+ Assert.True (pin1 == pin2);
+ }
+
+ [Test]
+ public void InEqualsOp () {
+ var pin1 = new Pin {
+ Type = PinType.Place,
+ Position = new Position (11.9, -24),
+ Label = "Test",
+ Address = "123 Test street"
+ };
+
+ var pin2 = new Pin {
+ Type = PinType.Place,
+ Position = new Position (12, -24),
+ Label = "Test",
+ Address = "123 Test street"
+ };
+
+ Assert.True (pin1 != pin2);
+ }
+
+ [Test]
+ public void Label ()
+ {
+ var pin = new Pin {
+ Label = "OriginalLabel"
+ };
+
+ bool signaled = false;
+ pin.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "Label")
+ signaled = true;
+ };
+
+ pin.Label = "Should Signal";
+
+ Assert.True (signaled);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/PinchGestureRecognizerTests.cs b/Xamarin.Forms.Core.UnitTests/PinchGestureRecognizerTests.cs
new file mode 100644
index 00000000..3af55035
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/PinchGestureRecognizerTests.cs
@@ -0,0 +1,75 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ public class PinchGestureRecognizerTests : BaseTestFixture
+ {
+ [Test]
+ public void Constructor ()
+ {
+ var pinch = new PinchGestureRecognizer ();
+
+ }
+
+ [Test]
+ public void PinchStartedTest ()
+ {
+ var view = new View ();
+ var pinch = new PinchGestureRecognizer ();
+
+ GestureStatus result = GestureStatus.Canceled;
+ var point = new Point (10, 10);
+ var resultPoint = Point.Zero;
+ pinch.PinchUpdated += (object sender, PinchGestureUpdatedEventArgs e) => {
+ result = e.Status;
+ resultPoint = e.ScaleOrigin;
+ };
+
+ ((IPinchGestureController)pinch).SendPinchStarted (view,point);
+ Assert.AreEqual (GestureStatus.Started, result);
+ Assert.AreEqual (point, resultPoint);
+ }
+
+ [Test]
+ public void PinchCompletedTest ()
+ {
+ var view = new View ();
+ var pinch = new PinchGestureRecognizer ();
+
+ GestureStatus result = GestureStatus.Canceled;
+ pinch.PinchUpdated += (object sender, PinchGestureUpdatedEventArgs e) => {
+ result = e.Status;
+ };
+
+ ((IPinchGestureController)pinch).SendPinchEnded (view);
+ Assert.AreEqual (GestureStatus.Completed, result);
+ }
+
+ [Test]
+ public void PinchUpdatedTest ()
+ {
+ var view = new View ();
+ var pinch = new PinchGestureRecognizer ();
+ var point = new Point (10, 10);
+ var resultPoint = Point.Zero;
+ double result = -1;
+ pinch.PinchUpdated += (object sender, PinchGestureUpdatedEventArgs e) => {
+ result = e.Scale;
+ resultPoint = e.ScaleOrigin;
+ };
+
+ ((IPinchGestureController)pinch).SendPinch (view, 2, point);
+ Assert.AreEqual (2, result);
+ }
+
+ [Test]
+ public void OnlyOnePinchGesturePerViewTest ()
+ {
+ var view = new View ();
+ view.GestureRecognizers.Add(new PinchGestureRecognizer ());
+ Assert.Throws<InvalidOperationException> (() => view.GestureRecognizers.Add (new PinchGestureRecognizer ()));
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Core.UnitTests/PointTests.cs b/Xamarin.Forms.Core.UnitTests/PointTests.cs
new file mode 100644
index 00000000..40a31b81
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/PointTests.cs
@@ -0,0 +1,121 @@
+using System;
+using NUnit.Framework;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class PointTests : BaseTestFixture
+ {
+ [Test]
+ public void TestPointEquality ()
+ {
+ Assert.True (new Point (0, 1) != new Point (1, 0));
+ Assert.True (new Point (5, 5) == new Point (5, 5));
+ }
+
+ [Test]
+ public void TestPointDistance ()
+ {
+ Assert.That (new Point (2, 2).Distance (new Point (5, 6)), Is.EqualTo (5).Within (0.001));
+ }
+
+ [Test]
+ public void TestPointMath ()
+ {
+ var point = new Point (2, 3) + new Size (3, 2);
+ Assert.AreEqual (new Point (5, 5), point);
+
+ point = new Point (3, 4) - new Size (2, 3);
+ Assert.AreEqual (new Point (1, 1), point);
+ }
+
+ [Test]
+ public void TestPointFromSize ()
+ {
+ var point = new Point (new Size (10, 20));
+
+ Assert.AreEqual (10, point.X);
+ Assert.AreEqual (20, point.Y);
+ }
+
+ [Test]
+ public void TestPointOffset ()
+ {
+ var point = new Point (2, 2);
+
+ point = point.Offset (10, 20);
+
+ Assert.AreEqual (new Point (12, 22), point);
+ }
+
+ [Test]
+ public void TestPointRound ()
+ {
+ var point = new Point (2.4, 2.7);
+ point = point.Round ();
+
+ Assert.AreEqual (Math.Round (2.4), point.X);
+ Assert.AreEqual (Math.Round (2.7), point.Y);
+ }
+
+ [Test]
+ public void TestPointEmpty ()
+ {
+ var point = new Point ();
+
+ Assert.True (point.IsEmpty);
+ }
+
+ [Test]
+ public void TestPointHashCode ([Range (3, 6)] double x1, [Range (3, 6)] double y1, [Range (3, 6)] double x2,
+ [Range (3, 6)] double y2)
+ {
+ bool result = new Point (x1, y1).GetHashCode () == new Point (x2, y2).GetHashCode ();
+ if (x1 == x2 && y1 == y2)
+ Assert.True (result);
+ else
+ Assert.False (result);
+ }
+
+ [Test]
+ public void TestSizeFromPoint ()
+ {
+ var point = new Point (2, 4);
+ var size = (Size) point;
+
+ Assert.AreEqual (new Size (2, 4), size);
+ }
+
+ [Test]
+ public void TestPointEquals ()
+ {
+ var point = new Point (2, 4);
+
+ Assert.True (point.Equals (new Point (2, 4)));
+ Assert.False (point.Equals (new Point (3, 4)));
+ Assert.False (point.Equals ("Point"));
+ }
+
+ [Test]
+ [TestCase (0, 0, ExpectedResult = "{X=0 Y=0}")]
+ [TestCase (5, 2, ExpectedResult = "{X=5 Y=2}")]
+ public string TestPointToString (double x, double y)
+ {
+ return new Point (x, y).ToString ();
+ }
+
+ [Test]
+ public void TestPointTypeConverter ()
+ {
+ var converter = new PointTypeConverter ();
+ Assert.True (converter.CanConvertFrom (typeof(string)));
+ Assert.AreEqual (new Point (1, 2), converter.ConvertFromInvariantString ("1,2"));
+ Assert.AreEqual (new Point (1, 2), converter.ConvertFromInvariantString ("1, 2"));
+ Assert.AreEqual (new Point (1, 2), converter.ConvertFromInvariantString (" 1 , 2 "));
+ Assert.AreEqual (new Point (1.1, 2), converter.ConvertFromInvariantString ("1.1,2"));
+ Assert.Throws<InvalidOperationException> (()=>converter.ConvertFromInvariantString (""));
+ }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/PositionTests.cs b/Xamarin.Forms.Core.UnitTests/PositionTests.cs
new file mode 100644
index 00000000..aec845ed
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/PositionTests.cs
@@ -0,0 +1,89 @@
+using System;
+using NUnit.Framework;
+using Xamarin.Forms.Maps;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class PositionTests : BaseTestFixture
+ {
+ [Test]
+ public void Construction ()
+ {
+ Position position = new Position();
+ Assert.AreEqual (position.Latitude, 0);
+ Assert.AreEqual (position.Longitude, 0);
+ }
+
+ [Test]
+ public void CopyConstructor ()
+ {
+ var position = new Position (12, 13);
+ var copy = position;
+
+ Assert.AreEqual (12, copy.Latitude);
+ Assert.AreEqual (13, copy.Longitude);
+ }
+
+ [Test]
+ public void EqualityOp ()
+ {
+ var position1 = new Position (-28, 180);
+ var position2 = new Position (-28, 180);
+ Assert.True (position1 == position2);
+ }
+
+ [Test]
+ public void InEqualityOp()
+ {
+ var position1 = new Position (-8, 180);
+ var position2 = new Position (-28, 180);
+ Assert.True(position1 != position2);
+ }
+
+
+ [Test]
+ public void Equals ()
+ {
+ var position1 = new Position (78, 167);
+ var position2 = new Position (78, 167);
+ Assert.True (position1.Equals (position2));
+ Assert.False (position2.Equals (null));
+ Assert.True (position2.Equals (position2));
+ Assert.False (position2.Equals ("position2"));
+ }
+
+ [Test]
+ public void LatitudeClamping () {
+ var position = new Position (-90.1, 0);
+ Assert.AreEqual (position.Latitude, -90);
+
+ position = new Position (165, 0);
+ Assert.AreEqual (position.Latitude, 90);
+
+ position = new Position (15.0, 0);
+ Assert.AreEqual (position.Latitude, 15.0);
+ }
+
+ [Test]
+ public void LongitudeClamping () {
+ var position = new Position (0, -180.001);
+ Assert.AreEqual (position.Longitude, -180.0);
+
+ position = new Position (0, 1000);
+ Assert.AreEqual (position.Longitude, 180);
+
+ position = new Position (0, 0);
+ Assert.AreEqual (position.Longitude, 0);
+ }
+
+ [Test]
+ public void Hashcode ()
+ {
+ var position = new Position (20, 25);
+ var position2 = new Position (25, 20);
+ Assert.AreNotEqual (position.GetHashCode (), position2.GetHashCode ());
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ProgressBarTests.cs b/Xamarin.Forms.Core.UnitTests/ProgressBarTests.cs
new file mode 100644
index 00000000..2af7eac0
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ProgressBarTests.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ProgressBarTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ Ticker.Default = new BlockingTicker ();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ Ticker.Default = null;
+ }
+
+ [Test]
+ public void TestClamp ()
+ {
+ ProgressBar bar = new ProgressBar ();
+
+ bar.Progress = 2;
+ Assert.AreEqual (1, bar.Progress);
+
+ bar.Progress = -1;
+ Assert.AreEqual (0, bar.Progress);
+ }
+
+ [Test]
+ public void TestProgressTo ()
+ {
+ var bar = new ProgressBar ();
+
+ bar.ProgressTo (0.8, 250, Easing.Linear);
+
+ Assert.That (bar.Progress, Is.EqualTo (0.8).Within (0.001));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/Properties/AssemblyInfo.cs b/Xamarin.Forms.Core.UnitTests/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..51c143e2
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/Properties/AssemblyInfo.cs
@@ -0,0 +1,27 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("Xamarin.Forms.Core.UnitTests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Xamarin Inc.")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Xamarin Inc.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
diff --git a/Xamarin.Forms.Core.UnitTests/RectangleUnitTests.cs b/Xamarin.Forms.Core.UnitTests/RectangleUnitTests.cs
new file mode 100644
index 00000000..722020bb
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/RectangleUnitTests.cs
@@ -0,0 +1,208 @@
+using NUnit.Framework;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class RectangleUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestRectangleConstruction ()
+ {
+ var rect = new Rectangle ();
+ Assert.AreEqual (0, rect.X);
+ Assert.AreEqual (0, rect.Y);
+ Assert.AreEqual (0, rect.Width);
+ Assert.AreEqual (0, rect.Height);
+
+ rect = new Rectangle (2, 3, 4, 5);
+ Assert.AreEqual (2, rect.X);
+ Assert.AreEqual (3, rect.Y);
+ Assert.AreEqual (4, rect.Width);
+ Assert.AreEqual (5, rect.Height);
+
+ rect = new Rectangle (new Point (2, 3), new Size (4, 5));
+ Assert.AreEqual (2, rect.X);
+ Assert.AreEqual (3, rect.Y);
+ Assert.AreEqual (4, rect.Width);
+ Assert.AreEqual (5, rect.Height);
+ }
+
+ [Test]
+ public void TestRectangleFromLTRB ()
+ {
+ var rect = Rectangle.FromLTRB (10, 10, 30, 40);
+
+ Assert.AreEqual (new Rectangle (10, 10, 20, 30), rect);
+ }
+
+ [Test]
+ public void TestRectangleCalculatedPoints ()
+ {
+ var rect = new Rectangle (2, 3, 4, 5);
+ Assert.AreEqual (2, rect.Left);
+ Assert.AreEqual (3, rect.Top);
+ Assert.AreEqual (6, rect.Right);
+ Assert.AreEqual (8, rect.Bottom);
+
+ Assert.AreEqual (new Size (4, 5), rect.Size);
+ Assert.AreEqual (new Point (2, 3), rect.Location);
+
+ Assert.AreEqual (new Point (4, 5.5), rect.Center);
+
+ rect.Left = 1;
+ Assert.AreEqual (1, rect.X);
+
+ rect.Right = 3;
+ Assert.AreEqual (2, rect.Width);
+
+ rect.Top = 1;
+ Assert.AreEqual (1, rect.Y);
+
+ rect.Bottom = 2;
+ Assert.AreEqual (1, rect.Height);
+ }
+
+ [Test]
+ public void TestRectangleContains ()
+ {
+ var rect = new Rectangle (0, 0, 10, 10);
+ Assert.True (rect.Contains (5, 5));
+ Assert.True (rect.Contains (new Point (5, 5)));
+ Assert.True (rect.Contains (new Rectangle (1, 1, 3, 3)));
+
+ Assert.True (rect.Contains (0, 0));
+ Assert.False (rect.Contains (10, 10));
+ }
+
+ [Test]
+ public void TestRectangleInflate ()
+ {
+ var rect = new Rectangle (0, 0, 10, 10);
+ rect = rect.Inflate (5, 5);
+
+ Assert.AreEqual (new Rectangle (-5, -5, 20, 20), rect);
+
+ rect = rect.Inflate (new Size (-5, -5));
+
+ Assert.AreEqual (new Rectangle (0, 0, 10, 10), rect);
+ }
+
+ [Test]
+ public void TestRectangleOffset ()
+ {
+ var rect = new Rectangle (0, 0, 10, 10);
+ rect = rect.Offset (10, 10);
+
+ Assert.AreEqual (new Rectangle (10, 10, 10, 10), rect);
+
+ rect = rect.Offset (new Point (-10, -10));
+
+ Assert.AreEqual (new Rectangle (0, 0, 10, 10), rect);
+ }
+
+ [Test]
+ public void TestRectangleRound ()
+ {
+ var rect = new Rectangle (0.2, 0.3, 0.6, 0.7);
+
+ Assert.AreEqual (new Rectangle (0, 0, 1, 1), rect.Round ());
+ }
+
+ [Test]
+ public void TestRectangleIntersect ()
+ {
+ var rect1 = new Rectangle (0, 0, 10, 10);
+
+ var rect2 = new Rectangle (2, 2, 6, 6);
+
+ var intersection = rect1.Intersect (rect2);
+
+ Assert.AreEqual (rect2, intersection);
+
+ rect2 = new Rectangle(2, 2, 12, 12);
+ intersection = rect1.Intersect (rect2);
+
+ Assert.AreEqual (new Rectangle (2, 2, 8, 8), intersection);
+
+ rect2 = new Rectangle (20, 20, 2, 2);
+ intersection = rect1.Intersect (rect2);
+
+ Assert.AreEqual (Rectangle.Zero, intersection);
+ }
+
+ [Test]
+ [TestCase(0, 0, ExpectedResult = true)]
+ [TestCase(0, 5, ExpectedResult = true)]
+ [TestCase(5, 0, ExpectedResult = true)]
+ [TestCase(2, 3, ExpectedResult = false)]
+ public bool TestIsEmpty (int w, int h)
+ {
+ return new Rectangle (0, 0, w, h).IsEmpty;
+ }
+
+ [Test]
+ [TestCase(0, 0, 8, 8, 0, 0, 5, 5, ExpectedResult = true)]
+ [TestCase(0, 0, 5, 5, 5, 5, 5, 5, ExpectedResult = false)]
+ [TestCase(0, 0, 2, 2, 3, 0, 5, 5, ExpectedResult = false)]
+ public bool TestIntersectsWith (double x1, double y1, double w1, double h1, double x2, double y2, double w2, double h2)
+ {
+ return new Rectangle (x1, y1, w1, h1).IntersectsWith (new Rectangle (x2, y2, w2, h2));
+ }
+
+ [Test]
+ public void TestSetSize ()
+ {
+ var rect = new Rectangle ();
+ rect.Size = new Size (10, 20);
+
+ Assert.AreEqual (new Rectangle (0, 0, 10, 20), rect);
+ }
+
+ [Test]
+ public void TestSetLocation ()
+ {
+ var rect = new Rectangle ();
+ rect.Location = new Point (10, 20);
+
+ Assert.AreEqual (new Rectangle (10, 20, 0, 0), rect);
+ }
+
+ [Test]
+ public void TestUnion ()
+ {
+ Assert.AreEqual (new Rectangle (0, 3, 13, 10), new Rectangle (3, 3, 10, 10).Union (new Rectangle(0, 5, 2, 2)));
+ }
+
+ [Test]
+ [TestCase(0, 0, 2, 2, ExpectedResult = "{X=0 Y=0 Width=2 Height=2}")]
+ [TestCase(1, 0, 3, 2, ExpectedResult = "{X=1 Y=0 Width=3 Height=2}")]
+ public string TestRectangleToString (double x, double y, double w, double h)
+ {
+ return new Rectangle (x, y, w, h).ToString ();
+ }
+
+ [Test]
+ public void TestRectangleEquals ()
+ {
+ Assert.True (new Rectangle (0, 0, 10, 10).Equals (new Rectangle(0, 0, 10, 10)));
+ Assert.False (new Rectangle (0, 0, 10, 10).Equals ("Rectangle"));
+ Assert.False (new Rectangle (0, 0, 10, 10).Equals (null));
+
+ Assert.True (new Rectangle (0, 0, 10, 10) == new Rectangle (0, 0, 10, 10));
+ Assert.True (new Rectangle (0, 0, 10, 10) != new Rectangle (0, 0, 10, 5));
+ }
+
+ [Test]
+ public void TestRectangleGetHashCode ([Range(3, 4)] double x1, [Range(3, 4)] double y1, [Range(3, 4)] double w1, [Range(3, 4)] double h1,
+ [Range(3, 4)] double x2, [Range(3, 4)] double y2, [Range(3, 4)] double w2, [Range(3, 4)] double h2)
+ {
+ bool result = new Rectangle (x1, y1, w1, h1).GetHashCode () == new Rectangle (x2, y2, w2, h2).GetHashCode ();
+
+ if (x1 == x2 && y1 == y2 && w1 == w2 && h1 == h2)
+ Assert.True (result);
+ else
+ Assert.False (result);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/RegistrarUnitTests.cs b/Xamarin.Forms.Core.UnitTests/RegistrarUnitTests.cs
new file mode 100644
index 00000000..9758eaf0
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/RegistrarUnitTests.cs
@@ -0,0 +1,149 @@
+using System;
+using System.Reflection;
+using NUnit.Framework;
+using Xamarin.Forms;
+using Xamarin.Forms.Core.UnitTests;
+
+[assembly: TestHandler (typeof (Button), typeof (ButtonTarget))]
+[assembly: TestHandler (typeof (Slider), typeof (SliderTarget))]
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ internal class TestHandlerAttribute : HandlerAttribute
+ {
+ public TestHandlerAttribute (Type handler, Type target) : base (handler, target)
+ {
+
+ }
+ }
+
+ internal class ButtonTarget : IRegisterable {}
+
+ internal class SliderTarget : IRegisterable {}
+
+ [TestFixture]
+ public class RegistrarTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup ()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ Registrar.RegisterAll (new [] {
+ typeof (TestHandlerAttribute)
+ });
+
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void GetButtonHandler ()
+ {
+ var buttonTarget = Registrar.Registered.GetHandler<ButtonTarget> (typeof (Button));
+ Assert.IsNotNull (buttonTarget);
+ Assert.That (buttonTarget, Is.InstanceOf<ButtonTarget>());
+ }
+
+ [Test]
+ public void GetSliderHandler()
+ {
+ var sliderTarget = Registrar.Registered.GetHandler<SliderTarget> (typeof (Slider));
+ Assert.IsNotNull (sliderTarget);
+ Assert.That (sliderTarget, Is.InstanceOf<SliderTarget> ());
+ }
+ }
+
+ [TestFixture]
+ public class SimpleRegistrarUnitTests
+ {
+ class MockRenderer {}
+ class ButtonMockRenderer : MockRenderer {}
+ class ShinyButtonMockRenderer : MockRenderer {}
+ class CrashMockRenderer : MockRenderer
+ {
+ public CrashMockRenderer ()
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ [Test]
+ public void TestConstructor ()
+ {
+ var registrar = new Registrar<MockRenderer> ();
+
+ var renderer = registrar.GetHandler (typeof (Button));
+
+ Assert.Null (renderer);
+ }
+
+ [Test]
+ public void TestGetRendererForKnownClass ()
+ {
+ var registrar = new Registrar<MockRenderer> ();
+
+ registrar.Register (typeof(View), typeof(MockRenderer));
+
+ var renderer = registrar.GetHandler (typeof (View));
+
+ Assert.That (renderer, Is.InstanceOf<MockRenderer>());
+ }
+
+ [Test]
+ public void TestGetRendererForUnknownSubclass ()
+ {
+ var registrar = new Registrar<MockRenderer> ();
+
+ registrar.Register (typeof (View), typeof (MockRenderer));
+
+ var renderer = registrar.GetHandler (typeof (Button));
+
+ Assert.That (renderer, Is.InstanceOf<MockRenderer>());
+ }
+
+ [Test]
+ public void TestGetRendererWithRegisteredSubclass ()
+ {
+ var registrar = new Registrar<MockRenderer> ();
+
+ registrar.Register (typeof (View), typeof (MockRenderer));
+ registrar.Register (typeof (Button), typeof (ButtonMockRenderer));
+
+ var buttonRenderer = registrar.GetHandler (typeof (Button));
+ var viewRenderer = registrar.GetHandler (typeof (View));
+
+ Assert.That (buttonRenderer, Is.InstanceOf<ButtonMockRenderer>());
+ Assert.That (viewRenderer, Is.Not.InstanceOf<ButtonMockRenderer>());
+ Assert.That (viewRenderer, Is.InstanceOf<MockRenderer>());
+ }
+
+ [Test]
+ public void TestReplaceRenderer ()
+ {
+ var registrar = new Registrar<MockRenderer> ();
+
+ registrar.Register (typeof (View), typeof (MockRenderer));
+ registrar.Register (typeof (Button), typeof (ButtonMockRenderer));
+ registrar.Register (typeof (Button), typeof (ShinyButtonMockRenderer));
+
+ var buttonRenderer = registrar.GetHandler (typeof (Button));
+
+ Assert.That (buttonRenderer, Is.InstanceOf<ShinyButtonMockRenderer>());
+ }
+
+ [Test]
+ public void GetHandlerType()
+ {
+ var registrar = new Registrar<MockRenderer>();
+ registrar.Register (typeof (View), typeof (MockRenderer));
+
+ Assert.AreEqual (typeof (MockRenderer), registrar.GetHandlerType (typeof (View)));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/RelativeLayoutTests.cs b/Xamarin.Forms.Core.UnitTests/RelativeLayoutTests.cs
new file mode 100644
index 00000000..96b3dfc8
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/RelativeLayoutTests.cs
@@ -0,0 +1,516 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class RelativeLayoutTests : BaseTestFixture
+ {
+ class UnitExpressionSearch : ExpressionVisitor, IExpressionSearch
+ {
+ List<object> results;
+ Type targeType;
+ public List<T> FindObjects<T>(Expression expression) where T : class
+ {
+ results = new List<object> ();
+ targeType = typeof (T);
+ Visit (expression);
+ return results.Select (o => o as T).ToList ();
+ }
+
+ protected override Expression VisitMember(MemberExpression node)
+ {
+ if (node.Expression is ConstantExpression && node.Member is FieldInfo) {
+ var container = ((ConstantExpression)node.Expression).Value;
+ var value = ((FieldInfo)node.Member).GetValue (container);
+
+ if (targeType.IsInstanceOfType (value)) {
+ results.Add (value);
+ }
+ }
+ return base.VisitMember (node);
+ }
+ }
+
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ ExpressionSearch.Default = new UnitExpressionSearch ();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ ExpressionSearch.Default = new UnitExpressionSearch ();
+ }
+
+ [Test]
+ public void SimpleLayout ()
+ {
+ var relativeLayout = new RelativeLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child,
+ Constraint.Constant (30),
+ Constraint.Constant (20),
+ Constraint.RelativeToParent (parent => parent.Height / 2),
+ Constraint.RelativeToParent (parent => parent.Height / 4));
+
+ relativeLayout.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (30, 20, 50, 25), child.Bounds);
+ }
+
+ [Test]
+ public void SimpleExpressionLayout ()
+ {
+ var relativeLayout = new RelativeLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child,
+ () => 30,
+ () => 20,
+ () => relativeLayout.Height / 2,
+ () => relativeLayout.Height / 4);
+
+ relativeLayout.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (30, 20, 50, 25), child.Bounds);
+ }
+
+ [Test]
+ public void SimpleBoundsSizing ()
+ {
+ var relativeLayout = new RelativeLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child, () => new Rectangle (30, 20, relativeLayout.Height / 2, relativeLayout.Height / 4));
+
+ relativeLayout.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (30, 20, 50, 25), child.Bounds);
+ }
+
+ [Test]
+ public void UnconstrainedSize()
+ {
+ var relativeLayout = new RelativeLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new View {
+ IsPlatformEnabled = true,
+ WidthRequest = 25,
+ HeightRequest = 50
+ };
+
+ relativeLayout.Children.Add (child, Constraint.Constant (30), Constraint.Constant (20));
+
+ relativeLayout.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (30, 20, 25, 50), child.Bounds);
+ }
+
+ [Test]
+ public void ViewRelativeLayout ()
+ {
+ var relativeLayout = new RelativeLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child1 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child1,
+ Constraint.Constant (30),
+ Constraint.Constant (20),
+ Constraint.RelativeToParent (parent => parent.Height / 5),
+ Constraint.RelativeToParent (parent => parent.Height / 10));
+
+ var child2 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child2,
+ Constraint.RelativeToView (child1, (layout, view) => view.Bounds.Right + 10),
+ Constraint.RelativeToView (child1, (layout, view) => view.Y),
+ Constraint.RelativeToView (child1, (layout, view) => view.Width),
+ Constraint.RelativeToView (child1, (layout, view) => view.Height));
+
+ relativeLayout.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (30, 20, 20, 10), child1.Bounds);
+ Assert.AreEqual (new Rectangle (60, 20, 20, 10), child2.Bounds);
+ }
+
+ [Test]
+ public void ViewRelativeLayoutWithExpressions()
+ {
+ var relativeLayout = new RelativeLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child1 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child1,
+ () => 30,
+ () => 20,
+ () => relativeLayout.Height / 5,
+ () => relativeLayout.Height / 10);
+
+ var child2 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child2,
+ () => child1.Bounds.Right + 10,
+ () => child1.Y,
+ () => child1.Width,
+ () => child1.Height);
+
+ relativeLayout.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (30, 20, 20, 10), child1.Bounds);
+ Assert.AreEqual (new Rectangle (60, 20, 20, 10), child2.Bounds);
+ }
+
+ [Test]
+ public void ViewRelativeToMultipleViews ()
+ {
+ var relativeLayout = new RelativeLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child1 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child1,
+ Constraint.Constant (30),
+ Constraint.Constant (20),
+ Constraint.RelativeToParent (parent => parent.Height / 5),
+ Constraint.RelativeToParent (parent => parent.Height / 10));
+
+ var child2 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child2,
+ Constraint.Constant (30),
+ Constraint.Constant (50),
+ Constraint.RelativeToParent (parent => parent.Height / 4),
+ Constraint.RelativeToParent (parent => parent.Height / 5));
+
+ var child3 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child3,
+ Constraint.RelativeToView (child1, (layout, view) => view.Bounds.Right + 10),
+ Constraint.RelativeToView (child2, (layout, view) => view.Y),
+ Constraint.RelativeToView (child1, (layout, view) => view.Width),
+ Constraint.RelativeToView (child2, (layout, view) => view.Height * 2));
+
+ relativeLayout.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (30, 20, 20, 10), child1.Bounds);
+ Assert.AreEqual (new Rectangle (30, 50, 25, 20), child2.Bounds);
+ Assert.AreEqual (new Rectangle (60, 50, 20, 40), child3.Bounds);
+ }
+
+ [Test]
+ public void ExpressionRelativeToMultipleViews()
+ {
+ var relativeLayout = new RelativeLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child1 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child1,
+ Constraint.Constant (30),
+ Constraint.Constant (20),
+ Constraint.RelativeToParent (parent => parent.Height / 5),
+ Constraint.RelativeToParent (parent => parent.Height / 10));
+
+ var child2 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child2,
+ Constraint.Constant (30),
+ Constraint.Constant (50),
+ Constraint.RelativeToParent (parent => parent.Height / 4),
+ Constraint.RelativeToParent (parent => parent.Height / 5));
+
+ var child3 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child3,
+ () => child1.Bounds.Right + 10,
+ () => child1.Y,
+ () => child1.Width + child2.Width,
+ () => child1.Height * 2 + child2.Height);
+
+ relativeLayout.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (30, 20, 20, 10), child1.Bounds);
+ Assert.AreEqual (new Rectangle (30, 50, 25, 20), child2.Bounds);
+ Assert.AreEqual (new Rectangle (60, 20, 45, 40), child3.Bounds);
+ }
+
+ [Test]
+ public void ThreePassLayout ()
+ {
+ var relativeLayout = new RelativeLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child1 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child1,
+ Constraint.Constant (30),
+ Constraint.Constant (20),
+ Constraint.RelativeToParent (parent => parent.Height / 5),
+ Constraint.RelativeToParent (parent => parent.Height / 10));
+
+ var child2 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child2,
+ Constraint.Constant (30),
+ Constraint.Constant (50),
+ Constraint.RelativeToParent (parent => parent.Height / 4),
+ Constraint.RelativeToParent (parent => parent.Height / 5));
+
+ var child3 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child3,
+ Constraint.RelativeToView (child1, (layout, view) => view.Bounds.Right + 10),
+ Constraint.RelativeToView (child2, (layout, view) => view.Y),
+ Constraint.RelativeToView (child1, (layout, view) => view.Width),
+ Constraint.RelativeToView (child2, (layout, view) => view.Height * 2));
+
+ var child4 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child4,
+ Constraint.RelativeToView (child1, (layout, view) => view.Bounds.Right + 10),
+ Constraint.RelativeToView (child2, (layout, view) => view.Y),
+ Constraint.RelativeToView (child1, (layout, view) => view.Width),
+ Constraint.RelativeToView (child3, (layout, view) => view.Height * 2));
+
+ relativeLayout.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (30, 20, 20, 10), child1.Bounds);
+ Assert.AreEqual (new Rectangle (30, 50, 25, 20), child2.Bounds);
+ Assert.AreEqual (new Rectangle (60, 50, 20, 40), child3.Bounds);
+ Assert.AreEqual (new Rectangle (60, 50, 20, 80), child4.Bounds);
+ }
+
+ [Test]
+ public void ThreePassLayoutWithExpressions()
+ {
+ var relativeLayout = new RelativeLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child1 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child1,
+ x: () => 30,
+ y: () => 20,
+ width: () => relativeLayout.Height / 5,
+ height: () => relativeLayout.Height / 10);
+
+ var child2 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child2,
+ x: () => 30,
+ y: () => 50,
+ width: () => relativeLayout.Height / 4,
+ height: () => relativeLayout.Height / 5);
+
+ var child3 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child3,
+ x: () => child1.Bounds.Right + 10,
+ y: () => child2.Y,
+ width: () => child1.Width,
+ height: () => child2.Height * 2);
+
+ var child4 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child4,
+ x: () => child1.Bounds.Right + 10,
+ y: () => child2.Y,
+ width: () => child1.Width,
+ height: () => child3.Height * 2);
+
+ relativeLayout.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (30, 20, 20, 10), child1.Bounds);
+ Assert.AreEqual (new Rectangle (30, 50, 25, 20), child2.Bounds);
+ Assert.AreEqual (new Rectangle (60, 50, 20, 40), child3.Bounds);
+ Assert.AreEqual (new Rectangle (60, 50, 20, 80), child4.Bounds);
+ }
+
+ [Test]
+ public void ThrowsWithUnsolvableConstraints ()
+ {
+ var relativeLayout = new RelativeLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child1 = new View {
+ IsPlatformEnabled = true
+ };
+
+ var child2 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child1,
+ () => 30,
+ () => 20,
+ () => child2.Height / 5,
+ () => relativeLayout.Height / 10);
+
+ relativeLayout.Children.Add (child2,
+ () => child1.Bounds.Right + 10,
+ () => child1.Y,
+ () => child1.Width,
+ () => child1.Height);
+
+ Assert.Throws<UnsolvableConstraintsException> (() => relativeLayout.Layout (new Rectangle (0, 0, 100, 100)));
+ }
+
+ [Test]
+ public void ChildAddedBeforeLayoutChildrenAfterInitialLayout ()
+ {
+ var relativeLayout = new MockRelativeLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ var child = new View {
+ IsPlatformEnabled = true
+ };
+
+ var child1 = new View {
+ IsPlatformEnabled = true
+ };
+
+ relativeLayout.Children.Add (child,
+ Constraint.Constant (30),
+ Constraint.Constant (20),
+ Constraint.RelativeToParent (parent => parent.Height / 2),
+ Constraint.RelativeToParent (parent => parent.Height / 4));
+
+
+ relativeLayout.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.IsTrue (relativeLayout.childAdded);
+ Assert.IsTrue (relativeLayout.added);
+ Assert.IsTrue (relativeLayout.layoutChildren);
+
+ relativeLayout.layoutChildren = relativeLayout.added = relativeLayout.childAdded = false;
+
+ Assert.IsFalse (relativeLayout.childAdded);
+ Assert.IsFalse (relativeLayout.added);
+ Assert.IsFalse (relativeLayout.layoutChildren);
+
+ relativeLayout.Children.Add (child1,
+ Constraint.Constant (30),
+ Constraint.Constant (20),
+ Constraint.RelativeToParent (parent => parent.Height / 2),
+ Constraint.RelativeToParent (parent => parent.Height / 4));
+
+ Assert.IsTrue (relativeLayout.childAdded);
+ Assert.IsTrue (relativeLayout.added);
+ Assert.IsTrue (relativeLayout.layoutChildren);
+
+ }
+ }
+
+ internal class MockRelativeLayout : RelativeLayout
+ {
+ internal bool layoutChildren;
+ internal bool childAdded;
+ internal bool added;
+
+ protected override void LayoutChildren (double x, double y, double width, double height)
+ {
+ if(added)
+ layoutChildren = true;
+
+ base.LayoutChildren (x, y, width, height);
+ }
+
+ protected override void OnAdded (View view)
+ {
+ if(childAdded)
+ added = true;
+ base.OnAdded (view);
+ }
+
+ protected override void OnChildAdded (Element child)
+ {
+ childAdded = true;
+ base.OnChildAdded (child);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ResourceDictionaryTests.cs b/Xamarin.Forms.Core.UnitTests/ResourceDictionaryTests.cs
new file mode 100644
index 00000000..d4229221
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ResourceDictionaryTests.cs
@@ -0,0 +1,256 @@
+using System;
+using System.Linq;
+using NUnit.Framework;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ResourceDictionaryTests : BaseTestFixture
+ {
+ [Test]
+ public void Add ()
+ {
+ var rd = new ResourceDictionary ();
+ rd.Add ("foo", "bar");
+ Assert.AreEqual ("bar", rd ["foo"]);
+ }
+
+ [Test]
+ public void AddKVP ()
+ {
+ var rd = new ResourceDictionary ();
+ ((ICollection<KeyValuePair<string,object>>)rd).Add (new KeyValuePair<string,object> ("foo", "bar"));
+ Assert.AreEqual ("bar", rd ["foo"]);
+ }
+
+ [Test]
+ public void ResourceDictionaryTriggersValueChangedOnAdd ()
+ {
+ var rd = new ResourceDictionary ();
+ ((IResourceDictionary)rd).ValuesChanged += (sender, e) => {
+ Assert.AreEqual (1, e.Values.Count());
+ var kvp = e.Values.First();
+ Assert.AreEqual ("foo", kvp.Key);
+ Assert.AreEqual ("FOO", kvp.Value);
+ Assert.Pass ();
+ };
+ rd.Add ("foo", "FOO");
+ Assert.Fail ();
+ }
+
+ [Test]
+ public void ResourceDictionaryTriggersValueChangedOnChange ()
+ {
+ var rd = new ResourceDictionary ();
+ rd.Add ("foo", "FOO");
+ ((IResourceDictionary)rd).ValuesChanged += (sender, e) => {
+ Assert.AreEqual (1, e.Values.Count());
+ var kvp = e.Values.First();
+ Assert.AreEqual ("foo", kvp.Key);
+ Assert.AreEqual ("BAR", kvp.Value);
+ Assert.Pass ();
+ };
+ rd ["foo"] = "BAR";
+ Assert.Fail ();
+ }
+
+ [Test]
+ public void ResourceDictionaryCtor ()
+ {
+ var rd = new ResourceDictionary ();
+ Assert.AreEqual (0, rd.Count());
+ }
+
+ [Test]
+ public void ElementMergesParentRDWithCurrent ()
+ {
+ var elt = new VisualElement {
+ Resources = new ResourceDictionary {
+ { "bar","BAR" },
+ }
+ };
+
+ var parent = new VisualElement {
+ Resources = new ResourceDictionary {
+ { "foo", "FOO" },
+ }
+ };
+
+ elt.Parent = parent;
+
+ object value;
+ Assert.True (elt.TryGetResource ("foo", out value));
+ Assert.AreEqual ("FOO", value);
+ Assert.True (elt.TryGetResource ("bar", out value));
+ Assert.AreEqual ("BAR", value);
+ }
+
+ [Test]
+ public void CurrentOverridesParentValues ()
+ {
+ var elt = new VisualElement {
+ Resources = new ResourceDictionary {
+ { "bar","BAZ" },
+ }
+ };
+
+ var parent = new VisualElement {
+ Resources = new ResourceDictionary {
+ { "foo", "FOO" },
+ { "bar","BAR" },
+ }
+ };
+
+ elt.Parent = parent;
+
+ object value;
+ Assert.True (elt.TryGetResource ("foo", out value));
+ Assert.AreEqual ("FOO", value);
+ Assert.True (elt.TryGetResource ("bar", out value));
+ Assert.AreEqual ("BAZ", value);
+ }
+
+ [Test]
+ public void AddingToParentTriggersValuesChanged ()
+ {
+ var elt = new VisualElement {
+ Resources = new ResourceDictionary {
+ { "bar","BAR" },
+ }
+ };
+
+ var parent = new VisualElement {
+ Resources = new ResourceDictionary {
+ { "foo", "FOO" },
+ }
+ };
+
+ elt.Parent = parent;
+
+ ((IElement)elt).AddResourcesChangedListener ((sender, e) => {
+ Assert.AreEqual (1, e.Values.Count ());
+ var kvp = e.Values.First ();
+ Assert.AreEqual ("baz", kvp.Key);
+ Assert.AreEqual ("BAZ", kvp.Value);
+ Assert.Pass ();
+ });
+
+ parent.Resources ["baz"] = "BAZ";
+ Assert.Fail ();
+ }
+
+ [Test]
+ public void ResourcesChangedNotRaisedIfKeyExistsInCurrent ()
+ {
+ var elt = new VisualElement {
+ Resources = new ResourceDictionary {
+ { "bar","BAR" },
+ }
+ };
+
+ var parent = new VisualElement {
+ Resources = new ResourceDictionary {
+ { "foo", "FOO" },
+ }
+ };
+
+ elt.Parent = parent;
+
+ ((IElement)elt).AddResourcesChangedListener ((sender, e) => Assert.Fail ());
+ parent.Resources ["bar"] = "BAZ";
+ Assert.Pass ();
+ }
+
+ [Test]
+ public void SettingParentTriggersValuesChanged ()
+ {
+ var elt = new VisualElement {
+ Resources = new ResourceDictionary {
+ { "bar","BAR" },
+ }
+ };
+
+ var parent = new VisualElement {
+ Resources = new ResourceDictionary {
+ {"foo", "FOO"},
+ {"baz", "BAZ"},
+ {"bar", "NEWBAR"}
+ }
+ };
+
+ ((IElement)elt).AddResourcesChangedListener ((sender, e) => {
+ Assert.AreEqual (2, e.Values.Count ());
+ Assert.AreEqual ("FOO", e.Values.First (kvp => kvp.Key == "foo").Value);
+ Assert.AreEqual ("BAZ", e.Values.First (kvp => kvp.Key == "baz").Value);
+ Assert.Pass ();
+ });
+ elt.Parent = parent;
+ Assert.Fail ();
+ }
+
+ [Test]
+ public void SettingResourcesTriggersResourcesChanged ()
+ {
+ var elt = new VisualElement ();
+
+ var parent = new VisualElement {
+ Resources = new ResourceDictionary {
+ {"bar", "BAR"}
+ }
+ };
+
+ elt.Parent = parent;
+
+ ((IElement)elt).AddResourcesChangedListener ((sender, e) => {
+ Assert.AreEqual (3, e.Values.Count ());
+ Assert.Pass ();
+ });
+ elt.Resources = new ResourceDictionary {
+ {"foo", "FOO"},
+ {"baz", "BAZ"},
+ {"bar", "NEWBAR"}
+ };
+ Assert.Fail();
+ }
+
+ [Test]
+ public void DontThrowOnReparenting ()
+ {
+ var elt = new View { Resources = new ResourceDictionary () };
+ var parent = new StackLayout ();
+
+ parent.Children.Add (elt);
+ Assert.DoesNotThrow (() => parent.Children.Remove (elt));
+ }
+
+ [Test]
+ public void MultiLevelMerge ()
+ {
+ var elt = new VisualElement {
+ Resources = new ResourceDictionary {
+ { "bar","BAR" },
+ }
+ };
+
+ var parent = new VisualElement {
+ Resources = new ResourceDictionary {
+ { "foo", "FOO" },
+ },
+ Parent = new VisualElement {
+ Resources = new ResourceDictionary {
+ {"baz", "BAZ"}
+ }
+ }
+ };
+
+ ((IElement)elt).AddResourcesChangedListener ((sender, e) => {
+ Assert.AreEqual (2, e.Values.Count ());
+ Assert.Pass ();
+ });
+
+ elt.Parent = parent;
+ Assert.Fail ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/ScrollViewUnitTests.cs b/Xamarin.Forms.Core.UnitTests/ScrollViewUnitTests.cs
new file mode 100644
index 00000000..066d4e5d
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ScrollViewUnitTests.cs
@@ -0,0 +1,403 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ScrollViewUnitTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void TestConstructor ()
+ {
+ ScrollView scrollView = new ScrollView ();
+
+ Assert.Null (scrollView.Content);
+
+ View view = new View ();
+ scrollView = new ScrollView {Content = view};
+
+ Assert.AreEqual (view, scrollView.Content);
+ }
+
+ [Test]
+ [TestCase (ScrollOrientation.Horizontal)]
+ [TestCase (ScrollOrientation.Both)]
+ public void GetsCorrectSizeRequestWithWrappingContent (ScrollOrientation orientation)
+ {
+ var scrollView = new ScrollView {
+ IsPlatformEnabled = true,
+ Orientation = orientation,
+ Platform = new UnitPlatform (null, true)
+ };
+
+ var hLayout = new StackLayout {
+ IsPlatformEnabled = true,
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ new Label {Text = "THIS IS A REALLY LONG STRING", IsPlatformEnabled = true},
+ new Label {Text = "THIS IS A REALLY LONG STRING", IsPlatformEnabled = true},
+ new Label {Text = "THIS IS A REALLY LONG STRING", IsPlatformEnabled = true},
+ new Label {Text = "THIS IS A REALLY LONG STRING", IsPlatformEnabled = true},
+ new Label {Text = "THIS IS A REALLY LONG STRING", IsPlatformEnabled = true},
+ }
+ };
+
+ scrollView.Content = hLayout;
+
+ var r = scrollView.GetSizeRequest (100, 100);
+
+ Assert.AreEqual (10, r.Request.Height);
+ }
+
+ [Test]
+ public void TestContentSizeChangedVertical ()
+ {
+ View view = new View {IsPlatformEnabled = true, WidthRequest = 100, HeightRequest = 100};
+
+ ScrollView scroll = new ScrollView {Content = view};
+ scroll.Platform = new UnitPlatform ();
+ scroll.Layout (new Rectangle (0, 0, 50, 50));
+
+ Assert.AreEqual (new Size (50, 100), scroll.ContentSize);
+
+ bool changed = false;
+ scroll.PropertyChanged += (sender, e) => {
+ switch (e.PropertyName) {
+ case "ContentSize":
+ changed = true;
+ break;
+ }
+ };
+
+ view.HeightRequest = 200;
+
+ Assert.True (changed);
+ Assert.AreEqual (new Size (50, 200), scroll.ContentSize);
+ }
+
+ [Test]
+ public void TestContentSizeChangedVerticalBidirectional ()
+ {
+ View view = new View { IsPlatformEnabled = true, WidthRequest = 100, HeightRequest = 100 };
+
+ ScrollView scroll = new ScrollView { Content = view, Orientation = ScrollOrientation.Both };
+ scroll.Platform = new UnitPlatform ();
+ scroll.Layout (new Rectangle (0, 0, 50, 50));
+
+ Assert.AreEqual (new Size (100, 100), scroll.ContentSize);
+
+ bool changed = false;
+ scroll.PropertyChanged += (sender, e) => {
+ switch (e.PropertyName) {
+ case "ContentSize":
+ changed = true;
+ break;
+ }
+ };
+
+ view.HeightRequest = 200;
+
+ Assert.True (changed);
+ Assert.AreEqual (new Size (100, 200), scroll.ContentSize);
+ }
+
+ [Test]
+ public void TestContentSizeChangedHorizontal ()
+ {
+ View view = new View {IsPlatformEnabled = true, WidthRequest = 100, HeightRequest = 100};
+
+ var scroll = new ScrollView {
+ Orientation = ScrollOrientation.Horizontal,
+ Content = view
+ };
+ scroll.Platform = new UnitPlatform ();
+ scroll.Layout (new Rectangle (0, 0, 50, 50));
+
+ Assert.AreEqual (new Size (100, 50), scroll.ContentSize);
+
+ bool changed = false;
+ scroll.PropertyChanged += (sender, e) => {
+ switch (e.PropertyName) {
+ case "ContentSize":
+ changed = true;
+ break;
+ }
+ };
+
+ view.WidthRequest = 200;
+
+ Assert.True (changed);
+ Assert.AreEqual (new Size (200, 50), scroll.ContentSize);
+ }
+
+ [Test]
+ public void TestContentSizeChangedHorizontalBidirectional ()
+ {
+ View view = new View { IsPlatformEnabled = true, WidthRequest = 100, HeightRequest = 100 };
+
+ var scroll = new ScrollView {
+ Orientation = ScrollOrientation.Both,
+ Content = view
+ };
+ scroll.Platform = new UnitPlatform ();
+ scroll.Layout (new Rectangle (0, 0, 50, 50));
+
+ Assert.AreEqual (new Size (100, 100), scroll.ContentSize);
+
+ bool changed = false;
+ scroll.PropertyChanged += (sender, e) => {
+ switch (e.PropertyName) {
+ case "ContentSize":
+ changed = true;
+ break;
+ }
+ };
+
+ view.WidthRequest = 200;
+
+ Assert.True (changed);
+ Assert.AreEqual (new Size (200, 100), scroll.ContentSize);
+ }
+
+ [Test]
+ public void TestContentSizeClamping ()
+ {
+ View view = new View {IsPlatformEnabled = true, WidthRequest = 100, HeightRequest = 100};
+
+ var scroll = new ScrollView {
+ Orientation = ScrollOrientation.Horizontal,
+ Content = view,
+ Platform = new UnitPlatform ()
+ };
+ scroll.Layout (new Rectangle (0, 0, 50, 50));
+
+ bool changed = false;
+ scroll.PropertyChanged += (sender, e) => {
+ switch (e.PropertyName) {
+ case "ContentSize":
+ changed = true;
+ break;
+ }
+ };
+
+ view.HeightRequest = 200;
+
+ Assert.False (changed);
+ Assert.AreEqual (new Size (100, 50), scroll.ContentSize);
+ }
+
+ [Test]
+ public void TestChildChanged ()
+ {
+ ScrollView scrollView = new ScrollView ();
+
+ bool changed = false;
+ scrollView.PropertyChanged += (sender, e) => {
+ switch (e.PropertyName) {
+ case "Content":
+ changed = true;
+ break;
+ }
+ };
+ View view = new View ();
+ scrollView.Content = view;
+
+ Assert.True (changed);
+ }
+
+ [Test]
+ public void TestChildDoubleSet ()
+ {
+ var scrollView = new ScrollView ();
+
+ bool changed = false;
+ scrollView.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "Content")
+ changed = true;
+ };
+
+ var child = new View ();
+ scrollView.Content = child;
+
+ Assert.True (changed);
+ Assert.AreEqual (child, scrollView.Content);
+
+ changed = false;
+
+ scrollView.Content = child;
+
+ Assert.False (changed);
+
+ scrollView.Content = null;
+
+ Assert.True (changed);
+ Assert.Null (scrollView.Content);
+ }
+
+ [Test]
+ public void TestOrientation ()
+ {
+ var scrollView = new ScrollView ();
+
+ Assert.AreEqual (ScrollOrientation.Vertical, scrollView.Orientation);
+
+ bool signaled = false;
+ scrollView.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "Orientation")
+ signaled = true;
+ };
+
+ scrollView.Orientation = ScrollOrientation.Horizontal;
+
+ Assert.AreEqual (ScrollOrientation.Horizontal, scrollView.Orientation);
+ Assert.True (signaled);
+
+ scrollView.Orientation = ScrollOrientation.Both;
+ Assert.AreEqual (ScrollOrientation.Both, scrollView.Orientation);
+ Assert.True (signaled);
+ }
+
+ [Test]
+ public void TestOrientationDoubleSet ()
+ {
+ var scrollView = new ScrollView ();
+
+ bool signaled = false;
+ scrollView.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == "Orientation")
+ signaled = true;
+ };
+
+ scrollView.Orientation = scrollView.Orientation;
+
+ Assert.False (signaled);
+ }
+
+
+ [Test]
+ public void TestScrollTo()
+ {
+ var scrollView = new ScrollView ();
+ scrollView.Platform = new UnitPlatform ();
+
+ var item = new View { };
+ scrollView.Content = new StackLayout { Children = { item } };
+
+ bool requested = false;
+ ((IScrollViewController) scrollView).ScrollToRequested += (sender, args) => {
+ requested = true;
+ Assert.AreEqual(args.ScrollY,100);
+ Assert.AreEqual(args.ScrollX,0);
+ Assert.Null (args.Item);
+ Assert.That (args.ShouldAnimate, Is.EqualTo (true));
+ };
+
+ scrollView.ScrollToAsync (0,100, true);
+ Assert.That (requested, Is.True);
+ }
+
+ [Test]
+ public void TestScrollToNotAnimated()
+ {
+ var scrollView = new ScrollView ();
+ scrollView.Platform = new UnitPlatform ();
+
+ var item = new View { };
+ scrollView.Content = new StackLayout { Children = { item } };
+
+ bool requested = false;
+ ((IScrollViewController) scrollView).ScrollToRequested += (sender, args) => {
+ requested = true;
+ Assert.AreEqual(args.ScrollY,100);
+ Assert.AreEqual(args.ScrollX,0);
+ Assert.Null (args.Item);
+ Assert.That (args.ShouldAnimate, Is.EqualTo (false));
+ };
+
+ scrollView.ScrollToAsync (0,100, false);
+ Assert.That (requested, Is.True);
+ }
+
+ [Test]
+ public void TestScrollToElement ()
+ {
+ var scrollView = new ScrollView ();
+ scrollView.Platform = new UnitPlatform ();
+
+ var item = new Label { Text = "Test" };
+ scrollView.Content = new StackLayout { Children = { item } };
+
+ bool requested = false;
+ ((IScrollViewController) scrollView).ScrollToRequested += (sender, args) => {
+ requested = true;
+
+ Assert.That (args.Element, Is.SameAs (item));
+ Assert.That (args.Position, Is.EqualTo (ScrollToPosition.Center));
+ Assert.That (args.ShouldAnimate, Is.EqualTo (true));
+ };
+
+ scrollView.ScrollToAsync (item, ScrollToPosition.Center, true);
+ Assert.That (requested, Is.True);
+ }
+
+ [Test]
+ public void TestScrollToElementNotAnimated ()
+ {
+ var scrollView = new ScrollView ();
+ scrollView.Platform = new UnitPlatform ();
+
+ var item = new Label { Text = "Test" };
+ scrollView.Content = new StackLayout { Children = { item } };
+
+ bool requested = false;
+ ((IScrollViewController) scrollView).ScrollToRequested += (sender, args) => {
+ requested = true;
+
+ Assert.That (args.Element, Is.SameAs (item));
+ Assert.That (args.Position, Is.EqualTo (ScrollToPosition.Center));
+ Assert.That (args.ShouldAnimate, Is.EqualTo (false));
+ };
+
+ scrollView.ScrollToAsync (item, ScrollToPosition.Center, false);
+ Assert.That (requested, Is.True);
+ }
+
+ [Test]
+ public void TestScrollToInvalid ()
+ {
+ var scrollView = new ScrollView ();
+ scrollView.Platform = new UnitPlatform ();
+
+ Assert.That (() => scrollView.ScrollToAsync (new VisualElement(), ScrollToPosition.Center, true), Throws.ArgumentException);
+ Assert.That (() => scrollView.ScrollToAsync (null, (ScrollToPosition) 500, true), Throws.ArgumentException);
+ }
+
+ [Test]
+ public void SetScrollPosition ()
+ {
+ var scroll = new ScrollView();
+ IScrollViewController controller = scroll;
+ controller.SetScrolledPosition (100, 100);
+
+ Assert.That (scroll.ScrollX, Is.EqualTo (100));
+ Assert.That (scroll.ScrollY, Is.EqualTo (100));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/SearchBarUnitTests.cs b/Xamarin.Forms.Core.UnitTests/SearchBarUnitTests.cs
new file mode 100644
index 00000000..a09aa429
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/SearchBarUnitTests.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class SearchBarUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestConstructor ()
+ {
+ SearchBar searchBar = new SearchBar ();
+
+ Assert.Null (searchBar.Placeholder);
+ Assert.Null (searchBar.Text);
+ }
+
+ [Test]
+ public void TestContentsChanged ()
+ {
+ SearchBar searchBar = new SearchBar ();
+
+ bool thrown = false;
+
+ searchBar.TextChanged += (sender, e) => thrown = true;
+
+ searchBar.Text = "Foo";
+
+ Assert.True (thrown);
+ }
+
+ [Test]
+ public void TestSearchButtonPressed ()
+ {
+ SearchBar searchBar = new SearchBar ();
+
+ bool thrown = false;
+ searchBar.SearchButtonPressed += (sender, e) => thrown = true;
+
+ searchBar.OnSearchButtonPressed ();
+
+ Assert.True (thrown);
+ }
+
+ [Test]
+ public void TestSearchCommandParameter ()
+ {
+ var searchBar = new SearchBar ();
+
+ object param = "Testing";
+ object result = null;
+ searchBar.SearchCommand = new Command (p => { result = p; });
+ searchBar.SearchCommandParameter = param;
+
+ searchBar.OnSearchButtonPressed ();
+
+ Assert.AreEqual (param, result);
+ }
+
+ [TestCase (null, "Text Changed")]
+ [TestCase ("Initial Text", null)]
+ [TestCase ("Initial Text", "Text Changed")]
+ public void SearchBarTextChangedEventArgs (string initialText, string finalText)
+ {
+ var searchBar = new SearchBar {
+ Text = initialText
+ };
+
+ SearchBar searchBarFromSender = null;
+ string oldText = null;
+ string newText = null;
+
+ searchBar.TextChanged += (s, e) => {
+ searchBarFromSender = (SearchBar)s;
+ oldText = e.OldTextValue;
+ newText = e.NewTextValue;
+ };
+
+ searchBar.Text = finalText;
+
+ Assert.AreEqual (searchBar, searchBarFromSender);
+ Assert.AreEqual (initialText, oldText);
+ Assert.AreEqual (finalText, newText);
+ }
+
+ [Test]
+ public void CommandCanExecuteUpdatesEnabled ()
+ {
+ var searchBar = new SearchBar ();
+
+ bool result = false;
+
+ var bindingContext = new {
+ Command = new Command (() => { }, () => result)
+ };
+
+ searchBar.SetBinding (SearchBar.SearchCommandProperty, "Command");
+ searchBar.BindingContext = bindingContext;
+
+ Assert.False (searchBar.IsEnabled);
+
+ result = true;
+
+ bindingContext.Command.ChangeCanExecute ();
+
+ Assert.True (searchBar.IsEnabled);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/SizeTests.cs b/Xamarin.Forms.Core.UnitTests/SizeTests.cs
new file mode 100644
index 00000000..d845d615
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/SizeTests.cs
@@ -0,0 +1,93 @@
+using NUnit.Framework;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class SizeTests : BaseTestFixture
+ {
+ [Test]
+ public void TestSizeIsZero ()
+ {
+ var size = new Size ();
+
+ Assert.True (size.IsZero);
+
+ size = new Size (10, 10);
+
+ Assert.False (size.IsZero);
+ }
+
+ [Test]
+ public void TestSizeAdd ()
+ {
+ var size1 = new Size (10, 10);
+ var size2 = new Size (20, 20);
+
+ var result = size1 + size2;
+
+ Assert.AreEqual (new Size (30, 30), result);
+ }
+
+ [Test]
+ public void TestSizeSubtract ()
+ {
+ var size1 = new Size (10, 10);
+ var size2 = new Size (2, 2);
+
+ var result = size1 - size2;
+
+ Assert.AreEqual (new Size (8, 8), result);
+ }
+
+ [Test]
+ public void TestPointFromSize ([Range(0, 2)] double x, [Range(0, 2)] double y)
+ {
+ var size = new Size (x, y);
+ var point = (Point) size;
+
+ Assert.AreEqual (x, point.X);
+ Assert.AreEqual (y, point.Y);
+ }
+
+ [Test]
+ public void HashCode ([Range(3, 5)] double w1, [Range(3, 5)] double h1, [Range(3, 5)] double w2, [Range(3, 5)] double h2)
+ {
+ bool result = new Size (w1, h1).GetHashCode () == new Size (w2, h2).GetHashCode ();
+
+ if (w1 == w2 && h1 == h2)
+ Assert.True (result);
+ else
+ Assert.False (result);
+ }
+
+ [Test]
+ public void Equality ()
+ {
+ Assert.False (new Size ().Equals (null));
+ Assert.False (new Size ().Equals ("Size"));
+ Assert.True (new Size (2, 3).Equals (new Size (2, 3)));
+
+ Assert.True (new Size (2, 3) == new Size (2, 3));
+ Assert.True (new Size (2, 3) != new Size (3, 2));
+ }
+
+ [Test]
+ [TestCase(0, 0, ExpectedResult = "{Width=0 Height=0}")]
+ [TestCase(1, 5, ExpectedResult = "{Width=1 Height=5}")]
+ public string TestToString (double w, double h)
+ {
+ return new Size (w, h).ToString ();
+ }
+
+ [Test]
+ public void MultiplyByScalar ([Range (12, 15)] int w, [Range (12, 15)] int h, [Values (0.0, 2.0, 7.0, 0.25)] double scalar)
+ {
+ var size = new Size (w, h);
+ var result = size * scalar;
+
+ Assert.AreEqual (w * scalar, result.Width);
+ Assert.AreEqual (h * scalar, result.Height);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/SliderUnitTests.cs b/Xamarin.Forms.Core.UnitTests/SliderUnitTests.cs
new file mode 100644
index 00000000..22ad75ba
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/SliderUnitTests.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class SliderUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestConstructor ()
+ {
+ var slider = new Slider (20, 200, 50);
+
+ Assert.AreEqual (20, slider.Minimum);
+ Assert.AreEqual (200, slider.Maximum);
+ Assert.AreEqual (50, slider.Value);
+ }
+
+ [Test]
+ public void TestInvalidConstructor ()
+ {
+ Assert.Throws<ArgumentOutOfRangeException> (() => new Slider (10, 5, 10));
+ }
+
+ [Test]
+ public void TestConstructorClamping ()
+ {
+ Slider slider = new Slider (50, 100, 0);
+
+ Assert.AreEqual (50, slider.Value);
+ }
+
+ [Test]
+ public void TestMinValueClamp ()
+ {
+ Slider slider = new Slider (0, 100, 0);
+
+ slider.Minimum = 10;
+
+ Assert.AreEqual (10, slider.Value);
+ Assert.AreEqual (10, slider.Minimum);
+ }
+
+ [Test]
+ public void TestMaxValueClamp ()
+ {
+ Slider slider = new Slider (0, 100, 100);
+
+ slider.Maximum = 10;
+
+ Assert.AreEqual (10, slider.Value);
+ Assert.AreEqual (10, slider.Maximum);
+ }
+
+ [Test]
+ public void TestInvalidMaxValue ()
+ {
+ var slider = new Slider ();
+ Assert.Throws<ArgumentException> (() => slider.Maximum = slider.Minimum - 1);
+ }
+
+ [Test]
+ public void TestInvalidMinValue ()
+ {
+ var slider = new Slider ();
+ Assert.Throws<ArgumentException> (() => slider.Minimum = slider.Maximum + 1);
+ }
+
+ [Test]
+ public void TestValueChanged ()
+ {
+ var slider = new Slider ();
+ var changed = false;
+
+ slider.ValueChanged += (sender, arg) => changed = true;
+
+ slider.Value += 1;
+
+ Assert.True (changed);
+ }
+
+ [TestCase (0.0, 1.0)]
+ [TestCase (1.0, 0.5)]
+ public void SliderValueChangedEventArgs (double initialValue, double finalValue)
+ {
+ var slider = new Slider {
+ Minimum = 0.0,
+ Maximum = 1.0,
+ Value = initialValue
+ };
+
+ Slider sliderFromSender = null;
+ double oldValue = 0.0;
+ double newValue = 0.0;
+
+ slider.ValueChanged += (s, e) => {
+ sliderFromSender = (Slider)s;
+ oldValue = e.OldValue;
+ newValue = e.NewValue;
+ };
+
+ slider.Value = finalValue;
+
+ Assert.AreEqual (slider, sliderFromSender);
+ Assert.AreEqual (initialValue, oldValue);
+ Assert.AreEqual (finalValue, newValue);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/StackLayoutUnitTests.cs b/Xamarin.Forms.Core.UnitTests/StackLayoutUnitTests.cs
new file mode 100644
index 00000000..fb4a8aac
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/StackLayoutUnitTests.cs
@@ -0,0 +1,619 @@
+using System.Collections;
+using System.Linq;
+using NUnit.Framework;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class StackLayoutUnitTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void EmptyLayoutDoesntCrash ()
+ {
+ var stackLayout = new StackLayout ();
+ stackLayout.Layout (new Rectangle (0, 0, 200, 200));
+ }
+
+ [Test]
+ public void TestLastChildNotVisible ()
+ {
+ View child1, child2;
+ var stack = new StackLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Children = {
+ (child1 = new View {WidthRequest = 20, HeightRequest = 20, IsPlatformEnabled = true}),
+ (child2 = new View {WidthRequest = 30, HeightRequest = 30, IsPlatformEnabled = true, IsVisible = false})
+ }
+ };
+
+ var r = stack.GetSizeRequest (100, 100);
+
+ Assert.AreEqual (new SizeRequest (new Size(20, 20)), r);
+ }
+
+ [Test]
+ public void TestLayoutVertical ()
+ {
+ View child1, child2;
+ var stack = new StackLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Children = {
+ (child1 = new View {WidthRequest = 20, HeightRequest = 20, IsPlatformEnabled = true}),
+ (child2 = new View {WidthRequest = 30, HeightRequest = 30, IsPlatformEnabled = true})
+ }
+ };
+
+ stack.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (0, 0, 100, 20), child1.Bounds);
+ Assert.AreEqual (new Rectangle (0, 26, 100, 30), child2.Bounds);
+ }
+
+ [Test]
+ public void ReinflatesViewsCorrectly ()
+ {
+ var child1 = new BoxView {
+ IsPlatformEnabled = true,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ HeightRequest = 400,
+ MinimumHeightRequest = 10
+ };
+
+ var child2 = new BoxView {
+ IsPlatformEnabled = true,
+ HeightRequest = 40,
+ MinimumHeightRequest = 40
+ };
+
+ var stack = new StackLayout {
+ Spacing = 0,
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Children = { child1, child2 }
+ };
+
+ stack.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (0, 0, 100, 60), child1.Bounds);
+ Assert.AreEqual (new Rectangle (0, 60, 100, 40), child2.Bounds);
+
+ stack.GetSizeRequest (100, 100);
+ stack.Layout (new Rectangle (0, 0, 100, 500));
+
+ Assert.AreEqual (new Rectangle (0, 0, 100, 460), child1.Bounds);
+ Assert.AreEqual (new Rectangle (0, 460, 100, 40), child2.Bounds);
+ }
+
+ [Test]
+ public void TestLayoutHorizontal ()
+ {
+ View child1, child2;
+ var stack = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Children = {
+ (child1 = new View {WidthRequest = 20, HeightRequest = 20, IsPlatformEnabled = true}),
+ (child2 = new View {WidthRequest = 30, HeightRequest = 30, IsPlatformEnabled = true})
+ }
+ };
+
+ stack.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (0, 0, 20, 100), child1.Bounds);
+ Assert.AreEqual (new Rectangle (26, 0, 30, 100), child2.Bounds);
+ }
+
+ [Test]
+ public void TestExpandVertical ()
+ {
+ View child1, child2, child3;
+ var stack = new StackLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Orientation = StackOrientation.Vertical,
+ Children = {
+ (child1 = new View {WidthRequest = 20, HeightRequest = 20, IsPlatformEnabled = true}),
+ (child2 = new View {
+ WidthRequest = 20,
+ HeightRequest = 20,
+ IsPlatformEnabled = true,
+ VerticalOptions = LayoutOptions.FillAndExpand
+ }),
+ (child3 = new View {WidthRequest = 20, HeightRequest = 20, IsPlatformEnabled = true})
+ }
+ };
+
+ stack.Padding = new Thickness (10, 5);
+ stack.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (10, 5, 80, 20), child1.Bounds);
+ Assert.AreEqual (new Rectangle (10, 31, 80, 100 - 2 * 31), child2.Bounds);
+ Assert.AreEqual (new Rectangle (10, 75, 80, 20), child3.Bounds);
+ }
+
+ [Test]
+ public void TestExpandHorizontal() {
+ View child1, child2, child3;
+ var stack = new StackLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ (child1 = new View {WidthRequest = 20, HeightRequest = 20, IsPlatformEnabled = true}),
+ (child2 = new View {
+ WidthRequest = 20,
+ HeightRequest = 20,
+ IsPlatformEnabled = true,
+ HorizontalOptions = LayoutOptions.FillAndExpand
+ }),
+ (child3 = new View {WidthRequest = 20, HeightRequest = 20, IsPlatformEnabled = true})
+ }
+ };
+
+ stack.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.AreEqual (new Rectangle (0, 0, 20, 100), child1.Bounds);
+ Assert.AreEqual (new Rectangle (26, 0, 100 - 2 * 26, 100), child2.Bounds);
+ Assert.AreEqual (new Rectangle (80, 0, 20, 100), child3.Bounds);
+ }
+
+ [Test]
+ public void TestSizeRequestVertical ()
+ {
+ var stack = new StackLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Children = {
+ new View {WidthRequest = 20, HeightRequest = 20, IsPlatformEnabled = true},
+ new View {WidthRequest = 30, HeightRequest = 30, IsPlatformEnabled = true}
+ }
+ };
+
+ var size = stack.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request;
+ Assert.AreEqual (new Size (30, 56), size);
+ }
+
+ [Test]
+ public void TestSizeRequestHorizontal ()
+ {
+ var stack = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Children = {
+ new View {WidthRequest = 20, HeightRequest = 20, IsPlatformEnabled = true},
+ new View {WidthRequest = 30, HeightRequest = 30, IsPlatformEnabled = true}
+ }
+ };
+
+ var size = stack.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request;
+ Assert.AreEqual (new Size (56, 30), size);
+ }
+
+ [Test]
+ public void HorizontalRequestInVerticalLayout ()
+ {
+ var stack = new StackLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Children = {
+ new View {WidthRequest = 20, HeightRequest = 30, IsPlatformEnabled = true, HorizontalOptions = LayoutOptions.Start},
+ new View {
+ WidthRequest = 20,
+ HeightRequest = 30,
+ IsPlatformEnabled = true,
+ HorizontalOptions = LayoutOptions.Center
+ },
+ new View {WidthRequest = 20, HeightRequest = 30, IsPlatformEnabled = true, HorizontalOptions = LayoutOptions.End}
+ }
+ };
+
+ stack.Layout (new Rectangle (0, 0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (0, 0, 20, 30), stack.Children[0].Bounds);
+ Assert.AreEqual (new Rectangle (90, 36, 20, 30), stack.Children[1].Bounds);
+ Assert.AreEqual (new Rectangle (180, 72, 20, 30), stack.Children[2].Bounds);
+ }
+
+ [Test]
+ public void VerticalRequestInHorizontalLayout ()
+ {
+ var stack = new StackLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ new View {WidthRequest = 20, HeightRequest = 30, IsPlatformEnabled = true, VerticalOptions = LayoutOptions.Start},
+ new View {WidthRequest = 20, HeightRequest = 30, IsPlatformEnabled = true, VerticalOptions = LayoutOptions.Center},
+ new View {WidthRequest = 20, HeightRequest = 30, IsPlatformEnabled = true, VerticalOptions = LayoutOptions.End}
+ }
+ };
+
+ stack.Layout (new Rectangle (0, 0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (0, 0, 20, 30), stack.Children.Cast<View>().ToArray()[0].Bounds);
+ Assert.AreEqual (new Rectangle (26, 85, 20, 30), stack.Children.Cast<View>().ToArray()[1].Bounds);
+ Assert.AreEqual (new Rectangle (52, 170, 20, 30), stack.Children.Cast<View>().ToArray()[2].Bounds);
+ }
+
+ [Test]
+ public void RespectMinimumHeightRequest ()
+ {
+ var stack = new StackLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Spacing = 10,
+ Children = {
+ new View {WidthRequest = 100, HeightRequest = 100, IsPlatformEnabled = true},
+ new View {WidthRequest = 100, HeightRequest = 100, IsPlatformEnabled = true},
+ new View {WidthRequest = 100, HeightRequest = 100, MinimumHeightRequest = 10, IsPlatformEnabled = true}
+ }
+ };
+
+ stack.Layout (new Rectangle (0, 0, 100, 250));
+
+ Assert.That (stack.Children.ToArray()[0].Bounds, Is.EqualTo (new Rectangle (0, 0, 100, 100)));
+ Assert.That (stack.Children.ToArray()[1].Bounds, Is.EqualTo (new Rectangle (0, 110, 100, 100)));
+ Assert.That (stack.Children.ToArray()[2].Bounds, Is.EqualTo (new Rectangle (0, 220, 100, 30)));
+ }
+
+ [Test]
+ public void RespectMinimumWidthRequest ()
+ {
+ var stack = new StackLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Orientation = StackOrientation.Horizontal,
+ Spacing = 10,
+ Children = {
+ new View {WidthRequest = 100, HeightRequest = 100, IsPlatformEnabled = true},
+ new View {WidthRequest = 100, HeightRequest = 100, IsPlatformEnabled = true},
+ new View {WidthRequest = 100, HeightRequest = 100, MinimumWidthRequest = 10, IsPlatformEnabled = true}
+ }
+ };
+
+ stack.Layout (new Rectangle (0, 0, 250, 100));
+
+ Assert.That (stack.Children.ToArray()[0].Bounds, Is.EqualTo (new Rectangle (0, 0, 100, 100)));
+ Assert.That (stack.Children.ToArray()[1].Bounds, Is.EqualTo (new Rectangle (110, 0, 100, 100)));
+ Assert.That (stack.Children.ToArray()[2].Bounds, Is.EqualTo (new Rectangle (220, 0, 30, 100)));
+ }
+
+ [Test]
+ public void GetMinimumSizeVertical ()
+ {
+ var stack = new StackLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Spacing = 10,
+ Children = {
+ new View {WidthRequest = 100, HeightRequest = 100, IsPlatformEnabled = true},
+ new View {WidthRequest = 100, HeightRequest = 100, IsPlatformEnabled = true},
+ new View {WidthRequest = 100, HeightRequest = 100, MinimumHeightRequest = 10, IsPlatformEnabled = true}
+ }
+ };
+
+ var result = stack.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+ Assert.That (result.Minimum, Is.EqualTo (new Size (100, 230)));
+ }
+
+ [Test]
+ public void GetMinimumSizeHorizontal ()
+ {
+ var stack = new StackLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Spacing = 10,
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ new View {WidthRequest = 100, HeightRequest = 100, IsPlatformEnabled = true},
+ new View {WidthRequest = 100, HeightRequest = 100, IsPlatformEnabled = true},
+ new View {WidthRequest = 100, HeightRequest = 100, MinimumWidthRequest = 10, IsPlatformEnabled = true}
+ }
+ };
+
+ var result = stack.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+ Assert.That (result.Minimum, Is.EqualTo (new Size (230, 100)));
+ }
+
+ [Test]
+ public void TestVisibility ()
+ {
+ View child1, child2;
+ var stack = new StackLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Children = {
+ (child1 = new View {IsPlatformEnabled = true}),
+ (child2 = new View {IsPlatformEnabled = true})
+ }
+ };
+
+ stack.Layout (new Rectangle (0, 0, 100, 100));
+
+ var size = stack.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request;
+ Assert.AreEqual (new Rectangle (0, 0, 100, 20), child1.Bounds);
+ Assert.AreEqual (new Rectangle (0, 26, 100, 20), child2.Bounds);
+ Assert.AreEqual (new Size (100, 46), size);
+
+ child1.IsVisible = false;
+ Assert.False (child1.IsVisible);
+ Assert.AreEqual (new Rectangle (0, 0, 100, 20), child2.Bounds);
+ size = stack.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request;
+ Assert.AreEqual (new Size (100, 20), size);
+
+ }
+
+ [Test]
+ public void OffOrientationMinimumSize ()
+ {
+ var stack = new StackLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Spacing = 0
+ };
+
+ stack.Children.Add (new View {
+ IsPlatformEnabled = true,
+ WidthRequest = 100,
+ HeightRequest = 100,
+ MinimumWidthRequest = 10,
+ MinimumHeightRequest = 10
+ });
+
+ var result = stack.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+ Assert.AreEqual (new Size (10, 10), result.Minimum);
+ }
+
+ [Test]
+ public void NestedMinimumSizeOverflow ()
+ {
+ var stack = new StackLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Spacing = 0
+ };
+
+ var hbox = new StackLayout {
+ IsPlatformEnabled = true,
+ Spacing = 0,
+ Orientation = StackOrientation.Horizontal
+ };
+
+ View child1, child2;
+ hbox.Children.Add (child1 = new View {
+ IsPlatformEnabled = true,
+ WidthRequest = 100,
+ HeightRequest = 100,
+ MinimumWidthRequest = 10,
+ MinimumHeightRequest = 10
+ });
+
+ hbox.Children.Add (child2 = new View {
+ IsPlatformEnabled = true,
+ WidthRequest = 100,
+ HeightRequest = 100,
+ MinimumWidthRequest = 10,
+ MinimumHeightRequest = 10
+ });
+
+ stack.Children.Add (hbox);
+
+ stack.Layout (new Rectangle (0, 0, 70, 70));
+ Assert.AreEqual (new Rectangle (0, 0, 70, 70), stack.Bounds);
+ Assert.AreEqual (new Rectangle (0, 0, 35, 70), child1.Bounds);
+ Assert.AreEqual (new Rectangle (35, 0, 35, 70), child2.Bounds);
+ }
+
+ [TestCase (StackOrientation.Vertical, LayoutAlignment.Start, false, 0, 0, 200, 100, 0, 100, 200, 10)]
+ [TestCase (StackOrientation.Vertical, LayoutAlignment.Start, true, 0, 0, 200, 100, 0, 190, 200, 10)]
+ [TestCase (StackOrientation.Vertical, LayoutAlignment.Center, false, 0, 0, 200, 100, 0, 100, 200, 10)]
+ [TestCase (StackOrientation.Vertical, LayoutAlignment.Center, true, 0, 45, 200, 100, 0, 190, 200, 10)]
+ [TestCase (StackOrientation.Vertical, LayoutAlignment.End, false, 0, 0, 200, 100, 0, 100, 200, 10)]
+ [TestCase (StackOrientation.Vertical, LayoutAlignment.End, true, 0, 90, 200, 100, 0, 190, 200, 10)]
+ [TestCase (StackOrientation.Horizontal, LayoutAlignment.Start, false, 0, 0, 100, 200, 100, 0, 10, 200)]
+ [TestCase (StackOrientation.Horizontal, LayoutAlignment.Start, true, 0, 0, 100, 200, 190, 0, 10, 200)]
+ [TestCase (StackOrientation.Horizontal, LayoutAlignment.Center, false, 0, 0, 100, 200, 100, 0, 10, 200)]
+ [TestCase (StackOrientation.Horizontal, LayoutAlignment.Center, true, 45, 0, 100, 200, 190, 0, 10, 200)]
+ [TestCase (StackOrientation.Horizontal, LayoutAlignment.End, false, 0, 0, 100, 200, 100, 0, 10, 200)]
+ [TestCase (StackOrientation.Horizontal, LayoutAlignment.End, true, 90, 0, 100, 200, 190, 0, 10, 200)]
+ public void LayoutExpansion(StackOrientation orientation, LayoutAlignment align, bool expand, double x1, double y1, double w1, double h1, double x2, double y2, double w2, double h2)
+ {
+ var options = new LayoutOptions (align, expand);
+ var stack = new StackLayout {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true,
+ Spacing = 0,
+ Orientation = orientation
+ };
+
+ View child1, child2;
+ stack.Children.Add (child1 = new View {
+ IsPlatformEnabled = true,
+ WidthRequest = 100,
+ HeightRequest = 100
+ });
+
+ if (orientation == StackOrientation.Vertical)
+ child1.VerticalOptions = options;
+ else
+ child1.HorizontalOptions = options;
+
+ stack.Children.Add (child2 = new View {
+ IsPlatformEnabled = true,
+ WidthRequest = 10,
+ HeightRequest = 10
+ });
+
+ stack.Layout (new Rectangle (0, 0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (x1, y1, w1, h1), child1.Bounds);
+ Assert.AreEqual (new Rectangle (x2, y2, w2, h2), child2.Bounds);
+ }
+
+ [Test]
+ public void RelayoutOnRemove ()
+ {
+ var child1 = new BoxView {
+ IsPlatformEnabled = true,
+ };
+
+ var child2 = new BoxView {
+ IsPlatformEnabled = true,
+ };
+
+ var stack = new StackLayout {
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform (),
+ Children = {child1, child2}
+ };
+
+ stack.Layout (new Rectangle (0, 0, 200, 200));
+
+ Assert.AreEqual (new Rectangle (0, 0, 200, 40), child1.Bounds);
+ Assert.AreEqual (new Rectangle (0, 46, 200, 40), child2.Bounds);
+
+ stack.Children.RemoveAt (0);
+
+ Assert.AreEqual (new Rectangle (0, 0, 200, 40), child2.Bounds);
+ }
+
+ [Test]
+ public void FixedVerticalStackFixesExpander ()
+ {
+ var child1 = new BoxView {
+ IsPlatformEnabled = true,
+ };
+
+ var child2 = new BoxView {
+ IsPlatformEnabled = true,
+ VerticalOptions = LayoutOptions.FillAndExpand
+ };
+
+ var stack = new StackLayout {
+ ComputedConstraint = LayoutConstraint.Fixed,
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform (),
+ Children = {child1, child2}
+ };
+
+ stack.Layout (new Rectangle (0, 0, 200, 200));
+
+ Assert.AreEqual (LayoutConstraint.Fixed, child2.Constraint);
+ }
+
+ [Test]
+ public void HFixedVerticalStackFixesExpander ()
+ {
+ var child1 = new BoxView {
+ IsPlatformEnabled = true,
+ };
+
+ var child2 = new BoxView {
+ IsPlatformEnabled = true,
+ VerticalOptions = LayoutOptions.FillAndExpand
+ };
+
+ var stack = new StackLayout {
+ ComputedConstraint = LayoutConstraint.HorizontallyFixed,
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform (),
+ Children = {child1, child2}
+ };
+
+ stack.Layout (new Rectangle (0, 0, 200, 200));
+
+ Assert.AreEqual (LayoutConstraint.HorizontallyFixed, child2.Constraint);
+ }
+
+ [Test]
+ public void FixedHorizontalStackFixesExpander ()
+ {
+ var child1 = new BoxView {
+ IsPlatformEnabled = true,
+ };
+
+ var child2 = new BoxView {
+ IsPlatformEnabled = true,
+ HorizontalOptions = LayoutOptions.FillAndExpand
+ };
+
+ var stack = new StackLayout {
+ ComputedConstraint = LayoutConstraint.Fixed,
+ Orientation = StackOrientation.Horizontal,
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform (),
+ Children = {child1, child2}
+ };
+
+ stack.Layout (new Rectangle (0, 0, 200, 200));
+
+ Assert.AreEqual (LayoutConstraint.Fixed, child2.Constraint);
+ }
+
+ [Test]
+ public void HFixedHorizontalStackFixesExpander ()
+ {
+ var child1 = new BoxView {
+ IsPlatformEnabled = true,
+ };
+
+ var child2 = new BoxView {
+ IsPlatformEnabled = true,
+ HorizontalOptions = LayoutOptions.FillAndExpand
+ };
+
+ var stack = new StackLayout {
+ ComputedConstraint = LayoutConstraint.VerticallyFixed,
+ Orientation = StackOrientation.Horizontal,
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform (),
+ Children = {child1, child2}
+ };
+
+ stack.Layout (new Rectangle (0, 0, 200, 200));
+
+ Assert.AreEqual (LayoutConstraint.VerticallyFixed, child2.Constraint);
+ }
+
+ [Ignore ("This test intended to test bz38416 however I just for the life of me cant figure it out in simplified form. I am failure.")]
+ [Test]
+ public void TheWTFTest ()
+ {
+ var child1 = new BoxView {
+ IsPlatformEnabled = true,
+ WidthRequest = 20,
+ HeightRequest = 20,
+ MinimumWidthRequest = 10,
+ MinimumHeightRequest = 10,
+ VerticalOptions = LayoutOptions.FillAndExpand
+ };
+
+ var stack = new StackLayout {
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform (),
+ Children = {child1}
+ };
+
+ stack.Layout (new Rectangle (0, 0, 100, 100));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/StepperUnitTests.cs b/Xamarin.Forms.Core.UnitTests/StepperUnitTests.cs
new file mode 100644
index 00000000..d011c7ab
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/StepperUnitTests.cs
@@ -0,0 +1,176 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class StepperUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestConstructor ()
+ {
+ var stepper = new Stepper (120, 200, 150, 2);
+
+ Assert.AreEqual (120, stepper.Minimum);
+ Assert.AreEqual (200, stepper.Maximum);
+ Assert.AreEqual (150, stepper.Value);
+ Assert.AreEqual (2, stepper.Increment);
+ }
+
+ [Test]
+ public void TestInvalidConstructor ()
+ {
+ Assert.Throws<ArgumentOutOfRangeException>(()=>new Stepper (100, 0, 50, 1));
+ }
+
+ [Test]
+ public void TestInvalidMaxValue ()
+ {
+ Stepper stepper = new Stepper ();
+ Assert.Throws<ArgumentException> (() => stepper.Maximum = stepper.Minimum - 1);
+ }
+
+ [Test]
+ public void TestInvalidMinValue ()
+ {
+ Stepper stepper = new Stepper ();
+ Assert.Throws<ArgumentException> (() => stepper.Minimum = stepper.Maximum + 1);
+ }
+
+ [Test]
+ public void TestValidMaxValue ()
+ {
+ Stepper stepper = new Stepper ();
+
+ stepper.Maximum = 2000;
+
+ Assert.AreEqual (2000, stepper.Maximum);
+ }
+
+ [Test]
+ public void TestValidMinValue ()
+ {
+ Stepper stepper = new Stepper ();
+
+ stepper.Maximum = 2000;
+ stepper.Minimum = 200;
+
+ Assert.AreEqual (200, stepper.Minimum);
+ }
+
+ [Test]
+ public void TestConstructorClampValue ()
+ {
+ Stepper stepper = new Stepper (0, 100, 2000, 1);
+
+ Assert.AreEqual (100, stepper.Value);
+
+ stepper = new Stepper (0, 100, -200, 1);
+
+ Assert.AreEqual (0, stepper.Value);
+ }
+
+ [Test]
+ public void TestMinClampValue ()
+ {
+ Stepper stepper = new Stepper ();
+
+ bool minThrown = false;
+ bool valThrown = false;
+
+ stepper.PropertyChanged += (sender, e) => {
+ switch (e.PropertyName) {
+ case "Minimum":
+ minThrown = true;
+ break;
+ case "Value":
+ Assert.False (minThrown);
+ valThrown = true;
+ break;
+ }
+ };
+
+ stepper.Minimum = 10;
+
+ Assert.AreEqual (10, stepper.Minimum);
+ Assert.AreEqual (10, stepper.Value);
+ Assert.True (minThrown);
+ Assert.True (valThrown);
+ }
+
+ [Test]
+ public void TestMaxClampValue ()
+ {
+ Stepper stepper = new Stepper ();
+
+ stepper.Value = 50;
+
+ bool maxThrown = false;
+ bool valThrown = false;
+
+ stepper.PropertyChanged += (sender, e) => {
+ switch (e.PropertyName) {
+ case "Maximum":
+ maxThrown = true;
+ break;
+ case "Value":
+ Assert.False (maxThrown);
+ valThrown = true;
+ break;
+ }
+ };
+
+ stepper.Maximum = 25;
+
+ Assert.AreEqual (25, stepper.Maximum);
+ Assert.AreEqual (25, stepper.Value);
+ Assert.True (maxThrown);
+ Assert.True (valThrown);
+ }
+
+ [Test]
+ public void TestValueChangedEvent ()
+ {
+ var stepper = new Stepper ();
+
+ bool fired = false;
+ stepper.ValueChanged += (sender, arg) => fired = true;
+
+ stepper.Value = 50;
+
+ Assert.True (fired);
+ }
+
+ [TestCase (100.0, 0.5)]
+ [TestCase (10.0, 25.0)]
+ [TestCase (0, 39.5)]
+ public void StepperValueChangedEventArgs (double initialValue, double finalValue)
+ {
+ var stepper = new Stepper {
+ Maximum = 100,
+ Minimum = 0,
+ Increment = 0.5,
+ Value = initialValue
+ };
+
+ Stepper stepperFromSender = null;
+ var oldValue = 0.0;
+ var newValue = 0.0;
+
+ stepper.ValueChanged += (s, e) => {
+ stepperFromSender = (Stepper)s;
+ oldValue = e.OldValue;
+ newValue = e.NewValue;
+ };
+
+ stepper.Value = finalValue;
+
+ Assert.AreEqual (stepper, stepperFromSender);
+ Assert.AreEqual (initialValue, oldValue);
+ Assert.AreEqual (finalValue, newValue);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/StyleTests.cs b/Xamarin.Forms.Core.UnitTests/StyleTests.cs
new file mode 100644
index 00000000..be1c7990
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/StyleTests.cs
@@ -0,0 +1,670 @@
+using NUnit.Framework;
+using System;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class StyleTests : BaseTestFixture
+ {
+ [Test]
+ public void ApplyUnapplyStyle ()
+ {
+ var style = new Style (typeof(VisualElement)) {
+ Setters = {
+ new Setter { Property = Label.TextProperty, Value = "foo" },
+ new Setter { Property = VisualElement.BackgroundColorProperty, Value = Color.Pink },
+ }
+ };
+
+ var label = new Label {
+ Style = style
+ };
+ Assert.AreEqual ("foo", label.Text);
+ Assert.AreEqual (Color.Pink, label.BackgroundColor);
+
+ label.Style = null;
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label.Text);
+ Assert.AreEqual (VisualElement.BackgroundColorProperty.DefaultValue, label.BackgroundColor);
+ }
+
+ [Test]
+ public void BindingAndDynamicResourcesInStyle ()
+ {
+ var style = new Style (typeof(VisualElement)) {
+ Setters = {
+ new Setter { Property = VisualElement.IsEnabledProperty, Value = false }
+ }
+ };
+ style.Setters.AddBinding (Label.TextProperty, new Binding ("foo"));
+ style.Setters.AddDynamicResource (VisualElement.BackgroundColorProperty, "qux");
+
+ var label = new Label {
+ Style = style
+ };
+
+ label.BindingContext = new {foo = "FOO"};
+ Assert.AreEqual ("FOO", label.Text);
+
+ label.Resources = new ResourceDictionary {
+ {"qux", Color.Pink}
+ };
+ Assert.AreEqual (Color.Pink, label.BackgroundColor);
+
+ label.Style = null;
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label.Text);
+ Assert.AreEqual (VisualElement.BackgroundColorProperty.DefaultValue, label.BackgroundColor);
+ }
+
+ [Test]
+ public void StyleCanBeAppliedMultipleTimes ()
+ {
+ var style = new Style (typeof(VisualElement)) {
+ Setters = {
+ new Setter{ Property = VisualElement.IsEnabledProperty, Value = false }
+ }
+ };
+ style.Setters.AddBinding (Label.TextProperty, new Binding ("foo"));
+ style.Setters.AddDynamicResource (VisualElement.BackgroundColorProperty, "qux");
+
+ var label0 = new Label {
+ Style = style
+ };
+ var label1 = new Label {
+ Style = style
+ };
+
+ label0.BindingContext = label1.BindingContext = new {foo = "FOO"};
+ label0.Resources = label1.Resources = new ResourceDictionary {
+ {"qux", Color.Pink}
+ };
+
+ Assert.AreEqual ("FOO", label0.Text);
+ Assert.AreEqual ("FOO", label1.Text);
+
+ Assert.AreEqual (Color.Pink, label0.BackgroundColor);
+ Assert.AreEqual (Color.Pink, label1.BackgroundColor);
+
+ label0.Style = label1.Style = null;
+
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label0.Text);
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label1.Text);
+ Assert.AreEqual (VisualElement.BackgroundColorProperty.DefaultValue, label0.BackgroundColor);
+ Assert.AreEqual (VisualElement.BackgroundColorProperty.DefaultValue, label1.BackgroundColor);
+ }
+
+ [Test]
+ public void BaseStyleIsAppliedUnapplied ()
+ {
+ var baseStyle = new Style (typeof(VisualElement)) {
+ Setters = {
+ new Setter { Property = Label.TextProperty, Value = "baseStyle" },
+ }
+ };
+ var style = new Style(typeof(Label)) {
+ BasedOn = baseStyle,
+ };
+
+ var label = new Label {
+ Style = style
+ };
+ Assert.AreEqual ("baseStyle", label.Text);
+
+ label.Style = null;
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label.Text);
+ }
+
+ [Test]
+ public void StyleOverrideBaseStyle ()
+ {
+ var baseStyle = new Style(typeof(VisualElement)) {
+ Setters = {
+ new Setter{Property= Label.TextProperty,Value= "baseStyle" },
+ }
+ };
+ var style = new Style(typeof(VisualElement)) {
+ BasedOn = baseStyle,
+ Setters = {
+ new Setter{Property= Label.TextProperty,Value= "style" },
+ }
+ };
+
+ var label = new Label {
+ Style = style
+ };
+ Assert.AreEqual ("style", label.Text);
+
+ label.Style = null;
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label.Text);
+ }
+
+ [Test]
+ public void AddImplicitStyleToResourceDictionary ()
+ {
+ var rd = new ResourceDictionary {
+ new Style (typeof(Label)) { Setters = {
+ new Setter { Property = Label.TextColorProperty, Value = Color.Pink },
+ }
+ },
+ { "foo", "FOO" },
+ {"labelStyle", new Style (typeof(Label)) { Setters = {
+ new Setter { Property = Label.TextColorProperty, Value = Color.Purple }
+ }
+ }
+ }
+ };
+
+ Assert.AreEqual (3, rd.Count);
+ Assert.Contains ("Xamarin.Forms.Label", (System.Collections.ICollection)rd.Keys);
+ }
+
+ [Test]
+ public void ImplicitStylesAreAppliedOnSettingRD ()
+ {
+ var rd = new ResourceDictionary {
+ new Style (typeof(Label)) { Setters = {
+ new Setter { Property = Label.TextColorProperty, Value = Color.Pink },
+ }
+ },
+ { "foo", "FOO" },
+ {"labelStyle", new Style (typeof(Label)) { Setters = {
+ new Setter { Property = Label.TextColorProperty, Value = Color.Purple }
+ }
+ }
+ }
+ };
+
+ var label = new Label ();
+ var layout = new StackLayout { Children = { label } };
+
+ Assert.AreEqual (label.TextColor, Label.TextColorProperty.DefaultValue);
+ layout.Resources = rd;
+ Assert.AreEqual (label.TextColor, Color.Pink);
+ }
+
+ [Test]
+ public void ImplicitStylesAreAppliedOnSettingParrent ()
+ {
+ var rd = new ResourceDictionary {
+ new Style (typeof(Label)) { Setters = {
+ new Setter { Property = Label.TextColorProperty, Value = Color.Pink },
+ }
+ },
+ { "foo", "FOO" },
+ {"labelStyle", new Style (typeof(Label)) { Setters = {
+ new Setter { Property = Label.TextColorProperty, Value = Color.Purple }
+ }
+ }
+ }
+ };
+
+ var label = new Label ();
+ var layout = new StackLayout ();
+ layout.Resources = rd;
+
+ Assert.AreEqual (label.TextColor, Label.TextColorProperty.DefaultValue);
+ layout.Children.Add (label);
+ Assert.AreEqual (label.TextColor, Color.Pink);
+ }
+
+ [Test]
+ public void ImplicitStylesOverridenByStyle ()
+ {
+ var rd = new ResourceDictionary {
+ new Style (typeof(Label)) { Setters = {
+ new Setter { Property = Label.TextColorProperty, Value = Color.Pink },
+ }
+ },
+ { "foo", "FOO" },
+ {"labelStyle", new Style (typeof(Label)) { Setters = {
+ new Setter { Property = Label.TextColorProperty, Value = Color.Purple }
+ }
+ }
+ }
+ };
+
+ var label = new Label ();
+ label.SetDynamicResource (VisualElement.StyleProperty, "labelStyle");
+ var layout = new StackLayout { Children = { label }, Resources = rd };
+
+ Assert.AreEqual (label.TextColor, Color.Purple);
+ }
+
+ [Test]
+ public void UnsettingStyleReApplyImplicit ()
+ {
+ var rd = new ResourceDictionary {
+ new Style (typeof(Label)) { Setters = {
+ new Setter { Property = Label.TextColorProperty, Value = Color.Pink },
+ }
+ },
+ { "foo", "FOO" },
+ {"labelStyle", new Style (typeof(Label)) { Setters = {
+ new Setter { Property = Label.TextColorProperty, Value = Color.Purple }
+ }
+ }
+ }
+ };
+
+ var label = new Label ();
+ label.SetDynamicResource (VisualElement.StyleProperty, "labelStyle");
+ var layout = new StackLayout { Children = { label }, Resources = rd };
+
+ Assert.AreEqual (label.TextColor, Color.Purple);
+ label.Style = null;
+ Assert.AreEqual (label.TextColor, Color.Pink);
+ }
+
+ [Test]
+ public void DynamicStyle ()
+ {
+ var baseStyle0 = new Style(typeof(Label)) {
+ Setters = {
+ new Setter {Property = Label.TextProperty, Value = "foo"},
+ new Setter {Property = Label.TextColorProperty, Value = Color.Pink}
+ }
+ };
+ var baseStyle1 = new Style(typeof(Label)) {
+ Setters = {
+ new Setter {Property = Label.TextProperty, Value = "bar"},
+ new Setter {Property = Label.TextColorProperty, Value = Color.Purple}
+ }
+ };
+ var style = new Style (typeof(Label)) {
+ BaseResourceKey = "basestyle",
+ Setters = {
+ new Setter { Property = Label.BackgroundColorProperty, Value = Color.Red },
+ new Setter { Property = Label.TextColorProperty, Value = Color.Red },
+ }
+ };
+
+ var label0 = new Label {
+ Style = style
+ };
+
+ Assert.AreEqual (Color.Red, label0.BackgroundColor);
+ Assert.AreEqual (Color.Red, label0.TextColor);
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label0.Text);
+
+ var layout0 = new StackLayout {
+ Resources = new ResourceDictionary {
+ {"basestyle", baseStyle0}
+ },
+ Children = {
+ label0
+ }
+ };
+
+ Assert.AreEqual (Color.Red, label0.BackgroundColor);
+ Assert.AreEqual (Color.Red, label0.TextColor);
+ Assert.AreEqual ("foo", label0.Text);
+
+ var label1 = new Label {
+ Style = style
+ };
+
+ Assert.AreEqual (Color.Red, label1.BackgroundColor);
+ Assert.AreEqual (Color.Red, label1.TextColor);
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label1.Text);
+
+ var layout1 = new StackLayout {
+ Children = {
+ label1
+ }
+ };
+ layout1.Resources = new ResourceDictionary {
+ {"basestyle", baseStyle1}
+ };
+
+ Assert.AreEqual (Color.Red, label1.BackgroundColor);
+ Assert.AreEqual (Color.Red, label1.TextColor);
+ Assert.AreEqual ("bar", label1.Text);
+ }
+
+ [Test]
+ public void TestTriggersAndBehaviors ()
+ {
+ var behavior = new MockBehavior<Entry> ();
+ var style = new Style (typeof(Entry)) {
+ Setters = {
+ new Setter {Property = Entry.TextProperty, Value = "foo"},
+ },
+ Triggers = {
+ new Trigger (typeof (VisualElement)) {Property = Entry.IsPasswordProperty, Value=true, Setters = {
+ new Setter {Property = VisualElement.ScaleProperty, Value = 2d},
+ }}
+ },
+ Behaviors = {
+ behavior,
+ }
+ };
+
+ var entry = new Entry { Style = style };
+ Assert.AreEqual ("foo", entry.Text);
+ Assert.AreEqual (1d, entry.Scale);
+
+ entry.IsPassword = true;
+ Assert.AreEqual (2d, entry.Scale);
+
+ Assert.True (behavior.attached);
+
+ entry.Style = null;
+
+ Assert.AreEqual (Entry.TextProperty.DefaultValue, entry.Text);
+ Assert.True (entry.IsPassword);
+ Assert.AreEqual (1d, entry.Scale);
+ Assert.True (behavior.detached);
+ }
+
+ [Test]
+ //Issue #2124
+ public void SetValueOverridesStyle ()
+ {
+ var style = new Style (typeof(Label)) {
+ Setters = {
+ new Setter {Property = Label.TextColorProperty, Value=Color.Black},
+ }
+ };
+
+ var label = new Label { TextColor = Color.White, Style = style };
+ Assert.AreEqual (Color.White, label.TextColor);
+ }
+
+ [Test]
+ //https://bugzilla.xamarin.com/show_bug.cgi?id=28556
+ public void TriggersAppliedAfterSetters ()
+ {
+ var style = new Style (typeof(Entry)) {
+ Setters = {
+ new Setter { Property = Entry.TextColorProperty, Value = Color.Yellow }
+ },
+ Triggers = {
+ new Trigger (typeof(Entry)) {
+ Property = VisualElement.IsEnabledProperty,
+ Value = false,
+ Setters = {
+ new Setter { Property = Entry.TextColorProperty, Value = Color.Red }
+ },
+ }
+ },
+ };
+
+ var entry = new Entry { IsEnabled = false, Style = style };
+ Assert.AreEqual (Color.Red, entry.TextColor);
+ entry.IsEnabled = true;
+ Assert.AreEqual (Color.Yellow, entry.TextColor);
+ }
+
+ [Test]
+ //https://bugzilla.xamarin.com/show_bug.cgi?id=31207
+ public async void StyleDontHoldStrongReferences ()
+ {
+ var style = new Style (typeof(Label));
+ var label = new Label ();
+ var tracker = new WeakReference (label);
+ label.Style = style;
+ label = null;
+
+ await Task.Delay (10);
+ GC.Collect ();
+
+ Assert.False (tracker.IsAlive);
+ Assert.NotNull (style);
+ }
+
+ class MyLabel : Label
+ {
+ }
+
+ class MyButton : Button
+ {
+ }
+
+ [Test]
+ public void ImplicitStylesNotAppliedToDerivedTypesByDefault ()
+ {
+ var style = new Style (typeof (Label)) {
+ Setters = {
+ new Setter { Property = Label.TextProperty, Value = "Foo" }
+ }
+ };
+ var view = new ContentView {
+ Resources = new ResourceDictionary { style },
+ Content = new MyLabel (),
+ };
+
+ Assert.AreEqual (Label.TextProperty.DefaultValue, ((MyLabel)view.Content).Text);
+ }
+
+ [Test]
+ public void ImplicitStylesAreAppliedToDerivedIfSpecified ()
+ {
+ var style = new Style (typeof (Label)) {
+ Setters = {
+ new Setter { Property = Label.TextProperty, Value = "Foo" }
+ },
+ ApplyToDerivedTypes = true
+ };
+ var view = new ContentView {
+ Resources = new ResourceDictionary { style },
+ Content = new MyLabel (),
+ };
+
+ Assert.AreEqual ("Foo", ((MyLabel)view.Content).Text);
+ }
+
+ [Test]
+ public void ClassStylesAreApplied ()
+ {
+ var classstyle = new Style (typeof (Label)) {
+ Setters = {
+ new Setter { Property = Label.TextProperty, Value = "Foo" }
+ },
+ Class = "fooClass",
+ };
+ var style = new Style (typeof (Label)) {
+ Setters = {
+ new Setter { Property = Label.TextColorProperty, Value = Color.Red }
+ },
+ };
+ var view = new ContentView {
+ Resources = new ResourceDictionary { classstyle },
+ Content = new Label {
+ StyleClass = "fooClass",
+ Style = style
+ }
+ };
+ Assert.AreEqual ("Foo", ((Label)view.Content).Text);
+ Assert.AreEqual (Color.Red, ((Label)view.Content).TextColor);
+ }
+
+ [Test]
+ public void ImplicitStylesNotAppliedByDefaultIfAStyleExists ()
+ {
+ var implicitstyle = new Style (typeof (Label)) {
+ Setters = {
+ new Setter { Property = Label.TextProperty, Value = "Foo" }
+ },
+ };
+ var style = new Style (typeof (Label)) {
+ Setters = {
+ new Setter { Property = Label.TextColorProperty, Value = Color.Red }
+ },
+ };
+ var view = new ContentView {
+ Resources = new ResourceDictionary { implicitstyle },
+ Content = new Label {
+ Style = style
+ }
+ };
+ Assert.AreEqual (Label.TextProperty.DefaultValue, ((Label)view.Content).Text);
+ Assert.AreEqual (Color.Red, ((Label)view.Content).TextColor);
+ }
+
+ [Test]
+ public void ImplicitStylesAppliedIfStyleCanCascade ()
+ {
+ var implicitstyle = new Style (typeof (Label)) {
+ Setters = {
+ new Setter { Property = Label.TextProperty, Value = "Foo" }
+ },
+ };
+ var style = new Style (typeof (Label)) {
+ Setters = {
+ new Setter { Property = Label.TextColorProperty, Value = Color.Red },
+ },
+ CanCascade = true
+ };
+ var view = new ContentView {
+ Resources = new ResourceDictionary { implicitstyle },
+ Content = new Label {
+ Style = style
+ }
+ };
+ Assert.AreEqual ("Foo", ((Label)view.Content).Text);
+ Assert.AreEqual (Color.Red, ((Label)view.Content).TextColor);
+ }
+
+ [Test]
+ public void MultipleStylesCanShareTheSameClassName ()
+ {
+ var buttonStyle = new Style (typeof(Button)) {
+ Setters = {
+ new Setter { Property = Button.TextColorProperty, Value = Color.Pink },
+ },
+ Class = "pink",
+ ApplyToDerivedTypes = true,
+ };
+ var labelStyle = new Style (typeof(Label)) {
+ Setters = {
+ new Setter { Property = Button.BackgroundColorProperty, Value = Color.Pink },
+ },
+ Class = "pink",
+ ApplyToDerivedTypes = false,
+ };
+
+
+ var button = new Button {
+ StyleClass = "pink",
+ };
+ var myButton = new MyButton {
+ StyleClass = "pink",
+ };
+
+ var label = new Label {
+ StyleClass = "pink"
+ };
+ var myLabel = new MyLabel {
+ StyleClass = "pink"
+ };
+
+
+ new StackLayout {
+ Resources = new ResourceDictionary {buttonStyle, labelStyle},
+ Children = {
+ button,
+ label,
+ myLabel,
+ myButton,
+ }
+ };
+
+ Assert.AreEqual (Color.Pink, button.TextColor);
+ Assert.AreEqual (Color.Default, button.BackgroundColor);
+
+ Assert.AreEqual (Color.Pink, myButton.TextColor);
+ Assert.AreEqual (Color.Default, myButton.BackgroundColor);
+
+ Assert.AreEqual (Color.Pink, label.BackgroundColor);
+ Assert.AreEqual (Color.Default, label.TextColor);
+
+ Assert.AreEqual (Color.Default, myLabel.BackgroundColor);
+ Assert.AreEqual (Color.Default, myLabel.TextColor);
+ }
+
+ [Test]
+ public void StyleClassAreCorrecltyMerged ()
+ {
+ var buttonStyle = new Style (typeof(Button)) {
+ Setters = {
+ new Setter { Property = Button.TextColorProperty, Value = Color.Pink },
+ },
+ Class = "pink",
+ ApplyToDerivedTypes = true,
+ };
+ var labelStyle = new Style (typeof(Label)) {
+ Setters = {
+ new Setter { Property = Button.BackgroundColorProperty, Value = Color.Pink },
+ },
+ Class = "pink",
+ ApplyToDerivedTypes = false,
+ };
+
+ var button = new Button {
+ StyleClass = "pink",
+ };
+ var label = new Label {
+ StyleClass = "pink"
+ };
+
+ var cv = new ContentView {
+ Resources = new ResourceDictionary {buttonStyle},
+ Content = new StackLayout {
+ Resources = new ResourceDictionary {labelStyle},
+ Children = {
+ button,
+ label,
+ }
+ }
+ };
+
+ Assert.AreEqual (Color.Pink, button.TextColor);
+ Assert.AreEqual (Color.Default, button.BackgroundColor);
+
+ Assert.AreEqual (Color.Pink, label.BackgroundColor);
+ Assert.AreEqual (Color.Default, label.TextColor);
+ }
+
+ [Test]
+ public void StyleClassAreCorrecltyMergedForAlreadyParentedPArents ()
+ {
+ var buttonStyle = new Style (typeof (Button)) {
+ Setters = {
+ new Setter { Property = Button.TextColorProperty, Value = Color.Pink },
+ },
+ Class = "pink",
+ ApplyToDerivedTypes = true,
+ };
+ var labelStyle = new Style (typeof (Label)) {
+ Setters = {
+ new Setter { Property = Button.BackgroundColorProperty, Value = Color.Pink },
+ },
+ Class = "pink",
+ ApplyToDerivedTypes = false,
+ };
+
+ var button = new Button {
+ StyleClass = "pink",
+ };
+ var label = new Label {
+ StyleClass = "pink"
+ };
+
+ var cv = new ContentView {
+ Resources = new ResourceDictionary { buttonStyle },
+ Content = new StackLayout {
+ Resources = new ResourceDictionary { labelStyle },
+ }
+ };
+
+ (cv.Content as StackLayout).Children.Add (button);
+ (cv.Content as StackLayout).Children.Add (label);
+
+ Assert.AreEqual (Color.Pink, button.TextColor);
+ Assert.AreEqual (Color.Default, button.BackgroundColor);
+
+ Assert.AreEqual (Color.Pink, label.BackgroundColor);
+ Assert.AreEqual (Color.Default, label.TextColor);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/SwitchCellTests.cs b/Xamarin.Forms.Core.UnitTests/SwitchCellTests.cs
new file mode 100644
index 00000000..16fee76b
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/SwitchCellTests.cs
@@ -0,0 +1,62 @@
+using System;
+using NUnit.Framework;
+using NUnit.Framework.Constraints;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class SwitchCellTemplateTests : BaseTestFixture
+ {
+ [Test]
+ public void Create()
+ {
+ var template = new DataTemplate (typeof(SwitchCell));
+ var content = template.CreateContent();
+
+ Assert.That (content, Is.InstanceOf<SwitchCell>());
+ }
+
+ [Test]
+ public void Text()
+ {
+ var template = new DataTemplate (typeof (SwitchCell));
+ template.SetValue (SwitchCell.TextProperty, "text");
+
+ SwitchCell cell = (SwitchCell)template.CreateContent();
+ Assert.That (cell.Text, Is.EqualTo ("text"));
+ }
+
+ [Test]
+ public void On()
+ {
+ var template = new DataTemplate (typeof (SwitchCell));
+ template.SetValue (SwitchCell.OnProperty, true);
+
+ SwitchCell cell = (SwitchCell)template.CreateContent();
+ Assert.That (cell.On, Is.EqualTo (true));
+ }
+
+ [TestCase (false, true)]
+ [TestCase (true, false)]
+ public void SwitchCellSwitchChangedArgs (bool initialValue, bool finalValue)
+ {
+ var template = new DataTemplate (typeof (SwitchCell));
+ SwitchCell cell = (SwitchCell)template.CreateContent ();
+
+ SwitchCell switchCellFromSender = null;
+ bool newSwitchValue = false;
+
+ cell.On = initialValue;
+
+ cell.OnChanged += (s, e) => {
+ switchCellFromSender = (SwitchCell)s;
+ newSwitchValue = e.Value;
+ };
+
+ cell.On = finalValue;
+
+ Assert.AreEqual (cell, switchCellFromSender);
+ Assert.AreEqual (finalValue, newSwitchValue);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/SwitchUnitTests.cs b/Xamarin.Forms.Core.UnitTests/SwitchUnitTests.cs
new file mode 100644
index 00000000..9748c3e9
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/SwitchUnitTests.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class SwitchUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestConstructor ()
+ {
+ Switch sw = new Switch ();
+
+ Assert.IsFalse (sw.IsToggled);
+ }
+
+ [Test]
+ public void TestOnEvent ()
+ {
+ Switch sw = new Switch ();
+
+ bool fired = false;
+ sw.Toggled += (sender, e) => fired = true;
+
+ sw.IsToggled = true;
+
+ Assert.IsTrue (fired);
+ }
+
+ [Test]
+ public void TestOnEventNotDoubleFired ()
+ {
+ var sw = new Switch ();
+
+ bool fired = false;
+ sw.IsToggled = true;
+
+ sw.Toggled += (sender, args) => fired = true;
+ sw.IsToggled = true;
+
+ Assert.IsFalse (fired);
+ }
+ }
+
+}
diff --git a/Xamarin.Forms.Core.UnitTests/TabbedFormUnitTests.cs b/Xamarin.Forms.Core.UnitTests/TabbedFormUnitTests.cs
new file mode 100644
index 00000000..608ad393
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/TabbedFormUnitTests.cs
@@ -0,0 +1,32 @@
+using System.Linq;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class TabbedPageTests : MultiPageTests<Page>
+ {
+ protected override MultiPage<Page> CreateMultiPage()
+ {
+ return new TabbedPage();
+ }
+
+ protected override Page CreateContainedPage()
+ {
+ return new ContentPage { Content = new View() };
+ }
+
+ protected override int GetIndex (Page page)
+ {
+ return TabbedPage.GetIndex (page);
+ }
+
+ [Test]
+ public void TestConstructor ()
+ {
+ TabbedPage page = new TabbedPage ();
+
+ Assert.That (page.Children, Is.Empty);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/TableModelTests.cs b/Xamarin.Forms.Core.UnitTests/TableModelTests.cs
new file mode 100644
index 00000000..9173d387
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/TableModelTests.cs
@@ -0,0 +1,87 @@
+using System;
+using NUnit.Framework;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class TableModelTests : BaseTestFixture
+ {
+ class TestModel : TableModel
+ {
+ public override int GetRowCount (int section)
+ {
+ return 10;
+ }
+
+ public override int GetSectionCount ()
+ {
+ return 1;
+ }
+
+ public override object GetItem (int section, int row)
+ {
+ return "Foo";
+ }
+
+ public string ProtectedSectionTitle ()
+ {
+ return GetSectionTitle (0);
+ }
+ }
+
+ [Test]
+ public void DefaultSectionTitle ()
+ {
+ Assert.IsNull (new TestModel ().ProtectedSectionTitle ());
+ }
+
+ [Test]
+ public void DefualtSectionIndexTitles ()
+ {
+ Assert.IsNull (new TestModel ().GetSectionIndexTitles ());
+ }
+
+ [Test]
+ public void DefaultHeaderCell ()
+ {
+ Assert.IsNull (new TestModel ().GetHeaderCell (0));
+ }
+
+ [Test]
+ public void DefaultCellFromObject ()
+ {
+ var model = new TestModel ();
+ var cell = model.GetCell (0, 5);
+
+ Assert.That (cell, Is.TypeOf<TextCell> ());
+
+ var textCell = (TextCell) cell;
+ Assert.AreEqual ("Foo", textCell.Text);
+ }
+
+ [Test]
+ public void RowLongPressed ()
+ {
+ var model = new TestModel ();
+
+ var longPressedItem = "";
+ model.ItemLongPressed += (sender, arg) => {
+ longPressedItem = (string)arg.Data;
+ };
+
+ model.RowLongPressed (0, 5);
+ }
+
+ [Test]
+ public void RowSelectedForObject ()
+ {
+ var model = new TestModel ();
+ string result = null;
+ model.ItemSelected += (sender, arg) => result = (string)arg.Data;
+
+ model.RowSelected ("Foobar");
+ Assert.AreEqual ("Foobar", result);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/TableRootUnitTests.cs b/Xamarin.Forms.Core.UnitTests/TableRootUnitTests.cs
new file mode 100644
index 00000000..0c9d42fe
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/TableRootUnitTests.cs
@@ -0,0 +1,103 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class TableRootUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void Ctor()
+ {
+ const string title = "FooBar";
+ var model = new TableRoot (title);
+ Assert.AreEqual (title, model.Title);
+ }
+
+ [Test]
+ public void CtorInvalid()
+ {
+ Assert.Throws<ArgumentNullException> (() => new TableRoot (null));
+ }
+
+ [Test]
+ public void TestGetSections ()
+ {
+ var model = new TableRoot ("Name") {
+ new TableSection ("Section 1") {
+ new TextCell { Text = "Item 1.1", Detail = "Hint 1"},
+ new TextCell { Text = "Item 1.2", Detail = "Hint 2"},
+ new TextCell { Text = "Item 1.3", Detail = "Hint 3"}
+ },
+ new TableSection ("Section 2") {
+ new TextCell { Text = "Item 2.1", Detail = "Hint 1"},
+ new TextCell { Text = "Item 2.2", Detail = "Hint 2"},
+ new TextCell { Text = "Item 2.3", Detail = "Hint 3"}
+ }
+ };
+
+ Assert.AreEqual (2, model.Count);
+ }
+
+ [Test]
+ public void TestCollectionChanged ()
+ {
+ var model = new TableRoot ();
+
+ bool changed = false;
+ model.CollectionChanged += (sender, e) => changed = true;
+
+ model.Add (new TableSection ("Foo"));
+
+ Assert.True (changed);
+
+ changed = false;
+
+ model [0].Add (new TextCell { Text = "Foobar" });
+
+ // Our tree is not supposed to track up like this
+ Assert.False (changed);
+ }
+
+ [Test]
+ public void TestTree ()
+ {
+ var model = new TableRoot ("Name") {
+ new TableSection ("Section 1") {
+ new TextCell { Text = "Item 1.1", Detail = "Hint 1"},
+ new TextCell { Text = "Item 1.2", Detail = "Hint 2"},
+ new TextCell { Text = "Item 1.3", Detail = "Hint 3"}
+ },
+ new TableSection {
+ new TextCell { Text = "Item 2.1", Detail = "Hint 1"},
+ new TextCell { Text = "Item 2.2", Detail = "Hint 2"},
+ new TextCell { Text = "Item 2.3", Detail = "Hint 3"}
+ }
+ };
+
+ Assert.AreEqual ("Item 1.1", (model[0][0] as TextCell).Text);
+ Assert.AreEqual ("Item 1.2", (model[0][1] as TextCell).Text);
+ Assert.AreEqual ("Item 1.3", (model[0][2] as TextCell).Text);
+ Assert.AreEqual ("Item 2.1", (model[1][0] as TextCell).Text);
+ Assert.AreEqual ("Item 2.2", (model[1][1] as TextCell).Text);
+ Assert.AreEqual ("Item 2.3", (model[1][2] as TextCell).Text);
+ }
+
+ //[Test]
+ //public void TestAddFromEnumerable ()
+ //{;
+ // TableSection first, second;
+ // var model = new TableRoot ();
+ // model.Add (new[] {
+ // first = new TableSection (),
+ // second = new TableSection ()
+ // });
+
+ // Assert.AreEqual (first, model[0]);
+ // Assert.AreEqual (second, model[1]);
+ //}
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/TableSectionTests.cs b/Xamarin.Forms.Core.UnitTests/TableSectionTests.cs
new file mode 100644
index 00000000..bcf405b5
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/TableSectionTests.cs
@@ -0,0 +1,225 @@
+using System.Collections.Generic;
+using NUnit.Framework;
+
+using NContains = NUnit.Framework.Contains;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class TableSectionTests : BaseTestFixture
+ {
+ [SetUp]
+ public void Setup()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void Constructor ()
+ {
+ var section = new TableSection ("Title");
+ Assert.AreEqual ("Title", section.Title);
+ Assert.That (section, Is.Empty);
+ }
+
+ [Test]
+ public void IsReadOnly ()
+ {
+ var section = new TableSection () as ICollection<Cell>;
+ Assert.False (section.IsReadOnly);
+ }
+
+ [Test]
+ public void Add ()
+ {
+ var section = new TableSection ();
+ TextCell first, second;
+ section.Add (first = new TextCell { Text = "Text" });
+ section.Add (second = new TextCell { Text = "Text" });
+
+ Assert.That (section, NContains.Item (first));
+ Assert.That (section, NContains.Item (second));
+ }
+
+ [Test]
+ public void Remove ()
+ {
+ var section = new TableSection ();
+ TextCell first;
+ section.Add (first = new TextCell { Text = "Text" });
+ section.Add (new TextCell { Text = "Text" });
+
+ var result = section.Remove (first);
+ Assert.True (result);
+ Assert.That (section, Has.No.Contains (first));
+ }
+
+ [Test]
+ public void Clear ()
+ {
+ var section = new TableSection {new TextCell { Text = "Text" }, new TextCell { Text = "Text" }};
+ section.Clear ();
+ Assert.That (section, Is.Empty);
+ }
+
+ [Test]
+ public void Contains ()
+ {
+ var section = new TableSection ();
+ TextCell first, second;
+ section.Add (first = new TextCell { Text = "Text" });
+ section.Add (second = new TextCell { Text = "Text" });
+
+ Assert.True (section.Contains (first));
+ Assert.True (section.Contains (second));
+ }
+
+ [Test]
+ public void IndexOf ()
+ {
+ var section = new TableSection ();
+ TextCell first, second;
+ section.Add (first = new TextCell { Text = "Text" });
+ section.Add (second = new TextCell { Text = "Text" });
+
+ Assert.AreEqual (0, section.IndexOf (first));
+ Assert.AreEqual (1, section.IndexOf (second));
+ }
+
+ [Test]
+ public void Insert ()
+ {
+ var section = new TableSection ();
+ section.Add (new TextCell { Text = "Text" });
+ section.Add (new TextCell { Text = "Text" });
+
+ var third = new TextCell { Text = "Text" };
+ section.Insert (1, third);
+ Assert.AreEqual (third, section[1]);
+ }
+
+ [Test]
+ public void RemoveAt ()
+ {
+ var section = new TableSection ();
+ TextCell first, second;
+ section.Add (first = new TextCell { Text = "Text" });
+ section.Add (second = new TextCell { Text = "Text" });
+
+ section.RemoveAt (0);
+ Assert.That (section, Has.No.Contains (first));
+ }
+
+ [Test]
+ public void Overwrite ()
+ {
+ var section = new TableSection ();
+ TextCell second;
+ section.Add (new TextCell { Text = "Text" });
+ section.Add (second = new TextCell { Text = "Text" });
+
+ var third = new TextCell { Text = "Text" };
+ section[1] = third;
+
+ Assert.AreEqual (third, section[1]);
+ Assert.That (section, Has.No.Contains (second));
+ }
+
+ [Test]
+ public void CopyTo ()
+ {
+ var section = new TableSection ();
+ TextCell first, second;
+ section.Add (first = new TextCell { Text = "Text" });
+ section.Add (second = new TextCell { Text = "Text" });
+
+ Cell[] cells = new Cell[2];
+ section.CopyTo (cells, 0);
+
+ Assert.AreEqual (first, cells[0]);
+ Assert.AreEqual (second, cells[1]);
+ }
+
+ [Test]
+ public void ChainsBindingContextOnSet ()
+ {
+ var section = new TableSection ();
+ TextCell first, second;
+ section.Add (first = new TextCell { Text = "Text" });
+ section.Add (second = new TextCell { Text = "Text" });
+
+ var bindingContext = "bindingContext";
+
+ section.BindingContext = bindingContext;
+
+ Assert.AreEqual (bindingContext, first.BindingContext);
+ Assert.AreEqual (bindingContext, second.BindingContext);
+ }
+
+ [Test]
+ public void ChainsBindingContextWithExistingContext ()
+ {
+ var section = new TableSection ();
+ TextCell first, second;
+ section.Add (first = new TextCell { Text = "Text" });
+ section.Add (second = new TextCell { Text = "Text" });
+
+ var bindingContext = "bindingContext";
+ section.BindingContext = bindingContext;
+
+ bindingContext = "newContext";
+ section.BindingContext = bindingContext;
+
+ Assert.AreEqual (bindingContext, first.BindingContext);
+ Assert.AreEqual (bindingContext, second.BindingContext);
+ }
+
+ [Test]
+ public void ChainsBindingContextToNewlyAdded ()
+ {
+ var section = new TableSection ();
+ var bindingContext = "bindingContext";
+ section.BindingContext = bindingContext;
+
+ TextCell first, second;
+ section.Add (first = new TextCell { Text = "Text" });
+ section.Add (second = new TextCell { Text = "Text" });
+
+ Assert.AreEqual (bindingContext, first.BindingContext);
+ Assert.AreEqual (bindingContext, second.BindingContext);
+ }
+
+ [Test]
+ public void TestBindingTitleSectionChange ()
+ {
+ var vm = new MockViewModel { Text = "FooBar" };
+ var section = new TableSection ();
+
+ section.BindingContext = vm;
+ section.SetBinding (TableSectionBase.TitleProperty, "Text");
+
+ Assert.AreEqual ("FooBar", section.Title);
+
+ vm.Text = "Baz";
+
+ Assert.AreEqual ("Baz", section.Title);
+ }
+
+ [Test]
+ public void TestBindingTitle ()
+ {
+ var section = new TableSection ();
+ var mock = new MockViewModel ();
+ section.BindingContext = mock;
+ section.SetBinding (TableSection.TitleProperty, new Binding ("Text"));
+
+ Assert.AreEqual (mock.Text, section.Title);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/TableViewUnitTests.cs b/Xamarin.Forms.Core.UnitTests/TableViewUnitTests.cs
new file mode 100644
index 00000000..7e5ca496
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/TableViewUnitTests.cs
@@ -0,0 +1,84 @@
+using System.Linq;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class TableViewUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestConstructor ()
+ {
+ var table = new TableView ();
+
+ Assert.False (table.Root.Any ());
+ Assert.AreEqual (LayoutOptions.FillAndExpand, table.HorizontalOptions);
+ Assert.AreEqual (LayoutOptions.FillAndExpand, table.VerticalOptions);
+ }
+
+ [Test]
+ public void TestModelChanged ()
+ {
+ var table = new TableView ();
+
+ bool changed = false;
+
+ table.ModelChanged += (sender, e) => changed = true;
+
+ table.Root = new TableRoot ("NewRoot");
+
+ Assert.True (changed);
+ }
+
+ [Test]
+ public void BindingsContextChainsToModel ()
+ {
+ const string context = "Context";
+ var table = new TableView { BindingContext = context, Root = new TableRoot() };
+
+ Assert.AreEqual (context, table.Root.BindingContext);
+
+ // reverse assignment order
+ table = new TableView { Root = new TableRoot(), BindingContext = context};
+ Assert.AreEqual (context, table.Root.BindingContext);
+ }
+
+ [Test]
+ public void ParentsViewCells ()
+ {
+ ViewCell viewCell = new ViewCell { View = new Label () };
+ var table = new TableView {
+ Platform = new UnitPlatform (),
+ Root = new TableRoot {
+ new TableSection {
+ viewCell
+ }
+ }
+ };
+
+ Assert.AreEqual (table, viewCell.Parent);
+ Assert.AreEqual (viewCell, viewCell.View.Parent);
+ Assert.AreEqual (table.Platform, viewCell.View.Platform);
+ }
+
+ [Test]
+ public void ParentsAddedViewCells ()
+ {
+ var viewCell = new ViewCell { View = new Label () };
+ var section = new TableSection ();
+ var table = new TableView {
+ Platform = new UnitPlatform (),
+ Root = new TableRoot {
+ section
+ }
+ };
+
+ section.Add (viewCell);
+
+ Assert.AreEqual (table, viewCell.Parent);
+ Assert.AreEqual (viewCell, viewCell.View.Parent);
+ Assert.AreEqual (table.Platform, viewCell.View.Platform);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/TapGestureRecognizerTests.cs b/Xamarin.Forms.Core.UnitTests/TapGestureRecognizerTests.cs
new file mode 100644
index 00000000..5b639b2c
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/TapGestureRecognizerTests.cs
@@ -0,0 +1,33 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class TapGestureRecognizerTests : BaseTestFixture
+ {
+ [Test]
+ public void Constructor ()
+ {
+ var tap = new TapGestureRecognizer ();
+
+ Assert.AreEqual (null, tap.Command);
+ Assert.AreEqual (null, tap.CommandParameter);
+ Assert.AreEqual (1, tap.NumberOfTapsRequired);
+ }
+
+ [Test]
+ public void CallbackPassesParameter ()
+ {
+ var view = new View ();
+ var tap = new TapGestureRecognizer ();
+ tap.CommandParameter = "Hello";
+
+ object result = null;
+ tap.Command = new Command (o => result = o);
+
+ tap.SendTapped (view);
+ Assert.AreEqual (result, tap.CommandParameter);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/TemplatedItemsListTests.cs b/Xamarin.Forms.Core.UnitTests/TemplatedItemsListTests.cs
new file mode 100644
index 00000000..d723b660
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/TemplatedItemsListTests.cs
@@ -0,0 +1,1073 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class TemplatedItemsListTests : BaseTestFixture
+ {
+ class MockItemsView
+ : ItemsView<BindableObject>
+ {
+ public MockItemsView()
+ {
+ TemplatedItems.IsGroupingEnabledProperty = IsGroupingEnabledProperty;
+ }
+
+ public event Action<BindableObject> Hooked;
+ public event Action<BindableObject> Unhooked;
+
+ public static readonly BindableProperty IsGroupingEnabledProperty =
+ BindableProperty.Create<MockItemsView, bool> (lv => lv.IsGroupingEnabled, false);
+
+ public bool IsGroupingEnabled
+ {
+ get { return (bool)GetValue (IsGroupingEnabledProperty); }
+ set { SetValue (IsGroupingEnabledProperty, value); }
+ }
+
+ protected override BindableObject CreateDefault (object item)
+ {
+ return new TextCell { Text = item.ToString () };
+ }
+
+ public new TemplatedItemsList<ItemsView<BindableObject>, BindableObject> TemplatedItems
+ {
+ get { return base.TemplatedItems; }
+ }
+
+ BindingBase groupShortNameBinding;
+ public BindingBase GroupShortNameBinding
+ {
+ get { return groupShortNameBinding; }
+ set {
+ if (groupShortNameBinding == value)
+ return;
+ OnPropertyChanging ();
+ groupShortNameBinding = value;
+ TemplatedItems.GroupShortNameBinding = value;
+ OnPropertyChanged ();
+ }
+ }
+
+ BindingBase groupDisplayBinding;
+ public BindingBase GroupDisplayBinding
+ {
+ get { return groupDisplayBinding; }
+ set {
+ if (groupDisplayBinding == value)
+ return;
+
+ OnPropertyChanging ();
+ groupDisplayBinding = value;
+ TemplatedItems.GroupDisplayBinding = value;
+ OnPropertyChanged ();
+ }
+ }
+
+ protected override void SetupContent (BindableObject content, int index)
+ {
+ base.SetupContent (content, index);
+
+ if (Hooked != null)
+ Hooked (content);
+ }
+
+ protected override void UnhookContent (BindableObject content)
+ {
+ base.UnhookContent (content);
+
+ if (Unhooked != null)
+ Unhooked (content);
+ }
+ }
+
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ bindable = new MockItemsView();
+
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ MockItemsView bindable;
+
+ [Test]
+ public void ListProxyNotNullWithNullItemsSource()
+ {
+ Assert.IsNotNull (bindable.TemplatedItems.ListProxy);
+ }
+
+ [Test]
+ public void ResetOnItemsSourceChanged()
+ {
+ bool raised = false;
+ NotifyCollectionChangedAction action = default(NotifyCollectionChangedAction);
+ bindable.TemplatedItems.CollectionChanged += (sender, args) => {
+ raised = true;
+ action = args.Action;
+ };
+
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, Enumerable.Empty<string>());
+
+ Assert.IsTrue (raised, "CollectionChanged was not raised");
+ Assert.AreEqual (NotifyCollectionChangedAction.Reset, action);
+ }
+ /*
+ [Test]
+ public void ResetOnInfiniteScrollingChanged()
+ {
+ bool raised = false;
+ NotifyCollectionChangedAction action = default(NotifyCollectionChangedAction);
+ bindable.TemplatedItems.CollectionChanged += (sender, args) => {
+ raised = true;
+ action = args.Action;
+ };
+
+ bindable.SetValue (ItemsView.InfiniteScrollingProperty, true);
+
+ Assert.IsTrue (raised, "CollectionChanged was not raised");
+ Assert.AreEqual (NotifyCollectionChangedAction.Reset, action);
+ }*/
+
+ [Test]
+ public void ResetOnTemplateChanged()
+ {
+ // Template changes won't trigger a reset if there's no items.
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, new[] { "Foo" });
+
+ bool raised = false;
+ NotifyCollectionChangedAction action = default(NotifyCollectionChangedAction);
+ bindable.TemplatedItems.CollectionChanged += (sender, args) => {
+ raised = true;
+ action = args.Action;
+ };
+
+ bindable.SetValue (ItemsView<BindableObject>.ItemTemplateProperty, new DataTemplate());
+
+ Assert.IsTrue (raised, "CollectionChanged was not raised");
+ Assert.AreEqual (NotifyCollectionChangedAction.Reset, action);
+ }
+
+ [Test]
+ public void PassThroughChanges()
+ {
+ var collection = new ObservableCollection<string>();
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ bool raised = false;
+ NotifyCollectionChangedEventArgs args = null;
+ bindable.TemplatedItems.CollectionChanged += (sender, eventArgs) => {
+ raised = true;
+ args = eventArgs;
+ };
+
+ string str = "foo bar";
+ collection.Add (str);
+
+ Assert.IsTrue (raised, "CollectionChanged was not raised");
+ Assert.AreEqual (NotifyCollectionChangedAction.Add, args.Action);
+ Assert.AreEqual (0, args.NewStartingIndex);
+ Assert.IsNotNull (args.NewItems);
+ Assert.AreEqual (1, args.NewItems.Count);
+ Assert.AreSame (str, ((Cell)args.NewItems[0]).BindingContext);
+ }
+
+ [Test]
+ public void ListProxyUpdatesWithItemsSource()
+ {
+ var collection = new List<string> { "foo bar" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ Assert.IsNotNull (bindable.TemplatedItems.ListProxy);
+ Assert.AreEqual (collection.Count, bindable.TemplatedItems.ListProxy.Count);
+ }
+
+ [Test]
+ public void GetOrCreateContent ([Values (0, 1, 2)] int index)
+ {
+ var collection = new List<string> { "foo", "bar", "baz" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ DataTemplate template = new DataTemplate (typeof (TextCell));
+ template.SetBinding (TextCell.TextProperty, new Binding ("."));
+ bindable.SetValue (ItemsView<BindableObject>.ItemTemplateProperty, template);
+
+ BindableObject content = bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+ Assert.IsNotNull (content);
+
+ TextCell textCell = content as TextCell;
+ Assert.IsNotNull (textCell, "Content was did not match the template type, expected {0} but got {1}", typeof(TextCell), content.GetType());
+
+ Assert.AreSame (collection[index], textCell.BindingContext);
+ Assert.AreSame (collection[index], textCell.Text);
+
+ BindableObject content2 = bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+ Assert.AreSame (content, content2);
+ }
+
+ [Test]
+ public void GetOrCreateContentDefault()
+ {
+ Assert.IsNull (bindable.GetValue (ItemsView<BindableObject>.ItemTemplateProperty));
+
+ var collection = new List<string> { "foo", "bar", "baz" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ const int index = 0;
+ BindableObject content = bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+ Assert.IsNotNull (content);
+
+ TextCell textCell = content as TextCell;
+ Assert.IsNotNull (textCell, "Content was did not match the template type, expected {0} but got {1}", typeof(TextCell), content.GetType());
+
+ Assert.AreSame (collection[index], textCell.BindingContext);
+ Assert.AreSame (collection[index], textCell.Text);
+
+ BindableObject content2 = bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+ Assert.AreSame (content, content2);
+ }
+
+ [Test]
+ public void GetOrCreateContentAfterTemplateChange()
+ {
+ var collection = new List<string> { "foo", "bar", "baz" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ const int index = 0;
+
+ DataTemplate template = new DataTemplate (typeof (TextCell));
+ template.SetBinding (TextCell.TextProperty, new Binding ("."));
+ bindable.SetValue (ItemsView<BindableObject>.ItemTemplateProperty, template);
+
+ BindableObject content = bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+ Assert.That (content, Is.InstanceOf<TextCell>());
+
+ template = new DataTemplate (typeof (SwitchCell));
+ template.SetBinding (SwitchCell.TextProperty, new Binding ("."));
+
+ bindable.SetValue (ItemsView<BindableObject>.ItemTemplateProperty, template);
+
+ BindableObject content2 = bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+ Assert.IsNotNull (content2);
+ Assert.That (content2, Is.InstanceOf<SwitchCell>());
+
+ var switchCell = (SwitchCell) content2;
+ Assert.AreSame (collection[index], switchCell.BindingContext);
+ }
+
+ [Test]
+ public void GetOrCreateContentAfterItemsSourceChanged()
+ {
+ var collection = new List<string> { "foo", "bar", "baz" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ const int index = 0;
+
+ DataTemplate template = new DataTemplate (typeof (TextCell));
+ template.SetBinding (TextCell.TextProperty, new Binding ("."));
+ bindable.SetValue (ItemsView<BindableObject>.ItemTemplateProperty, template);
+
+ BindableObject content = bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+ Assert.IsNotNull (content);
+
+ collection = new List<string> { "we", "wee", "weee" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ var content2 = (TextCell)bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+
+ Assert.AreNotSame (content, content2);
+ Assert.AreSame (collection[index], content2.BindingContext);
+ Assert.AreSame (collection[index], content2.Text);
+ }
+
+ /*[Test]
+ public void GetOrCreateContentAfterInfiniteScrollingChanged()
+ {
+ var collection = new List<string> { "foo", "bar", "baz" };
+ bindable.SetValue (ItemsView.ItemsSourceProperty, collection);
+
+ const int index = 0;
+
+ DataTemplate template = new DataTemplate (typeof (TextCell));
+ template.SetBinding (TextCell.TextProperty, new Binding ("."));
+ bindable.SetValue (ItemsView.ItemTemplateProperty, template);
+
+ BindableObject content = bindable.TemplatedItems.GetOrCreateContent (index, collection[index], o => new TextCell (o.ToString()));
+ Assert.IsNotNull (content);
+
+ bindable.SetValue (ItemsView.InfiniteScrollingProperty, true);
+
+ var content2 = (TextCell)bindable.TemplatedItems.GetOrCreateContent (index, collection[index], o => new TextCell (o.ToString()));
+
+ Assert.AreNotSame (content, content2);
+ Assert.AreSame (collection[index], content2.BindingContext);
+ Assert.AreSame (collection[index], content2.Text);
+ }*/
+
+ [Test]
+ [Description ("Make sure we're not duplicate cell instances for an equal item if it's a different index")]
+ public void GetOrCreateContentEqualItemDifferentItemDifferentIndex()
+ {
+ Assert.IsNull (bindable.GetValue (ItemsView<BindableObject>.ItemTemplateProperty));
+
+ var collection = new List<string> { "foo", "foo" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ BindableObject content = bindable.TemplatedItems.GetOrCreateContent (0, collection[0]);
+ Assert.IsNotNull (content);
+
+ TextCell textCell = content as TextCell;
+ Assert.IsNotNull (textCell, "Content was did not match the template type, expected {0} but got {1}", typeof(TextCell), content.GetType());
+
+ Assert.AreSame (collection[0], textCell.BindingContext);
+ Assert.AreSame (collection[0], textCell.Text);
+
+ BindableObject content2 = bindable.TemplatedItems.GetOrCreateContent (1, collection[1]);
+ Assert.AreNotSame (content, content2);
+
+ Assert.AreSame (collection[1], textCell.BindingContext);
+ Assert.AreSame (collection[1], textCell.Text);
+ }
+
+ [Test]
+ [Description ("Make sure we're not duplicate cell instances for the same item if it's a different index")]
+ public void GetOrCreateContentEqualItemSameItemDifferentIndex()
+ {
+ Assert.IsNull (bindable.GetValue (ItemsView<BindableObject>.ItemTemplateProperty));
+
+ string item = "foo";
+
+ var collection = new List<string> { item, item };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ BindableObject content = bindable.TemplatedItems.GetOrCreateContent (0, item);
+ Assert.IsNotNull (content);
+
+ TextCell textCell = content as TextCell;
+ Assert.IsNotNull (textCell, "Content was did not match the template type, expected {0} but got {1}", typeof(TextCell), content.GetType());
+
+ Assert.AreSame (item, textCell.BindingContext);
+ Assert.AreSame (item, textCell.Text);
+
+ BindableObject content2 = bindable.TemplatedItems.GetOrCreateContent (1, item);
+ Assert.AreNotSame (content, content2);
+
+ Assert.AreSame (item, textCell.BindingContext);
+ Assert.AreSame (item, textCell.Text);
+ }
+
+ [Test]
+ public void ItemsSourceInsertPreRealzied()
+ {
+ var collection = new ObservableCollection<string> { "foo", "bar" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ collection.Insert (1, "baz");
+
+ Assert.That (bindable.TemplatedItems.Count, Is.EqualTo (3));
+ Assert.That (bindable.TemplatedItems.GetOrCreateContent (0, collection[0]).BindingContext, Is.SameAs (collection[0]));
+ Assert.That (bindable.TemplatedItems.GetOrCreateContent (1, collection[1]).BindingContext, Is.SameAs (collection[1]));
+ Assert.That (bindable.TemplatedItems.GetOrCreateContent (2, collection[2]).BindingContext, Is.SameAs (collection[2]));
+ }
+
+ [Test]
+ public void ItemsSourceInsertPostRealized()
+ {
+ var collection = new ObservableCollection<string> { "foo", "bar" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ // Force the handler to realize/create the content
+ bindable.TemplatedItems.GetOrCreateContent (0, collection[0]);
+ bindable.TemplatedItems.GetOrCreateContent (1, collection[1]);
+
+ collection.Insert (1, "baz");
+
+ Assert.That (bindable.TemplatedItems.Count, Is.EqualTo (3));
+ Assert.That (bindable.TemplatedItems.GetOrCreateContent (0, collection[0]).BindingContext, Is.SameAs (collection[0]));
+ Assert.That (bindable.TemplatedItems.GetOrCreateContent (1, collection[1]).BindingContext, Is.SameAs (collection[1]));
+ Assert.That (bindable.TemplatedItems.GetOrCreateContent (2, collection[2]).BindingContext, Is.SameAs (collection[2]));
+ }
+
+ [TestCase (0, 0, 0)]
+ [TestCase (3, 1, 0)]
+ public void GetGroupIndexFromGlobalGroupIndex (int globalIndex, int expectedIndex, int expectedLeftOver)
+ {
+ var collection = new[] {
+ new[] { "foo", "fad" },
+ new[] { "bar", "baz" }
+ };
+ bindable.ItemsSource = collection;
+ bindable.IsGroupingEnabled = true;
+
+ int leftOver;
+ int index = bindable.TemplatedItems.GetGroupIndexFromGlobal (globalIndex, out leftOver);
+ Assert.That (index, Is.EqualTo (expectedIndex));
+ Assert.That (leftOver, Is.EqualTo (expectedLeftOver));
+ }
+
+ [TestCase (1, 0, 1)]
+ [TestCase (2, 0, 2)]
+ [TestCase (4, 1, 1)]
+ [TestCase (5, 1, 2)]
+ public void GetGroupIndexFromGlobalItemIndex (int globalIndex, int expectedIndex, int expectedLeftOver)
+ {
+ var collection = new[] {
+ new[] { "foo", "fad" },
+ new[] { "bar", "baz" }
+ };
+ bindable.ItemsSource = collection;
+ bindable.IsGroupingEnabled = true;
+
+ int leftOver;
+ int index = bindable.TemplatedItems.GetGroupIndexFromGlobal (globalIndex, out leftOver);
+ Assert.That (index, Is.EqualTo (expectedIndex));
+ Assert.That (leftOver, Is.EqualTo (expectedLeftOver));
+ }
+
+ [Test]
+ public void GetGroupAndIndexOfItem ([Values (0, 1, 2)] int group, [Values (0, 1, 2)] int index)
+ {
+ var collection = new[] {
+ new[] { "foo", "fad" },
+ new[] { "bar", "baz" }
+ };
+ bindable.ItemsSource = collection;
+ bindable.IsGroupingEnabled = true;
+
+ object item = null;
+ if (group < collection.Length) {
+ if (index < collection[group].Length)
+ item = collection[group][index];
+ }
+
+ if (item == null) {
+ item = "not in here";
+ group = index = -1;
+ }
+
+ var location = bindable.TemplatedItems.GetGroupAndIndexOfItem (item);
+ Assert.That (location.Item1, Is.EqualTo (group), "Group index was incorrect");
+ Assert.That (location.Item2, Is.EqualTo (index), "Item index was incorrect");
+ }
+
+ [Test]
+ public void GetGroupAndIndexOfItemNotGrouped ()
+ {
+ var items = Enumerable.Range (0, 10).ToList ();
+ bindable.ItemsSource = items;
+
+ var location = bindable.TemplatedItems.GetGroupAndIndexOfItem (null, items[2]);
+
+ Assert.That (location.Item1, Is.EqualTo (0));
+ Assert.That (location.Item2, Is.EqualTo (2));
+ }
+
+ [Test]
+ public void ItemsSourcePropertyChangedWithBindable()
+ {
+ bool raised = false;
+ bindable.TemplatedItems.PropertyChanged += (s, e) => {
+ if (e.PropertyName == "ItemsSource")
+ raised = true;
+ };
+
+ bindable.ItemsSource = new object[0];
+
+ Assert.That (raised, Is.True, "INPC not raised for ItemsSource");
+ }
+
+ [Test]
+ public void IndexCorrectAfterMovingGroups()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.IsGroupingEnabled = true;
+
+ items.Move (0, 1);
+
+ var til = bindable.TemplatedItems.GetGroup (1);
+ int index = GetIndex (til.HeaderContent);
+
+ Assert.That (index, Is.EqualTo (1));
+ }
+
+ [Test]
+ public void ShortNameSetBeforeGrouping()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupDisplayBinding = new Binding (".[0]");
+ bindable.GroupShortNameBinding = new Binding (".[0]");
+ bindable.IsGroupingEnabled = true;
+
+ Assert.That (bindable.TemplatedItems.ShortNames[0], Is.EqualTo ("foo"));
+ }
+
+ [Test]
+ public void ItemAddedWithShortNameSetButUngrouped()
+ {
+ var items = new ObservableCollection<string> { "foo", "bar" };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+
+ Assert.That (() => items.Add ("baz"), Throws.Nothing);
+ }
+
+ [Test]
+ public void ItemAddedWithShortNameSetButGroupingDisabled()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+ bindable.IsGroupingEnabled = false;
+
+ Assert.That (() => items.Add (new ObservableCollection<string>()), Throws.Nothing);
+ }
+
+ int GetIndex (BindableObject item)
+ {
+ return TemplatedItemsList<ItemsView<BindableObject>, BindableObject>.GetIndex (item);
+ }
+
+ [Test]
+ public void GetIndex()
+ {
+ var items = new List<string> { "foo", "bar", "baz" };
+
+ bindable.ItemsSource = items;
+
+ BindableObject item = bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+ int index = GetIndex (item);
+ Assert.That (index, Is.EqualTo (1));
+ }
+
+ [Test]
+ public void GetIndexAfterInsert()
+ {
+ var items = new ObservableCollection<string> { "foo", "bar", "baz" };
+
+ bindable.ItemsSource = items;
+
+ BindableObject originalItem = bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+
+ items.Insert (1, "fad");
+
+ BindableObject item = bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+
+ int index = GetIndex (item);
+ Assert.That (index, Is.EqualTo (1));
+
+ index = GetIndex (originalItem);
+ Assert.That (index, Is.EqualTo (2));
+ }
+
+ [Test]
+ public void GetIndexAfterMove()
+ {
+ var items = new ObservableCollection<string> { "foo", "bar", "baz" };
+
+ bindable.ItemsSource = items;
+
+ BindableObject item0 = bindable.TemplatedItems.GetOrCreateContent (0, items[0]);
+ BindableObject item1 = bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+ BindableObject item2 = bindable.TemplatedItems.GetOrCreateContent (2, items[2]);
+
+ items.Move (0, 2); // foo, bar, baz becomes bar (1), baz (2), foo (0)
+
+ Assert.That (GetIndex (item0), Is.EqualTo (2));
+ Assert.That (GetIndex (item1), Is.EqualTo (0));
+ Assert.That (GetIndex (item2), Is.EqualTo (1));
+ }
+
+ [Test]
+ public void GetIndexAfterRemove()
+ {
+ var items = new ObservableCollection<string> { "foo", "bar", "baz" };
+
+ bindable.ItemsSource = items;
+
+ BindableObject item1 = bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+ BindableObject item2 = bindable.TemplatedItems.GetOrCreateContent (2, items[2]);
+
+ items.RemoveAt (0);
+
+ Assert.That (GetIndex (item1), Is.EqualTo (0));
+ Assert.That (GetIndex (item2), Is.EqualTo (1));
+ }
+
+ [Test]
+ public void GetGroup()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ var til = bindable.TemplatedItems.GetGroup (1);
+ var item = til[1];
+
+ var group = TemplatedItemsList<ItemsView<BindableObject>, BindableObject>.GetGroup (item);
+
+ Assert.That (group, Is.SameAs (til));
+ }
+
+ [Test]
+ public void GetIndexGrouped()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ var til = bindable.TemplatedItems.GetGroup (1);
+ var item = til[1];
+
+ int index = GetIndex (item);
+ Assert.That (index, Is.EqualTo (1));
+ }
+
+ [Test]
+ public void GetGroupAndIndexOfItem()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ var result = bindable.TemplatedItems.GetGroupAndIndexOfItem (items[1], items[1][1]);
+
+ Assert.That (result.Item1, Is.EqualTo (1));
+ Assert.That (result.Item2, Is.EqualTo (1));
+ }
+
+ [Test]
+ public void GetGroupAndIndexOfItemNoGroup()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ var result = bindable.TemplatedItems.GetGroupAndIndexOfItem (null, items[1][1]);
+
+ Assert.That (result.Item1, Is.EqualTo (1));
+ Assert.That (result.Item2, Is.EqualTo (1));
+ }
+
+ [Test]
+ public void GetGroupAndIndexOfItemNotFound()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ var group = new ObservableCollection<string> { "bam" };
+
+ var result = bindable.TemplatedItems.GetGroupAndIndexOfItem (group, group[0]);
+
+ Assert.That (result.Item1, Is.EqualTo (-1));
+ Assert.That (result.Item2, Is.EqualTo (-1));
+ }
+
+ [Test]
+ public void GetGroupAndIndexOfItemItemNotFound()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ var result = bindable.TemplatedItems.GetGroupAndIndexOfItem (items[1], "bam");
+
+ Assert.That (result.Item1, Is.EqualTo (1));
+ Assert.That (result.Item2, Is.EqualTo (-1));
+ }
+
+ [Test]
+ [Description ("Issue #2464: ANE thrown when moving items in a ListView")]
+ public void MovingPastRealizedWindowAndBackDoesntThrow()
+ {
+ var items = new ObservableCollection<string> (Enumerable.Range (0, 100).Select (i => i.ToString()));
+
+ bindable.ItemsSource = items;
+
+ bindable.TemplatedItems.GetOrCreateContent (0, items[0]);
+ bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+
+ items.Move (0, 3);
+ Assert.That (() => items.Move (3, 2), Throws.Nothing);
+
+ Assert.That (GetIndex (bindable.TemplatedItems[0]), Is.EqualTo (0));
+ Assert.That (GetIndex (bindable.TemplatedItems[1]), Is.EqualTo (1));
+ Assert.That (GetIndex (bindable.TemplatedItems[2]), Is.EqualTo (2));
+ Assert.That (GetIndex (bindable.TemplatedItems[3]), Is.EqualTo (3));
+ }
+
+ [Test]
+ public void GetGlobalIndexOfItem ()
+ {
+ var items = new ObservableCollection<string> (Enumerable.Range (0, 100).Select (i => i.ToString()));
+ bindable.ItemsSource = items;
+
+ int global = bindable.TemplatedItems.GetGlobalIndexOfItem ("50");
+ Assert.That (global, Is.EqualTo (50));
+ }
+
+ [Test]
+ public void GetGlobalIndexOfItemNotFound ()
+ {
+ var items = new ObservableCollection<string> (Enumerable.Range (0, 100).Select (i => i.ToString()));
+ bindable.ItemsSource = items;
+
+ int global = bindable.TemplatedItems.GetGlobalIndexOfItem ("101");
+ Assert.That (global, Is.EqualTo (-1));
+ }
+
+ [Test]
+ public void GetGlobalIndexOfItemGrouped ()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ int global = bindable.TemplatedItems.GetGlobalIndexOfItem ("baz");
+ Assert.That (global, Is.EqualTo (5));
+ }
+
+ [Test]
+ public void GetGlobalIndexOfItemGroupedNotFound ()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ int global = bindable.TemplatedItems.GetGlobalIndexOfItem ("101");
+ Assert.That (global, Is.EqualTo (-1));
+ }
+
+ [Test]
+ public void GetGlobalIndexOfGroupItemGrouped ()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "baz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ int global = bindable.TemplatedItems.GetGlobalIndexOfItem (items[1], "baz");
+ Assert.That (global, Is.EqualTo (5));
+ }
+
+ [Test]
+ public void GetGlobalIndexOfGroupItemGroupedNotFound ()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "foo", "faz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ int global = bindable.TemplatedItems.GetGlobalIndexOfItem (items[1], "bar");
+ Assert.That (global, Is.EqualTo (-1));
+ }
+
+ [Test]
+ public void GetGlobalIndexOfGroupItemGroupedGroupNotFound ()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "foo", "faz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ int global = bindable.TemplatedItems.GetGlobalIndexOfItem (new object(), "foo");
+ Assert.That (global, Is.EqualTo (-1));
+ }
+
+ [Test]
+ public void SetupContentOnCreation()
+ {
+ var items = new ObservableCollection<string> {
+ "Foo",
+ "Bar"
+ };
+
+ bindable.ItemTemplate = new DataTemplate (typeof (TextCell)) {
+ Bindings = {
+ { TextCell.TextProperty, new Binding (".") }
+ }
+ };
+
+ int count = 0;
+ bindable.Hooked += obj => {
+ count++;
+ Assert.That (obj, Is.InstanceOf (typeof (TextCell)));
+ Assert.That (items, Contains.Item (obj.BindingContext));
+ };
+
+ bindable.ItemsSource = items;
+
+ bindable.TemplatedItems.GetOrCreateContent (0, items[0]);
+ bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+
+ Assert.That (count, Is.EqualTo (2));
+ }
+
+ [Test]
+ public void UnhookGroupOnRemoval()
+ {
+ var inner = new ObservableCollection<string> {
+ "Foo",
+ };
+
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ inner
+ };
+
+ bindable.IsGroupingEnabled = true;
+ bindable.GroupDisplayBinding = new Binding (".[0]");
+
+ bindable.ItemTemplate = new DataTemplate (typeof (TextCell)) {
+ Bindings = {
+ { TextCell.TextProperty, new Binding (".") }
+ }
+ };
+
+ int count = 0;
+ bindable.Unhooked += obj => {
+ if (count == 0) {
+ Assert.That (obj.BindingContext, Is.InstanceOf (typeof (TemplatedItemsList<ItemsView<BindableObject>, BindableObject>)));
+ Assert.That (((TemplatedItemsList<ItemsView<BindableObject>, BindableObject>) obj.BindingContext).ListProxy.ProxiedEnumerable, Is.SameAs (inner));
+ } else {
+ Assert.That (obj.BindingContext, Is.SameAs (inner[0]));
+ }
+
+ count++;
+ };
+
+ bindable.ItemsSource = items;
+
+ var til = bindable.TemplatedItems.GetGroup (0);
+ til.GetOrCreateContent (0, inner[0]);
+
+ Assume.That (til, Is.Not.Null);
+ Assume.That (til.HeaderContent, Is.Not.Null);
+ Assume.That (count, Is.EqualTo (0));
+
+ items.RemoveAt (0);
+
+ Assert.That (count, Is.EqualTo (2));
+ }
+
+ [Test]
+ public void HookAndUnhookGroupOnReplace()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> {
+ "Foo",
+ }
+ };
+
+ bindable.IsGroupingEnabled = true;
+ bindable.GroupDisplayBinding = new Binding (".[0]");
+ bindable.ItemTemplate = new DataTemplate (typeof (TextCell)) {
+ Bindings = {
+ { TextCell.TextProperty, new Binding (".") }
+ }
+ };
+
+ bindable.ItemsSource = items;
+
+ var til = bindable.TemplatedItems.GetGroup (0);
+ til.GetOrCreateContent (0, items[0][0]);
+
+ Assume.That (til, Is.Not.Null);
+ Assume.That (til.HeaderContent, Is.Not.Null);
+
+ int hcount = 0;
+ bindable.Hooked += obj => {
+ Assert.That (obj.BindingContext, Is.InstanceOf (typeof (TemplatedItemsList<ItemsView<BindableObject>, BindableObject>)));
+ hcount++;
+ };
+
+ int ucount = 0;
+ bindable.Unhooked += obj => {
+ Assert.That (obj.BindingContext,
+ Is.InstanceOf (typeof (TemplatedItemsList<ItemsView<BindableObject>, BindableObject>))
+ .Or.EqualTo ("Foo"));
+
+ ucount++;
+ };
+
+ items[0] = new ObservableCollection<string> { "Baz" };
+
+ Assert.That (hcount, Is.EqualTo (1));
+ Assert.That (ucount, Is.EqualTo (2));
+ }
+
+ [Test]
+ public void UnhookContentOnRemoval()
+ {
+ var items = new ObservableCollection<string> {
+ "Foo",
+ "Bar"
+ };
+
+ bindable.ItemTemplate = new DataTemplate (typeof (TextCell)) {
+ Bindings = {
+ { TextCell.TextProperty, new Binding (".") }
+ }
+ };
+
+ int count = 0;
+ bindable.Unhooked += obj => {
+ count++;
+ Assert.That (obj, Is.InstanceOf (typeof (TextCell)));
+ Assert.That (obj.BindingContext, Is.EqualTo ("Foo"));
+ };
+
+ bindable.ItemsSource = items;
+
+ bindable.TemplatedItems.GetOrCreateContent (0, items[0]);
+ bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+
+ Assume.That (count, Is.EqualTo (0));
+
+ items.RemoveAt (0);
+
+ Assert.That (count, Is.EqualTo (1));
+ }
+
+ [Test]
+ public void HookAndUnhookContentOnReplace()
+ {
+ var items = new ObservableCollection<string> {
+ "Foo",
+ "Bar"
+ };
+
+ bindable.ItemTemplate = new DataTemplate (typeof (TextCell)) {
+ Bindings = {
+ { TextCell.TextProperty, new Binding (".") }
+ }
+ };
+
+ bindable.ItemsSource = items;
+
+ bindable.TemplatedItems.GetOrCreateContent (0, items[0]);
+ bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+
+ int hcount = 0;
+ bindable.Hooked += obj => {
+ hcount++;
+ Assert.That (obj, Is.InstanceOf (typeof (TextCell)));
+ Assert.That (obj.BindingContext, Is.EqualTo ("Baz"));
+ };
+
+ int ucount = 0;
+ bindable.Unhooked += obj => {
+ ucount++;
+ Assert.That (obj, Is.InstanceOf (typeof (TextCell)));
+ Assert.That (obj.BindingContext, Is.EqualTo ("Foo"));
+ };
+
+ items[0] = "Baz";
+
+ Assert.That (hcount, Is.EqualTo (1));
+ Assert.That (ucount, Is.EqualTo (1));
+ }
+
+ [Test (Description = "If the cell exists and has an index, we still need to check if it's in the group asked for")]
+ public void IndexOfFailsForCellInAnotherGroup ()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ var group1 = bindable.TemplatedItems.GetGroup (0);
+ var cell = group1[1];
+
+ Assume.That (group1.IndexOf (cell), Is.EqualTo (1));
+
+ var group2 = bindable.TemplatedItems.GetGroup (1);
+
+ Assert.That (group2.IndexOf (cell), Is.EqualTo (-1));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/TextCellTests.cs b/Xamarin.Forms.Core.UnitTests/TextCellTests.cs
new file mode 100644
index 00000000..43965a35
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/TextCellTests.cs
@@ -0,0 +1,129 @@
+using System;
+using NUnit.Framework;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class TextCellTests : BaseTestFixture
+ {
+ [Test]
+ public void TestTapped ()
+ {
+ var cell = new TextCell ();
+ bool tapped = false;
+ cell.Tapped += (sender, args) => tapped = true;
+
+ cell.OnTapped();
+ Assert.True (tapped);
+ }
+
+ [Test]
+ public void TestCommand()
+ {
+ bool executed = false;
+
+ var cmd = new Command (() => executed = true);
+ var cell = new TextCell();
+ cell.Command = cmd;
+ cell.OnTapped();
+
+ Assert.IsTrue (executed, "Command was not executed");
+ }
+
+ [Test]
+ public void TestCommandParameter()
+ {
+ bool executed = false;
+
+ object obj = new object();
+ var cmd = new Command (p => {
+ Assert.AreSame (obj, p);
+ executed = true;
+ });
+
+ var cell = new TextCell {
+ Command = cmd,
+ CommandParameter = obj
+ };
+
+ cell.OnTapped();
+
+ Assert.IsTrue (executed, "Command was not executed");
+ }
+
+ [Test]
+ public void TestCommandCanExecute()
+ {
+ bool tested = false;
+
+ var cmd = new Command (() => { },
+ canExecute: () => {
+ tested = true;
+ return true;
+ });
+
+ new TextCell { Command = cmd };
+ Assert.IsTrue (tested, "Command.CanExecute was not called");
+ }
+
+ [Test]
+ public void TestCommandCanExecuteDisables()
+ {
+ var cmd = new Command (() => { }, () => false);
+ var cell = new TextCell { Command = cmd };
+ Assert.IsFalse (cell.IsEnabled, "Cell was not disabled");
+ }
+
+ [Test]
+ public void TestCommandCanExecuteChanged()
+ {
+ bool first = true;
+ var cmd = new Command (() => { }, () => {
+ if (first) {
+ first = false;
+ return false;
+ } else {
+ return true;
+ }
+ });
+
+ var cell = new TextCell { Command = cmd };
+ Assert.IsFalse (cell.IsEnabled, "Cell was not disabled");
+
+ cmd.ChangeCanExecute();
+
+ Assert.IsTrue (cell.IsEnabled, "Cell was not reenabled");
+ }
+
+ [Test]
+ public void Create ()
+ {
+ var template = new DataTemplate (typeof (TextCell));
+ var content = template.CreateContent ();
+
+ Assert.IsNotNull (content);
+ Assert.That (content, Is.InstanceOf<TextCell> ());
+ }
+
+ [Test]
+ public void Detail ()
+ {
+ var template = new DataTemplate (typeof (TextCell));
+ template.SetValue (TextCell.DetailProperty, "detail");
+
+ TextCell cell = (TextCell)template.CreateContent ();
+ Assert.That (cell.Detail, Is.EqualTo ("detail"));
+ }
+
+ [Test]
+ public void Text ()
+ {
+ var template = new DataTemplate (typeof (TextCell));
+ template.SetValue (TextCell.TextProperty, "text");
+
+ TextCell cell = (TextCell)template.CreateContent ();
+ Assert.That (cell.Text, Is.EqualTo ("text"));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ThicknessTests.cs b/Xamarin.Forms.Core.UnitTests/ThicknessTests.cs
new file mode 100644
index 00000000..2ba08269
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ThicknessTests.cs
@@ -0,0 +1,132 @@
+using NUnit.Framework;
+using System;
+using System.Globalization;
+using System.Security.Cryptography.X509Certificates;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ThicknessTests : BaseTestFixture
+ {
+ [Test]
+ public void Constructor ()
+ {
+ var thickness = new Thickness ();
+
+ Assert.AreEqual (0, thickness.Left);
+ Assert.AreEqual (0, thickness.Top);
+ Assert.AreEqual (0, thickness.Right);
+ Assert.AreEqual (0, thickness.Bottom);
+ Assert.AreEqual (0, thickness.HorizontalThickness);
+ Assert.AreEqual (0, thickness.VerticalThickness);
+ }
+
+ [Test]
+ public void UniformParameterizedConstructor()
+ {
+ var thickness = new Thickness(3);
+
+ Assert.AreEqual(3, thickness.Left);
+ Assert.AreEqual(3, thickness.Top);
+ Assert.AreEqual(3, thickness.Right);
+ Assert.AreEqual(3, thickness.Bottom);
+ Assert.AreEqual(6, thickness.HorizontalThickness);
+ Assert.AreEqual(6, thickness.VerticalThickness);
+ }
+
+ [Test]
+ public void HorizontalVerticalParameterizedConstructor()
+ {
+ var thickness = new Thickness(4, 5);
+
+ Assert.AreEqual(4, thickness.Left);
+ Assert.AreEqual(5, thickness.Top);
+ Assert.AreEqual(4, thickness.Right);
+ Assert.AreEqual(5, thickness.Bottom);
+ Assert.AreEqual(8, thickness.HorizontalThickness);
+ Assert.AreEqual(10, thickness.VerticalThickness);
+ }
+
+ [Test]
+ public void ParameterizedConstructor ()
+ {
+ var thickness = new Thickness (1, 2, 3, 4);
+
+ Assert.AreEqual (1, thickness.Left);
+ Assert.AreEqual (2, thickness.Top);
+ Assert.AreEqual (3, thickness.Right);
+ Assert.AreEqual (4, thickness.Bottom);
+ Assert.AreEqual (4, thickness.HorizontalThickness);
+ Assert.AreEqual (6, thickness.VerticalThickness);
+ }
+
+ [Test]
+ public void ParameterizedConstuctorDoubles ()
+ {
+ var thickness = new Thickness (1.2, 3.3, 4.2, 10.66);
+ Assert.AreEqual (1.2, thickness.Left);
+ Assert.AreEqual (3.3, thickness.Top);
+ Assert.AreEqual (4.2, thickness.Right);
+ Assert.AreEqual (10.66, thickness.Bottom);
+ Assert.AreEqual (5.4, thickness.HorizontalThickness);
+ Assert.AreEqual (13.96, thickness.VerticalThickness);
+ }
+
+ [Test]
+ public void Equality ()
+ {
+ Assert.False (new Thickness ().Equals (null));
+ Assert.False (new Thickness ().Equals ("Thickness"));
+ Assert.False (new Thickness ().Equals (new Thickness (1, 2, 3, 4)));
+ Assert.True (new Thickness ().Equals (new Thickness ()));
+
+ Assert.True (new Thickness () == new Thickness ());
+ Assert.True (new Thickness (4, 3, 2, 1) != new Thickness (1, 2, 3, 4));
+ }
+
+ [Test]
+ public void HashCode ([Range(3, 4)] double l1, [Range(3, 4)] double t1, [Range(3, 4)] double r1, [Range(3, 4)] double b1,
+ [Range(3, 4)] double l2, [Range(3, 4)] double t2, [Range(3, 4)] double r2, [Range(3, 4)] double b2)
+ {
+ bool result = new Thickness (l1, t1, r1, b1).GetHashCode () == new Thickness (l2, t2, r2, b2).GetHashCode ();
+ if (l1 == l2 && t1 == t2 && r1 == r2 && b1 == b2)
+ Assert.True (result);
+ else
+ Assert.False (result);
+ }
+
+ [Test]
+ public void ImplicitConversionFromSize ()
+ {
+ Thickness thickness = new Thickness();
+ Assert.DoesNotThrow (() => thickness = new Size (42, 84));
+ Assert.AreEqual (new Thickness (42, 84), thickness);
+
+ Assert.DoesNotThrow (() => thickness = 42);
+ Assert.AreEqual (new Thickness (42), thickness);
+ }
+
+ [Test]
+ public void TestThicknessTypeConverter ()
+ {
+ var converter = new ThicknessTypeConverter ();
+ Assert.True (converter.CanConvertFrom (typeof(string)));
+ Assert.AreEqual (new Thickness (1), converter.ConvertFromInvariantString ("1"));
+ Assert.AreEqual (new Thickness (1, 2), converter.ConvertFromInvariantString ("1, 2"));
+ Assert.AreEqual (new Thickness (1, 2, 3, 4), converter.ConvertFromInvariantString ("1, 2, 3, 4"));
+ Assert.AreEqual (new Thickness (1.1, 2), converter.ConvertFromInvariantString ("1.1,2"));
+ Assert.Throws<InvalidOperationException> (() => converter.ConvertFromInvariantString (""));
+ }
+
+ [Test]
+ public void ThicknessTypeConverterDoubles ()
+ {
+ var converter = new ThicknessTypeConverter ();
+ Assert.AreEqual (new Thickness (1.3), converter.ConvertFromInvariantString ("1.3"));
+ Assert.AreEqual (new Thickness (1.4, 2.8), converter.ConvertFromInvariantString ("1.4, 2.8"));
+ Assert.AreEqual (new Thickness (1.6, 2.1, 3.8, 4.2), converter.ConvertFromInvariantString (" 1.6 , 2.1, 3.8, 4.2"));
+ Assert.AreEqual (new Thickness (1.1, 2), converter.ConvertFromInvariantString ("1.1,2"));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/TimePickerUnitTest.cs b/Xamarin.Forms.Core.UnitTests/TimePickerUnitTest.cs
new file mode 100644
index 00000000..343d3ed1
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/TimePickerUnitTest.cs
@@ -0,0 +1,43 @@
+using System;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class TimePickerUnitTest : BaseTestFixture
+ {
+ [Test]
+ public void TestConstructor ()
+ {
+ TimePicker picker = new TimePicker ();
+
+ Assert.AreEqual (new TimeSpan (), picker.Time);
+ }
+
+ [Test]
+ public void TestTimeOutOfRange ()
+ {
+ TimePicker picker = new TimePicker ();
+
+ Assert.That (() => picker.Time = new TimeSpan (1000, 0, 0), Throws.ArgumentException);
+ Assert.AreEqual (picker.Time, new TimeSpan ());
+
+ picker.Time = new TimeSpan (8, 30, 0);
+
+ Assert.AreEqual (new TimeSpan (8, 30, 0), picker.Time);
+
+ Assert.That (() => picker.Time = new TimeSpan (-1, 0, 0), Throws.ArgumentException);
+ Assert.AreEqual (new TimeSpan (8, 30, 0), picker.Time);
+ }
+
+ [Test]
+ [Description ("Issue #745")]
+ public void ZeroTimeIsValid()
+ {
+ var picker = new TimePicker ();
+
+ Assert.That (() => picker.Time = new TimeSpan (0, 0, 0), Throws.Nothing);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ToolbarItemTests.cs b/Xamarin.Forms.Core.UnitTests/ToolbarItemTests.cs
new file mode 100644
index 00000000..d5fefb45
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ToolbarItemTests.cs
@@ -0,0 +1,11 @@
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ToolbarItemTests
+ : MenuItemTests
+ {
+
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/ToolbarTrackerTests.cs b/Xamarin.Forms.Core.UnitTests/ToolbarTrackerTests.cs
new file mode 100644
index 00000000..32155be3
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ToolbarTrackerTests.cs
@@ -0,0 +1,194 @@
+using System.Linq;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ internal class ToolbarTrackerTests : BaseTestFixture
+ {
+ [Test]
+ public void Constructor ()
+ {
+ var tracker = new ToolbarTracker ();
+ Assert.Null (tracker.Target);
+ Assert.False (tracker.ToolbarItems.Any ());
+ }
+
+ [Test]
+ public void SimpleTrackEmpty ()
+ {
+ var tracker = new ToolbarTracker ();
+
+ var page = new ContentPage ();
+ tracker.Target = page;
+
+ Assert.False (tracker.ToolbarItems.Any ());
+ }
+
+ [Test]
+ public void SimpleTrackWithItems ()
+ {
+ var tracker = new ToolbarTracker ();
+
+ ToolbarItem item1, item2;
+ var page = new ContentPage {
+ ToolbarItems = {
+ new ToolbarItem ("Foo", "Foo.png", () => {}),
+ new ToolbarItem ("Bar", "Bar.png", () => {})
+ }
+ };
+ tracker.Target = page;
+
+ Assert.True (tracker.ToolbarItems.Contains (page.ToolbarItems[0]));
+ Assert.True (tracker.ToolbarItems.Contains (page.ToolbarItems[1]));
+ }
+
+ [Test]
+ public void TrackPreConstructedTabbedPage ()
+ {
+ var tracker = new ToolbarTracker ();
+
+ var toolbarItem1 = new ToolbarItem ("Foo", "Foo.png", () => { });
+ var toolbarItem2 = new ToolbarItem ("Foo", "Foo.png", () => { });
+ var toolbarItem3 = new ToolbarItem ("Foo", "Foo.png", () => { });
+
+ var subPage1 = new ContentPage {
+ ToolbarItems = {toolbarItem1}
+ };
+
+ var subPage2 = new ContentPage {
+ ToolbarItems = {toolbarItem2, toolbarItem3}
+ };
+
+ var tabbedpage = new TabbedPage {
+ Children = {
+ subPage1,
+ subPage2
+ }
+ };
+
+ tabbedpage.CurrentPage = subPage1;
+
+ tracker.Target = tabbedpage;
+
+ Assert.True (tracker.ToolbarItems.Count () == 1);
+ Assert.True (tracker.ToolbarItems.First () == subPage1.ToolbarItems[0]);
+
+ bool changed = false;
+ tracker.CollectionChanged += (sender, args) => changed = true;
+
+ tabbedpage.CurrentPage = subPage2;
+
+ Assert.True (tracker.ToolbarItems.Count () == 2);
+ Assert.True (tracker.ToolbarItems.First () == subPage2.ToolbarItems[0]);
+ Assert.True (tracker.ToolbarItems.Last () == subPage2.ToolbarItems[1]);
+ }
+
+ [Test]
+ public void AdditionalTargets ()
+ {
+ var tracker = new ToolbarTracker ();
+
+ var toolbarItem1 = new ToolbarItem ("Foo", "Foo.png", () => { });
+ var toolbarItem2 = new ToolbarItem ("Foo", "Foo.png", () => { });
+
+ var page = new ContentPage {
+ ToolbarItems = {
+ toolbarItem1
+ }
+ };
+
+ var additionalPage = new ContentPage {
+ ToolbarItems = {toolbarItem2}
+ };
+
+ tracker.Target = page;
+ tracker.AdditionalTargets = new[] {additionalPage};
+
+ Assert.True (tracker.ToolbarItems.Contains (toolbarItem1));
+ Assert.True (tracker.ToolbarItems.Contains (toolbarItem2));
+ }
+
+ [Test]
+ public async Task PushAfterTrackingStarted ()
+ {
+ var tracker = new ToolbarTracker ();
+
+ var toolbarItem1 = new ToolbarItem ("Foo", "Foo.png", () => { });
+ var toolbarItem2 = new ToolbarItem ("Foo", "Foo.png", () => { });
+
+ var page = new NavigationPage {
+ ToolbarItems = {
+ toolbarItem1
+ }
+ };
+
+ var firstPage = new ContentPage {
+ ToolbarItems = { toolbarItem2 }
+ };
+
+ tracker.Target = page;
+
+ Assert.True (tracker.ToolbarItems.Contains (toolbarItem1));
+ Assert.False (tracker.ToolbarItems.Contains (toolbarItem2));
+
+ await page.Navigation.PushAsync (firstPage);
+
+ Assert.True (tracker.ToolbarItems.Contains (toolbarItem1));
+ Assert.True (tracker.ToolbarItems.Contains (toolbarItem2));
+ }
+
+ [Test]
+ public async Task PopAfterTrackingStarted ()
+ {
+ var tracker = new ToolbarTracker ();
+
+ var toolbarItem1 = new ToolbarItem ("Foo", "Foo.png", () => { });
+ var toolbarItem2 = new ToolbarItem ("Foo", "Foo.png", () => { });
+
+ var page = new NavigationPage (new ContentPage ()) {
+ ToolbarItems = {
+ toolbarItem1
+ }
+ };
+
+ var firstPage = new ContentPage {
+ ToolbarItems = { toolbarItem2 }
+ };
+
+ tracker.Target = page;
+
+ await page.Navigation.PushAsync (firstPage);
+
+ Assert.True (tracker.ToolbarItems.Contains (toolbarItem1));
+ Assert.True (tracker.ToolbarItems.Contains (toolbarItem2));
+
+ await page.Navigation.PopAsync ();
+
+ Assert.True (tracker.ToolbarItems.Contains (toolbarItem1));
+ Assert.False (tracker.ToolbarItems.Contains (toolbarItem2));
+ }
+
+ [Test]
+ public void UnsetTarget ()
+ {
+ var tracker = new ToolbarTracker ();
+
+ ToolbarItem item1, item2;
+ var page = new ContentPage {
+ ToolbarItems = {
+ new ToolbarItem ("Foo", "Foo.png", () => {}),
+ new ToolbarItem ("Bar", "Bar.png", () => {})
+ }
+ };
+ tracker.Target = page;
+
+ Assert.True (tracker.ToolbarItems.Count () == 2);
+
+ tracker.Target = null;
+
+ Assert.False (tracker.ToolbarItems.Any ());
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ToolbarUnitTests.cs b/Xamarin.Forms.Core.UnitTests/ToolbarUnitTests.cs
new file mode 100644
index 00000000..efe07ebf
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ToolbarUnitTests.cs
@@ -0,0 +1,144 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ToolbarUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestConstructor ()
+ {
+ Toolbar toolbar = new Toolbar ();
+
+ Assert.That (toolbar.Items, Is.Empty);
+ }
+
+ [Test]
+ public void TestAdd ()
+ {
+ Toolbar toolbar = new Toolbar ();
+
+ ToolbarItem item = new ToolbarItem ("Foo", "Bar.jpg", () => {});
+ toolbar.Add (item);
+
+ Assert.AreEqual (item, toolbar.Items [0]);
+ }
+
+ [Test]
+ public void TestRemove ()
+ {
+ Toolbar toolbar = new Toolbar ();
+
+ ToolbarItem item = new ToolbarItem ("Foo", "Bar.jpg", () => {});
+ ToolbarItem item2 = new ToolbarItem ("Foo", "Bar.jpg", () => {});
+ toolbar.Add (item);
+ toolbar.Add (item2);
+
+ toolbar.Remove (item);
+
+ Assert.AreEqual (item2, toolbar.Items [0]);
+ }
+
+ [Test]
+ public void TestItemAdded ()
+ {
+ Toolbar toolbar = new Toolbar ();
+
+ ToolbarItem item = new ToolbarItem ("Foo", "Bar.jpg", () => {});
+
+ bool added = false;
+ toolbar.ItemAdded += (sender, e) => added = true;
+
+ toolbar.Add (item);
+
+ Assert.True (added);
+
+ added = false;
+ toolbar.Add (item);
+
+ Assert.False (added);
+ }
+
+ [Test]
+ public void TestItemRemoved ()
+ {
+ Toolbar toolbar = new Toolbar ();
+
+ ToolbarItem item = new ToolbarItem ("Foo", "Bar.jpg", () => {});
+ toolbar.Add (item);
+
+ bool removed = false;
+ toolbar.ItemRemoved += (sender, e) => removed = true;
+
+ toolbar.Remove (item);
+
+ Assert.True (removed);
+ }
+
+ [Test]
+ public void TestClear ()
+ {
+ var toolbar = new Toolbar ();
+
+ var item = new ToolbarItem ("Foo", "Bar.jpg", () => {});
+ var item2 = new ToolbarItem ("Foo", "Bar.jpg", () => {});
+
+ toolbar.Add (item);
+ toolbar.Add (item2);
+
+ toolbar.Clear ();
+
+ Assert.That (toolbar.Items, Is.Empty);
+ }
+
+ [Test]
+ public void ToolBarItemAddedEventArgs ()
+ {
+ var toolbar = new Toolbar ();
+
+ var item = new ToolbarItem ("Foo", "Bar.jpg", () => { });
+ var item2 = new ToolbarItem ("Foo", "Bar.jpg", () => { });
+
+ ToolbarItem itemArg = null;
+
+ toolbar.ItemAdded += (s, e) => {
+ itemArg = e.ToolbarItem;
+ };
+
+ toolbar.Add (item);
+ Assert.AreEqual (item, itemArg);
+
+ toolbar.Add (item2);
+ Assert.AreEqual (item2, itemArg);
+ }
+
+ [Test]
+ public void ToolBarItemRemovedEventArgs ()
+ {
+ var toolbar = new Toolbar ();
+
+ var item = new ToolbarItem ("Foo", "Bar.jpg", () => { });
+ var item2 = new ToolbarItem ("Foo", "Bar.jpg", () => { });
+
+ toolbar.Add (item);
+ toolbar.Add (item2);
+
+ ToolbarItem itemArg = null;
+
+ toolbar.ItemRemoved += (s, e) => {
+ itemArg = e.ToolbarItem;
+ };
+
+ toolbar.Remove (item);
+ Assert.AreEqual (item, itemArg);
+
+ toolbar.Remove (item2);
+ Assert.AreEqual (item2, itemArg);
+ }
+ }
+
+}
diff --git a/Xamarin.Forms.Core.UnitTests/TriggerTests.cs b/Xamarin.Forms.Core.UnitTests/TriggerTests.cs
new file mode 100644
index 00000000..1fe16669
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/TriggerTests.cs
@@ -0,0 +1,116 @@
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class TriggerTests : BaseTestFixture
+ {
+ class MockElement : VisualElement
+ {
+ }
+
+ [Test]
+ public void SettersAppliedOnConditionChanged ()
+ {
+ var conditionbp = BindableProperty.Create ("foo", typeof(string), typeof(BindableObject), null);
+ var setterbp = BindableProperty.Create ("bar", typeof(string), typeof(BindableObject), null);
+ var element = new MockElement ();
+ var trigger = new Trigger (typeof(VisualElement)) {
+ Property = conditionbp,
+ Value = "foobar",
+ Setters = {
+ new Setter { Property = setterbp, Value = "qux" },
+ }
+ };
+
+ element.SetValue (setterbp, "default");
+ element.Triggers.Add (trigger);
+
+ Assert.AreEqual ("default", element.GetValue (setterbp));
+ element.SetValue (conditionbp, "foobar");
+ Assert.AreEqual ("qux", element.GetValue (setterbp));
+ element.SetValue (conditionbp, "");
+ Assert.AreEqual ("default", element.GetValue (setterbp));
+ }
+
+ [Test]
+ public void SettersAppliedOnAttachIfConditionIsTrue ()
+ {
+ var conditionbp = BindableProperty.Create ("foo", typeof(string), typeof(BindableObject), null);
+ var setterbp = BindableProperty.Create ("bar", typeof(string), typeof(BindableObject), null);
+ var element = new MockElement ();
+ var trigger = new Trigger (typeof(VisualElement)) {
+ Property = conditionbp,
+ Value = "foobar",
+ Setters = {
+ new Setter { Property = setterbp, Value = "qux" },
+ }
+ };
+
+ element.SetValue (setterbp, "default");
+ element.SetValue (conditionbp, "foobar");
+ Assert.AreEqual ("default", element.GetValue (setterbp));
+ element.Triggers.Add (trigger);
+ Assert.AreEqual ("qux", element.GetValue (setterbp));
+ }
+
+ [Test]
+ public void SettersUnappliedOnDetach ()
+ {
+ var conditionbp = BindableProperty.Create ("foo", typeof(string), typeof(BindableObject), null);
+ var setterbp = BindableProperty.Create ("bar", typeof(string), typeof(BindableObject), null);
+ var element = new MockElement ();
+ var trigger = new Trigger (typeof(VisualElement)) {
+ Property = conditionbp,
+ Value = "foobar",
+ Setters = {
+ new Setter { Property = setterbp, Value = "qux" },
+ }
+ };
+
+ element.SetValue (setterbp, "default");
+ element.Triggers.Add (trigger);
+
+ Assert.AreEqual ("default", element.GetValue (setterbp));
+ element.SetValue (conditionbp, "foobar");
+ Assert.AreEqual ("qux", element.GetValue (setterbp));
+ element.Triggers.Remove (trigger);
+ Assert.AreEqual ("default", element.GetValue (setterbp));
+ }
+
+ [Test]
+ public void EnterAndExitActionsTriggered ()
+ {
+ var conditionbp = BindableProperty.Create ("foo", typeof(string), typeof(BindableObject), null);
+ var element = new MockElement ();
+ var enteraction = new MockTriggerAction ();
+ var exitaction = new MockTriggerAction ();
+ var trigger = new Trigger (typeof(VisualElement)) {
+ Property = conditionbp,
+ Value = "foobar",
+ EnterActions = {
+ enteraction
+ },
+ ExitActions = {
+ exitaction
+ }
+ };
+
+ Assert.False (enteraction.Invoked);
+ Assert.False (exitaction.Invoked);
+ element.Triggers.Add (trigger);
+ Assert.False (enteraction.Invoked);
+ Assert.False (exitaction.Invoked);
+ element.SetValue (conditionbp, "foobar");
+ Assert.True (enteraction.Invoked);
+ Assert.False (exitaction.Invoked);
+
+ enteraction.Invoked = exitaction.Invoked = false;
+ Assert.False (enteraction.Invoked);
+ Assert.False (exitaction.Invoked);
+ element.SetValue (conditionbp, "");
+ Assert.False (enteraction.Invoked);
+ Assert.True (exitaction.Invoked);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/TypeUnitTests.cs b/Xamarin.Forms.Core.UnitTests/TypeUnitTests.cs
new file mode 100644
index 00000000..70c40a55
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/TypeUnitTests.cs
@@ -0,0 +1,23 @@
+using NUnit.Framework;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class TypeUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestVec2 ()
+ {
+ var vec2 = new Vec2 ();
+
+ Assert.AreEqual (0, vec2.X);
+ Assert.AreEqual (0, vec2.Y);
+
+ vec2 = new Vec2 (2, 3);
+
+ Assert.AreEqual (2, vec2.X);
+ Assert.AreEqual (3, vec2.Y);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/UnitPlatform.cs b/Xamarin.Forms.Core.UnitTests/UnitPlatform.cs
new file mode 100644
index 00000000..8dbf3e04
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/UnitPlatform.cs
@@ -0,0 +1,40 @@
+using System;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ public class UnitPlatform : IPlatform
+ {
+ Page page;
+ Func<VisualElement, double, double, SizeRequest> getNativeSizeFunc;
+ readonly bool useRealisticLabelMeasure;
+
+ public UnitPlatform (Func<VisualElement, double, double, SizeRequest> getNativeSizeFunc = null, bool useRealisticLabelMeasure = false)
+ {
+ this.getNativeSizeFunc = getNativeSizeFunc;
+ this.useRealisticLabelMeasure = useRealisticLabelMeasure;
+ }
+
+ public SizeRequest GetNativeSize (VisualElement view, double widthConstraint, double heightConstraint)
+ {
+ if (getNativeSizeFunc != null)
+ return getNativeSizeFunc (view, widthConstraint, heightConstraint);
+ // EVERYTHING IS 100 x 20
+
+ var label = view as Label;
+ if (label != null && useRealisticLabelMeasure) {
+ var letterSize = new Size (5, 10);
+ var w = label.Text.Length * letterSize.Width;
+ var h = letterSize.Height;
+ if (!double.IsPositiveInfinity (widthConstraint) && w > widthConstraint) {
+ h = ((int) w / (int) widthConstraint) * letterSize.Height;
+ w = widthConstraint - (widthConstraint % letterSize.Width);
+
+ }
+ return new SizeRequest (new Size (w, h), new Size (Math.Min (10, w), h));
+ }
+
+ return new SizeRequest(new Size (100, 20));
+ }
+ }
+
+}
diff --git a/Xamarin.Forms.Core.UnitTests/UriImageSourceTests.cs b/Xamarin.Forms.Core.UnitTests/UriImageSourceTests.cs
new file mode 100644
index 00000000..39bce931
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/UriImageSourceTests.cs
@@ -0,0 +1,145 @@
+using System;
+using NUnit.Framework;
+using System.Threading;
+using System.IO;
+using System.Threading.Tasks;
+using System.Reflection;
+using System.IO.IsolatedStorage;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class UriImageSourceTests : BaseTestFixture
+ {
+ IsolatedStorageFile NativeStore { get; set; }
+
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices (getStreamAsync: GetStreamAsync);
+ NativeStore = IsolatedStorageFile.GetUserStoreForAssembly ();
+ networkcalls = 0;
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ string cacheName = "ImageLoaderCache";
+ if (NativeStore.DirectoryExists (cacheName)) {
+ foreach (var f in NativeStore.GetFileNames (cacheName + "/*"))
+ NativeStore.DeleteFile (Path.Combine (cacheName, f));
+ }
+ NativeStore.Dispose ();
+ NativeStore = null;
+ }
+
+ static Random rnd = new Random ();
+ static int networkcalls = 0;
+ static async Task<Stream> GetStreamAsync (Uri uri, CancellationToken cancellationToken)
+ {
+ await Task.Delay (rnd.Next (30, 2000));
+ if (cancellationToken.IsCancellationRequested)
+ throw new TaskCanceledException ();
+ networkcalls++;
+ return typeof(UriImageSourceTests).Assembly.GetManifestResourceStream (uri.LocalPath.Substring (1));
+ }
+
+ [Test]
+ [Ignore]
+ public void LoadImageFromStream ()
+ {
+ var loader = new UriImageSource {
+ Uri = new Uri ("http://foo.com/Images/crimson.jpg"),
+ };
+ Stream s0 = loader.GetStreamAsync ().Result;
+
+ Assert.AreEqual (79109, s0.Length);
+ }
+
+ [Test]
+ [Ignore]
+ public void SecondCallLoadFromCache ()
+ {
+ var loader = new UriImageSource {
+ Uri = new Uri ("http://foo.com/Images/crimson.jpg"),
+ };
+ Assert.AreEqual (0, networkcalls);
+
+ using (var s0 = loader.GetStreamAsync ().Result) {
+ Assert.AreEqual (79109, s0.Length);
+ Assert.AreEqual (1, networkcalls);
+ }
+
+ using (var s1 = loader.GetStreamAsync ().Result) {
+ Assert.AreEqual (79109, s1.Length);
+ Assert.AreEqual (1, networkcalls);
+ }
+ }
+
+ [Test]
+ [Ignore]
+ public void DoNotKeepFailedRetrieveInCache ()
+ {
+ var loader = new UriImageSource {
+ Uri = new Uri ("http://foo.com/missing.png"),
+ };
+ Assert.AreEqual (0, networkcalls);
+
+ var s0 = loader.GetStreamAsync ().Result;
+ Assert.IsNull (s0);
+ Assert.AreEqual (1, networkcalls);
+
+ var s1 = loader.GetStreamAsync ().Result;
+ Assert.IsNull (s1);
+ Assert.AreEqual (2, networkcalls);
+ }
+
+ [Test]
+ [Ignore]
+ public void ConcurrentCallsOnSameUriAreQueued ()
+ {
+ var loader = new UriImageSource {
+ Uri = new Uri ("http://foo.com/Images/crimson.jpg"),
+ };
+ Assert.AreEqual (0, networkcalls);
+
+ var t0 = loader.GetStreamAsync ();
+ var t1 = loader.GetStreamAsync ();
+
+ //var s0 = t0.Result;
+ using (var s1 = t1.Result) {
+ Assert.AreEqual (1, networkcalls);
+ Assert.AreEqual (79109, s1.Length);
+ }
+ }
+
+ [Test]
+ public void NullUriDoesNotCrash ()
+ {
+ var loader = new UriImageSource ();
+ Assert.DoesNotThrow (() => {
+ loader.Uri = null;
+ });
+ }
+
+ [Test]
+ public void UrlHashKeyAreTheSame ()
+ {
+ var urlHash1 = Device.PlatformServices.GetMD5Hash ("http://www.optipess.com/wp-content/uploads/2010/08/02_Bad-Comics6-10.png?a=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbasdasdasdasdasasdasdasdasdasd");
+ var urlHash2 = Device.PlatformServices.GetMD5Hash ("http://www.optipess.com/wp-content/uploads/2010/08/02_Bad-Comics6-10.png?a=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbasdasdasdasdasasdasdasdasdasd");
+ Assert.IsTrue (urlHash1 == urlHash2);
+ }
+
+ [Test]
+ public void UrlHashKeyAreNotTheSame ()
+ {
+ var urlHash1 = Device.PlatformServices.GetMD5Hash ("http://www.optipess.com/wp-content/uploads/2010/08/02_Bad-Comics6-10.png?a=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbasdasdasdasdasasdasdasdasdasd");
+ var urlHash2 = Device.PlatformServices.GetMD5Hash ("http://www.optipess.com/wp-content/uploads/2010/08/02_Bad-Comics6-10.png?a=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbasdasdasdasdasasdasda");
+ Assert.IsTrue (urlHash1 != urlHash2);
+ }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ViewCellTests.cs b/Xamarin.Forms.Core.UnitTests/ViewCellTests.cs
new file mode 100644
index 00000000..2a8647d4
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ViewCellTests.cs
@@ -0,0 +1,65 @@
+using System;
+using NUnit.Framework;
+
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ViewCellTests : BaseTestFixture
+ {
+ [Test]
+ public void SetParentBeforeView ()
+ {
+ var parent = new View { Platform = new UnitPlatform () };
+ var child = new View ();
+ var viewCell = new ViewCell ();
+
+ Assert.Null (viewCell.View);
+ Assert.DoesNotThrow (() => viewCell.Parent = parent);
+
+ viewCell.View = child;
+ Assert.AreSame (parent, viewCell.Parent);
+ Assert.AreSame (viewCell, child.Parent);
+ Assert.AreSame (parent.Platform, child.Platform);
+ }
+
+ [Test]
+ //issue 550
+ public void SetBindingContextBeforeParent ()
+ {
+ var parent = new View {
+ Platform = new UnitPlatform (),
+ BindingContext = new object (),
+ };
+
+ var itemcontext = new object ();
+ var cell = new ViewCell { View = new Label ()};
+ cell.BindingContext = itemcontext;
+ cell.Parent = parent;
+
+ Assert.AreSame (itemcontext, cell.View.BindingContext);
+ }
+
+ [Test]
+ public void SetBindingContextBeforeView ()
+ {
+ var context = new object ();
+ var view = new View ();
+ var cell = new ViewCell ();
+ cell.BindingContext = context;
+ cell.View = view;
+ Assert.AreSame (context, view.BindingContext);
+ }
+
+ [Test]
+ public void SetViewBeforeBindingContext ()
+ {
+ var context = new object ();
+ var view = new View ();
+ var cell = new ViewCell ();
+ cell.View = view;
+ cell.BindingContext = context;
+ Assert.AreSame (context, view.BindingContext);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/ViewUnitTests.cs b/Xamarin.Forms.Core.UnitTests/ViewUnitTests.cs
new file mode 100644
index 00000000..97700ca4
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/ViewUnitTests.cs
@@ -0,0 +1,868 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Threading.Tasks;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class ViewUnitTests : BaseTestFixture
+ {
+ [SetUp]
+ public override void Setup ()
+ {
+ base.Setup ();
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown ()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void TestLayout ()
+ {
+ View view = new View ();
+ view.Layout (new Rectangle (50, 25, 100, 200));
+
+ Assert.AreEqual (view.X, 50);
+ Assert.AreEqual (view.Y, 25);
+ Assert.AreEqual (view.Width, 100);
+ Assert.AreEqual (view.Height, 200);
+ }
+
+ [Test]
+ public void TestPreferredSize ()
+ {
+ View view = new View {
+ IsPlatformEnabled = true,
+ Platform = new UnitPlatform ()
+ };
+
+ bool fired = false;
+ view.MeasureInvalidated += (sender, e) => fired = true;
+
+ view.WidthRequest = 200;
+ view.HeightRequest = 300;
+
+ Assert.True (fired);
+
+ var result = view.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity).Request;
+ Assert.AreEqual (new Size (200, 300), result);
+ }
+
+ [Test]
+ public void TestSizeChangedEvent ()
+ {
+ View view = new View ();
+
+ bool fired = false;
+ view.SizeChanged += (sender, e) => fired = true;
+
+ view.Layout (new Rectangle (0, 0, 100, 100));
+
+ Assert.True (fired);
+ }
+
+ [Test]
+ public void TestOpacityClamping ()
+ {
+ var view = new View ();
+
+ view.Opacity = -1;
+ Assert.AreEqual (0, view.Opacity);
+
+ view.Opacity = 2;
+ Assert.AreEqual (1, view.Opacity);
+ }
+
+ [Test]
+ public void TestMeasureInvalidatedFiredOnVisibilityChanged ()
+ {
+ var view = new View {IsVisible = false};
+ bool signaled = false;
+ view.MeasureInvalidated += (sender, e) => {
+ signaled = true;
+ };
+ view.IsVisible = true;
+ Assert.True (signaled);
+ }
+
+ [Test]
+ public void TestOnPlatformiOS ()
+ {
+ var view = new View ();
+
+ bool ios = false;
+ bool android = false;
+ bool winphone = false;
+
+ Device.OS = TargetPlatform.iOS;
+
+ Device.OnPlatform (
+ iOS: () => ios = true,
+ Android: () => android = true,
+ WinPhone: () => winphone = true);
+
+ Assert.True (ios);
+ Assert.False (android);
+ Assert.False (winphone);
+ }
+
+ [Test]
+ public void TestOnPlatformAndroid ()
+ {
+ var view = new View ();
+
+ bool ios = false;
+ bool android = false;
+ bool winphone = false;
+
+ Device.OS = TargetPlatform.Android;
+
+ Device.OnPlatform (
+ iOS: () => ios = true,
+ Android: () => android = true,
+ WinPhone: () => winphone = true);
+
+ Assert.False (ios);
+ Assert.True (android);
+ Assert.False (winphone);
+ }
+
+ [Test]
+ public void TestOnPlatformWinPhone ()
+ {
+ var view = new View ();
+
+ bool ios = false;
+ bool android = false;
+ bool winphone = false;
+
+ Device.OS = TargetPlatform.WinPhone;
+
+ Device.OnPlatform (
+ iOS: () => ios = true,
+ Android: () => android = true,
+ WinPhone: () => winphone = true);
+
+ Assert.False (ios);
+ Assert.False (android);
+ Assert.True (winphone);
+ }
+
+ [Test]
+ public void TestOnPlatformDefault ()
+ {
+ var view = new View ();
+
+ bool ios = false;
+ bool android = false;
+
+ Device.OS = TargetPlatform.Android;
+
+ Device.OnPlatform (
+ iOS: () => ios = false,
+ Default: () => android = true);
+
+ Assert.False (ios);
+ Assert.True (android);
+ }
+
+ [Test]
+ public void TestOnPlatformNoOpWithoutDefault ()
+ {
+ bool any = false;
+ Device.OS = TargetPlatform.Other;
+
+ Device.OnPlatform (
+ iOS: () => any = true,
+ Android: () => any = true,
+ WinPhone: () => any = true);
+
+ Assert.False (any);
+ }
+
+ [Test]
+ public void TestDefaultOniOS ()
+ {
+ bool defaultExecuted = false;
+
+ Device.OS = TargetPlatform.iOS;
+
+ Device.OnPlatform (
+ Android: () => { },
+ WinPhone: () => { },
+ Default:() => defaultExecuted = true);
+
+ Assert.True (defaultExecuted);
+ }
+
+ [Test]
+ public void TestDefaultOnAndroid ()
+ {
+ bool defaultExecuted = false;
+
+ Device.OS = TargetPlatform.Android;
+
+ Device.OnPlatform (
+ iOS: () => { },
+ WinPhone: () => { },
+ Default:() => defaultExecuted = true);
+
+ Assert.True (defaultExecuted);
+ }
+
+ [Test]
+ public void TestDefaultOnWinPhone ()
+ {
+ bool defaultExecuted = false;
+
+ Device.OS = TargetPlatform.WinPhone;
+
+ Device.OnPlatform (
+ iOS: () => { },
+ Android: () => { },
+ Default:() => defaultExecuted = true);
+
+ Assert.True (defaultExecuted);
+ }
+
+ [Test]
+ public void TestDefaultOnOther ()
+ {
+ bool defaultExecuted = false;
+
+ Device.OS = TargetPlatform.Other;
+
+ Device.OnPlatform (
+ iOS: () => { },
+ Android: () => { },
+ WinPhone: () => { },
+ Default:() => defaultExecuted = true);
+
+ Assert.True (defaultExecuted);
+ }
+
+ [Test]
+ public void TestNativeStateConsistent ()
+ {
+ var view = new View { IsPlatformEnabled = true };
+
+ Assert.True (view.IsNativeStateConsistent);
+
+ view.IsNativeStateConsistent = false;
+
+ Assert.False (view.IsNativeStateConsistent);
+
+ bool sizeChanged = false;
+ view.MeasureInvalidated += (sender, args) => {
+ sizeChanged = true;
+ };
+
+ view.IsNativeStateConsistent = true;
+
+ Assert.True (sizeChanged);
+
+ sizeChanged = false;
+ view.IsNativeStateConsistent = true;
+
+ Assert.False (sizeChanged);
+ }
+
+ [Test]
+ public void TestFadeTo ()
+ {
+ var view = new View {IsPlatformEnabled = true, Platform = new UnitPlatform ()};
+ Ticker.Default = new BlockingTicker ();
+
+ view.FadeTo (0.1);
+
+ Assert.True (Math.Abs (0.1 - view.Opacity) < 0.001);
+ }
+
+ [Test]
+ public void TestTranslateTo ()
+ {
+ var view = new View {IsPlatformEnabled = true, Platform = new UnitPlatform ()};
+ Ticker.Default = new BlockingTicker ();
+
+ view.TranslateTo (100, 50);
+
+ Assert.AreEqual (100, view.TranslationX);
+ Assert.AreEqual (50, view.TranslationY);
+ }
+
+ [Test]
+ public void ScaleTo ()
+ {
+ var view = new View {IsPlatformEnabled = true, Platform = new UnitPlatform ()};
+ Ticker.Default = new BlockingTicker ();
+
+ view.ScaleTo (2);
+
+ Assert.AreEqual (2, view.Scale);
+ }
+
+ [Test]
+ public void TestNativeSizeChanged ()
+ {
+ var view = new View ();
+
+ bool sizeChanged = false;
+ view.MeasureInvalidated += (sender, args) => sizeChanged = true;
+
+ ((IVisualElementController)view).NativeSizeChanged ();
+
+ Assert.True (sizeChanged);
+ }
+
+ [Test]
+ public void TestRotateTo ()
+ {
+ var view = new View {IsPlatformEnabled = true, Platform = new UnitPlatform ()};
+ Ticker.Default = new BlockingTicker ();
+
+ view.RotateTo (25);
+
+ Assert.That (view.Rotation, Is.EqualTo (25).Within (0.001));
+ }
+
+ [Test]
+ public void TestRotateYTo ()
+ {
+ var view = new View {IsPlatformEnabled = true, Platform = new UnitPlatform ()};
+ Ticker.Default = new BlockingTicker ();
+
+ view.RotateYTo (25);
+
+ Assert.That (view.RotationY, Is.EqualTo (25).Within (0.001));
+ }
+
+ [Test]
+ public void TestRotateXTo ()
+ {
+ var view = new View {IsPlatformEnabled = true, Platform = new UnitPlatform ()};
+ Ticker.Default = new BlockingTicker ();
+
+ view.RotateXTo (25);
+
+ Assert.That (view.RotationX, Is.EqualTo (25).Within (0.001));
+ }
+
+ [Test]
+ public void TestRelRotateTo ()
+ {
+ var view = new View {Rotation = 30, IsPlatformEnabled = true, Platform = new UnitPlatform ()};
+ Ticker.Default = new BlockingTicker ();
+
+ view.RelRotateTo (20);
+
+ Assert.That (view.Rotation, Is.EqualTo (50).Within (0.001));
+ }
+
+ [Test]
+ public void TestRelScaleTo ()
+ {
+ var view = new View {Scale = 1, IsPlatformEnabled = true, Platform = new UnitPlatform ()};
+ Ticker.Default = new BlockingTicker ();
+
+ view.RelScaleTo (1);
+
+ Assert.That (view.Scale, Is.EqualTo (2).Within (0.001));
+ }
+
+ class ParentSignalView : View
+ {
+ public bool ParentSet { get; set; }
+
+ protected override void OnParentSet ()
+ {
+ ParentSet = true;
+ base.OnParentSet ();
+ }
+ }
+
+ [Test]
+ public void TestDoubleSetParent ()
+ {
+ var view = new ParentSignalView ();
+ var parent = new NaiveLayout {Children = {view}};
+
+ view.ParentSet = false;
+ view.Parent = parent;
+
+ Assert.False (view.ParentSet, "OnParentSet should not be called in the event the parent is already properly set");
+ }
+
+ [Test]
+ public void TestAncestorAdded ()
+ {
+ var child = new NaiveLayout ();
+ var view = new NaiveLayout {Children = {child}};
+
+ bool added = false;
+ view.DescendantAdded += (sender, arg) => added = true;
+
+ child.Children.Add (new View ());
+
+ Assert.True (added, "AncestorAdded must fire when adding a child to an ancestor of a view.");
+ }
+
+ [Test]
+ public void TestAncestorRemoved ()
+ {
+ var ancestor = new View ();
+ var child = new NaiveLayout {Children = {ancestor}};
+ var view = new NaiveLayout {Children = {child}};
+
+ bool removed = false;
+ view.DescendantRemoved += (sender, arg) => removed = true;
+
+ child.Children.Remove (ancestor);
+ Assert.True (removed, "AncestorRemoved must fire when removing a child from an ancestor of a view.");
+ }
+
+ [Test]
+ public void TestOnPlatformGeneric ()
+ {
+ Device.OS = TargetPlatform.WinPhone;
+ Assert.AreEqual (3, Device.OnPlatform (1, 2, 3));
+
+ Device.OS = TargetPlatform.iOS;
+ Assert.AreEqual (1, Device.OnPlatform (1, 2, 3));
+
+ Device.OS = TargetPlatform.Android;
+ Assert.AreEqual (2, Device.OnPlatform (1, 2, 3));
+
+ Device.OS = TargetPlatform.Other;
+ Assert.AreEqual (1, Device.OnPlatform (1, 2, 3));
+ }
+
+ [Test]
+ public void TestBatching ()
+ {
+ var view = new View ();
+
+ bool committed = false;
+ view.BatchCommitted += (sender, arg) => committed = true;
+
+ view.BatchBegin ();
+
+ Assert.True (view.Batched);
+
+ view.BatchBegin ();
+
+ Assert.True (view.Batched);
+
+ view.BatchCommit ();
+
+ Assert.True (view.Batched);
+ Assert.False (committed);
+
+ view.BatchCommit ();
+
+ Assert.False (view.Batched);
+ Assert.True (committed);
+ }
+
+ [Test]
+ public void IsPlatformEnabled ()
+ {
+ var view = new View ();
+
+ Assert.False (view.IsPlatformEnabled);
+
+ view.IsPlatformEnabled = true;
+
+ Assert.True (view.IsPlatformEnabled);
+
+ view.IsPlatformEnabled = false;
+
+ Assert.False (view.IsPlatformEnabled);
+ }
+
+ [Test]
+ public void TestBindingContextChaining ()
+ {
+ View child;
+ var group = new NaiveLayout {
+ Children = { (child = new View ()) }
+ };
+
+ var context = new object ();
+ group.BindingContext = context;
+
+ Assert.AreEqual (context, child.BindingContext);
+ }
+
+
+
+ [Test]
+ public void FocusWithoutSubscriber ()
+ {
+ var view = new View ();
+
+ Assert.False (view.Focus ());
+ }
+
+ [Test]
+ public void FocusWithSubscriber ([Values(true, false)] bool result)
+ {
+ var view = new View ();
+ view.FocusChangeRequested += (sender, arg) => arg.Result = result;
+ Assert.True (view.Focus () == result);
+ }
+
+ [Test]
+ public void DoNotSignalWhenAlreadyFocused ()
+ {
+ var view = new View ();
+ view.SetValueCore (VisualElement.IsFocusedPropertyKey, true);
+ bool signaled = false;
+ view.FocusChangeRequested += (sender, args) => signaled = true;
+
+ Assert.True (view.Focus (), "View.Focus returned false");
+ Assert.False (signaled, "FocusRequested was raised");
+ }
+
+ [Test]
+ public void UnFocus ()
+ {
+ var view = new View ();
+ view.SetValueCore (VisualElement.IsFocusedPropertyKey, true);
+
+ var requested = false;
+ view.FocusChangeRequested += (sender, args) => {
+ requested = !args.Focus;
+ };
+
+ view.Unfocus ();
+
+ Assert.True (requested);
+ }
+
+ [Test]
+ public void UnFocusDoesNotFireWhenNotFocused ()
+ {
+ var view = new View ();
+ view.SetValueCore (VisualElement.IsFocusedPropertyKey, false);
+
+ var requested = false;
+ view.FocusChangeRequested += (sender, args) => {
+ requested = args.Focus;
+ };
+
+ view.Unfocus ();
+
+ Assert.False (requested);
+ }
+
+ [Test]
+ public void PlatformSet ()
+ {
+ var view = new View ();
+ bool set = false;
+ view.PlatformSet += (sender, args) => set = true;
+
+ view.Platform = new UnitPlatform ();
+
+ Assert.True (set);
+ }
+
+ [Test]
+ public void TestFocusedEvent ()
+ {
+ var view = new View ();
+
+ bool fired = false;
+ view.Focused += (sender, args) => fired = true;
+ view.SetValueCore (VisualElement.IsFocusedPropertyKey, true);
+
+
+ Assert.True (fired);
+ }
+
+ [Test]
+ public void TestUnFocusedEvent ()
+ {
+ var view = new View ();
+ view.SetValueCore (VisualElement.IsFocusedPropertyKey, true);
+
+ bool fired = false;
+ view.Unfocused += (sender, args) => fired = true;
+ view.SetValueCore (VisualElement.IsFocusedPropertyKey, false);
+
+ Assert.True (fired);
+ }
+
+ [Test]
+ public void TestBeginInvokeOnMainThread ()
+ {
+ Device.PlatformServices = new MockPlatformServices (invokeOnMainThread: action => action ());
+
+ bool invoked = false;
+ Device.BeginInvokeOnMainThread (() => invoked = true);
+
+ Assert.True (invoked);
+ }
+
+ [Test]
+ public void InvokeOnMainThreadThrowsWhenNull ()
+ {
+ Device.PlatformServices = null;
+ Assert.Throws<InvalidOperationException>(() => Device.BeginInvokeOnMainThread (() => { }));
+ }
+
+ [Test]
+ public void TestOpenUriAction ()
+ {
+ var uri = new Uri ("http://www.xamarin.com/");
+ var invoked = false;
+ Device.PlatformServices = new MockPlatformServices (openUriAction: u => {
+ Assert.AreSame (uri, u);
+ invoked = true;
+ });
+
+ Device.OpenUri (uri);
+ Assert.True (invoked);
+ }
+
+ [Test]
+ public void OpenUriThrowsWhenNull ()
+ {
+ Device.PlatformServices = null;
+ var uri = new Uri ("http://www.xamarin.com/");
+ Assert.Throws<InvalidOperationException> (() => Device.OpenUri (uri));
+ }
+
+ [Test]
+ public void MinimumWidthRequest ()
+ {
+ var view = new View ();
+
+ bool signaled = false;
+ view.MeasureInvalidated += (sender, args) => signaled = true;
+
+ view.MinimumWidthRequest = 10;
+ Assert.True (signaled);
+ Assert.AreEqual (10, view.MinimumWidthRequest);
+
+ signaled = false;
+ view.MinimumWidthRequest = 10;
+ Assert.False (signaled);
+ }
+
+ [Test]
+ public void MinimumHeightRequest ()
+ {
+ var view = new View ();
+
+ bool signaled = false;
+ view.MeasureInvalidated += (sender, args) => signaled = true;
+
+ view.MinimumHeightRequest = 10;
+ Assert.True (signaled);
+ Assert.AreEqual (10, view.MinimumHeightRequest);
+
+ signaled = false;
+ view.MinimumHeightRequest = 10;
+ Assert.False (signaled);
+ }
+
+ [Test]
+ public void MinimumWidthRequestInSizeRequest ()
+ {
+ var view = new View {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ view.HeightRequest = 20;
+ view.WidthRequest = 200;
+ view.MinimumWidthRequest = 100;
+
+ var result = view.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+ Assert.AreEqual (new Size (200, 20), result.Request);
+ Assert.AreEqual (new Size (100, 20), result.Minimum);
+ }
+
+ [Test]
+ public void MinimumHeightRequestInSizeRequest ()
+ {
+ var view = new View {
+ Platform = new UnitPlatform (),
+ IsPlatformEnabled = true
+ };
+
+ view.HeightRequest = 200;
+ view.WidthRequest = 20;
+ view.MinimumHeightRequest = 100;
+
+ var result = view.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+ Assert.AreEqual (new Size (20, 200), result.Request);
+ Assert.AreEqual (new Size (20, 100), result.Minimum);
+ }
+
+ [Test]
+ public void StartTimerSimple ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ var task = new TaskCompletionSource<bool> ();
+
+ Task.Factory.StartNew (() => Device.StartTimer (TimeSpan.FromMilliseconds (200), () => {
+ task.SetResult (false);
+ return false;
+ }));
+
+ task.Task.Wait ();
+ Assert.False (task.Task.Result);
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void StartTimerMultiple ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ var task = new TaskCompletionSource<int> ();
+
+ int steps = 0;
+ Task.Factory.StartNew (() => Device.StartTimer (TimeSpan.FromMilliseconds (200), () => {
+ steps++;
+ if (steps < 2)
+ return true;
+ task.SetResult (steps);
+ return false;
+ }));
+
+ task.Task.Wait ();
+ Assert.AreEqual (2, task.Task.Result);
+ Device.PlatformServices = null;
+ }
+
+ [Test]
+ public void BindingsApplyAfterViewAddedToParentWithContextSet()
+ {
+ var parent = new NaiveLayout();
+ parent.BindingContext = new MockViewModel { Text = "test" };
+
+ var child = new Entry();
+ child.SetBinding (Entry.TextProperty, new Binding ("Text"));
+
+ parent.Children.Add (child);
+
+ Assert.That (child.BindingContext, Is.SameAs (parent.BindingContext));
+ Assert.That (child.Text, Is.EqualTo ("test"));
+ }
+
+ [Test]
+ public void IdIsUnique ()
+ {
+ var view1 = new View ();
+ var view2 = new View ();
+
+ Assert.True (view1.Id != view2.Id);
+ }
+
+ [Test]
+ public void MockBounds ()
+ {
+ var view = new View ();
+ view.Layout (new Rectangle (10, 20, 30, 40));
+
+ bool changed = false;
+ view.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == View.XProperty.PropertyName ||
+ args.PropertyName == View.YProperty.PropertyName ||
+ args.PropertyName == View.WidthProperty.PropertyName ||
+ args.PropertyName == View.HeightProperty.PropertyName)
+ changed = true;
+ };
+
+ view.SizeChanged += (sender, args) => changed = true;
+
+ view.MockBounds (new Rectangle (5, 10, 15, 20));
+
+ Assert.AreEqual (new Rectangle (5, 10, 15, 20), view.Bounds);
+ Assert.False (changed);
+
+ view.UnmockBounds ();
+
+ Assert.AreEqual (new Rectangle (10, 20, 30, 40), view.Bounds);
+ Assert.False (changed);
+ }
+
+ [Test]
+ public void AddGestureRecognizer ()
+ {
+ var view = new View ();
+ var gestureRecognizer = new TapGestureRecognizer ();
+
+ view.GestureRecognizers.Add (gestureRecognizer);
+
+ Assert.True (view.GestureRecognizers.Contains (gestureRecognizer));
+ }
+
+ [Test]
+ public void AddGestureRecognizerSetsParent ()
+ {
+ var view = new View ();
+ var gestureRecognizer = new TapGestureRecognizer ();
+
+ view.GestureRecognizers.Add (gestureRecognizer);
+
+ Assert.AreEqual (view, gestureRecognizer.Parent);
+ }
+
+ [Test]
+ public void RemoveGestureRecognizerUnsetsParent ()
+ {
+ var view = new View ();
+ var gestureRecognizer = new TapGestureRecognizer ();
+
+ view.GestureRecognizers.Add (gestureRecognizer);
+ view.GestureRecognizers.Remove (gestureRecognizer);
+
+ Assert.Null (gestureRecognizer.Parent);
+ }
+
+ [Test]
+ public void WidthRequestEffectsGetSizeRequest ()
+ {
+ var view = new View ();
+ view.IsPlatformEnabled = true;
+ view.Platform = new UnitPlatform ((ve, widthConstraint, heightConstraint) => {
+ if (widthConstraint < 30)
+ return new SizeRequest (new Size (40, 50));
+ return new SizeRequest(new Size(20, 100));
+ });
+
+ view.WidthRequest = 20;
+ var request = view.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+
+ Assert.AreEqual (new Size (20, 50), request.Request);
+ }
+
+ [Test]
+ public void HeightRequestEffectsGetSizeRequest ()
+ {
+ var view = new View ();
+ view.IsPlatformEnabled = true;
+ view.Platform = new UnitPlatform ((ve, widthConstraint, heightConstraint) => {
+ if (heightConstraint < 30)
+ return new SizeRequest (new Size (40, 50));
+ return new SizeRequest(new Size(20, 100));
+ });
+
+ view.HeightRequest = 20;
+ var request = view.GetSizeRequest (double.PositiveInfinity, double.PositiveInfinity);
+
+ Assert.AreEqual (new Size (40, 20), request.Request);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/WebViewUnitTests.cs b/Xamarin.Forms.Core.UnitTests/WebViewUnitTests.cs
new file mode 100644
index 00000000..d441f4b8
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/WebViewUnitTests.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class WebViewUnitTests : BaseTestFixture
+ {
+ [Test]
+ public void TestSourceImplicitConversion ()
+ {
+ var web = new WebView ();
+ Assert.Null (web.Source);
+ web.Source = "http://www.google.com";
+ Assert.NotNull (web.Source);
+ Assert.True (web.Source is UrlWebViewSource);
+ Assert.AreEqual ("http://www.google.com", ((UrlWebViewSource)web.Source).Url);
+ }
+
+ [Test]
+ public void TestSourceChangedPropagation ()
+ {
+ var source = new UrlWebViewSource {Url ="http://www.google.com"};
+ var web = new WebView { Source = source };
+ bool signaled = false;
+ web.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == WebView.SourceProperty.PropertyName)
+ signaled = true;
+ };
+ Assert.False (signaled);
+ source.Url = "http://www.xamarin.com";
+ Assert.True (signaled);
+ }
+
+ [Test]
+ public void TestSourceDisconnected ()
+ {
+ var source = new UrlWebViewSource {Url="http://www.google.com"};
+ var web = new WebView { Source = source };
+ web.Source = new UrlWebViewSource {Url="Foo"};
+ bool signaled = false;
+ web.PropertyChanged += (sender, args) => {
+ if (args.PropertyName == WebView.SourceProperty.PropertyName)
+ signaled = true;
+ };
+ Assert.False (signaled);
+ source.Url = "http://www.xamarin.com";
+ Assert.False (signaled);
+ }
+
+ class ViewModel
+ {
+ public string HTML { get; set; } = "<html><body><p>This is a WebView!</p></body></html>";
+
+ public string URL { get; set; } = "http://xamarin.com";
+
+ }
+
+ [Test]
+ public void TestBindingContextPropagatesToSource ()
+ {
+ var htmlWebView = new WebView {
+ };
+ var urlWebView = new WebView {
+ };
+
+ var htmlSource = new HtmlWebViewSource ();
+ htmlSource.SetBinding (HtmlWebViewSource.HtmlProperty, "HTML");
+ htmlWebView.Source = htmlSource;
+
+ var urlSource = new UrlWebViewSource ();
+ urlSource.SetBinding (UrlWebViewSource.UrlProperty, "URL");
+ urlWebView.Source = urlSource;
+
+ var viewModel = new ViewModel ();
+
+ var container = new StackLayout {
+ BindingContext = viewModel,
+ Padding = new Size (20, 20),
+ Children = {
+ htmlWebView,
+ urlWebView
+ }
+ };
+
+ Assert.AreEqual ("<html><body><p>This is a WebView!</p></body></html>", htmlSource.Html);
+ Assert.AreEqual ("http://xamarin.com", urlSource.Url);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.UnitTests/Xamarin.Forms.Core.UnitTests.csproj b/Xamarin.Forms.Core.UnitTests/Xamarin.Forms.Core.UnitTests.csproj
new file mode 100644
index 00000000..a7324ca1
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/Xamarin.Forms.Core.UnitTests.csproj
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{00259593-A283-47A5-ACB7-9C3819B16364}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Core.UnitTests</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Core.UnitTests</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;TURKEY</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="nunit.framework">
+ <HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="AnimatableKeyTests.cs" />
+ <Compile Include="BaseTestFixture.cs" />
+ <Compile Include="AbsoluteLayoutTests.cs" />
+ <Compile Include="BindableObjectExtensionTests.cs" />
+ <Compile Include="BindableObjectUnitTests.cs" />
+ <Compile Include="BindablePropertyUnitTests.cs" />
+ <Compile Include="BindingBaseUnitTests.cs" />
+ <Compile Include="BindingExpressionTests.cs" />
+ <Compile Include="BindingTests.cs" />
+ <Compile Include="BindingTypeConverterTests.cs" />
+ <Compile Include="BindingUnitTests.cs" />
+ <Compile Include="ButtonUnitTest.cs" />
+ <Compile Include="CarouselPageTests.cs" />
+ <Compile Include="CellTests.cs" />
+ <Compile Include="ColorUnitTests.cs" />
+ <Compile Include="CommandSourceTests.cs" />
+ <Compile Include="CommandTests.cs" />
+ <Compile Include="ContentFormUnitTests.cs" />
+ <Compile Include="ContraintTypeConverterTests.cs" />
+ <Compile Include="ControlTemplateTests.cs" />
+ <Compile Include="DataTemplateSelectorTests.cs" />
+ <Compile Include="DatePickerUnitTest.cs" />
+ <Compile Include="DependencyServiceTests.cs" />
+ <Compile Include="DistanceTests.cs" />
+ <Compile Include="DynamicBindingContextTests.cs" />
+ <Compile Include="EasingTests.cs" />
+ <Compile Include="EffectTests.cs" />
+ <Compile Include="ElementTests.cs" />
+ <Compile Include="EntryCellTests.cs" />
+ <Compile Include="EntryUnitTests.cs" />
+ <Compile Include="FluentTests.cs" />
+ <Compile Include="FontUnitTests.cs" />
+ <Compile Include="FormattedStringTests.cs" />
+ <Compile Include="FrameUnitTests.cs" />
+ <Compile Include="GeocoderUnitTests.cs" />
+ <Compile Include="GroupViewUnitTests.cs" />
+ <Compile Include="ImageTests.cs" />
+ <Compile Include="KeyboardTests.cs" />
+ <Compile Include="LabelTests.cs" />
+ <Compile Include="ListProxyTests.cs" />
+ <Compile Include="ListViewTests.cs" />
+ <Compile Include="MapSpanTests.cs" />
+ <Compile Include="MapTests.cs" />
+ <Compile Include="MarginTests.cs" />
+ <Compile Include="MasterDetailFormUnitTests.cs" />
+ <Compile Include="MenuItemTests.cs" />
+ <Compile Include="MessagingCenterTests.cs" />
+ <Compile Include="MockViewModel.cs" />
+ <Compile Include="MotionTests.cs" />
+ <Compile Include="MultiPageTests.cs" />
+ <Compile Include="NavigationMenuUnitTests.cs" />
+ <Compile Include="NavigationModelTests.cs" />
+ <Compile Include="NavigationProxyTests.cs" />
+ <Compile Include="NavigationUnitTest.cs" />
+ <Compile Include="NotifyCollectionChangedEventArgsExtensionsTests.cs" />
+ <Compile Include="ObservableWrapperTests.cs" />
+ <Compile Include="OpenGLViewUnitTests.cs" />
+ <Compile Include="PageTests.cs" />
+ <Compile Include="PanGestureRecognizerUnitTests.cs" />
+ <Compile Include="PinTests.cs" />
+ <Compile Include="PointTests.cs" />
+ <Compile Include="PositionTests.cs" />
+ <Compile Include="ProgressBarTests.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="RectangleUnitTests.cs" />
+ <Compile Include="RegistrarUnitTests.cs" />
+ <Compile Include="RelativeLayoutTests.cs" />
+ <Compile Include="ScrollViewUnitTests.cs" />
+ <Compile Include="SearchBarUnitTests.cs" />
+ <Compile Include="SizeTests.cs" />
+ <Compile Include="SliderUnitTests.cs" />
+ <Compile Include="StackLayoutUnitTests.cs" />
+ <Compile Include="StepperUnitTests.cs" />
+ <Compile Include="SwitchCellTests.cs" />
+ <Compile Include="SwitchUnitTests.cs" />
+ <Compile Include="TabbedFormUnitTests.cs" />
+ <Compile Include="TableModelTests.cs" />
+ <Compile Include="TableRootUnitTests.cs" />
+ <Compile Include="TableSectionTests.cs" />
+ <Compile Include="TableViewUnitTests.cs" />
+ <Compile Include="TapGestureRecognizerTests.cs" />
+ <Compile Include="TemplatedItemsListTests.cs" />
+ <Compile Include="TextCellTests.cs" />
+ <Compile Include="ThicknessTests.cs" />
+ <Compile Include="TimePickerUnitTest.cs" />
+ <Compile Include="ToolbarItemTests.cs" />
+ <Compile Include="ToolbarTrackerTests.cs" />
+ <Compile Include="ToolbarUnitTests.cs" />
+ <Compile Include="TypeUnitTests.cs" />
+ <Compile Include="ViewCellTests.cs" />
+ <Compile Include="ViewUnitTests.cs" />
+ <Compile Include="WebViewUnitTests.cs" />
+ <Compile Include="ImageSourceTests.cs" />
+ <Compile Include="DataTemplateTests.cs" />
+ <Compile Include="LayoutOptionsUnitTests.cs" />
+ <Compile Include="ContentViewUnitTest.cs" />
+ <Compile Include="MockPlatformServices.cs" />
+ <Compile Include="GridTests.cs" />
+ <Compile Include="UnitPlatform.cs" />
+ <Compile Include="GridLengthTypeConverterTests.cs" />
+ <Compile Include="BoxViewUnitTests.cs" />
+ <Compile Include="NotifiedPropertiesTests.cs" />
+ <Compile Include="PickerTests.cs" />
+ <Compile Include="EditorTests.cs" />
+ <Compile Include="UriImageSourceTests.cs" />
+ <Compile Include="ResourceDictionaryTests.cs" />
+ <Compile Include="BehaviorTest.cs" />
+ <Compile Include="EventTriggerTest.cs" />
+ <Compile Include="DynamicResourceTests.cs" />
+ <Compile Include="StyleTests.cs" />
+ <Compile Include="DataTriggerTests.cs" />
+ <Compile Include="MultiTriggerTests.cs" />
+ <Compile Include="TriggerTests.cs" />
+ <Compile Include="PinchGestureRecognizerTests.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7D13BAC2-C6A4-416A-B07E-C169B199E52B}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform\Xamarin.Forms.Platform.csproj">
+ <Project>{67f9d3a8-f71e-4428-913f-c37ae82cdb24}</Project>
+ <Name>Xamarin.Forms.Platform</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ItemGroup />
+ <ItemGroup>
+ <EmbeddedResource Include="Images\crimson.jpg">
+ <LogicalName>Images/crimson.jpg</LogicalName>
+ </EmbeddedResource>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Core.UnitTests/packages.config b/Xamarin.Forms.Core.UnitTests/packages.config
new file mode 100644
index 00000000..d27552db
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit" version="2.6.2" targetFramework="net45" />
+</packages>
diff --git a/Xamarin.Forms.Core.Windows.UITests/App.cs b/Xamarin.Forms.Core.Windows.UITests/App.cs
new file mode 100644
index 00000000..966ef261
--- /dev/null
+++ b/Xamarin.Forms.Core.Windows.UITests/App.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.UITest;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal static class RunningApp
+ {
+ public static IApp App;
+
+ public static void Restart ()
+ {
+ App = null;
+ //App = ConfigureApp
+ // .iOS
+ // .Debug ()
+ // .InstalledApp ("com.xamarin.quickui.controlgallery")
+ // .StartApp ();
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.Windows.UITests/PlatformQueries.cs b/Xamarin.Forms.Core.Windows.UITests/PlatformQueries.cs
new file mode 100644
index 00000000..9599d5d3
--- /dev/null
+++ b/Xamarin.Forms.Core.Windows.UITests/PlatformQueries.cs
@@ -0,0 +1,129 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal static class PlatformMethodQueries
+ {
+ public static readonly Dictionary<BindableProperty, Tuple<string[], bool>> PropertyPlatformMethodDictionary = new Dictionary<BindableProperty, Tuple<string[], bool>> {
+ { ActivityIndicator.ColorProperty, Tuple.Create (new[] { "getProgressDrawable", "getColor" }, false) },
+ { ActivityIndicator.IsRunningProperty, Tuple.Create (new[] { "isIndeterminate" }, false) },
+ { Button.BorderColorProperty, Tuple.Create (new[] { "getBackground" }, false) },
+ { Button.BorderRadiusProperty, Tuple.Create (new[] { "getBackground" }, false) },
+ { Button.BorderWidthProperty, Tuple.Create (new[] { "getBackground" }, false) },
+ { Button.ImageProperty, Tuple.Create (new[] { "getBackground" }, false) },
+ { Button.FontProperty, Tuple.Create (new[] { "getTypeface", "isBold" }, false) },
+ { Button.TextProperty, Tuple.Create (new[] { "getText" }, false) },
+ { Button.TextColorProperty, Tuple.Create (new[] { "getCurrentTextColor" }, false) },
+ { View.AnchorXProperty, Tuple.Create (new[] { "getPivotX" }, true) },
+ { View.AnchorYProperty, Tuple.Create (new[] { "getPivotY" }, true) },
+ { View.BackgroundColorProperty, Tuple.Create (new[] { "getBackground", "getColor" }, true) },
+ { View.IsEnabledProperty, Tuple.Create (new[] { "isEnabled" }, false) },
+ { View.OpacityProperty, Tuple.Create (new[] { "getAlpha" }, true) },
+ { View.RotationProperty, Tuple.Create (new[] { "getRotation" }, true) },
+ { View.RotationXProperty, Tuple.Create (new[] { "getRotationX" }, true) },
+ { View.RotationYProperty, Tuple.Create (new[] { "getRotationY" }, true) },
+ { View.ScaleProperty, Tuple.Create (new[] { "getScaleX", "getScaleY" }, true) },
+ };
+ }
+
+ internal static class PlatformViews
+ {
+ public static readonly string ActivityIndicator = "android.widget.ProgressBar";
+ public static readonly string BoxView = "xamarin.forms.platform.android.BoxRenderer";
+ public static readonly string Button = "android.widget.Button";
+ public static readonly string DatePicker = "android.widget.EditText";
+ public static readonly string Editor = "xamarin.forms.platform.android.EditorEditText";
+ public static readonly string Entry = "xamarin.forms.platform.android.EntryEditText";
+ public static readonly string Frame = "xamarin.forms.platform.android.appcompat.FrameRenderer";
+ public static readonly string Image = "android.widget.ImageView";
+ public static readonly string Label = "android.widget.TextView";
+ public static readonly string ListView = "android.widget.ListView";
+ public static readonly string OpenGLView = "android.widget.GLSurfaceView";
+ public static readonly string Picker = "android.widget.EditText";
+ public static readonly string ProgressBar = "android.widget.ProgressBar";
+ public static readonly string SearchBar = "android.widget.SearchView";
+ public static readonly string Slider = "android.widget.SeekBar";
+ public static readonly string Stepper = "button marked:'+'";
+ public static readonly string Switch = "android.widget.Switch";
+ public static readonly string TableView = "android.widget.ListView";
+ public static readonly string TimePicker = "android.widget.EditText";
+ public static readonly string WebView = "android.widget.WebView";
+ }
+
+ internal static class PlatformQueries
+ {
+ public static readonly Func<AppQuery, AppQuery> Root = q => q.Id ("content");
+ public static readonly Func<AppQuery, AppQuery> RootPageListView = q => q.Raw ("ListViewRenderer index:0");
+ public static readonly Func<AppQuery, AppQuery> GalleryListView = q => q.Raw ("ListViewRenderer index:1");
+ public static readonly Func<AppQuery, AppQuery> PageWithoutNavigationBar = q => q.Raw ("* id:'content' index:0");
+ public static readonly Func<AppQuery, AppQuery> NavigationBarBackButton = q => q.Class ("android.support.v7.widget.Toolbar").Child ("android.widget.ImageButton");
+
+ // Views
+ public static readonly Func<AppQuery, AppQuery> ActivityIndicator = q => q.ClassFull (PlatformViews.ActivityIndicator);
+ public static readonly Func<AppQuery, AppQuery> Button = q => q.ClassFull (PlatformViews.Button);
+
+ public static Func<AppQuery, AppQuery> EntryWithPlaceholder (string text) {
+ return q => q.Raw (string.Format ("EntryEditText hint:'{0}'", text));
+ }
+ public static Func<AppQuery, AppQuery> EntryCellWithPlaceholder (string text) {
+ return q => q.Raw (string.Format ("EntryCellEditText hint:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryWithText (string text) {
+ return q => q.Raw (string.Format ("EntryEditText text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryCellWithText (string text) {
+ return q => q.Raw (string.Format ("EntryCellEditText text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EditorsWithText (string text) {
+ return q => q.Raw (string.Format ("EditorEditText text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryWithIndex (int index) {
+ return q => q.Raw (string.Format ("EntryEditText index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> SearchBarWithIndex (int index) {
+ return q => q.Raw (string.Format ("SearchView index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> LabelWithIndex (int index) {
+ return q => q.Raw (string.Format ("TextView index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> LabelWithText (string text) {
+ return q => q.Raw (string.Format ("TextView text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> LabelWithId (string id) {
+ return q => q.Raw (string.Format ("TextView id:'{0}'", id));
+ }
+
+ public static Func<AppQuery, AppQuery> PickerEntryWithIndex (int index) {
+ return q => q.Raw (string.Format ("EditText index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> PickerEntryWithPlaceholder (string placeholder) {
+ return q => q.Raw (string.Format ("EditText hint:'{0}'", placeholder));
+ }
+
+ public static Func<AppQuery, AppQuery> PickerEntryWithText (string text) {
+ return q => q.Raw (string.Format ("EditText text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> SwitchWithIndex (int index) {
+ return q => q.Raw (string.Format ("Switch index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> StepperWithIndex (int index) {
+ return q => q.Raw (string.Format ("button marked:'+' index:{0}", index));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.Windows.UITests/Properties/AssemblyInfo.cs b/Xamarin.Forms.Core.Windows.UITests/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..f26f6e8c
--- /dev/null
+++ b/Xamarin.Forms.Core.Windows.UITests/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Xamarin.Forms.Core.Windows.UITests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Forms.Core.Windows.UITests")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("0a39a74b-6f7a-4d41-84f2-b0ccdce899df")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Xamarin.Forms.Core.Windows.UITests/Xamarin.Forms.Core.Windows.UITests.csproj b/Xamarin.Forms.Core.Windows.UITests/Xamarin.Forms.Core.Windows.UITests.csproj
new file mode 100644
index 00000000..4891efd4
--- /dev/null
+++ b/Xamarin.Forms.Core.Windows.UITests/Xamarin.Forms.Core.Windows.UITests.csproj
@@ -0,0 +1,292 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Core.UITests</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Core.Windows.UITests</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;__WINDOWS__;UITEST</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;UITEST</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="nunit.framework, Version=3.0.5813.39031, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
+ <HintPath>..\packages\NUnit.3.0.1\lib\net45\nunit.framework.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xml" />
+ <Reference Include="Xamarin.UITest, Version=1.2.0.308, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.UITest.1.2.0.308-dev\lib\Xamarin.UITest.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\BaseTestFixture.cs">
+ <Link>BaseTestFixture.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Queries.cs">
+ <Link>Queries.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Remotes\BaseViewContainerRemote.cs">
+ <Link>Remotes\BaseViewContainerRemote.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Remotes\EventViewContainerRemote.cs">
+ <Link>Remotes\EventViewContainerRemote.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Remotes\LayeredViewContainerRemote.cs">
+ <Link>Remotes\LayeredViewContainerRemote.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Remotes\RemoteFactory.cs">
+ <Link>Remotes\RemoteFactory.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Remotes\StateViewContainerRemote.cs">
+ <Link>Remotes\StateViewContainerRemote.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Remotes\ViewContainerRemote.cs">
+ <Link>Remotes\ViewContainerRemote.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ActionSheetUITests.cs">
+ <Link>Tests\ActionSheetUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ActivityIndicatorUITests.cs">
+ <Link>Tests\ActivityIndicatorUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\AutomationIDUITests.cs">
+ <Link>Tests\AutomationIDUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\BoxViewUITests.cs">
+ <Link>Tests\BoxViewUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ButtonUITests.cs">
+ <Link>Tests\ButtonUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ContextActionsUITests.cs">
+ <Link>Tests\ContextActionsUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\DatePickerUITests.cs">
+ <Link>Tests\DatePickerUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\DisplayAlertUITests.cs">
+ <Link>Tests\DisplayAlertUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\EditorUITests.cs">
+ <Link>Tests\EditorUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\EntryUITests.cs">
+ <Link>Tests\EntryUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\FrameUITests.cs">
+ <Link>Tests\FrameUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ImageUITests.cs">
+ <Link>Tests\ImageUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\LabelUITests.cs">
+ <Link>Tests\LabelUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-AbsoluteLayoutGalleryTest.cs">
+ <Link>Tests\Legacy-AbsoluteLayoutGalleryTest.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-BoundViewUITest.cs">
+ <Link>Tests\Legacy-BoundViewUITest.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-ButtonUITests.cs">
+ <Link>Tests\Legacy-ButtonUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-CarouselPageUITests.cs">
+ <Link>Tests\Legacy-CarouselPageUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-CellsUITests.cs">
+ <Link>Tests\Legacy-CellsUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-ClipToBoundsUITests.cs">
+ <Link>Tests\Legacy-ClipToBoundsUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-EditorUITests.cs">
+ <Link>Tests\Legacy-EditorUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-EntryUITests.cs">
+ <Link>Tests\Legacy-EntryUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-GridGalleryUITests.cs">
+ <Link>Tests\Legacy-GridGalleryUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-GroupedListActionsUITests.cs">
+ <Link>Tests\Legacy-GroupedListActionsUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-InputIntentUITests.cs">
+ <Link>Tests\Legacy-InputIntentUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-ListUITests.cs">
+ <Link>Tests\Legacy-ListUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-MapUITests.cs">
+ <Link>Tests\Legacy-MapUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-MinimumSizeUITest.cs">
+ <Link>Tests\Legacy-MinimumSizeUITest.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-NavigationBarUITests.cs">
+ <Link>Tests\Legacy-NavigationBarUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-RelativeLayoutUITest.cs">
+ <Link>Tests\Legacy-RelativeLayoutUITest.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-SearchBarUITests.cs">
+ <Link>Tests\Legacy-SearchBarUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-SliderUITests.cs">
+ <Link>Tests\Legacy-SliderUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-StackLayoutUITest.cs">
+ <Link>Tests\Legacy-StackLayoutUITest.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-StepperUITests.cs">
+ <Link>Tests\Legacy-StepperUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-SwitchUITests.cs">
+ <Link>Tests\Legacy-SwitchUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-TableViewUITests.cs">
+ <Link>Tests\Legacy-TableViewUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-TemplatedCarouselPageUITests.cs">
+ <Link>Tests\Legacy-TemplatedCarouselPageUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-TemplatedTabPageUITests.cs">
+ <Link>Tests\Legacy-TemplatedTabPageUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-ToolbarGalleryUITests.cs">
+ <Link>Tests\Legacy-ToolbarGalleryUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-UnevenListTests.cs">
+ <Link>Tests\Legacy-UnevenListTests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-UnevenViewCellUITests.cs">
+ <Link>Tests\Legacy-UnevenViewCellUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\Legacy-ViewCellUITests.cs">
+ <Link>Tests\Legacy-ViewCellUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\PickerUITests.cs">
+ <Link>Tests\PickerUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ProgressBarUITests.cs">
+ <Link>Tests\ProgressBarUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\RootGalleryUITests.cs">
+ <Link>Tests\RootGalleryUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ScrollViewUITests.cs">
+ <Link>Tests\ScrollViewUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\SearchBarUITests.cs">
+ <Link>Tests\SearchBarUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\SliderUITests.cs">
+ <Link>Tests\SliderUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\StepperUITests.cs">
+ <Link>Tests\StepperUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\SwitchUITests.cs">
+ <Link>Tests\SwitchUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\TimePickerUITests.cs">
+ <Link>Tests\TimePickerUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ToolbarItemTests.cs">
+ <Link>Tests\ToolbarItemTests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\ViewUITests.cs">
+ <Link>Tests\ViewUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Tests\WebViewUITests.cs">
+ <Link>Tests\WebViewUITests.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\AppExtensions.cs">
+ <Link>Utilities\AppExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\Drag.cs">
+ <Link>Utilities\Drag.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\Gestures.cs">
+ <Link>Utilities\Gestures.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\Logger.cs">
+ <Link>Utilities\Logger.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\NumericExtensions.cs">
+ <Link>Utilities\NumericExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\ParsingUtils.cs">
+ <Link>Utilities\ParsingUtils.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\UITestCustomExceptions.cs">
+ <Link>Utilities\UITestCustomExceptions.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.iOS.UITests\Utilities\ViewInspector.cs">
+ <Link>Utilities\ViewInspector.cs</Link>
+ </Compile>
+ <Compile Include="App.cs" />
+ <Compile Include="PlatformQueries.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.CustomAttributes\Xamarin.Forms.CustomAttributes.csproj">
+ <Project>{4dcd0420-1168-4b77-86db-6196ee4bd491}</Project>
+ <Name>Xamarin.Forms.CustomAttributes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7d13bac2-c6a4-416a-b07e-c169b199e52b}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform\Xamarin.Forms.Platform.csproj">
+ <Project>{67f9d3a8-f71e-4428-913f-c37ae82cdb24}</Project>
+ <Name>Xamarin.Forms.Platform</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="..\Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Xamarin.Forms.Controls.Issues.Shared.projitems" Label="Shared" />
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Core.Windows.UITests/packages.config b/Xamarin.Forms.Core.Windows.UITests/packages.config
new file mode 100644
index 00000000..76a06ef7
--- /dev/null
+++ b/Xamarin.Forms.Core.Windows.UITests/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit" version="3.0.1" targetFramework="net45" />
+ <package id="Xamarin.UITest" version="1.2.0.308-dev" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/App.cs b/Xamarin.Forms.Core.iOS.UITests/App.cs
new file mode 100644
index 00000000..845bb9a5
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/App.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using NUnit.Framework;
+
+using Xamarin.UITest;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal static class RunningApp
+ {
+ public static iOSApp App;
+
+ public static void Restart ()
+ {
+ App = ConfigureApp
+ .iOS
+ .Debug ()
+ .InstalledApp ("com.xamarin.quickui.controlgallery")
+ .StartApp (Xamarin.UITest.Configuration.AppDataMode.Clear);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/BaseTestFixture.cs b/Xamarin.Forms.Core.iOS.UITests/BaseTestFixture.cs
new file mode 100644
index 00000000..a92d357c
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/BaseTestFixture.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using NUnit.Framework;
+
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal abstract class BaseTestFixture
+ {
+ // TODO: Landscape tests
+
+ public static IApp App { get; private set; }
+ public string PlatformViewType { get; protected set; }
+ public bool ShouldResetPerFixture { get; protected set; }
+ public AppRect ScreenBounds { get; private set; }
+
+ protected BaseTestFixture ()
+ {
+ ShouldResetPerFixture = true;
+ }
+
+ protected abstract void NavigateToGallery ();
+
+ [TestFixtureSetUp]
+ protected virtual void FixtureSetup ()
+ {
+ if (ShouldResetPerFixture) {
+ RelaunchApp ();
+ }
+ }
+
+ [TestFixtureTearDown]
+ protected virtual void FixtureTeardown ()
+ {
+ }
+
+ [SetUp]
+ protected virtual void TestSetup ()
+ {
+ if (!ShouldResetPerFixture) {
+ RelaunchApp ();
+ }
+ App.Screenshot ("Begin Test");
+ }
+
+ [TearDown]
+ protected virtual void TestTearDown ()
+ {
+ App.Screenshot ("Test complete");
+ }
+
+ void RelaunchApp ()
+ {
+ App = null;
+ RunningApp.App = null;
+
+ try {
+ RunningApp.Restart ();
+ } catch (Exception ex) {
+ // if at first you dont succeed
+ RunningApp.Restart ();
+ }
+ App = RunningApp.App;
+
+ App.SetOrientationPortrait ();
+ ScreenBounds = App.RootViewRect ();
+ NavigateToGallery ();
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Makefile b/Xamarin.Forms.Core.iOS.UITests/Makefile
new file mode 100644
index 00000000..242ff29b
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Makefile
@@ -0,0 +1,2 @@
+console:
+ DEBUG=1 DEVICE_TARGET=device DEVICE_ENDPOINT=http://10.0.1.159:37265 calabash-ios console
diff --git a/Xamarin.Forms.Core.iOS.UITests/PlatformQueries.cs b/Xamarin.Forms.Core.iOS.UITests/PlatformQueries.cs
new file mode 100644
index 00000000..4ae2515c
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/PlatformQueries.cs
@@ -0,0 +1,136 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.UITest.iOS;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal static class iOSLoaderIdentifier
+ {
+
+ }
+
+ internal static class PlatformMethodQueries
+ {
+ public static readonly Dictionary<BindableProperty, Tuple<string[], bool>> PropertyPlatformMethodDictionary = new Dictionary<BindableProperty, Tuple<string[], bool>> {
+ { ActivityIndicator.ColorProperty, Tuple.Create (new[] { "color" }, false) },
+ { ActivityIndicator.IsRunningProperty, Tuple.Create (new[] { "isAnimating" }, false) },
+ { Button.BorderRadiusProperty, Tuple.Create (new[] { "layer", "cornerRadius" }, false) },
+ { Button.BorderWidthProperty, Tuple.Create (new[] { "layer", "borderWidth" }, false) },
+ { Button.FontProperty, Tuple.Create (new[] { "titleLabel", "font" }, false) },
+ { Button.TextProperty, Tuple.Create (new[] { "titleLabel", "text" }, false) },
+ { Button.TextColorProperty, Tuple.Create (new[] { "titleLabel", "textColor" }, false) },
+ { View.AnchorXProperty, Tuple.Create (new[] { "layer", "transform" }, true) },
+ { View.AnchorYProperty, Tuple.Create (new[] { "layer", "transform" }, true) },
+ { View.BackgroundColorProperty, Tuple.Create (new[] { "backgroundColor" }, false) },
+ { View.IsEnabledProperty, Tuple.Create (new[] { "isEnabled" }, false) },
+ { View.OpacityProperty, Tuple.Create (new [] { "alpha" }, true) },
+ { View.RotationProperty, Tuple.Create (new[] { "layer", "transform" }, true) },
+ { View.RotationXProperty, Tuple.Create (new[] { "layer", "transform" }, true) },
+ { View.RotationYProperty, Tuple.Create (new[] { "layer", "transform" }, true) },
+ { View.ScaleProperty, Tuple.Create (new[] { "layer", "transform" }, true) },
+ };
+ }
+
+ internal static class PlatformViews
+ {
+ public static readonly string ActivityIndicator = "UIActivityIndicatorView";
+ public static readonly string BoxView = "Xamarin_Forms_Platform_iOS_BoxRenderer";
+ public static readonly string Button = "UIButton";
+ public static readonly string DatePicker = "UITextField";
+ public static readonly string Editor = "UITextView";
+ public static readonly string Entry = "UITextField";
+ public static readonly string Frame = "view:'Xamarin_Forms_Platform_iOS_FrameRenderer'";
+ public static readonly string Image = "UIImageView";
+ public static readonly string Label = "UILabel";
+ public static readonly string ListView = "UITableView";
+ public static readonly string OpenGLView = "GLKView";
+ public static readonly string Picker = "UITextField";
+ public static readonly string ProgressBar = "UIProgressView";
+ public static readonly string SearchBar = "UISearchBar";
+ public static readonly string Slider = "UISlider";
+ public static readonly string Stepper = "UIStepper";
+ public static readonly string Switch = "UISwitch";
+ public static readonly string TableView = "UITableView";
+ public static readonly string TimePicker = "UITextField";
+ public static readonly string WebView = "UIWebView";
+ }
+
+ internal static class PlatformQueries
+ {
+ public static readonly Func<AppQuery, AppQuery> Root = q => q.Class ("UIWindow");
+ public static readonly Func<AppQuery, AppQuery> RootPageListView = q => q.Class ("Xamarin_Forms_Platform_iOS_ListViewRenderer index:0");
+ public static readonly Func<AppQuery, AppQuery> GalleryListView = q => q.Class ("Xamarin_Forms_Platform_iOS_ListViewRenderer index:1");
+ public static readonly Func<AppQuery, AppQuery> PageWithoutNavigationBar = q => q.Raw ("*").Index (7);
+ public static readonly Func<AppQuery, AppQuery> NavigationBarBackButton = q => q.Class ("UINavigationItemButtonView");
+
+ // Controls
+ public static readonly Func<AppQuery, AppQuery> ActivityIndicator = q => q.ClassFull (PlatformViews.ActivityIndicator);
+ public static readonly Func<AppQuery, AppQuery> Button = q => q.ClassFull (PlatformViews.Button);
+
+ public static Func<AppQuery, AppQuery> EntryWithPlaceholder (string text) {
+ return q => q.Raw (string.Format ("TextField placeholder:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryWithText (string text) {
+ return q => q.Raw (string.Format ("TextField text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryCellWithPlaceholder (string text) {
+ return q => q.Raw (string.Format ("UITextFieldLabel text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryCellWithText (string text) {
+ return q => q.Raw (string.Format ("TextField text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EditorsWithText (string text) {
+ return q => q.Raw (string.Format ("TextView text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryWithIndex (int index) {
+ return q => q.Raw (string.Format ("TextField index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> SearchBarWithIndex (int index) {
+ return q => q.Raw (string.Format ("SearchBar index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> LabelWithIndex (int index) {
+ return q => q.Raw (string.Format ("Label index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> LabelWithText (string text) {
+ return q => q.Raw (string.Format ("Label text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> LabelWithId (string id) {
+ return q => q.Raw (string.Format ("Label id:'{0}'", id));
+ }
+
+ public static Func<AppQuery, AppQuery> PickerEntryWithIndex (int index) {
+ return q => q.Raw (string.Format ("TextField index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> PickerEntryWithPlaceholder (string placeholder) {
+ return q => q.Raw (string.Format ("TextField placeholder:'{0}'", placeholder));
+ }
+
+ public static Func<AppQuery, AppQuery> PickerEntryWithText (string text) {
+ return q => q.Raw (string.Format ("TextField text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> SwitchWithIndex (int index) {
+ return q => q.Raw (string.Format ("Switch index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> StepperWithIndex (int index) {
+ return q => q.Raw (string.Format ("Stepper index:{0}", index));
+ }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Properties/AssemblyInfo.cs b/Xamarin.Forms.Core.iOS.UITests/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..1246e892
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Properties/AssemblyInfo.cs
@@ -0,0 +1,40 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Xamarin.Forms.Core.iOS.UITests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Forms.Core.iOS.UITests")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("e3f6d744-9587-4d06-b7eb-5560d847c107")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+
+[assembly: InternalsVisibleTo("Xamarin.Forms.Loader")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.UITest.Validator")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.UITest.TestCloud")]
diff --git a/Xamarin.Forms.Core.iOS.UITests/Queries.cs b/Xamarin.Forms.Core.iOS.UITests/Queries.cs
new file mode 100644
index 00000000..dbc8ef47
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Queries.cs
@@ -0,0 +1,165 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal static class GalleryQueries
+ {
+ public const string AutomationIDGallery = "* marked:'AutomationID Gallery'";
+ public const string ActivityIndicatorGallery = "* marked:'ActivityIndicator Gallery'";
+ public const string BoxViewGallery = "* marked:'BoxView Gallery'";
+ public const string ButtonGallery = "* marked:'Button Gallery'";
+ public const string ContextActionsListGallery = "* marked:'ContextActions List Gallery'";
+ public const string ContextActionsTableGallery = "* marked:'ContextActions Table Gallery'";
+ public const string DatePickerGallery = "* marked:'DatePicker Gallery'";
+ public const string EditorGallery = "* marked:'Editor Gallery'";
+ public const string EntryGallery = "* marked:'Entry Gallery'";
+ public const string FrameGallery = "* marked:'Frame Gallery'";
+ public const string ImageGallery = "* marked:'Image Gallery'";
+ public const string LabelGallery = "* marked:'Label Gallery'";
+ public const string ListViewGallery = "* marked:'ListView Gallery'";
+ public const string OpenGLViewGallery = "* marked:'OpenGLView Gallery'";
+ public const string PickerGallery = "* marked:'Picker Gallery'";
+ public const string ProgressBarGallery = "* marked:'ProgressBar Gallery'";
+ public const string ScrollViewGallery = "* marked:'ScrollView Gallery'";
+ public const string ScrollViewGalleryHorizontal = "* marked:'ScrollView Gallery Horizontal'";
+ public const string SearchBarGallery = "* marked:'SearchBar Gallery'";
+ public const string SliderGallery = "* marked:'Slider Gallery'";
+ public const string StepperGallery = "* marked:'Stepper Gallery'";
+ public const string SwitchGallery = "* marked:'Switch Gallery'";
+ public const string TableViewGallery = "* marked:'TableView Gallery'";
+ public const string TimePickerGallery = "* marked:'TimePicker Gallery'";
+ public const string WebViewGallery = "* marked:'WebView Gallery'";
+ public const string ToolbarItemGallery = "* marked:'ToolbarItems Gallery'";
+ public const string DisplayAlertGallery = "* marked:'DisplayAlert Gallery'";
+ public const string ActionSheetGallery = "* marked:'ActionSheet Gallery'";
+ public const string RootPagesGallery = "* marked:'RootPages Gallery'";
+
+ public const string AppearingGallery = "* marked:'Appearing Gallery'";
+
+ // Legacy galleries
+ public const string AbsoluteLayoutGalleryLegacy = "* marked:'AbsoluteLayout Gallery - Legacy'";
+ public const string BoundPageGalleryLegacy = "* marked:'BoundPage Gallery - Legacy'";
+ public const string ButtonGalleryLegacy = "* marked:'Button Gallery - Legacy'";
+ public const string CellsGalleryLegacy = "* marked:'Cells Gallery - Legacy'";
+ public const string CarouselPageGalleryLegacy = "* marked:'CarouselPage Gallery - Legacy'";
+ public const string ClipToBoundsGalleryLegacy = "* marked:'ClipToBounds Gallery - Legacy'";
+ public const string EditorGalleryLegacy = "* marked:'Editor Gallery - Legacy'";
+ public const string EntryGalleryLegacy = "* marked:'Entry Gallery - Legacy'";
+ public const string GridGalleryLegacy = "* marked:'Grid Gallery - Legacy'";
+ public const string GroupedListActionsGalleryLegacy = "* marked:'GroupedListActions Gallery - Legacy'";
+ public const string GroupedListGalleryLegacy = "* marked:'GroupedList Gallery - Legacy'";
+ public const string InputIntentGalleryLegacy = "* marked:'InputIntent Gallery - Legacy'";
+ public const string ListViewGalleryLegacy = "* marked:'ListView Gallery - Legacy'";
+ public const string MapGalleryLegacy = "* marked:'Map Gallery - Legacy'";
+ public const string MinimumSizeGalleryLegacy = "* marked:'MinimumSize Gallery - Legacy'";
+ public const string NavigationBarGalleryLegacy = "* marked:'NavigationBar Gallery - Legacy'";
+ public const string RelativeLayoutGalleryLegacy = "* marked:'RelativeLayout Gallery - Legacy'";
+ public const string SearchBarGalleryLegacy = "* marked:'SearchBar Gallery - Legacy'";
+ public const string SliderGalleryLegacy = "* marked:'Slider Gallery - Legacy'";
+ public const string StackLayoutGalleryLegacy = "* marked:'StackLayout Gallery - Legacy'";
+ public const string StepperGalleryLegacy = "* marked:'Stepper Gallery - Legacy'";
+ public const string SwitchGalleryLegacy = "* marked:'Switch Gallery - Legacy'";
+ public const string TableViewGalleryLegacy = "* marked:'TableView Gallery - Legacy'";
+ public const string TemplatedCarouselPageGalleryLegacy = "* marked:'TemplatedCarouselPage Gallery - Legacy'";
+ public const string TemplatedTabbedPageGalleryLegacy = "* marked:'TemplatedTabbedPage Gallery - Legacy'";
+ public const string ToolbarGalleryLegacy = "* marked:'Toolbar Gallery - Legacy'";
+ public const string UnevenViewCellGalleryLegacy = "* marked:'UnevenViewCell Gallery - Legacy'";
+ public const string UnevenListGalleryLegacy = "* marked:'UnevenList Gallery - Legacy'";
+ public const string ViewCellGalleryLegacy = "* marked:'ViewCell Gallery - Legacy'";
+ }
+
+ internal static class Queries
+ {
+ #region Shared queries
+ public static Func<AppQuery, AppQuery> RootPageListView = PlatformQueries.RootPageListView;
+ public static Func<AppQuery, AppQuery> GalleryListView = PlatformQueries.GalleryListView;
+
+ public static Func<AppQuery, AppQuery> ButtonWithText (string text)
+ {
+ return q => q.Button (text);
+ }
+
+ public static Func<AppQuery, AppQuery> ElementWithText (string text)
+ {
+ return q => q.Marked (text);
+ }
+
+ public static Func<AppQuery, AppQuery> All ()
+ {
+ return q => q.All ();
+ }
+
+ #endregion
+
+ #region Platform queries
+
+ public static Func<AppQuery, AppQuery> NavigationBarBackButton ()
+ {
+ return PlatformQueries.NavigationBarBackButton;
+ }
+
+ public static Func<AppQuery, AppQuery> PageWithoutNavigationBar ()
+ {
+ return PlatformQueries.PageWithoutNavigationBar;
+ }
+
+ public static Func<AppQuery, AppQuery> Root ()
+ {
+ return PlatformQueries.Root;
+ }
+
+ public static Func<AppQuery, AppQuery> EntryCellWithPlaceholder (string placeholder)
+ {
+ return PlatformQueries.EntryCellWithPlaceholder (placeholder);
+ }
+
+ public static Func<AppQuery, AppQuery> EntryCellWithText (string placeholder)
+ {
+ return PlatformQueries.EntryCellWithText (placeholder);
+ }
+
+ #endregion
+
+ }
+
+ internal static class Views
+ {
+ public static readonly string ActivityIndicator = PlatformViews.ActivityIndicator;
+ public static readonly string BoxView = PlatformViews.BoxView;
+ public static readonly string Button = PlatformViews.Button;
+ public static readonly string DatePicker = PlatformViews.DatePicker;
+ public static readonly string Editor = PlatformViews.Editor;
+ public static readonly string Entry = PlatformViews.Entry;
+ public static readonly string Frame = PlatformViews.Frame;
+ public static readonly string Image = PlatformViews.Image;
+ public static readonly string Label = PlatformViews.Label;
+ public static readonly string ListView = PlatformViews.ListView;
+ public static readonly string OpenGLView = PlatformViews.OpenGLView;
+ public static readonly string Picker = PlatformViews.Picker;
+ public static readonly string ProgressBar = PlatformViews.ProgressBar;
+ public static readonly string SearchBar = PlatformViews.SearchBar;
+ public static readonly string Slider = PlatformViews.Slider;
+ public static readonly string Stepper = PlatformViews.Stepper;
+ public static readonly string Switch = PlatformViews.Switch;
+ public static readonly string TableView = PlatformViews.TableView;
+ public static readonly string TimePicker = PlatformViews.TimePicker;
+ public static readonly string WebView = PlatformViews.WebView;
+ }
+
+ internal static class Rects
+ {
+ public static AppRect RootViewRect (this IApp app)
+ {
+ return app.Query (q => q.Raw ("* index:0"))[0].Rect;
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Remotes/BaseViewContainerRemote.cs b/Xamarin.Forms.Core.iOS.UITests/Remotes/BaseViewContainerRemote.cs
new file mode 100644
index 00000000..f51782ce
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Remotes/BaseViewContainerRemote.cs
@@ -0,0 +1,315 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Runtime.Remoting.Messaging;
+using System.Security.Permissions;
+
+using NUnit.Framework;
+
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.iOS;
+using System.Globalization;
+
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal abstract class BaseViewContainerRemote
+ {
+ bool requiresDismissal;
+
+ protected IApp App { get; private set; }
+
+ public string ViewQuery { get; private set; }
+
+ public string PlatformViewType { get; set; }
+
+ public string ContainerQuery { get; private set; }
+ public string ContainerDescendents { get; private set; }
+
+ public string EventLabelQuery { get; set; }
+
+ public string StateLabelQuery { get; private set; }
+ public string StateButtonQuery { get; private set; }
+
+ public string LayeredHiddenButtonQuery { get; private set; }
+ public string LayeredLabelQuery { get; private set; }
+
+ protected BaseViewContainerRemote (IApp app, Enum formsType, string platformViewType)
+ {
+ App = app;
+ PlatformViewType = platformViewType;
+
+ // Currently tests are failing because the ViewInitilized is setting the renderer and control, fix and then remove index one
+
+ ContainerQuery = string.Format("* marked:'{0}Container'", formsType);
+ ContainerDescendents = string.Format("* marked:'{0}Container' child *", formsType);
+
+ ViewQuery = string.Format ("* marked:'{0}VisualElement'", formsType);
+
+ EventLabelQuery = string.Format ("* marked:'{0}EventLabel'", formsType);
+ StateLabelQuery = string.Format ("* marked:'{0}StateLabel'", formsType);
+ StateButtonQuery = string.Format ("* marked:'{0}StateButton'", formsType);
+ LayeredHiddenButtonQuery = string.Format ("* marked:'{0}LayeredHiddenButton'", formsType);
+ LayeredLabelQuery = string.Format ("* marked:'{0}LayeredLabel'", formsType);
+
+ if (platformViewType == PlatformViews.DatePicker) {
+ requiresDismissal = true;
+ }
+ }
+
+ public virtual void GoTo ([CallerMemberName] string callerMemberName = "")
+ {
+ var scrollBounds = App.Query (Queries.PageWithoutNavigationBar ()).First ().Rect;
+
+ // Scroll using gutter to the right of view, avoid scrolling inside of WebView
+ if (PlatformViewType == PlatformViews.WebView) {
+ scrollBounds = new AppRect {
+ X = scrollBounds.Width - 20,
+ CenterX = scrollBounds.Width - 10,
+ Y = scrollBounds.Y,
+ CenterY = scrollBounds.CenterY,
+ Width = 20,
+ Height = scrollBounds.Height,
+ };
+ }
+
+
+ while (true) {
+ var result = App.Query (o => o.Raw(ContainerQuery));
+ if (result.Any ())
+ break;
+ App.Tap (o => o.Raw ("* marked:'MoveNextButton'"));
+ }
+
+ //Assert.True (App.ScrollForElement (
+ // ContainerQuery, new Drag (scrollBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium)
+ //), "Failed to find element in: " + callerMemberName);
+
+ App.Screenshot ("Go to element");
+ }
+
+ public void TapView ()
+ {
+ App.Tap (q => q.Raw (ViewQuery));
+ }
+
+ public void DismissPopOver ()
+ {
+ App.Screenshot ("About to dismiss pop over");
+ App.Tap (q => q.Button ("Done"));
+ App.Screenshot ("Pop over dismissed");
+ }
+
+ public AppResult GetView ()
+ {
+ return App.Query (q => q.Raw (ViewQuery)).First ();
+ }
+
+ public AppResult[] GetViews ()
+ {
+ return App.Query (q => q.Raw (ViewQuery));
+ }
+
+ public AppResult[] GetContainerDescendants ()
+ {
+ return App.Query (q => q.Raw (ContainerDescendents));
+ }
+
+ public T GetProperty<T> (BindableProperty formProperty)
+ {
+ Tuple<string[], bool> property = formProperty.GetPlatformPropertyQuery ();
+ string[] propertyPath = property.Item1;
+ bool isOnParentRenderer = property.Item2;
+
+ var query = ViewQuery;
+ if (isOnParentRenderer &&
+ PlatformViewType != PlatformViews.BoxView &&
+ PlatformViewType != PlatformViews.Frame) {
+ query = query + " parent * index:0";
+ }
+
+ object prop = null;
+ bool found = false;
+
+ bool isEdgeCase = false;
+ if (App is AndroidApp && formProperty == View.ScaleProperty)
+ isEdgeCase = true;
+
+ if (!isEdgeCase) {
+ found =
+ MaybeGetProperty<string> (App, query, propertyPath, out prop) ||
+ MaybeGetProperty<float> (App, query, propertyPath, out prop) ||
+ MaybeGetProperty<bool> (App, query, propertyPath, out prop) ||
+ MaybeGetProperty<object> (App, query, propertyPath, out prop);
+ }
+
+
+ if (App is AndroidApp && formProperty == View.ScaleProperty) {
+ var matrix = new Matrix ();
+ matrix.M00 = App.Query (q => q.Raw (query).Invoke (propertyPath[0]).Value<float> ()).First ();
+ matrix.M11 = App.Query (q => q.Raw (query).Invoke (propertyPath[1]).Value<float> ()).First ();
+ matrix.M22 = 0.5f;
+ matrix.M33 = 1.0f;
+ return (T)((object)matrix);
+ }
+
+ if (!found || prop == null) {
+ throw new NullReferenceException ("null property");
+ }
+
+ if (prop.GetType () == typeof(T))
+ return (T)prop;
+
+ if (prop.GetType () == typeof(string) && typeof(T) == typeof(Matrix)) {
+ Matrix matrix = ParsingUtils.ParseCATransform3D ((string)prop);
+ return (T)((object)matrix);
+ }
+
+ if (typeof(T) == typeof(Color)) {
+ if (App is iOSApp) {
+ Color color = ParsingUtils.ParseUIColor ((string)prop);
+ return (T)((object)color);
+ } else {
+ uint intColor = (uint)((float)prop);
+ Color color = Color.FromUint (intColor);
+ return (T)((object)color);
+ }
+ }
+
+ if (prop.GetType () == typeof (string) && typeof(T) == typeof(Font)) {
+ if (App is iOSApp) {
+ Font font = ParsingUtils.ParseUIFont ((string)prop);
+ return (T)((object)font);
+ } else {
+
+ }
+ }
+
+ T result = default(T);
+
+ var stringToBoolConverter = new StringToBoolConverter ();
+ var floatToBoolConverter = new FloatToBoolConverter ();
+
+ if (stringToBoolConverter.CanConvertTo (prop, typeof(bool))) {
+ result = (T)stringToBoolConverter.ConvertTo (prop, typeof(bool));
+ } else if (floatToBoolConverter.CanConvertTo (prop, typeof(bool))) {
+ result = (T)floatToBoolConverter.ConvertTo (prop, typeof(bool));
+ }
+
+ return result;
+ }
+
+ static bool MaybeGetProperty<T>(IApp app, string query, string[] propertyPath, out object result)
+ {
+
+ try {
+ switch (propertyPath.Length){
+ case 1:
+ result = app.Query (q => q.Raw (query).Invoke (propertyPath[0]).Value<T> ()).First ();
+ break;
+ case 2:
+ result = app.Query (q => q.Raw (query).Invoke (propertyPath[0]).Invoke (propertyPath[1]).Value<T> ()).First ();
+ break;
+ case 3:
+ result = app.Query (q => q.Raw (query).Invoke (propertyPath[0]).Invoke (propertyPath[1]).Invoke (propertyPath[2]).Value<T> ()).First ();
+ break;
+ case 4:
+ result = app.Query (q => q.Raw (query).Invoke (propertyPath[0]).Invoke (propertyPath[1]).Invoke (propertyPath[2]).Invoke(propertyPath[3]).Value<T> ()).First ();
+ break;
+ default:
+ result = null;
+ return false;
+ }
+ }
+ catch {
+ result = null;
+ return false;
+ }
+
+ return true;
+ }
+
+ }
+
+ internal class StringToBoolConverter : TypeConverter
+ {
+ public override bool CanConvertTo (object source, Type targetType)
+ {
+ if (targetType != typeof(bool) || !(source is string))
+ return false;
+
+ var str = (string)source;
+ str = str.ToLowerInvariant ();
+
+ switch (str) {
+ case "0":
+ case "1":
+ case "false":
+ case "true":
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public override object ConvertTo (object source, Type targetType)
+ {
+ var str = (string)source;
+ str = str.ToLowerInvariant();
+
+ switch (str)
+ {
+ case "1":
+ case "true":
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+
+ internal class FloatToBoolConverter : TypeConverter
+ {
+ public override bool CanConvertTo (object source, Type targetType)
+ {
+ if (targetType != typeof(bool) || !(source is float))
+ return false;
+
+ var flt = (float)source;
+ var epsilon = 0.0001;
+ if (Math.Abs (flt - 1.0f) < epsilon || Math.Abs (flt - 0.0f) < epsilon)
+ return true;
+ else
+ return false;
+ }
+
+ public override object ConvertTo (object source, Type targetType)
+ {
+ var flt = (float)source;
+ var epsilon = 0.0001;
+ if (Math.Abs (flt - 1.0f) < epsilon)
+ return true;
+ else
+ return false;
+ }
+ }
+
+ internal abstract class TypeConverter
+ {
+ public abstract bool CanConvertTo (object source, Type targetType);
+
+ public abstract object ConvertTo (object source, Type targetType);
+ }
+
+ internal static class PlatformMethods
+ {
+ public static Tuple<string[], bool> GetPlatformPropertyQuery (this BindableProperty bindableProperty)
+ {
+ return PlatformMethodQueries.PropertyPlatformMethodDictionary[bindableProperty];
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Remotes/EventViewContainerRemote.cs b/Xamarin.Forms.Core.iOS.UITests/Remotes/EventViewContainerRemote.cs
new file mode 100644
index 00000000..d603974d
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Remotes/EventViewContainerRemote.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Linq;
+
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal sealed class EventViewContainerRemote : BaseViewContainerRemote
+ {
+ public EventViewContainerRemote (IApp app, Enum formsType, string platformViewType)
+ : base (app, formsType, platformViewType) { }
+
+ public AppResult GetEventLabel ()
+ {
+ App.WaitForElement (q => q.Raw (EventLabelQuery));
+ return App.Query (q => q.Raw (EventLabelQuery)).First ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Remotes/LayeredViewContainerRemote.cs b/Xamarin.Forms.Core.iOS.UITests/Remotes/LayeredViewContainerRemote.cs
new file mode 100644
index 00000000..6f6c1071
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Remotes/LayeredViewContainerRemote.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Linq;
+using System.Security.Cryptography.X509Certificates;
+
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal sealed class LayeredViewContainerRemote : BaseViewContainerRemote
+ {
+ public LayeredViewContainerRemote (IApp app, Enum formsType, string platformViewType)
+ : base (app, formsType, platformViewType) {}
+
+ public AppResult GetLayeredLabel ()
+ {
+ return App.Query (q => q.Raw (LayeredLabelQuery)).First ();
+ }
+
+ public void TapHiddenButton ()
+ {
+ App.Tap (q => q.Raw (LayeredHiddenButtonQuery));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Remotes/RemoteFactory.cs b/Xamarin.Forms.Core.iOS.UITests/Remotes/RemoteFactory.cs
new file mode 100644
index 00000000..ec9757ef
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Remotes/RemoteFactory.cs
@@ -0,0 +1,56 @@
+using System;
+
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+
+// Potential cleanup of Raw Queries
+// public void MyTest(IApp app)
+// {
+// var viewName = "myView";
+//
+// app.Query (x => x.Marked (viewName + " View").Parent ().Index (0).Sibling ().Index (1).Child (0).Child (0));
+//
+// app.Query (x => x.Marked (viewName + " View").Parent (0).Sibling (1).Child (0).Child (0));
+//
+// app.Query (x => x.LayeredHiddenButton ("mine").LayeredHiddenButton ("yours"));
+//
+// app.Query (x => x.LayeredHiddenButton (viewName).Parentx(4));
+//
+// app.ForAndroid (x => {
+// x.Back();
+// });
+// }
+
+
+// Potential cleanup of Raw Queries
+// make public or reflection will not pick up in REPL
+// internal static class Exts
+// {
+// public static void ForAndroid(this IApp app, Action<AndroidApp> action)
+// {
+// if (app is AndroidApp)
+// {
+// action (app as AndroidApp);
+// }
+// }
+//
+// public static AppQuery LayeredHiddenButton(this AppQuery query, string viewName)
+// {
+// if(query.QueryPlatform == QueryPlatform.Android)
+// {
+// return query.Marked (viewName + " Android View").Parent (0).Sibling (1).Child (0).Child (0);
+//
+// }
+// return query.Marked (viewName + " iOS View").Parent (0).Sibling (1).Child (0).Child (0);
+// }
+//
+// public static AppQuery Parentx(this AppQuery query, int index)
+// {
+// return query.Parent ().Index (index);
+// }
+// }
+
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Remotes/StateViewContainerRemote.cs b/Xamarin.Forms.Core.iOS.UITests/Remotes/StateViewContainerRemote.cs
new file mode 100644
index 00000000..2d7a1172
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Remotes/StateViewContainerRemote.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+using NUnit.Framework;
+
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal sealed class StateViewContainerRemote : BaseViewContainerRemote
+ {
+ public StateViewContainerRemote (IApp app, Enum formsType, string platformViewType)
+ : base(app, formsType, platformViewType) { }
+
+ public void TapStateButton ()
+ {
+ App.Screenshot ("Before state change");
+ App.Tap (q => q.Raw (StateButtonQuery));
+ App.Screenshot ("After state change");
+ }
+
+ public AppResult GetStateLabel ()
+ {
+ return App.Query (q => q.Raw (StateLabelQuery)).First ();
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Remotes/ViewContainerRemote.cs b/Xamarin.Forms.Core.iOS.UITests/Remotes/ViewContainerRemote.cs
new file mode 100644
index 00000000..f19d3e6b
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Remotes/ViewContainerRemote.cs
@@ -0,0 +1,13 @@
+using System;
+
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal sealed class ViewContainerRemote : BaseViewContainerRemote
+ {
+ public ViewContainerRemote (IApp app, Enum formsType, string platformViewType)
+ : base (app, formsType, platformViewType) { }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/ActionSheetUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/ActionSheetUITests.cs
new file mode 100644
index 00000000..9899d024
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/ActionSheetUITests.cs
@@ -0,0 +1,171 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+using System;
+using System.Threading;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("ActionSheet")]
+ internal class ActionSheetUITests : BaseTestFixture
+ {
+ AppRect screenSize;
+
+ public ActionSheetUITests ()
+ {
+
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.ActionSheetGallery);
+ }
+
+ static void CheckExtras ()
+ {
+ App.WaitForElement (c => c.Marked ("Extra One"));
+ App.WaitForElement (c => c.Marked ("Extra Eight"));
+ }
+
+ protected override void TestSetup ()
+ {
+ base.TestSetup ();
+ screenSize = App.Query (q => q.Marked ("ActionSheetPage"))[0].Rect;
+ }
+
+ [Test]
+ public void TestDisplayActionSheet ()
+ {
+ ScrollAndTap ("ActionSheet Extras");
+ CheckExtras ();
+ App.Tap (c => c.Marked ("Extra One"));
+ }
+
+ [Test]
+ public void TestDisplayActionSheetCancel ()
+ {
+ ScrollAndTap ("ActionSheet Cancel");
+ // iPad does not have a Cancel button for action sheet
+ if (App.Query (q => q.Marked ("Cancel")).Length > 0)
+ App.Tap (c => c.Marked ("Cancel"));
+ else
+ App.TapCoordinates (20, screenSize.Height / 2);
+ }
+
+ [Test]
+ public void TestDisplayActionSheetCancelDestruction ()
+ {
+ ScrollAndTap ("ActionSheet Cancel Destruction");
+ App.WaitForNoElement (c => c.Marked ("Extra One"));
+ App.WaitForElement (c => c.Marked ("Destruction"));
+ if (App.Query (q => q.Marked ("Cancel")).Length > 0)
+ App.Tap (c => c.Marked ("Cancel"));
+ else
+ App.TapCoordinates (20, screenSize.Height / 2);
+ }
+
+ [Test]
+ public void TestDisplayActionSheetCancelExtras ()
+ {
+ ScrollAndTap ("ActionSheet Cancel Extras");
+ CheckExtras ();
+ if (App.Query (q => q.Marked ("Cancel")).Length > 0)
+ App.Tap (c => c.Marked ("Cancel"));
+ else
+ App.TapCoordinates (20, screenSize.Height / 2);
+ }
+
+ [Test]
+ public void TestDisplayActionSheetCancelExtrasDestruction ()
+ {
+ ScrollAndTap ("ActionSheet Cancel Destruction Extras");
+ CheckExtras ();
+ App.WaitForElement (c => c.Marked ("Destruction"));
+ if (App.Query (q => q.Marked ("Cancel")).Length > 0)
+ App.Tap (c => c.Marked ("Cancel"));
+ else
+ App.TapCoordinates (20, screenSize.Height / 2);
+ }
+
+ [Test]
+ public void TestDisplayActionSheetDestruction ()
+ {
+ ScrollAndTap ("ActionSheet Destruction");
+ App.WaitForNoElement (c => c.Marked ("Extra One"));
+ App.Tap (c => c.Marked ("Destruction"));
+ }
+
+ [Test]
+ public void TestDisplayActionSheetDestructionExtras ()
+ {
+ ScrollAndTap ("ActionSheet Destruction Extras");
+ CheckExtras ();
+ App.Tap (c => c.Marked ("Extra One"));
+ }
+
+ [Test]
+ public void TestDisplayActionSheetTitleCancel ()
+ {
+ ScrollAndTap ("ActionSheet Title Cancel");
+ App.WaitForElement (c => c.Marked ("Title"));
+ if (App.Query (q => q.Marked ("Cancel")).Length > 0)
+ App.Tap (c => c.Marked ("Cancel"));
+ else
+ App.TapCoordinates (20, screenSize.Height / 2);
+ }
+
+ [Test]
+ public void TestDisplayActionSheetTitleCancelDestruction ()
+ {
+ ScrollAndTap ("ActionSheet Title Cancel Destruction");
+ App.WaitForElement (c => c.Marked ("Title"));
+ App.WaitForNoElement (c => c.Marked ("Extra One"));
+ App.Tap (c => c.Marked ("Destruction"));
+ }
+
+ [Test]
+ public void TestDisplayActionSheetTitleCancelDestructionExtras ()
+ {
+ ScrollAndTap ("ActionSheet Title Cancel Destruction Extras");
+ App.WaitForElement (c => c.Marked ("Title"));
+ CheckExtras ();
+ App.Tap (c => c.Marked ("Destruction"));
+ }
+
+ [Test]
+ public void TestDisplayActionSheetTitleDestruction ()
+ {
+ ScrollAndTap ("ActionSheet Title Destruction");
+ App.WaitForElement (c => c.Marked ("Title"));
+ App.WaitForNoElement (c => c.Marked ("Extra One"));
+ App.Tap (c => c.Marked ("Destruction"));
+ }
+
+ [Test]
+ public void TestDisplayActionSheetTitleDestructionExtras ()
+ {
+ ScrollAndTap ("ActionSheet Title Destruction Extras");
+ App.WaitForElement (c => c.Marked ("Title"));
+ CheckExtras ();
+ App.Tap (c => c.Marked ("Destruction"));
+ }
+
+
+ [Test]
+ public void TestDisplayActionSheetTitleExtras ()
+ {
+ ScrollAndTap ("ActionSheet Title Extras");
+ CheckExtras ();
+ App.Tap (c => c.Marked ("Extra One"));
+ }
+
+ void ScrollAndTap(string actionSheet)
+ {
+ App.ScrollForElement(string.Format("* text:'{0}'", actionSheet), new Drag(App.Query(q => q.Marked("ActionSheetPage"))[0].Rect, Drag.Direction.BottomToTop, Drag.DragLength.Long));
+ App.Tap(q=>q.Raw(string.Format("* text:'{0}'", actionSheet)));
+ }
+
+ }
+}
+
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/ActivityIndicatorUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/ActivityIndicatorUITests.cs
new file mode 100644
index 00000000..325a5682
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/ActivityIndicatorUITests.cs
@@ -0,0 +1,76 @@
+using System;
+using System.IO;
+using System.Linq;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("ActivityIndicator")]
+ internal class ActivityIndicatorUITests : _ViewUITests
+ {
+ public ActivityIndicatorUITests ()
+ {
+ PlatformViewType = Views.ActivityIndicator;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.ActivityIndicatorGallery);
+ }
+
+ // View tests
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _Focus () {}
+
+ public override void _GestureRecognizers ()
+ {
+ // TODO Can implement this
+ var remote = new ViewContainerRemote (App, Test.View.GestureRecognizers, PlatformViewType);
+ remote.GoTo ();
+ }
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsEnabled () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsFocused () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _UnFocus () {}
+
+ //[UiTest (typeof(ActivityIndicator), "Color")]
+ public void Color ()
+ {
+ //TODO: this was failing and is changing in next version of calabash (UI-Test-pre nuget) to a json rgb
+
+// var remote = RemoteFactory.CreateRemote<ViewContainerRemote> (App, "Color", PlatformViewType);
+// remote.GoTo ();
+//
+// var color = remote.GetProperty<Color> (ActivityIndicator.ColorProperty);
+// Assert.AreEqual (Forms.Color.Lime, color);
+ }
+
+ // ActivityIndicator tests
+ [Test]
+ [UiTest (typeof(ActivityIndicator), "IsRunning")]
+ public void IsRunning ()
+ {
+ var remote = new ViewContainerRemote (App, Test.ActivityIndicator.IsRunning, PlatformViewType);
+ remote.GoTo ();
+
+ var isRunning = remote.GetProperty<bool> (ActivityIndicator.IsRunningProperty);
+ Assert.IsTrue (isRunning);
+ }
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/AppearingUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/AppearingUITests.cs
new file mode 100644
index 00000000..c346b4fc
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/AppearingUITests.cs
@@ -0,0 +1,64 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [Category ("Lifecycle")]
+ internal class AppearingUITests : BaseTestFixture
+ {
+
+ public AppearingUITests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.AppearingGallery);
+ }
+
+ [Test]
+ public void AppearingNavigationPage ()
+ {
+ App.Tap (t => t.Marked ("NavAppearingPage"));
+ App.WaitForElement ("Appearing NavAppearingPage");
+ App.WaitForElement ("Appearing Page 1");
+ App.Tap (t => t.Marked ("Push new Page"));
+ App.WaitForElement ("Disappearing Page 1");
+ App.WaitForElement ("Appearing Page 2");
+ App.Tap (t => t.Marked ("Change Main Page"));
+ App.WaitForElement ("Disappearing Page 2");
+ App.WaitForElement ("Disappearing NavAppearingPage");
+ App.WaitForElement ("Appearing Page 3");
+ }
+
+
+ [Test]
+ public void AppearingCarouselPage ()
+ {
+ App.Tap (t => t.Marked ("CarouselAppearingPage"));
+ App.WaitForElement ("Appearing CarouselAppearingPage");
+ App.WaitForElement ("Appearing Page 1");
+
+ }
+
+ [Test]
+ public void AppearingTabbedPage ()
+ {
+ App.Tap (t => t.Marked ("TabbedAppearingPage"));
+ App.WaitForElement ("Appearing TabbedAppearingPage");
+ App.WaitForElement ("Appearing Page 1");
+
+ }
+
+ [Test]
+ public void AppearingMasterDetailPage ()
+ {
+ App.Tap (t => t.Marked ("MasterAppearingPage"));
+ App.WaitForElement ("Appearing MasterAppearingPage");
+ App.WaitForElement ("Appearing Page 1");
+
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/AutomationIDUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/AutomationIDUITests.cs
new file mode 100644
index 00000000..7746bafa
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/AutomationIDUITests.cs
@@ -0,0 +1,73 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+using System;
+using System.Threading;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("AutomationID")]
+ internal class AutomationIDUITests : BaseTestFixture
+ {
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.AutomationIDGallery);
+ }
+
+ [Test]
+ public void Test1 ()
+ {
+ App.Tap (c => c.Marked ("btnTest1"));
+ App.WaitForElement (c => c.Marked ("scrollMain"));
+ App.WaitForElement (c => c.Marked ("stckMain"));
+ App.WaitForElement (c => c.Marked ("actHello"));
+ App.WaitForElement (c => c.Marked ("bxvHello"));
+ App.Tap (c => c.Marked ("btnHello"));
+ App.WaitForElement (c => c.Marked ("dtPicker"));
+ App.WaitForElement (c => c.Marked ("tPicker"));
+
+ var label = App.Query ("lblHello") [0];
+ Assert.AreEqual (label.Text, "Hello Label");
+
+ var editor = App.Query ("editorHello") [0];
+ Assert.AreEqual (editor.Text, "Hello Editor");
+
+ var entry = App.Query ("entryHello") [0];
+ Assert.AreEqual (entry.Text, "Hello Entry");
+
+ App.Tap (c => c.Marked ("popModal"));
+ }
+
+
+ [Test]
+ public void Test2 ()
+ {
+ App.Tap (c => c.Marked ("btnTest2"));
+ App.WaitForElement (c => c.Marked ("imgHello"));
+ App.WaitForElement (c => c.Marked ("lstView"));
+ App.WaitForElement (c => c.Marked ("pickerHello"));
+ App.WaitForElement (c => c.Marked ("progressHello"));
+ App.ScrollDownTo (c => c.Marked ("progressHello"));
+ App.WaitForElement (c => c.Marked ("srbHello"));
+ App.WaitForElement (c => c.Marked ("sliHello"));
+ App.WaitForElement (c => c.Marked ("stepperHello"));
+ App.WaitForElement (c => c.Marked ("switchHello"));
+ //App.WaitForElement (c => c.Marked ("webviewHello"));
+ App.Tap (c => c.Marked ("popModal"));
+ }
+
+ [Test]
+ [Ignore("only works on ios")]
+ public void TestToolbarItem ()
+ {
+ App.Tap (c => c.Marked ("tbItemHello"));
+ App.WaitForElement (x => x.Marked ("Hello"));
+ App.Tap (c => c.Marked ("ok"));
+ App.Tap (c => c.Marked ("tbItemHello2"));
+ App.WaitForElement (x => x.Marked ("Hello2"));
+ App.Tap (c => c.Marked ("ok"));
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/BoxViewUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/BoxViewUITests.cs
new file mode 100644
index 00000000..cf542c3e
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/BoxViewUITests.cs
@@ -0,0 +1,57 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("BoxView")]
+ internal class BoxViewUITests : _ViewUITests
+ {
+ public BoxViewUITests ()
+ {
+ PlatformViewType = Views.BoxView;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.BoxViewGallery);
+ }
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _Focus () {}
+
+ // TODO
+ public override void _GestureRecognizers () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsFocused () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _UnFocus () {}
+
+ // TODO
+ // Implement control specific ui tests
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsEnabled () {}
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/ButtonUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/ButtonUITests.cs
new file mode 100644
index 00000000..5ae8f506
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/ButtonUITests.cs
@@ -0,0 +1,178 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Button")]
+ internal class ButtonUITests : _ViewUITests
+ {
+ public ButtonUITests ()
+ {
+ PlatformViewType = Views.Button;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.ButtonGallery);
+ }
+
+ // View Tests
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _Focus () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _GestureRecognizers () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsFocused () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _UnFocus () {}
+
+ // Button Tests
+ [Test]
+ [UiTest (typeof(Button),"BorderColor")]
+ [UiTestBroken (BrokenReason.CalabashAndroidUnsupported, "Figure out how to get Android Drawables")]
+ [UiTestBroken (BrokenReason.CalabashiOSUnsupported, "iOS nil result")]
+ public void BorderColor ()
+ {
+ //TODO iOS
+ var remote = new ViewContainerRemote (App, Test.Button.BorderColor, PlatformViewType);
+ remote.GoTo ();
+
+ }
+
+ [Test]
+ [UiTest (typeof (Button), "BorderRadius")]
+ [UiTestBroken (BrokenReason.CalabashAndroidUnsupported, "Figure out how to get Android Drawables")]
+ public void BorderRadius ()
+ {
+ var remote = new ViewContainerRemote (App, Test.Button.BorderRadius, PlatformViewType);
+ remote.GoTo ();
+
+ if (App is iOSApp) {
+ var borderRadius = remote.GetProperty<float> (Button.BorderRadiusProperty);
+ Assert.AreEqual (20.0f, borderRadius);
+ }
+
+ }
+
+ [Test]
+ [UiTest (typeof (Button), "BorderWidth")]
+ [UiTestBroken (BrokenReason.CalabashAndroidUnsupported, "Figure out how to get Android Drawables")]
+ public void BorderWidth ()
+ {
+ var remote = new ViewContainerRemote (App, Test.Button.BorderWidth, PlatformViewType);
+ remote.GoTo ();
+
+ if (App is iOSApp) {
+ var borderWidth = remote.GetProperty<float> (Button.BorderWidthProperty);
+ Assert.AreEqual (15.0f, borderWidth);
+ }
+
+ }
+
+ [Test]
+ [UiTest (typeof (Button), "Clicked")]
+ public void Clicked ()
+ {
+ var remote = new EventViewContainerRemote (App, Test.Button.Clicked, PlatformViewType);
+ remote.GoTo ();
+
+ var textBeforeClick = remote.GetEventLabel ().Text;
+ Assert.AreEqual ("Event: Clicked (none)", textBeforeClick);
+
+ // Click Button
+ remote.TapView ();
+
+ var textAfterClick = remote.GetEventLabel ().Text;
+ Assert.AreEqual ("Event: Clicked (fired 1)", textAfterClick);
+ }
+
+ [Test]
+ [UiTest (typeof (Button), "Command")]
+ public void Command ()
+ {
+ var remote = new ViewContainerRemote (App, Test.Button.Command, PlatformViewType);
+ remote.GoTo ();
+
+ remote.TapView ();
+
+ App.WaitForElement (q => q.Marked ("Hello Command"));
+ App.Tap (q => q.Marked ("Destroy"));
+ }
+
+ [Test]
+ [UiTest (typeof (Button), "Font")]
+ public void Font ()
+ {
+ //TODO iOS
+ var remote = new ViewContainerRemote (App, Test.Button.Font, PlatformViewType);
+ remote.GoTo ();
+
+ if (App is AndroidApp) {
+ var isBold = remote.GetProperty<bool> (Button.FontProperty);
+ Assert.True (isBold);
+ } else {
+ var font = remote.GetProperty<Font> (Button.FontProperty);
+ Assert.True (font.FontAttributes.HasFlag (FontAttributes.Bold));
+ }
+
+ }
+
+ [Test]
+ [UiTest (typeof (Button), "Image")]
+ [UiTestExempt (ExemptReason.TimeConsuming, "Need way to check Android resources")]
+ public void Image ()
+ {
+ //TODO iOS
+ var remote = new ViewContainerRemote (App, Test.Button.Image, PlatformViewType);
+ remote.GoTo ();
+ }
+
+ [Test]
+ [UiTest (typeof (Button), "Text")]
+ public void Text ()
+ {
+ var remote = new ViewContainerRemote (App, Test.Button.Text, PlatformViewType);
+ remote.GoTo ();
+
+ var buttonText = remote.GetProperty<string> (Button.TextProperty);
+ Assert.AreEqual ("Text", buttonText);
+ }
+
+ [Test]
+ [UiTest (typeof (Button), "TextColor")]
+ public void TextColor ()
+ {
+ //TODO iOS
+ if (App is AndroidApp) {
+ var remote = new ViewContainerRemote (App, Test.Button.TextColor, PlatformViewType);
+ remote.GoTo ();
+
+ var buttonTextColor = remote.GetProperty<Color> (Button.TextColorProperty);
+ Assert.AreEqual (Color.Pink, buttonTextColor);
+ }
+ }
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/ContextActionsUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/ContextActionsUITests.cs
new file mode 100644
index 00000000..7691dd46
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/ContextActionsUITests.cs
@@ -0,0 +1,129 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+using System;
+using System.Threading;
+
+using Xamarin.UITest.Android;
+using Xamarin.UITest.iOS;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Cells")]
+ internal class ContextActionsListUITests : BaseTestFixture
+ {
+
+ public ContextActionsListUITests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.ContextActionsListGallery);
+ }
+
+ const string cell0 = "Subject Line 0";
+ const string cell1 = "Subject Line 1";
+ const string move = "Move";
+ const string delete = "Delete";
+ const string clear = "Clear Items";
+ const string mark = "Mark";
+
+ [Test]
+ public void ContextActionsShow ()
+ {
+ if (App is AndroidApp) {
+ // mark is an icon on android
+ App.TouchAndHold (q => q.Marked (cell0));
+ App.WaitForElement (q => q.Marked (delete));
+ App.Screenshot ("I have actions!");
+ } else if (App is iOSApp) {
+ Assert.Inconclusive ("Not tested on iOS yet");
+ }
+ }
+
+ [Test]
+ public void ContextActionsDelete ()
+ {
+ if (App is AndroidApp) {
+ // mark is an icon on android
+ App.TouchAndHold (q => q.Marked (cell0));
+ App.WaitForElement (q => q.Marked (delete));
+ App.Screenshot ("I have actions!");
+
+ App.Tap (q => q.Marked (delete));
+ App.WaitForNoElement (q => q.Marked (cell0));
+ App.Screenshot ("Deleted cell 0");
+
+ } else if (App is iOSApp) {
+ Assert.Inconclusive ("Not tested on iOS yet");
+ }
+ }
+
+ [Test]
+ public void PopoverDismiss()
+ {
+ if (App is iOSApp) {
+ var app = ((iOSApp)App);
+ if (app.Device.IsTablet) {
+ var screenBounds = App.Query (PlatformQueries.Root)[0].Rect;
+ var cellBounds = App.Query (q => q.Marked (cell0))[0].Rect;
+ App.DragCoordinates (screenBounds.Width - 10, cellBounds.CenterY, 10, cellBounds.CenterY);
+ App.Screenshot("I see context actions");
+ App.Tap (q => q.Marked ("More"));
+ App.Screenshot ("Should see Popover");
+ App.TapCoordinates (50, 50);
+ App.Screenshot ("I should not crash");
+ } else {
+ Assert.Inconclusive("Not testing iOS Phone");
+ }
+ } else {
+ Assert.Inconclusive ("Not testing on Android");
+ }
+ }
+ }
+
+ [TestFixture]
+ [Category ("Cells")]
+ internal class ContextActionsTableUITests : BaseTestFixture
+ {
+ public ContextActionsTableUITests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.ContextActionsTableGallery);
+ }
+
+ const string cell0 = "Subject Line 0";
+ const string cell1 = "Subject Line 1";
+ const string move = "Move";
+ const string delete = "Delete";
+ const string clear = "Clear Items";
+ const string mark = "Mark";
+ const string cellWithNoContextActions = "I have no ContextActions";
+
+ [Test]
+ public void ContextActionsShowAndReset ()
+ {
+ if (App is AndroidApp) {
+ // mark is an icon on android
+ App.TouchAndHold (q => q.Marked (cell0));
+ App.WaitForElement (q => q.Marked (delete));
+ App.Screenshot ("I have actions!");
+
+ App.Tap (q => q.Marked (cellWithNoContextActions));
+ App.WaitForNoElement (q => q.Marked (delete));
+ App.Screenshot ("Actions should be gone");
+
+ } else if (App is iOSApp) {
+ Assert.Inconclusive ("Not tested on iOS yet");
+ }
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/DatePickerUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/DatePickerUITests.cs
new file mode 100644
index 00000000..5769f71b
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/DatePickerUITests.cs
@@ -0,0 +1,55 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("DatePicker")]
+ internal class DatePickerUITests : _ViewUITests
+ {
+ public DatePickerUITests ()
+ {
+ PlatformViewType = Views.DatePicker;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.DatePickerGallery);
+ }
+
+ // View Tests
+ // TODO
+ public override void _Focus () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _GestureRecognizers () {}
+
+ // TODO
+ public override void _IsFocused () {}
+
+ // TODO
+ public override void _UnFocus () {}
+
+ // TODO
+ // Implement control specific ui tests
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/DisplayAlertUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/DisplayAlertUITests.cs
new file mode 100644
index 00000000..be0e4997
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/DisplayAlertUITests.cs
@@ -0,0 +1,85 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+using System;
+using System.Threading;
+
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("DisplayAlert")]
+ internal class DisplayAlertUITests : BaseTestFixture
+ {
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.DisplayAlertGallery);
+ }
+
+ [Test]
+ public void TestWithCancelButton ()
+ {
+
+ App.Tap (c => c.Marked ("Alert Override1"));
+ App.Screenshot ("Display Alert");
+ App.WaitForElement (c => c.Marked ("TheAlertTitle"));
+ App.WaitForElement (c => c.Marked ("TheAlertMessage"));
+ App.WaitForElement (c => c.Marked ("TheCancelButton"));
+ App.Screenshot ("Display Alert Closed");
+ App.Tap (c => c.Marked ("TheCancelButton"));
+ App.WaitForNoElement (c => c.Marked ("TheAlertTitle"));
+ }
+
+ [Test]
+ public void TestWithCancelAndOkButton ()
+ {
+ App.Tap (c => c.Marked ("Alert Override2"));
+ App.Screenshot ("Display Alert");
+ App.WaitForElement (c => c.Marked ("TheAlertTitle"));
+ App.WaitForElement (c => c.Marked ("TheAlertMessage"));
+ App.WaitForElement (c => c.Marked ("TheAcceptButton"));
+ App.WaitForElement (c => c.Marked ("TheCancelButton"));
+ App.Tap (c => c.Marked ("TheCancelButton"));
+ App.Screenshot ("Display Alert Closed");
+ App.WaitForNoElement (c => c.Marked ("TheAlertTitle"));
+ }
+
+ [Test]
+ public void TestOkAndCancelResults ()
+ {
+ App.Tap (c => c.Marked ("Alert Override2"));
+ App.Screenshot ("Display Alert");
+ App.WaitForElement (c => c.Marked ("TheCancelButton"));
+ App.Tap (c => c.Marked ("TheCancelButton"));
+ App.Screenshot ("Display Alert Closed with cancel");
+ App.WaitForElement (c => c.Marked ("Result: False"));
+ App.Tap (c => c.Marked ("test2"));
+ App.Screenshot ("Display Alert");
+ App.WaitForElement (c => c.Marked ("TheAcceptButton"));
+ App.Tap (c => c.Marked ("TheAcceptButton"));
+ App.Screenshot ("Display Alert Closed with True");
+ App.WaitForElement (c => c.Marked ("Result: True"));
+ }
+
+// [Test]
+// public void TestRotation ()
+// {
+// App.SetOrientationLandscape ();
+//
+// //App.Tap (c => c.Marked ("Alert Override1"));
+// // 27-01-2015 14:30:02.125 -08:00 - 28524 - Tapping first element (2 total) matching Marked("Alert Override1") at coordinates [ 512, 113 ].
+//
+// App.TapCoordinates (665, 512);
+//
+// App.WaitForElement (c => c.Marked ("TheAlertTitle"));
+//
+// App.Screenshot ("Display Alert After Rotation");
+// App.WaitForElement (c => c.Marked ("TheAlertTitle"));
+// App.Tap (c => c.Marked("TheCancelButton"));
+// App.WaitForNoElement (c => c.Marked("TheCancelButton"));
+// App.SetOrientationPortrait ();
+//
+// }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/EditorUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/EditorUITests.cs
new file mode 100644
index 00000000..6701faad
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/EditorUITests.cs
@@ -0,0 +1,55 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Editor")]
+ internal class EditorUITests : _ViewUITests
+ {
+ public EditorUITests ()
+ {
+ PlatformViewType = Views.Editor;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.EditorGallery);
+ }
+
+ // View Tests
+ // TODO
+ public override void _Focus () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _GestureRecognizers () {}
+
+ // TODO
+ public override void _IsFocused () {}
+
+ // TODO
+ public override void _UnFocus () {}
+
+ // TODO
+ // Implement control specific ui tests
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/EntryUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/EntryUITests.cs
new file mode 100644
index 00000000..45b73374
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/EntryUITests.cs
@@ -0,0 +1,73 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Entry")]
+ internal class EntryUITests : _ViewUITests
+ {
+ public EntryUITests ()
+ {
+ PlatformViewType = Views.Entry;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.EntryGallery);
+ }
+
+ // TODO
+ public override void _Focus () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _GestureRecognizers () {}
+
+ // TODO
+ public override void _IsFocused () {}
+
+ // TODO
+ public override void _UnFocus () {}
+
+ // TODO
+ // Implement control specific ui tests
+ [Test]
+ [UiTest (typeof(Entry), "Completed")]
+ public void Completed ()
+ {
+ var remote = new EventViewContainerRemote (App, Test.Entry.Completed, PlatformViewType);
+ remote.GoTo ();
+
+ App.EnterText (q=> q.Raw (remote.ViewQuery), "Test");
+
+ if (App is AndroidApp) {
+ ((AndroidApp)App).PressUserAction (UserAction.Done);
+ } else {
+ App.PressEnter ();
+ }
+
+ var eventLabelText = remote.GetEventLabel ().Text;
+ Assert.AreEqual (eventLabelText, "Event: Completed (fired 1)");
+ }
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/FrameUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/FrameUITests.cs
new file mode 100644
index 00000000..f7a59ed5
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/FrameUITests.cs
@@ -0,0 +1,57 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Frame")]
+ internal class FrameUITests : _ViewUITests
+ {
+ public FrameUITests ()
+ {
+ PlatformViewType = Views.Frame;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.FrameGallery);
+ }
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _Focus () {}
+
+ // TODO
+ public override void _GestureRecognizers () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsFocused () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _UnFocus () {}
+
+ // TODO
+ // Implement control specific ui tests
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsEnabled () {}
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/ImageUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/ImageUITests.cs
new file mode 100644
index 00000000..5c19d1cb
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/ImageUITests.cs
@@ -0,0 +1,63 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Image")]
+ internal class ImageUITests : _ViewUITests
+ {
+ public ImageUITests ()
+ {
+ PlatformViewType = Views.Image;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.ImageGallery);
+
+ // let remote images load
+ Thread.Sleep (2000);
+ }
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _Focus () {}
+
+ // TODO
+ public override void _GestureRecognizers () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsEnabled () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsFocused () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _UnFocus () {}
+
+ // TODO
+ // Implement control specific ui tests
+
+ // TODO
+ // Tests for remote images
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/LabelUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/LabelUITests.cs
new file mode 100644
index 00000000..423774fd
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/LabelUITests.cs
@@ -0,0 +1,57 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Label")]
+ internal class LabelUITests : _ViewUITests
+ {
+ public LabelUITests ()
+ {
+ PlatformViewType = Views.Label;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.LabelGallery);
+ }
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _Focus () {}
+
+ // TODO
+ public override void _GestureRecognizers () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsEnabled () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsFocused () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _UnFocus () {}
+
+ // TODO
+ // Implement control specific ui tests
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-AbsoluteLayoutGalleryTest.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-AbsoluteLayoutGalleryTest.cs
new file mode 100644
index 00000000..c23a0d27
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-AbsoluteLayoutGalleryTest.cs
@@ -0,0 +1,229 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+using System;
+using System.Threading;
+using Xamarin.UITest.Queries;
+using System.Diagnostics;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("AbsoluteLayout")]
+ internal class AbsoluteLayoutGalleryTests : BaseTestFixture
+ {
+ // TODO: Port to new conventions
+
+ public AbsoluteLayoutGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.AbsoluteLayoutGalleryLegacy);
+ }
+
+ [Test]
+ public void AbsoluteLayoutGalleryMoveBox ()
+ {
+ App.Screenshot ("At Gallery");
+
+ // App.WaitForElement (q => q.Raw (Views.BoxView), "Timeout : Box Renderers");
+ // Assert.AreEqual (1, App.Query (q => q.Raw (Views.BoxView)).Length);
+
+ // App.WaitForElement (q => q.Raw (Views.Label), "Timeout : Labels");
+ // Assert.AreEqual (4, App.Query(q => q.Raw (Views.Label)).Length);
+
+ // App.WaitForElement (q => q.Raw (Views.Slider), "Timeout : Sliders");
+ // Assert.AreEqual (4, App.Query(q => q.Raw (Views.Slider)).Length);
+ // App.Screenshot ("All elements exist");
+
+ // App.WaitForElement (q => q.Raw (Views.Slider));
+ // // Move green box left
+ // var sliders = (App.Query (q => q.Raw (Views.Slider)));
+ // var sliderCenter = (sliders[0]).Rect.CenterX;
+ // var sliderLeft = (sliders[0]).Rect.X;
+ // var sliderRight = sliderLeft + (sliders[0]).Rect.Width;
+
+ // var xSlider = (sliders[0]).Rect.CenterY;
+ // var ySlider = (sliders[1]).Rect.CenterY;
+
+ //var absoluteBounds = App.Query (PlatformQueries.AbsoluteGalleryBackground)[0].Rect;
+
+ //// Move box left
+ //App.DragFromTo (sliderCenter, xSlider, sliderLeft, xSlider, Speed.Slow);
+ //Assert.AreEqual (absoluteBounds.X, (App.Query (PlatformQueries.BoxRendererQuery))[0].Rect.X, 2.0);
+ //App.Screenshot ("Box moved to left bounds");
+
+ //// Move box right
+ //App.DragFromTo (sliderLeft, xSlider, sliderRight, xSlider, Speed.Slow);
+ //Assert.AreEqual (absoluteBounds.X + absoluteBounds.Width, (App.Query (PlatformQueries.BoxRendererQuery))[0].Rect.X + (App.Query (PlatformQueries.BoxRendererQuery))[0].Rect.Width, 2.0);
+ //App.Screenshot ("Box moved to right bounds");
+
+ ////Move box up
+ //var boxContainer = App.Query (PlatformQueries.AbsoluteGalleryBackground)[0];
+ //var boxContainerTop = boxContainer.Rect.Y;
+ //var boxContainerBottom = boxContainer.Rect.Y + boxContainer.Rect.Height;
+
+ //App.DragFromTo (sliderCenter, ySlider, sliderLeft, ySlider, Speed.Slow);
+ //Assert.AreEqual (boxContainerTop, (App.Query (PlatformQueries.BoxRendererQuery))[0].Rect.Y);
+ //App.Screenshot ("Box moved to top bounds");
+
+ //// Move box down
+ //App.DragFromTo (sliderLeft, ySlider, sliderRight, ySlider, Speed.Slow);
+ //Assert.AreEqual (boxContainerBottom, (App.Query (PlatformQueries.BoxRendererQuery))[0].Rect.Y + (App.Query (PlatformQueries.BoxRendererQuery))[0].Rect.Height);
+ //App.Screenshot ("Box moved to bottom bounds");
+ }
+
+ //[Test]
+ //[Description ("MaxWidth")]
+ //public void AbsoluteLayoutGalleryResizeToMaximumWidth ()
+ //{
+ //App.WaitForElement (PlatformQueries.Sliders, "Timeout : Sliders");
+
+ //AppRect widthSlider = (App.Query (PlatformQueries.Sliders))[2].Rect;
+ //float sliderCenter = widthSlider.CenterX;
+ //float sliderY = widthSlider.CenterY;
+ //float sliderRight = widthSlider.X + widthSlider.Width;
+
+ //App.DragFromTo (sliderCenter, sliderY, sliderRight, sliderY, Speed.Slow);
+
+ //AppRect absoluteBounds = App.Query (PlatformQueries.AbsoluteGalleryBackground)[0].Rect;
+ //AppRect boxBounds = App.Query (PlatformQueries.BoxRendererQuery)[0].Rect;
+
+ //Assert.AreEqual (absoluteBounds.Width, boxBounds.Width, 2.0);
+ //App.Screenshot ("Box at maximum width");
+ //}
+
+ //[Test]
+ //[Description ("MaxHeight")]
+ //public void AbsoluteLayoutGalleryResizeToMaximumHeight ()
+ //{
+ //App.WaitForElement (PlatformQueries.Sliders, "Timeout : Sliders");
+
+ //AppRect widthSlider = (App.Query (PlatformQueries.Sliders))[3].Rect;
+ //float sliderCenter = widthSlider.CenterX;
+ //float sliderY = widthSlider.CenterY;
+ //float sliderRight = widthSlider.X + widthSlider.Width;
+
+ //App.DragFromTo (sliderCenter, sliderY, sliderRight, sliderY, Speed.Slow);
+
+ //AppRect absoluteBounds = App.Query (PlatformQueries.AbsoluteGalleryBackground)[0].Rect;
+ //AppRect boxBounds = App.Query (PlatformQueries.BoxRendererQuery)[0].Rect;
+
+ //Assert.AreEqual (absoluteBounds.Height, boxBounds.Height, 2.0);
+ //App.Screenshot ("Box at maximum height");
+ //}
+
+ //[Test]
+ //[Description ("MinWidth")]
+ //public void AbsoluteLayoutGalleryResizeToMinimumWidth ()
+ //{
+ //App.WaitForElement (PlatformQueries.Sliders, "Timeout : Sliders");
+
+ //AppRect widthSlider = (App.Query (PlatformQueries.Sliders))[2].Rect;
+ //float sliderCenter = widthSlider.CenterX;
+ //float sliderY = widthSlider.CenterY;
+ //float sliderLeft = widthSlider.X - 20;
+
+ //App.DragFromTo (sliderCenter, sliderY, sliderLeft, sliderY, Speed.Slow);
+
+ //bool isZeroed = false;
+ //if (App.Query (PlatformQueries.BoxRendererQuery).Length == 0) {
+ // // Android removes 0 width BoxView
+ // isZeroed = true;
+ //} else {
+ // if (App.Query (PlatformQueries.BoxRendererQuery)[0].Rect.Width <= 4.0)
+ // isZeroed = true;
+ //}
+
+ //Assert.IsTrue (isZeroed, "Box is minimum width");
+ //App.Screenshot ("Box at minimum width");
+ }
+
+ //[Test]
+ //[Description ("MinHeight")]
+ //public void AbsoluteLayoutGalleryResizeToMinimumHeight ()
+ //{
+ //App.WaitForElement (PlatformQueries.Sliders, "Timeout : Sliders");
+
+ //AppRect widthSlider = (App.Query (PlatformQueries.Sliders))[3].Rect;
+ //float sliderCenter = widthSlider.CenterX;
+ //float sliderY = widthSlider.CenterY;
+ //float sliderLeft = widthSlider.X - 20;
+
+ //App.DragFromTo (sliderCenter, sliderY, sliderLeft, sliderY, Speed.Slow);
+
+ //bool isZeroed = false;
+ //if (App.Query (PlatformQueries.BoxRendererQuery).Length == 0) {
+ // // Android removes 0 height BoxView
+ // isZeroed = true;
+ //} else {
+ // if (App.Query (PlatformQueries.BoxRendererQuery)[0].Rect.Height <= 4.0)
+ // isZeroed = true;
+ //}
+
+ //Assert.IsTrue (isZeroed, "Box is minimum height");
+ //App.Screenshot ("Box at minimum height");
+ //}
+
+/*******************************************************/
+/**************** Landscape tests **********************/
+/*******************************************************/
+
+ //[Test]
+ //[Description ("Move box around with sliders - landscape")]
+ //public void AbsoluteLayoutGalleryMoveBoxLandscape ()
+ //{
+ // App.SetOrientationLandscape ();
+ // App.Screenshot ("Rotated to Landscape");
+ // AbsoluteLayoutGalleryMoveBox ();
+ // App.SetOrientationPortrait ();
+ // App.Screenshot ("Rotated to Portrait");
+ //}
+
+ //[Test]
+ //[Description ("Resize to max width with sliders - landscape")]
+ //public void AbsoluteLayoutGalleryResizeToMaximumWidthLandscape ()
+ //{
+ // App.SetOrientationLandscape ();
+ // App.Screenshot ("Rotated to Landscape");
+ // AbsoluteLayoutGalleryResizeToMaximumWidth ();
+ // App.SetOrientationPortrait ();
+ // App.Screenshot ("Rotated to Portrait");
+ //}
+
+ //[Test]
+ //[Description ("Resize to max height with sliders - landscape")]
+ //public void AbsoluteLayoutGalleryResizeToMaximumHeightLandscape ()
+ //{
+ // App.SetOrientationLandscape ();
+ // App.Screenshot ("Rotated to Landscape");
+ // AbsoluteLayoutGalleryResizeToMaximumHeight ();
+ // App.SetOrientationPortrait ();
+ // App.Screenshot ("Rotated to Portrait");
+ //}
+
+ //[Test]
+ //[Description ("Resize to min height with sliders - landscape")]
+ //public void AbsoluteLayoutGalleryResizeToMinimumWidthLandscape ()
+ //{
+ // App.SetOrientationLandscape ();
+ // App.Screenshot ("Rotated to Landscape");
+ // AbsoluteLayoutGalleryResizeToMinimumWidth ();
+ // App.SetOrientationPortrait ();
+ // App.Screenshot ("Rotated to Portrait");
+ //}
+
+ //[Test]
+ //[Description ("Resize to min height with sliders - landscape")]
+ //public void AbsoluteLayoutGalleryResizeToMinimumHeightLandscape ()
+ //{
+ // App.SetOrientationLandscape ();
+ // App.Screenshot ("Rotated to Landscape");
+ // AbsoluteLayoutGalleryResizeToMinimumHeight ();
+ // App.SetOrientationPortrait ();
+ // App.Screenshot ("Rotated to Portrait");
+ //}
+ //}
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-BoundViewUITest.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-BoundViewUITest.cs
new file mode 100644
index 00000000..625a27ca
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-BoundViewUITest.cs
@@ -0,0 +1,96 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+using System;
+using System.Threading;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Templated")]
+ internal class BoundViewGalleryTests : BaseTestFixture
+ {
+ // TODO: Port to new conventions
+
+ public BoundViewGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.BoundPageGalleryLegacy);
+ }
+
+ //void AllElementsPresent ()
+ //{
+ // App.WaitForElement (q => q.Button ("Click Me!"));
+ // App.Screenshot ("All elements present");
+ //}
+
+ [Test]
+ [Description ("Test bound view navigation")]
+ public void BoundViewGalleryNavigateToAndBack ()
+ {
+ App.Screenshot ("At Gallery");
+
+// AllElementsPresent ();
+
+// App.Tap (q => q.Button ("Click Me!"));
+// App.WaitForElement (q => q.Marked ("Second Page"), "Timeout : Second Page");
+// App.Screenshot ("Navigation to next page successful");
+
+// App.Tap (PlatformQueries.Back);
+// App.WaitForElement (q => q.Button ("Click Me!"), "Timeout : Click Me!");
+// App.Screenshot ("Navigation back successful");
+ }
+
+// [Test]
+// [Description ("Test button click")]
+// public void BoundViewGalleryClickButton ()
+// {
+// App.Tap (q => q.Button ("Click Me!"));
+// App.WaitForElement (q => q.Marked ("Second Page"), "Timeout : Second Page");
+// }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+
+// [Test]
+// [Description ("Verify all elements are preset - landscape")]
+// public void BoundViewGalleryAllElementsPresentLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// Thread.Sleep (1000);
+// App.Screenshot ("Rotated to Landscape");
+// AllElementsPresent ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Test bound view navigation- landscape")]
+// public void BoundViewGalleryNavigateToAndBackLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// Thread.Sleep (1000);
+// App.Screenshot ("Rotated to Landscape");
+// BoundViewGalleryNavigateToAndBack ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Test button click - landscape")]
+// public void BoundViewGalleryClickButtonLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// Thread.Sleep (1000);
+// App.Screenshot ("Rotated to Landscape");
+// BoundViewGalleryClickButton ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ButtonUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ButtonUITests.cs
new file mode 100644
index 00000000..71443ce2
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ButtonUITests.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ // Run these to test in CI before full suite
+ [TestFixture]
+ [Category ("Button")]
+ internal class ButtonGalleryTests : BaseTestFixture
+ {
+ // TODO: Rotate Button - test rotation
+ // TODO: Port to new conventions
+
+ public ButtonGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.ButtonGalleryLegacy);
+ }
+
+ [Test]
+ [Description ("Disabled Button")]
+ public void ButtonGalleryOnOffDisbledButton ()
+ {
+ App.Screenshot ("At Gallery");
+
+ // App.ScrollDownForElement (q => q.Marked ("Cannot Tap"), 3);
+ // App.Tap (q => q.Button ("Disabled Button"));
+ // Assert.AreEqual (1, App.Query (q => q.Button ("Disabled Button")).Length);
+ // App.Screenshot ("Tried to tap disabled button");
+ // App.Tap (PlatformQueries.Switch);
+ // App.Screenshot ("Tapped switch");
+ // App.Tap (q => q.Button ("Disabled Button"));
+ // App.WaitForElement (q => q.Marked ("TAPPED!"));
+ // App.Screenshot ("Disabled button should not be enabled and change labels text");
+ }
+
+ //[Test]
+ //[UiTest (Test.Device.StartTimer)]
+ //[Description ("Clicking the 'Timer Button'")]
+ //public void ButtonGalleryTimerButton ()
+ //{
+ // App.ScrollDownForElement (q => q.Marked ("Timer"), 10);
+ // App.Screenshot ("Press 'Timer' Button");
+
+ // App.Tap (q => q.Button ("Timer"));
+
+ // App.WaitForElement (q => q.Marked ("Timer Elapsed 3"), "Timeout : Timer Elapsed 3");
+ // App.Screenshot ("Timer button elapsed 3");
+ //}
+
+ //[Test]
+ //[UiTest (Test.Page.DisplayAlert)]
+ //public void ButtonGalleryAlertAccepted ()
+ //{
+ // App.ScrollDownForElement (q => q.Marked ("Alert"), 10);
+
+ // App.Screenshot ("Press 'Alert' Button");
+
+ // App.Tap (q => q.Marked ("Alert"));
+ // App.WaitForElement (q => q.Marked ("Accept"), "Timeout : Accept");
+
+ // App.Screenshot ("Press 'Accept' or 'Cancel'");
+
+ // App.Tap (q => q.Marked ("Accept"));
+ // App.WaitForElement (q => q.Button ("Accepted"), "Timeout : Accepted");
+
+ // App.Screenshot ("See 'Accepted' or 'Cancelled'");
+ //}
+
+
+ //[Test]
+ //[UiTest (Test.Page.DisplayAlert)]
+ //public void ButtonGalleryAlertCancelled ()
+ //{
+ // App.ScrollDownForElement (q => q.Marked ("Alert"), 10);
+
+ // App.Screenshot ("Press 'Alert' Button");
+
+ // App.Tap (q => q.Marked ("Alert"));
+ // App.WaitForElement (q => q.Marked ("Cancel"), "Timeout : Cancel");
+
+ // App.Screenshot ("Press 'Accept' or 'Cancel'");
+
+ // App.Tap (q => q.Marked ("Cancel"));
+ // App.WaitForElement (q => q.Button ("Cancelled"), "Timeout : Cancelled");
+
+ // App.Screenshot ("See 'Accepted' or 'Cancelled'");
+ //}
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-CarouselPageUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-CarouselPageUITests.cs
new file mode 100644
index 00000000..14a6ed4b
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-CarouselPageUITests.cs
@@ -0,0 +1,63 @@
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("CarouselPage")]
+ internal class CarouselPageGalleryTests : BaseTestFixture
+ {
+ // TODO: Port to new conventions
+
+ public CarouselPageGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.CarouselPageGalleryLegacy);
+ }
+
+ [Test]
+ [Description ("Swiping between screens")]
+ [UiTest (typeof(CarouselPage))]
+ public void CarouselPageGallerySwipeScreens ()
+ {
+ App.Screenshot ("At Gallery");
+
+ // var rootViewWidth = App.Query (q => q.Raw ("*"))[0].Rect.Width;
+ // var rootViewHeight = App.Query (q => q.Raw ("*"))[0].Rect.Height;
+
+ // // Verify the elements can be touched
+ // App.Tap (q => q.Button ("Click me one"));
+ // App.WaitForNoElement (q => q.Marked ("No click one"), "Timeout : No click one");
+ // App.WaitForElement (q => q.Marked ("Clicked one"), "Timeout : Clicked one");
+
+ // App.Pan (new Drag (ScreenBounds, rootViewWidth - 20, rootViewHeight / 2, 20, rootViewHeight / 2, Drag.Direction.RightToLeft));
+
+ // App.WaitForElement (q => q.Marked ("No click two"), "Timeout : No click two");
+ // App.WaitForElement (q => q.Button ("Click me two"), "Timeout : Click me two");
+ // App.Screenshot ("On page two");
+
+ // // Verify the elements can be touched
+ // App.Tap (q => q.Button ("Click me two"));
+ // App.WaitForNoElement (q => q.Marked ("No click two"), "Timeout : No click two");
+ // App.WaitForElement (q => q.Marked ("Clicked two"), "Timeout : Clicked two");
+
+ // App.Pan (new Drag (ScreenBounds, rootViewWidth - 20, rootViewHeight / 2, 20, rootViewHeight / 2, Drag.Direction.RightToLeft));
+
+ // App.WaitForElement (q => q.Marked ("No click three"), "Timeout : No click three");
+ // App.WaitForElement (q => q.Button ("Click me three"), "Timeout : Click me three");
+ // App.Screenshot ("On page three");
+
+ // // Verify the elements can be touched
+ // App.Tap (q => q.Button ("Click me three"));
+ // App.WaitForNoElement (q => q.Marked ("No click three"), "Timeout : No click three");
+ // App.WaitForElement (q => q.Marked ("Clicked three"), "Clicked three");
+ // App.Screenshot ("All screens interacted with");
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-CellsUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-CellsUITests.cs
new file mode 100644
index 00000000..e6efd5f9
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-CellsUITests.cs
@@ -0,0 +1,318 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Cells")]
+ internal class CellsGalleryTests : BaseTestFixture
+ {
+ // TODO find a way to test individula elements of cells
+ // TODO port to new framework
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.CellsGalleryLegacy);
+ }
+
+ [Test]
+ [Description ("ListView with TextCells, all are present")]
+ [UiTest (typeof(ListView))]
+ [UiTest (typeof(TextCell))]
+ public void CellsGalleryTextCellList ()
+ {
+ App.ScrollForElement ("* marked:'TextCell List'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ App.Tap (q => q.Marked ("TextCell List"));
+ App.WaitForElement (q => q.Marked ("Text 0"), "Timeout : Text 0");
+
+ App.Screenshot ("At TextCell List Gallery");
+
+ App.ScrollForElement ("* marked:'Detail 99'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ App.WaitForElement (q => q.Marked ("Detail 99"), "Timeout : Detail 99");
+
+ App.Screenshot ("All TextCells are present");
+ }
+
+ [Test]
+ [Description ("TableView with TextCells, all are present")]
+ [UiTest (typeof(TableView))]
+ [UiTest (typeof(TextCell))]
+ public void CellsGalleryTextCellTable ()
+ {
+ App.ScrollForElement ("* marked:'TextCell Table'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ App.Tap (q => q.Marked ("TextCell Table"));
+ App.WaitForElement (q => q.Marked ("Text 1"), "Timeout : Text 1");
+
+ App.Screenshot ("At TextCell Table Gallery");
+
+ App.ScrollForElement ("* marked:'Detail 12'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ App.WaitForElement (q => q.Marked ("Detail 12"), "Timeout : Detail 12");
+
+ App.Screenshot ("All TextCells are present");
+ }
+
+ [Test]
+ [Description ("ListView with ImageCells, all are present")]
+ [UiTest (typeof(ListView))]
+ [UiTest (typeof(ImageCell))]
+ public void CellsGalleryImageCellList ()
+ {
+ Thread.Sleep (2000);
+
+ App.ScrollForElement ("* marked:'ImageCell List'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ Thread.Sleep (2000);
+
+ App.Tap (q => q.Marked ("ImageCell List"));
+ App.WaitForElement (q => q.Marked ("Text 0"), "Timeout : Text 0");
+
+ App.Screenshot ("At ImageCell List Gallery");
+
+ var scollBounds = App.Query (q => q.Marked ("ImageCellListView")).First ().Rect;
+ App.ScrollForElement ("* marked:'Detail 99'", new Drag (scollBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ App.WaitForElement (q => q.Marked ("Detail 99"), "Timeout : Detail 99");
+
+ App.Screenshot ("All ImageCells are present");
+
+ var numberOfImages = App.Query (q => q.Raw (PlatformViews.Image)).Length;
+ // Check that there are images present. In Android,
+ // have to make sure that there are more than 2 for navigation.
+ Assert.IsTrue (numberOfImages > 2);
+
+ App.Screenshot ("Images are present");
+ }
+
+ [Test]
+ [Description ("ListView with ImageCells, file access problems")]
+ [UiTest (typeof(ListView))]
+ [UiTest (typeof(ImageCell))]
+ public void CellsGalleryImageUrlCellList ()
+ {
+
+ App.ScrollForElement ("* marked:'ImageCell Url List'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ App.Tap (q => q.Marked ("ImageCell Url List"));
+
+ var scollBounds = App.Query (q => q.Marked ("ImageUrlCellListView")).First ().Rect;
+ App.ScrollForElement ("* marked:'Detail 200'", new Drag (scollBounds, Drag.Direction.BottomToTop, Drag.DragLength.Long), 40);
+
+ App.WaitForElement (q => q.Marked ("Detail 200"), "Timeout : Detail 200");
+
+ App.Screenshot ("All ImageCells are present");
+
+ var numberOfImages = App.Query (q => q.Raw (PlatformViews.Image)).Length;
+ // Check that there are images present. In Android,
+ // have to make sure that there are more than 2 for navigation.
+ Assert.IsTrue (numberOfImages > 2);
+
+ App.Screenshot ("Images are present");
+ }
+
+
+
+
+ [Test]
+ [Description ("TableView with ImageCells, all are present")]
+ [UiTest (typeof(TableView))]
+ [UiTest (typeof(ImageCell))]
+ public void CellsGalleryImageCellTable ()
+ {
+ App.ScrollForElement ("* marked:'ImageCell Table'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ App.Tap (q => q.Marked ("ImageCell Table"));
+ App.WaitForElement (q => q.Marked ("Text 1"), "Timeout : Text 1");
+
+ App.Screenshot ("At ImageCell Table Gallery");
+
+ App.ScrollForElement ("* marked:'Detail 12'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ App.WaitForElement (q => q.Marked ("Detail 12"), "Timeout : Detail 12");
+
+ App.Screenshot ("All ImageCells are present");
+
+ var numberOfImages = App.Query (q => q.Raw (PlatformViews.Image)).Length;
+ // Check that there are images present. In Android,
+ // have to make sure that there are more than 2 for navigation.
+ Assert.IsTrue (numberOfImages > 2);
+
+ App.Screenshot ("Images are present");
+ }
+
+ [Test]
+ [Description ("ListView with SwitchCells, all are present")]
+ [UiTest (typeof(ListView))]
+ [UiTest (typeof(SwitchCell))]
+ public void CellsGallerySwitchCellList ()
+ {
+ App.ScrollForElement ("* marked:'SwitchCell List'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ App.Tap (q => q.Marked ("SwitchCell List"));
+ App.WaitForElement (q => q.Marked ("Label 0"), "Timeout : Label 0");
+
+ App.Screenshot ("At SwitchCell List Gallery");
+
+ App.ScrollForElement ("* marked:'Label 99'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ var numberOfSwitches = App.Query (q => q.Raw (PlatformViews.Switch)).Length;
+ Assert.IsTrue (numberOfSwitches > 2);
+
+ App.Screenshot ("Switches are present");
+ }
+
+ [Test]
+ [Description ("TableView with SwitchCells, all are present")]
+ [UiTest (typeof(TableView))]
+ [UiTest (typeof(SwitchCell))]
+ public void CellsGallerySwitchCellTable ()
+ {
+ App.ScrollForElement ("* marked:'SwitchCell Table'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ App.Tap (q => q.Marked ("SwitchCell Table"));
+ App.WaitForElement (q => q.Marked ("text 1"), "Timeout : text 1");
+
+ App.Screenshot ("At SwitchCell Table Gallery");
+
+ App.ScrollForElement ("* marked:'text 32'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ var numberOfSwitches = App.Query (q => q.Raw (PlatformViews.Switch)).Length;
+ Assert.IsTrue (numberOfSwitches > 2);
+
+ App.Screenshot ("Switches are present");
+ }
+
+ [Test]
+ [Description ("ListView with EntryCells, all are present")]
+ [UiTest (typeof(ListView))]
+ [UiTest (typeof(EntryCell))]
+ public void CellsGalleryEntryCellList ()
+ {
+ App.ScrollForElement ("* marked:'EntryCell List'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ App.Tap (q => q.Marked ("EntryCell List"));
+ App.WaitForElement (q => q.Marked ("Label 0"), "Timeout : Label 0");
+
+ App.Screenshot ("At EntryCell List Gallery");
+
+ App.ScrollForElement ("* marked:'Label 99'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ App.Screenshot ("All EntryCells are present");
+ }
+
+ [Description ("Entered text stays after scrolled out of view")]
+ [Issue (IssueTracker.Github, 1024, "EntryCell with text set clears after scrolling off screen", PlatformAffected.Android)]
+ [UiTest (typeof(EntryCell))]
+ public void CellsGalleryIssue1024 ()
+ {
+ // TODO fix
+// App.ScrollForElement ("* marked:'EntryCell List'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+//
+// App.Tap (q => q.Marked ("EntryCell List"));
+// App.WaitForElement (q => q.Marked ("Label 0"), "Timeout : Label 0");
+// App.Screenshot ("At EntryCell List Gallery");
+//
+// App.Tap (Queries.EntryCellWithPlaceholder ("Placeholder 1"));
+// App.EnterText (Queries.EntryCellWithPlaceholder ("Placeholder 1"), "I am going to be scrolled off screen");
+//
+// App.Screenshot ("Dismiss keyboard");
+//
+// App.ScrollForElement ("* marked:'Label 40'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+// App.Screenshot ("Scroll down");
+//
+// App.ScrollForElement ("* marked:'Label 0'", new Drag (ScreenBounds, Drag.Direction.TopToBottom, Drag.DragLength.Medium));
+//
+// App.WaitForElement (Queries.EntryCellWithText ("I am going to be scrolled off screen"), "Timeout : Scrolled Entry with Text");
+// App.Screenshot ("Scroll back up to cell");
+ }
+
+ [Test]
+ [Description ("TableView with EntryCells, all are present")]
+ [UiTest (typeof(TableView))]
+ [UiTest (typeof(EntryCell))]
+ public void CellsGalleryEntryCellTable ()
+ {
+ App.ScrollForElement ("* marked:'EntryCell Table'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ App.Tap (q => q.Marked ("EntryCell Table"));
+ App.WaitForElement (q => q.Marked ("Text 2"), "Timeout : Text 2");
+
+ App.Screenshot ("At EntryCell Table Gallery");
+
+ App.ScrollForElement ("* marked:'Text 32'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ App.Screenshot ("All EntryCells are present");
+ }
+
+ [Test]
+ [Category ("EntryCell")]
+ [Description ("EntryCell fires .Completed event")]
+ [UiTest (typeof(EntryCell), "Completed")]
+ public void CellsGalleryEntryCellCompleted ()
+ {
+ App.ScrollForElement ("* marked:'EntryCell Table'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ App.Tap (q => q.Marked ("EntryCell Table"));
+ App.WaitForElement (q => q.Marked ("Text 2"), "Timeout : Text 2");
+
+ App.Screenshot ("At EntryCell Table Gallery");
+ App.ScrollForElement ("* marked:'Enter text'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ App.Screenshot ("Before clicking Entry");
+
+ App.Tap (PlatformQueries.EntryCellWithPlaceholder ("I am a placeholder"));
+ App.EnterText (PlatformQueries.EntryCellWithPlaceholder ("I am a placeholder"), "Hi");
+ App.Screenshot ("Entered Text");
+ if (App is AndroidApp) {
+ ((AndroidApp)App).PressUserAction (UserAction.Done);
+ } else {
+ App.PressEnter ();
+ }
+ App.WaitForElement (q => q.Marked ("Entered: 1"));
+ App.Screenshot ("Completed should have changed label's text");
+ }
+
+ //[Test]
+ [Description ("Issue 1033 - page does not respect orientation changes")]
+ public void CellsGalleryIssue1033 ()
+ {
+// App.SetOrientationLandscape ();
+// App.Tap (q => q.Marked ("TextCell List"));
+// App.WaitForElement (q => q.Marked ("Text 2"), "Timeout : Text 2");
+// float listViewHeightLandscape = App.Query (q => q.Raw (Views.ListView))[0].Rect.Height;
+// App.Screenshot ("Landscape list");
+//
+//
+// App.NavigateBack ();
+// App.Screenshot ("Navigate back");
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Set orientation to portrait");
+//
+// App.Tap (q => q.Marked ("TextCell List"));
+// App.WaitForElement (q => q.Marked ("Text 2"), "Timeout : Text 2");
+// float listViewHeightPortrait = App.Query (q => q.Raw (Views.ListView))[0].Rect.Height;
+// App.Screenshot ("Portrait list");
+//
+// // Should be be the same size if the layout is resized
+// Assert.AreNotEqual (listViewHeightLandscape, listViewHeightPortrait);
+ }
+
+ protected override void TestTearDown()
+ {
+ App.NavigateBack ();
+ base.TestTearDown();
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ClipToBoundsUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ClipToBoundsUITests.cs
new file mode 100644
index 00000000..9dffeaaf
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ClipToBoundsUITests.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Runtime;
+using NUnit.Framework;
+using Xamarin.UITest;
+using Xamarin.UITest.Shared;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("AbsoluteLayout")]
+ internal class ClipToBoundsGalleryTests : BaseTestFixture
+ {
+ // TODO detect size before and after clip
+ // TODO: Port to new conventions
+
+ public ClipToBoundsGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.ClipToBoundsGalleryLegacy);
+ }
+ [Test]
+ [Description ("Check all elements exist")]
+ public void ClipToBoundsGalleryAllElementsExist ()
+ {
+// App.WaitForElement (q => q.Button ("Clip"), "Timeout : Clip");
+// var boxes = App.Query (PlatformQueries.BoxRendererQuery);
+// Assert.AreEqual (2, boxes.Length);
+// App.Screenshot ("2 boxes exist");
+
+
+ }
+
+// [Test]
+// [Description ("Clip boxes")]
+// public void ClipToBoundsGalleryClipElements ()
+// {
+// App.Tap (q => q.Button ("Clip"));
+// App.Screenshot ("Clip elements");
+// }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+
+// [Test]
+// [Description ("Check all elements exist - landscape")]
+// public void ClipToBoundsGalleryAllElementsExistLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// ClipToBoundsGalleryAllElementsExist ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Clip boxes - landscape")]
+// public void ClipToBoundsGalleryClipElementsLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// ClipToBoundsGalleryClipElements ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+ // }
+
+ }
+}
+
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-EditorUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-EditorUITests.cs
new file mode 100644
index 00000000..df34deec
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-EditorUITests.cs
@@ -0,0 +1,269 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NUnit.Framework;
+using System.Threading;
+
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Editor")]
+ internal class EditorGalleryTests : BaseTestFixture
+ {
+ // TODO: Port to new conventions
+
+ public EditorGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.EditorGalleryLegacy);
+ }
+
+ [Test]
+ [Category ("ManualReview")]
+ [Description ("Try Default keyboard")]
+ [UiTest (typeof (Editor), "Keyboard")]
+ [UiTest (typeof (Keyboard), "Default")]
+ public void EditorGalleryDefaultKeyboardGallery ()
+ {
+// App.Tap (q => q.Marked ("Default Keyboard"));
+// App.WaitForElement (PlatformQueries.Editors, "Timeout : Editors");
+// App.Screenshot ("At Default Keyboard Gallery");
+
+// App.Tap (PlatformQueries.Editors);
+// // App.KeyboardIsPresent ();
+// App.Screenshot ("Keyboard showing");
+
+// var text = "This is some text that I am entering";
+// App.EnterText (PlatformQueries.Editors, text);
+// App.WaitForElement (PlatformQueries.EditorsWithText (text), "Timeout : Editor with Text " + text);
+// App.Screenshot ("Text Entered");
+
+// App.PressEnter ();
+// // App.KeyboardIsDismissed ();
+// App.Screenshot ("Pressed enter");
+ }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Editor.Completed Fires")]
+// [UiTest (Test.Views.Editor)]
+// [UiTest (Test.Editor.Completed)]
+// public void EditorGalleryDefaultKeyboardGalleryCompletedFires ()
+// {
+// App.Tap (q => q.Marked ("Default Keyboard"));
+// App.WaitForElement (PlatformQueries.Editors, "Timeout : Editors");
+// App.Screenshot ("At Default Keyboard Gallery");
+
+// App.Tap (PlatformQueries.Editors);
+// // App.KeyboardIsPresent ();
+// App.Screenshot ("Keyboard showing");
+// App.EnterText (PlatformQueries.Editors, "First Line");
+// App.PressEnter ();
+
+// App.Screenshot ("Pressed enter");
+// App.EnterText (PlatformQueries.Editors, "Second Line");
+// App.Screenshot ("Entered second line");
+// App.Tap (PlatformQueries.LabelWithText("Nothing entered"));
+// App.Screenshot ("Keyboard dismissed");
+//// App.Tap (q => q.Marked ("Done"));
+
+
+// App.WaitForNoElement (q => q.Marked ("Nothing entered"));
+// App.Screenshot ("Test complete");
+//// App.WaitForElement (q => q.Marked ("Entered : First Line Second Line"));
+// }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Try Chat keyboard")]
+// [UiTest (Test.Views.Editor)]
+// [UiTest (Test.InputView.Keyboard)]
+// [UiTest (Test.Keyboard.Chat)]
+// public void EditorGalleryChatKeyboardGallery ()
+// {
+// App.Tap (q => q.Marked ("Chat Keyboard"));
+// App.WaitForElement (PlatformQueries.Editors, "Timeout : Editors");
+// App.Screenshot ("At Chat Keyboard Gallery");
+
+// App.Tap (PlatformQueries.Editors);
+// // App.KeyboardIsPresent ();
+// App.Screenshot ("Keyboard showing");
+
+// var text = "This is some text that I am entering";
+// App.EnterText (PlatformQueries.Editors, text);
+// App.WaitForElement (PlatformQueries.EditorsWithText (text), "Timeout : Editor with Text " + text);
+// App.Screenshot ("Text Entered");
+
+// App.PressEnter ();
+// // App.KeyboardIsDismissed ();
+// App.Screenshot ("Pressed enter");
+// }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Try Text keyboard")]
+// [UiTest (Test.Views.Editor)]
+// [UiTest (Test.InputView.Keyboard)]
+// [UiTest (Test.Keyboard.Text)]
+// public void EditorGalleryTextKeyboardGallery ()
+// {
+// App.Tap (q => q.Marked ("Text Keyboard"));
+// App.WaitForElement (PlatformQueries.Editors, "Timeout : Editors");
+// App.Screenshot ("At Text Keyboard Gallery");
+
+// App.Tap (PlatformQueries.Editors);
+// // App.KeyboardIsPresent ();
+// App.Screenshot ("Keyboard showing");
+
+// var text = "This is some text that I am entering";
+// App.EnterText (PlatformQueries.Editors, text);
+// App.WaitForElement (PlatformQueries.EditorsWithText (text), "Timeout : Editor with Text " + text);
+// App.Screenshot ("Text Entered");
+
+// App.PressEnter ();
+// // App.KeyboardIsDismissed ();
+// App.Screenshot ("Pressed enter");
+// }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Try Url keyboard")]
+// [UiTest (Test.Views.Editor)]
+// [UiTest (Test.InputView.Keyboard)]
+// [UiTest (Test.Keyboard.Url)]
+// public void EditorGalleryUrlKeyboardGallery ()
+// {
+// App.Tap (q => q.Marked ("Url Keyboard"));
+// App.WaitForElement (PlatformQueries.Editors, "Timeout : Editors");
+// App.Screenshot ("At Url Keyboard Gallery");
+
+// App.Tap (PlatformQueries.Editors);
+// // App.KeyboardIsPresent ();
+// App.Screenshot ("Keyboard showing");
+
+// var text = "https://www.xamarin.com";
+// App.EnterText (PlatformQueries.Editors, text);
+// App.WaitForElement (PlatformQueries.EditorsWithText (text), "Timeout : Editor with Text " + text);
+// App.Screenshot ("Text Entered");
+
+// App.PressEnter ();
+// // App.KeyboardIsDismissed ();
+// App.Screenshot ("Pressed enter");
+// }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Try Numeric keyboard")]
+// [UiTest (Test.Views.Editor)]
+// [UiTest (Test.InputView.Keyboard)]
+// [UiTest (Test.Keyboard.Numeric)]
+// public void EditorGalleryNumericKeyboardGallery ()
+// {
+// App.Tap (q => q.Marked ("Numeric Keyboard"));
+// App.WaitForElement (PlatformQueries.Editors, "Timeout : Editors");
+// App.Screenshot ("At Numeric Keyboard Gallery");
+
+// App.Tap (PlatformQueries.Editors);
+// // App.KeyboardIsPresent ();
+// App.Screenshot ("Keyboard showing");
+
+// var text = "12345678910";
+// App.EnterText (PlatformQueries.Editors, text);
+// App.WaitForElement (PlatformQueries.EditorsWithText (text), "Timeout : Editor with Text " + text);
+// App.Screenshot ("Text Entered");
+// }
+
+// [Test]
+// [Description ("TextChanged event")]
+// [UiTest (Test.Views.Editor)]
+// [UiTest (Test.Editor.TextChanged)]
+// public void EditorGalleryDefaultKeyboardTextChanged ()
+// {
+// App.Tap (q => q.Marked ("Default Keyboard"));
+// App.WaitForElement (PlatformQueries.Editors, "Timeout : Editors");
+// App.Screenshot ("At Default Keyboard Gallery");
+
+// App.EnterText (PlatformQueries.Editors, "ABC");
+// App.Screenshot ("Entered three characters");
+// App.WaitForElement (PlatformQueries.LabelWithText ("xxx"));
+// var labelText = App.GetTextForQuery (PlatformQueries.LabelWithIndex (1));
+// Assert.AreEqual ("xxx", labelText);
+// }
+
+// [Test]
+// [Description ("TextChanged event - Issue #")]
+// [UiTest (Test.Views.Editor)]
+// [UiTest (Test.Editor.TextChanged)]
+// public void EditorGalleryChatKeyboardTextChanged ()
+// {
+// App.Tap (q => q.Marked ("Chat Keyboard"));
+// App.WaitForElement (PlatformQueries.Editors, "Timeout : Editors");
+// App.Screenshot ("At Chat Keyboard Gallery");
+
+// App.EnterText (PlatformQueries.Editors, "ABC");
+// App.Screenshot ("Entered three characters");
+// App.WaitForElement (PlatformQueries.LabelWithText ("xxx"));
+// var labelText = App.GetTextForQuery (PlatformQueries.LabelWithIndex (1));
+// Assert.AreEqual ("xxx", labelText);
+// }
+
+// [Test]
+// [Description ("TextChanged event")]
+// [UiTest (Test.Views.Editor)]
+// [UiTest (Test.Editor.TextChanged)]
+// public void EditorGalleryNumericKeyboardTextChanged ()
+// {
+// App.Tap (q => q.Marked ("Numeric Keyboard"));
+// App.WaitForElement (PlatformQueries.Editors, "Timeout : Editors");
+// App.Screenshot ("At Numeric Keyboard Gallery");
+
+// App.EnterText (PlatformQueries.Editors, "123");
+// App.Screenshot ("Entered three characters");
+// App.WaitForElement (PlatformQueries.LabelWithText ("xxx"));
+// var labelText = App.GetTextForQuery (PlatformQueries.LabelWithIndex (1));
+// Assert.AreEqual ("xxx", labelText);
+// }
+
+// [Test]
+// [Description ("TextChanged event")]
+// [UiTest (Test.Views.Editor)]
+// [UiTest (Test.Editor.TextChanged)]
+// public void EditorGalleryTextKeyboardTextChanged ()
+// {
+// App.Tap (q => q.Marked ("Text Keyboard"));
+// App.WaitForElement (PlatformQueries.Editors, "Timeout : Editors");
+// App.Screenshot ("At Text Keyboard Gallery");
+
+// App.EnterText (PlatformQueries.Editors, "ABC");
+// App.Screenshot ("Entered three characters");
+// App.WaitForElement (PlatformQueries.LabelWithText ("xxx"));
+// var labelText = App.GetTextForQuery (PlatformQueries.LabelWithIndex (1));
+// Assert.AreEqual ("xxx", labelText);
+// }
+
+// [Test]
+// [Description ("TextChanged event")]
+// [UiTest (Test.Views.Editor)]
+// [UiTest (Test.Editor.TextChanged)]
+// public void EditorGalleryUrlKeyboardTextChanged ()
+// {
+// App.Tap (q => q.Marked ("Url Keyboard"));
+// App.WaitForElement (PlatformQueries.Editors, "Timeout : Editors");
+// App.Screenshot ("At Url Keyboard Gallery");
+
+// App.EnterText (PlatformQueries.Editors, "ABC");
+// App.Screenshot ("Entered three characters");
+// App.WaitForElement (PlatformQueries.LabelWithText ("xxx"));
+// var labelText = App.GetTextForQuery (PlatformQueries.LabelWithIndex (1));
+// Assert.AreEqual ("xxx", labelText);
+// }
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-EntryUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-EntryUITests.cs
new file mode 100644
index 00000000..e88ff6b6
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-EntryUITests.cs
@@ -0,0 +1,301 @@
+using System;
+using NUnit.Framework;
+using System.Collections.Generic;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Entry")]
+ internal class EntryGalleryTests : BaseTestFixture
+ {
+ // TODO: Get Toggle color tests for both iOS and Android, Keyboard dismisses for Enter
+ // TODO: Port to new conventions
+
+ public EntryGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.EntryGalleryLegacy);
+ }
+ [Test]
+ [Description ("All Entry Gallery elements are present")]
+ public void EntryGalleryAllElementsPresent ()
+ {
+
+// var entryElements = new [] {
+// q => q.Marked ("Enter something in Normal"),
+// q => q.Marked ("No typing has happened in Normal yet"),
+// PlatformQueries.EntryWithPlaceholder ("Normal"),
+// PlatformQueries.EntryWithPlaceholder ("Password"),
+// PlatformQueries.EntryWithPlaceholder ("Numeric Password"),
+// q => q.Marked ("Focus an Entry"),
+// PlatformQueries.EntryWithPlaceholder ("Disabled"),
+// PlatformQueries.EntryWithPlaceholder ("Activation"),
+// PlatformQueries.EntryWithPlaceholder ("Transparent"),
+// PlatformQueries.EntryWithPlaceholder ("Keyboard.Default")
+// };
+
+// foreach (var entry in entryElements)
+// App.ScrollDownForElement (entry, 10);
+
+// var buttons = new [] {
+// "Toggle Text Color",
+// "Toggle Secure",
+// "Change Placeholder",
+// "Focus First"
+// };
+
+// foreach (var button in buttons)
+// App.ScrollDownForElement (q => q.Button (button), 10);
+
+// App.Screenshot ("All elements present");
+ }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Check that the keyboard shows for each Entry")]
+// public void EntryGalleryKeyboardDisplays ()
+// {
+// AppRect windowBounds = App.MainScreenBounds ();
+
+// var placeHolders = new [] {
+// "Normal",
+// "Password",
+// "Numeric Password",
+// "Disabled",
+// "Activation",
+// "Transparent",
+// "Keyboard.Default"
+// };
+
+// foreach (var placeholder in placeHolders) {
+// App.ScrollDownForElement (PlatformQueries.EntryWithPlaceholder (placeholder), 3);
+// if (placeholder != "Disabled") {
+// App.Tap (PlatformQueries.EntryWithPlaceholder (placeholder));
+// //App.KeyboardIsPresent ();
+// App.Screenshot ("Keyboard shown: " + placeholder);
+// // Tap empty part of screen
+// App.TapCoordinates (10, windowBounds.Height / 3);
+// } else { // Disabled entry should not show keyboard
+// App.Tap (PlatformQueries.EntryWithPlaceholder (placeholder));
+// //App.KeyboardIsDismissed ();
+// App.Screenshot ("Keyboard not shown: " + placeholder);
+// }
+// }
+
+// App.Screenshot ("Keyboard should be dismissed");
+// }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Enter text in each entry")]
+// public void EntryGalleryEnterTextInEachFieldAndTapScreenDismiss ()
+// {
+// var entries = new [] {
+// new { Placeholder = "Normal", LabelValue = "Normal Focused" },
+// new { Placeholder = "Password", LabelValue = "Password Focused" },
+// new { Placeholder = "Numeric Password", LabelValue = "Numeric Password Focused" },
+// new { Placeholder = "Disabled", LabelValue = "Disabled Focused" },
+// new { Placeholder = "Activation", LabelValue = "Activation Focused" },
+// new { Placeholder = "Transparent", LabelValue = "Transparent Focused" },
+// new { Placeholder = "Keyboard.Default", LabelValue = "Keyboard.Default Focused" },
+// };
+
+// AppRect windowBounds = App.MainScreenBounds ();
+// int helloNum = 0;
+
+// foreach (var entry in entries) {
+// App.ScrollDownForElement (PlatformQueries.EntryWithPlaceholder (entry.Placeholder), 3);
+// if (entry.Placeholder == "Disabled") {
+// App.Tap (PlatformQueries.EntryWithPlaceholder (entry.Placeholder));
+// // App.KeyboardIsDismissed ();
+// } else if (entry.Placeholder == "Numeric Password") {
+// App.Tap (PlatformQueries.EntryWithPlaceholder (entry.Placeholder));
+// // App.KeyboardIsPresent ();
+// App.EnterText (PlatformQueries.EntryWithPlaceholder (entry.Placeholder), "167728");
+// App.TapCoordinates (10, windowBounds.Height / 3);
+// } else {
+// App.Tap (PlatformQueries.EntryWithPlaceholder (entry.Placeholder));
+// // App.KeyboardIsPresent ();
+// App.EnterText (PlatformQueries.EntryWithPlaceholder (entry.Placeholder), "Hello " + helloNum);
+// App.TapCoordinates (10, windowBounds.Height / 3);
+// helloNum++;
+// }
+// }
+
+// App.Screenshot ("Entered text in each entry, password should be hidden");
+// App.Tap (q => q.Button ("Toggle Secure"));
+
+// App.ScrollUpForElement (q => q.Marked ("Hello 0"), 5);
+// App.ScrollDownForElement (q => q.Marked ("Hello 1"), 5);
+// App.ScrollDownForElement (q => q.Marked ("167728"), 5);
+// App.ScrollDownForElement (q => q.Marked ("Hello 3"), 5);
+// App.ScrollDownForElement (q => q.Marked ("Hello 4"), 5);
+// App.ScrollDownForElement (q => q.Marked ("Hello 5"), 5);
+
+// App.Screenshot ("Entered text in each entry, password should be shown");
+// }
+
+//// [Test]
+//// public void ToggleTextColor ()
+//// {
+//// AllElementsPresent ();
+////
+//// var text = "hello";
+//// App.EnterText (PlatformQueries.EntryWithPlaceholder ("Normal"), text);
+//// var initialTextColor = App.Query (q => q.Raw (string.Format ("{0} {1}:'{2}', :getCurrentTextColor", PlatformStrings.Entry, PlatformStrings.Text, text)));
+//// App.Tap (q => q.Button ("Toggle Text Color"));
+//// var secondTextColor = App.Query (q => q.Raw (string.Format ("{0} {1}:'{2}', :getCurrentTextColor", PlatformStrings.Entry, PlatformStrings.Text, text)));
+//// Assert.AreNotEqual (initialTextColor, secondTextColor);
+//// }
+
+// [Test]
+// [Description ("Change Placeholder in each entry")]
+// public void EntryGalleryChangePlaceholder ()
+// {
+// for (var i = 1; i <= 5; i++) {
+// App.ScrollDownForElement (q => q.Button ("Change Placeholder"), 5);
+// App.Tap (q => q.Button ("Change Placeholder"));
+// App.ScrollUpForElement (PlatformQueries.EntryWithPlaceholder ("Placeholder " + i), 5);
+// }
+
+// App.Screenshot ("Changed placeholder 5 times");
+// }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Update Keyboard Type - #1307")]
+// public void EntryGalleryChangeKeyboardType ()
+// {
+// App.ScrollDownForElement (PlatformQueries.EntryWithPlaceholder ("Keyboard.Default"), 5);
+// App.Tap (PlatformQueries.EntryWithPlaceholder ("Keyboard.Default"));
+// App.Screenshot ("I should see the default keyboard");
+// App.PressEnter ();
+// App.Screenshot ("Keyboard should be dismissed");
+// App.Screenshot ("Manually check that keyboard type is switched");
+//// App.WaitForElement (PlatformQueries.EntryWithPlaceholder ("Keyboard.Numeric"));
+//// App.Tap (PlatformQueries.EntryWithPlaceholder ("Keyboard.Numeric"));
+// App.Screenshot ("I should see the numeric keyboard");
+// }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Completed handler firing, keyboard dismissing - #1308")]
+// public void EntryGalleryCheckCompletedKeyboardDismissed ()
+// {
+// App.WaitForElement (q => q.Marked ("Enter something in Normal"));
+// App.ScrollDownForElement (PlatformQueries.EntryWithPlaceholder ("Normal"), 5);
+// App.Tap (PlatformQueries.EntryWithPlaceholder ("Normal"));
+// App.Screenshot ("Tapped Normal");
+// App.EnterText (PlatformQueries.EntryWithPlaceholder ("Normal"), "It has been entered");
+// App.Screenshot ("The keyboard should be shown");
+// // App.PressEnter ();
+// App.Screenshot ("Keyboard should be dismissed - Check manually");
+// //App.WaitForNoElement (q => q.Marked ("Enter something in Normal"));
+// //App.ScrollUpForElement (q => q.Marked ("It has been entered"), 5);
+// App.Screenshot ("Text should have changed");
+// }
+
+// [Test]
+// [Description ("Test the TextChanged event")]
+// public void EntryGalleryTextChangedEventTest ()
+// {
+// App.Screenshot ("Waiting for entry gallery");
+// App.WaitForElement (q => q.Marked ("No typing has happened in Normal yet"));
+// App.Screenshot ("Entering text in Normal");
+// App.EnterText (PlatformQueries.EntryWithPlaceholder ("Normal"), "a");
+// App.WaitForElement (q => q.Marked ("You typed in normal"));
+// App.Screenshot ("Text entered, TextChanged event should have fired");
+// }
+
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+
+// [Test]
+// [Description ("All Entry Gallery elements are present - landscape")]
+// public void EntryGalleryAllElementsPresentLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// EntryGalleryAllElementsPresent ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Check that the keyboard shows for each Entry - landscape")]
+// public void EntryGalleryKeyboardDisplaysLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// EntryGalleryKeyboardDisplays ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Enter text in each entry - landscape")]
+// public void EntryGalleryEnterTextInEachFieldAndTapScreenDismissLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// EntryGalleryEnterTextInEachFieldAndTapScreenDismiss ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Change Placeholder in each entry - landscape")]
+// public void EntryGalleryChangePlaceholderLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// EntryGalleryChangePlaceholder ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Update Keyboard Type - #1307 - Landscape")]
+// public void EntryGalleryChangeKeyboardTypeLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// EntryGalleryChangeKeyboardType ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Completed handler firing, keyboard dismissing - #1308 - Landscape")]
+// public void EntryGalleryCheckCompletedKeyboardDismissedLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// EntryGalleryCheckCompletedKeyboardDismissed ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Test the TextChanged event - Landscape")]
+// public void EntryGalleryTextChangedEventTestLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// EntryGalleryTextChangedEventTest ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-GridGalleryUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-GridGalleryUITests.cs
new file mode 100644
index 00000000..04b59460
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-GridGalleryUITests.cs
@@ -0,0 +1,132 @@
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+using System.Threading;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("GridLayout")]
+ internal class GridLayoutGalleryTests : BaseTestFixture
+ {
+ // TODO - test Absolutes
+ // TODO: Port to new conventions
+
+ public GridLayoutGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.GridGalleryLegacy);
+ }
+
+ //void AllElementsPresent ()
+ //{
+ // App.ScrollForElement ("* marked:'Column Types:'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ // App.ScrollForElement ("* marked:'Absolute Width'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ // App.ScrollForElement ("* marked:'Auto Width'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ // App.ScrollForElement ("* marked:'Star'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ // App.ScrollForElement ("* marked:'*'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ // App.ScrollForElement ("* marked:'**'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ // App.ScrollForElement ("* marked:'***'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ // App.ScrollForElement ("* marked:'Right'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ // App.ScrollForElement ("* marked:'Center'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ // App.ScrollForElement ("* marked:'Left'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ // App.ScrollForElement ("* marked:'Fill'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ // App.ScrollForElement ("* marked:'Spans:'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ // App.ScrollForElement ("* marked:'Spanning 4 columns'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ // App.ScrollForElement ("* marked:'Spanning 3 rows'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ // App.ScrollForElement ("* marked:'Spanning 4 columns'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+ // App.ScrollForElement ("* marked:'a block 3x3'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+ // App.Screenshot ("All elements present");
+ //}
+
+
+ [Test]
+ [Category("ManualReview")]
+ [Description ("Check Grid Star sizing")]
+ [UiTest (typeof(Grid))]
+ public void GridLayoutGalleryStarLayout ()
+ {
+ // AllElementsPresent ();
+
+ // App.ScrollForElement ("* marked:'*'", new Drag (ScreenBounds, Drag.Direction.TopToBottom, Drag.DragLength.Medium));
+
+ // var oneStarWidth = App.Query (q => q.Marked ("*"))[0].Rect.Width;
+ // var twoStarWidth = App.Query (q => q.Marked ("**"))[0].Rect.Width;
+ // var threeStarWidth = App.Query (q => q.Marked ("***"))[0].Rect.Width;
+
+ // Assert.AreEqual (threeStarWidth, oneStarWidth * 3, 2.0);
+ // Assert.AreEqual (twoStarWidth, oneStarWidth * 2, 2.0);
+
+ // App.Screenshot ("Star layout correct");
+ }
+
+ // TODO port to new framework
+ //[Test]
+ //[UiTest (Test.Layouts.Grid)]
+ //public void GridLayoutGallerySpanSizes ()
+ //{
+ // AllElementsPresent ();
+
+ // var unitWidth = App.Query (q => q.Marked ("Unit"))[0].Rect.Width;
+ // var unitHeight = App.Query (q => q.Marked ("Unit"))[0].Rect.Height;
+
+ // var spanningFourColumnsWidth = App.Query (q => q.Marked ("Spanning 4 columns"))[0].Rect.Width;
+ // var spanningFourColumnsHeight = App.Query (q => q.Marked ("Spanning 4 columns"))[0].Rect.Height;
+
+ // // platform queries deal with label rendering differences
+ // var threeXThreeWidth = App.Query (PlatformQueries.ThreeXThreeGridCell) [0].Rect.Width;
+ // var threeXThreeHeight = App.Query (PlatformQueries.ThreeXThreeGridCell) [0].Rect.Height;
+
+ // var spanningThreeRowsWidth = App.Query (PlatformQueries.SpanningThreeRows)[0].Rect.Width;
+ // var spanningThreeRowsHeight = App.Query (PlatformQueries.SpanningThreeRows)[0].Rect.Height;
+
+ // Assert.AreEqual (spanningFourColumnsWidth, unitWidth * 4, 2.0);
+ // Assert.AreEqual (spanningFourColumnsHeight, unitHeight, 2.0);
+
+ // Assert.AreEqual (threeXThreeWidth, unitWidth * 3, 2.0);
+ // Assert.AreEqual (threeXThreeHeight, unitHeight * 3, 2.0);
+
+ // Assert.AreEqual (spanningThreeRowsWidth, unitWidth, 2.0);
+ // Assert.AreEqual (spanningThreeRowsHeight, unitHeight * 3, 2.0);
+
+ // App.Screenshot ("Span sizes correct");
+ //}
+
+ // TODO port to new framework
+ //[Test]
+ //[UiTest (Test.Layouts.Grid)]
+ //public void GridLayoutGalleryResizesProperlyAfterRotation ()
+ //{
+ // // Displays GridLayout bug on rotation (Issue #854)
+ // AllElementsPresent ();
+
+ // AppRect detailBounds = App.DetailPage ().Rect;
+
+ // var oneStarWidth = App.Query (q => q.Marked ("*"))[0].Rect.Width;
+ // var twoStarWidth = App.Query (q => q.Marked ("**"))[0].Rect.Width;
+ // var threeStarWidth = App.Query (q => q.Marked ("***"))[0].Rect.Width;
+
+ // Assert.AreEqual (detailBounds.Width, oneStarWidth + twoStarWidth + threeStarWidth, 1.0);
+ // App.Screenshot ("All stars fill portrait screen width");
+
+ // App.SetOrientationLandscape ();
+
+ // AppRect detailBoundsAfterRotation = App.DetailPage ().Rect;
+ // var oneStarWidthAfterRotation = App.Query (q => q.Marked ("*"))[0].Rect.Width;
+ // var twoStarWidthAfterRotation = App.Query (q => q.Marked ("**"))[0].Rect.Width;
+ // var threeStarWidthAfterRotation = App.Query (q => q.Marked ("***"))[0].Rect.Width;
+
+ // Assert.AreEqual (detailBoundsAfterRotation.Width, oneStarWidthAfterRotation + twoStarWidthAfterRotation + threeStarWidthAfterRotation, 1.0);
+ // App.Screenshot ("Grid stars resized");
+
+ // App.SetOrientationPortrait ();
+ //}
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-GroupedListActionsUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-GroupedListActionsUITests.cs
new file mode 100644
index 00000000..289b5389
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-GroupedListActionsUITests.cs
@@ -0,0 +1,277 @@
+using NUnit.Framework;
+using System.Threading;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("ListView")]
+ internal class GroupedListActionsGalleryTests : BaseTestFixture
+ {
+ // TODO Group item actions, isolate specific indices (iOS is by 1, Android by two for cells)
+ // TODO: Port to new conventions
+
+ public GroupedListActionsGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.GroupedListActionsGalleryLegacy);
+ }
+
+ [Test]
+ [Description ("All of the grouped list actions are displayed")]
+ public void GroupedListActionsGalleryAllElementsExist ()
+ {
+// var actions = new [] {
+// "General",
+// "Change group name",
+// "Change group short name",
+// "Child item actions",
+// "Clear this group",
+// "Insert group item",
+// "Insert 2 group items",
+// "Remove next item",
+// "Dummy item RDI",
+// "Remove next 2 dummy items",
+// "Dummy item RmDI-1",
+// "Dummy item RmDI-2",
+// "Replace dummy item",
+// "Dummy item RpDI",
+// "Replace next two dummy items",
+// "Dummy item RpDI-1",
+// "Dummy item RpDI-2",
+// "Select next dummy item",
+// "Dummy item SI",
+// "Move dummy above this one",
+// "Dummy item MDI",
+// "Move last 2 items above this one",
+// "Dummy item M2DI-1",
+// "Dummy item M2DI-2",
+// "Group item actions",
+// "Clear all",
+// "Insert group",
+// "Insert 2 groups",
+// "Remove previous dummy group",
+// "Remove previous 2 dummy groups",
+// "Replace previous dummy group",
+// "Replace previous 2 dummy groups",
+// "Move next group above",
+// "Move next 2 groups above"
+// };
+
+// foreach (var action in actions) {
+// App.ScrollDownForElement (q => q.Marked (action), 40);
+// }
+
+// App.Screenshot ("All actions are preset");
+ }
+
+// [Test]
+// [Description ("Change group name")]
+// public void GroupedListActionsGalleryChangeGroupName ()
+// {
+// App.ScrollDownForElement (q => q.Marked ("General"), 40);
+// App.Screenshot ("Before changing group name");
+// App.Tap (q => q.Marked ("Change group name"));
+// App.WaitForElement (q => q.Marked ("General (changed)"));
+// App.Screenshot ("After changing group name");
+// }
+
+// [Test]
+// [Description ("Child actions - clear group")]
+// public void GroupedListActionsGalleryChildClearGroup ()
+// {
+// App.ScrollDownForElement (q => q.Marked ("Clear this group"), 40);
+// App.Screenshot ("Before clearing group");
+// App.Tap (q => q.Marked ("Clear this group"));
+// App.WaitForNoElement (q => q.Marked ("Insert group item"));
+// App.WaitForNoElement (q => q.Marked ("Insert 2 group items"));
+// App.Screenshot ("After clearing the group");
+// }
+
+// [Test]
+// [Description ("Child actions - insert item(s)")]
+// public void GroupedListActionsGalleryChildInsertItems ()
+// {
+// App.ScrollDownForElement (q => q.Marked ("Insert group item"), 40);
+// App.Screenshot ("Before inserting item");
+
+// App.Tap (q => q.Marked ("Insert group item"));
+// App.ScrollUpForElement (q => q.Marked ("Inserted item S"), 2);
+// App.WaitForElement (q => q.Marked ("Inserted item S"));
+// App.Screenshot ("After inserting item");
+
+// App.ScrollDownForElement (q => q.Marked ("Insert 2 group items"), 2);
+// App.Tap (q => q.Marked ("Insert 2 group items"));
+// App.ScrollUpForElement (q => q.Marked ("Inserted item D 0"), 2);
+// App.WaitForElement (q => q.Marked ("Inserted item D 0"));
+// App.WaitForElement (q => q.Marked ("Inserted item D 1"));
+// App.Screenshot ("After inserting 2 items");
+// }
+
+
+// [Test]
+// [Description ("Child actions - remove item(s)")]
+// public void GroupedListActionsGalleryChildRemoveItems ()
+// {
+// App.ScrollDownForElement (q => q.Marked ("Remove next item"), 40);
+// App.Screenshot ("Before removing item");
+
+// App.Tap (q => q.Marked ("Remove next item"));
+// App.WaitForNoElement (q => q.Marked ("Dummy item RDI"));
+// App.Screenshot ("After removing item");
+
+// App.ScrollDownForElement (q => q.Marked ("Remove next 2 dummy items"), 40);
+// App.Tap (q => q.Marked ("Remove next 2 dummy items"));
+// App.WaitForNoElement (q => q.Marked ("Dummy item RmDI-1"));
+// App.WaitForNoElement (q => q.Marked ("Dummy item RmDI-2"));
+// App.Screenshot ("After removing 2 items");
+// }
+
+// [Test]
+// [Description ("Child actions - replace item(s)")]
+// public void GroupedListActionsGalleryChildReplaceItems ()
+// {
+// App.ScrollDownForElement (q => q.Marked ("Replace dummy item"), 40);
+// App.Screenshot ("Before replacing item");
+
+// App.Tap (q => q.Marked ("Replace dummy item"));
+// App.WaitForNoElement (q => q.Marked ("Dummy item RpDI"));
+// App.ScrollDownForElement (q => q.Marked ("Replaced item"), 2);
+// App.Screenshot ("After replacing item");
+
+// App.ScrollDownForElement (q => q.Marked ("Replace next two dummy items"), 40);
+// App.Tap (q => q.Marked ("Replace next two dummy items"));
+// App.WaitForNoElement (q => q.Marked ("Dummy item RpDI-1"));
+// App.WaitForNoElement (q => q.Marked ("Dummy item RpDI-2"));
+// App.WaitForElement (q => q.Marked ("Replaced items 0"));
+// App.WaitForElement (q => q.Marked ("Replaced items 1"));
+// App.Screenshot ("After replacing 2 items");
+// }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Child actions - select item(s)")]
+// public void GroupedListActionsGalleryChildSelectItems ()
+// {
+// App.ScrollDownForElement (q => q.Marked ("Select next dummy item"), 40);
+// App.Screenshot ("Before selecting item");
+// App.Tap (q => q.Marked ("Select next dummy item"));
+// App.Screenshot ("After selecting item");
+// }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Child actions - move item(s)")]
+// public void GroupedListActionsGalleryChildMoveItems ()
+// {
+// App.ScrollDownForElement (q => q.Marked ("Move dummy above this one"), 40);
+// App.Screenshot ("Before moving item");
+
+// App.Tap (q => q.Marked ("Move dummy above this one"));
+// App.Screenshot ("Dummy item MDI should now be above 'Move dummy above this one'");
+
+// App.Tap (q => q.Marked ("Move last 2 items above this one"));
+// App.Screenshot ("Dummy item M2DI-1 and M2DI-2 should now be above 'Move last 2 items above this one'");
+
+// }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+
+// [Test]
+// [Description ("Child item action test - landscape")]
+// public void GroupedListActionsGalleryAllElementsExistLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// GroupedListActionsGalleryAllElementsExist ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to portrait");
+// }
+
+// [Test]
+// [Description ("Change group name - landscape")]
+// public void GroupedListActionsGalleryChangeGroupNameLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// GroupedListActionsGalleryChangeGroupName ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to portrait");
+// }
+
+// [Test]
+// [Description ("Child actions - clear group - landscape")]
+// public void GroupedListActionsGalleryChildClearGroupLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// GroupedListActionsGalleryChildClearGroup ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to portrait");
+// }
+
+// [Test]
+// [Description ("Child actions - insert item(s) - landscape")]
+// public void GroupedListActionsGalleryChildInsertItemsLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// GroupedListActionsGalleryChildInsertItems ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to portrait");
+// }
+
+
+// [Test]
+// [Description ("Child actions - remove item(s) - landscape")]
+// public void GroupedListActionsGalleryChildRemoveItemsLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// GroupedListActionsGalleryChildRemoveItems ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to portrait");
+// }
+
+// [Test]
+// [Description ("Child actions - replace item(s) - landscape")]
+// public void GroupedListActionsGalleryChildReplaceItemsLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// GroupedListActionsGalleryChildReplaceItems ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to portrait");
+// }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Child actions - select item(s) - landscape")]
+// public void GroupedListActionsGalleryChildSelectItemsLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// GroupedListActionsGalleryChildSelectItems ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to portrait");
+// }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Child actions - move item(s) - landscape")]
+// public void GroupedListActionsGalleryChildMoveItemsLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// GroupedListActionsGalleryChildMoveItems ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to portrait");
+// }
+
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-InputIntentUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-InputIntentUITests.cs
new file mode 100644
index 00000000..10713087
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-InputIntentUITests.cs
@@ -0,0 +1,190 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using NUnit.Framework;
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Entry")]
+ internal class InputIntentGalleryTests : BaseTestFixture
+ {
+ // TODO: Detect keyboard types, fix scroll coordinates
+ // TODO: Port to new conventions
+
+ public InputIntentGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.InputIntentGalleryLegacy);
+ }
+
+ [Test]
+ [Description ("All entries are shown")]
+ public void InputIntentGalleryAllElementsExist ()
+ {
+// var inputs = new [] {
+// "Default",
+// "Email Input",
+// "Text Input",
+// "Url Input",
+// "Numeric Input",
+// "Telephone Input",
+// "Chat Input",
+// "Custom Entry"
+// };
+
+// foreach (var input in inputs)
+// App.ScrollDownForElement (PlatformQueries.EntryWithPlaceholder (input), 5);
+
+// App.Screenshot ("All Entries exist");
+ }
+
+// [Test]
+// [Description ("Tap each entry and dismiss keyboard by tapping outside of keyboard")]
+// public void InputIntentGalleryTapEachEntry ()
+// {
+// AppRect screenSize = App.MainScreenBounds ();
+// var numberOfEntries = App.Query (PlatformQueries.Entrys).Length;
+// App.Screenshot ("Tap each entry");
+
+// var inputs = new List<string> () {
+// "Default",
+// "Email Input",
+// "Text Input",
+// "Url Input",
+// "Numeric Input",
+// "Telephone Input",
+// "Chat Input",
+// "Custom Entry"
+// };
+
+// foreach (var input in inputs) {
+// App.ScrollDownForElement (PlatformQueries.EntryWithPlaceholder (input), 5);
+// App.Tap (PlatformQueries.EntryWithPlaceholder (input));
+// App.Screenshot ("Input Tapped: " + input);
+// App.TapCoordinates (5, screenSize.Height / 3);
+// App.Screenshot ("Clicked main screen, keyboard should be dismissed");
+// }
+
+// App.ScrollUpForElement (q => q.Marked ("Custom Focused"), 5);
+
+// App.Screenshot ("Label should now say 'Custom Focused'");
+// }
+
+// [Test]
+// [Description ("Enter text in each entry")]
+// public void InputIntentGalleryEnterTextInEachEnry ()
+// {
+
+// AppRect screenSize = App.MainScreenBounds ();
+
+// var inputs = new Dictionary<string, string> () {
+// { "Default", "abc Quick weee!" },
+// { "Email Input", "s@test.com" },
+// { "Text Input", "Hi, I am text!" },
+// { "Url Input", "https://www.xamarin.com/" },
+// { "Numeric Input", "12345678910" },
+// { "Telephone Input", "0000001234" },
+// { "Chat Input", "Sorry, I wasn\'t paying attention." },
+// { "Custom Entry", "I should be custom" }
+// };
+
+// App.Screenshot ("Enter text in each input");
+
+// foreach (var input in inputs) {
+// App.ScrollDownForElement (PlatformQueries.EntryWithPlaceholder (input.Key), 5);
+// App.Tap (PlatformQueries.EntryWithPlaceholder (input.Key));
+// App.EnterText (PlatformQueries.EntryWithPlaceholder (input.Key), input.Value);
+// App.Screenshot ("Text entered");
+// App.TapCoordinates (5, screenSize.Height / 3);
+// App.Screenshot ("Clicked main screen, keyboard should be dismissed");
+// }
+
+// }
+
+// [Test]
+// [Description ("Open keyboard and navigate back without dismissing")]
+// public void InputIntentGalleryNavigateBackWithoutDismissingKeyboard ()
+// {
+// // Should catch any regression of Issue #638, #928
+// var inputs = new List<string> () {
+// "Default",
+// "Email Input",
+// "Text Input",
+// "Url Input",
+// "Numeric Input",
+// "Telephone Input",
+// "Chat Input",
+// "Custom Entry"
+// };
+
+// foreach (string input in inputs) {
+// App.ScrollDownForElement (PlatformQueries.EntryWithPlaceholder (input), 5);
+// App.Tap (PlatformQueries.EntryWithPlaceholder (input));
+// App.Screenshot ("Input Tapped");
+
+// App.Tap (PlatformQueries.Back);
+// App.Screenshot ("Back at Control Gallery");
+// App.ScrollDownForElement (q => q.Button ("InputIntent"), 2);
+// App.Tap (q => q.Button ("InputIntent"));
+// }
+// }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+
+// [Test]
+// [Description ("All entries are shown - landscape")]
+// public void InputIntentGalleryAllElementsExistLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// InputIntentGalleryAllElementsExist ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to portrait");
+// }
+
+// [Test]
+// [Description ("Tap each entry and dismiss keyboard by tapping outside of keyboard - landscape")]
+// public void InputIntentGalleryTapEachEntryLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// InputIntentGalleryTapEachEntry ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to portrait");
+// }
+
+// [Test]
+// [Description ("Enter text in each entry")]
+// public void InputIntentGalleryEnterTextInEachEnryLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// InputIntentGalleryEnterTextInEachEnry ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to portrait");
+// }
+
+// [Test]
+// [Description ("Open keyboard and navigate back without dismissing")]
+// public void InputIntentGalleryNavigateBackWithoutDismissingKeyboardLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// InputIntentGalleryNavigateBackWithoutDismissingKeyboard ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to portrait");
+// }
+
+ }
+}
+
+
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ListUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ListUITests.cs
new file mode 100644
index 00000000..e57ed902
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ListUITests.cs
@@ -0,0 +1,92 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("ListView")]
+ internal class ListGalleryTests : BaseTestFixture
+ {
+ // TODO
+ // TODO: Port to new conventions
+
+ public ListGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.ListViewGalleryLegacy);
+ }
+// void AllElementsExist ()
+// {
+// for (int i = 0; i < 5; i++)
+// App.WaitForElement (q => q.Marked (i.ToString ()));
+
+// App.Screenshot ("List elements exist");
+// }
+
+ [Test]
+ [Description ("Click 0 - 5 and reset")]
+ public void ListGalleryClickElementsAndReset ()
+ {
+// AllElementsExist ();
+
+// for (int i = 0; i < 5; i++) {
+// App.Tap (q => q.Raw (string.Format ("{0} index:{1}", PlatformStrings.Cell, i)));
+// }
+
+// App.WaitForNoElement (q => q.Marked ("0"), "Timeout : 0");
+// Assert.AreEqual (2, App.Query (q => q.Marked ("5")).Length);
+
+// App.Screenshot ("Clicked 0 - 5");
+
+// App.Tap (q => q.Raw (PlatformStrings.Cell + " index:5"));
+
+// App.WaitForElement (q => q.Marked ("0"), "Timeout : 0");
+// Assert.AreEqual (1, App.Query (q => q.Marked ("5")).Length);
+
+// App.Screenshot ("Reset elements");
+ }
+
+// [Test]
+// [Description ("Scroll to the end of the list")]
+// public void ListGalleryScrollToEndOfList ()
+// {
+// AllElementsExist ();
+
+// for (int i = 0; i < 50; i++)
+// App.ScrollDownForElement (q => q.Marked (i.ToString ()), 2);
+
+// App.Screenshot ("At the bottom of the list");
+// }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+
+// [Test]
+// [Description ("Click 0 - 5 and reset - Landscape")]
+// public void ListGalleryClickElementsAndResetLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// ListGalleryClickElementsAndReset ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Scroll to the end of the list - Landscape")]
+// public void ListGalleryScrollToEndOfListLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// ListGalleryScrollToEndOfList ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-MapUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-MapUITests.cs
new file mode 100644
index 00000000..f2d55f3e
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-MapUITests.cs
@@ -0,0 +1,110 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+using System.Diagnostics;
+using System.Threading;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Map")]
+ internal class MapGalleryTests : BaseTestFixture
+ {
+ // TODO - Figure out how to implement the map stuff for Android, ie query pins etc
+ // TODO: Port to new conventions
+
+ public MapGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.MapGalleryLegacy);
+ }
+
+ [Test]
+ [Description ("Gallery element are present")]
+ public void MapGalleryAllElementsPresent ()
+ {
+ // CustomScrollDownToBottomForAllElements ();
+ // App.Screenshot ("All elements exist");
+ }
+
+ //[Test]
+ //[Description ("Change MapMapType")]
+ //public void MapGalleryMapType ()
+ //{
+ // AppRect screenBounds = App.MainScreenBounds ();
+ // App.DragFromToForElement (5, q => q.Button ("Map Type"), screenBounds.Width - 15, screenBounds.Height - 100, screenBounds.Width - 15, 15);
+ // App.Tap (q => q.Button ("Map Type"));
+ // App.Screenshot ("Selected Map Type");
+ // App.Tap (q => q.Button ("Satellite"));
+ // App.Screenshot ("Satellite MapType selected");
+ // App.DragFromToForElement (5, PlatformQueries.SearchBars, screenBounds.Width - 15, 75, screenBounds.Width - 15, screenBounds.Height - 100);
+ //}
+
+
+// [Test]
+// public void PinDetails ()
+// {
+// App.Tap (q => q.Raw(PlatformStrings.MapPin + " index:0"));
+// App.WaitForElement (q => q.Marked ("Sistine Chapel"));
+// App.WaitForElement (q => q.Marked ("Piazza della Rotunda, 00186 Rome, Province of Rome, Italy"));
+//
+// App.Screenshot ("First pin");
+//
+// App.Tap (q => q.Raw(PlatformStrings.MapPin + " index:1"));
+// App.WaitForElement (q => q.Marked ("Pantheon"));
+// App.WaitForElement (q => q.Marked ("Piazza del Colosseo, 00186 Rome, Province of Rome, Italy"));
+//
+// App.Screenshot ("Second pin");
+//
+// App.Tap (q => q.Raw(PlatformStrings.MapPin + " index:2"));
+// App.WaitForElement (q => q.Marked ("Colosseum"));
+// App.WaitForElement (q => q.Marked ("Piazza del Colosseo, 00184 Rome, Province of Rome, Italy"));
+//
+// App.Screenshot ("Third pin");
+// }
+
+
+ //void CustomScrollDownToBottomForAllElements ()
+ //{
+ // AppRect screenBounds = App.MainScreenBounds ();
+
+ // App.DragFromToForElement (5, PlatformQueries.SearchBars, screenBounds.Width - 15, screenBounds.Height - 100, screenBounds.Width - 15, 15);
+ // App.DragFromToForElement (5, PlatformQueries.Map, screenBounds.Width - 15, screenBounds.Height - 100, screenBounds.Width - 15, 15);
+
+ // App.DragFromToForElement (5, q => q.Button ("Map Type"), screenBounds.Width - 15, screenBounds.Height - 100, screenBounds.Width - 15, 15);
+ // App.DragFromToForElement (5, q => q.Button ("Zoom In"), screenBounds.Width - 15, screenBounds.Height - 100, screenBounds.Width - 15, 15);
+ // App.DragFromToForElement (5, q => q.Button ("Zoom Out"), 15, screenBounds.Height - 100, 15, 15);
+ // App.DragFromToForElement (5, q => q.Button ("Address From Position"), screenBounds.Width - 15, screenBounds.Height - 100, screenBounds.Width - 15, 15);
+ //}
+
+/*******************************************************/
+/**************** Landscape tests **********************/
+/*******************************************************/
+
+ //[Test]
+ //[Description ("Gallery element are present - Landscape")]
+ //public void MapGalleryAllElementsPresentLandscape ()
+ //{
+ // App.SetOrientationLandscape ();
+ // App.Screenshot ("Rotated to Landscape");
+ // MapGalleryAllElementsPresent ();
+ // App.SetOrientationPortrait ();
+ // App.Screenshot ("Rotated to Portrait");
+ //}
+
+ //[Test]
+ //[Description ("Change MapMapType - Landscape")]
+ //public void MapGalleryMapTypeLandscape ()
+ //{
+ // App.SetOrientationLandscape ();
+ // App.Screenshot ("Rotated to Landscape");
+ // MapGalleryMapType ();
+ // App.SetOrientationPortrait ();
+ // App.Screenshot ("Rotated to Portrait");
+ //}
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-MinimumSizeUITest.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-MinimumSizeUITest.cs
new file mode 100644
index 00000000..9de241c0
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-MinimumSizeUITest.cs
@@ -0,0 +1,48 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("StackLayout")]
+ internal class MinimumSizeGalleryTests : BaseTestFixture
+ {
+ // TODO
+ // TODO: Port to new conventions
+
+ public MinimumSizeGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.MinimumSizeGalleryLegacy);
+ }
+
+
+ [Test]
+ [Description ("Scroll to the bottom of the TableView")]
+ public void MinimumSizeGalleryTableViewElementsAreAccessible ()
+ {
+ // AllElementsPresent ();
+
+ // var tableView = App.Query (PlatformQueries.Tables) [0];
+
+ // var tableX = tableView.Rect.X;
+ // var tableY = tableView.Rect.Y;
+ // var tableWidth = tableView.Rect.Width;
+ // var tableHeight = tableView.Rect.Height;
+
+ // var elementFound = App.DragFromToForElement (20, q => q.Marked ("Cell 4 Last"), tableWidth / 2, (tableY + tableHeight) - 70, tableWidth / 2, tableY + 30);
+
+ // Assert.IsTrue (elementFound);
+ // App.Screenshot ("All table elements exist");
+ }
+
+/*******************************************************/
+/**************** Landscape tests **********************/
+/*******************************************************/
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-NavigationBarUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-NavigationBarUITests.cs
new file mode 100644
index 00000000..5af7751d
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-NavigationBarUITests.cs
@@ -0,0 +1,57 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+using System;
+using System.Threading;
+using Xamarin.UITest.Queries;
+using System.Diagnostics;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ //[TestFixture]
+ //[Category ("NavigationPage")]
+ internal class NavigationBarGalleryTests : BaseTestFixture
+ {
+ // TODO: Port to new conventions
+
+ public NavigationBarGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ //App.NavigateToGallery (GalleryQueries.NavigationBarGalleryLegacy);
+ }
+
+ //[Test]
+ //[Category ("ManualReview")]
+ //[Description ("Change NavigationPage Bar colors")]
+ public void NavigationBarGalleryTestsChangeColors ()
+ {
+ // App.Screenshot ("Background should be green, Text and back button / arrow should be yellow");
+
+ // App.Tap (q => q.Button ("Change BarTextColor"));
+ // App.Screenshot ("Text / back button / arrow should change to teal");
+ // App.Tap (q => q.Button ("Change BarTextColor"));
+ // App.Screenshot ("Text / back button / arrow should change to Color.Default");
+ // App.Tap (q => q.Button ("Change BarTextColor"));
+ // App.Screenshot ("Text / back button / arrow should change to teal");
+
+ // App.Tap (q => q.Button ("Change BarBackgroundColor"));
+ // App.Screenshot ("Background color should change to navy");
+ // App.Tap (q => q.Button ("Change BarBackgroundColor"));
+ // App.Screenshot ("Background color should change to Color.Default");
+ // App.Tap (q => q.Button ("Change BarBackgroundColor"));
+ // App.Screenshot ("Background color should change to navy");
+
+ // App.Tap (q => q.Button ("Change Both to default"));
+ // App.Screenshot ("Background color / text / back button / arrow should change to Color.Default");
+
+ // App.Tap (q => q.Button ("Make sure Tint still works"));
+ // App.Screenshot ("Background arrow should change to red");
+
+ // App.Tap (q => q.Button ("Black background, white text"));
+ // App.Screenshot ("Status bar should be white on iOS");
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-RelativeLayoutUITest.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-RelativeLayoutUITest.cs
new file mode 100644
index 00000000..72171f39
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-RelativeLayoutUITest.cs
@@ -0,0 +1,49 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+using System.Linq;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("RelativeLayout")]
+ internal class RelativeLayoutGalleryTests : BaseTestFixture
+ {
+ // TODO - Add relative layout tests
+ // TODO: Port to new conventions
+
+ public RelativeLayoutGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.RelativeLayoutGalleryLegacy);
+ }
+
+ [Test]
+ [Description ("All elements are present")]
+ public void RelativeLayoutGalleryAllElementsPresent ()
+ {
+// var elements = Enumerable.Range (0, 201).Select (x => x);
+// foreach (int element in elements)
+// App.ScrollDownForElement (q => q.Marked (element.ToString ()), 10);
+ }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+
+// [Test]
+// [Description ("All elements are present - Landscape")]
+// public void RelativeLayoutGalleryAllElementsPresentLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// RelativeLayoutGalleryAllElementsPresent ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-SearchBarUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-SearchBarUITests.cs
new file mode 100644
index 00000000..d9461cf6
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-SearchBarUITests.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NUnit.Framework;
+using System.Threading;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("SearchBar")]
+ internal class SearchBarGalleryTests : BaseTestFixture
+ {
+ // TODO: Enter text and try searching
+ // TODO: Port to new conventions
+
+ public SearchBarGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.SearchBarGalleryLegacy);
+ }
+
+ [Test]
+ [Category ("ManualReview")]
+ [Description ("Enter query into each SearchBar")]
+ public void SearchBarGalleryEnterSearchText ()
+ {
+// SearchBarGalleryAllElementsPresent ();
+// for (var i = 0; i < 3; i++) {
+// App.ScrollDownForElement (PlatformQueries.SearchBarWithIndex (i), 5);
+// App.Tap (PlatformQueries.SearchBarWithIndex (i));
+// App.EnterText (PlatformQueries.SearchBarWithIndex (i), "Search: " + i);
+// App.Screenshot ("Keyboard should be shown");
+// App.PressEnter ();
+// App.WaitForElement (q => q.Marked ("Search: " + i));
+// App.Screenshot (string.Format("Keyboard should be dismissed - Label should have changed to 'Search: {0}'", i));
+// }
+
+// App.Tap (q => q.Button ("More SearchBars"));
+// App.WaitForElement (q => q.Marked ("Search Query 2"));
+
+// SearchBarGalleryAllElementsPresentPageTwo ();
+
+// // Disabled keyboard
+// App.Tap (PlatformQueries.SearchBarWithIndex (0));
+// App.Screenshot ("Should not see keyboard for disabled SearchBar");
+
+// App.Tap (PlatformQueries.SearchBarWithIndex (1));
+// App.Screenshot ("Should not see keyboard for disabled SearchBar");
+// App.EnterText (PlatformQueries.SearchBarWithIndex (1), "Entered transparent");
+// App.PressEnter ();
+// App.WaitForElement (q => q.Marked ("Entered transparent"));
+// App.Screenshot ("Entered query for tranparent SearchBar");
+ }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Enable disable keyboard, Issues #1182, #1237")]
+// public void SearchBarGalleryEnableDisableSearchBar ()
+// {
+// App.Tap (q => q.Button ("More SearchBars"));
+// App.WaitForElement (q => q.Marked ("Search Query 2"));
+
+// SearchBarGalleryAllElementsPresentPageTwo ();
+
+// App.Tap (PlatformQueries.SearchBarWithIndex (0));
+// App.Screenshot ("SearchBar should not be focused, keyboard should not be shown");
+
+// App.Tap (q => q.Button ("Toggle enabled"));
+// App.Tap (PlatformQueries.SearchBarWithIndex (0));
+// App.EnterText (PlatformQueries.SearchBarWithIndex (0), "Now Enabled");
+// App.PressEnter ();
+// App.ScrollDownForElement (q => q.Marked ("Now Enabled"), 2);
+// App.Screenshot ("Enabled and abled to query");
+
+// App.Tap (q => q.Button ("Toggle enabled"));
+// App.Screenshot ("Disabled again");
+
+// App.ScrollUpForElement (PlatformQueries.SearchBarWithIndex (0), 2);
+// App.Tap (PlatformQueries.SearchBarWithIndex (0));
+// App.Screenshot ("SearchBar should not be focused, keyboard should not be shown after diabling once again");
+// }
+
+// [Test]
+//// [Category ("Single")]
+// [Description ("Test the TextChanged event")]
+// public void SearchBarGalleryTextChangedEventTest ()
+// {
+// SearchBarGalleryAllElementsPresent ();
+
+// App.EnterText (PlatformQueries.SearchBarWithIndex (0), "A");
+// App.Screenshot ("Entered three characters in noPlaceholder search bar");
+// var labelText = App.GetTextForQuery (PlatformQueries.LabelWithText ("1"));
+// Assert.AreEqual ("1", labelText);
+
+// App.EnterText (PlatformQueries.SearchBarWithIndex (1), "B");
+// App.Screenshot ("Entered three characters in normal search bar");
+// labelText = App.GetTextForQuery (PlatformQueries.LabelWithText ("2"));
+// Assert.AreEqual ("2", labelText);
+
+// App.EnterText (PlatformQueries.SearchBarWithIndex (2), "C");
+// App.Screenshot ("Entered three characters in activation search bar");
+// labelText = App.GetTextForQuery (PlatformQueries.LabelWithText ("3"));
+// Assert.AreEqual ("3", labelText);
+
+// }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Enable disable keyboard, Issues #1182, #1237 - landscape")]
+// public void SearchBarGalleryEnableDisableSearchBarLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// SearchBarGalleryEnableDisableSearchBar ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Category ("ManualReview")]
+// [Description ("Enter query into each SearchBar - Landscape")]
+// public void SearchBarGalleryEnterSearchTextLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// SearchBarGalleryEnterSearchText ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// void SearchBarGalleryAllElementsPresent ()
+// {
+// var searchBars = App.Query (PlatformQueries.SearchBars);
+// Assert.AreEqual (3, searchBars.Length);
+
+// App.ScrollDownForElement (q => q.Marked ("Search Query"), 5);
+
+// App.ScrollUp ();
+// App.Screenshot ("All SearchBars present");
+// }
+
+
+
+// void SearchBarGalleryAllElementsPresentPageTwo ()
+// {
+// App.ScrollDownForElement (q => q.Marked ("Search Query 2"), 5);
+// App.ScrollDownForElement (q => q.Button ("Toggle enabled"), 5);
+
+// App.ScrollUp ();
+// App.Screenshot ("All SearchBars present - Page 2");
+// }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-SliderUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-SliderUITests.cs
new file mode 100644
index 00000000..11c33d7f
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-SliderUITests.cs
@@ -0,0 +1,94 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Slider")]
+ internal class SliderGalleryTests : BaseTestFixture
+ {
+ // TODO: Detect Slider value changes
+ // TODO: Port to new conventions
+
+ public SliderGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.SliderGalleryLegacy);
+ }
+// void AllElementsPresent ()
+// {
+// var sliders = App.Query (PlatformQueries.Sliders);
+// Assert.AreEqual (3, sliders.Length);
+
+// App.Screenshot ("All Sliders present");
+// }
+
+ [Test]
+ [Description ("Slide all Sliders, test ValueChanged event")]
+ public void SliderGallerySlideAllSliders ()
+ {
+// AllElementsPresent ();
+
+// var sliders = App.Query (PlatformQueries.Sliders);
+// var sliderLeft = sliders[0].Rect.X;
+// var sliderRight = sliderLeft + sliders[0].Rect.Width - 5; // Needed to move 5 pixels left so that the drag would register
+// var topSliderY = sliders[0].Rect.CenterY;
+// var middleSliderY = sliders[1].Rect.CenterY;
+// var bottomSliderY = sliders[2].Rect.CenterY;
+
+// // Move top slider, numbers should change
+// App.DragFromTo (sliderLeft, topSliderY, sliderRight, topSliderY);
+// App.WaitForElement (q => q.Marked ("100"), "Timeout : 100");
+// App.Screenshot ("Move first slider right");
+
+// App.DragFromTo (sliderRight, topSliderY, sliderLeft, topSliderY);
+// App.WaitForElement (q => q.Marked ("20"), "Timeout : 20");
+// App.Screenshot ("Move first slider left");
+
+// // Move middle slider, shouldn't move
+// App.DragFromTo (sliderLeft, middleSliderY, sliderRight, middleSliderY);
+// App.WaitForElement (q => q.Marked ("20"), "Timeout : 20");
+// App.Screenshot ("Tried to move disabled slider");
+
+// // Move bottom slider, should move but nothing happens
+// App.DragFromTo (sliderLeft, bottomSliderY, sliderRight, bottomSliderY);
+// App.WaitForElement (q => q.Marked ("20"), "Timeout : 20");
+// App.Screenshot ("Move third slider right");
+
+// App.DragFromTo (sliderRight, bottomSliderY, sliderLeft, bottomSliderY);
+// App.WaitForElement (q => q.Marked ("20"), "Timeout : 20");
+// App.Screenshot ("Move first slider left");
+
+ }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+
+// [Test]
+// public void AllElementsPresentLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// AllElementsPresent ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Slide all Sliders - Landscape")]
+// public void SliderGallerySlideAllSlidersLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// SliderGallerySlideAllSliders ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-StackLayoutUITest.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-StackLayoutUITest.cs
new file mode 100644
index 00000000..b17c7ec8
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-StackLayoutUITest.cs
@@ -0,0 +1,76 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("StackLayout")]
+ internal class StackLayoutGalleryTests : BaseTestFixture
+ {
+ // TODO
+ // TODO: Port to new conventions
+
+ public StackLayoutGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.StackLayoutGalleryLegacy);
+ }
+
+// void AllElementsPresent ()
+// {
+// var buttons = new [] {
+// "Boring",
+// "Exciting!",
+// "Amazing!",
+// "Meh"
+// };
+
+// foreach (var button in buttons) {
+// App.WaitForElement (q => q.Button (button));
+// }
+
+// App.Screenshot ("All elements exist");
+// }
+
+ [Test]
+ [Description ("Check that each button is there and click them")]
+ public void StackLayoutGalleryClickEachButton ()
+ {
+// AllElementsPresent ();
+
+// App.Tap (q => q.Button ("Boring"));
+// App.WaitForElement (q => q.Button ("clicked1"), "Timeout : clicked1");
+
+// App.Tap (q => q.Button ("Exciting!"));
+// App.WaitForElement (q => q.Button ("clicked2"), "Timeout : clicked2");
+
+// App.Tap (q => q.Button ("Amazing!"));
+// App.WaitForElement (q => q.Button ("clicked3"), "Timeout : clicked3");
+
+// App.Tap (q => q.Button ("Meh"));
+// App.WaitForElement (q => q.Button ("clicked4"), "Timeout : clicked4");
+
+// App.Screenshot ("All buttons clicked");
+ }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+// [Test]
+// [Description ("Check that each button is there and click them - Landscape")]
+// public void StackLayoutGalleryClickEachButtonLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// StackLayoutGalleryClickEachButton ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-StepperUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-StepperUITests.cs
new file mode 100644
index 00000000..a468e310
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-StepperUITests.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NUnit.Framework;
+using System.Diagnostics;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Stepper")]
+ internal class StepperGalleryTests : BaseTestFixture
+ {
+ // TODO: Checking enabled / disabled states
+ // TODO: Port to new conventions
+
+ public StepperGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.StepperGalleryLegacy);
+ }
+
+ [Test]
+ [Description ("Check all elements exist")]
+ public void StepperGalleryAllElementsPresent ()
+ {
+// App.WaitForElement (PlatformQueries.LabelWithText ("0"));
+// var labels = App.Query (PlatformQueries.LabelWithText ("0"));
+// Assert.AreEqual (2, labels.Length);
+
+// var steppers = App.Query (PlatformQueries.Steppers);
+// Assert.AreEqual (2, steppers.Length);
+
+// App.Screenshot ("All elements exist");
+ }
+
+// [Test]
+// [Description ("Check that value changed event fires")]
+// public void StepperGalleryValueChangedEventTest ()
+// {
+// StepperGalleryAllElementsPresent ();
+// var labelText = "";
+// for (int i = 1; i <= 5; i++) {
+// App.Tap (PlatformQueries.StepperWithIndex (0));
+// App.Screenshot (string.Format ("Tapped first stepper {0} times", i));
+// App.WaitForElement (PlatformQueries.LabelWithText ((i*10).ToString ()));
+// labelText = App.GetTextForQuery (PlatformQueries.LabelWithText ((i*10).ToString ()));
+// Assert.AreEqual ((i*10).ToString (), labelText);
+// }
+
+// for (int i = 1; i <= 5; i++) {
+// App.Tap (PlatformQueries.StepperWithIndex (1));
+// App.Screenshot (string.Format ("Tapped second stepper {0} times", i));
+// App.WaitForElement (PlatformQueries.LabelWithText ((i*.05).ToString ()));
+// labelText = App.GetTextForQuery (PlatformQueries.LabelWithText ((i*.05).ToString ()));
+// Assert.AreEqual ((i*.05).ToString (), labelText);
+// }
+// }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+
+// [Test]
+// [Description ("Check all elements exist - Landscape")]
+// public void StepperGalleryAllElementsPresetLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// StepperGalleryAllElementsPresent ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Check that events fire - Landscape")]
+//// [Category ("Single")]
+// public void StepperGalleryEventTestLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// StepperGalleryValueChangedEventTest ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-SwitchUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-SwitchUITests.cs
new file mode 100644
index 00000000..67a23d88
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-SwitchUITests.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NUnit.Framework;
+using System.Diagnostics;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Switch")]
+ internal class SwitchGalleryTests : BaseTestFixture
+ {
+ // TODO: Checking enabled / disabled states
+ // TODO: Port to new conventions
+
+ public SwitchGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.SwitchGalleryLegacy);
+ }
+
+ [Test]
+ [Description ("Check all elements exist")]
+ public void SwitchGalleryAllElementsPresent ()
+ {
+// var label = App.Query (PlatformQueries.LabelWithText("Test Label"));
+// Assert.AreEqual (1, label.Length);
+
+// var switches = App.Query (q => q.Raw ("Switch"));
+// Assert.AreEqual (3, switches.Length);
+
+// var steppers = App.Query (PlatformQueries.Steppers);
+// Assert.AreEqual (1, steppers.Length);
+
+// App.Screenshot ("All elements exist");
+ }
+
+// [Test]
+// [Description ("Check that events fire")]
+//// [Category ("Single")]
+// public void SwitchGalleryEventTest ()
+// {
+// App.Tap (PlatformQueries.SwitchWithIndex (0));
+// App.Screenshot ("Toggled normal switch");
+// App.WaitForElement (PlatformQueries.LabelWithText ("Toggled normal switch"));
+// var labelText = App.GetTextForQuery (PlatformQueries.LabelWithText ("Toggled normal switch"));
+// Assert.AreEqual ("Toggled normal switch", labelText);
+
+// App.Tap (PlatformQueries.SwitchWithIndex (1));
+// App.Screenshot ("Tried to toggle disabled switch");
+// App.WaitForElement (PlatformQueries.LabelWithText ("Toggled normal switch"));
+// labelText = App.GetTextForQuery (PlatformQueries.LabelWithText ("Toggled normal switch"));
+// Assert.AreEqual ("Toggled normal switch", labelText);
+
+// App.Tap (PlatformQueries.SwitchWithIndex (2));
+// App.Screenshot ("Toggled transparent switch");
+// App.WaitForElement (PlatformQueries.LabelWithText ("Toggled transparent switch"));
+// labelText = App.GetTextForQuery (PlatformQueries.LabelWithText ("Toggled transparent switch"));
+// Assert.AreEqual ("Toggled transparent switch", labelText);
+
+// for (int i = 1; i <= 5; i++) {
+// App.Tap (PlatformQueries.Steppers);
+// App.Screenshot (string.Format ("Tapped stepper {0} times", i));
+// App.WaitForElement (PlatformQueries.LabelWithText (i.ToString ()));
+// labelText = App.GetTextForQuery (PlatformQueries.LabelWithText (i.ToString ()));
+// Assert.AreEqual (i.ToString (), labelText);
+// }
+// }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+
+// [Test]
+// [Description ("Check all elements exist - Landscape")]
+// public void SwitchGalleryAllElementsPresetLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// SwitchGalleryAllElementsPresent ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Check that events fire - Landscape")]
+//// [Category ("Single")]
+// public void SwitchGalleryEventTestLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// SwitchGalleryEventTest ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-TableViewUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-TableViewUITests.cs
new file mode 100644
index 00000000..5f9bd80c
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-TableViewUITests.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Runtime;
+using NUnit.Framework;
+using Xamarin.UITest;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("TableView")]
+ internal class TableViewGalleryTests : BaseTestFixture
+ {
+
+ // TODO: test sizes
+ // TODO: Port to new conventions
+
+ public TableViewGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.TableViewGalleryLegacy);
+ }
+
+ [Test]
+ [Description ("Elements of section header are present")]
+ public void TableViewGalleryHeader ()
+ {
+// App.WaitForElement (q => q.Marked ("Section One"), "Timeout : Section One");
+// App.Screenshot ("Header is present");
+ }
+
+// [Test]
+// [Description ("TableCells are present")]
+// public void TableViewGalleryTableCellsArePresent ()
+// {
+// var list = App.Query (PlatformQueries.Tables);
+// Assert.AreEqual (1, list.Length);
+// App.WaitForElement (q => q.Marked ("View Cell 1"), "Timeout : View Cell 1");
+// App.WaitForElement (q => q.Marked ("View Cell 2"), "Timeout : View Cell 2");
+
+// App.Screenshot ("TableCells are present");
+// }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+
+// [Test]
+// [Description ("Elements of CustomHeader are present - Landscape")]
+// public void TableViewGalleryCustomHeaderLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TableViewGalleryHeader ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("TableCells are present - Landscape")]
+// public void TableViewGalleryTableCellsArePresentLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TableViewGalleryTableCellsArePresent ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+ }
+}
+
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-TemplatedCarouselPageUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-TemplatedCarouselPageUITests.cs
new file mode 100644
index 00000000..f01641a5
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-TemplatedCarouselPageUITests.cs
@@ -0,0 +1,407 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+using System.Threading;
+using Xamarin.UITest.Queries;
+using System;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Templated")]
+ internal class TemplatedCarouselPageGalleryTests : BaseTestFixture
+ {
+ // TODO: Port to new conventions
+
+ public TemplatedCarouselPageGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.TemplatedCarouselPageGalleryLegacy);
+ }
+ //AppRect scrollContainerBounds = new AppRect ();
+
+// void AllElementsPresent ()
+// {
+// AllElementExistForPage (0);
+
+// App.Screenshot ("All elements found on page 0");
+
+// SwipeLeft ();
+
+// App.Screenshot ("Swiped left");
+
+// AllElementExistForPage (1);
+
+// App.Screenshot ("All elements found on page 1");
+// }
+
+ [Test]
+ [Description ("Insert page")]
+ public void TemplatedCarouselPageGalleryInsertPage ()
+ {
+// AllElementsPresent ();
+
+// App.Tap (q => q.Button ("Insert Tab: 1"));
+
+// SwipeLeft ();
+
+// AllElementExistForPage (2);
+// App.Screenshot ("At page 2");
+
+// SwipeRight ();
+
+// AllElementExistForPage (1);
+// App.Screenshot ("At page 1");
+
+// SwipeRight ();
+
+// AllElementExistForPage (0);
+// App.Screenshot ("At page 0");
+ }
+
+// [Test]
+// [Description ("Remove page")]
+// public void TemplatedCarouselPageGalleryRemovePage ()
+// {
+// AllElementsPresent ();
+
+// App.Tap (q => q.Button ("Remove Tab: 1"));
+
+// AllElementExistForPage (0);
+// App.Screenshot ("Removed page 1");
+// }
+
+// [Test]
+// [Description ("Insert / Remove page")]
+// public void TemplatedCarouselPageGalleryAddRemovePage ()
+// {
+// AllElementsPresent ();
+
+// App.Tap (q => q.Button ("Insert Tab: 1"));
+
+// SwipeLeft ();
+
+// AllElementExistForPage (2);
+// App.Screenshot ("At page 2");
+
+// App.Tap (q => q.Button ("Remove Tab: 2"));
+// AllElementExistForPage (0);
+// App.Screenshot ("Removed page 2");
+
+// SwipeLeft ();
+
+// App.Tap (q => q.Button ("Remove Tab: 1"));
+// AllElementExistForPage (0);
+// App.Screenshot ("Removed page 1");
+// }
+
+// [Test]
+// [Description ("Reset pages")]
+// public void TemplatedCarouselPageGalleryResetAllPages ()
+// {
+// AllElementsPresent ();
+
+// App.WaitForElement (q => q.Button ("Insert Tab: 1"));
+// App.Tap (q => q.Button ("Insert Tab: 1"));
+
+// SwipeLeft ();
+// AllElementExistForPage (2);
+// App.Tap (q => q.Button ("Insert Tab: 2"));
+
+// SwipeLeft ();
+// AllElementExistForPage (3);
+// App.Screenshot ("At page 3");
+
+// SwipeRight ();
+// App.Tap (q => q.Button ("Reset all tabs: 2"));
+
+// AllElementExistForPage (0);
+// App.Screenshot ("Pages reset");
+
+// SwipeLeft ();
+// AllElementExistForPage (1);
+// App.Screenshot ("On Page 1 again");
+
+// SwipeLeft ();
+// AllElementExistForPage (1);
+// App.Screenshot ("On Page 1 again");
+// }
+
+// [Test]
+// [Description ("Insert / go to next pages")]
+// public void TemplatedCarouselPageGalleryNextPage ()
+// {
+// TemplatedCarouselPageGalleryInsertPage ();
+
+// AppRect screenSize = App.MainScreenBounds ();
+// ScrollDownForQuery (q => q.Button ("Delayed reset: 0"), scrollContainerBounds);
+// App.Tap (q => q.Button ("Next Page: 0"));
+// AllElementExistForPage (1);
+// App.Screenshot ("At page 1");
+
+// ScrollDownForQuery (q => q.Button ("Delayed reset: 1"), scrollContainerBounds);
+// App.Tap (q => q.Button ("Next Page: 1"));
+// AllElementExistForPage (2);
+// App.Screenshot ("At page 2");
+
+// ScrollDownForQuery (q => q.Button ("Delayed reset: 2"), scrollContainerBounds);
+// App.Tap (q => q.Button ("Next Page: 2"));
+// AllElementExistForPage (0);
+// App.Screenshot ("At page 0");
+// }
+
+// [Test]
+// [Description ("Reproduction for a crash related to adding / reseting pages")]
+// public void TemplatedCarouselPageGalleryAddResetCrash ()
+// {
+// AllElementsPresent ();
+
+// SwipeRight ();
+
+// App.Tap (q => q.Button ("Insert Tab: 0"));
+// App.Tap (q => q.Button ("Insert Tab: 0"));
+// App.Screenshot ("Added two pages from Page 0");
+
+// SwipeLeft ();
+// App.Tap (q => q.Button ("Insert Tab: 3"));
+// App.Tap (q => q.Button ("Insert Tab: 3"));
+// App.Screenshot ("Added two pages from Page 3");
+
+// App.Tap (q => q.Button ("Reset all tabs: 3"));
+// AllElementExistForPage (0);
+// App.Screenshot ("Pages reset without crashing");
+// }
+
+// [Test]
+// [Description ("Reproduction for a crash related to adding / reseting pages")]
+// public void TemplatedCarouselPageGalleryAnotherAddResetCrash ()
+// {
+// AllElementsPresent ();
+
+// App.WaitForElement (q => q.Button ("Insert Tab: 1"));
+// App.Tap (q => q.Button ("Insert Tab: 1"));
+
+// SwipeLeft ();
+
+// AllElementExistForPage (2);
+// App.Screenshot ("At page 2");
+
+// App.Tap (q => q.Button ("Reset all tabs: 2"));
+// App.WaitForElement (q => q.Marked ("Insert Tab: 0"));
+// AllElementExistForPage (0);
+// }
+
+// [Test]
+// [Description ("Delayed reset of all content")]
+// public void TemplatedCarouselPageGalleryDelayResetAllElements ()
+// {
+// AllElementsPresent ();
+
+// App.ScrollDownForElement (q => q.Button ("Delayed reset: 1"), 2);
+// App.Tap (q => q.Button ("Delayed reset: 1"));
+
+// App.WaitForNoElement (q => q.Marked ("Lorem ipsum dolor sit amet #1"));
+// App.WaitForElement (q => q.Marked ("Insert Tab: 0"));
+// AllElementExistForPage (0);
+// }
+
+// [Test]
+// [Description ("Reproduction for a crash related to removing the first page")]
+// public void TemplatedCarouselPageGalleryRemoveFirstPageAndResetCrash ()
+// {
+// AllElementsPresent ();
+
+// SwipeRight ();
+// AllElementExistForPage (0);
+
+// App.Tap (q => q.Marked ("Remove Tab: 0"));
+// App.Screenshot ("Remove first page");
+
+// AllElementExistForPage (1);
+// App.Tap (q => q.Marked ("Reset all tabs: 1"));
+
+// AllElementExistForPage (0);
+// App.Screenshot ("Reset all pages");
+// }
+
+// void SwipeLeft ()
+// {
+
+// AppRect swipeLabelBounds = App.Query (q => q.Marked ("Swipe Here"))[0].Rect;
+// // Account for padded scrollview implementations on the different platforms
+// App.DragFromTo (
+// scrollContainerBounds.X + scrollContainerBounds.Width - PlatformValues.OffsetForScrollView,
+// swipeLabelBounds.CenterY,
+// scrollContainerBounds.X + PlatformValues.OffsetForScrollView,
+// swipeLabelBounds.CenterY
+// );
+// Thread.Sleep (2000);
+// }
+
+// void SwipeRight ()
+// {
+
+// AppRect swipeLabelBounds = App.Query (q => q.Marked ("Swipe Here"))[0].Rect;
+// // Account for padded scrollview implementations on the different platforms
+// App.DragFromTo (
+// scrollContainerBounds.X + PlatformValues.OffsetForScrollView,
+// swipeLabelBounds.CenterY,
+// scrollContainerBounds.X + scrollContainerBounds.Width - PlatformValues.OffsetForScrollView,
+// swipeLabelBounds.CenterY
+// );
+// Thread.Sleep (2000);
+// }
+
+// void ScrollDownForQuery (Func<AppQuery, AppQuery> query, AppRect scrollContainer)
+// {
+// AppRect screenSize = App.MainScreenBounds ();
+// float swipeY = scrollContainer.X + 5;
+// App.DragFromToForElement (5, query, swipeY, (2 / 3.0f) * screenSize.Height, swipeY, screenSize.Height / 3.0f);
+// }
+
+// void ScrollUpForQuery (Func<AppQuery, AppQuery> query, AppRect scrollContainer)
+// {
+// AppRect screenSize = App.MainScreenBounds ();
+// float swipeY = scrollContainer.X + 5;
+// App.DragFromToForElement (2, query, swipeY, screenSize.Height / 3.0f, swipeY, (2 / 3.0f) * screenSize.Height);
+// }
+
+
+// void AllElementExistForPage (int index)
+// {
+// var title = "Lorem ipsum dolor sit amet #" + index;
+// // Wait for element to load before querying its parent (problem on iOS)
+// if (App.Query (q => q.Marked (title)).Length < 1)
+// App.ScrollUpForElement (q => q.Marked (title), 3);
+// App.WaitForElement (q => q.Marked (title));
+// scrollContainerBounds = App.Query (q => q.Marked (title).Parent ())[2].Rect;
+
+// ScrollUpForQuery (q => q.Marked (title), scrollContainerBounds);
+
+// var buttons = new [] {
+// "Insert Tab: " + index,
+// "Change title: " + index,
+// "Remove Tab: " + index,
+// "Reset all tabs: " + index,
+// "Next Page: " + index,
+// "Delayed reset: " + index,
+// };
+
+// App.WaitForElement (q => q.Marked (title), "Timeout: " + title);
+
+// foreach (var button in buttons) {
+// if (App.Query (q => q.Button (button)).Length < 1)
+// ScrollDownForQuery (q=> q.Button (button), scrollContainerBounds);
+// App.WaitForElement (q => q.Button (button));
+// }
+// ScrollUpForQuery (q => q.Marked (title), scrollContainerBounds);
+// }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+
+// [Test]
+// [Description ("Insert page - Landscape")]
+// public void TemplatedCarouselPageGalleryInsertPageLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedCarouselPageGalleryInsertPage ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Remove page - Landscape")]
+// public void TemplatedCarouselPageGalleryRemovePageLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedCarouselPageGalleryRemovePage ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Insert / Remove page - Landscape")]
+// public void TemplatedCarouselPageGalleryAddRemovePageLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedCarouselPageGalleryAddRemovePage ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Reset pages - Landscape")]
+// public void TemplatedCarouselPageGalleryResetAllPagesLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedCarouselPageGalleryResetAllPages ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Insert / go to next pages - Landscape")]
+// public void TemplatedCarouselPageGalleryNextPageLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedCarouselPageGalleryNextPage ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Reproduction for a crash related to adding / reseting pages - Landscape")]
+// public void TemplatedCarouselPageGalleryAddResetCrashLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedCarouselPageGalleryAddResetCrash ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Reproduction for a crash related to adding / reseting pages - Landscape")]
+// public void TemplatedCarouselPageGalleryAnotherAddResetCrashLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedCarouselPageGalleryAnotherAddResetCrash ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Delayed reset of all content - Landscape")]
+// public void TemplatedCarouselPageGalleryDelayResetAllElementsLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedCarouselPageGalleryDelayResetAllElements ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Reproduction for a crash related to removing the first page - Landscape")]
+// public void TemplatedCarouselPageGalleryRemoveFirstPageAndResetCrashLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedCarouselPageGalleryRemoveFirstPageAndResetCrash ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-TemplatedTabPageUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-TemplatedTabPageUITests.cs
new file mode 100644
index 00000000..180c7bff
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-TemplatedTabPageUITests.cs
@@ -0,0 +1,346 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+using System;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Templated")]
+ internal class TemplatedTabPageGalleryTests : BaseTestFixture
+ {
+ // TODO
+ // TODO: Port to new conventions
+
+ public TemplatedTabPageGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.TemplatedTabbedPageGalleryLegacy);
+ }
+
+// void AllElementsExist ()
+// {
+// var labels = new [] {
+// "Lorem ipsum dolor sit amet #0",
+// "Page 0",
+// "Page 1",
+// };
+
+// foreach (var label in labels)
+// App.WaitForElement (q => q.Marked (label), "Timeout : " + label);
+
+// AllElementExistForPage (0);
+
+// App.Tap (q => q.Marked ("Page 1"));
+// AllElementExistForPage (1);
+
+// App.Screenshot ("All elements exist");
+// }
+
+ [Test]
+ [Description ("Insert tab")]
+ public void TemplatedTabPageGalleryInsertTab ()
+ {
+// AllElementsExist ();
+
+// App.Tap (q => q.Button ("Insert Tab: 1"));
+// App.WaitForElement (q => q.Marked ("Page 2"), "Timeout : Page 2");
+
+// App.Screenshot ("Page 2 added");
+
+// App.Tap (q => q.Marked ("Page 2"));
+// AllElementExistForPage (2);
+
+// App.Screenshot ("Page 2 selected");
+ }
+
+// [Test]
+// [Description ("Insert tab crash reproduction")]
+// public void TemplatedTabPageGalleryInsertTabCrash ()
+// {
+// TemplatedTabPageGalleryInsertTab ();
+// App.Tap (q => q.Marked ("Page 1"));
+// AllElementExistForPage (1);
+
+// App.Tap (q => q.Marked ("Page 0"));
+// AllElementExistForPage (0);
+// }
+
+// [Test]
+// [Description ("Change tab Title")]
+// public void TemplatedTabPageGalleryChangeTitles ()
+// {
+// AllElementsExist ();
+// App.Tap (q => q.Marked ("Change title: 1"));
+// App.WaitForNoElement (q => q.Marked ("Page 1"), "Timeout : Page 1");
+
+// // Change Page 1 title
+// for (int i = 0; i < 3; i++) {
+// App.WaitForElement (q => q.Marked ("Title: " + i), "Timeout : Title " + i);
+// App.Tap (q => q.Marked ("Change title: 1"));
+// }
+
+// App.Screenshot ("Page 1 titles changed");
+
+// // Change Page 0 title
+// App.Tap (q => q.Marked ("Page 0"));
+// App.Tap (q => q.Button ("Change title: 0"));
+// App.WaitForNoElement (q => q.Marked ("Page 0"), "Timeout : Page 0");
+
+// for (int i = 0; i < 3; i++) {
+// App.WaitForElement (q => q.Marked ("Title: " + i), "Timeout : Title " + i);
+// App.Tap (q => q.Button ("Change title: 0"));
+// }
+
+// App.Screenshot ("Page 0 titles changed");
+// }
+
+// [Test]
+// [Description ("Move tabs")]
+// public void TemplatedTabPageGalleryMoveTabs ()
+// {
+// AllElementsExist ();
+
+// int pageZeroTabIndex = App.IndexForElementWithText (PlatformQueries.Labels, "Page 0");
+// int pageOneTabIndex = App.IndexForElementWithText (PlatformQueries.Labels, "Page 1");
+
+// // Elements found
+// Assert.AreNotEqual (-1, pageZeroTabIndex);
+// Assert.AreNotEqual (-1, pageOneTabIndex);
+
+// Assert.Greater (pageOneTabIndex, pageZeroTabIndex);
+
+// App.Screenshot ("Tabs before move");
+
+// App.Tap (q => q.Button ("Move Tab: 1"));
+
+// int pageZeroMovedTabIndex = App.IndexForElementWithText (PlatformQueries.Labels, "Page 0");
+// int pageOneMovedTabIndex = App.IndexForElementWithText (PlatformQueries.Labels, "Page 1");
+
+// // Elements found
+// Assert.AreNotEqual (-1, pageZeroMovedTabIndex);
+// Assert.AreNotEqual (-1, pageOneMovedTabIndex);
+
+// Assert.Greater (pageZeroMovedTabIndex, pageOneMovedTabIndex);
+
+// App.Screenshot ("Tabs after move");
+// }
+
+// [Test]
+// [Description ("Remove tabs")]
+// public void TemplatedTabPageGalleryRemoveTabs ()
+// {
+// AllElementsExist ();
+
+// App.Tap (q => q.Button ("Remove Tab: 1"));
+// App.WaitForNoElement (q => q.Marked ("Page 1"), "Timeout : Page 1");
+
+// App.Screenshot ("Remove Page 1");
+// }
+
+// [Test]
+// [Description ("Add / remove tabs")]
+// public void TemplatedTabPageGalleryAddRemoveTabs ()
+// {
+// TemplatedTabPageGalleryInsertTab ();
+
+// App.Tap (q => q.Button ("Remove Tab: 2"));
+// App.WaitForNoElement (q => q.Marked ("Page 2"), "Timeout : Page 2");
+
+// App.Screenshot ("Remove Page 2");
+
+// App.Tap (q => q.Button ("Remove Tab: 0"));
+// App.WaitForNoElement (q => q.Marked ("Page 0"), "Timeout : Page 0");
+
+// App.Screenshot ("Remove Page 0");
+
+// AllElementExistForPage (1);
+// }
+
+// [Test]
+// [Description ("Reset tabs")]
+// public void TemplatedTabPageGalleryResetAllTabs ()
+// {
+// TemplatedTabPageGalleryChangeTitles ();
+
+// App.Tap (q => q.Button ("Insert Tab: 0"));
+// App.WaitForElement (q => q.Marked ("Page 2"), "Timeout : Page 2");
+
+// App.Screenshot ("Page 2 added");
+
+// App.Tap (q => q.Marked ("Page 2"));
+// AllElementExistForPage (2);
+
+// App.Screenshot ("Page 2 selected");
+
+// App.ScrollDownForElement (q => q.Button ("Reset all tabs: 2"), 3);
+// App.Tap (q => q.Button ("Reset all tabs: 2"));
+// App.WaitForElement (q => q.Marked ("Page 0"), "Timeout : Page 0");
+// App.WaitForElement (q => q.Marked ("Page 1"), "Timeout : Page 1");
+
+// var numberOfTabs = App.Query (q => q.Raw (PlatformStrings.Label + " {text BEGINSWITH 'Page'}")).Length;
+// Assert.AreEqual (2, numberOfTabs);
+
+// App.Screenshot ("Tabs reset");
+// }
+
+// [Test]
+// [Description ("Go to next tabs")]
+// public void TemplatedTabPageGalleryNextPage ()
+// {
+// TemplatedTabPageGalleryInsertTab ();
+
+// ScrollDownForQuery (q => q.Button ("Next Page: 2"));
+// App.Tap (q => q.Button ("Next Page: 2"));
+// AllElementExistForPage (0);
+// App.Screenshot ("On Page 0");
+
+// ScrollDownForQuery (q => q.Button ("Next Page: 0"));
+// App.Tap (q => q.Button ("Next Page: 0"));
+// AllElementExistForPage (1);
+// App.Screenshot ("On Page 1");
+
+// ScrollDownForQuery (q => q.Button ("Next Page: 1"));
+// App.Tap (q => q.Button ("Next Page: 1"));
+// AllElementExistForPage (2);
+// App.Screenshot ("On Page 2");
+
+// ScrollDownForQuery (q => q.Button ("Next Page: 2"));
+// App.Tap (q => q.Button ("Next Page: 2"));
+// AllElementExistForPage (0);
+// App.Screenshot ("On Page 0");
+// }
+
+// void AllElementExistForPage (int index)
+// {
+// var title = "Lorem ipsum dolor sit amet #" + index;
+
+// ScrollUpForQuery (q => q.Marked (title));
+
+// var buttons = new [] {
+// "Insert Tab: " + index,
+// "Change title: " + index,
+// "Move Tab: " + index,
+// "Remove Tab: " + index,
+// "Reset all tabs: " + index,
+// "Next Page: " + index,
+// };
+
+// App.WaitForElement (q => q.Marked (title));
+
+// foreach (var button in buttons)
+// ScrollDownForQuery (q => q.Button (button));
+
+// ScrollUpForQuery (q => q.Marked (title));
+// }
+
+// void ScrollDownForQuery (Func<AppQuery, AppQuery> query)
+// {
+// var screenBounds = App.MainScreenBounds ();
+// App.DragFromToForElement (2, query, screenBounds.Width - 10, (2 / 3.0f) * screenBounds.Height, screenBounds.Width - 10, screenBounds.Height / 3.0f);
+// }
+
+// void ScrollUpForQuery (Func<AppQuery, AppQuery> query)
+// {
+// var screenBounds = App.MainScreenBounds ();
+// App.DragFromToForElement (2, query, screenBounds.Width - 10, screenBounds.Height / 3.0f, screenBounds.Width - 10, (2 / 3.0f) * screenBounds.Height);
+// }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+
+// [Test]
+// [Description ("Insert tab - Landscape")]
+// public void TemplatedTabPageGalleryInsertTabLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedTabPageGalleryInsertTab ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Insert tab crash reproduction - Landscape")]
+// public void TemplatedTabPageGalleryInsertTabCrashLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedTabPageGalleryInsertTabCrash ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Change tab Title - Landscape")]
+// public void TemplatedTabPageGalleryChangeTitlesLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedTabPageGalleryChangeTitles ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Move tabs - Landscape")]
+// public void TemplatedTabPageGalleryMoveTabsLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedTabPageGalleryMoveTabs ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Remove tabs - Landscape")]
+// public void TemplatedTabPageGalleryRemoveTabLandscapes ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedTabPageGalleryRemoveTabs ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Add / remove tabs - Landscape")]
+// public void TemplatedTabPageGalleryAddRemoveTabsLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedTabPageGalleryAddRemoveTabs ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Reset tabs - Landscape")]
+// public void TemplatedTabPageGalleryResetAllTabsLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedTabPageGalleryResetAllTabs ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Go to next tabs - Landscape")]
+// public void TemplatedTabPageGalleryNextPageLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// TemplatedTabPageGalleryNextPage ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ToolbarGalleryUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ToolbarGalleryUITests.cs
new file mode 100644
index 00000000..ad00a191
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ToolbarGalleryUITests.cs
@@ -0,0 +1,51 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("ToolBar")]
+ internal class ToolbarGalleryTests : BaseTestFixture
+ {
+ // TODO - Is there a ToolBar item limit, test image only toolbar item
+ // TODO: Port to new conventions
+
+ public ToolbarGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.ToolbarGalleryLegacy);
+ }
+
+ //void AllElementsPresent ()
+ //{
+ // var elements = new [] { "One", "Two", "Three", "Four", "Click the toolbar" };
+ // foreach (var element in elements)
+ // App.WaitForElement (q => q.Marked (element));
+
+ // App.Screenshot ("All elements exist");
+ //}
+
+ [Test]
+ public void ToolbarGalleryToolbarAction ()
+ {
+ // AllElementsPresent ();
+
+ // var elements = new [] { "One", "Two", "Three", "Four" };
+ // foreach (var element in elements) {
+ // App.Tap (q => q.Marked (element));
+ // App.WaitForElement (q => q.Marked ("Activated: " + element));
+ // }
+
+ // App.Screenshot ("Toolbar commands fire");
+ }
+
+/*******************************************************/
+/**************** Landscape tests **********************/
+/*******************************************************/
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-UnevenListTests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-UnevenListTests.cs
new file mode 100644
index 00000000..b425545f
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-UnevenListTests.cs
@@ -0,0 +1,38 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Cells")]
+ internal class UnevenListTests : BaseTestFixture
+ {
+ public UnevenListTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.UnevenListGalleryLegacy);
+ }
+
+ [Test]
+ public void UnevenListCellTest ()
+ {
+ if (UnevenListTests.ShouldRunTest(RunningApp.App)) {
+ var element = App.Query (q => q.Marked ("unevenCellListGalleryDynamic").Descendant (("UITableViewCellContentView"))) [0];
+
+ Assert.GreaterOrEqual (element.Rect.Height, 100);
+ }
+ }
+
+ public static bool ShouldRunTest (IApp app)
+ {
+ var appAs = app as iOSApp;
+ return (appAs != null && appAs.Device.IsPhone);
+ }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-UnevenViewCellUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-UnevenViewCellUITests.cs
new file mode 100644
index 00000000..1b826ec0
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-UnevenViewCellUITests.cs
@@ -0,0 +1,94 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Cells")]
+ internal class UnevenViewCellGalleryTests : BaseTestFixture
+ {
+ // TODO
+ // TODO: Port to new conventions
+
+ public UnevenViewCellGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.UnevenViewCellGalleryLegacy);
+ }
+// void AllElementsPresent ()
+// {
+// App.WaitForElement (q => q.Marked ("Testing"), "Timeout : Testing");
+// App.WaitForElement (PlatformQueries.Map, "Timeout : Map");
+// App.Screenshot ("All elements exist");
+// }
+
+ [Test]
+ [Description ("All views exist")]
+ public void UnevenViewCellGalleryScrollDownForAllElements ()
+ {
+// AllElementsPresent ();
+
+// var window = App.Query (q => q.Raw ("*")) [0];
+// var windowWidth = window.Rect.Width;
+// var windowHeight = window.Rect.Height;
+
+// App.DragFromToForElement (20, q => q.Marked ("1 day"), windowWidth - 100, windowHeight - 100, windowWidth - 100, windowHeight / 2);
+// App.DragFromToForElement (20, q => q.Marked ("2 days"), windowWidth - 100, windowHeight - 100, windowWidth - 100, windowHeight / 2);
+// App.DragFromToForElement (20, q => q.Marked ("3 days"), windowWidth - 100, windowHeight - 100, windowWidth - 100, windowHeight / 2);
+// App.DragFromToForElement (20, q => q.Marked ("4 days"), windowWidth - 100, windowHeight - 100, windowWidth - 100, windowHeight / 2);
+// App.DragFromToForElement (20, q => q.Marked ("5 days"), windowWidth - 100, windowHeight - 100, windowWidth - 100, windowHeight / 2);
+
+// App.Screenshot ("All views exist");
+ }
+
+// [Test]
+// [Description ("Check uneven ViewCell sizes")]
+// public void UnevenViewCellGalleryCheckViewCellSizes ()
+// {
+// AllElementsPresent ();
+
+// var window = App.Query (q => q.Raw ("*")) [0];
+// var windowWidth = window.Rect.Width;
+// var windowHeight = window.Rect.Height;
+
+// var unevenCellHeight = App.Query (PlatformQueries.Map) [0].Rect.Height;
+
+// App.DragFromToForElement (20, q => q.Marked ("1 day"), windowWidth - 100, windowHeight - 100, windowWidth - 100, windowHeight / 2);
+
+// var evenCellHeight = App.Query (q => q.Marked ("1 day")) [0].Rect.Height;
+
+// Assert.Greater (unevenCellHeight, evenCellHeight);
+// }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+
+// [Test]
+// [Description ("All views exist - Landscape")]
+// public void UnevenViewCellGalleryScrollDownForAllElementsLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// UnevenViewCellGalleryScrollDownForAllElements ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+// [Test]
+// [Description ("Check uneven ViewCell sizes - Landscape")]
+// public void UnevenViewCellGalleryCheckViewCellSizesLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// UnevenViewCellGalleryCheckViewCellSizes ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ViewCellUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ViewCellUITests.cs
new file mode 100644
index 00000000..c6a79e71
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/Legacy-ViewCellUITests.cs
@@ -0,0 +1,66 @@
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Cells")]
+ internal class ViewCellGalleryTests : BaseTestFixture
+ {
+// // TODO
+ // TODO: Port to new conventions
+
+ public ViewCellGalleryTests ()
+ {
+ ShouldResetPerFixture = false;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.ViewCellGalleryLegacy);
+ }
+
+// public void AllElementsPresent ()
+// {
+// App.WaitForElement (q => q.Marked ("Testing"), "Timeout : Testing");
+// App.WaitForElement (q => q.Marked ("0"), "Timeout : 0");
+// App.WaitForElement (q => q.Marked ("BrandLabel"), "Timeout : BrandLabel");
+
+// App.Screenshot ("All elements exist");
+// }
+
+ [Test]
+ [UiTest (typeof(ViewCell))]
+ [Description ("All elements exist")]
+ public void ViewCellGalleryScrollDownForAllElements ()
+ {
+// AllElementsPresent ();
+
+// App.ScrollForElement ("* marked:'0'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+// App.ScrollForElement ("* marked:'1'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+// App.ScrollForElement ("* marked:'2'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+// App.ScrollForElement ("* marked:'3'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+// App.ScrollForElement ("* marked:'4'", new Drag (ScreenBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium));
+
+// App.Screenshot ("All ViewCells exist");
+ }
+
+///*******************************************************/
+///**************** Landscape tests **********************/
+///*******************************************************/
+
+// [Test]
+// [Description ("All elements exist - Landscape")]
+// public void ViewCellGalleryScrollDownForAllElementsLandscape ()
+// {
+// App.SetOrientationLandscape ();
+// App.Screenshot ("Rotated to Landscape");
+// ViewCellGalleryScrollDownForAllElements ();
+// App.SetOrientationPortrait ();
+// App.Screenshot ("Rotated to Portrait");
+// }
+
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/PickerUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/PickerUITests.cs
new file mode 100644
index 00000000..19357fad
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/PickerUITests.cs
@@ -0,0 +1,54 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Picker")]
+ internal class PickerUITests : _ViewUITests
+ {
+ public PickerUITests ()
+ {
+ PlatformViewType = Views.Picker;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.PickerGallery);
+ }
+
+ // TODO
+ public override void _Focus () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _GestureRecognizers () {}
+
+ // TODO
+ public override void _IsFocused () {}
+
+ // TODO
+ public override void _UnFocus () {}
+
+ // TODO
+ // Implement control specific ui tests
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/ProgressBarUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/ProgressBarUITests.cs
new file mode 100644
index 00000000..5d95145c
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/ProgressBarUITests.cs
@@ -0,0 +1,56 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("ProgressBar")]
+ internal class ProgressBarUITests : _ViewUITests
+ {
+ public ProgressBarUITests ()
+ {
+ PlatformViewType = Views.ProgressBar;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.ProgressBarGallery);
+ }
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _Focus () {}
+
+ // TODO
+ public override void _GestureRecognizers () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsFocused () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _UnFocus () {}
+
+ // TODO
+ // Implement control specific ui tests
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsEnabled () {}
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/RootGalleryUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/RootGalleryUITests.cs
new file mode 100644
index 00000000..764c3a69
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/RootGalleryUITests.cs
@@ -0,0 +1,88 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+
+using System;
+using System.Threading;
+using System.Collections.Generic;
+using System.Linq;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal sealed class RootPageModel
+ {
+ public string ButtonId { get; private set; }
+ public string PageId { get; private set; }
+ public bool IsModal { get; private set; }
+
+ public RootPageModel (string buttonId, string pageID, bool isModal = false)
+ {
+ ButtonId = buttonId;
+ PageId = pageID;
+ IsModal = isModal;
+ }
+ }
+
+ [TestFixture]
+ [Category ("RootGallery")]
+ internal class RootGalleryUITests : BaseTestFixture
+ {
+ IEnumerable<RootPageModel> rootPages;
+
+ public RootGalleryUITests ()
+ {
+ string[] ids = {
+ "Content",
+ "Nav->Content",
+ "MDP->Nav->Content",
+ "Tab->Content",
+ "Tab->MDP->Nav->Content",
+ "Tab->Nav->Content",
+ "Tab(Many)->Nav->Content",
+ "Nav->Tab->Content(BAD IDEA)",
+ "Nav->Tab(Many)->Content(BAD IDEA)",
+ "MDP->Nav->Tab->Content(BAD IDEA)"
+ };
+ string[] modalIds = {
+ "(Modal)Content",
+ "(Modal)Nav->Content",
+ "(Modal)MDP->Nav->Content",
+ "(Modal)Tab->Content",
+ "(Modal)Tab->MDP->Nav->Content",
+ "(Modal)Tab->Nav->Content",
+ "(Modal)Tab(Many)->Nav->Content",
+ "(Modal)Nav->Tab->Content(BAD IDEA)",
+ "(Modal)Nav->Tab(Many)->Content(BAD IDEA)",
+ "(Modal)MDP->Nav->Tab->Content(BAD IDEA)",
+ };
+
+ rootPages =
+ (from id in ids
+ select new RootPageModel (id + "ButtonId", id + "PageId")).Union (
+ from id in modalIds
+ select new RootPageModel (id + "ButtonId", id + "PageId",true));
+
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.RootPagesGallery);
+ }
+
+ [Test]
+ [Ignore("Ignore while we dont't have a response from XTC team why this fails some times")]
+ public void VisitEachPage ()
+ {
+ foreach (var page in rootPages) {
+ var scrollViewArea = App.Query (q => q.Marked ("ChoosePageScrollView")).First ().Rect;
+ App.ScrollForElement (string.Format("* marked:'{0}'", page.ButtonId), new Drag (scrollViewArea, Drag.Direction.BottomToTop, Drag.DragLength.Long));
+ App.Tap (q => q.Marked (page.ButtonId));
+ if(!page.IsModal || App is iOSApp)
+ App.WaitForElement (q => q.Marked (page.PageId));
+ App.Screenshot ("Page: " + page.PageId);
+ }
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/ScrollViewUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/ScrollViewUITests.cs
new file mode 100644
index 00000000..ed75fa43
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/ScrollViewUITests.cs
@@ -0,0 +1,68 @@
+using NUnit.Framework;
+using Xamarin.UITest;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("ScrollView")]
+ internal class ScrollViewGalleryTests : BaseTestFixture
+ {
+ public ScrollViewGalleryTests ()
+ {
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.ScrollViewGallery);
+ }
+
+ [Test]
+ [Description ("Scroll element to the start")]
+ public void ScrollToElement1Start ()
+ {
+ var scroller = App.Query (c => c.Marked ("thescroller"))[0];
+ //need to extract the contentOffset on iOS
+ App.Tap(c=> c.Marked("Start"));
+ App.WaitForElement (c => c.Marked ("the scrollto button"));
+ //Assert.Equals (App.Query (c => c.Marked ("the before")).Length, 0);
+ App.Screenshot ("Element is on the top");
+ }
+
+ [Test]
+ [Description ("Scroll element to the center")]
+ public void ScrollToElement2Center ()
+ {
+ App.Tap(c=> c.Marked("Center"));
+ App.WaitForElement (c => c.Marked ("the scrollto button"));
+ App.WaitForElement (c => c.Marked ("the before"));
+ App.WaitForElement (c => c.Marked ("the after"));
+ App.Screenshot ("Element is in the center");
+ }
+
+ [Test]
+ [Description ("Scroll element to the end")]
+ public void ScrollToElement3End ()
+ {
+ App.Tap(c=> c.Marked("End"));
+ App.WaitForElement (c => c.Marked ("the scrollto button"));
+ //Assert.Equals (App.Query (c => c.Marked ("the after")).Length, 0);
+ App.Screenshot ("Element is in the end");
+ }
+
+ [Test]
+ [Description ("ScrollTo Y = 100")]
+ public void ScrollToY ()
+ {
+ App.Tap(c=> c.Marked("Scroll to 100"));
+ }
+
+ [Test]
+ [Description ("ScrollTo Y = 100 no animation")]
+ public void ScrollToYNoAnim ()
+ {
+ App.ScrollDown ();
+ App.ScrollDown ();
+ App.Tap (c => c.Marked ("Scroll to 100 no anim"));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/SearchBarUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/SearchBarUITests.cs
new file mode 100644
index 00000000..e45ba385
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/SearchBarUITests.cs
@@ -0,0 +1,54 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("SearchBar")]
+ internal class SearchBarUITests : _ViewUITests
+ {
+ public SearchBarUITests ()
+ {
+ PlatformViewType = Views.SearchBar;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.SearchBarGallery);
+ }
+
+ // TODO
+ public override void _Focus () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _GestureRecognizers () {}
+
+ // TODO
+ public override void _IsFocused () {}
+
+ // TODO
+ public override void _UnFocus () {}
+
+ // TODO
+ // Implement control specific ui tests
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/SliderUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/SliderUITests.cs
new file mode 100644
index 00000000..6f8eb775
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/SliderUITests.cs
@@ -0,0 +1,54 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Slider")]
+ internal class SliderUITests : _ViewUITests
+ {
+ public SliderUITests ()
+ {
+ PlatformViewType = Views.Slider;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.SliderGallery);
+ }
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _Focus () {}
+
+ // TODO
+ public override void _GestureRecognizers () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsFocused () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _UnFocus () {}
+
+ // TODO
+ // Implement control specific ui tests
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/StepperUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/StepperUITests.cs
new file mode 100644
index 00000000..bec1e22e
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/StepperUITests.cs
@@ -0,0 +1,54 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Stepper")]
+ internal class StepperUITests : _ViewUITests
+ {
+ public StepperUITests ()
+ {
+ PlatformViewType = Views.Stepper;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.StepperGallery);
+ }
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _Focus () {}
+
+ // TODO
+ public override void _GestureRecognizers () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsFocused () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _UnFocus () {}
+
+ // TODO
+ // Implement control specific ui tests
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/SwitchUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/SwitchUITests.cs
new file mode 100644
index 00000000..344aae4a
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/SwitchUITests.cs
@@ -0,0 +1,54 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("Switch")]
+ internal class SwitchUITests : _ViewUITests
+ {
+ public SwitchUITests ()
+ {
+ PlatformViewType = Views.Switch;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.SwitchGallery);
+ }
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _Focus () {}
+
+ // TODO
+ public override void _GestureRecognizers () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _IsFocused () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _UnFocus () {}
+
+ // TODO
+ // Implement control specific ui tests
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/TimePickerUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/TimePickerUITests.cs
new file mode 100644
index 00000000..63e6a29e
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/TimePickerUITests.cs
@@ -0,0 +1,56 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("TimePicker")]
+ internal class TimePickerUITests : _ViewUITests
+ {
+ public TimePickerUITests ()
+ {
+ PlatformViewType = Views.TimePicker;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.TimePickerGallery);
+
+ Thread.Sleep (4000);
+ }
+
+ // TODO
+ public override void _Focus () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction")]
+ public override void _GestureRecognizers () {}
+
+ // TODO
+ public override void _IsFocused () {}
+
+ // TODO
+ public override void _UnFocus () {}
+
+ // TODO
+ // Implement control specific ui tests
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/ToolbarItemTests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/ToolbarItemTests.cs
new file mode 100644
index 00000000..ce846db9
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/ToolbarItemTests.cs
@@ -0,0 +1,102 @@
+using System;
+using NUnit.Framework;
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("ToolbarItem")]
+ internal class ToolbarItemTests : BaseTestFixture
+ {
+ string btn1Id = "tb1";
+ string btn4Id = "tb4";
+
+ static bool isSecondaryMenuOpen = false;
+ static void ShouldShowMenu ()
+ {
+ if (App is AndroidApp) {
+ isSecondaryMenuOpen = true;
+ //show secondary menu
+ App.Tap (c => c.Class ("android.support.v7.widget.ActionMenuPresenter$OverflowMenuButton"));
+ }
+ }
+
+ static void ShouldHideMenu ()
+ {
+ if (App is AndroidApp && isSecondaryMenuOpen) {
+ isSecondaryMenuOpen = false;
+ App.Back ();
+ }
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.ToolbarItemGallery);
+ if (App is iOSApp) {
+ btn1Id = "menuIcon";
+ btn4Id = "tb4";
+ }
+ }
+
+ [Test]
+ public void ToolbarButtonsClick ()
+ {
+ ShouldHideMenu ();
+ App.Tap (c => c.Marked (btn1Id));
+ }
+
+ [Test]
+ public void ToolbarButtonsCommand ()
+ {
+ ShouldShowMenu ();
+ if (App is AndroidApp) {
+ var btn = App.Query (c => c.Marked (btn4Id))[0];
+ }
+ else {
+ App.Tap (c => c.Marked (btn4Id));
+ }
+ }
+
+ [Test]
+ public void ToolbarButtonsDisable ()
+ {
+ ShouldHideMenu ();
+ var btn1 = App.Query (c => c.Marked (btn1Id)) [0];
+ ShouldShowMenu ();
+ var btn2 = App.Query (c => c.Marked (btn4Id)) [0];
+ Assert.False (btn1.Enabled, "Toolbar Item should be disable");
+ //TODO: how to check Enable for the textview
+ //Assert.False (btn2.Enabled, "Toolbar Item should be disable");
+ }
+
+ [Test]
+ public void ToolbarButtonsExist ()
+ {
+ ShouldHideMenu ();
+ var existsPrimary = App.Query (c => c.Marked (btn1Id)).Length;
+ var existsPrimary2 = App.Query (c => c.Marked ("tb2")).Length;
+ ShouldShowMenu ();
+ var existsSecondary = App.Query (c => c.Marked ("tb3")).Length;
+ var existsSecondary2 = App.Query (c => c.Marked (btn4Id)).Length;
+ Assert.True (existsPrimary > 0, "Toolbar Item 1 no name, not found");
+ Assert.True (existsPrimary2 > 0, "Toolbar Item 2, not found");
+ Assert.True (existsSecondary > 0, "Toolbar Item 1 no name, not found");
+ Assert.True (existsSecondary2 > 0, "Toolbar Item 1, not found");
+ }
+
+ [Test]
+ public void ToolbarButtonsOrder ()
+ {
+ ShouldHideMenu ();
+ var btn1 = App.Query (c => c.Marked (btn1Id)) [0];
+ ShouldShowMenu ();
+ var btn2 = App.Query (c => c.Marked ("tb4")) [0];
+ if(App is iOSApp)
+ Assert.True (btn1.Rect.CenterY < btn2.Rect.CenterY);
+ }
+
+ }
+}
+
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/ViewUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/ViewUITests.cs
new file mode 100644
index 00000000..a11d1f66
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/ViewUITests.cs
@@ -0,0 +1,257 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Net.Configuration;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal abstract class _ViewUITests : BaseTestFixture
+ {
+ /* Under score prefixes ensure inherited properties run first in test suite */
+ //[Test]
+ //[Category ("View")]
+ //[UiTestBroken (BrokenReason.UITestBug, "Issue #115 - when trying to get anchorPoint, iOS")]
+ //[UiTest (Test.VisualElement.AnchorX)]
+ public virtual void _AnchorX ()
+ {
+ //var remote = RemoteFactory.CreateRemote<StateViewContainerRemote> (App, "AnchorX", PlatformViewType);
+ //remote.GoTo ();
+
+ ////App.LogPropertiesForView (remote.ViewQuery, true);
+
+ //if (App is AndroidApp) {
+ // var anchorX = remote.GetProperty<float> (View.AnchorXProperty);
+ // var viewWidth = remote.GetView ().Rect.Width;
+ // Assert.AreEqual (anchorX, 0.25 * viewWidth);
+ //} else if (App is iOSApp) {
+ // var anchorXMatrix = remote.GetProperty<Matrix> (View.AnchorXProperty);
+ // var viewWidth = remote.GetView ().Rect.Width;
+ // Assert.AreEqual (anchorXMatrix.M30, 0 - (viewWidth * 0.25f));
+ //}
+ }
+
+ // [Test]
+ // [UiTest (Test.VisualElement.AnchorY)]
+ // TODO: working on some views, others not
+ public virtual void _AnchorY ()
+ {
+ //var remote = RemoteFactory.CreateRemote<StateViewContainerRemote> (App, "AnchorY", PlatformViewType);
+ //remote.GoTo ();
+
+ //if (App is AndroidApp) {
+ // var anchorY = remote.GetProperty<float> (View.AnchorYProperty);
+ // var viewHeight = remote.GetView ().Rect.Height;
+ // Assert.AreEqual (anchorY, viewHeight);
+ //} else if (App is iOSApp) {
+ // var anchorYMatrix = remote.GetProperty<Matrix> (View.AnchorYProperty);
+ // var viewHeight = remote.GetView ().Rect.Height;
+ // Assert.AreEqual (anchorYMatrix.M31, viewHeight / 2.0f);
+ //}
+ }
+
+ // [Test]
+ // [UiTest (Test.VisualElement.BackgroundColor)]
+ // [UiTestBroken (BrokenReason.UITestBug, "UITest Issue #107")]
+ public virtual void _BackgroundColor ()
+ {
+ //TODO: this was failing and is changing in next version of calabash (UI-Test-pre nuget) to a json rgb
+// var remote = RemoteFactory.CreateRemote<ViewContainerRemote> (App, "BackgroundColor", PlatformViewType);
+// remote.GoTo ();
+// if (App is iOSApp) {
+// var backgroundColor = remote.GetProperty<Color> (View.BackgroundColorProperty);
+// Assert.AreEqual (Color.Blue, backgroundColor);
+// }
+
+ }
+
+ [Test]
+ [UiTest (typeof(VisualElement), "Focus")]
+ public abstract void _Focus ();
+
+ [Test]
+ [UiTest (typeof (VisualElement), "GestureRecognizers")]
+ public abstract void _GestureRecognizers ();
+
+ //[Test]
+ [UiTest (typeof (VisualElement), "InputTransparent")]
+ public virtual void _InputTransparent ()
+ {
+ //var remote = new LayeredViewContainerRemote (App, Test.VisualElement.InputTransparent, PlatformViewType);
+ //remote.GoTo ();
+
+ //var hiddenButtonClickedLabelTextPre = remote.GetLayeredLabel ().Text;
+ //Assert.AreEqual ("Hidden Button (Not Clicked)", hiddenButtonClickedLabelTextPre);
+
+ //remote.TapHiddenButton ();
+
+ //var hiddenButtonClickedLabelTextPost = remote.GetLayeredLabel ().Text;
+ //var hiddenButtonClicked = hiddenButtonClickedLabelTextPost == "Hidden Button (Clicked)";
+
+ //// Allow tests to continue by dismissing DatePicker that should not show
+ //// Remove when InputTransparency works
+ //if (!hiddenButtonClicked && PlatformViewType == PlatformViews.DatePicker)
+ // remote.DismissPopOver ();
+
+ //Assert.True (hiddenButtonClicked);
+ }
+
+ [Test]
+ [UiTest (typeof (VisualElement), "IsEnabled")]
+ public virtual void _IsEnabled ()
+ {
+ var propName = Test.VisualElement.IsEnabled.ToString ();
+ var remote = new StateViewContainerRemote (App, Test.VisualElement.IsEnabled, PlatformViewType);
+ remote.GoTo ();
+
+ var enabled = remote.GetProperty<bool> (View.IsEnabledProperty);
+ Assert.IsTrue (enabled);
+
+ remote.TapStateButton ();
+
+ enabled = remote.GetProperty<bool> (View.IsEnabledProperty);
+ Assert.IsFalse (enabled);
+
+ remote.TapStateButton ();
+
+ var isEnabled = remote.GetStateLabel ().Text;
+ Assert.AreEqual ("True", isEnabled);
+
+ remote.TapStateButton ();
+
+ var isDisabled = remote.GetStateLabel ().Text;
+ Assert.AreEqual ("False", isDisabled);
+ }
+
+ [Test]
+ [UiTest (typeof (VisualElement), "IsFocused")]
+ public abstract void _IsFocused ();
+
+ [Test]
+ [UiTest (typeof (VisualElement), "IsVisible")]
+ public virtual void _IsVisible ()
+ {
+ var remote = new StateViewContainerRemote (App, Test.VisualElement.IsVisible, PlatformViewType);
+ remote.GoTo ();
+
+ var viewPre = remote.GetViews ();
+
+ Assert.AreEqual (1, viewPre.Length);
+
+ remote.TapStateButton ();
+
+ var viewPost = remote.GetViews ();
+
+ Assert.AreEqual (0, viewPost.Length);
+ }
+
+ [UiTestExemptAttribute (ExemptReason.None, "Not sure how to test at the moment")]
+ public virtual void _Layout (){}
+
+ [UiTestExemptAttribute (ExemptReason.None, "Not sure how to test at the moment")]
+ public virtual void _Navigation () {}
+
+ [Test]
+ [UiTest (typeof (VisualElement), "Opacity")]
+ public virtual void _Opacity ()
+ {
+ var remote = new ViewContainerRemote (App, Test.VisualElement.Opacity, PlatformViewType);
+ remote.GoTo ();
+
+ float opacity = -1f;
+ opacity = remote.GetProperty<float> (View.OpacityProperty);
+ Assert.AreEqual (0.5f, opacity);
+ }
+
+ [Test]
+ [UiTest (typeof(VisualElement), "Rotation")]
+ [UiTestBroken (BrokenReason.CalabashBug, "Calabash bug")]
+ public virtual void _Rotation ()
+ {
+ var remote = new ViewContainerRemote (App, Test.VisualElement.Rotation, PlatformViewType);
+ remote.GoTo ();
+
+ if (App is AndroidApp) {
+ var rotation = remote.GetProperty<float> (View.RotationProperty);
+ Assert.AreEqual (10.0f, rotation);
+ } else if (App is iOSApp) {
+ var rotationMatrix = remote.GetProperty<Matrix> (View.RotationProperty);
+ Matrix generatedMatrix = NumericExtensions.CalculateRotationMatrixForDegrees (10, Axis.Z);
+ Assert.AreEqual (generatedMatrix, rotationMatrix);
+ }
+ }
+
+ [Test]
+ [UiTest (typeof (VisualElement), "RotationX")]
+ public virtual void _RotationX ()
+ {
+ var remote = new ViewContainerRemote (App, Test.VisualElement.RotationX, PlatformViewType);
+ remote.GoTo ();
+
+ if (App is AndroidApp) {
+ var rotationX = remote.GetProperty<float> (View.RotationXProperty);
+ Assert.AreEqual (33.0f, rotationX);
+ } else if (App is iOSApp) {
+ var rotationXMatrix = remote.GetProperty<Matrix> (View.RotationXProperty);
+ Matrix matrix = NumericExtensions.CalculateRotationMatrixForDegrees (33.0f, Axis.X);
+ Assert.AreEqual (matrix, rotationXMatrix);
+ }
+ }
+
+ [Test]
+ [UiTest (typeof (VisualElement), "RotationY")]
+ public virtual void _RotationY ()
+ {
+ var remote = new ViewContainerRemote (App, Test.VisualElement.RotationY, PlatformViewType);
+ remote.GoTo ();
+
+ if (App is AndroidApp) {
+ var rotationY = remote.GetProperty<float> (View.RotationYProperty);
+ Assert.AreEqual (10.0f, rotationY);
+ } else if (App is iOSApp) {
+ var rotationYMatrix = remote.GetProperty<Matrix> (View.RotationYProperty);
+ Matrix matrix = NumericExtensions.CalculateRotationMatrixForDegrees (10.0f, Axis.Y);
+ Assert.AreEqual (matrix, rotationYMatrix);
+ }
+ }
+
+ [Test]
+ [UiTest (typeof (VisualElement), "Scale")]
+ public virtual void _Scale ()
+ {
+ var remote = new ViewContainerRemote (App, Test.VisualElement.Scale, PlatformViewType);
+ remote.GoTo ();
+
+ var scaleMatrix = remote.GetProperty<Matrix> (View.ScaleProperty);
+ Matrix generatedMatrix = NumericExtensions.BuildScaleMatrix (0.5f);
+ Assert.AreEqual (generatedMatrix, scaleMatrix);
+ }
+
+ [Test]
+ [UiTest (typeof (VisualElement), "TranslationX")]
+ [Category ("ManualReview")]
+ public virtual void _TranslationX ()
+ {
+ var remote = new ViewContainerRemote (App, Test.VisualElement.TranslationX, PlatformViewType);
+ remote.GoTo ();
+ }
+
+ [Test]
+ [UiTest (typeof (VisualElement), "TranslationY")]
+ [Category ("ManualReview")]
+ public virtual void _TranslationY ()
+ {
+ var remote = new ViewContainerRemote (App, Test.VisualElement.TranslationY, PlatformViewType);
+ remote.GoTo ();
+ }
+
+ [Test]
+ [UiTest (typeof (VisualElement), "Unfocus")]
+ public abstract void _UnFocus ();
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Tests/WebViewUITests.cs b/Xamarin.Forms.Core.iOS.UITests/Tests/WebViewUITests.cs
new file mode 100644
index 00000000..d4233cba
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Tests/WebViewUITests.cs
@@ -0,0 +1,93 @@
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.iOS;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ [TestFixture]
+ [Category ("WebView")]
+ internal class WebViewUITests : _ViewUITests
+ {
+ public WebViewUITests ()
+ {
+ PlatformViewType = Views.WebView;
+ }
+
+ protected override void NavigateToGallery ()
+ {
+ App.NavigateToGallery (GalleryQueries.WebViewGallery);
+ }
+
+ [Category ("ManualReview")]
+ public override void _IsEnabled ()
+ {
+ Assert.Inconclusive ("Does not make sense for WebView");
+ }
+
+ [Test]
+ [Category ("ManualReview")]
+ public override void _IsVisible () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction with Label")]
+ public override void _Focus () {}
+
+ // TODO
+ public override void _GestureRecognizers () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction with Label")]
+ public override void _IsFocused () {}
+
+ [Test]
+ [Category ("ManualReview")]
+ public override void _Opacity () {}
+
+ [Test]
+ [Category ("ManualReview")]
+ public override void _Rotation () {}
+
+ [Test]
+ [Category ("ManualReview")]
+ public override void _RotationX () {}
+
+ [Test]
+ [Category ("ManualReview")]
+ public override void _RotationY () {}
+
+
+ [Test]
+ [Category ("ManualReview")]
+ public override void _TranslationX () {}
+
+ [Test]
+ [Category ("ManualReview")]
+ public override void _TranslationY () {}
+
+ [Test]
+ [Category ("ManualReview")]
+ public override void _Scale () {}
+
+ [UiTestExempt (ExemptReason.CannotTest, "Invalid interaction with Label")]
+ public override void _UnFocus () {}
+
+ // TODO
+ // Implement control specific ui tests
+
+ protected override void FixtureTeardown ()
+ {
+ App.NavigateBack ();
+ base.FixtureTeardown ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/AppExtensions.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/AppExtensions.cs
new file mode 100644
index 00000000..c6f2508c
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/AppExtensions.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+using NUnit.Framework;
+
+using Xamarin.UITest;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.iOS;
+using Xamarin.UITest.Queries;
+using System.Text.RegularExpressions;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal static class AppExtensions
+ {
+ public static AppRect ScreenBounds (this IApp app)
+ {
+ return app.Query (Queries.Root ()).First().Rect;
+ }
+
+ public static void NavigateBack (this IApp app)
+ {
+ app.Tap (Queries.NavigationBarBackButton ());
+ }
+
+ public static void NavigateToGallery (this IApp app, string page)
+ {
+ var text = Regex.Match (page, "'(?<text>[^']*)'").Groups["text"].Value;
+ app.EnterText (q => q.Raw ("* marked:'SearchBar'"), text);
+ //var searchBar = app.Query (q => q.Raw ("* marked:'SearchBar'")).Single ();
+ Thread.Sleep(10000);
+
+ app.Tap (q => q.Raw ("* marked:'GoToTestButton'"));
+ app.WaitForNoElement (o => o.Raw ("* marked:'GoToTestButton'"), "Timed out", TimeSpan.FromMinutes(2));
+
+ //app.Screenshot ("Navigating to gallery ...");
+ //var galleryListViewBounds = app.Query (Queries.GalleryListView)[0].Rect;
+ //app.ScrollForElement (page, new Drag (galleryListViewBounds, Drag.Direction.BottomToTop, Drag.DragLength.Long));
+ //app.Tap (q => q.Raw (page));
+ //app.Screenshot ("At gallery!");
+ }
+
+ public static void NavigateToTestCases (this IApp app, string testCase)
+ {
+ app.Tap (q => q.Button ("Go to Test Cases"));
+ app.WaitForElement (q => q.Raw ("* marked:'TestCasesIssueList'"));
+
+ app.EnterText (q => q.Raw ("* marked:'SearchBarGo'"), testCase);
+
+ app.WaitForElement (q => q.Raw ("* marked:'SearchButton'"));
+ app.Tap (q => q.Raw ("* marked:'SearchButton'"));
+
+ //app.NavigateToTestCase(testCase);
+ }
+
+ public static void NavigateToTestCase (this IApp app, string testCase)
+ {
+ string testCasesQuery = "* marked:'" + testCase + "'";
+ var testCaseIssue = app.Query (q => q.Raw ("* marked:'TestCasesIssueList'")).FirstOrDefault ();
+ if (testCaseIssue != null) {
+ AppRect scrollRect = testCaseIssue.Rect;
+ app.ScrollForElement (testCasesQuery, new Drag (scrollRect, Drag.Direction.BottomToTop, Drag.DragLength.Long));
+ app.Tap (q => q.Raw (testCasesQuery));
+ } else {
+ Debug.WriteLine (string.Format ("Failed to find test case {0}", testCase));
+ }
+ }
+
+ public static bool RectsEqual (AppRect rectOne, AppRect rectTwo)
+ {
+ const float equalsTolerance = 0.1f;
+
+ bool areEqual =
+ (Math.Abs (rectOne.X - rectTwo.X) < equalsTolerance) &&
+ (Math.Abs (rectOne.Y - rectTwo.Y) < equalsTolerance) &&
+ (Math.Abs (rectOne.Width - rectTwo.Width) < equalsTolerance) &&
+ (Math.Abs (rectOne.Height - rectTwo.Height) < equalsTolerance) &&
+ (Math.Abs (rectOne.CenterX - rectTwo.CenterX) < equalsTolerance) &&
+ (Math.Abs (rectOne.CenterY - rectTwo.CenterY) < equalsTolerance);
+
+ return areEqual;
+ }
+
+ public static void WaitForAnimating (this IApp app, Func<AppQuery, AppQuery> query)
+ {
+ // Right now only checks if bounds are moving
+ const int pollingRate = 200;
+ const int timeout = 5000;
+ var sw = new Stopwatch ();
+
+ var previousState = app.Query (query).First ().Rect;
+
+ sw.Start ();
+ while (true) {
+
+ var newState = app.Query (query).First ().Rect;
+
+ if (RectsEqual (previousState, newState))
+ break;
+
+ previousState = newState;
+
+ if (sw.ElapsedMilliseconds >= timeout)
+ throw new Exception("Timed out");
+
+ Thread.Sleep (pollingRate);
+ }
+ sw.Stop ();
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/Drag.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/Drag.cs
new file mode 100644
index 00000000..71b1fa03
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/Drag.cs
@@ -0,0 +1,173 @@
+using System.Reflection.Emit;
+
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal class Drag
+ {
+ internal enum DragLength
+ {
+ Long,
+ Medium,
+ Short
+ }
+
+ internal enum Direction
+ {
+ TopToBottom,
+ BottomToTop,
+ RightToLeft,
+ LeftToRight
+ }
+
+ AppRect dragBounds;
+ float xStart;
+ float yStart;
+ float xEnd;
+ float yEnd;
+ Direction dragDirection;
+ Direction oppositeDirection;
+ DragLength dragLength;
+
+ public Drag (AppRect dragbounds, float xStart, float yStart, float xEnd, float yEnd, Direction direction)
+ {
+ dragBounds = dragbounds;
+ this.xStart = xStart;
+ this.yStart = yStart;
+ this.xEnd = xEnd;
+ this.yEnd = yEnd;
+ dragDirection = direction;
+ oppositeDirection = GetOppositeDirection (direction);
+ }
+
+ public Drag (AppRect dragBounds, Direction direction, DragLength dragLength)
+ {
+ this.dragBounds = dragBounds;
+ dragDirection = direction;
+ this.dragLength = dragLength;
+ SetDragForBounds (dragDirection, dragLength);
+ }
+
+ void SetDragForBounds (Direction direction, DragLength dragLength)
+ {
+ // percentage of bounds to scroll centered in element
+ float scrollPercentage;
+
+ switch (dragLength) {
+ case DragLength.Long:
+ scrollPercentage = 0.8f;
+ break;
+ case DragLength.Medium:
+ scrollPercentage = 0.5f;
+ break;
+ default:
+ scrollPercentage = 0.2f;
+ break;
+ }
+
+ if (direction == Direction.LeftToRight) {
+ yStart = dragBounds.CenterY;
+ yEnd = dragBounds.CenterY;
+ float xDisplacement = (dragBounds.CenterX + (dragBounds.Width / 2)) - dragBounds.X;
+ float insetForScroll = (xDisplacement - (xDisplacement * scrollPercentage)) / 2;
+ xStart = dragBounds.X + insetForScroll;
+ xEnd = (dragBounds.CenterX + (dragBounds.Width / 2)) - insetForScroll;
+ } else if (direction == Direction.RightToLeft) {
+ yStart = dragBounds.CenterY;
+ yEnd = dragBounds.CenterY;
+ float xDisplacement = (dragBounds.CenterX + (dragBounds.Width / 2)) - dragBounds.X;
+ float insetForScroll = (xDisplacement - (xDisplacement * scrollPercentage)) / 2;
+ xStart = (dragBounds.CenterX + (dragBounds.Width / 2)) - insetForScroll;
+ xEnd = dragBounds.X + insetForScroll;
+ } else if (direction == Direction.TopToBottom) {
+ xStart = dragBounds.CenterX;
+ xEnd = dragBounds.CenterX;
+ float yDisplacement = (dragBounds.CenterY + (dragBounds.Height / 2)) - dragBounds.Y;
+ float insetForScroll = (yDisplacement - (yDisplacement * scrollPercentage)) / 2;
+ yStart = dragBounds.Y + insetForScroll;
+ yEnd = (dragBounds.CenterY + (dragBounds.Height / 2)) - insetForScroll;
+ } else if (direction == Direction.BottomToTop) {
+ xStart = dragBounds.CenterX;
+ xEnd = dragBounds.CenterX;
+ float yDisplacement = (dragBounds.CenterY + (dragBounds.Height / 2)) - dragBounds.Y;
+ float insetForScroll = (yDisplacement - (yDisplacement * scrollPercentage)) / 2;
+ yStart = (dragBounds.CenterY + (dragBounds.Height / 2)) - insetForScroll;
+ yEnd = dragBounds.Y + insetForScroll;
+
+ }
+ }
+
+ Direction GetOppositeDirection (Direction direction)
+ {
+ switch (direction) {
+ case Direction.TopToBottom:
+ return Direction.BottomToTop;
+ case Direction.BottomToTop:
+ return Direction.TopToBottom;
+ case Direction.RightToLeft:
+ return Direction.LeftToRight;
+ case Direction.LeftToRight:
+ return Direction.RightToLeft;
+ default:
+ return Direction.TopToBottom;
+ }
+ }
+
+ public AppRect DragBounds
+ {
+ get { return dragBounds; }
+ }
+
+ public float XStart
+ {
+ get { return xStart; }
+ }
+
+ public float YStart
+ {
+ get { return yStart; }
+ }
+
+ public float XEnd
+ {
+ get { return xEnd; }
+ }
+
+ public float YEnd
+ {
+ get { return yEnd; }
+ }
+
+ public Direction DragDirection
+ {
+ get { return dragDirection; }
+ set
+ {
+ if (dragDirection == value)
+ return;
+
+ dragDirection = value;
+ oppositeDirection = GetOppositeDirection (dragDirection);
+ OnDragDirectionChanged ();
+ }
+ }
+
+ void OnDragDirectionChanged ()
+ {
+ SetDragForBounds (dragDirection, dragLength);
+ }
+
+ public Direction OppositeDirection
+ {
+ get { return oppositeDirection; }
+ private set
+ {
+ if (oppositeDirection == value)
+ return;
+
+ oppositeDirection = value;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/Gestures.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/Gestures.cs
new file mode 100644
index 00000000..548ff06d
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/Gestures.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Dynamic;
+using System.Linq;
+using System.Security.Cryptography;
+
+using Xamarin.UITest;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.iOS;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal static class Gestures
+ {
+ public static bool ScrollForElement (this IApp app, string query, Drag drag, int maxSteps = 25)
+ {
+ int count = 0;
+
+ int centerTolerance = 50;
+
+ Func<AppQuery, AppQuery> elementQuery = q => q.Raw (query);
+
+ // Visible elements
+ if (app.Query (elementQuery).Length > 1) {
+ throw new UITestQueryMultipleResultsException (query);
+ }
+
+ // check to see if the element is visible already
+ if (app.Query (elementQuery).Length == 1) {
+ // centering an element whos CenterX is close to the bounding rectangle's center X can sometime register the swipe as a tap
+ float elementDistanceToDragCenter = Math.Abs (app.Query (elementQuery).First ().Rect.CenterY - drag.DragBounds.CenterY);
+ if (elementDistanceToDragCenter > centerTolerance)
+ app.CenterElementInView (elementQuery, drag.DragBounds, drag.DragDirection);
+ return true;
+ }
+
+ // loop until element is seen
+ while (app.Query (elementQuery).Length == 0 && count < maxSteps) {
+ app.DragCoordinates (drag.XStart, drag.YStart, drag.XEnd, drag.YEnd);
+ count++;
+ }
+
+ if (count != maxSteps) {
+ // centering an element whos CenterX is close to the bounding rectangle's center X can sometime register the swipe as a tap
+ float elementDistanceToDragCenter = Math.Abs (app.Query (elementQuery).First ().Rect.CenterY - drag.DragBounds.CenterY);
+ if (elementDistanceToDragCenter > centerTolerance)
+ app.CenterElementInView (elementQuery, drag.DragBounds, drag.DragDirection);
+ return true;
+ }
+
+ count = 0;
+ drag.DragDirection = drag.OppositeDirection;
+
+ while (app.Query (elementQuery).Length == 0 && count < maxSteps) {
+ app.DragCoordinates (drag.XStart, drag.YStart, drag.XEnd, drag.YEnd);
+ count++;
+ }
+
+ if (count != maxSteps) {
+ app.CenterElementInView (elementQuery, drag.DragBounds, drag.DragDirection);
+ return true;
+ }
+
+ return false;
+ }
+
+ static void CenterElementInView (this IApp app, Func<AppQuery, AppQuery> element, AppRect containingView, Drag.Direction direction)
+ {
+ // TODO Implement horizontal centering
+
+ if (direction == Drag.Direction.BottomToTop || direction == Drag.Direction.TopToBottom) {
+
+ var elementBounds = app.Query (element).First ().Rect;
+
+ bool elementCenterBelowContainerCenter = elementBounds.CenterY > containingView.CenterY;
+ bool elementCenterAboveContainerCenter = elementBounds.CenterY < containingView.CenterY;
+
+ var displacementToCenter = Math.Abs (elementBounds.CenterY - containingView.CenterY) / 2;
+
+ // avoid drag as touch
+ if (displacementToCenter < 50)
+ return;
+
+ if (elementCenterBelowContainerCenter) {
+
+ var drag = new Drag (
+ containingView,
+ containingView.CenterX, containingView.CenterY + displacementToCenter,
+ containingView.CenterX, containingView.CenterY - displacementToCenter,
+ Drag.Direction.BottomToTop
+ );
+
+ app.DragCoordinates (drag.XStart, drag.YStart, drag.XEnd, drag.YEnd);
+
+ } else if (elementCenterAboveContainerCenter) {
+
+ var drag = new Drag (
+ containingView,
+ containingView.CenterX, containingView.CenterY - displacementToCenter,
+ containingView.CenterX, containingView.CenterY + displacementToCenter,
+ Drag.Direction.TopToBottom
+ );
+
+ app.DragCoordinates (drag.XStart, drag.YStart, drag.XEnd, drag.YEnd);
+ }
+ }
+ }
+
+ public static void Pan (this IApp app, Drag drag)
+ {
+ app.DragCoordinates (drag.XStart, drag.YStart, drag.XEnd, drag.YEnd);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/Logger.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/Logger.cs
new file mode 100644
index 00000000..ed0041ae
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/Logger.cs
@@ -0,0 +1,71 @@
+using System;
+using System.IO;
+using System.Reflection;
+
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal static class Logger
+ {
+ static StreamWriter queryWriter;
+
+ public static void Init ()
+ {
+ queryWriter = new StreamWriter ("../../Xamarin.Forms.Core-UITest-queries.log", false);
+ }
+
+ public static void Log (string text)
+ {
+ queryWriter.Write (text);
+ }
+
+ public static void LogLine (string text = "")
+ {
+ queryWriter.WriteLine (text);
+ }
+
+ public static void Close ()
+ {
+ queryWriter.Flush ();
+ queryWriter.Close ();
+ }
+
+ public static void LogQueryResult (AppResult[] resultsForQuery)
+ {
+ foreach (AppResult result in resultsForQuery)
+ WriteAppResult (result);
+ }
+
+ static void WriteAppResult (AppResult appResult)
+ {
+ var classText = string.Format (" {0, -10} : {1}", "Class", appResult.Class);
+ var descriptionText = string.Format (" {0, -10} : {1}", "Description", appResult.Description);
+ var enabledText = string.Format (" {0, -10} : {1}", "Enabled", appResult.Enabled);
+ var idText = string.Format (" {0, -10} : {1}", "Id", appResult.Id);
+ var labelText = string.Format (" {0, -10} : {1}", "Label", appResult.Id);
+ var textText = string.Format (" {0, -10} : {1}", "Text", appResult.Text);
+
+ var rectText = string.Format (" {0, -10}", "Rect");
+ var rectContentsText = string.Format (" [X:{0} Y:{1} W:{2} H:{3}] [CX:{4} CY:{5}]",
+ appResult.Rect.X,
+ appResult.Rect.Y,
+ appResult.Rect.Width,
+ appResult.Rect.Height,
+ appResult.Rect.CenterX,
+ appResult.Rect.CenterY
+ );
+
+ queryWriter.WriteLine (classText);
+ queryWriter.WriteLine (descriptionText);
+ queryWriter.WriteLine (enabledText);
+ queryWriter.WriteLine (idText);
+ queryWriter.WriteLine (labelText);
+ queryWriter.WriteLine (textText);
+ queryWriter.WriteLine (rectText);
+ queryWriter.WriteLine (rectContentsText);
+ queryWriter.WriteLine();
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/NumericExtensions.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/NumericExtensions.cs
new file mode 100644
index 00000000..13a4b2bf
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/NumericExtensions.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Runtime.Remoting.Messaging;
+
+using NUnit.Framework;
+
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.iOS;
+using System.Globalization;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal class Matrix : Object
+ {
+ public double M00, M01, M02, M03;
+ public double M10, M11, M12, M13;
+ public double M20, M21, M22, M23;
+ public double M30, M31, M32, M33;
+
+ public void Log () {
+
+ //Logger.LogLine ();
+
+ //Logger.LogLine (string.Format ("{0,-3}, {1,-3}, {2,-3}, {3,-3}", M00, M01, M02, M03));
+ //Logger.LogLine (string.Format ("{0,-3}, {1,-3}, {2,-3}, {3,-3}", M10, M11, M12, M13));
+ //Logger.LogLine (string.Format ("{0,-3}, {1,-3}, {2,-3}, {3,-3}", M20, M21, M22, M23));
+ //Logger.LogLine (string.Format ("{0,-3}, {1,-3}, {2,-3}, {3,-3}", M30, M31, M32, M33));
+
+ //Logger.LogLine ();
+ }
+
+ public override bool Equals (object obj)
+ {
+ if (obj == null)
+ return false;
+
+ var transform = obj as Matrix;
+ if ((Object)transform == null)
+ return false;
+
+ const double tolerance = 0.01;
+ bool result =
+ Math.Abs (M00 - transform.M00) < tolerance &&
+ Math.Abs (M01 - transform.M01) < tolerance &&
+ Math.Abs (M02 - transform.M02) < tolerance &&
+ Math.Abs (M03 - transform.M03) < tolerance &&
+ Math.Abs (M10 - transform.M10) < tolerance &&
+ Math.Abs (M11 - transform.M11) < tolerance &&
+ Math.Abs (M12 - transform.M12) < tolerance &&
+ Math.Abs (M13 - transform.M13) < tolerance &&
+ Math.Abs (M20 - transform.M20) < tolerance &&
+ Math.Abs (M21 - transform.M21) < tolerance &&
+ Math.Abs (M22 - transform.M22) < tolerance &&
+ Math.Abs (M23 - transform.M23) < tolerance &&
+ Math.Abs (M30 - transform.M30) < tolerance &&
+ Math.Abs (M31 - transform.M31) < tolerance &&
+ Math.Abs (M32 - transform.M32) < tolerance &&
+ Math.Abs (M33 - transform.M33) < tolerance;
+
+ return result;
+ }
+
+ public override int GetHashCode ()
+ {
+ return 0;
+ }
+ }
+
+ internal enum Axis
+ {
+ X,
+ Y,
+ Z
+ }
+
+ internal static class NumericExtensions
+ {
+ public static double ToRadians(this float val)
+ {
+ return (Math.PI / 180.0) * val;
+ }
+
+ public static Matrix CalculateRotationMatrixForDegrees (float degrees, Axis rotationAxis)
+ {
+ var angle = degrees.ToRadians ();
+
+ var transform = new Matrix ();
+ if (rotationAxis == Axis.X) {
+ transform.M00 = 1; transform.M01 = 0; transform.M02 = 0; transform.M03 = 0;
+ transform.M10 = 0; transform.M11 = (float) Math.Cos (angle); transform.M12 = (float) Math.Sin (angle); transform.M13 = 0;
+ transform.M20 = 0; transform.M21 = -(float) Math.Sin (angle); transform.M22 = (float) Math.Cos (angle); transform.M23 = 0;
+ transform.M30 = 0; transform.M31 = 0; transform.M32 = 0; transform.M33 = 1;
+ } else if (rotationAxis == Axis.Y) {
+ transform.M00 = (float) Math.Cos (angle); transform.M01 = 0; transform.M02 = -(float) Math.Sin (angle); transform.M03 = 0;
+ transform.M10 = 0; transform.M11 = 1; transform.M12 = 0; transform.M13 = 0;
+ transform.M20 = (float) Math.Sin (angle); transform.M21 = 0; transform.M22 = (float) Math.Cos (angle); transform.M23 = 0;
+ transform.M30 = 0; transform.M31 = 0; transform.M32 = 0; transform.M33 = 1;
+ } else {
+ transform.M00 = (float) Math.Cos (angle); transform.M01 = (float) Math.Sin (angle); transform.M02 = 0; transform.M03 = 0;
+ transform.M10 = -(float) Math.Sin (angle); transform.M11 = (float) Math.Cos (angle); transform.M12 = 0; transform.M13 = 0;
+ transform.M20 = 0; transform.M21 = 0; transform.M22 = 1; transform.M23 = 0;
+ transform.M30 = 0; transform.M31 = 0; transform.M32 = 0; transform.M33 = 1;
+ }
+
+ return transform;
+ }
+
+ public static Matrix BuildScaleMatrix (float scale)
+ {
+ var transform = new Matrix ();
+
+ transform.M00 = scale; transform.M01 = 0; transform.M02 = 0; transform.M03 = 0;
+ transform.M10 = 0; transform.M11 = scale; transform.M12 = 0; transform.M13 = 0;
+ transform.M20 = 0; transform.M21 = 0; transform.M22 = scale; transform.M23 = 0;
+ transform.M30 = 0; transform.M31 = 0; transform.M32 = 0; transform.M33 = 1;
+
+ return transform;
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/ParsingUtils.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/ParsingUtils.cs
new file mode 100644
index 00000000..6598e0f5
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/ParsingUtils.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Runtime.Remoting.Messaging;
+
+using NUnit.Framework;
+
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.iOS;
+using System.Globalization;
+using System.Text.RegularExpressions;
+using System.IO;
+
+namespace Xamarin.Forms.Core.UITests
+{
+
+ internal static class ParsingUtils
+ {
+ public static Font ParseUIFont (string font)
+ {
+ FontAttributes fontAttrs = FontAttributes.None;
+
+ // Logger.LogLine ("TEST PARSING");
+
+ if (font.Contains ("font-weight: bold;")) {
+ // Logger.LogLine ("Found Bold");
+ fontAttrs = FontAttributes.Bold;
+ }
+
+ return new Font ().WithAttributes (fontAttrs);
+ }
+
+ public static Color ParseUIColor (string backgroundColor)
+ {
+ var delimiters = new char[] { ' ' };
+ string[] words = backgroundColor.Split (delimiters, StringSplitOptions.RemoveEmptyEntries);
+ return new Color (double.Parse (words[1]), double.Parse (words[2]), double.Parse (words[3]), double.Parse (words[4]));
+ }
+
+ public static Point ParseCGPoint (object CGPoint) {
+ var point = new Point { X = 0, Y = 0 };
+ return point;
+ }
+
+ public static Matrix ParseCATransform3D (string CATransform3D)
+ {
+ // Logger.Log (CATransform3D);
+ char[] delimiters = { '<', ' ', '>' };
+ string[] words = CATransform3D.Split (delimiters, StringSplitOptions.RemoveEmptyEntries);
+
+ List<double> numbers = new List<double> ();
+
+ // Each number is represented by 2 blocks returned by server
+ for (int i = 0; i < (words.Length - 1); i += 2) {
+ string word = words[i] + words[i + 1];
+ var number = Int64.Parse (word, NumberStyles.HexNumber);
+ byte[] bytes = BitConverter.GetBytes (number);
+ byte[] reversedBytes = bytes.Reverse ().ToArray ();
+ double value = BitConverter.ToDouble (reversedBytes, 0);
+ numbers.Add (value);
+ }
+
+ var transformationMatrix = new Matrix ();
+ transformationMatrix.M00 = numbers[0];
+ transformationMatrix.M01 = numbers[1];
+ transformationMatrix.M02 = numbers[2];
+ transformationMatrix.M03 = numbers[3];
+ transformationMatrix.M10 = numbers[4];
+ transformationMatrix.M11 = numbers[5];
+ transformationMatrix.M12 = numbers[6];
+ transformationMatrix.M13 = numbers[7];
+ transformationMatrix.M20 = numbers[8];
+ transformationMatrix.M21 = numbers[9];
+ transformationMatrix.M22 = numbers[10];
+ transformationMatrix.M23 = numbers[11];
+ transformationMatrix.M30 = numbers[12];
+ transformationMatrix.M31 = numbers[13];
+ transformationMatrix.M32 = numbers[14];
+ transformationMatrix.M33 = numbers[15];
+
+ return transformationMatrix;
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/UITestCustomExceptions.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/UITestCustomExceptions.cs
new file mode 100644
index 00000000..6969ac52
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/UITestCustomExceptions.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.UITest.Queries;
+using System.Runtime.CompilerServices;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal class UITestQueryNoResultException : Exception
+ {
+ readonly string message;
+
+ public UITestQueryNoResultException (string query)
+ {
+ message = string.Format ("Found no elements for query with target: {0}", query);
+ }
+
+ public override string Message
+ {
+ get { return message; }
+ }
+ }
+
+ internal class UITestQuerySingleResultException : Exception
+ {
+ readonly string message;
+
+ public UITestQuerySingleResultException (string query)
+ {
+ message = string.Format ("Found single element for query with target: {0}", query);
+ }
+
+ public override string Message
+ {
+ get { return message; }
+ }
+ }
+
+ internal class UITestQueryMultipleResultsException : Exception
+ {
+ readonly string message;
+
+ public UITestQueryMultipleResultsException (string query)
+ {
+ message = string.Format ("Found muliple elements for query with target: {0}", query);
+ }
+
+ public override string Message
+ {
+ get { return message; }
+ }
+ }
+
+ internal class UITestRemoteException : Exception
+ {
+ readonly string message;
+
+ public UITestRemoteException (string message)
+ {
+ this.message = message;
+ }
+
+ public override string Message
+ {
+ get { return message; }
+ }
+ }
+
+ internal class UITestRemoteQueryException : Exception
+ {
+ readonly string message;
+
+ public UITestRemoteQueryException (string query)
+ {
+ message = string.Format ("Error for query with target: {0}", query);
+ }
+
+ public override string Message
+ {
+ get { return message; }
+ }
+ }
+
+ internal class UITestErrorException : Exception
+ {
+ readonly string message;
+
+ public UITestErrorException (string message, [CallerMemberName] string caller = null)
+ {
+ message = string.Format ("Test error: {0}, {1}", caller, message);
+ }
+
+ public override string Message
+ {
+ get { return message; }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Core.iOS.UITests/Utilities/ViewInspector.cs b/Xamarin.Forms.Core.iOS.UITests/Utilities/ViewInspector.cs
new file mode 100644
index 00000000..288ee3d6
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Utilities/ViewInspector.cs
@@ -0,0 +1,342 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.UITest;
+using Xamarin.UITest.Android;
+using Xamarin.UITest.iOS;
+using System.Linq;
+
+namespace Xamarin.Forms.Core.UITests
+{
+ internal static class ViewInspector
+ {
+ public static void LogPropertiesForView (this IApp app, string query, bool isOnParent = false)
+ {
+ if (app is AndroidApp) {
+ LogPropertiesForAndroidView ((AndroidApp)app, query, isOnParent);
+ } else {
+ LogPropertiesForUIView ((iOSApp)app, query, isOnParent);
+ LogPropertiesForCALayer ((iOSApp)app, query, isOnParent);
+ }
+ }
+
+ static void LogPropertiesForUIView (this iOSApp app, string query, bool isOnParent = false) {
+
+ //Logger.LogLine ("--- UIView Properties ---");
+
+ var properties = new [] {
+ // just getters with no params, bools
+ "alpha",
+ "autoresizesSubviews",
+ "autoresizingMask",
+ "backgroundColor",
+ "bounds",
+ "center",
+ "clearsContextBeforeDrawing",
+ "clipsToBounds",
+ "contentMode",
+ "contentScaleFactor",
+ "exclusiveTouch",
+ "frame",
+ "gestureRecognizers",
+ "hidden",
+ "layer",
+ "motionEffects",
+ "multipleTouchEnabled",
+ "opaque",
+ "restorationIdentifier",
+ "subviews",
+ "superview",
+ "tag",
+ "tintAdjustmentMode",
+ "tintColor",
+ "transform",
+ "userInteractionEnabled",
+ "window"
+ };
+
+ if (isOnParent)
+ query = query + " parent * index:0";
+
+ foreach (var property in properties) {
+ object prop;
+ bool found =
+ MaybeGetProperty<string> (app, query, property, out prop) ||
+ MaybeGetProperty<int> (app, query, property, out prop) ||
+ MaybeGetProperty<float> (app, query, property, out prop) ||
+ MaybeGetProperty<bool> (app, query, property, out prop);
+
+ //if (found)
+ // Logger.LogLine (string.Format ("{0,-30}: {1}", property, prop));
+ }
+
+ //Logger.LogLine();
+
+ }
+
+ static void LogPropertiesForCALayer(this iOSApp app, string query, bool isOnParent = false)
+ {
+ // Logger.LogLine ("--- UIView.Layer Properties ---");
+
+ var properties = new[] {
+ "actions",
+ "anchorPoint",
+ "anchorPointZ",
+ "backgroundColor",
+ "backgroundFilters",
+ "borderColor",
+ "borderWidth",
+ "bounds",
+ "compositingFilter",
+ "contents",
+ "contentsCenter",
+ "contentsGravity",
+ "contentsRect",
+ "contentsScale",
+ "cornerRadius",
+ "delegate",
+ "doubleSided",
+ "drawsAsynchronously",
+ "edgeAntialiasingMask",
+ "filters",
+ "frame",
+ "geometryFlipped",
+ "hidden",
+ "magnificationFilter",
+ "mask",
+ "masksToBounds",
+ "minificationFilter",
+ "minificationFilterBias",
+ "name",
+ "needsDisplayOnBoundsChange",
+ "opacity",
+ "opaque",
+ "position",
+ "rasterizationScale",
+ "shadowColor",
+ "shadowOffset",
+ "shadowOpacity",
+ "shadowPath",
+ "shadowRadius",
+ "shouldRasterize",
+ "style",
+ "sublayers",
+ "sublayerTransform",
+ "superlayer",
+ "transform",
+ "visibleRect",
+ "zPosition"
+ };
+
+ if (isOnParent)
+ query = query + " parent * index:0";
+
+ foreach (var property in properties)
+ {
+ object prop;
+ bool found =
+ MaybeGetLayerProperty<string>(app, query, property, out prop) ||
+ MaybeGetLayerProperty<int>(app, query, property, out prop) ||
+ MaybeGetLayerProperty<bool>(app, query, property, out prop);
+
+ //if (found)
+ // Logger.LogLine(string.Format("{0,-30}: {1}", property, prop));
+ }
+
+ //Logger.LogLine();
+
+ }
+
+ static void LogPropertiesForAndroidView (this AndroidApp app, string query, bool isOnParent = false)
+ {
+ // Logger.LogLine( "--- Android View Properties ---");
+
+ var properties = new [] {
+ // just getters with no params, bools
+ //"getAccessibilityLiveRegion",
+ //"getAccessibilbityNodeProvider",
+ //"getAlpha",
+ //"getAnimation",
+ //"getApplicationWindowToken",
+ //"getBackground",
+ //"getBaseline",
+ //"getBottom",
+ //"getCameraDistance",
+ //"getClipBounds",
+ //"getContentDescription",
+ //"getContext",
+ //"getDefaultSize",
+ //"getDisplay",
+ //"getDrawableState",
+ //"getDrawingCache",
+ //"getDrawingCacheBackgroundColor",
+ //"getDrawingRect",
+ //"getDrawingTime",
+ //"getFilterTouchesWhenObscurred",
+ //"getFitsSystemWindows",
+ //"getFocusables",
+ //"getHandler",
+ //"getHeight",
+ //"getHitRect",
+ //"getHorizontalFadingEdgeLength",
+ //"getId",
+ //"getImportantForAccessibility",
+ //"getKeepScreenOn",
+ //"getKeyDispatcherState",
+ //"getLabelFor",
+ //"getLayerType",
+ //"getLayoutDirection",
+ //"getLayourParams",
+ //"getLeft",
+ "getMatrix",
+ //"getMeasuredHeight",
+ //"getMeasuredHeightAndState",
+ //"getMeasuredState",
+ //"getMeasuredWidth",
+ //"getMeasuredWidthAndState",
+ //"getMinimumHeight",
+ //"getMinimumWidth",
+ //"getNextFocusDownId",
+ //"getNextFocusForwardId",
+ //"getNextFocusLeftId",
+ //"getNextFocusRightId",
+ //"getNextFocusUpId",
+ //"getOnFocusChangedListener",
+ //"getOverScrollMethod",
+ //"getOverlay",
+ //"getPaddingBottom",
+ //"getPaddingEnd",
+ //"getPaddingLeft",
+ //"getPaddingRight",
+ //"getPaddingStart",
+ //"getPaddingTop",
+ //"getParent",
+ //"getParentForAccessibility",
+ //"getPivotX",
+ //"getPivotY",
+ //"getResources",
+ //"getRight",
+ //"getRootView",
+ //"getRotation",
+ //"getRotationX",
+ //"getRotationY",
+ "getScaleX",
+ "getScaleY",
+ //"getScrollBarDefaultDelayBeforeFade",
+ //"getScrollBarFadeDuration",
+ //"getScrollBarSize",
+ //"getScrollBarStyle",
+ //"getScrollX",
+ //"getScrollY",
+ //"getSolidColor",
+ //"getSystemUiVisibility",
+ //"getTag",
+ //"getTextAlignment",
+ //"getTextDirection",
+ //"getTop",
+ //"getTouchDelegate",
+ //"getTouchables",
+ //"getTranslationX",
+ //"getTranslationY",
+ //"getVerticalFadingEdgeLength",
+ //"getVerticalScrollbarPosition",
+ //"getVerticalScrollbarWidth",
+ //"getViewTreeObserver",
+ //"getVisibility",
+ //"getWidth",
+ //"getWindowId",
+ //"getWindowSystemUiVisbility",
+ //"getWindowToken",
+ //"getWindowVisibility",
+ //"getX",
+ //"getY",
+ //"hasFocus",
+ //"hasFocusable",
+ //"hasOnClickListener",
+ //"hasOverlappingRendering",
+ //"hasTransientState",
+ //"hasWindowFocus",
+ //"isActivated",
+ //"isAttachedToWindow",
+ //"isClickable",
+ //"isDirty",
+ //"isDrawingCacheEnabled",
+ //"isDuplicateParentStateEnabled",
+ //"isEnabled",
+ //"isFocusable",
+ //"isFocusableInTouchWindow",
+ //"isFocused",
+ //"isHapticFeedbackEnabled",
+ //"isHardwareAccelerated",
+ //"isHorizontalFadingEdgeEnabled",
+ //"isHovered",
+ //"idInEditMode",
+ //"isInLayout",
+ //"isInTouchMode",
+ //"isLaidOut",
+ //"isLayoutDirectionResolved",
+ //"isLayoutRequested",
+ //"isLongClickable",
+ //"isOpaque",
+ //"isPaddingRelative",
+ //"isPressed",
+ //"isSaveEnabled",
+ //"isSaveFromParentEnabled",
+ //"isScrollContainer",
+ //"isScrollBarFadingEnabled",
+ //"isSelected",
+ //"isShown",
+ //"isSoundEffectsEnabled",
+ //"isTextAlignmentResolved",
+ //"isTextDirectionResolved",
+ //"isVerticalFadingEdgeEnabled",
+ //"isVerticalScrollBarEnabled"
+ };
+
+ if (isOnParent)
+ query = query + " parent * index:0";
+
+ foreach (var property in properties) {
+ object prop;
+ bool found =
+ MaybeGetProperty<string> (app, query, property, out prop) ||
+ //MaybeGetProperty<int> (app, query, property, out prop) ||
+ MaybeGetProperty<float> (app, query, property, out prop) ||
+ MaybeGetProperty<bool> (app, query, property, out prop);
+
+ //if (found)
+ // Logger.LogLine (string.Format ("{0,-30}: {1}", property, prop));
+ }
+
+ //Logger.LogLine();
+
+ }
+
+ static bool MaybeGetLayerProperty<T> (iOSApp app, string query, string property, out object result)
+ {
+
+ try {
+ result = app.Query (q => q.Raw (query).Invoke ("layer").Invoke (property).Value<T> ()).First ();
+ } catch {
+ result = null;
+ return false;
+ }
+
+ return true;
+ }
+
+ static bool MaybeGetProperty<T> (IApp app, string query, string property, out object result)
+ {
+
+ try {
+ result = app.Query (q => q.Raw (query).Invoke (property).Value<T> ()).First ();
+ } catch {
+ result = null;
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Core.iOS.UITests/Xamarin.Forms.Core.iOS.UITests.csproj b/Xamarin.Forms.Core.iOS.UITests/Xamarin.Forms.Core.iOS.UITests.csproj
new file mode 100644
index 00000000..2846ddc0
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/Xamarin.Forms.Core.iOS.UITests.csproj
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{EADD8100-B3AE-4A31-92C4-267A64A1C6EB}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Core.UITests</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Core.iOS.UITests</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;__IOS__;UITEST</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;__IOS__;UITEST</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;__IOS__;UITEST</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ <Reference Include="nunit.framework">
+ <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="Xamarin.UITest, Version=1.3.3.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.UITest.1.3.3\lib\Xamarin.UITest.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BaseTestFixture.cs" />
+ <Compile Include="App.cs" />
+ <Compile Include="PlatformQueries.cs" />
+ <Compile Include="Remotes\BaseViewContainerRemote.cs" />
+ <Compile Include="Remotes\EventViewContainerRemote.cs" />
+ <Compile Include="Remotes\LayeredViewContainerRemote.cs" />
+ <Compile Include="Remotes\ViewContainerRemote.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Queries.cs" />
+ <Compile Include="Remotes\StateViewContainerRemote.cs" />
+ <Compile Include="Remotes\RemoteFactory.cs" />
+ <Compile Include="Tests\ContextActionsUITests.cs" />
+ <Compile Include="Tests\Legacy-BoundViewUITest.cs" />
+ <Compile Include="Tests\Legacy-ClipToBoundsUITests.cs" />
+ <Compile Include="Tests\Legacy-GroupedListActionsUITests.cs" />
+ <Compile Include="Tests\Legacy-ButtonUITests.cs" />
+ <Compile Include="Tests\Legacy-EditorUITests.cs" />
+ <Compile Include="Tests\Legacy-EntryUITests.cs" />
+ <Compile Include="Tests\Legacy-AbsoluteLayoutGalleryTest.cs" />
+ <Compile Include="Tests\ActivityIndicatorUITests.cs" />
+ <Compile Include="Tests\Legacy-CarouselPageUITests.cs" />
+ <Compile Include="Tests\Legacy-CellsUITests.cs" />
+ <Compile Include="Tests\DatePickerUITests.cs" />
+ <Compile Include="Tests\BoxViewUITests.cs" />
+ <Compile Include="Tests\EditorUITests.cs" />
+ <Compile Include="Tests\FrameUITests.cs" />
+ <Compile Include="Tests\Legacy-GridGalleryUITests.cs" />
+ <Compile Include="Tests\ImageUITests.cs" />
+ <Compile Include="Tests\Legacy-InputIntentUITests.cs" />
+ <Compile Include="Tests\Legacy-ListUITests.cs" />
+ <Compile Include="Tests\Legacy-MapUITests.cs" />
+ <Compile Include="Tests\Legacy-MinimumSizeUITest.cs" />
+ <Compile Include="Tests\Legacy-RelativeLayoutUITest.cs" />
+ <Compile Include="Tests\Legacy-SliderUITests.cs" />
+ <Compile Include="Tests\Legacy-StackLayoutUITest.cs" />
+ <Compile Include="Tests\Legacy-StepperUITests.cs" />
+ <Compile Include="Tests\Legacy-SwitchUITests.cs" />
+ <Compile Include="Tests\Legacy-SearchBarUITests.cs" />
+ <Compile Include="Tests\Legacy-TemplatedCarouselPageUITests.cs" />
+ <Compile Include="Tests\Legacy-TemplatedTabPageUITests.cs" />
+ <Compile Include="Tests\Legacy-TableViewUITests.cs" />
+ <Compile Include="Tests\Legacy-ToolbarGalleryUITests.cs" />
+ <Compile Include="Tests\Legacy-UnevenViewCellUITests.cs" />
+ <Compile Include="Tests\Legacy-ViewCellUITests.cs" />
+ <Compile Include="Tests\Legacy-NavigationBarUITests.cs" />
+ <Compile Include="Tests\WebViewUITests.cs" />
+ <Compile Include="Tests\TimePickerUITests.cs" />
+ <Compile Include="Tests\SwitchUITests.cs" />
+ <Compile Include="Tests\StepperUITests.cs" />
+ <Compile Include="Tests\SliderUITests.cs" />
+ <Compile Include="Tests\SearchBarUITests.cs" />
+ <Compile Include="Tests\ProgressBarUITests.cs" />
+ <Compile Include="Tests\PickerUITests.cs" />
+ <Compile Include="Tests\LabelUITests.cs" />
+ <Compile Include="Tests\EntryUITests.cs" />
+ <Compile Include="Tests\ButtonUITests.cs" />
+ <Compile Include="Tests\ViewUITests.cs" />
+ <Compile Include="Utilities\AppExtensions.cs" />
+ <Compile Include="Utilities\Drag.cs" />
+ <Compile Include="Utilities\Gestures.cs" />
+ <Compile Include="Utilities\Logger.cs" />
+ <Compile Include="Utilities\NumericExtensions.cs" />
+ <Compile Include="Utilities\ParsingUtils.cs" />
+ <Compile Include="Utilities\UITestCustomExceptions.cs" />
+ <Compile Include="Utilities\ViewInspector.cs" />
+ <Compile Include="Tests\DisplayAlertUITests.cs" />
+ <Compile Include="Tests\ActionSheetUITests.cs" />
+ <Compile Include="Tests\ToolbarItemTests.cs" />
+ <Compile Include="Tests\RootGalleryUITests.cs" />
+ <Compile Include="Tests\ScrollViewUITests.cs" />
+ <Compile Include="Tests\Legacy-UnevenListTests.cs" />
+ <Compile Include="Tests\AppearingUITests.cs" />
+ <Compile Include="Tests\AutomationIDUITests.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.CustomAttributes\Xamarin.Forms.CustomAttributes.csproj">
+ <Project>{4DCD0420-1168-4B77-86DB-6196EE4BD491}</Project>
+ <Name>Xamarin.Forms.CustomAttributes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7d13bac2-c6a4-416a-b07e-c169b199e52b}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform\Xamarin.Forms.Platform.csproj">
+ <Project>{67f9d3a8-f71e-4428-913f-c37ae82cdb24}</Project>
+ <Name>Xamarin.Forms.Platform</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="..\Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Xamarin.Forms.Controls.Issues.Shared.projitems" Label="Shared" />
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+ </Target>
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ItemGroup />
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Core.iOS.UITests/packages.config b/Xamarin.Forms.Core.iOS.UITests/packages.config
new file mode 100644
index 00000000..031fa54c
--- /dev/null
+++ b/Xamarin.Forms.Core.iOS.UITests/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit" version="2.6.4" targetFramework="net45" />
+ <package id="Xamarin.UITest" version="1.3.3" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.Core/AbsoluteLayout.cs b/Xamarin.Forms.Core/AbsoluteLayout.cs
new file mode 100644
index 00000000..51b5ca12
--- /dev/null
+++ b/Xamarin.Forms.Core/AbsoluteLayout.cs
@@ -0,0 +1,313 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+
+namespace Xamarin.Forms
+{
+ public class AbsoluteLayout : Layout<View>
+ {
+ public static readonly BindableProperty LayoutFlagsProperty = BindableProperty.CreateAttached("LayoutFlags", typeof(AbsoluteLayoutFlags), typeof(AbsoluteLayout), AbsoluteLayoutFlags.None);
+
+ public static readonly BindableProperty LayoutBoundsProperty = BindableProperty.CreateAttached("LayoutBounds", typeof(Rectangle), typeof(AbsoluteLayout), new Rectangle(0, 0, AutoSize, AutoSize));
+
+ readonly AbsoluteElementCollection _children;
+
+ public AbsoluteLayout()
+ {
+ _children = new AbsoluteElementCollection(InternalChildren, this);
+ }
+
+ public static double AutoSize
+ {
+ get { return -1; }
+ }
+
+ public new IAbsoluteList<View> Children
+ {
+ get { return _children; }
+ }
+
+ [TypeConverter(typeof(BoundsTypeConverter))]
+ public static Rectangle GetLayoutBounds(BindableObject bindable)
+ {
+ return (Rectangle)bindable.GetValue(LayoutBoundsProperty);
+ }
+
+ public static AbsoluteLayoutFlags GetLayoutFlags(BindableObject bindable)
+ {
+ return (AbsoluteLayoutFlags)bindable.GetValue(LayoutFlagsProperty);
+ }
+
+ public static void SetLayoutBounds(BindableObject bindable, Rectangle bounds)
+ {
+ bindable.SetValue(LayoutBoundsProperty, bounds);
+ }
+
+ public static void SetLayoutFlags(BindableObject bindable, AbsoluteLayoutFlags flags)
+ {
+ bindable.SetValue(LayoutFlagsProperty, flags);
+ }
+
+ protected override void LayoutChildren(double x, double y, double width, double height)
+ {
+ foreach (View child in LogicalChildren)
+ {
+ Rectangle rect = ComputeLayoutForRegion(child, new Size(width, height));
+ rect.X += x;
+ rect.Y += y;
+
+ LayoutChildIntoBoundingRegion(child, rect);
+ }
+ }
+
+ protected override void OnChildAdded(Element child)
+ {
+ base.OnChildAdded(child);
+ child.PropertyChanged += ChildOnPropertyChanged;
+ }
+
+ protected override void OnChildRemoved(Element child)
+ {
+ child.PropertyChanged -= ChildOnPropertyChanged;
+ base.OnChildRemoved(child);
+ }
+
+ [Obsolete("Use OnMeasure")]
+ protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ var bestFitSize = new Size();
+ var minimum = new Size();
+ foreach (View child in LogicalChildren)
+ {
+ SizeRequest desiredSize = ComputeBoundingRegionDesiredSize(child);
+
+ bestFitSize.Width = Math.Max(bestFitSize.Width, desiredSize.Request.Width);
+ bestFitSize.Height = Math.Max(bestFitSize.Height, desiredSize.Request.Height);
+ minimum.Width = Math.Max(minimum.Width, desiredSize.Minimum.Width);
+ minimum.Height = Math.Max(minimum.Height, desiredSize.Minimum.Height);
+ }
+
+ return new SizeRequest(bestFitSize, minimum);
+ }
+
+ internal override void ComputeConstraintForView(View view)
+ {
+ AbsoluteLayoutFlags layoutFlags = GetLayoutFlags(view);
+
+ if ((layoutFlags & AbsoluteLayoutFlags.SizeProportional) == AbsoluteLayoutFlags.SizeProportional)
+ {
+ view.ComputedConstraint = Constraint;
+ return;
+ }
+
+ var result = LayoutConstraint.None;
+ Rectangle layoutBounds = GetLayoutBounds(view);
+ if ((layoutFlags & AbsoluteLayoutFlags.HeightProportional) != 0)
+ {
+ bool widthLocked = layoutBounds.Width != AutoSize;
+ result = Constraint & LayoutConstraint.VerticallyFixed;
+ if (widthLocked)
+ result |= LayoutConstraint.HorizontallyFixed;
+ }
+ else if ((layoutFlags & AbsoluteLayoutFlags.WidthProportional) != 0)
+ {
+ bool heightLocked = layoutBounds.Height != AutoSize;
+ result = Constraint & LayoutConstraint.HorizontallyFixed;
+ if (heightLocked)
+ result |= LayoutConstraint.VerticallyFixed;
+ }
+ else
+ {
+ if (layoutBounds.Width != AutoSize)
+ result |= LayoutConstraint.HorizontallyFixed;
+ if (layoutBounds.Height != AutoSize)
+ result |= LayoutConstraint.VerticallyFixed;
+ }
+
+ view.ComputedConstraint = result;
+ }
+
+ void ChildOnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == LayoutFlagsProperty.PropertyName || e.PropertyName == LayoutBoundsProperty.PropertyName)
+ {
+ InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ UpdateChildrenLayout();
+ }
+ }
+
+ static SizeRequest ComputeBoundingRegionDesiredSize(View view)
+ {
+ var width = 0.0;
+ var height = 0.0;
+
+ var sizeRequest = new Lazy<SizeRequest>(() => view.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.IncludeMargins));
+
+ Rectangle bounds = GetLayoutBounds(view);
+ AbsoluteLayoutFlags absFlags = GetLayoutFlags(view);
+ bool widthIsProportional = (absFlags & AbsoluteLayoutFlags.WidthProportional) != 0;
+ bool heightIsProportional = (absFlags & AbsoluteLayoutFlags.HeightProportional) != 0;
+ bool xIsProportional = (absFlags & AbsoluteLayoutFlags.XProportional) != 0;
+ bool yIsProportional = (absFlags & AbsoluteLayoutFlags.YProportional) != 0;
+
+ // add in required x values
+ if (!xIsProportional)
+ {
+ width += bounds.X;
+ }
+
+ if (!yIsProportional)
+ {
+ height += bounds.Y;
+ }
+
+ double minWidth = width;
+ double minHeight = height;
+
+ if (!widthIsProportional && bounds.Width != AutoSize)
+ {
+ // fixed size
+ width += bounds.Width;
+ minWidth += bounds.Width;
+ }
+ else if (!widthIsProportional)
+ {
+ // auto size
+ width += sizeRequest.Value.Request.Width;
+ minWidth += sizeRequest.Value.Minimum.Width;
+ }
+ else
+ {
+ // proportional size
+ width += sizeRequest.Value.Request.Width / Math.Max(0.25, bounds.Width);
+ //minWidth += 0;
+ }
+
+ if (!heightIsProportional && bounds.Height != AutoSize)
+ {
+ // fixed size
+ height += bounds.Height;
+ minHeight += bounds.Height;
+ }
+ else if (!heightIsProportional)
+ {
+ // auto size
+ height += sizeRequest.Value.Request.Height;
+ minHeight += sizeRequest.Value.Minimum.Height;
+ }
+ else
+ {
+ // proportional size
+ height += sizeRequest.Value.Request.Height / Math.Max(0.25, bounds.Height);
+ //minHeight += 0;
+ }
+
+ return new SizeRequest(new Size(width, height), new Size(minWidth, minHeight));
+ }
+
+ static Rectangle ComputeLayoutForRegion(View view, Size region)
+ {
+ var result = new Rectangle();
+
+ SizeRequest sizeRequest;
+ Rectangle bounds = GetLayoutBounds(view);
+ AbsoluteLayoutFlags absFlags = GetLayoutFlags(view);
+ bool widthIsProportional = (absFlags & AbsoluteLayoutFlags.WidthProportional) != 0;
+ bool heightIsProportional = (absFlags & AbsoluteLayoutFlags.HeightProportional) != 0;
+ bool xIsProportional = (absFlags & AbsoluteLayoutFlags.XProportional) != 0;
+ bool yIsProportional = (absFlags & AbsoluteLayoutFlags.YProportional) != 0;
+
+ if (widthIsProportional)
+ {
+ result.Width = Math.Round(region.Width * bounds.Width);
+ }
+ else if (bounds.Width != AutoSize)
+ {
+ result.Width = bounds.Width;
+ }
+
+ if (heightIsProportional)
+ {
+ result.Height = Math.Round(region.Height * bounds.Height);
+ }
+ else if (bounds.Height != AutoSize)
+ {
+ result.Height = bounds.Height;
+ }
+
+ if (!widthIsProportional && bounds.Width == AutoSize)
+ {
+ if (!heightIsProportional && bounds.Width == AutoSize)
+ {
+ // Width and Height are auto
+ sizeRequest = view.Measure(region.Width, region.Height, MeasureFlags.IncludeMargins);
+ result.Width = sizeRequest.Request.Width;
+ result.Height = sizeRequest.Request.Height;
+ }
+ else
+ {
+ // Only width is auto
+ sizeRequest = view.Measure(region.Width, result.Height, MeasureFlags.IncludeMargins);
+ result.Width = sizeRequest.Request.Width;
+ }
+ }
+ else if (!heightIsProportional && bounds.Height == AutoSize)
+ {
+ // Only height is auto
+ sizeRequest = view.Measure(result.Width, region.Height, MeasureFlags.IncludeMargins);
+ result.Height = sizeRequest.Request.Height;
+ }
+
+ if (xIsProportional)
+ {
+ result.X = Math.Round((region.Width - result.Width) * bounds.X);
+ }
+ else
+ {
+ result.X = bounds.X;
+ }
+
+ if (yIsProportional)
+ {
+ result.Y = Math.Round((region.Height - result.Height) * bounds.Y);
+ }
+ else
+ {
+ result.Y = bounds.Y;
+ }
+
+ return result;
+ }
+
+ public interface IAbsoluteList<T> : IList<T> where T : View
+ {
+ void Add(View view, Rectangle bounds, AbsoluteLayoutFlags flags = AbsoluteLayoutFlags.None);
+
+ void Add(View view, Point position);
+ }
+
+ class AbsoluteElementCollection : ElementCollection<View>, IAbsoluteList<View>
+ {
+ public AbsoluteElementCollection(ObservableCollection<Element> inner, AbsoluteLayout parent) : base(inner)
+ {
+ Parent = parent;
+ }
+
+ internal AbsoluteLayout Parent { get; set; }
+
+ public void Add(View view, Rectangle bounds, AbsoluteLayoutFlags flags = AbsoluteLayoutFlags.None)
+ {
+ SetLayoutBounds(view, bounds);
+ SetLayoutFlags(view, flags);
+ Add(view);
+ }
+
+ public void Add(View view, Point position)
+ {
+ SetLayoutBounds(view, new Rectangle(position.X, position.Y, AutoSize, AutoSize));
+ Add(view);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/AbsoluteLayoutFlags.cs b/Xamarin.Forms.Core/AbsoluteLayoutFlags.cs
new file mode 100644
index 00000000..dcc81c10
--- /dev/null
+++ b/Xamarin.Forms.Core/AbsoluteLayoutFlags.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [Flags]
+ public enum AbsoluteLayoutFlags
+ {
+ None = 0,
+ XProportional = 1 << 0,
+ YProportional = 1 << 1,
+ WidthProportional = 1 << 2,
+ HeightProportional = 1 << 3,
+ PositionProportional = 1 | 1 << 1,
+ SizeProportional = 1 << 2 | 1 << 3,
+ All = ~0
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ActionSheetArguments.cs b/Xamarin.Forms.Core/ActionSheetArguments.cs
new file mode 100644
index 00000000..3417ed61
--- /dev/null
+++ b/Xamarin.Forms.Core/ActionSheetArguments.cs
@@ -0,0 +1,45 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ internal class ActionSheetArguments
+ {
+ public ActionSheetArguments(string title, string cancel, string destruction, IEnumerable<string> buttons)
+ {
+ Title = title;
+ Cancel = cancel;
+ Destruction = destruction;
+ Buttons = buttons;
+ Result = new TaskCompletionSource<string>();
+ }
+
+ /// <summary>
+ /// Gets titles of any buttons on the action sheet that aren't <see cref="Cancel" /> or <see cref="Destruction" />. Can
+ /// be <c>null</c>.
+ /// </summary>
+ public IEnumerable<string> Buttons { get; private set; }
+
+ /// <summary>
+ /// Gets the text for a cancel button. Can be null.
+ /// </summary>
+ public string Cancel { get; private set; }
+
+ /// <summary>
+ /// Gets the text for a destructive button. Can be null.
+ /// </summary>
+ public string Destruction { get; private set; }
+
+ public TaskCompletionSource<string> Result { get; }
+
+ /// <summary>
+ /// Gets the title for the action sheet. Can be null.
+ /// </summary>
+ public string Title { get; private set; }
+
+ public void SetResult(string result)
+ {
+ Result.TrySetResult(result);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ActivityIndicator.cs b/Xamarin.Forms.Core/ActivityIndicator.cs
new file mode 100644
index 00000000..3689609a
--- /dev/null
+++ b/Xamarin.Forms.Core/ActivityIndicator.cs
@@ -0,0 +1,24 @@
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_ActivityIndicatorRenderer))]
+ public class ActivityIndicator : View
+ {
+ public static readonly BindableProperty IsRunningProperty = BindableProperty.Create("IsRunning", typeof(bool), typeof(ActivityIndicator), default(bool));
+
+ public static readonly BindableProperty ColorProperty = BindableProperty.Create("Color", typeof(Color), typeof(ActivityIndicator), Color.Default);
+
+ public Color Color
+ {
+ get { return (Color)GetValue(ColorProperty); }
+ set { SetValue(ColorProperty, value); }
+ }
+
+ public bool IsRunning
+ {
+ get { return (bool)GetValue(IsRunningProperty); }
+ set { SetValue(IsRunningProperty, value); }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/AlertArguments.cs b/Xamarin.Forms.Core/AlertArguments.cs
new file mode 100644
index 00000000..87224cb4
--- /dev/null
+++ b/Xamarin.Forms.Core/AlertArguments.cs
@@ -0,0 +1,43 @@
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ internal class AlertArguments
+ {
+ public AlertArguments(string title, string message, string accept, string cancel)
+ {
+ Title = title;
+ Message = message;
+ Accept = accept;
+ Cancel = cancel;
+ Result = new TaskCompletionSource<bool>();
+ }
+
+ /// <summary>
+ /// Gets the text for the accept button. Can be null.
+ /// </summary>
+ public string Accept { get; private set; }
+
+ /// <summary>
+ /// Gets the text of the cancel button.
+ /// </summary>
+ public string Cancel { get; private set; }
+
+ /// <summary>
+ /// Gets the message for the alert. Can be null.
+ /// </summary>
+ public string Message { get; private set; }
+
+ public TaskCompletionSource<bool> Result { get; }
+
+ /// <summary>
+ /// Gets the title for the alert. Can be null.
+ /// </summary>
+ public string Title { get; private set; }
+
+ public void SetResult(bool result)
+ {
+ Result.TrySetResult(result);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/AnimatableKey.cs b/Xamarin.Forms.Core/AnimatableKey.cs
new file mode 100644
index 00000000..2a73ef6d
--- /dev/null
+++ b/Xamarin.Forms.Core/AnimatableKey.cs
@@ -0,0 +1,82 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ internal class AnimatableKey
+ {
+ public AnimatableKey(IAnimatable animatable, string handle)
+ {
+ if (animatable == null)
+ {
+ throw new ArgumentNullException(nameof(animatable));
+ }
+
+ if (string.IsNullOrEmpty(handle))
+ {
+ throw new ArgumentException("Argument is null or empty", nameof(handle));
+ }
+
+ Animatable = new WeakReference<IAnimatable>(animatable);
+ Handle = handle;
+ }
+
+ public WeakReference<IAnimatable> Animatable { get; }
+
+ public string Handle { get; }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+ return Equals((AnimatableKey)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ IAnimatable target;
+ if (!Animatable.TryGetTarget(out target))
+ {
+ return Handle?.GetHashCode() ?? 0;
+ }
+
+ return ((target?.GetHashCode() ?? 0) * 397) ^ (Handle?.GetHashCode() ?? 0);
+ }
+ }
+
+ protected bool Equals(AnimatableKey other)
+ {
+ if (!string.Equals(Handle, other.Handle))
+ {
+ return false;
+ }
+
+ IAnimatable thisAnimatable;
+
+ if (!Animatable.TryGetTarget(out thisAnimatable))
+ {
+ return false;
+ }
+
+ IAnimatable thatAnimatable;
+
+ if (!other.Animatable.TryGetTarget(out thatAnimatable))
+ {
+ return false;
+ }
+
+ return Equals(thisAnimatable, thatAnimatable);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Animation.cs b/Xamarin.Forms.Core/Animation.cs
new file mode 100644
index 00000000..03cded1e
--- /dev/null
+++ b/Xamarin.Forms.Core/Animation.cs
@@ -0,0 +1,138 @@
+//
+// Tweener.cs
+//
+// Author:
+// Jason Smith <jason.smith@xamarin.com>
+//
+// Copyright (c) 2012 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ public class Animation : IEnumerable
+ {
+ readonly List<Animation> _children;
+ readonly Easing _easing;
+ readonly Action _finished;
+ readonly Action<double> _step;
+ double _beginAt;
+ double _finishAt;
+ bool _finishedTriggered;
+
+ public Animation()
+ {
+ _children = new List<Animation>();
+ _easing = Easing.Linear;
+ _step = f => { };
+ }
+
+ public Animation(Action<double> callback, double start = 0.0f, double end = 1.0f, Easing easing = null, Action finished = null)
+ {
+ _children = new List<Animation>();
+ _easing = easing ?? Easing.Linear;
+ _finished = finished;
+
+ Func<double, double> transform = AnimationExtensions.Interpolate(start, end);
+ _step = f => callback(transform(f));
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _children.GetEnumerator();
+ }
+
+ public void Add(double beginAt, double finishAt, Animation animation)
+ {
+ if (beginAt < 0 || beginAt > 1)
+ throw new ArgumentOutOfRangeException("beginAt");
+
+ if (finishAt < 0 || finishAt > 1)
+ throw new ArgumentOutOfRangeException("finishAt");
+
+ if (finishAt <= beginAt)
+ throw new ArgumentException("finishAt must be greater than beginAt");
+
+ animation._beginAt = beginAt;
+ animation._finishAt = finishAt;
+ _children.Add(animation);
+ }
+
+ public void Commit(IAnimatable owner, string name, uint rate = 16, uint length = 250, Easing easing = null, Action<double, bool> finished = null, Func<bool> repeat = null)
+ {
+ owner.Animate(name, this, rate, length, easing, finished, repeat);
+ }
+
+ public Action<double> GetCallback()
+ {
+ Action<double> result = f =>
+ {
+ _step(_easing.Ease(f));
+ foreach (Animation animation in _children)
+ {
+ if (animation._finishedTriggered)
+ continue;
+
+ double val = Math.Max(0.0f, Math.Min(1.0f, (f - animation._beginAt) / (animation._finishAt - animation._beginAt)));
+
+ if (val <= 0.0f) // not ready to process yet
+ continue;
+
+ Action<double> callback = animation.GetCallback();
+ callback(val);
+
+ if (val >= 1.0f)
+ {
+ animation._finishedTriggered = true;
+ if (animation._finished != null)
+ animation._finished();
+ }
+ }
+ };
+ return result;
+ }
+
+ public Animation Insert(double beginAt, double finishAt, Animation animation)
+ {
+ Add(beginAt, finishAt, animation);
+ return this;
+ }
+
+ public Animation WithConcurrent(Animation animation, double beginAt = 0.0f, double finishAt = 1.0f)
+ {
+ animation._beginAt = beginAt;
+ animation._finishAt = finishAt;
+ _children.Add(animation);
+ return this;
+ }
+
+ public Animation WithConcurrent(Action<double> callback, double start = 0.0f, double end = 1.0f, Easing easing = null, double beginAt = 0.0f, double finishAt = 1.0f)
+ {
+ var child = new Animation(callback, start, end, easing);
+ child._beginAt = beginAt;
+ child._finishAt = finishAt;
+ _children.Add(child);
+ return this;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/AnimationExtensions.cs b/Xamarin.Forms.Core/AnimationExtensions.cs
new file mode 100644
index 00000000..efc3e405
--- /dev/null
+++ b/Xamarin.Forms.Core/AnimationExtensions.cs
@@ -0,0 +1,259 @@
+//
+// Tweener.cs
+//
+// Author:
+// Jason Smith <jason.smith@xamarin.com>
+//
+// Copyright (c) 2012 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ public static class AnimationExtensions
+ {
+ static readonly Dictionary<AnimatableKey, Info> s_animations;
+ static readonly Dictionary<AnimatableKey, int> s_kinetics;
+
+ static AnimationExtensions()
+ {
+ s_animations = new Dictionary<AnimatableKey, Info>();
+ s_kinetics = new Dictionary<AnimatableKey, int>();
+ }
+
+ public static bool AbortAnimation(this IAnimatable self, string handle)
+ {
+ CheckAccess();
+
+ var key = new AnimatableKey(self, handle);
+
+ return AbortAnimation(key) && AbortKinetic(key);
+ }
+
+ public static void Animate(this IAnimatable self, string name, Animation animation, uint rate = 16, uint length = 250, Easing easing = null, Action<double, bool> finished = null,
+ Func<bool> repeat = null)
+ {
+ self.Animate(name, animation.GetCallback(), rate, length, easing, finished, repeat);
+ }
+
+ public static void Animate(this IAnimatable self, string name, Action<double> callback, double start, double end, uint rate = 16, uint length = 250, Easing easing = null,
+ Action<double, bool> finished = null, Func<bool> repeat = null)
+ {
+ self.Animate(name, Interpolate(start, end), callback, rate, length, easing, finished, repeat);
+ }
+
+ public static void Animate(this IAnimatable self, string name, Action<double> callback, uint rate = 16, uint length = 250, Easing easing = null, Action<double, bool> finished = null,
+ Func<bool> repeat = null)
+ {
+ self.Animate(name, x => x, callback, rate, length, easing, finished, repeat);
+ }
+
+ public static void Animate<T>(this IAnimatable self, string name, Func<double, T> transform, Action<T> callback, uint rate = 16, uint length = 250, Easing easing = null,
+ Action<T, bool> finished = null, Func<bool> repeat = null)
+ {
+ if (transform == null)
+ throw new ArgumentNullException(nameof(transform));
+ if (callback == null)
+ throw new ArgumentNullException(nameof(callback));
+ if (self == null)
+ throw new ArgumentNullException(nameof(self));
+
+ CheckAccess();
+
+ var key = new AnimatableKey(self, name);
+
+ AbortAnimation(key);
+
+ Action<double> step = f => callback(transform(f));
+ Action<double, bool> final = null;
+ if (finished != null)
+ final = (f, b) => finished(transform(f), b);
+
+ var info = new Info { Rate = rate, Length = length, Easing = easing ?? Easing.Linear };
+
+ var tweener = new Tweener(info.Length);
+ tweener.Handle = key;
+ tweener.ValueUpdated += HandleTweenerUpdated;
+ tweener.Finished += HandleTweenerFinished;
+
+ info.Tweener = tweener;
+ info.Callback = step;
+ info.Finished = final;
+ info.Repeat = repeat;
+ info.Owner = new WeakReference<IAnimatable>(self);
+
+ s_animations[key] = info;
+
+ info.Callback(0.0f);
+ tweener.Start();
+ }
+
+ public static void AnimateKinetic(this IAnimatable self, string name, Func<double, double, bool> callback, double velocity, double drag, Action finished = null)
+ {
+ CheckAccess();
+
+ var key = new AnimatableKey(self, name);
+
+ AbortKinetic(key);
+
+ double sign = velocity / Math.Abs(velocity);
+ velocity = Math.Abs(velocity);
+
+ int tick = Ticker.Default.Insert(step =>
+ {
+ long ms = step;
+
+ velocity -= drag * ms;
+ velocity = Math.Max(0, velocity);
+
+ var result = false;
+ if (velocity > 0)
+ {
+ result = callback(sign * velocity * ms, velocity);
+ }
+
+ if (!result)
+ {
+ finished?.Invoke();
+ s_kinetics.Remove(key);
+ }
+ return result;
+ });
+
+ s_kinetics[key] = tick;
+ }
+
+ public static bool AnimationIsRunning(this IAnimatable self, string handle)
+ {
+ CheckAccess();
+
+ var key = new AnimatableKey(self, handle);
+
+ return s_animations.ContainsKey(key);
+ }
+
+ public static Func<double, double> Interpolate(double start, double end = 1.0f, double reverseVal = 0.0f, bool reverse = false)
+ {
+ double target = reverse ? reverseVal : end;
+ return x => start + (target - start) * x;
+ }
+
+ static bool AbortAnimation(AnimatableKey key)
+ {
+ if (!s_animations.ContainsKey(key))
+ {
+ return false;
+ }
+
+ Info info = s_animations[key];
+ info.Tweener.ValueUpdated -= HandleTweenerUpdated;
+ info.Tweener.Finished -= HandleTweenerFinished;
+ info.Tweener.Stop();
+ info.Finished?.Invoke(1.0f, true);
+
+ return s_animations.Remove(key);
+ }
+
+ static bool AbortKinetic(AnimatableKey key)
+ {
+ if (!s_kinetics.ContainsKey(key))
+ {
+ return false;
+ }
+
+ Ticker.Default.Remove(s_kinetics[key]);
+ return s_kinetics.Remove(key);
+ }
+
+ static void CheckAccess()
+ {
+ if (Device.IsInvokeRequired)
+ {
+ throw new InvalidOperationException("Animation operations must be invoked on the UI thread");
+ }
+ }
+
+ static void HandleTweenerFinished(object o, EventArgs args)
+ {
+ var tweener = o as Tweener;
+ Info info;
+ if (tweener != null && s_animations.TryGetValue(tweener.Handle, out info))
+ {
+ var repeat = false;
+ if (info.Repeat != null)
+ repeat = info.Repeat();
+
+ IAnimatable owner;
+ if (info.Owner.TryGetTarget(out owner))
+ owner.BatchBegin();
+ info.Callback(tweener.Value);
+
+ if (!repeat)
+ {
+ s_animations.Remove(tweener.Handle);
+ tweener.ValueUpdated -= HandleTweenerUpdated;
+ tweener.Finished -= HandleTweenerFinished;
+ }
+
+ info.Finished?.Invoke(tweener.Value, false);
+
+ if (info.Owner.TryGetTarget(out owner))
+ owner.BatchCommit();
+
+ if (repeat)
+ {
+ tweener.Start();
+ }
+ }
+ }
+
+ static void HandleTweenerUpdated(object o, EventArgs args)
+ {
+ var tweener = o as Tweener;
+ Info info;
+ IAnimatable owner;
+
+ if (tweener != null && s_animations.TryGetValue(tweener.Handle, out info) && info.Owner.TryGetTarget(out owner))
+ {
+ owner.BatchBegin();
+ info.Callback(info.Easing.Ease(tweener.Value));
+ owner.BatchCommit();
+ }
+ }
+
+ class Info
+ {
+ public Action<double> Callback;
+ public Action<double, bool> Finished;
+ public Func<bool> Repeat;
+ public Tweener Tweener;
+
+ public Easing Easing { get; set; }
+
+ public uint Length { get; set; }
+
+ public WeakReference<IAnimatable> Owner { get; set; }
+
+ public uint Rate { get; set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Application.cs b/Xamarin.Forms.Core/Application.cs
new file mode 100644
index 00000000..1dfe258b
--- /dev/null
+++ b/Xamarin.Forms.Core/Application.cs
@@ -0,0 +1,308 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ public class Application : Element, IResourcesProvider, IApplicationController
+ {
+ static Application s_current;
+ readonly Task<IDictionary<string, object>> _propertiesTask;
+
+ bool _isSaving;
+
+ ReadOnlyCollection<Element> _logicalChildren;
+
+ Page _mainPage;
+
+ ResourceDictionary _resources;
+ bool _saveAgain;
+
+ protected Application()
+ {
+ var f = false;
+ if (f)
+ Loader.Load();
+ NavigationProxy = new NavigationImpl(this);
+ Current = this;
+ _propertiesTask = GetPropertiesAsync();
+
+ SystemResources = DependencyService.Get<ISystemResourcesProvider>().GetSystemResources();
+ SystemResources.ValuesChanged += OnParentResourcesChanged;
+ }
+
+ public static Application Current
+ {
+ get { return s_current; }
+ internal set
+ {
+ if (s_current == value)
+ return;
+ if (value == null)
+ s_current = null; //Allow to reset current for unittesting
+ s_current = value;
+ }
+ }
+
+ public Page MainPage
+ {
+ get { return _mainPage; }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (_mainPage == value)
+ return;
+
+ OnPropertyChanging();
+ if (_mainPage != null)
+ {
+ InternalChildren.Remove(_mainPage);
+ _mainPage.Parent = null;
+ }
+
+ _mainPage = value;
+
+ if (_mainPage != null)
+ {
+ _mainPage.Parent = this;
+ _mainPage.NavigationProxy.Inner = NavigationProxy;
+ InternalChildren.Add(_mainPage);
+ }
+ OnPropertyChanged();
+ }
+ }
+
+ public IDictionary<string, object> Properties
+ {
+ get { return _propertiesTask.Result; }
+ }
+
+ internal override ReadOnlyCollection<Element> LogicalChildren
+ {
+ get { return _logicalChildren ?? (_logicalChildren = new ReadOnlyCollection<Element>(InternalChildren)); }
+ }
+
+ internal NavigationProxy NavigationProxy { get; }
+
+ internal int PanGestureId { get; set; }
+
+ internal IResourceDictionary SystemResources { get; }
+
+ ObservableCollection<Element> InternalChildren { get; } = new ObservableCollection<Element>();
+
+ public ResourceDictionary Resources
+ {
+ get { return _resources; }
+ set
+ {
+ if (_resources == value)
+ return;
+ OnPropertyChanging();
+ if (_resources != null)
+ ((IResourceDictionary)_resources).ValuesChanged -= OnResourcesChanged;
+ _resources = value;
+ OnResourcesChanged(value);
+ if (_resources != null)
+ ((IResourceDictionary)_resources).ValuesChanged += OnResourcesChanged;
+ OnPropertyChanged();
+ }
+ }
+
+ public event EventHandler<ModalPoppedEventArgs> ModalPopped;
+
+ public event EventHandler<ModalPoppingEventArgs> ModalPopping;
+
+ public event EventHandler<ModalPushedEventArgs> ModalPushed;
+
+ public event EventHandler<ModalPushingEventArgs> ModalPushing;
+
+ public async Task SavePropertiesAsync()
+ {
+ if (Device.IsInvokeRequired)
+ Device.BeginInvokeOnMainThread(async () => await SetPropertiesAsync());
+ else
+ await SetPropertiesAsync();
+ }
+
+ protected override void OnParentSet()
+ {
+ throw new InvalidOperationException("Setting a Parent on Application is invalid.");
+ }
+
+ protected virtual void OnResume()
+ {
+ }
+
+ protected virtual void OnSleep()
+ {
+ }
+
+ protected virtual void OnStart()
+ {
+ }
+
+ internal static void ClearCurrent()
+ {
+ s_current = null;
+ }
+
+ internal static bool IsApplicationOrNull(Element element)
+ {
+ return element == null || element is Application;
+ }
+
+ internal override void OnParentResourcesChanged(IEnumerable<KeyValuePair<string, object>> values)
+ {
+ if (Resources == null || Resources.Count == 0)
+ {
+ base.OnParentResourcesChanged(values);
+ return;
+ }
+
+ var innerKeys = new HashSet<string>();
+ var changedResources = new List<KeyValuePair<string, object>>();
+ foreach (KeyValuePair<string, object> c in Resources)
+ innerKeys.Add(c.Key);
+ foreach (KeyValuePair<string, object> value in values)
+ {
+ if (innerKeys.Add(value.Key))
+ changedResources.Add(value);
+ }
+ OnResourcesChanged(changedResources);
+ }
+
+ internal event EventHandler PopCanceled;
+
+ internal void SendResume()
+ {
+ s_current = this;
+ OnResume();
+ }
+
+ internal Task SendSleepAsync()
+ {
+ OnSleep();
+ return SavePropertiesAsync();
+ }
+
+ internal void SendStart()
+ {
+ OnStart();
+ }
+
+ async Task<IDictionary<string, object>> GetPropertiesAsync()
+ {
+ var deserializer = DependencyService.Get<IDeserializer>();
+ if (deserializer == null)
+ {
+ Log.Warning("Startup", "No IDeserialzier was found registered");
+ return new Dictionary<string, object>(4);
+ }
+
+ IDictionary<string, object> properties = await deserializer.DeserializePropertiesAsync().ConfigureAwait(false);
+ if (properties == null)
+ properties = new Dictionary<string, object>(4);
+
+ return properties;
+ }
+
+ void OnModalPopped(Page modalPage)
+ {
+ EventHandler<ModalPoppedEventArgs> handler = ModalPopped;
+ if (handler != null)
+ handler(this, new ModalPoppedEventArgs(modalPage));
+ }
+
+ bool OnModalPopping(Page modalPage)
+ {
+ EventHandler<ModalPoppingEventArgs> handler = ModalPopping;
+ var args = new ModalPoppingEventArgs(modalPage);
+ if (handler != null)
+ handler(this, args);
+ return args.Cancel;
+ }
+
+ void OnModalPushed(Page modalPage)
+ {
+ EventHandler<ModalPushedEventArgs> handler = ModalPushed;
+ if (handler != null)
+ handler(this, new ModalPushedEventArgs(modalPage));
+ }
+
+ void OnModalPushing(Page modalPage)
+ {
+ EventHandler<ModalPushingEventArgs> handler = ModalPushing;
+ if (handler != null)
+ handler(this, new ModalPushingEventArgs(modalPage));
+ }
+
+ void OnPopCanceled()
+ {
+ EventHandler handler = PopCanceled;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+
+ async Task SetPropertiesAsync()
+ {
+ if (_isSaving)
+ {
+ _saveAgain = true;
+ return;
+ }
+ _isSaving = true;
+ await DependencyService.Get<IDeserializer>().SerializePropertiesAsync(Properties);
+ if (_saveAgain)
+ await DependencyService.Get<IDeserializer>().SerializePropertiesAsync(Properties);
+ _isSaving = _saveAgain = false;
+ }
+
+ class NavigationImpl : NavigationProxy
+ {
+ readonly Application _owner;
+
+ public NavigationImpl(Application owner)
+ {
+ _owner = owner;
+ }
+
+ protected override async Task<Page> OnPopModal(bool animated)
+ {
+ Page modal = ModalStack[ModalStack.Count - 1];
+ if (_owner.OnModalPopping(modal))
+ {
+ _owner.OnPopCanceled();
+ return null;
+ }
+ Page result = await base.OnPopModal(animated);
+ result.Parent = null;
+ _owner.OnModalPopped(result);
+ return result;
+ }
+
+ protected override async Task OnPushModal(Page modal, bool animated)
+ {
+ _owner.OnModalPushing(modal);
+
+ modal.Parent = _owner;
+
+ if (modal.NavigationProxy.ModalStack.Count == 0)
+ {
+ modal.NavigationProxy.Inner = this;
+ await base.OnPushModal(modal, animated);
+ }
+ else
+ {
+ await base.OnPushModal(modal, animated);
+ modal.NavigationProxy.Inner = this;
+ }
+
+ _owner.OnModalPushed(modal);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Aspect.cs b/Xamarin.Forms.Core/Aspect.cs
new file mode 100644
index 00000000..6a0085ca
--- /dev/null
+++ b/Xamarin.Forms.Core/Aspect.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Forms
+{
+ public enum Aspect
+ {
+ AspectFit,
+ AspectFill,
+ Fill
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BackButtonPressedEventArgs.cs b/Xamarin.Forms.Core/BackButtonPressedEventArgs.cs
new file mode 100644
index 00000000..2cc9a185
--- /dev/null
+++ b/Xamarin.Forms.Core/BackButtonPressedEventArgs.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class BackButtonPressedEventArgs : EventArgs
+ {
+ public bool Handled { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BaseMenuItem.cs b/Xamarin.Forms.Core/BaseMenuItem.cs
new file mode 100644
index 00000000..58831aa5
--- /dev/null
+++ b/Xamarin.Forms.Core/BaseMenuItem.cs
@@ -0,0 +1,6 @@
+namespace Xamarin.Forms
+{
+ public abstract class BaseMenuItem : Element
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BindableObject.cs b/Xamarin.Forms.Core/BindableObject.cs
new file mode 100644
index 00000000..683d390a
--- /dev/null
+++ b/Xamarin.Forms.Core/BindableObject.cs
@@ -0,0 +1,647 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms
+{
+ public abstract class BindableObject : INotifyPropertyChanged, IDynamicResourceHandler
+ {
+ public static readonly BindableProperty BindingContextProperty = BindableProperty.Create("BindingContext", typeof(object), typeof(BindableObject), default(object), BindingMode.OneWay, null,
+ BindingContextPropertyBindingPropertyChanged, null, null, BindingContextPropertyBindingChanging);
+
+ readonly List<BindablePropertyContext> _properties = new List<BindablePropertyContext>(4);
+
+ bool _applying;
+
+ object _inheritedContext;
+
+ public object BindingContext
+ {
+ get { return _inheritedContext ?? GetValue(BindingContextProperty); }
+ set { SetValue(BindingContextProperty, value); }
+ }
+
+ void IDynamicResourceHandler.SetDynamicResource(BindableProperty property, string key)
+ {
+ SetDynamicResource(property, key, false);
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public event EventHandler BindingContextChanged;
+
+ public void ClearValue(BindableProperty property)
+ {
+ ClearValue(property, true);
+ }
+
+ public void ClearValue(BindablePropertyKey propertyKey)
+ {
+ if (propertyKey == null)
+ throw new ArgumentNullException("propertyKey");
+
+ ClearValue(propertyKey.BindableProperty, false);
+ }
+
+ public object GetValue(BindableProperty property)
+ {
+ if (property == null)
+ throw new ArgumentNullException("property");
+
+ BindablePropertyContext context = property.DefaultValueCreator != null ? GetOrCreateContext(property) : GetContext(property);
+
+ if (context == null)
+ return property.DefaultValue;
+
+ return context.Value;
+ }
+
+ public event PropertyChangingEventHandler PropertyChanging;
+
+ public void RemoveBinding(BindableProperty property)
+ {
+ if (property == null)
+ throw new ArgumentNullException("property");
+
+ BindablePropertyContext context = GetContext(property);
+ if (context == null || context.Binding == null)
+ return;
+
+ RemoveBinding(property, context);
+ }
+
+ public void SetBinding(BindableProperty targetProperty, BindingBase binding)
+ {
+ SetBinding(targetProperty, binding, false);
+ }
+
+ public void SetValue(BindableProperty property, object value)
+ {
+ SetValue(property, value, false, true);
+ }
+
+ public void SetValue(BindablePropertyKey propertyKey, object value)
+ {
+ if (propertyKey == null)
+ throw new ArgumentNullException("propertyKey");
+
+ SetValue(propertyKey.BindableProperty, value, false, false);
+ }
+
+ protected internal static void SetInheritedBindingContext(BindableObject bindable, object value)
+ {
+ BindablePropertyContext bpContext = bindable.GetContext(BindingContextProperty);
+ if (bpContext != null && ((bpContext.Attributes & BindableContextAttributes.IsManuallySet) != 0))
+ return;
+
+ object oldContext = bindable._inheritedContext;
+ if (bpContext != null && oldContext == null)
+ oldContext = bpContext.Value;
+
+ if (bpContext != null && bpContext.Binding != null)
+ {
+ bpContext.Binding.Context = value;
+ bindable._inheritedContext = null;
+ }
+ else
+ {
+ if (ReferenceEquals(oldContext, value))
+ return;
+
+ bindable._inheritedContext = value;
+ }
+
+ bindable.ApplyBindings(oldContext);
+ bindable.OnBindingContextChanged();
+ }
+
+ protected void ApplyBindings(object oldContext = null)
+ {
+ ApplyBindings(oldContext, false);
+ }
+
+ protected virtual void OnBindingContextChanged()
+ {
+ EventHandler change = BindingContextChanged;
+ if (change != null)
+ change(this, EventArgs.Empty);
+ }
+
+ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler(this, new PropertyChangedEventArgs(propertyName));
+ }
+
+ protected virtual void OnPropertyChanging([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangingEventHandler changing = PropertyChanging;
+ if (changing != null)
+ changing(this, new PropertyChangingEventArgs(propertyName));
+ }
+
+ protected void UnapplyBindings()
+ {
+ foreach (BindablePropertyContext context in _properties)
+ {
+ if (context.Binding == null)
+ continue;
+
+ context.Binding.Unapply();
+ }
+ }
+
+ internal bool GetIsBound(BindableProperty targetProperty)
+ {
+ if (targetProperty == null)
+ throw new ArgumentNullException("targetProperty");
+
+ BindablePropertyContext bpcontext = GetContext(targetProperty);
+ return bpcontext != null && bpcontext.Binding != null;
+ }
+
+ internal object[] GetValues(BindableProperty property0, BindableProperty property1)
+ {
+ var values = new object[2];
+
+ for (var i = 0; i < _properties.Count; i++)
+ {
+ BindablePropertyContext context = _properties[i];
+
+ if (ReferenceEquals(context.Property, property0))
+ {
+ values[0] = context.Value;
+ property0 = null;
+ }
+ else if (ReferenceEquals(context.Property, property1))
+ {
+ values[1] = context.Value;
+ property1 = null;
+ }
+
+ if (property0 == null && property1 == null)
+ return values;
+ }
+
+ if (!ReferenceEquals(property0, null))
+ values[0] = property0.DefaultValueCreator == null ? property0.DefaultValue : CreateAndAddContext(property0).Value;
+ if (!ReferenceEquals(property1, null))
+ values[1] = property1.DefaultValueCreator == null ? property1.DefaultValue : CreateAndAddContext(property1).Value;
+
+ return values;
+ }
+
+ internal object[] GetValues(BindableProperty property0, BindableProperty property1, BindableProperty property2)
+ {
+ var values = new object[3];
+
+ for (var i = 0; i < _properties.Count; i++)
+ {
+ BindablePropertyContext context = _properties[i];
+
+ if (ReferenceEquals(context.Property, property0))
+ {
+ values[0] = context.Value;
+ property0 = null;
+ }
+ else if (ReferenceEquals(context.Property, property1))
+ {
+ values[1] = context.Value;
+ property1 = null;
+ }
+ else if (ReferenceEquals(context.Property, property2))
+ {
+ values[2] = context.Value;
+ property2 = null;
+ }
+
+ if (property0 == null && property1 == null && property2 == null)
+ return values;
+ }
+
+ if (!ReferenceEquals(property0, null))
+ values[0] = property0.DefaultValueCreator == null ? property0.DefaultValue : CreateAndAddContext(property0).Value;
+ if (!ReferenceEquals(property1, null))
+ values[1] = property1.DefaultValueCreator == null ? property1.DefaultValue : CreateAndAddContext(property1).Value;
+ if (!ReferenceEquals(property2, null))
+ values[2] = property2.DefaultValueCreator == null ? property2.DefaultValue : CreateAndAddContext(property2).Value;
+
+ return values;
+ }
+
+ internal virtual void OnRemoveDynamicResource(BindableProperty property)
+ {
+ }
+
+ internal virtual void OnSetDynamicResource(BindableProperty property, string key)
+ {
+ }
+
+ internal void RemoveDynamicResource(BindableProperty property)
+ {
+ if (property == null)
+ throw new ArgumentNullException("property");
+
+ OnRemoveDynamicResource(property);
+ BindablePropertyContext context = GetOrCreateContext(property);
+ context.Attributes &= ~BindableContextAttributes.IsDynamicResource;
+ }
+
+ internal void SetBinding(BindableProperty targetProperty, BindingBase binding, bool fromStyle)
+ {
+ if (targetProperty == null)
+ throw new ArgumentNullException("targetProperty");
+ if (binding == null)
+ throw new ArgumentNullException("binding");
+
+ BindablePropertyContext context = null;
+ if (fromStyle && (context = GetContext(targetProperty)) != null && (context.Attributes & BindableContextAttributes.IsDefaultValue) == 0 &&
+ (context.Attributes & BindableContextAttributes.IsSetFromStyle) == 0)
+ return;
+
+ context = context ?? GetOrCreateContext(targetProperty);
+ if (fromStyle)
+ context.Attributes |= BindableContextAttributes.IsSetFromStyle;
+ else
+ context.Attributes &= ~BindableContextAttributes.IsSetFromStyle;
+
+ if (context.Binding != null)
+ context.Binding.Unapply();
+
+ BindingBase oldBinding = context.Binding;
+ context.Binding = binding;
+
+ if (targetProperty.BindingChanging != null)
+ targetProperty.BindingChanging(this, oldBinding, binding);
+
+ binding.Apply(BindingContext, this, targetProperty);
+ }
+
+ internal void SetDynamicResource(BindableProperty property, string key)
+ {
+ SetDynamicResource(property, key, false);
+ }
+
+ internal void SetDynamicResource(BindableProperty property, string key, bool fromStyle)
+ {
+ if (property == null)
+ throw new ArgumentNullException("property");
+ if (string.IsNullOrEmpty(key))
+ throw new ArgumentNullException("key");
+
+ BindablePropertyContext context = null;
+ if (fromStyle && (context = GetContext(property)) != null && (context.Attributes & BindableContextAttributes.IsDefaultValue) == 0 &&
+ (context.Attributes & BindableContextAttributes.IsSetFromStyle) == 0)
+ return;
+
+ context = context ?? GetOrCreateContext(property);
+
+ context.Attributes |= BindableContextAttributes.IsDynamicResource;
+ if (fromStyle)
+ context.Attributes |= BindableContextAttributes.IsSetFromStyle;
+ else
+ context.Attributes &= ~BindableContextAttributes.IsSetFromStyle;
+
+ OnSetDynamicResource(property, key);
+ }
+
+ internal void SetValue(BindableProperty property, object value, bool fromStyle)
+ {
+ SetValue(property, value, fromStyle, true);
+ }
+
+ internal void SetValueCore(BindablePropertyKey propertyKey, object value, SetValueFlags attributes = SetValueFlags.None)
+ {
+ SetValueCore(propertyKey.BindableProperty, value, attributes, SetValuePrivateFlags.None);
+ }
+
+ internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes = SetValueFlags.None)
+ {
+ SetValueCore(property, value, attributes, SetValuePrivateFlags.Default);
+ }
+
+ internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
+ {
+ bool checkAccess = (privateAttributes & SetValuePrivateFlags.CheckAccess) != 0;
+ bool manuallySet = (privateAttributes & SetValuePrivateFlags.ManuallySet) != 0;
+ bool silent = (privateAttributes & SetValuePrivateFlags.Silent) != 0;
+ bool fromStyle = (privateAttributes & SetValuePrivateFlags.FromStyle) != 0;
+ bool converted = (privateAttributes & SetValuePrivateFlags.Converted) != 0;
+
+ if (property == null)
+ throw new ArgumentNullException("property");
+ if (checkAccess && property.IsReadOnly)
+ {
+ Debug.WriteLine("Can not set the BindableProperty \"{0}\" because it is readonly.", property.PropertyName);
+ return;
+ }
+
+ if (!converted && !property.TryConvert(ref value))
+ {
+ Log.Warning("SetValue", "Can not convert {0} to type '{1}'", value, property.ReturnType);
+ return;
+ }
+
+ if (property.ValidateValue != null && !property.ValidateValue(this, value))
+ throw new ArgumentException("Value was an invalid value for " + property.PropertyName, "value");
+
+ if (property.CoerceValue != null)
+ value = property.CoerceValue(this, value);
+
+ BindablePropertyContext context = GetOrCreateContext(property);
+ if (manuallySet)
+ context.Attributes |= BindableContextAttributes.IsManuallySet;
+ else
+ context.Attributes &= ~BindableContextAttributes.IsManuallySet;
+
+ if (fromStyle)
+ context.Attributes |= BindableContextAttributes.IsSetFromStyle;
+ // else ommitted on purpose
+
+ bool currentlyApplying = _applying;
+
+ if ((context.Attributes & BindableContextAttributes.IsBeingSet) != 0)
+ {
+ Queue<SetValueArgs> delayQueue = context.DelayedSetters;
+ if (delayQueue == null)
+ context.DelayedSetters = delayQueue = new Queue<SetValueArgs>();
+
+ delayQueue.Enqueue(new SetValueArgs(property, context, value, currentlyApplying, attributes));
+ }
+ else
+ {
+ context.Attributes |= BindableContextAttributes.IsBeingSet;
+ SetValueActual(property, context, value, currentlyApplying, attributes, silent);
+
+ Queue<SetValueArgs> delayQueue = context.DelayedSetters;
+ if (delayQueue != null)
+ {
+ while (delayQueue.Count > 0)
+ {
+ SetValueArgs s = delayQueue.Dequeue();
+ SetValueActual(s.Property, s.Context, s.Value, s.CurrentlyApplying, s.Attributes);
+ }
+
+ context.DelayedSetters = null;
+ }
+
+ context.Attributes &= ~BindableContextAttributes.IsBeingSet;
+ }
+ }
+
+ void ApplyBindings(object oldContext, bool skipBindingContext)
+ {
+ foreach (BindablePropertyContext context in _properties.ToArray())
+ {
+ BindingBase binding = context.Binding;
+ if (binding == null)
+ continue;
+
+ if (skipBindingContext && context.Property == BindingContextProperty)
+ continue;
+
+ binding.Unapply();
+ binding.Apply(BindingContext, this, context.Property);
+ }
+ }
+
+ static void BindingContextPropertyBindingChanging(BindableObject bindable, BindingBase oldBindingBase, BindingBase newBindingBase)
+ {
+ object context = bindable._inheritedContext;
+ var oldBinding = oldBindingBase as Binding;
+ var newBinding = newBindingBase as Binding;
+
+ if (context == null && oldBinding != null)
+ context = oldBinding.Context;
+ if (context != null && newBinding != null)
+ newBinding.Context = context;
+ }
+
+ static void BindingContextPropertyBindingPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
+ {
+ object oldInheritedContext = bindable._inheritedContext;
+ bindable._inheritedContext = null;
+ bindable.ApplyBindings(oldInheritedContext ?? oldvalue, true);
+ bindable.OnBindingContextChanged();
+ }
+
+ void ClearValue(BindableProperty property, bool checkaccess)
+ {
+ if (property == null)
+ throw new ArgumentNullException("property");
+
+ if (checkaccess && property.IsReadOnly)
+ throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName));
+
+ BindablePropertyContext bpcontext = GetContext(property);
+ if (bpcontext == null)
+ return;
+
+ object original = bpcontext.Value;
+
+ object newValue = property.GetDefaultValue(this);
+
+ bool same = Equals(original, newValue);
+ if (!same)
+ {
+ if (property.PropertyChanging != null)
+ property.PropertyChanging(this, original, newValue);
+
+ OnPropertyChanging(property.PropertyName);
+ }
+
+ bpcontext.Attributes &= ~BindableContextAttributes.IsManuallySet;
+ bpcontext.Value = newValue;
+ bpcontext.Attributes |= BindableContextAttributes.IsDefaultValue;
+
+ if (!same)
+ {
+ OnPropertyChanged(property.PropertyName);
+ if (property.PropertyChanged != null)
+ property.PropertyChanged(this, original, newValue);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ BindablePropertyContext CreateAndAddContext(BindableProperty property)
+ {
+ var context = new BindablePropertyContext { Property = property, Value = property.DefaultValueCreator != null ? property.DefaultValueCreator(this) : property.DefaultValue };
+
+ if (property.DefaultValueCreator != null)
+ context.Attributes = BindableContextAttributes.IsDefaultValue;
+
+ _properties.Add(context);
+ return context;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ BindablePropertyContext GetContext(BindableProperty property)
+ {
+ List<BindablePropertyContext> properties = _properties;
+
+ for (var i = 0; i < properties.Count; i++)
+ {
+ BindablePropertyContext context = properties[i];
+ if (ReferenceEquals(context.Property, property))
+ return context;
+ }
+
+ return null;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ BindablePropertyContext GetOrCreateContext(BindableProperty property)
+ {
+ BindablePropertyContext context = GetContext(property);
+ if (context == null)
+ {
+ context = CreateAndAddContext(property);
+ }
+
+ return context;
+ }
+
+ void RemoveBinding(BindableProperty property, BindablePropertyContext context)
+ {
+ context.Binding.Unapply();
+
+ if (property.BindingChanging != null)
+ property.BindingChanging(this, context.Binding, null);
+
+ context.Binding = null;
+ }
+
+ void SetValue(BindableProperty property, object value, bool fromStyle, bool checkAccess)
+ {
+ if (property == null)
+ throw new ArgumentNullException("property");
+
+ if (checkAccess && property.IsReadOnly)
+ throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName));
+
+ BindablePropertyContext context = null;
+ if (fromStyle && (context = GetContext(property)) != null && (context.Attributes & BindableContextAttributes.IsDefaultValue) == 0 &&
+ (context.Attributes & BindableContextAttributes.IsSetFromStyle) == 0)
+ return;
+
+ SetValueCore(property, value, SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearDynamicResource,
+ (fromStyle ? SetValuePrivateFlags.FromStyle : SetValuePrivateFlags.ManuallySet) | (checkAccess ? SetValuePrivateFlags.CheckAccess : 0));
+ }
+
+ void SetValueActual(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, SetValueFlags attributes, bool silent = false)
+ {
+ object original = context.Value;
+ bool raiseOnEqual = (attributes & SetValueFlags.RaiseOnEqual) != 0;
+ bool clearDynamicResources = (attributes & SetValueFlags.ClearDynamicResource) != 0;
+ bool clearOneWayBindings = (attributes & SetValueFlags.ClearOneWayBindings) != 0;
+ bool clearTwoWayBindings = (attributes & SetValueFlags.ClearTwoWayBindings) != 0;
+
+ bool same = Equals(value, original);
+ if (!silent && (!same || raiseOnEqual))
+ {
+ if (property.PropertyChanging != null)
+ property.PropertyChanging(this, original, value);
+
+ OnPropertyChanging(property.PropertyName);
+ }
+
+ if (!same || raiseOnEqual)
+ {
+ context.Value = value;
+ }
+
+ context.Attributes &= ~BindableContextAttributes.IsDefaultValue;
+
+ if ((context.Attributes & BindableContextAttributes.IsDynamicResource) != 0 && clearDynamicResources)
+ RemoveDynamicResource(property);
+
+ BindingBase binding = context.Binding;
+ if (binding != null)
+ {
+ if (clearOneWayBindings && binding.GetRealizedMode(property) == BindingMode.OneWay || clearTwoWayBindings && binding.GetRealizedMode(property) == BindingMode.TwoWay)
+ {
+ RemoveBinding(property, context);
+ binding = null;
+ }
+ }
+
+ if (!silent && (!same || raiseOnEqual))
+ {
+ if (binding != null && !currentlyApplying)
+ {
+ _applying = true;
+ binding.Apply(true);
+ _applying = false;
+ }
+
+ OnPropertyChanged(property.PropertyName);
+
+ if (property.PropertyChanged != null)
+ property.PropertyChanged(this, original, value);
+ }
+ }
+
+ [Flags]
+ enum BindableContextAttributes
+ {
+ IsManuallySet = 1 << 0,
+ IsBeingSet = 1 << 1,
+ IsDynamicResource = 1 << 2,
+ IsSetFromStyle = 1 << 3,
+ IsDefaultValue = 1 << 4
+ }
+
+ class BindablePropertyContext
+ {
+ public BindableContextAttributes Attributes;
+ public BindingBase Binding;
+ public Queue<SetValueArgs> DelayedSetters;
+ public BindableProperty Property;
+ public object Value;
+ }
+
+ [Flags]
+ internal enum SetValueFlags
+ {
+ None = 0,
+ ClearOneWayBindings = 1 << 0,
+ ClearTwoWayBindings = 1 << 1,
+ ClearDynamicResource = 1 << 2,
+ RaiseOnEqual = 1 << 3
+ }
+
+ [Flags]
+ internal enum SetValuePrivateFlags
+ {
+ None = 0,
+ CheckAccess = 1 << 0,
+ Silent = 1 << 1,
+ ManuallySet = 1 << 2,
+ FromStyle = 1 << 3,
+ Converted = 1 << 4,
+ Default = CheckAccess
+ }
+
+ class SetValueArgs
+ {
+ public readonly SetValueFlags Attributes;
+ public readonly BindablePropertyContext Context;
+ public readonly bool CurrentlyApplying;
+ public readonly BindableProperty Property;
+ public readonly object Value;
+
+ public SetValueArgs(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, SetValueFlags attributes)
+ {
+ Property = property;
+ Context = context;
+ Value = value;
+ CurrentlyApplying = currentlyApplying;
+ Attributes = attributes;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BindableObjectExtensions.cs b/Xamarin.Forms.Core/BindableObjectExtensions.cs
new file mode 100644
index 00000000..2eab2380
--- /dev/null
+++ b/Xamarin.Forms.Core/BindableObjectExtensions.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Linq.Expressions;
+
+namespace Xamarin.Forms
+{
+ public static class BindableObjectExtensions
+ {
+ public static void SetBinding(this BindableObject self, BindableProperty targetProperty, string path, BindingMode mode = BindingMode.Default, IValueConverter converter = null,
+ string stringFormat = null)
+ {
+ if (self == null)
+ throw new ArgumentNullException("self");
+ if (targetProperty == null)
+ throw new ArgumentNullException("targetProperty");
+
+ var binding = new Binding(path, mode, converter, stringFormat: stringFormat);
+ self.SetBinding(targetProperty, binding);
+ }
+
+ public static void SetBinding<TSource>(this BindableObject self, BindableProperty targetProperty, Expression<Func<TSource, object>> sourceProperty, BindingMode mode = BindingMode.Default,
+ IValueConverter converter = null, string stringFormat = null)
+ {
+ if (self == null)
+ throw new ArgumentNullException("self");
+ if (targetProperty == null)
+ throw new ArgumentNullException("targetProperty");
+ if (sourceProperty == null)
+ throw new ArgumentNullException("sourceProperty");
+
+ Binding binding = Binding.Create(sourceProperty, mode, converter, stringFormat: stringFormat);
+ self.SetBinding(targetProperty, binding);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BindableProperty.cs b/Xamarin.Forms.Core/BindableProperty.cs
new file mode 100644
index 00000000..f95d38ab
--- /dev/null
+++ b/Xamarin.Forms.Core/BindableProperty.cs
@@ -0,0 +1,331 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace Xamarin.Forms
+{
+ [DebuggerDisplay("{PropertyName}")]
+ [TypeConverter(typeof(BindablePropertyConverter))]
+ public sealed class BindableProperty
+ {
+ public delegate void BindingPropertyChangedDelegate(BindableObject bindable, object oldValue, object newValue);
+
+ public delegate void BindingPropertyChangedDelegate<in TPropertyType>(BindableObject bindable, TPropertyType oldValue, TPropertyType newValue);
+
+ public delegate void BindingPropertyChangingDelegate(BindableObject bindable, object oldValue, object newValue);
+
+ public delegate void BindingPropertyChangingDelegate<in TPropertyType>(BindableObject bindable, TPropertyType oldValue, TPropertyType newValue);
+
+ public delegate object CoerceValueDelegate(BindableObject bindable, object value);
+
+ public delegate TPropertyType CoerceValueDelegate<TPropertyType>(BindableObject bindable, TPropertyType value);
+
+ public delegate object CreateDefaultValueDelegate(BindableObject bindable);
+
+ public delegate TPropertyType CreateDefaultValueDelegate<in TDeclarer, out TPropertyType>(TDeclarer bindable);
+
+ public delegate bool ValidateValueDelegate(BindableObject bindable, object value);
+
+ public delegate bool ValidateValueDelegate<in TPropertyType>(BindableObject bindable, TPropertyType value);
+
+ // more or less the encoding of this, without the need to reflect
+ // http://msdn.microsoft.com/en-us/library/y5b434w4.aspx
+ static readonly Dictionary<Type, Type[]> SimpleConvertTypes = new Dictionary<Type, Type[]>
+ {
+ { typeof(sbyte), new[] { typeof(string), typeof(short), typeof(int), typeof(long), typeof(float), typeof(double), typeof(decimal) } },
+ { typeof(byte), new[] { typeof(string), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
+ { typeof(short), new[] { typeof(string), typeof(int), typeof(long), typeof(float), typeof(double), typeof(decimal) } },
+ { typeof(ushort), new[] { typeof(string), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
+ { typeof(int), new[] { typeof(string), typeof(long), typeof(float), typeof(double), typeof(decimal) } },
+ { typeof(uint), new[] { typeof(string), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
+ { typeof(long), new[] { typeof(string), typeof(float), typeof(double), typeof(decimal) } },
+ { typeof(char), new[] { typeof(string), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
+ { typeof(float), new[] { typeof(string), typeof(double) } },
+ { typeof(ulong), new[] { typeof(string), typeof(float), typeof(double), typeof(decimal) } }
+ };
+
+ BindableProperty(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay,
+ ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
+ CoerceValueDelegate coerceValue = null, BindablePropertyBindingChanging bindingChanging = null, bool isReadOnly = false, CreateDefaultValueDelegate defaultValueCreator = null)
+ {
+ if (propertyName == null)
+ throw new ArgumentNullException("propertyName");
+ if (ReferenceEquals(returnType, null))
+ throw new ArgumentNullException("returnType");
+ if (ReferenceEquals(declaringType, null))
+ throw new ArgumentNullException("declaringType");
+
+ // don't use Enum.IsDefined as its redonkulously expensive for what it does
+ if (defaultBindingMode != BindingMode.Default && defaultBindingMode != BindingMode.OneWay && defaultBindingMode != BindingMode.OneWayToSource && defaultBindingMode != BindingMode.TwoWay)
+ throw new ArgumentException("Not a valid type of BindingMode", "defaultBindingMode");
+ if (defaultValue == null && Nullable.GetUnderlyingType(returnType) == null && returnType.GetTypeInfo().IsValueType)
+ throw new ArgumentException("Not a valid default value", "defaultValue");
+ if (defaultValue != null && !returnType.IsInstanceOfType(defaultValue))
+ throw new ArgumentException("Default value did not match return type", "defaultValue");
+ if (defaultBindingMode == BindingMode.Default)
+ defaultBindingMode = BindingMode.OneWay;
+
+ PropertyName = propertyName;
+ ReturnType = returnType;
+ ReturnTypeInfo = returnType.GetTypeInfo();
+ DeclaringType = declaringType;
+ DefaultValue = defaultValue;
+ DefaultBindingMode = defaultBindingMode;
+ PropertyChanged = propertyChanged;
+ PropertyChanging = propertyChanging;
+ ValidateValue = validateValue;
+ CoerceValue = coerceValue;
+ BindingChanging = bindingChanging;
+ IsReadOnly = isReadOnly;
+ DefaultValueCreator = defaultValueCreator;
+ }
+
+ public Type DeclaringType { get; private set; }
+
+ public BindingMode DefaultBindingMode { get; private set; }
+
+ public object DefaultValue { get; }
+
+ public bool IsReadOnly { get; private set; }
+
+ public string PropertyName { get; }
+
+ public Type ReturnType { get; }
+
+ internal BindablePropertyBindingChanging BindingChanging { get; private set; }
+
+ internal CoerceValueDelegate CoerceValue { get; private set; }
+
+ internal CreateDefaultValueDelegate DefaultValueCreator { get; }
+
+ internal BindingPropertyChangedDelegate PropertyChanged { get; private set; }
+
+ internal BindingPropertyChangingDelegate PropertyChanging { get; private set; }
+
+ internal TypeInfo ReturnTypeInfo { get; }
+
+ internal ValidateValueDelegate ValidateValue { get; private set; }
+
+ [Obsolete("Generic versions of Create () are no longer supported and deprecated. They will be removed soon.")]
+ public static BindableProperty Create<TDeclarer, TPropertyType>(Expression<Func<TDeclarer, TPropertyType>> getter, TPropertyType defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay,
+ ValidateValueDelegate<TPropertyType> validateValue = null, BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null,
+ BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null, CoerceValueDelegate<TPropertyType> coerceValue = null,
+ CreateDefaultValueDelegate<TDeclarer, TPropertyType> defaultValueCreator = null) where TDeclarer : BindableObject
+ {
+ return Create(getter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, defaultValueCreator: defaultValueCreator);
+ }
+
+ public static BindableProperty Create(string propertyName, Type returnType, Type declaringType, object defaultValue = null, BindingMode defaultBindingMode = BindingMode.OneWay,
+ ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
+ CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
+ {
+ return new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue,
+ defaultValueCreator: defaultValueCreator);
+ }
+
+ [Obsolete("Generic versions of Create () are no longer supported and deprecated. They will be removed soon.")]
+ public static BindableProperty CreateAttached<TDeclarer, TPropertyType>(Expression<Func<BindableObject, TPropertyType>> staticgetter, TPropertyType defaultValue,
+ BindingMode defaultBindingMode = BindingMode.OneWay, ValidateValueDelegate<TPropertyType> validateValue = null, BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null,
+ BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null, CoerceValueDelegate<TPropertyType> coerceValue = null,
+ CreateDefaultValueDelegate<BindableObject, TPropertyType> defaultValueCreator = null)
+ {
+ return CreateAttached<TDeclarer, TPropertyType>(staticgetter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null,
+ defaultValueCreator: defaultValueCreator);
+ }
+
+ public static BindableProperty CreateAttached(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay,
+ ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
+ CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
+ {
+ return CreateAttached(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, false, defaultValueCreator);
+ }
+
+ [Obsolete("Generic versions of Create () are no longer supported and deprecated. They will be removed soon.")]
+ public static BindablePropertyKey CreateAttachedReadOnly<TDeclarer, TPropertyType>(Expression<Func<BindableObject, TPropertyType>> staticgetter, TPropertyType defaultValue,
+ BindingMode defaultBindingMode = BindingMode.OneWayToSource, ValidateValueDelegate<TPropertyType> validateValue = null,
+ BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null, BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null,
+ CoerceValueDelegate<TPropertyType> coerceValue = null, CreateDefaultValueDelegate<BindableObject, TPropertyType> defaultValueCreator = null)
+
+ {
+ return
+ new BindablePropertyKey(CreateAttached<TDeclarer, TPropertyType>(staticgetter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, true,
+ defaultValueCreator));
+ }
+
+ public static BindablePropertyKey CreateAttachedReadOnly(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWayToSource,
+ ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
+ CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
+ {
+ return
+ new BindablePropertyKey(CreateAttached(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, true,
+ defaultValueCreator));
+ }
+
+ [Obsolete("Generic versions of Create () are no longer supported and deprecated. They will be removed soon.")]
+ public static BindablePropertyKey CreateReadOnly<TDeclarer, TPropertyType>(Expression<Func<TDeclarer, TPropertyType>> getter, TPropertyType defaultValue,
+ BindingMode defaultBindingMode = BindingMode.OneWayToSource, ValidateValueDelegate<TPropertyType> validateValue = null,
+ BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null, BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null,
+ CoerceValueDelegate<TPropertyType> coerceValue = null, CreateDefaultValueDelegate<TDeclarer, TPropertyType> defaultValueCreator = null) where TDeclarer : BindableObject
+ {
+ return new BindablePropertyKey(Create(getter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, true, defaultValueCreator));
+ }
+
+ public static BindablePropertyKey CreateReadOnly(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWayToSource,
+ ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
+ CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
+ {
+ return
+ new BindablePropertyKey(new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue,
+ isReadOnly: true, defaultValueCreator: defaultValueCreator));
+ }
+
+ [Obsolete("Generic versions of Create () are no longer supported and deprecated. They will be removed soon.")]
+ internal static BindableProperty Create<TDeclarer, TPropertyType>(Expression<Func<TDeclarer, TPropertyType>> getter, TPropertyType defaultValue, BindingMode defaultBindingMode,
+ ValidateValueDelegate<TPropertyType> validateValue, BindingPropertyChangedDelegate<TPropertyType> propertyChanged, BindingPropertyChangingDelegate<TPropertyType> propertyChanging,
+ CoerceValueDelegate<TPropertyType> coerceValue, BindablePropertyBindingChanging bindingChanging, bool isReadOnly = false,
+ CreateDefaultValueDelegate<TDeclarer, TPropertyType> defaultValueCreator = null) where TDeclarer : BindableObject
+ {
+ if (getter == null)
+ throw new ArgumentNullException("getter");
+
+ Expression expr = getter.Body;
+
+ var unary = expr as UnaryExpression;
+ if (unary != null)
+ expr = unary.Operand;
+
+ var member = expr as MemberExpression;
+ if (member == null)
+ throw new ArgumentException("getter must be a MemberExpression", "getter");
+
+ var property = (PropertyInfo)member.Member;
+
+ ValidateValueDelegate untypedValidateValue = null;
+ BindingPropertyChangedDelegate untypedBindingPropertyChanged = null;
+ BindingPropertyChangingDelegate untypedBindingPropertyChanging = null;
+ CoerceValueDelegate untypedCoerceValue = null;
+ CreateDefaultValueDelegate untypedDefaultValueCreator = null;
+ if (validateValue != null)
+ untypedValidateValue = (bindable, value) => validateValue(bindable, (TPropertyType)value);
+ if (propertyChanged != null)
+ untypedBindingPropertyChanged = (bindable, oldValue, newValue) => propertyChanged(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
+ if (propertyChanging != null)
+ untypedBindingPropertyChanging = (bindable, oldValue, newValue) => propertyChanging(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
+ if (coerceValue != null)
+ untypedCoerceValue = (bindable, value) => coerceValue(bindable, (TPropertyType)value);
+ if (defaultValueCreator != null)
+ untypedDefaultValueCreator = o => defaultValueCreator((TDeclarer)o);
+
+ return new BindableProperty(property.Name, property.PropertyType, typeof(TDeclarer), defaultValue, defaultBindingMode, untypedValidateValue, untypedBindingPropertyChanged,
+ untypedBindingPropertyChanging, untypedCoerceValue, bindingChanging, isReadOnly, untypedDefaultValueCreator);
+ }
+
+ internal static BindableProperty Create(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode, ValidateValueDelegate validateValue,
+ BindingPropertyChangedDelegate propertyChanged, BindingPropertyChangingDelegate propertyChanging, CoerceValueDelegate coerceValue, BindablePropertyBindingChanging bindingChanging,
+ CreateDefaultValueDelegate defaultValueCreator = null)
+ {
+ return new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, bindingChanging,
+ defaultValueCreator: defaultValueCreator);
+ }
+
+ [Obsolete("Generic versions of Create () are no longer supported and deprecated. They will be removed soon.")]
+ internal static BindableProperty CreateAttached<TDeclarer, TPropertyType>(Expression<Func<BindableObject, TPropertyType>> staticgetter, TPropertyType defaultValue, BindingMode defaultBindingMode,
+ ValidateValueDelegate<TPropertyType> validateValue, BindingPropertyChangedDelegate<TPropertyType> propertyChanged, BindingPropertyChangingDelegate<TPropertyType> propertyChanging,
+ CoerceValueDelegate<TPropertyType> coerceValue, BindablePropertyBindingChanging bindingChanging, bool isReadOnly = false,
+ CreateDefaultValueDelegate<BindableObject, TPropertyType> defaultValueCreator = null)
+ {
+ if (staticgetter == null)
+ throw new ArgumentNullException("staticgetter");
+
+ Expression expr = staticgetter.Body;
+
+ var unary = expr as UnaryExpression;
+ if (unary != null)
+ expr = unary.Operand;
+
+ var methodcall = expr as MethodCallExpression;
+ if (methodcall == null)
+ throw new ArgumentException("staticgetter must be a MethodCallExpression", "staticgetter");
+
+ MethodInfo method = methodcall.Method;
+ if (!method.Name.StartsWith("Get", StringComparison.Ordinal))
+ throw new ArgumentException("staticgetter name must start with Get", "staticgetter");
+
+ string propertyname = method.Name.Substring(3);
+
+ ValidateValueDelegate untypedValidateValue = null;
+ BindingPropertyChangedDelegate untypedBindingPropertyChanged = null;
+ BindingPropertyChangingDelegate untypedBindingPropertyChanging = null;
+ CoerceValueDelegate untypedCoerceValue = null;
+ CreateDefaultValueDelegate untypedDefaultValueCreator = null;
+ if (validateValue != null)
+ untypedValidateValue = (bindable, value) => validateValue(bindable, (TPropertyType)value);
+ if (propertyChanged != null)
+ untypedBindingPropertyChanged = (bindable, oldValue, newValue) => propertyChanged(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
+ if (propertyChanging != null)
+ untypedBindingPropertyChanging = (bindable, oldValue, newValue) => propertyChanging(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
+ if (coerceValue != null)
+ untypedCoerceValue = (bindable, value) => coerceValue(bindable, (TPropertyType)value);
+ if (defaultValueCreator != null)
+ untypedDefaultValueCreator = o => defaultValueCreator(o);
+
+ return new BindableProperty(propertyname, method.ReturnType, typeof(TDeclarer), defaultValue, defaultBindingMode, untypedValidateValue, untypedBindingPropertyChanged, untypedBindingPropertyChanging,
+ untypedCoerceValue, bindingChanging, isReadOnly, untypedDefaultValueCreator);
+ }
+
+ internal static BindableProperty CreateAttached(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode, ValidateValueDelegate validateValue,
+ BindingPropertyChangedDelegate propertyChanged, BindingPropertyChangingDelegate propertyChanging, CoerceValueDelegate coerceValue, BindablePropertyBindingChanging bindingChanging,
+ bool isReadOnly, CreateDefaultValueDelegate defaultValueCreator = null)
+ {
+ return new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, bindingChanging, isReadOnly,
+ defaultValueCreator);
+ }
+
+ internal object GetDefaultValue(BindableObject bindable)
+ {
+ if (DefaultValueCreator != null)
+ return DefaultValueCreator(bindable);
+
+ return DefaultValue;
+ }
+
+ internal bool TryConvert(ref object value)
+ {
+ if (value == null)
+ {
+ return !ReturnTypeInfo.IsValueType || ReturnTypeInfo.IsGenericType && ReturnTypeInfo.GetGenericTypeDefinition() == typeof(Nullable<>);
+ }
+
+ Type valueType = value.GetType();
+ Type type = ReturnType;
+
+ // Dont support arbitrary IConvertible by limiting which types can use this
+ Type[] convertableTo;
+ if (SimpleConvertTypes.TryGetValue(valueType, out convertableTo) && Array.IndexOf(convertableTo, type) != -1)
+ {
+ value = Convert.ChangeType(value, type);
+ }
+ else if (!ReturnTypeInfo.IsAssignableFrom(valueType.GetTypeInfo()))
+ {
+ // Is there an implicit cast operator ?
+ MethodInfo cast = type.GetRuntimeMethod("op_Implicit", new[] { valueType });
+ if (cast != null && cast.ReturnType != type)
+ cast = null;
+ if (cast == null)
+ cast = valueType.GetRuntimeMethod("op_Implicit", new[] { valueType });
+ if (cast != null && cast.ReturnType != type)
+ cast = null;
+ if (cast == null)
+ return false;
+
+ value = cast.Invoke(null, new[] { value });
+ }
+
+ return true;
+ }
+
+ internal delegate void BindablePropertyBindingChanging(BindableObject bindable, BindingBase oldValue, BindingBase newValue);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BindablePropertyConverter.cs b/Xamarin.Forms.Core/BindablePropertyConverter.cs
new file mode 100644
index 00000000..af3fd5b6
--- /dev/null
+++ b/Xamarin.Forms.Core/BindablePropertyConverter.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+using System.Xml;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms
+{
+ public sealed class BindablePropertyConverter : TypeConverter, IExtendedTypeConverter
+ {
+ object IExtendedTypeConverter.ConvertFrom(CultureInfo culture, object value, IServiceProvider serviceProvider)
+ {
+ return ((IExtendedTypeConverter)this).ConvertFromInvariantString(value as string, serviceProvider);
+ }
+
+ object IExtendedTypeConverter.ConvertFromInvariantString(string value, IServiceProvider serviceProvider)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ return null;
+ if (serviceProvider == null)
+ return null;
+ var parentValuesProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideParentValues;
+ var typeResolver = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;
+ if (typeResolver == null)
+ return null;
+ IXmlLineInfo lineinfo = null;
+ var xmlLineInfoProvider = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) as IXmlLineInfoProvider;
+ if (xmlLineInfoProvider != null)
+ lineinfo = xmlLineInfoProvider.XmlLineInfo;
+ string[] parts = value.Split('.');
+ Type type = null;
+ if (parts.Length == 1)
+ {
+ if (parentValuesProvider == null)
+ {
+ string msg = string.Format("Can't resolve {0}", parts[0]);
+ throw new XamlParseException(msg, lineinfo);
+ }
+ object parent = parentValuesProvider.ParentObjects.Skip(1).FirstOrDefault();
+ if (parentValuesProvider.TargetObject is Setter)
+ {
+ var style = parent as Style;
+ var triggerBase = parent as TriggerBase;
+ if (style != null)
+ type = style.TargetType;
+ else if (triggerBase != null)
+ type = triggerBase.TargetType;
+ }
+ else if (parentValuesProvider.TargetObject is Trigger)
+ type = (parentValuesProvider.TargetObject as Trigger).TargetType;
+
+ if (type == null)
+ {
+ string msg = string.Format("Can't resolve {0}", parts[0]);
+ throw new XamlParseException(msg, lineinfo);
+ }
+
+ return ConvertFrom(type, parts[0], lineinfo);
+ }
+ if (parts.Length == 2)
+ {
+ if (!typeResolver.TryResolve(parts[0], out type))
+ {
+ string msg = string.Format("Can't resolve {0}", parts[0]);
+ throw new XamlParseException(msg, lineinfo);
+ }
+ return ConvertFrom(type, parts[1], lineinfo);
+ }
+ string emsg = string.Format("Can't resolve {0}. Syntax is [[ns:]Type.]PropertyName.", value);
+ throw new XamlParseException(emsg, lineinfo);
+ }
+
+ public override object ConvertFromInvariantString(string value)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ return null;
+ if (value.Contains(":"))
+ {
+ Log.Warning(null, "Can't resolve properties with xml namespace prefix.");
+ return null;
+ }
+ string[] parts = value.Split('.');
+ if (parts.Length != 2)
+ {
+ Log.Warning(null, "Can't resolve {0}. Accepted syntax is Type.PropertyName.", value);
+ return null;
+ }
+ Type type = Type.GetType("Xamarin.Forms." + parts[0]);
+ return ConvertFrom(type, parts[1], null);
+ }
+
+ BindableProperty ConvertFrom(Type type, string propertyName, IXmlLineInfo lineinfo)
+ {
+ string name = propertyName + "Property";
+ FieldInfo bpinfo = type.GetField(fi => fi.Name == name && fi.IsStatic && fi.IsPublic && fi.FieldType == typeof(BindableProperty));
+ if (bpinfo == null)
+ throw new XamlParseException(string.Format("Can't resolve {0} on {1}", name, type.Name), lineinfo);
+ var bp = bpinfo.GetValue(null) as BindableProperty;
+ if (bp.PropertyName != propertyName)
+ throw new XamlParseException(string.Format("The PropertyName of {0}.{1} is not {2}", type.Name, name, propertyName), lineinfo);
+ return bp;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BindablePropertyKey.cs b/Xamarin.Forms.Core/BindablePropertyKey.cs
new file mode 100644
index 00000000..a4b9f4a4
--- /dev/null
+++ b/Xamarin.Forms.Core/BindablePropertyKey.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public sealed class BindablePropertyKey
+ {
+ internal BindablePropertyKey(BindableProperty property)
+ {
+ if (property == null)
+ throw new ArgumentNullException("property");
+
+ BindableProperty = property;
+ }
+
+ public BindableProperty BindableProperty { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Binding.cs b/Xamarin.Forms.Core/Binding.cs
new file mode 100644
index 00000000..5fa1dd65
--- /dev/null
+++ b/Xamarin.Forms.Core/Binding.cs
@@ -0,0 +1,233 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Text;
+
+namespace Xamarin.Forms
+{
+ public sealed class Binding : BindingBase
+ {
+ internal const string SelfPath = ".";
+ IValueConverter _converter;
+ object _converterParameter;
+
+ BindingExpression _expression;
+ string _path;
+ object _source;
+
+ public Binding()
+ {
+ }
+
+ public Binding(string path, BindingMode mode = BindingMode.Default, IValueConverter converter = null, object converterParameter = null, string stringFormat = null, object source = null)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (string.IsNullOrWhiteSpace(path))
+ throw new ArgumentException("path can not be an empty string", "path");
+
+ Path = path;
+ Converter = converter;
+ ConverterParameter = converterParameter;
+ Mode = mode;
+ StringFormat = stringFormat;
+ Source = source;
+ }
+
+ public IValueConverter Converter
+ {
+ get { return _converter; }
+ set
+ {
+ ThrowIfApplied();
+
+ _converter = value;
+ }
+ }
+
+ public object ConverterParameter
+ {
+ get { return _converterParameter; }
+ set
+ {
+ ThrowIfApplied();
+
+ _converterParameter = value;
+ }
+ }
+
+ public string Path
+ {
+ get { return _path; }
+ set
+ {
+ ThrowIfApplied();
+
+ _path = value;
+ _expression = new BindingExpression(this, !string.IsNullOrWhiteSpace(value) ? value : SelfPath);
+ }
+ }
+
+ public object Source
+ {
+ get { return _source; }
+ set
+ {
+ ThrowIfApplied();
+ _source = value;
+ }
+ }
+
+ public static Binding Create<TSource>(Expression<Func<TSource, object>> propertyGetter, BindingMode mode = BindingMode.Default, IValueConverter converter = null, object converterParameter = null,
+ string stringFormat = null)
+ {
+ if (propertyGetter == null)
+ throw new ArgumentNullException("propertyGetter");
+
+ string path = GetBindingPath(propertyGetter);
+ return new Binding(path, mode, converter, converterParameter, stringFormat);
+ }
+
+ internal override void Apply(bool fromTarget)
+ {
+ base.Apply(fromTarget);
+
+ if (_expression == null)
+ _expression = new BindingExpression(this, SelfPath);
+
+ _expression.Apply(fromTarget);
+ }
+
+ internal override void Apply(object newContext, BindableObject bindObj, BindableProperty targetProperty)
+ {
+ object src = _source;
+ base.Apply(src ?? newContext, bindObj, targetProperty);
+
+ object bindingContext = src ?? Context ?? newContext;
+ if (_expression == null && bindingContext != null)
+ _expression = new BindingExpression(this, SelfPath);
+
+ _expression.Apply(bindingContext, bindObj, targetProperty);
+ }
+
+ internal override BindingBase Clone()
+ {
+ return new Binding(Path, Mode) { Converter = Converter, ConverterParameter = ConverterParameter, StringFormat = StringFormat, Source = Source };
+ }
+
+ internal override object GetSourceValue(object value, Type targetPropertyType)
+ {
+ if (Converter != null)
+ value = Converter.Convert(value, targetPropertyType, ConverterParameter, CultureInfo.CurrentUICulture);
+
+ return base.GetSourceValue(value, targetPropertyType);
+ }
+
+ internal override object GetTargetValue(object value, Type sourcePropertyType)
+ {
+ if (Converter != null)
+ value = Converter.ConvertBack(value, sourcePropertyType, ConverterParameter, CultureInfo.CurrentUICulture);
+
+ return base.GetTargetValue(value, sourcePropertyType);
+ }
+
+ internal override void Unapply()
+ {
+ base.Unapply();
+
+ if (_expression != null)
+ _expression.Unapply();
+ }
+
+ static string GetBindingPath<TSource>(Expression<Func<TSource, object>> propertyGetter)
+ {
+ Expression expr = propertyGetter.Body;
+
+ var unary = expr as UnaryExpression;
+ if (unary != null)
+ expr = unary.Operand;
+
+ var builder = new StringBuilder();
+
+ var indexed = false;
+
+ var member = expr as MemberExpression;
+ if (member == null)
+ {
+ var methodCall = expr as MethodCallExpression;
+ if (methodCall != null)
+ {
+ if (methodCall.Arguments.Count == 0)
+ throw new ArgumentException("Method calls are not allowed in binding expression");
+
+ var arguments = new List<string>(methodCall.Arguments.Count);
+ foreach (Expression arg in methodCall.Arguments)
+ {
+ if (arg.NodeType != ExpressionType.Constant)
+ throw new ArgumentException("Only constants can be used as indexer arguments");
+
+ object value = ((ConstantExpression)arg).Value;
+ arguments.Add(value != null ? value.ToString() : "null");
+ }
+
+ Type declarerType = methodCall.Method.DeclaringType;
+ DefaultMemberAttribute defaultMember = declarerType.GetTypeInfo().GetCustomAttributes(typeof(DefaultMemberAttribute), true).OfType<DefaultMemberAttribute>().FirstOrDefault();
+ string indexerName = defaultMember != null ? defaultMember.MemberName : "Item";
+
+ MethodInfo getterInfo =
+ declarerType.GetProperties().Where(pi => pi.Name == indexerName && pi.CanRead && pi.GetMethod.IsPublic && !pi.GetMethod.IsStatic).Select(pi => pi.GetMethod).FirstOrDefault();
+ if (getterInfo != null)
+ {
+ if (getterInfo == methodCall.Method)
+ {
+ indexed = true;
+ builder.Append("[");
+
+ var first = true;
+ foreach (string argument in arguments)
+ {
+ if (!first)
+ builder.Append(",");
+
+ builder.Append(argument);
+ first = false;
+ }
+
+ builder.Append("]");
+
+ member = methodCall.Object as MemberExpression;
+ }
+ else
+ throw new ArgumentException("Method calls are not allowed in binding expressions");
+ }
+ else
+ throw new ArgumentException("Public indexer not found");
+ }
+ else
+ throw new ArgumentException("Invalid expression type");
+ }
+
+ while (member != null)
+ {
+ var property = (PropertyInfo)member.Member;
+ if (builder.Length != 0)
+ {
+ if (!indexed)
+ builder.Insert(0, ".");
+ else
+ indexed = false;
+ }
+
+ builder.Insert(0, property.Name);
+
+ // member = member.Expression as MemberExpression ?? (member.Expression as UnaryExpression)?.Operand as MemberExpression;
+ member = member.Expression as MemberExpression ?? (member.Expression is UnaryExpression ? (member.Expression as UnaryExpression).Operand as MemberExpression : null);
+ }
+
+ return builder.ToString();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BindingBase.cs b/Xamarin.Forms.Core/BindingBase.cs
new file mode 100644
index 00000000..0810cbcf
--- /dev/null
+++ b/Xamarin.Forms.Core/BindingBase.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Collections;
+using System.Runtime.CompilerServices;
+
+namespace Xamarin.Forms
+{
+ public abstract class BindingBase
+ {
+ static readonly ConditionalWeakTable<IEnumerable, CollectionSynchronizationContext> SynchronizedCollections = new ConditionalWeakTable<IEnumerable, CollectionSynchronizationContext>();
+
+ BindingMode _mode = BindingMode.Default;
+ string _stringFormat;
+
+ internal BindingBase()
+ {
+ }
+
+ public BindingMode Mode
+ {
+ get { return _mode; }
+ set
+ {
+ if (value != BindingMode.Default && value != BindingMode.OneWay && value != BindingMode.OneWayToSource && value != BindingMode.TwoWay)
+ throw new ArgumentException("mode is not a valid BindingMode", "mode");
+
+ ThrowIfApplied();
+
+ _mode = value;
+ }
+ }
+
+ public string StringFormat
+ {
+ get { return _stringFormat; }
+ set
+ {
+ ThrowIfApplied();
+
+ _stringFormat = value;
+ }
+ }
+
+ internal bool AllowChaining { get; set; }
+
+ internal object Context { get; set; }
+
+ internal bool IsApplied { get; private set; }
+
+ public static void DisableCollectionSynchronization(IEnumerable collection)
+ {
+ if (collection == null)
+ throw new ArgumentNullException("collection");
+
+ SynchronizedCollections.Remove(collection);
+ }
+
+ public static void EnableCollectionSynchronization(IEnumerable collection, object context, CollectionSynchronizationCallback callback)
+ {
+ if (collection == null)
+ throw new ArgumentNullException("collection");
+ if (callback == null)
+ throw new ArgumentNullException("callback");
+
+ SynchronizedCollections.Add(collection, new CollectionSynchronizationContext(context, callback));
+ }
+
+ protected void ThrowIfApplied()
+ {
+ if (IsApplied)
+ throw new InvalidOperationException("Can not change a binding while it's applied");
+ }
+
+ internal virtual void Apply(bool fromTarget)
+ {
+ IsApplied = true;
+ }
+
+ internal virtual void Apply(object context, BindableObject bindObj, BindableProperty targetProperty)
+ {
+ IsApplied = true;
+ }
+
+ internal abstract BindingBase Clone();
+
+ internal virtual object GetSourceValue(object value, Type targetPropertyType)
+ {
+ if (StringFormat != null)
+ return string.Format(StringFormat, value);
+
+ return value;
+ }
+
+ internal virtual object GetTargetValue(object value, Type sourcePropertyType)
+ {
+ return value;
+ }
+
+ internal static bool TryGetSynchronizedCollection(IEnumerable collection, out CollectionSynchronizationContext synchronizationContext)
+ {
+ if (collection == null)
+ throw new ArgumentNullException("collection");
+
+ return SynchronizedCollections.TryGetValue(collection, out synchronizationContext);
+ }
+
+ internal virtual void Unapply()
+ {
+ IsApplied = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BindingBaseExtensions.cs b/Xamarin.Forms.Core/BindingBaseExtensions.cs
new file mode 100644
index 00000000..a52c5cb1
--- /dev/null
+++ b/Xamarin.Forms.Core/BindingBaseExtensions.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ internal static class BindingBaseExtensions
+ {
+ internal static BindingMode GetRealizedMode(this BindingBase self, BindableProperty property)
+ {
+ if (self == null)
+ throw new ArgumentNullException("self");
+ if (property == null)
+ throw new ArgumentNullException("property");
+
+ return self.Mode != BindingMode.Default ? self.Mode : property.DefaultBindingMode;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BindingExpression.cs b/Xamarin.Forms.Core/BindingExpression.cs
new file mode 100644
index 00000000..505fc584
--- /dev/null
+++ b/Xamarin.Forms.Core/BindingExpression.cs
@@ -0,0 +1,506 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+
+namespace Xamarin.Forms
+{
+ internal class BindingExpression
+ {
+ internal const string PropertyNotFoundErrorMessage = "'{0}' property not found on '{1}', target property: '{2}.{3}'";
+
+ readonly List<BindingExpressionPart> _parts = new List<BindingExpressionPart>();
+
+ BindableProperty _targetProperty;
+ WeakReference<object> _weakSource;
+ WeakReference<BindableObject> _weakTarget;
+
+ internal BindingExpression(BindingBase binding, string path)
+ {
+ if (binding == null)
+ throw new ArgumentNullException("binding");
+ if (path == null)
+ throw new ArgumentNullException("path");
+
+ Binding = binding;
+ Path = path;
+
+ ParsePath();
+ }
+
+ internal BindingBase Binding { get; }
+
+ internal string Path { get; }
+
+ /// <summary>
+ /// Applies the binding expression to a previously set source and target.
+ /// </summary>
+ internal void Apply(bool fromTarget = false)
+ {
+ if (_weakSource == null || _weakTarget == null)
+ return;
+
+ BindableObject target;
+ if (!_weakTarget.TryGetTarget(out target))
+ {
+ Unapply();
+ return;
+ }
+
+ object source;
+ if (_weakSource.TryGetTarget(out source) && _targetProperty != null)
+ ApplyCore(source, target, _targetProperty, fromTarget);
+ }
+
+ /// <summary>
+ /// Applies the binding expression to a new source or target.
+ /// </summary>
+ internal void Apply(object sourceObject, BindableObject target, BindableProperty property)
+ {
+ _targetProperty = property;
+
+ BindableObject prevTarget;
+ if (_weakTarget != null && _weakTarget.TryGetTarget(out prevTarget) && !ReferenceEquals(prevTarget, target))
+ throw new InvalidOperationException("Binding instances can not be reused");
+
+ object previousSource;
+ if (_weakSource != null && _weakSource.TryGetTarget(out previousSource) && !ReferenceEquals(previousSource, sourceObject))
+ throw new InvalidOperationException("Binding instances can not be reused");
+
+ _weakSource = new WeakReference<object>(sourceObject);
+ _weakTarget = new WeakReference<BindableObject>(target);
+
+ ApplyCore(sourceObject, target, property);
+ }
+
+ internal void Unapply()
+ {
+ object sourceObject;
+ if (_weakSource != null && _weakSource.TryGetTarget(out sourceObject))
+ {
+ for (var i = 0; i < _parts.Count - 1; i++)
+ {
+ BindingExpressionPart part = _parts[i];
+
+ if (!part.IsSelf)
+ {
+ part.TryGetValue(sourceObject, out sourceObject);
+ }
+
+ var inpc = sourceObject as INotifyPropertyChanged;
+ if (inpc != null)
+ inpc.PropertyChanged -= part.ChangeHandler;
+ }
+ }
+
+ _weakSource = null;
+ _weakTarget = null;
+ }
+
+ /// <summary>
+ /// Applies the binding expression to a previously set source or target.
+ /// </summary>
+ void ApplyCore(object sourceObject, BindableObject target, BindableProperty property, bool fromTarget = false)
+ {
+ BindingMode mode = Binding.GetRealizedMode(_targetProperty);
+ if (mode == BindingMode.OneWay && fromTarget)
+ return;
+
+ bool needsGetter = (mode == BindingMode.TwoWay && !fromTarget) || mode == BindingMode.OneWay;
+ bool needsSetter = !needsGetter && ((mode == BindingMode.TwoWay && fromTarget) || mode == BindingMode.OneWayToSource);
+
+ object current = sourceObject;
+ object previous = null;
+ BindingExpressionPart part = null;
+
+ for (var i = 0; i < _parts.Count; i++)
+ {
+ part = _parts[i];
+ bool isLast = i + 1 == _parts.Count;
+
+ if (!part.IsSelf && current != null)
+ {
+ // Allow the object instance itself to provide its own TypeInfo
+ var reflectable = current as IReflectableType;
+ TypeInfo currentType = reflectable != null ? reflectable.GetTypeInfo() : current.GetType().GetTypeInfo();
+ if (part.LastGetter == null || !part.LastGetter.DeclaringType.GetTypeInfo().IsAssignableFrom(currentType))
+ SetupPart(currentType, part);
+
+ if (!isLast)
+ part.TryGetValue(current, out current);
+ }
+
+ if (!part.IsSelf && current != null)
+ {
+ if ((needsGetter && part.LastGetter == null) || (needsSetter && part.NextPart == null && part.LastSetter == null))
+ {
+ Log.Warning("Binding", PropertyNotFoundErrorMessage, part.Content, current, target.GetType(), property.PropertyName);
+ break;
+ }
+ }
+
+ if (mode == BindingMode.OneWay || mode == BindingMode.TwoWay)
+ {
+ var inpc = current as INotifyPropertyChanged;
+ if (inpc != null && !ReferenceEquals(current, previous))
+ {
+ // If we're reapplying, we don't want to double subscribe
+ inpc.PropertyChanged -= part.ChangeHandler;
+ inpc.PropertyChanged += part.ChangeHandler;
+ }
+ }
+
+ previous = current;
+ }
+
+ Debug.Assert(part != null, "There should always be at least the self part in the expression.");
+
+ if (needsGetter)
+ {
+ object value = property.DefaultValue;
+ if (part.TryGetValue(current, out value) || part.IsSelf)
+ {
+ value = Binding.GetSourceValue(value, property.ReturnType);
+ }
+ else
+ value = property.DefaultValue;
+
+ if (!TryConvert(part, ref value, property.ReturnType, true))
+ {
+ Log.Warning("Binding", "{0} can not be converted to type '{1}'", value, property.ReturnType);
+ return;
+ }
+
+ target.SetValueCore(property, value, BindableObject.SetValueFlags.ClearDynamicResource, BindableObject.SetValuePrivateFlags.Default | BindableObject.SetValuePrivateFlags.Converted);
+ }
+ else if (needsSetter && part.LastSetter != null && current != null)
+ {
+ object value = Binding.GetTargetValue(target.GetValue(property), part.SetterType);
+
+ if (!TryConvert(part, ref value, part.SetterType, false))
+ {
+ Log.Warning("Binding", "{0} can not be converted to type '{1}'", value, part.SetterType);
+ return;
+ }
+
+ object[] args;
+ if (part.IsIndexer)
+ {
+ args = new object[part.Arguments.Length + 1];
+ part.Arguments.CopyTo(args, 0);
+ args[args.Length - 1] = value;
+ }
+ else if (part.IsBindablePropertySetter)
+ {
+ args = new[] { part.BindablePropertyField, value };
+ }
+ else
+ {
+ args = new[] { value };
+ }
+
+ part.LastSetter.Invoke(current, args);
+ }
+ }
+
+ IEnumerable<BindingExpressionPart> GetPart(string part)
+ {
+ part = part.Trim();
+ if (part == string.Empty)
+ throw new FormatException("Path contains an empty part");
+
+ BindingExpressionPart indexer = null;
+
+ int lbIndex = part.IndexOf('[');
+ if (lbIndex != -1)
+ {
+ int rbIndex = part.LastIndexOf(']');
+ if (rbIndex == -1)
+ throw new FormatException("Indexer did not contain closing bracket");
+
+ int argLength = rbIndex - lbIndex - 1;
+ if (argLength == 0)
+ throw new FormatException("Indexer did not contain arguments");
+
+ string argString = part.Substring(lbIndex + 1, argLength);
+ indexer = new BindingExpressionPart(this, argString, true);
+
+ part = part.Substring(0, lbIndex);
+ part = part.Trim();
+ }
+
+ if (part.Length > 0)
+ yield return new BindingExpressionPart(this, part);
+ if (indexer != null)
+ yield return indexer;
+ }
+
+ void ParsePath()
+ {
+ string p = Path.Trim();
+
+ var last = new BindingExpressionPart(this, ".");
+ _parts.Add(last);
+
+ if (p[0] == '.')
+ {
+ if (p.Length == 1)
+ return;
+
+ p = p.Substring(1);
+ }
+
+ string[] pathParts = p.Split('.');
+ for (var i = 0; i < pathParts.Length; i++)
+ {
+ foreach (BindingExpressionPart part in GetPart(pathParts[i]))
+ {
+ last.NextPart = part;
+ _parts.Add(part);
+ last = part;
+ }
+ }
+ }
+
+ void SetupPart(TypeInfo sourceType, BindingExpressionPart part)
+ {
+ part.Arguments = null;
+ part.LastGetter = null;
+ part.LastSetter = null;
+
+ PropertyInfo property = null;
+ if (part.IsIndexer)
+ {
+ if (sourceType.IsArray)
+ {
+ int index;
+ if (!int.TryParse(part.Content, out index))
+ Log.Warning("Binding", "{0} could not be parsed as an index for a {1}", part.Content, sourceType);
+ else
+ part.Arguments = new object[] { index };
+
+ part.LastGetter = sourceType.GetDeclaredMethod("Get");
+ part.LastSetter = sourceType.GetDeclaredMethod("Set");
+ part.SetterType = sourceType.GetElementType();
+ }
+
+ DefaultMemberAttribute defaultMember = sourceType.GetCustomAttributes(typeof(DefaultMemberAttribute), true).OfType<DefaultMemberAttribute>().FirstOrDefault();
+ string indexerName = defaultMember != null ? defaultMember.MemberName : "Item";
+
+ part.IndexerName = indexerName;
+
+ property = sourceType.GetDeclaredProperty(indexerName);
+ if (property == null)
+ property = sourceType.BaseType.GetProperty(indexerName);
+
+ if (property != null)
+ {
+ ParameterInfo parameter = property.GetIndexParameters().FirstOrDefault();
+ if (parameter != null)
+ {
+ try
+ {
+ object arg = Convert.ChangeType(part.Content, parameter.ParameterType, CultureInfo.InvariantCulture);
+ part.Arguments = new[] { arg };
+ }
+ catch (FormatException)
+ {
+ }
+ catch (InvalidCastException)
+ {
+ }
+ catch (OverflowException)
+ {
+ }
+ }
+ }
+ }
+ else
+ {
+ property = sourceType.GetDeclaredProperty(part.Content);
+ if (property == null)
+ property = sourceType.BaseType.GetProperty(part.Content);
+ }
+
+ if (property != null)
+ {
+ if (property.CanRead && property.GetMethod.IsPublic && !property.GetMethod.IsStatic)
+ part.LastGetter = property.GetMethod;
+ if (property.CanWrite && property.SetMethod.IsPublic && !property.SetMethod.IsStatic)
+ {
+ part.LastSetter = property.SetMethod;
+ part.SetterType = part.LastSetter.GetParameters().Last().ParameterType;
+
+ if (Binding.AllowChaining)
+ {
+ FieldInfo bindablePropertyField = sourceType.GetDeclaredField(part.Content + "Property");
+ if (bindablePropertyField != null && bindablePropertyField.FieldType == typeof(BindableProperty) && sourceType.ImplementedInterfaces.Contains(typeof(IElementController)))
+ {
+ MethodInfo setValueMethod = null;
+ foreach (MethodInfo m in sourceType.AsType().GetRuntimeMethods())
+ {
+ if (m.Name.EndsWith("IElementController.SetValueFromRenderer"))
+ {
+ ParameterInfo[] parameters = m.GetParameters();
+ if (parameters.Length == 2 && parameters[0].ParameterType == typeof(BindableProperty))
+ {
+ setValueMethod = m;
+ break;
+ }
+ }
+ }
+ if (setValueMethod != null)
+ {
+ part.LastSetter = setValueMethod;
+ part.IsBindablePropertySetter = true;
+ part.BindablePropertyField = bindablePropertyField.GetValue(null);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ bool TryConvert(BindingExpressionPart part, ref object value, Type convertTo, bool toTarget)
+ {
+ if (value == null)
+ return true;
+ if ((toTarget && _targetProperty.TryConvert(ref value)) || (!toTarget && convertTo.IsInstanceOfType(value)))
+ return true;
+
+ object original = value;
+ try
+ {
+ value = Convert.ChangeType(value, convertTo, CultureInfo.InvariantCulture);
+ return true;
+ }
+ catch (InvalidCastException)
+ {
+ value = original;
+ return false;
+ }
+ catch (FormatException)
+ {
+ value = original;
+ return false;
+ }
+ catch (OverflowException)
+ {
+ value = original;
+ return false;
+ }
+ }
+
+ class BindingPair
+ {
+ public BindingPair(BindingExpressionPart part, object source, bool isLast)
+ {
+ Part = part;
+ Source = source;
+ IsLast = isLast;
+ }
+
+ public bool IsLast { get; set; }
+
+ public BindingExpressionPart Part { get; private set; }
+
+ public object Source { get; private set; }
+ }
+
+ class BindingExpressionPart
+ {
+ readonly BindingExpression _expression;
+
+ public readonly PropertyChangedEventHandler ChangeHandler;
+
+ public BindingExpressionPart(BindingExpression expression, string content, bool isIndexer = false)
+ {
+ _expression = expression;
+ IsSelf = content == Forms.Binding.SelfPath;
+ Content = content;
+ IsIndexer = isIndexer;
+
+ ChangeHandler = PropertyChanged;
+ }
+
+ public object[] Arguments { get; set; }
+
+ public object BindablePropertyField { get; set; }
+
+ public string Content { get; }
+
+ public string IndexerName { get; set; }
+
+ public bool IsBindablePropertySetter { get; set; }
+
+ public bool IsIndexer { get; }
+
+ public bool IsSelf { get; }
+
+ public MethodInfo LastGetter { get; set; }
+
+ public MethodInfo LastSetter { get; set; }
+
+ public BindingExpressionPart NextPart { get; set; }
+
+ public Type SetterType { get; set; }
+
+ public void PropertyChanged(object sender, PropertyChangedEventArgs args)
+ {
+ BindingExpressionPart part = NextPart ?? this;
+
+ string name = args.PropertyName;
+
+ if (!string.IsNullOrEmpty(name))
+ {
+ if (part.IsIndexer)
+ {
+ if (name.Contains("["))
+ {
+ if (name != string.Format("{0}[{1}]", part.IndexerName, part.Content))
+ return;
+ }
+ else if (name != part.IndexerName)
+ return;
+ }
+ else if (name != part.Content)
+ {
+ return;
+ }
+ }
+
+ Device.BeginInvokeOnMainThread(() => _expression.Apply());
+ }
+
+ public bool TryGetValue(object source, out object value)
+ {
+ value = source;
+
+ if (LastGetter != null && value != null)
+ {
+ if (IsIndexer)
+ {
+ try
+ {
+ value = LastGetter.Invoke(value, Arguments);
+ }
+ catch (TargetInvocationException ex)
+ {
+ if (!(ex.InnerException is KeyNotFoundException))
+ throw;
+ value = null;
+ }
+ return true;
+ }
+ value = LastGetter.Invoke(value, Arguments);
+ return true;
+ }
+
+ return false;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BindingMode.cs b/Xamarin.Forms.Core/BindingMode.cs
new file mode 100644
index 00000000..89396acb
--- /dev/null
+++ b/Xamarin.Forms.Core/BindingMode.cs
@@ -0,0 +1,10 @@
+namespace Xamarin.Forms
+{
+ public enum BindingMode
+ {
+ Default,
+ TwoWay,
+ OneWay,
+ OneWayToSource
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BindingTypeConverter.cs b/Xamarin.Forms.Core/BindingTypeConverter.cs
new file mode 100644
index 00000000..07dda896
--- /dev/null
+++ b/Xamarin.Forms.Core/BindingTypeConverter.cs
@@ -0,0 +1,10 @@
+namespace Xamarin.Forms
+{
+ public sealed class BindingTypeConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString(string value)
+ {
+ return new Binding(value);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BoundsConstraint.cs b/Xamarin.Forms.Core/BoundsConstraint.cs
new file mode 100644
index 00000000..43be86eb
--- /dev/null
+++ b/Xamarin.Forms.Core/BoundsConstraint.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+
+namespace Xamarin.Forms
+{
+ public class BoundsConstraint
+ {
+ Func<Rectangle> _measureFunc;
+
+ BoundsConstraint()
+ {
+ }
+
+ internal IEnumerable<View> RelativeTo { get; set; }
+
+ public static BoundsConstraint FromExpression(Expression<Func<Rectangle>> expression, IEnumerable<View> parents = null)
+ {
+ Func<Rectangle> compiled = expression.Compile();
+ var result = new BoundsConstraint
+ {
+ _measureFunc = compiled,
+ RelativeTo = parents ?? ExpressionSearch.Default.FindObjects<View>(expression).ToArray() // make sure we have our own copy
+ };
+
+ return result;
+ }
+
+ internal Rectangle Compute()
+ {
+ return _measureFunc();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BoundsTypeConverter.cs b/Xamarin.Forms.Core/BoundsTypeConverter.cs
new file mode 100644
index 00000000..549b7b63
--- /dev/null
+++ b/Xamarin.Forms.Core/BoundsTypeConverter.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Globalization;
+
+namespace Xamarin.Forms
+{
+ public class BoundsTypeConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString(string value)
+ {
+ if (value != null)
+ {
+ double x = -1, y = -1, w = -1, h = -1;
+ string[] xywh = value.Split(',');
+ bool hasX, hasY, hasW, hasH;
+
+ hasX = (xywh.Length == 2 || xywh.Length == 4) && double.TryParse(xywh[0], NumberStyles.Number, CultureInfo.InvariantCulture, out x);
+ hasY = (xywh.Length == 2 || xywh.Length == 4) && double.TryParse(xywh[1], NumberStyles.Number, CultureInfo.InvariantCulture, out y);
+ hasW = xywh.Length == 4 && double.TryParse(xywh[2], NumberStyles.Number, CultureInfo.InvariantCulture, out w);
+ hasH = xywh.Length == 4 && double.TryParse(xywh[3], NumberStyles.Number, CultureInfo.InvariantCulture, out h);
+
+ if (!hasW && xywh.Length == 4 && string.Compare("AutoSize", xywh[2].Trim(), StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ hasW = true;
+ w = AbsoluteLayout.AutoSize;
+ }
+
+ if (!hasH && xywh.Length == 4 && string.Compare("AutoSize", xywh[3].Trim(), StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ hasH = true;
+ h = AbsoluteLayout.AutoSize;
+ }
+
+ if (hasX && hasY && xywh.Length == 2)
+ return new Rectangle(x, y, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize);
+ if (hasX && hasY && hasW && hasH && xywh.Length == 4)
+ return new Rectangle(x, y, w, h);
+ }
+
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(Rectangle)));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BoxView.cs b/Xamarin.Forms.Core/BoxView.cs
new file mode 100644
index 00000000..79fef390
--- /dev/null
+++ b/Xamarin.Forms.Core/BoxView.cs
@@ -0,0 +1,23 @@
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_BoxViewRenderer))]
+ public class BoxView : View
+ {
+ public static readonly BindableProperty ColorProperty = BindableProperty.Create("Color", typeof(Color), typeof(BoxView), Color.Default);
+
+ public Color Color
+ {
+ get { return (Color)GetValue(ColorProperty); }
+ set { SetValue(ColorProperty, value); }
+ }
+
+ [Obsolete("Use OnMeasure")]
+ protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ return new SizeRequest(new Size(40, 40));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Button.cs b/Xamarin.Forms.Core/Button.cs
new file mode 100644
index 00000000..4662105f
--- /dev/null
+++ b/Xamarin.Forms.Core/Button.cs
@@ -0,0 +1,251 @@
+using System;
+using System.Windows.Input;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_ButtonRenderer))]
+ public class Button : View, IFontElement, IButtonController
+ {
+ public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(Button), null, propertyChanged: (bo, o, n) => ((Button)bo).OnCommandChanged());
+
+ public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create("CommandParameter", typeof(object), typeof(Button), null,
+ propertyChanged: (bindable, oldvalue, newvalue) => ((Button)bindable).CommandCanExecuteChanged(bindable, EventArgs.Empty));
+
+ public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(Button), null,
+ propertyChanged: (bindable, oldVal, newVal) => ((Button)bindable).InvalidateMeasure(InvalidationTrigger.MeasureChanged));
+
+ public static readonly BindableProperty TextColorProperty = BindableProperty.Create("TextColor", typeof(Color), typeof(Button), Color.Default);
+
+ public static readonly BindableProperty FontProperty = BindableProperty.Create("Font", typeof(Font), typeof(Button), default(Font), propertyChanged: FontStructPropertyChanged);
+
+ public static readonly BindableProperty FontFamilyProperty = BindableProperty.Create("FontFamily", typeof(string), typeof(Button), default(string), propertyChanged: SpecificFontPropertyChanged);
+
+ public static readonly BindableProperty FontSizeProperty = BindableProperty.Create("FontSize", typeof(double), typeof(Button), -1.0, propertyChanged: SpecificFontPropertyChanged,
+ defaultValueCreator: bindable => Device.GetNamedSize(NamedSize.Default, (Button)bindable));
+
+ public static readonly BindableProperty FontAttributesProperty = BindableProperty.Create("FontAttributes", typeof(FontAttributes), typeof(Button), FontAttributes.None,
+ propertyChanged: SpecificFontPropertyChanged);
+
+ public static readonly BindableProperty BorderWidthProperty = BindableProperty.Create("BorderWidth", typeof(double), typeof(Button), 0d);
+
+ public static readonly BindableProperty BorderColorProperty = BindableProperty.Create("BorderColor", typeof(Color), typeof(Button), Color.Default);
+
+ public static readonly BindableProperty BorderRadiusProperty = BindableProperty.Create("BorderRadius", typeof(int), typeof(Button), 5);
+
+ public static readonly BindableProperty ImageProperty = BindableProperty.Create("Image", typeof(FileImageSource), typeof(Button), default(FileImageSource),
+ propertyChanging: (bindable, oldvalue, newvalue) => ((Button)bindable).OnSourcePropertyChanging((ImageSource)oldvalue, (ImageSource)newvalue),
+ propertyChanged: (bindable, oldvalue, newvalue) => ((Button)bindable).OnSourcePropertyChanged((ImageSource)oldvalue, (ImageSource)newvalue));
+
+ bool _cancelEvents;
+
+ public Color BorderColor
+ {
+ get { return (Color)GetValue(BorderColorProperty); }
+ set { SetValue(BorderColorProperty, value); }
+ }
+
+ public int BorderRadius
+ {
+ get { return (int)GetValue(BorderRadiusProperty); }
+ set { SetValue(BorderRadiusProperty, value); }
+ }
+
+ public double BorderWidth
+ {
+ get { return (double)GetValue(BorderWidthProperty); }
+ set { SetValue(BorderWidthProperty, value); }
+ }
+
+ public ICommand Command
+ {
+ get { return (ICommand)GetValue(CommandProperty); }
+ set { SetValue(CommandProperty, value); }
+ }
+
+ public object CommandParameter
+ {
+ get { return GetValue(CommandParameterProperty); }
+ set { SetValue(CommandParameterProperty, value); }
+ }
+
+ public Font Font
+ {
+ get { return (Font)GetValue(FontProperty); }
+ set { SetValue(FontProperty, value); }
+ }
+
+ public FileImageSource Image
+ {
+ get { return (FileImageSource)GetValue(ImageProperty); }
+ set { SetValue(ImageProperty, value); }
+ }
+
+ public string Text
+ {
+ get { return (string)GetValue(TextProperty); }
+ set { SetValue(TextProperty, value); }
+ }
+
+ public Color TextColor
+ {
+ get { return (Color)GetValue(TextColorProperty); }
+ set { SetValue(TextColorProperty, value); }
+ }
+
+ bool IsEnabledCore
+ {
+ set { SetValueCore(IsEnabledProperty, value); }
+ }
+
+ void IButtonController.SendClicked()
+ {
+ ICommand cmd = Command;
+ if (cmd != null)
+ cmd.Execute(CommandParameter);
+
+ EventHandler handler = Clicked;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+
+ public FontAttributes FontAttributes
+ {
+ get { return (FontAttributes)GetValue(FontAttributesProperty); }
+ set { SetValue(FontAttributesProperty, value); }
+ }
+
+ public string FontFamily
+ {
+ get { return (string)GetValue(FontFamilyProperty); }
+ set { SetValue(FontFamilyProperty, value); }
+ }
+
+ [TypeConverter(typeof(FontSizeConverter))]
+ public double FontSize
+ {
+ get { return (double)GetValue(FontSizeProperty); }
+ set { SetValue(FontSizeProperty, value); }
+ }
+
+ public event EventHandler Clicked;
+
+ protected override void OnBindingContextChanged()
+ {
+ FileImageSource image = Image;
+ if (image != null)
+ SetInheritedBindingContext(image, BindingContext);
+
+ base.OnBindingContextChanged();
+ }
+
+ protected override void OnPropertyChanging(string propertyName = null)
+ {
+ if (propertyName == CommandProperty.PropertyName)
+ {
+ ICommand cmd = Command;
+ if (cmd != null)
+ cmd.CanExecuteChanged -= CommandCanExecuteChanged;
+ }
+
+ base.OnPropertyChanging(propertyName);
+ }
+
+ void CommandCanExecuteChanged(object sender, EventArgs eventArgs)
+ {
+ ICommand cmd = Command;
+ if (cmd != null)
+ IsEnabledCore = cmd.CanExecute(CommandParameter);
+ }
+
+ static void FontStructPropertyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var button = (Button)bindable;
+
+ if (button._cancelEvents)
+ return;
+
+ button.InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+
+ button._cancelEvents = true;
+
+ if (button.Font == Font.Default)
+ {
+ button.FontFamily = null;
+ button.FontSize = Device.GetNamedSize(NamedSize.Default, button);
+ button.FontAttributes = FontAttributes.None;
+ }
+ else
+ {
+ button.FontFamily = button.Font.FontFamily;
+ if (button.Font.UseNamedSize)
+ {
+ button.FontSize = Device.GetNamedSize(button.Font.NamedSize, button.GetType(), true);
+ }
+ else
+ {
+ button.FontSize = button.Font.FontSize;
+ }
+ button.FontAttributes = button.Font.FontAttributes;
+ }
+
+ button._cancelEvents = false;
+ }
+
+ void OnCommandChanged()
+ {
+ if (Command != null)
+ {
+ Command.CanExecuteChanged += CommandCanExecuteChanged;
+ CommandCanExecuteChanged(this, EventArgs.Empty);
+ }
+ else
+ IsEnabledCore = true;
+ }
+
+ void OnSourceChanged(object sender, EventArgs eventArgs)
+ {
+ OnPropertyChanged(ImageProperty.PropertyName);
+ InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+
+ void OnSourcePropertyChanged(ImageSource oldvalue, ImageSource newvalue)
+ {
+ if (newvalue != null)
+ {
+ newvalue.SourceChanged += OnSourceChanged;
+ SetInheritedBindingContext(newvalue, BindingContext);
+ }
+ InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+
+ void OnSourcePropertyChanging(ImageSource oldvalue, ImageSource newvalue)
+ {
+ if (oldvalue != null)
+ oldvalue.SourceChanged -= OnSourceChanged;
+ }
+
+ static void SpecificFontPropertyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var button = (Button)bindable;
+
+ if (button._cancelEvents)
+ return;
+
+ button.InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+
+ button._cancelEvents = true;
+
+ if (button.FontFamily != null)
+ {
+ button.Font = Font.OfSize(button.FontFamily, button.FontSize).WithAttributes(button.FontAttributes);
+ }
+ else
+ {
+ button.Font = Font.SystemFontOfSize(button.FontSize, button.FontAttributes);
+ }
+
+ button._cancelEvents = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/CarouselPage.cs b/Xamarin.Forms.Core/CarouselPage.cs
new file mode 100644
index 00000000..a6f769e5
--- /dev/null
+++ b/Xamarin.Forms.Core/CarouselPage.cs
@@ -0,0 +1,17 @@
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_CarouselPageRenderer))]
+ public class CarouselPage : MultiPage<ContentPage>
+ {
+ protected override ContentPage CreateDefault(object item)
+ {
+ var page = new ContentPage();
+ if (item != null)
+ page.Title = item.ToString();
+
+ return page;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/CarouselView.cs b/Xamarin.Forms.Core/CarouselView.cs
new file mode 100644
index 00000000..62e9393e
--- /dev/null
+++ b/Xamarin.Forms.Core/CarouselView.cs
@@ -0,0 +1,86 @@
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_CarouselViewRenderer))]
+ public class CarouselView : ItemsView, ICarouselViewController
+ {
+ public static readonly BindableProperty PositionProperty = BindableProperty.Create(nameof(Position), typeof(int), typeof(CarouselView), 0, BindingMode.TwoWay);
+
+ public static readonly BindableProperty ItemProperty = BindableProperty.Create(nameof(Item), typeof(object), typeof(CarouselView), 0, BindingMode.TwoWay);
+
+ object _lastItem;
+
+ int _lastPosition;
+
+ public CarouselView()
+ {
+ _lastPosition = 0;
+ _lastItem = null;
+ VerticalOptions = LayoutOptions.FillAndExpand;
+ HorizontalOptions = LayoutOptions.FillAndExpand;
+ }
+
+ public int Item
+ {
+ get { return (int)GetValue(ItemProperty); }
+ }
+
+ public int Position
+ {
+ get { return (int)GetValue(PositionProperty); }
+ set { SetValue(PositionProperty, value); }
+ }
+
+ void ICarouselViewController.SendPositionAppearing(int position)
+ {
+ ItemAppearing?.Invoke(this, new ItemVisibilityEventArgs(GetItem(position)));
+ }
+
+ void ICarouselViewController.SendPositionDisappearing(int position)
+ {
+ ItemDisappearing?.Invoke(this, new ItemVisibilityEventArgs(GetItem(position)));
+ }
+
+ void ICarouselViewController.SendSelectedItemChanged(object item)
+ {
+ if (item.Equals(_lastItem))
+ return;
+
+ ItemSelected?.Invoke(this, new SelectedItemChangedEventArgs(item));
+ _lastItem = item;
+ }
+
+ void ICarouselViewController.SendSelectedPositionChanged(int position)
+ {
+ if (_lastPosition == position)
+ return;
+
+ _lastPosition = position;
+ PositionSelected?.Invoke(this, new SelectedPositionChangedEventArgs(position));
+ }
+
+ public event EventHandler<SelectedItemChangedEventArgs> ItemSelected;
+
+ public event EventHandler<SelectedPositionChangedEventArgs> PositionSelected;
+
+ protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
+ {
+ var minimumSize = new Size(40, 40);
+ return new SizeRequest(minimumSize, minimumSize);
+ }
+
+ // non-public bc unable to implement on iOS
+ internal event EventHandler<ItemVisibilityEventArgs> ItemAppearing;
+
+ internal event EventHandler<ItemVisibilityEventArgs> ItemDisappearing;
+
+ object GetItem(int position)
+ {
+ var controller = (IItemViewController)this;
+ object item = controller.GetItem(position);
+ return item;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/CastingEnumerator.cs b/Xamarin.Forms.Core/CastingEnumerator.cs
new file mode 100644
index 00000000..62a823b1
--- /dev/null
+++ b/Xamarin.Forms.Core/CastingEnumerator.cs
@@ -0,0 +1,46 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ internal class CastingEnumerator<T, TFrom> : IEnumerator<T> where T : class where TFrom : class
+ {
+ readonly IEnumerator<TFrom> _enumerator;
+
+ bool _disposed;
+
+ public CastingEnumerator(IEnumerator<TFrom> enumerator)
+ {
+ _enumerator = enumerator;
+ }
+
+ public void Dispose()
+ {
+ if (_disposed)
+ return;
+ _disposed = true;
+
+ _enumerator.Dispose();
+ }
+
+ object IEnumerator.Current
+ {
+ get { return Current; }
+ }
+
+ public bool MoveNext()
+ {
+ return _enumerator.MoveNext();
+ }
+
+ public void Reset()
+ {
+ _enumerator.Reset();
+ }
+
+ public T Current
+ {
+ get { return _enumerator.Current as T; }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Cells/Cell.cs b/Xamarin.Forms.Core/Cells/Cell.cs
new file mode 100644
index 00000000..3b16d06a
--- /dev/null
+++ b/Xamarin.Forms.Core/Cells/Cell.cs
@@ -0,0 +1,209 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ public abstract class Cell : Element
+ {
+ public static readonly BindableProperty IsEnabledProperty = BindableProperty.Create("IsEnabled", typeof(bool), typeof(Cell), true, propertyChanged: OnIsEnabledPropertyChanged);
+
+ ObservableCollection<MenuItem> _contextActions;
+
+ double _height = -1;
+
+ bool _nextCallToForceUpdateSizeQueued;
+
+ public IList<MenuItem> ContextActions
+ {
+ get
+ {
+ if (_contextActions == null)
+ {
+ _contextActions = new ObservableCollection<MenuItem>();
+ _contextActions.CollectionChanged += OnContextActionsChanged;
+ }
+
+ return _contextActions;
+ }
+ }
+
+ public bool HasContextActions
+ {
+ get { return _contextActions != null && _contextActions.Count > 0 && IsEnabled; }
+ }
+
+ public double Height
+ {
+ get { return _height; }
+ set
+ {
+ if (_height == value)
+ return;
+
+ OnPropertyChanging("Height");
+ OnPropertyChanging("RenderHeight");
+ _height = value;
+ OnPropertyChanged("Height");
+ OnPropertyChanged("RenderHeight");
+ }
+ }
+
+ public bool IsEnabled
+ {
+ get { return (bool)GetValue(IsEnabledProperty); }
+ set { SetValue(IsEnabledProperty, value); }
+ }
+
+ public double RenderHeight
+ {
+ get
+ {
+ var table = RealParent as TableView;
+ if (table != null)
+ return table.HasUnevenRows && Height > 0 ? Height : table.RowHeight;
+
+ var list = RealParent as ListView;
+ if (list != null)
+ return list.HasUnevenRows && Height > 0 ? Height : list.RowHeight;
+
+ return 40;
+ }
+ }
+
+ public event EventHandler Appearing;
+
+ public event EventHandler Disappearing;
+
+ public void ForceUpdateSize()
+ {
+ if (_nextCallToForceUpdateSizeQueued)
+ return;
+
+ if ((Parent as ListView)?.HasUnevenRows == true)
+ {
+ _nextCallToForceUpdateSizeQueued = true;
+ OnForceUpdateSizeRequested();
+ }
+ }
+
+ public event EventHandler Tapped;
+
+ protected internal virtual void OnTapped()
+ {
+ if (Tapped != null)
+ Tapped(this, EventArgs.Empty);
+ }
+
+ protected virtual void OnAppearing()
+ {
+ EventHandler handler = Appearing;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ base.OnBindingContextChanged();
+
+ if (HasContextActions)
+ {
+ for (var i = 0; i < _contextActions.Count; i++)
+ SetInheritedBindingContext(_contextActions[i], BindingContext);
+ }
+ }
+
+ protected virtual void OnDisappearing()
+ {
+ EventHandler handler = Disappearing;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+
+ protected override void OnParentSet()
+ {
+ if (RealParent != null)
+ {
+ RealParent.PropertyChanged += OnParentPropertyChanged;
+ RealParent.PropertyChanging += OnParentPropertyChanging;
+ }
+
+ base.OnParentSet();
+ }
+
+ protected override void OnPropertyChanging(string propertyName = null)
+ {
+ if (propertyName == "Parent")
+ {
+ if (RealParent != null)
+ {
+ RealParent.PropertyChanged -= OnParentPropertyChanged;
+ RealParent.PropertyChanging -= OnParentPropertyChanging;
+ }
+ }
+
+ base.OnPropertyChanging(propertyName);
+ }
+
+ internal event EventHandler ForceUpdateSizeRequested;
+
+ internal void SendAppearing()
+ {
+ OnAppearing();
+
+ var container = RealParent as IListViewController;
+ if (container != null)
+ container.SendCellAppearing(this);
+ }
+
+ internal void SendDisappearing()
+ {
+ OnDisappearing();
+
+ var container = RealParent as IListViewController;
+ if (container != null)
+ container.SendCellDisappearing(this);
+ }
+
+ void OnContextActionsChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ for (var i = 0; i < _contextActions.Count; i++)
+ SetInheritedBindingContext(_contextActions[i], BindingContext);
+
+ OnPropertyChanged("HasContextActions");
+ }
+
+ async void OnForceUpdateSizeRequested()
+ {
+ // don't run more than once per 16 milliseconds
+ await Task.Delay(TimeSpan.FromMilliseconds(16));
+ EventHandler handler = ForceUpdateSizeRequested;
+ if (handler != null)
+ handler(this, null);
+
+ _nextCallToForceUpdateSizeQueued = false;
+ }
+
+ static void OnIsEnabledPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
+ {
+ (bindable as Cell).OnPropertyChanged("HasContextActions");
+ }
+
+ void OnParentPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ // Technically we might be raising this even if it didn't change, but I'm taking the bet that
+ // its uncommon enough that we don't want to take the penalty of N GetValue calls to verify.
+ if (e.PropertyName == "RowHeight")
+ OnPropertyChanged("RenderHeight");
+ }
+
+ void OnParentPropertyChanging(object sender, PropertyChangingEventArgs e)
+ {
+ if (e.PropertyName == "RowHeight")
+ OnPropertyChanging("RenderHeight");
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Cells/EntryCell.cs b/Xamarin.Forms.Core/Cells/EntryCell.cs
new file mode 100644
index 00000000..d74e365e
--- /dev/null
+++ b/Xamarin.Forms.Core/Cells/EntryCell.cs
@@ -0,0 +1,80 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class EntryCell : Cell
+ {
+ public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(EntryCell), null, BindingMode.TwoWay);
+
+ public static readonly BindableProperty LabelProperty = BindableProperty.Create("Label", typeof(string), typeof(EntryCell), null);
+
+ public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create("Placeholder", typeof(string), typeof(EntryCell), null);
+
+ public static readonly BindableProperty LabelColorProperty = BindableProperty.Create("LabelColor", typeof(Color), typeof(EntryCell), Color.Default);
+
+ public static readonly BindableProperty KeyboardProperty = BindableProperty.Create("Keyboard", typeof(Keyboard), typeof(EntryCell), Keyboard.Default);
+
+ public static readonly BindableProperty HorizontalTextAlignmentProperty = BindableProperty.Create("HorizontalTextAlignment", typeof(TextAlignment), typeof(EntryCell), TextAlignment.Start,
+ propertyChanged: OnHorizontalTextAlignmentPropertyChanged);
+
+ [Obsolete("XAlignProperty is obsolete. Please use HorizontalTextAlignmentProperty instead.")] public static readonly BindableProperty XAlignProperty = HorizontalTextAlignmentProperty;
+
+ public TextAlignment HorizontalTextAlignment
+ {
+ get { return (TextAlignment)GetValue(HorizontalTextAlignmentProperty); }
+ set { SetValue(HorizontalTextAlignmentProperty, value); }
+ }
+
+ public Keyboard Keyboard
+ {
+ get { return (Keyboard)GetValue(KeyboardProperty); }
+ set { SetValue(KeyboardProperty, value); }
+ }
+
+ public string Label
+ {
+ get { return (string)GetValue(LabelProperty); }
+ set { SetValue(LabelProperty, value); }
+ }
+
+ public Color LabelColor
+ {
+ get { return (Color)GetValue(LabelColorProperty); }
+ set { SetValue(LabelColorProperty, value); }
+ }
+
+ public string Placeholder
+ {
+ get { return (string)GetValue(PlaceholderProperty); }
+ set { SetValue(PlaceholderProperty, value); }
+ }
+
+ public string Text
+ {
+ get { return (string)GetValue(TextProperty); }
+ set { SetValue(TextProperty, value); }
+ }
+
+ [Obsolete("XAlign is obsolete. Please use HorizontalTextAlignment instead.")]
+ public TextAlignment XAlign
+ {
+ get { return (TextAlignment)GetValue(XAlignProperty); }
+ set { SetValue(XAlignProperty, value); }
+ }
+
+ public event EventHandler Completed;
+
+ internal void SendCompleted()
+ {
+ EventHandler handler = Completed;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+
+ static void OnHorizontalTextAlignmentPropertyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var label = (EntryCell)bindable;
+ label.OnPropertyChanged(nameof(XAlign));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Cells/INativeElementView.cs b/Xamarin.Forms.Core/Cells/INativeElementView.cs
new file mode 100644
index 00000000..2d015282
--- /dev/null
+++ b/Xamarin.Forms.Core/Cells/INativeElementView.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms
+{
+ public interface INativeElementView
+ {
+ Element Element { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Cells/ImageCell.cs b/Xamarin.Forms.Core/Cells/ImageCell.cs
new file mode 100644
index 00000000..6d5ba714
--- /dev/null
+++ b/Xamarin.Forms.Core/Cells/ImageCell.cs
@@ -0,0 +1,56 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class ImageCell : TextCell
+ {
+ public static readonly BindableProperty ImageSourceProperty = BindableProperty.Create("ImageSource", typeof(ImageSource), typeof(ImageCell), null,
+ propertyChanging: (bindable, oldvalue, newvalue) => ((ImageCell)bindable).OnSourcePropertyChanging((ImageSource)oldvalue, (ImageSource)newvalue),
+ propertyChanged: (bindable, oldvalue, newvalue) => ((ImageCell)bindable).OnSourcePropertyChanged((ImageSource)oldvalue, (ImageSource)newvalue));
+
+ public ImageCell()
+ {
+ Disappearing += (sender, e) =>
+ {
+ if (ImageSource == null)
+ return;
+ ImageSource.Cancel();
+ };
+ }
+
+ [TypeConverter(typeof(ImageSourceConverter))]
+ public ImageSource ImageSource
+ {
+ get { return (ImageSource)GetValue(ImageSourceProperty); }
+ set { SetValue(ImageSourceProperty, value); }
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ if (ImageSource != null)
+ SetInheritedBindingContext(ImageSource, BindingContext);
+
+ base.OnBindingContextChanged();
+ }
+
+ void OnSourceChanged(object sender, EventArgs eventArgs)
+ {
+ OnPropertyChanged(ImageSourceProperty.PropertyName);
+ }
+
+ void OnSourcePropertyChanged(ImageSource oldvalue, ImageSource newvalue)
+ {
+ if (newvalue != null)
+ {
+ newvalue.SourceChanged += OnSourceChanged;
+ SetInheritedBindingContext(newvalue, BindingContext);
+ }
+ }
+
+ void OnSourcePropertyChanging(ImageSource oldvalue, ImageSource newvalue)
+ {
+ if (oldvalue != null)
+ oldvalue.SourceChanged -= OnSourceChanged;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Cells/SwitchCell.cs b/Xamarin.Forms.Core/Cells/SwitchCell.cs
new file mode 100644
index 00000000..adab7f45
--- /dev/null
+++ b/Xamarin.Forms.Core/Cells/SwitchCell.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class SwitchCell : Cell
+ {
+ public static readonly BindableProperty OnProperty = BindableProperty.Create("On", typeof(bool), typeof(SwitchCell), false, propertyChanged: (obj, oldValue, newValue) =>
+ {
+ var switchCell = (SwitchCell)obj;
+ EventHandler<ToggledEventArgs> handler = switchCell.OnChanged;
+ if (handler != null)
+ handler(obj, new ToggledEventArgs((bool)newValue));
+ }, defaultBindingMode: BindingMode.TwoWay);
+
+ public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(SwitchCell), default(string));
+
+ public bool On
+ {
+ get { return (bool)GetValue(OnProperty); }
+ set { SetValue(OnProperty, value); }
+ }
+
+ public string Text
+ {
+ get { return (string)GetValue(TextProperty); }
+ set { SetValue(TextProperty, value); }
+ }
+
+ public event EventHandler<ToggledEventArgs> OnChanged;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Cells/TextCell.cs b/Xamarin.Forms.Core/Cells/TextCell.cs
new file mode 100644
index 00000000..01da6447
--- /dev/null
+++ b/Xamarin.Forms.Core/Cells/TextCell.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Windows.Input;
+
+namespace Xamarin.Forms
+{
+ public class TextCell : Cell
+ {
+ public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(TextCell), default(ICommand),
+ propertyChanging: (bindable, oldvalue, newvalue) =>
+ {
+ var textCell = (TextCell)bindable;
+ var oldcommand = (ICommand)oldvalue;
+ if (oldcommand != null)
+ oldcommand.CanExecuteChanged -= textCell.OnCommandCanExecuteChanged;
+ }, propertyChanged: (bindable, oldvalue, newvalue) =>
+ {
+ var textCell = (TextCell)bindable;
+ var newcommand = (ICommand)newvalue;
+ if (newcommand != null)
+ {
+ textCell.IsEnabled = newcommand.CanExecute(textCell.CommandParameter);
+ newcommand.CanExecuteChanged += textCell.OnCommandCanExecuteChanged;
+ }
+ });
+
+ public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create("CommandParameter", typeof(object), typeof(TextCell), default(object),
+ propertyChanged: (bindable, oldvalue, newvalue) =>
+ {
+ var textCell = (TextCell)bindable;
+ if (textCell.Command != null)
+ {
+ textCell.IsEnabled = textCell.Command.CanExecute(newvalue);
+ }
+ });
+
+ public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(TextCell), default(string));
+
+ public static readonly BindableProperty DetailProperty = BindableProperty.Create("Detail", typeof(string), typeof(TextCell), default(string));
+
+ public static readonly BindableProperty TextColorProperty = BindableProperty.Create("TextColor", typeof(Color), typeof(TextCell), Color.Default);
+
+ public static readonly BindableProperty DetailColorProperty = BindableProperty.Create("DetailColor", typeof(Color), typeof(TextCell), Color.Default);
+
+ public ICommand Command
+ {
+ get { return (ICommand)GetValue(CommandProperty); }
+ set { SetValue(CommandProperty, value); }
+ }
+
+ public object CommandParameter
+ {
+ get { return GetValue(CommandParameterProperty); }
+ set { SetValue(CommandParameterProperty, value); }
+ }
+
+ public string Detail
+ {
+ get { return (string)GetValue(DetailProperty); }
+ set { SetValue(DetailProperty, value); }
+ }
+
+ public Color DetailColor
+ {
+ get { return (Color)GetValue(DetailColorProperty); }
+ set { SetValue(DetailColorProperty, value); }
+ }
+
+ public string Text
+ {
+ get { return (string)GetValue(TextProperty); }
+ set { SetValue(TextProperty, value); }
+ }
+
+ public Color TextColor
+ {
+ get { return (Color)GetValue(TextColorProperty); }
+ set { SetValue(TextColorProperty, value); }
+ }
+
+ protected internal override void OnTapped()
+ {
+ base.OnTapped();
+
+ ICommand cmd = Command;
+ if (cmd != null)
+ cmd.Execute(CommandParameter);
+ }
+
+ void OnCommandCanExecuteChanged(object sender, EventArgs eventArgs)
+ {
+ IsEnabled = Command.CanExecute(CommandParameter);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Cells/ViewCell.cs b/Xamarin.Forms.Core/Cells/ViewCell.cs
new file mode 100644
index 00000000..334822f6
--- /dev/null
+++ b/Xamarin.Forms.Core/Cells/ViewCell.cs
@@ -0,0 +1,48 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("View")]
+ public class ViewCell : Cell
+ {
+ ReadOnlyCollection<Element> _logicalChildren;
+
+ View _view;
+
+ public View View
+ {
+ get { return _view; }
+ set
+ {
+ if (_view == value)
+ return;
+
+ OnPropertyChanging();
+
+ if (_view != null)
+ {
+ OnChildRemoved(_view);
+ _view.ComputedConstraint = LayoutConstraint.None;
+ }
+
+ _view = value;
+
+ if (_view != null)
+ {
+ _view.ComputedConstraint = LayoutConstraint.Fixed;
+ OnChildAdded(_view);
+ _logicalChildren = new ReadOnlyCollection<Element>(new List<Element>(new[] { View }));
+ }
+ else
+ {
+ _logicalChildren = null;
+ }
+
+ OnPropertyChanged();
+ }
+ }
+
+ internal override ReadOnlyCollection<Element> LogicalChildren => _logicalChildren ?? base.LogicalChildren;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ChatKeyboard.cs b/Xamarin.Forms.Core/ChatKeyboard.cs
new file mode 100644
index 00000000..26a403a0
--- /dev/null
+++ b/Xamarin.Forms.Core/ChatKeyboard.cs
@@ -0,0 +1,6 @@
+namespace Xamarin.Forms
+{
+ internal sealed class ChatKeyboard : Keyboard
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ChildCollectionChangedEventArgs.cs b/Xamarin.Forms.Core/ChildCollectionChangedEventArgs.cs
new file mode 100644
index 00000000..3c5e946a
--- /dev/null
+++ b/Xamarin.Forms.Core/ChildCollectionChangedEventArgs.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Specialized;
+
+namespace Xamarin.Forms
+{
+ internal class ChildCollectionChangedEventArgs : EventArgs
+ {
+ public ChildCollectionChangedEventArgs(NotifyCollectionChangedEventArgs args)
+ {
+ Args = args;
+ }
+
+ public NotifyCollectionChangedEventArgs Args { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/CollectionSynchronizationCallback.cs b/Xamarin.Forms.Core/CollectionSynchronizationCallback.cs
new file mode 100644
index 00000000..e186e016
--- /dev/null
+++ b/Xamarin.Forms.Core/CollectionSynchronizationCallback.cs
@@ -0,0 +1,7 @@
+using System;
+using System.Collections;
+
+namespace Xamarin.Forms
+{
+ public delegate void CollectionSynchronizationCallback(IEnumerable collection, object context, Action accessMethod, bool writeAccess);
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/CollectionSynchronizationContext.cs b/Xamarin.Forms.Core/CollectionSynchronizationContext.cs
new file mode 100644
index 00000000..a0144260
--- /dev/null
+++ b/Xamarin.Forms.Core/CollectionSynchronizationContext.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ internal sealed class CollectionSynchronizationContext
+ {
+ internal CollectionSynchronizationContext(object context, CollectionSynchronizationCallback callback)
+ {
+ ContextReference = new WeakReference(context);
+ Callback = callback;
+ }
+
+ internal CollectionSynchronizationCallback Callback { get; private set; }
+
+ internal object Context
+ {
+ get { return ContextReference != null ? ContextReference.Target : null; }
+ }
+
+ internal WeakReference ContextReference { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Color.cs b/Xamarin.Forms.Core/Color.cs
new file mode 100644
index 00000000..e9f2987d
--- /dev/null
+++ b/Xamarin.Forms.Core/Color.cs
@@ -0,0 +1,375 @@
+using System;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Xamarin.Forms
+{
+ [DebuggerDisplay("R={R}, G={G}, B={B}, A={A}, Hue={Hue}, Saturation={Saturation}, Luminosity={Luminosity}")]
+ [TypeConverter(typeof(ColorTypeConverter))]
+ public struct Color
+ {
+ readonly Mode _mode;
+
+ enum Mode
+ {
+ Default,
+ Rgb,
+ Hsl
+ }
+
+ public static Color Default
+ {
+ get { return new Color(-1d, -1d, -1d, -1d, Mode.Default); }
+ }
+
+ internal bool IsDefault
+ {
+ get { return _mode == Mode.Default; }
+ }
+
+ public static Color Accent { get; internal set; }
+
+ readonly float _a;
+
+ public double A
+ {
+ get { return _a; }
+ }
+
+ readonly float _r;
+
+ public double R
+ {
+ get { return _r; }
+ }
+
+ readonly float _g;
+
+ public double G
+ {
+ get { return _g; }
+ }
+
+ readonly float _b;
+
+ public double B
+ {
+ get { return _b; }
+ }
+
+ readonly float _hue;
+
+ public double Hue
+ {
+ get { return _hue; }
+ }
+
+ readonly float _saturation;
+
+ public double Saturation
+ {
+ get { return _saturation; }
+ }
+
+ readonly float _luminosity;
+
+ public double Luminosity
+ {
+ get { return _luminosity; }
+ }
+
+ public Color(double r, double g, double b, double a) : this(r, g, b, a, Mode.Rgb)
+ {
+ }
+
+ Color(double w, double x, double y, double z, Mode mode)
+ {
+ _mode = mode;
+ switch (mode)
+ {
+ default:
+ case Mode.Default:
+ _r = _g = _b = _a = -1;
+ _hue = _saturation = _luminosity = -1;
+ break;
+ case Mode.Rgb:
+ _r = (float)w.Clamp(0, 1);
+ _g = (float)x.Clamp(0, 1);
+ _b = (float)y.Clamp(0, 1);
+ _a = (float)z.Clamp(0, 1);
+ ConvertToHsl(_r, _g, _b, mode, out _hue, out _saturation, out _luminosity);
+ break;
+ case Mode.Hsl:
+ _hue = (float)w.Clamp(0, 1);
+ _saturation = (float)x.Clamp(0, 1);
+ _luminosity = (float)y.Clamp(0, 1);
+ _a = (float)z.Clamp(0, 1);
+ ConvertToRgb(_hue, _saturation, _luminosity, mode, out _r, out _g, out _b);
+ break;
+ }
+ }
+
+ public Color(double r, double g, double b) : this(r, g, b, 1)
+ {
+ }
+
+ public Color(double value) : this(value, value, value, 1)
+ {
+ }
+
+ public Color MultiplyAlpha(double alpha)
+ {
+ switch (_mode)
+ {
+ default:
+ case Mode.Default:
+ throw new InvalidOperationException("Invalid on Color.Default");
+ case Mode.Rgb:
+ return new Color(_r, _g, _b, _a * alpha, Mode.Rgb);
+ case Mode.Hsl:
+ return new Color(_hue, _saturation, _luminosity, _a * alpha, Mode.Hsl);
+ }
+ }
+
+ public Color AddLuminosity(double delta)
+ {
+ if (_mode == Mode.Default)
+ throw new InvalidOperationException("Invalid on Color.Default");
+
+ return new Color(_hue, _saturation, _luminosity + delta, _a, Mode.Hsl);
+ }
+
+ public Color WithHue(double hue)
+ {
+ if (_mode == Mode.Default)
+ throw new InvalidOperationException("Invalid on Color.Default");
+ return new Color(hue, _saturation, _luminosity, _a, Mode.Hsl);
+ }
+
+ public Color WithSaturation(double saturation)
+ {
+ if (_mode == Mode.Default)
+ throw new InvalidOperationException("Invalid on Color.Default");
+ return new Color(_hue, saturation, _luminosity, _a, Mode.Hsl);
+ }
+
+ public Color WithLuminosity(double luminosity)
+ {
+ if (_mode == Mode.Default)
+ throw new InvalidOperationException("Invalid on Color.Default");
+ return new Color(_hue, _saturation, luminosity, _a, Mode.Hsl);
+ }
+
+ static void ConvertToRgb(float hue, float saturation, float luminosity, Mode mode, out float r, out float g, out float b)
+ {
+ if (mode != Mode.Hsl)
+ throw new InvalidOperationException();
+
+ if (luminosity == 0)
+ {
+ r = g = b = 0;
+ return;
+ }
+
+ if (saturation == 0)
+ {
+ r = g = b = luminosity;
+ return;
+ }
+ float temp2 = luminosity <= 0.5f ? luminosity * (1.0f + saturation) : luminosity + saturation - luminosity * saturation;
+ float temp1 = 2.0f * luminosity - temp2;
+
+ var t3 = new[] { hue + 1.0f / 3.0f, hue, hue - 1.0f / 3.0f };
+ var clr = new float[] { 0, 0, 0 };
+ for (var i = 0; i < 3; i++)
+ {
+ if (t3[i] < 0)
+ t3[i] += 1.0f;
+ if (t3[i] > 1)
+ t3[i] -= 1.0f;
+ if (6.0 * t3[i] < 1.0)
+ clr[i] = temp1 + (temp2 - temp1) * t3[i] * 6.0f;
+ else if (2.0 * t3[i] < 1.0)
+ clr[i] = temp2;
+ else if (3.0 * t3[i] < 2.0)
+ clr[i] = temp1 + (temp2 - temp1) * (2.0f / 3.0f - t3[i]) * 6.0f;
+ else
+ clr[i] = temp1;
+ }
+
+ r = clr[0];
+ g = clr[1];
+ b = clr[2];
+ }
+
+ static void ConvertToHsl(float r, float g, float b, Mode mode, out float h, out float s, out float l)
+ {
+ float v = Math.Max(r, g);
+ v = Math.Max(v, b);
+
+ float m = Math.Min(r, g);
+ m = Math.Min(m, b);
+
+ l = (m + v) / 2.0f;
+ if (l <= 0.0)
+ {
+ h = s = l = 0;
+ return;
+ }
+ float vm = v - m;
+ s = vm;
+
+ if (s > 0.0)
+ {
+ s /= l <= 0.5f ? v + m : 2.0f - v - m;
+ }
+ else
+ {
+ h = 0;
+ s = 0;
+ return;
+ }
+
+ float r2 = (v - r) / vm;
+ float g2 = (v - g) / vm;
+ float b2 = (v - b) / vm;
+
+ if (r == v)
+ {
+ h = g == m ? 5.0f + b2 : 1.0f - g2;
+ }
+ else if (g == v)
+ {
+ h = b == m ? 1.0f + r2 : 3.0f - b2;
+ }
+ else
+ {
+ h = r == m ? 3.0f + g2 : 5.0f - r2;
+ }
+ h /= 6.0f;
+ }
+
+ public static bool operator ==(Color color1, Color color2)
+ {
+ return EqualsInner(color1, color2);
+ }
+
+ public static bool operator !=(Color color1, Color color2)
+ {
+ return !EqualsInner(color1, color2);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hashcode = _r.GetHashCode();
+ hashcode = (hashcode * 397) ^ _g.GetHashCode();
+ hashcode = (hashcode * 397) ^ _b.GetHashCode();
+ hashcode = (hashcode * 397) ^ _a.GetHashCode();
+ return hashcode;
+ }
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Color)
+ {
+ return EqualsInner(this, (Color)obj);
+ }
+ return base.Equals(obj);
+ }
+
+ static bool EqualsInner(Color color1, Color color2)
+ {
+ if (color1._mode == Mode.Default && color2._mode == Mode.Default)
+ return true;
+ if (color1._mode == Mode.Default || color2._mode == Mode.Default)
+ return false;
+ if (color1._mode == Mode.Hsl && color2._mode == Mode.Hsl)
+ return color1._hue == color2._hue && color1._saturation == color2._saturation && color1._luminosity == color2._luminosity && color1._a == color2._a;
+ return color1._r == color2._r && color1._g == color2._g && color1._b == color2._b && color1._a == color2._a;
+ }
+
+ public override string ToString()
+ {
+ return string.Format(CultureInfo.InvariantCulture, "[Color: A={0}, R={1}, G={2}, B={3}, Hue={4}, Saturation={5}, Luminosity={6}]", A, R, G, B, Hue, Saturation, Luminosity);
+ }
+
+ public static Color FromHex(string hex)
+ {
+ hex = hex.Replace("#", "");
+ switch (hex.Length)
+ {
+ case 3: //#rgb => ffrrggbb
+ hex = string.Format("ff{0}{1}{2}{3}{4}{5}", hex[0], hex[0], hex[1], hex[1], hex[2], hex[2]);
+ break;
+ case 4: //#argb => aarrggbb
+ hex = string.Format("{0}{1}{2}{3}{4}{5}{6}{7}", hex[0], hex[0], hex[1], hex[1], hex[2], hex[2], hex[3], hex[3]);
+ break;
+ case 6: //#rrggbb => ffrrggbb
+ hex = string.Format("ff{0}", hex);
+ break;
+ }
+ return FromUint(Convert.ToUInt32(hex.Replace("#", ""), 16));
+ }
+
+ public static Color FromUint(uint argb)
+ {
+ return FromRgba((byte)((argb & 0x00ff0000) >> 0x10), (byte)((argb & 0x0000ff00) >> 0x8), (byte)(argb & 0x000000ff), (byte)((argb & 0xff000000) >> 0x18));
+ }
+
+ public static Color FromRgba(int r, int g, int b, int a)
+ {
+ double red = (double)r / 255;
+ double green = (double)g / 255;
+ double blue = (double)b / 255;
+ double alpha = (double)a / 255;
+ return new Color(red, green, blue, alpha, Mode.Rgb);
+ }
+
+ public static Color FromRgb(int r, int g, int b)
+ {
+ return FromRgba(r, g, b, 255);
+ }
+
+ public static Color FromRgba(double r, double g, double b, double a)
+ {
+ return new Color(r, g, b, a);
+ }
+
+ public static Color FromRgb(double r, double g, double b)
+ {
+ return new Color(r, g, b, 1d, Mode.Rgb);
+ }
+
+ public static Color FromHsla(double h, double s, double l, double a = 1d)
+ {
+ return new Color(h, s, l, a, Mode.Hsl);
+ }
+
+ #region Color Definitions
+
+ public static readonly Color Transparent = FromRgba(0, 0, 0, 0);
+ public static readonly Color Aqua = FromRgb(0, 255, 255);
+ public static readonly Color Black = FromRgb(0, 0, 0);
+ public static readonly Color Blue = FromRgb(0, 0, 255);
+ public static readonly Color Fuchsia = FromRgb(255, 0, 255);
+ [Obsolete("Fuschia is obsolete as of version 1.3, please use the correct spelling of Fuchsia")] public static readonly Color Fuschia = FromRgb(255, 0, 255);
+ public static readonly Color Gray = FromRgb(128, 128, 128);
+ public static readonly Color Green = FromRgb(0, 128, 0);
+ public static readonly Color Lime = FromRgb(0, 255, 0);
+ public static readonly Color Maroon = FromRgb(128, 0, 0);
+ public static readonly Color Navy = FromRgb(0, 0, 128);
+ public static readonly Color Olive = FromRgb(128, 128, 0);
+ public static readonly Color Purple = FromRgb(128, 0, 128);
+ public static readonly Color Pink = FromRgb(255, 102, 255);
+ public static readonly Color Red = FromRgb(255, 0, 0);
+ public static readonly Color Silver = FromRgb(192, 192, 192);
+ public static readonly Color Teal = FromRgb(0, 128, 128);
+ public static readonly Color White = FromRgb(255, 255, 255);
+ public static readonly Color Yellow = FromRgb(255, 255, 0);
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ColorTypeConverter.cs b/Xamarin.Forms.Core/ColorTypeConverter.cs
new file mode 100644
index 00000000..547adf3b
--- /dev/null
+++ b/Xamarin.Forms.Core/ColorTypeConverter.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Linq;
+using System.Reflection;
+
+namespace Xamarin.Forms
+{
+ public class ColorTypeConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString(string value)
+ {
+ if (value != null)
+ {
+ if (value.Trim().StartsWith("#", StringComparison.Ordinal))
+ return Color.FromHex(value);
+ string[] parts = value.Split('.');
+ if (parts.Length == 1 || (parts.Length == 2 && parts[0] == "Color"))
+ {
+ string color = parts[parts.Length - 1];
+ switch (color)
+ {
+ case "Default":
+ return Color.Default;
+ case "Transparent":
+ return Color.Transparent;
+ case "Aqua":
+ return Color.Aqua;
+ case "Black":
+ return Color.Black;
+ case "Blue":
+ return Color.Blue;
+ case "Fuchsia":
+ return Color.Fuchsia;
+ case "Gray":
+ return Color.Gray;
+ case "Green":
+ return Color.Green;
+ case "Lime":
+ return Color.Lime;
+ case "Maroon":
+ return Color.Maroon;
+ case "Navy":
+ return Color.Navy;
+ case "Olive":
+ return Color.Olive;
+ case "Purple":
+ return Color.Purple;
+ case "Pink":
+ return Color.Pink;
+ case "Red":
+ return Color.Red;
+ case "Silver":
+ return Color.Silver;
+ case "Teal":
+ return Color.Teal;
+ case "White":
+ return Color.White;
+ case "Yellow":
+ return Color.Yellow;
+ }
+ FieldInfo field = typeof(Color).GetFields().FirstOrDefault(fi => fi.IsStatic && fi.Name == color);
+ if (field != null)
+ return (Color)field.GetValue(null);
+ PropertyInfo property = typeof(Color).GetProperties().FirstOrDefault(pi => pi.Name == color && pi.CanRead && pi.GetMethod.IsStatic);
+ if (property != null)
+ return (Color)property.GetValue(null, null);
+ }
+ }
+
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(Color)));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ColumnDefinition.cs b/Xamarin.Forms.Core/ColumnDefinition.cs
new file mode 100644
index 00000000..995f6c73
--- /dev/null
+++ b/Xamarin.Forms.Core/ColumnDefinition.cs
@@ -0,0 +1,34 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public sealed class ColumnDefinition : BindableObject, IDefinition
+ {
+ public static readonly BindableProperty WidthProperty = BindableProperty.Create("Width", typeof(GridLength), typeof(ColumnDefinition), new GridLength(1, GridUnitType.Star),
+ propertyChanged: (bindable, oldValue, newValue) => ((ColumnDefinition)bindable).OnSizeChanged());
+
+ public ColumnDefinition()
+ {
+ MinimumWidth = -1;
+ }
+
+ public GridLength Width
+ {
+ get { return (GridLength)GetValue(WidthProperty); }
+ set { SetValue(WidthProperty, value); }
+ }
+
+ internal double ActualWidth { get; set; }
+
+ internal double MinimumWidth { get; set; }
+
+ public event EventHandler SizeChanged;
+
+ void OnSizeChanged()
+ {
+ EventHandler eh = SizeChanged;
+ if (eh != null)
+ eh(this, EventArgs.Empty);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ColumnDefinitionCollection.cs b/Xamarin.Forms.Core/ColumnDefinitionCollection.cs
new file mode 100644
index 00000000..0ee0358b
--- /dev/null
+++ b/Xamarin.Forms.Core/ColumnDefinitionCollection.cs
@@ -0,0 +1,6 @@
+namespace Xamarin.Forms
+{
+ public sealed class ColumnDefinitionCollection : DefinitionCollection<ColumnDefinition>
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Command.cs b/Xamarin.Forms.Core/Command.cs
new file mode 100644
index 00000000..73ae1b08
--- /dev/null
+++ b/Xamarin.Forms.Core/Command.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Windows.Input;
+
+namespace Xamarin.Forms
+{
+ public sealed class Command<T> : Command
+ {
+ public Command(Action<T> execute) : base(o => execute((T)o))
+ {
+ if (execute == null)
+ throw new ArgumentNullException("execute");
+ }
+
+ public Command(Action<T> execute, Func<T, bool> canExecute) : base(o => execute((T)o), o => canExecute((T)o))
+ {
+ if (execute == null)
+ throw new ArgumentNullException("execute");
+ if (canExecute == null)
+ throw new ArgumentNullException("canExecute");
+ }
+ }
+
+ public class Command : ICommand
+ {
+ readonly Func<object, bool> _canExecute;
+ readonly Action<object> _execute;
+
+ public Command(Action<object> execute)
+ {
+ if (execute == null)
+ throw new ArgumentNullException("execute");
+
+ _execute = execute;
+ }
+
+ public Command(Action execute) : this(o => execute())
+ {
+ if (execute == null)
+ throw new ArgumentNullException("execute");
+ }
+
+ public Command(Action<object> execute, Func<object, bool> canExecute) : this(execute)
+ {
+ if (canExecute == null)
+ throw new ArgumentNullException("canExecute");
+
+ _canExecute = canExecute;
+ }
+
+ public Command(Action execute, Func<bool> canExecute) : this(o => execute(), o => canExecute())
+ {
+ if (execute == null)
+ throw new ArgumentNullException("execute");
+ if (canExecute == null)
+ throw new ArgumentNullException("canExecute");
+ }
+
+ public bool CanExecute(object parameter)
+ {
+ if (_canExecute != null)
+ return _canExecute(parameter);
+
+ return true;
+ }
+
+ public event EventHandler CanExecuteChanged;
+
+ public void Execute(object parameter)
+ {
+ _execute(parameter);
+ }
+
+ public void ChangeCanExecute()
+ {
+ EventHandler changed = CanExecuteChanged;
+ if (changed != null)
+ changed(this, EventArgs.Empty);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ConcurrentDictionary.cs b/Xamarin.Forms.Core/ConcurrentDictionary.cs
new file mode 100644
index 00000000..a229c6fe
--- /dev/null
+++ b/Xamarin.Forms.Core/ConcurrentDictionary.cs
@@ -0,0 +1,426 @@
+// ConcurrentDictionary.cs
+//
+// Copyright (c) 2009 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace Xamarin.Forms
+{
+ internal class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable
+ {
+ readonly IEqualityComparer<TKey> _comparer;
+
+ SplitOrderedList<TKey, KeyValuePair<TKey, TValue>> _internalDictionary;
+
+ public ConcurrentDictionary() : this(EqualityComparer<TKey>.Default)
+ {
+ }
+
+ public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection) : this(collection, EqualityComparer<TKey>.Default)
+ {
+ }
+
+ public ConcurrentDictionary(IEqualityComparer<TKey> comparer)
+ {
+ _comparer = comparer;
+ _internalDictionary = new SplitOrderedList<TKey, KeyValuePair<TKey, TValue>>(comparer);
+ }
+
+ public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer) : this(comparer)
+ {
+ foreach (KeyValuePair<TKey, TValue> pair in collection)
+ Add(pair.Key, pair.Value);
+ }
+
+ // Parameters unused
+ public ConcurrentDictionary(int concurrencyLevel, int capacity) : this(EqualityComparer<TKey>.Default)
+ {
+ }
+
+ public ConcurrentDictionary(int concurrencyLevel, IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer) : this(collection, comparer)
+ {
+ }
+
+ // Parameters unused
+ public ConcurrentDictionary(int concurrencyLevel, int capacity, IEqualityComparer<TKey> comparer) : this(comparer)
+ {
+ }
+
+ public bool IsEmpty
+ {
+ get { return Count == 0; }
+ }
+
+ void ICollection.CopyTo(Array array, int startIndex)
+ {
+ var arr = array as KeyValuePair<TKey, TValue>[];
+ if (arr == null)
+ return;
+
+ CopyTo(arr, startIndex, Count);
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ get { return true; }
+ }
+
+ object ICollection.SyncRoot
+ {
+ get { return this; }
+ }
+
+ void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> pair)
+ {
+ Add(pair.Key, pair.Value);
+ }
+
+ public void Clear()
+ {
+ // Pronk
+ _internalDictionary = new SplitOrderedList<TKey, KeyValuePair<TKey, TValue>>(_comparer);
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> pair)
+ {
+ return ContainsKey(pair.Key);
+ }
+
+ void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int startIndex)
+ {
+ CopyTo(array, startIndex);
+ }
+
+ public int Count
+ {
+ get { return _internalDictionary.Count; }
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
+ {
+ get { return false; }
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> pair)
+ {
+ return Remove(pair.Key);
+ }
+
+ void IDictionary.Add(object key, object value)
+ {
+ if (!(key is TKey) || !(value is TValue))
+ throw new ArgumentException("key or value aren't of correct type");
+
+ Add((TKey)key, (TValue)value);
+ }
+
+ bool IDictionary.Contains(object key)
+ {
+ if (!(key is TKey))
+ return false;
+
+ return ContainsKey((TKey)key);
+ }
+
+ IDictionaryEnumerator IDictionary.GetEnumerator()
+ {
+ return new ConcurrentDictionaryEnumerator(GetEnumeratorInternal());
+ }
+
+ bool IDictionary.IsFixedSize
+ {
+ get { return false; }
+ }
+
+ bool IDictionary.IsReadOnly
+ {
+ get { return false; }
+ }
+
+ object IDictionary.this[object key]
+ {
+ get
+ {
+ if (!(key is TKey))
+ throw new ArgumentException("key isn't of correct type", "key");
+
+ return this[(TKey)key];
+ }
+ set
+ {
+ if (!(key is TKey) || !(value is TValue))
+ throw new ArgumentException("key or value aren't of correct type");
+
+ this[(TKey)key] = (TValue)value;
+ }
+ }
+
+ ICollection IDictionary.Keys
+ {
+ get { return (ICollection)Keys; }
+ }
+
+ void IDictionary.Remove(object key)
+ {
+ if (!(key is TKey))
+ return;
+
+ Remove((TKey)key);
+ }
+
+ ICollection IDictionary.Values
+ {
+ get { return (ICollection)Values; }
+ }
+
+ void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
+ {
+ Add(key, value);
+ }
+
+ public bool ContainsKey(TKey key)
+ {
+ CheckKey(key);
+ KeyValuePair<TKey, TValue> dummy;
+ return _internalDictionary.Find(Hash(key), key, out dummy);
+ }
+
+ public TValue this[TKey key]
+ {
+ get { return GetValue(key); }
+ set { AddOrUpdate(key, value, value); }
+ }
+
+ public ICollection<TKey> Keys
+ {
+ get { return GetPart(kvp => kvp.Key); }
+ }
+
+ bool IDictionary<TKey, TValue>.Remove(TKey key)
+ {
+ return Remove(key);
+ }
+
+ public bool TryGetValue(TKey key, out TValue value)
+ {
+ CheckKey(key);
+ KeyValuePair<TKey, TValue> pair;
+ bool result = _internalDictionary.Find(Hash(key), key, out pair);
+ value = pair.Value;
+
+ return result;
+ }
+
+ public ICollection<TValue> Values
+ {
+ get { return GetPart(kvp => kvp.Value); }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumeratorInternal();
+ }
+
+ public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
+ {
+ return GetEnumeratorInternal();
+ }
+
+ public TValue AddOrUpdate(TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
+ {
+ CheckKey(key);
+ if (addValueFactory == null)
+ throw new ArgumentNullException("addValueFactory");
+ if (updateValueFactory == null)
+ throw new ArgumentNullException("updateValueFactory");
+ return _internalDictionary.InsertOrUpdate(Hash(key), key, () => Make(key, addValueFactory(key)), e => Make(key, updateValueFactory(key, e.Value))).Value;
+ }
+
+ public TValue AddOrUpdate(TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
+ {
+ return AddOrUpdate(key, _ => addValue, updateValueFactory);
+ }
+
+ public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
+ {
+ CheckKey(key);
+ return _internalDictionary.InsertOrGet(Hash(key), key, Make(key, default(TValue)), () => Make(key, valueFactory(key))).Value;
+ }
+
+ public TValue GetOrAdd(TKey key, TValue value)
+ {
+ CheckKey(key);
+ return _internalDictionary.InsertOrGet(Hash(key), key, Make(key, value), null).Value;
+ }
+
+ public KeyValuePair<TKey, TValue>[] ToArray()
+ {
+ // This is most certainly not optimum but there is
+ // not a lot of possibilities
+
+ return new List<KeyValuePair<TKey, TValue>>(this).ToArray();
+ }
+
+ public bool TryAdd(TKey key, TValue value)
+ {
+ CheckKey(key);
+ return _internalDictionary.Insert(Hash(key), key, Make(key, value));
+ }
+
+ public bool TryRemove(TKey key, out TValue value)
+ {
+ CheckKey(key);
+ KeyValuePair<TKey, TValue> data;
+ bool result = _internalDictionary.Delete(Hash(key), key, out data);
+ value = data.Value;
+ return result;
+ }
+
+ public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue)
+ {
+ CheckKey(key);
+ return _internalDictionary.CompareExchange(Hash(key), key, Make(key, newValue), e => e.Value.Equals(comparisonValue));
+ }
+
+ void Add(TKey key, TValue value)
+ {
+ while (!TryAdd(key, value))
+ ;
+ }
+
+ TValue AddOrUpdate(TKey key, TValue addValue, TValue updateValue)
+ {
+ CheckKey(key);
+ return _internalDictionary.InsertOrUpdate(Hash(key), key, Make(key, addValue), Make(key, updateValue)).Value;
+ }
+
+ void CheckKey(TKey key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+ }
+
+ void CopyTo(KeyValuePair<TKey, TValue>[] array, int startIndex)
+ {
+ CopyTo(array, startIndex, Count);
+ }
+
+ void CopyTo(KeyValuePair<TKey, TValue>[] array, int startIndex, int num)
+ {
+ foreach (KeyValuePair<TKey, TValue> kvp in this)
+ {
+ array[startIndex++] = kvp;
+
+ if (--num <= 0)
+ return;
+ }
+ }
+
+ IEnumerator<KeyValuePair<TKey, TValue>> GetEnumeratorInternal()
+ {
+ return _internalDictionary.GetEnumerator();
+ }
+
+ ICollection<T> GetPart<T>(Func<KeyValuePair<TKey, TValue>, T> extractor)
+ {
+ var temp = new List<T>();
+
+ foreach (KeyValuePair<TKey, TValue> kvp in this)
+ temp.Add(extractor(kvp));
+
+ return new ReadOnlyCollection<T>(temp);
+ }
+
+ TValue GetValue(TKey key)
+ {
+ TValue temp;
+ if (!TryGetValue(key, out temp))
+ throw new KeyNotFoundException(key.ToString());
+ return temp;
+ }
+
+ uint Hash(TKey key)
+ {
+ return (uint)_comparer.GetHashCode(key);
+ }
+
+ static KeyValuePair<T, V> Make<T, V>(T key, V value)
+ {
+ return new KeyValuePair<T, V>(key, value);
+ }
+
+ bool Remove(TKey key)
+ {
+ TValue dummy;
+
+ return TryRemove(key, out dummy);
+ }
+
+ class ConcurrentDictionaryEnumerator : IDictionaryEnumerator
+ {
+ readonly IEnumerator<KeyValuePair<TKey, TValue>> _internalEnum;
+
+ public ConcurrentDictionaryEnumerator(IEnumerator<KeyValuePair<TKey, TValue>> internalEnum)
+ {
+ _internalEnum = internalEnum;
+ }
+
+ public DictionaryEntry Entry
+ {
+ get
+ {
+ KeyValuePair<TKey, TValue> current = _internalEnum.Current;
+ return new DictionaryEntry(current.Key, current.Value);
+ }
+ }
+
+ public object Key
+ {
+ get { return _internalEnum.Current.Key; }
+ }
+
+ public object Value
+ {
+ get { return _internalEnum.Current.Value; }
+ }
+
+ public object Current
+ {
+ get { return Entry; }
+ }
+
+ public bool MoveNext()
+ {
+ return _internalEnum.MoveNext();
+ }
+
+ public void Reset()
+ {
+ _internalEnum.Reset();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Constraint.cs b/Xamarin.Forms.Core/Constraint.cs
new file mode 100644
index 00000000..bd219f0a
--- /dev/null
+++ b/Xamarin.Forms.Core/Constraint.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+
+namespace Xamarin.Forms
+{
+ [TypeConverter(typeof(ConstraintTypeConverter))]
+ public sealed class Constraint
+ {
+ Func<RelativeLayout, double> _measureFunc;
+
+ Constraint()
+ {
+ }
+
+ internal IEnumerable<View> RelativeTo { get; set; }
+
+ public static Constraint Constant(double size)
+ {
+ var result = new Constraint { _measureFunc = parent => size };
+
+ return result;
+ }
+
+ public static Constraint FromExpression(Expression<Func<double>> expression)
+ {
+ Func<double> compiled = expression.Compile();
+ var result = new Constraint
+ {
+ _measureFunc = layout => compiled(),
+ RelativeTo = ExpressionSearch.Default.FindObjects<View>(expression).ToArray() // make sure we have our own copy
+ };
+
+ return result;
+ }
+
+ public static Constraint RelativeToParent(Func<RelativeLayout, double> measure)
+ {
+ var result = new Constraint { _measureFunc = measure };
+
+ return result;
+ }
+
+ public static Constraint RelativeToView(View view, Func<RelativeLayout, View, double> measure)
+ {
+ var result = new Constraint { _measureFunc = layout => measure(layout, view), RelativeTo = new[] { view } };
+
+ return result;
+ }
+
+ internal double Compute(RelativeLayout parent)
+ {
+ return _measureFunc(parent);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ConstraintExpression.cs b/Xamarin.Forms.Core/ConstraintExpression.cs
new file mode 100644
index 00000000..b2ca4b8f
--- /dev/null
+++ b/Xamarin.Forms.Core/ConstraintExpression.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms
+{
+ public class ConstraintExpression : IMarkupExtension
+ {
+ public ConstraintExpression()
+ {
+ Factor = 1.0;
+ }
+
+ public double Constant { get; set; }
+
+ public string ElementName { get; set; }
+
+ public double Factor { get; set; }
+
+ public string Property { get; set; }
+
+ public ConstraintType Type { get; set; }
+
+ public object ProvideValue(IServiceProvider serviceProvider)
+ {
+ MethodInfo minfo;
+ switch (Type)
+ {
+ default:
+ case ConstraintType.RelativeToParent:
+ if (string.IsNullOrEmpty(Property))
+ return null;
+ minfo = typeof(View).GetProperties().First(pi => pi.Name == Property && pi.CanRead && pi.GetMethod.IsPublic).GetMethod;
+ return Constraint.RelativeToParent(p => (double)minfo.Invoke(p, new object[] { }) * Factor + Constant);
+ case ConstraintType.Constant:
+ return Constraint.Constant(Constant);
+ case ConstraintType.RelativeToView:
+ if (string.IsNullOrEmpty(Property))
+ return null;
+ if (string.IsNullOrEmpty(ElementName))
+ return null;
+ minfo = typeof(View).GetProperties().First(pi => pi.Name == Property && pi.CanRead && pi.GetMethod.IsPublic).GetMethod;
+ var valueProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
+ if (valueProvider == null || !(valueProvider.TargetObject is INameScope))
+ return null;
+ var view = ((INameScope)valueProvider.TargetObject).FindByName<View>(ElementName);
+ return Constraint.RelativeToView(view, delegate(RelativeLayout p, View v) { return (double)minfo.Invoke(v, new object[] { }) * Factor + Constant; });
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ConstraintType.cs b/Xamarin.Forms.Core/ConstraintType.cs
new file mode 100644
index 00000000..5ee8bc9a
--- /dev/null
+++ b/Xamarin.Forms.Core/ConstraintType.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Forms
+{
+ public enum ConstraintType
+ {
+ RelativeToParent,
+ RelativeToView,
+ Constant
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ConstraintTypeConverter.cs b/Xamarin.Forms.Core/ConstraintTypeConverter.cs
new file mode 100644
index 00000000..8cc45229
--- /dev/null
+++ b/Xamarin.Forms.Core/ConstraintTypeConverter.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Globalization;
+
+namespace Xamarin.Forms
+{
+ public class ConstraintTypeConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString(string value)
+ {
+ double size;
+ if (value != null && double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out size))
+ return Constraint.Constant(size);
+
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(Color)));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ContentPage.cs b/Xamarin.Forms.Core/ContentPage.cs
new file mode 100644
index 00000000..01957c39
--- /dev/null
+++ b/Xamarin.Forms.Core/ContentPage.cs
@@ -0,0 +1,26 @@
+namespace Xamarin.Forms
+{
+ [ContentProperty("Content")]
+ public class ContentPage : TemplatedPage
+ {
+ public static readonly BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(View), typeof(ContentPage), null, propertyChanged: TemplateUtilities.OnContentChanged);
+
+ public View Content
+ {
+ get { return (View)GetValue(ContentProperty); }
+ set { SetValue(ContentProperty, value); }
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ base.OnBindingContextChanged();
+
+ View content = Content;
+ ControlTemplate controlTemplate = ControlTemplate;
+ if (content != null && controlTemplate != null)
+ {
+ SetInheritedBindingContext(content, BindingContext);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ContentPresenter.cs b/Xamarin.Forms.Core/ContentPresenter.cs
new file mode 100644
index 00000000..a99a048b
--- /dev/null
+++ b/Xamarin.Forms.Core/ContentPresenter.cs
@@ -0,0 +1,91 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class ContentPresenter : Layout
+ {
+ public static BindableProperty ContentProperty = BindableProperty.Create("Content", typeof(View), typeof(ContentPresenter), null, propertyChanged: OnContentChanged);
+
+ public ContentPresenter()
+ {
+ SetBinding(ContentProperty, new TemplateBinding("Content"));
+ }
+
+ public View Content
+ {
+ get { return (View)GetValue(ContentProperty); }
+ set { SetValue(ContentProperty, value); }
+ }
+
+ protected override void LayoutChildren(double x, double y, double width, double height)
+ {
+ for (var i = 0; i < LogicalChildren.Count; i++)
+ {
+ Element element = LogicalChildren[i];
+ var child = element as View;
+ if (child != null)
+ LayoutChildIntoBoundingRegion(child, new Rectangle(x, y, width, height));
+ }
+ }
+
+ [Obsolete("Use OnMeasure")]
+ protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ double widthRequest = WidthRequest;
+ double heightRequest = HeightRequest;
+ var childRequest = new SizeRequest();
+ if ((widthRequest == -1 || heightRequest == -1) && Content != null)
+ {
+ childRequest = Content.Measure(widthConstraint, heightConstraint, MeasureFlags.IncludeMargins);
+ }
+
+ return new SizeRequest
+ {
+ Request = new Size { Width = widthRequest != -1 ? widthRequest : childRequest.Request.Width, Height = heightRequest != -1 ? heightRequest : childRequest.Request.Height },
+ Minimum = childRequest.Minimum
+ };
+ }
+
+ internal virtual void Clear()
+ {
+ Content = null;
+ }
+
+ internal override void ComputeConstraintForView(View view)
+ {
+ bool isFixedHorizontally = (Constraint & LayoutConstraint.HorizontallyFixed) != 0;
+ bool isFixedVertically = (Constraint & LayoutConstraint.VerticallyFixed) != 0;
+
+ var result = LayoutConstraint.None;
+ if (isFixedVertically && view.VerticalOptions.Alignment == LayoutAlignment.Fill)
+ result |= LayoutConstraint.VerticallyFixed;
+ if (isFixedHorizontally && view.HorizontalOptions.Alignment == LayoutAlignment.Fill)
+ result |= LayoutConstraint.HorizontallyFixed;
+ view.ComputedConstraint = result;
+ }
+
+ internal override void SetChildInheritedBindingContext(Element child, object context)
+ {
+ // We never want to use the standard inheritance mechanism, we will get this set by our parent
+ }
+
+ static async void OnContentChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var self = (ContentPresenter)bindable;
+
+ var oldView = (View)oldValue;
+ var newView = (View)newValue;
+ if (oldView != null)
+ {
+ self.InternalChildren.Remove(oldView);
+ oldView.ParentOverride = null;
+ }
+
+ if (newView != null)
+ {
+ self.InternalChildren.Add(newView);
+ newView.ParentOverride = await TemplateUtilities.FindTemplatedParentAsync((Element)bindable);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ContentPropertyAttribute.cs b/Xamarin.Forms.Core/ContentPropertyAttribute.cs
new file mode 100644
index 00000000..7aa60744
--- /dev/null
+++ b/Xamarin.Forms.Core/ContentPropertyAttribute.cs
@@ -0,0 +1,26 @@
+//
+// ContentPropertyAttribute.cs
+//
+// Author:
+// Stephane Delcroix <stephane@delcroix.org>
+//
+// Copyright (c) 2013 S. Delcroix
+//
+
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Class)]
+ public sealed class ContentPropertyAttribute : Attribute
+ {
+ internal static string[] ContentPropertyTypes = { "Xamarin.Forms.ContentPropertyAttribute", "System.Windows.Markup.ContentPropertyAttribute" };
+
+ public ContentPropertyAttribute(string name)
+ {
+ Name = name;
+ }
+
+ public string Name { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ContentView.cs b/Xamarin.Forms.Core/ContentView.cs
new file mode 100644
index 00000000..a30688f9
--- /dev/null
+++ b/Xamarin.Forms.Core/ContentView.cs
@@ -0,0 +1,26 @@
+namespace Xamarin.Forms
+{
+ [ContentProperty("Content")]
+ public class ContentView : TemplatedView
+ {
+ public static readonly BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(View), typeof(ContentView), null, propertyChanged: TemplateUtilities.OnContentChanged);
+
+ public View Content
+ {
+ get { return (View)GetValue(ContentProperty); }
+ set { SetValue(ContentProperty, value); }
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ base.OnBindingContextChanged();
+
+ View content = Content;
+ ControlTemplate controlTemplate = ControlTemplate;
+ if (content != null && controlTemplate != null)
+ {
+ SetInheritedBindingContext(content, BindingContext);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ControlTemplate.cs b/Xamarin.Forms.Core/ControlTemplate.cs
new file mode 100644
index 00000000..1e198e97
--- /dev/null
+++ b/Xamarin.Forms.Core/ControlTemplate.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class ControlTemplate : ElementTemplate
+ {
+ public ControlTemplate()
+ {
+ }
+
+ public ControlTemplate(Type type) : base(type)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/CustomKeyboard.cs b/Xamarin.Forms.Core/CustomKeyboard.cs
new file mode 100644
index 00000000..422198cc
--- /dev/null
+++ b/Xamarin.Forms.Core/CustomKeyboard.cs
@@ -0,0 +1,12 @@
+namespace Xamarin.Forms
+{
+ internal sealed class CustomKeyboard : Keyboard
+ {
+ internal CustomKeyboard(KeyboardFlags flags)
+ {
+ Flags = flags;
+ }
+
+ internal KeyboardFlags Flags { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/DataTemplate.cs b/Xamarin.Forms.Core/DataTemplate.cs
new file mode 100644
index 00000000..676718a0
--- /dev/null
+++ b/Xamarin.Forms.Core/DataTemplate.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ public class DataTemplate : ElementTemplate
+ {
+ public DataTemplate()
+ {
+ }
+
+ public DataTemplate(Type type) : base(type)
+ {
+ }
+
+ public DataTemplate(Func<object> loadTemplate) : base(loadTemplate)
+ {
+ }
+
+ public IDictionary<BindableProperty, BindingBase> Bindings { get; } = new Dictionary<BindableProperty, BindingBase>();
+
+ public IDictionary<BindableProperty, object> Values { get; } = new Dictionary<BindableProperty, object>();
+
+ public void SetBinding(BindableProperty property, BindingBase binding)
+ {
+ if (property == null)
+ throw new ArgumentNullException("property");
+ if (binding == null)
+ throw new ArgumentNullException("binding");
+
+ Values.Remove(property);
+ Bindings[property] = binding;
+ }
+
+ public void SetValue(BindableProperty property, object value)
+ {
+ if (property == null)
+ throw new ArgumentNullException("property");
+
+ Bindings.Remove(property);
+ Values[property] = value;
+ }
+
+ internal override void SetupContent(object item)
+ {
+ ApplyBindings(item);
+ ApplyValues(item);
+ }
+
+ void ApplyBindings(object item)
+ {
+ if (Bindings == null)
+ return;
+
+ var bindable = item as BindableObject;
+ if (bindable == null)
+ return;
+
+ foreach (KeyValuePair<BindableProperty, BindingBase> kvp in Bindings)
+ {
+ if (Values.ContainsKey(kvp.Key))
+ throw new InvalidOperationException("Binding and Value found for " + kvp.Key.PropertyName);
+
+ bindable.SetBinding(kvp.Key, kvp.Value.Clone());
+ }
+ }
+
+ void ApplyValues(object item)
+ {
+ if (Values == null)
+ return;
+
+ var bindable = item as BindableObject;
+ if (bindable == null)
+ return;
+ foreach (KeyValuePair<BindableProperty, object> kvp in Values)
+ bindable.SetValue(kvp.Key, kvp.Value);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/DataTemplateExtensions.cs b/Xamarin.Forms.Core/DataTemplateExtensions.cs
new file mode 100644
index 00000000..ffa0ffd0
--- /dev/null
+++ b/Xamarin.Forms.Core/DataTemplateExtensions.cs
@@ -0,0 +1,15 @@
+namespace Xamarin.Forms
+{
+ internal static class DataTemplateExtensions
+ {
+ public static object CreateContent(this DataTemplate self, object item, BindableObject container)
+ {
+ var selector = self as DataTemplateSelector;
+ if (selector != null)
+ {
+ self = selector.SelectTemplate(item, container);
+ }
+ return self.CreateContent();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/DataTemplateSelector.cs b/Xamarin.Forms.Core/DataTemplateSelector.cs
new file mode 100644
index 00000000..8ffa4781
--- /dev/null
+++ b/Xamarin.Forms.Core/DataTemplateSelector.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public abstract class DataTemplateSelector : DataTemplate
+ {
+ public DataTemplate SelectTemplate(object item, BindableObject container)
+ {
+ DataTemplate result = OnSelectTemplate(item, container);
+ if (result is DataTemplateSelector)
+ throw new NotSupportedException("DataTemplateSelector.OnSelectTemplate must not return another DataTemplateSelector");
+ return result;
+ }
+
+ protected abstract DataTemplate OnSelectTemplate(object item, BindableObject container);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/DateChangedEventArgs.cs b/Xamarin.Forms.Core/DateChangedEventArgs.cs
new file mode 100644
index 00000000..8fbc803d
--- /dev/null
+++ b/Xamarin.Forms.Core/DateChangedEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class DateChangedEventArgs : EventArgs
+ {
+ public DateChangedEventArgs(DateTime oldDate, DateTime newDate)
+ {
+ OldDate = oldDate;
+ NewDate = newDate;
+ }
+
+ public DateTime NewDate { get; private set; }
+
+ public DateTime OldDate { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/DatePicker.cs b/Xamarin.Forms.Core/DatePicker.cs
new file mode 100644
index 00000000..15f1c198
--- /dev/null
+++ b/Xamarin.Forms.Core/DatePicker.cs
@@ -0,0 +1,99 @@
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_DatePickerRenderer))]
+ public class DatePicker : View
+ {
+ public static readonly BindableProperty FormatProperty = BindableProperty.Create("Format", typeof(string), typeof(DatePicker), "d");
+
+ public static readonly BindableProperty DateProperty = BindableProperty.Create("Date", typeof(DateTime), typeof(DatePicker), DateTime.Today, BindingMode.TwoWay, coerceValue: CoerceDate,
+ propertyChanged: DatePropertyChanged);
+
+ public static readonly BindableProperty MinimumDateProperty = BindableProperty.Create("MinimumDate", typeof(DateTime), typeof(DatePicker), new DateTime(1900, 1, 1),
+ validateValue: ValidateMinimumDate, coerceValue: CoerceMinimumDate);
+
+ public static readonly BindableProperty MaximumDateProperty = BindableProperty.Create("MaximumDate", typeof(DateTime), typeof(DatePicker), new DateTime(2100, 12, 31),
+ validateValue: ValidateMaximumDate, coerceValue: CoerceMaximumDate);
+
+ public DateTime Date
+ {
+ get { return (DateTime)GetValue(DateProperty); }
+ set { SetValue(DateProperty, value); }
+ }
+
+ public string Format
+ {
+ get { return (string)GetValue(FormatProperty); }
+ set { SetValue(FormatProperty, value); }
+ }
+
+ public DateTime MaximumDate
+ {
+ get { return (DateTime)GetValue(MaximumDateProperty); }
+ set { SetValue(MaximumDateProperty, value); }
+ }
+
+ public DateTime MinimumDate
+ {
+ get { return (DateTime)GetValue(MinimumDateProperty); }
+ set { SetValue(MinimumDateProperty, value); }
+ }
+
+ public event EventHandler<DateChangedEventArgs> DateSelected;
+
+ static object CoerceDate(BindableObject bindable, object value)
+ {
+ var picker = (DatePicker)bindable;
+ DateTime dateValue = ((DateTime)value).Date;
+
+ if (dateValue > picker.MaximumDate)
+ dateValue = picker.MaximumDate;
+
+ if (dateValue < picker.MinimumDate)
+ dateValue = picker.MinimumDate;
+
+ return dateValue;
+ }
+
+ static object CoerceMaximumDate(BindableObject bindable, object value)
+ {
+ DateTime dateValue = ((DateTime)value).Date;
+ var picker = (DatePicker)bindable;
+ if (picker.Date > dateValue)
+ picker.Date = dateValue;
+
+ return dateValue;
+ }
+
+ static object CoerceMinimumDate(BindableObject bindable, object value)
+ {
+ DateTime dateValue = ((DateTime)value).Date;
+ var picker = (DatePicker)bindable;
+ if (picker.Date < dateValue)
+ picker.Date = dateValue;
+
+ return dateValue;
+ }
+
+ static void DatePropertyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var datePicker = (DatePicker)bindable;
+ EventHandler<DateChangedEventArgs> selected = datePicker.DateSelected;
+
+ if (selected != null)
+ selected(datePicker, new DateChangedEventArgs((DateTime)oldValue, (DateTime)newValue));
+ }
+
+ static bool ValidateMaximumDate(BindableObject bindable, object value)
+ {
+ return (DateTime)value >= ((DatePicker)bindable).MinimumDate;
+ }
+
+ static bool ValidateMinimumDate(BindableObject bindable, object value)
+ {
+ return (DateTime)value <= ((DatePicker)bindable).MaximumDate;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/DefinitionCollection.cs b/Xamarin.Forms.Core/DefinitionCollection.cs
new file mode 100644
index 00000000..bf0e4d06
--- /dev/null
+++ b/Xamarin.Forms.Core/DefinitionCollection.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ public class DefinitionCollection<T> : IList<T>, ICollection<T> where T : IDefinition
+ {
+ readonly List<T> _internalList = new List<T>();
+
+ internal DefinitionCollection()
+ {
+ }
+
+ public void Add(T item)
+ {
+ _internalList.Add(item);
+ item.SizeChanged += OnItemSizeChanged;
+ OnItemSizeChanged(this, EventArgs.Empty);
+ }
+
+ public void Clear()
+ {
+ foreach (T item in _internalList)
+ item.SizeChanged -= OnItemSizeChanged;
+ _internalList.Clear();
+ OnItemSizeChanged(this, EventArgs.Empty);
+ }
+
+ public bool Contains(T item)
+ {
+ return _internalList.Contains(item);
+ }
+
+ public void CopyTo(T[] array, int arrayIndex)
+ {
+ _internalList.CopyTo(array, arrayIndex);
+ }
+
+ public int Count
+ {
+ get { return _internalList.Count; }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ public bool Remove(T item)
+ {
+ item.SizeChanged -= OnItemSizeChanged;
+ bool success = _internalList.Remove(item);
+ if (success)
+ OnItemSizeChanged(this, EventArgs.Empty);
+ return success;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return _internalList.GetEnumerator();
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ return _internalList.GetEnumerator();
+ }
+
+ public int IndexOf(T item)
+ {
+ return _internalList.IndexOf(item);
+ }
+
+ public void Insert(int index, T item)
+ {
+ _internalList.Insert(index, item);
+ item.SizeChanged += OnItemSizeChanged;
+ OnItemSizeChanged(this, EventArgs.Empty);
+ }
+
+ public T this[int index]
+ {
+ get { return _internalList[index]; }
+ set
+ {
+ _internalList[index] = value;
+ value.SizeChanged += OnItemSizeChanged;
+ OnItemSizeChanged(this, EventArgs.Empty);
+ }
+ }
+
+ public void RemoveAt(int index)
+ {
+ T item = _internalList[index];
+ _internalList.RemoveAt(index);
+ item.SizeChanged -= OnItemSizeChanged;
+ OnItemSizeChanged(this, EventArgs.Empty);
+ }
+
+ public event EventHandler ItemSizeChanged;
+
+ void OnItemSizeChanged(object sender, EventArgs e)
+ {
+ EventHandler eh = ItemSizeChanged;
+ if (eh != null)
+ eh(this, EventArgs.Empty);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/DelegateLogListener.cs b/Xamarin.Forms.Core/DelegateLogListener.cs
new file mode 100644
index 00000000..20a0ab76
--- /dev/null
+++ b/Xamarin.Forms.Core/DelegateLogListener.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ internal class DelegateLogListener : LogListener
+ {
+ readonly Action<string, string> _log;
+
+ public DelegateLogListener(Action<string, string> log)
+ {
+ if (log == null)
+ throw new ArgumentNullException("log");
+
+ _log = log;
+ }
+
+ public override void Warning(string category, string message)
+ {
+ _log(category, message);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/DependencyAttribute.cs b/Xamarin.Forms.Core/DependencyAttribute.cs
new file mode 100644
index 00000000..e0ea22a1
--- /dev/null
+++ b/Xamarin.Forms.Core/DependencyAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public class DependencyAttribute : Attribute
+ {
+ public DependencyAttribute(Type implementorType)
+ {
+ Implementor = implementorType;
+ }
+
+ internal Type Implementor { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/DependencyFetchTarget.cs b/Xamarin.Forms.Core/DependencyFetchTarget.cs
new file mode 100644
index 00000000..2433c4f4
--- /dev/null
+++ b/Xamarin.Forms.Core/DependencyFetchTarget.cs
@@ -0,0 +1,8 @@
+namespace Xamarin.Forms
+{
+ public enum DependencyFetchTarget
+ {
+ GlobalInstance,
+ NewInstance
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/DependencyService.cs b/Xamarin.Forms.Core/DependencyService.cs
new file mode 100644
index 00000000..d3c43998
--- /dev/null
+++ b/Xamarin.Forms.Core/DependencyService.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Xamarin.Forms
+{
+ public static class DependencyService
+ {
+ static bool s_initialized;
+
+ static readonly List<Type> DependencyTypes = new List<Type>();
+ static readonly Dictionary<Type, DependencyData> DependencyImplementations = new Dictionary<Type, DependencyData>();
+
+ public static T Get<T>(DependencyFetchTarget fetchTarget = DependencyFetchTarget.GlobalInstance) where T : class
+ {
+ if (!s_initialized)
+ Initialize();
+
+ Type targetType = typeof(T);
+
+ if (!DependencyImplementations.ContainsKey(targetType))
+ {
+ Type implementor = FindImplementor(targetType);
+ DependencyImplementations[targetType] = implementor != null ? new DependencyData { ImplementorType = implementor } : null;
+ }
+
+ DependencyData dependencyImplementation = DependencyImplementations[targetType];
+ if (dependencyImplementation == null)
+ return null;
+
+ if (fetchTarget == DependencyFetchTarget.GlobalInstance)
+ {
+ if (dependencyImplementation.GlobalInstance == null)
+ {
+ dependencyImplementation.GlobalInstance = Activator.CreateInstance(dependencyImplementation.ImplementorType);
+ }
+ return (T)dependencyImplementation.GlobalInstance;
+ }
+ return (T)Activator.CreateInstance(dependencyImplementation.ImplementorType);
+ }
+
+ public static void Register<T>() where T : class
+ {
+ Type type = typeof(T);
+ if (!DependencyTypes.Contains(type))
+ DependencyTypes.Add(type);
+ }
+
+ public static void Register<T, TImpl>() where T : class where TImpl : class, T
+ {
+ Type targetType = typeof(T);
+ Type implementorType = typeof(TImpl);
+ if (!DependencyTypes.Contains(targetType))
+ DependencyTypes.Add(targetType);
+
+ DependencyImplementations[targetType] = new DependencyData { ImplementorType = implementorType };
+ }
+
+ static Type FindImplementor(Type target)
+ {
+ return DependencyTypes.FirstOrDefault(t => target.IsAssignableFrom(t));
+ }
+
+ static void Initialize()
+ {
+ Assembly[] assemblies = Device.GetAssemblies();
+ if (Registrar.ExtraAssemblies != null)
+ {
+ assemblies = assemblies.Union(Registrar.ExtraAssemblies).ToArray();
+ }
+
+ Type targetAttrType = typeof(DependencyAttribute);
+
+ // Don't use LINQ for performance reasons
+ // Naive implementation can easily take over a second to run
+ foreach (Assembly assembly in assemblies)
+ {
+ Attribute[] attributes = assembly.GetCustomAttributes(targetAttrType).ToArray();
+ if (attributes.Length == 0)
+ continue;
+
+ foreach (DependencyAttribute attribute in attributes)
+ {
+ if (!DependencyTypes.Contains(attribute.Implementor))
+ {
+ DependencyTypes.Add(attribute.Implementor);
+ }
+ }
+ }
+
+ s_initialized = true;
+ }
+
+ class DependencyData
+ {
+ public object GlobalInstance { get; set; }
+
+ public Type ImplementorType { get; set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Device.cs b/Xamarin.Forms.Core/Device.cs
new file mode 100644
index 00000000..db0a2747
--- /dev/null
+++ b/Xamarin.Forms.Core/Device.cs
@@ -0,0 +1,159 @@
+using System;
+using System.IO;
+using System.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ public static class Device
+ {
+ internal static DeviceInfo info;
+
+ static IPlatformServices s_platformServices;
+
+ public static TargetIdiom Idiom { get; internal set; }
+
+ public static TargetPlatform OS { get; internal set; }
+
+ internal static DeviceInfo Info
+ {
+ get
+ {
+ if (info == null)
+ throw new InvalidOperationException("You MUST call Xamarin.Forms.Init(); prior to using it.");
+ return info;
+ }
+ set { info = value; }
+ }
+
+ internal static bool IsInvokeRequired
+ {
+ get { return PlatformServices.IsInvokeRequired; }
+ }
+
+ internal static IPlatformServices PlatformServices
+ {
+ get
+ {
+ if (s_platformServices == null)
+ throw new InvalidOperationException("You MUST call Xamarin.Forms.Init(); prior to using it.");
+ return s_platformServices;
+ }
+ set { s_platformServices = value; }
+ }
+
+ public static void BeginInvokeOnMainThread(Action action)
+ {
+ PlatformServices.BeginInvokeOnMainThread(action);
+ }
+
+ public static double GetNamedSize(NamedSize size, Element targetElement)
+ {
+ return GetNamedSize(size, targetElement.GetType());
+ }
+
+ public static double GetNamedSize(NamedSize size, Type targetElementType)
+ {
+ return GetNamedSize(size, targetElementType, false);
+ }
+
+ public static void OnPlatform(Action iOS = null, Action Android = null, Action WinPhone = null, Action Default = null)
+ {
+ switch (OS)
+ {
+ case TargetPlatform.iOS:
+ if (iOS != null)
+ iOS();
+ else if (Default != null)
+ Default();
+ break;
+ case TargetPlatform.Android:
+ if (Android != null)
+ Android();
+ else if (Default != null)
+ Default();
+ break;
+ case TargetPlatform.Windows:
+ case TargetPlatform.WinPhone:
+ if (WinPhone != null)
+ WinPhone();
+ else if (Default != null)
+ Default();
+ break;
+ case TargetPlatform.Other:
+ if (Default != null)
+ Default();
+ break;
+ }
+ }
+
+ public static T OnPlatform<T>(T iOS, T Android, T WinPhone)
+ {
+ switch (OS)
+ {
+ case TargetPlatform.iOS:
+ return iOS;
+ case TargetPlatform.Android:
+ return Android;
+ case TargetPlatform.Windows:
+ case TargetPlatform.WinPhone:
+ return WinPhone;
+ }
+
+ return iOS;
+ }
+
+ public static void OpenUri(Uri uri)
+ {
+ PlatformServices.OpenUriAction(uri);
+ }
+
+ public static void StartTimer(TimeSpan interval, Func<bool> callback)
+ {
+ PlatformServices.StartTimer(interval, callback);
+ }
+
+ internal static Assembly[] GetAssemblies()
+ {
+ return PlatformServices.GetAssemblies();
+ }
+
+ internal static double GetNamedSize(NamedSize size, Type targetElementType, bool useOldSizes)
+ {
+ return PlatformServices.GetNamedSize(size, targetElementType, useOldSizes);
+ }
+
+ internal static Task<Stream> GetStreamAsync(Uri uri, CancellationToken cancellationToken)
+ {
+ return PlatformServices.GetStreamAsync(uri, cancellationToken);
+ }
+
+ public static class Styles
+ {
+ public static readonly string TitleStyleKey = "TitleStyle";
+
+ public static readonly string SubtitleStyleKey = "SubtitleStyle";
+
+ public static readonly string BodyStyleKey = "BodyStyle";
+
+ public static readonly string ListItemTextStyleKey = "ListItemTextStyle";
+
+ public static readonly string ListItemDetailTextStyleKey = "ListItemDetailTextStyle";
+
+ public static readonly string CaptionStyleKey = "CaptionStyle";
+
+ public static readonly Style TitleStyle = new Style(typeof(Label)) { BaseResourceKey = TitleStyleKey };
+
+ public static readonly Style SubtitleStyle = new Style(typeof(Label)) { BaseResourceKey = SubtitleStyleKey };
+
+ public static readonly Style BodyStyle = new Style(typeof(Label)) { BaseResourceKey = BodyStyleKey };
+
+ public static readonly Style ListItemTextStyle = new Style(typeof(Label)) { BaseResourceKey = ListItemTextStyleKey };
+
+ public static readonly Style ListItemDetailTextStyle = new Style(typeof(Label)) { BaseResourceKey = ListItemDetailTextStyleKey };
+
+ public static readonly Style CaptionStyle = new Style(typeof(Label)) { BaseResourceKey = CaptionStyleKey };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/DeviceInfo.cs b/Xamarin.Forms.Core/DeviceInfo.cs
new file mode 100644
index 00000000..dc83075a
--- /dev/null
+++ b/Xamarin.Forms.Core/DeviceInfo.cs
@@ -0,0 +1,51 @@
+using System;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+namespace Xamarin.Forms
+{
+ internal abstract class DeviceInfo : INotifyPropertyChanged, IDisposable
+ {
+ DeviceOrientation _currentOrientation;
+ bool _disposed;
+
+ public DeviceOrientation CurrentOrientation
+ {
+ get { return _currentOrientation; }
+ internal set
+ {
+ if (Equals(_currentOrientation, value))
+ return;
+ _currentOrientation = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public abstract Size PixelScreenSize { get; }
+
+ public abstract Size ScaledScreenSize { get; }
+
+ public abstract double ScalingFactor { get; }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_disposed)
+ return;
+ _disposed = true;
+ }
+
+ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/DeviceOrientation.cs b/Xamarin.Forms.Core/DeviceOrientation.cs
new file mode 100644
index 00000000..53a03f2d
--- /dev/null
+++ b/Xamarin.Forms.Core/DeviceOrientation.cs
@@ -0,0 +1,13 @@
+namespace Xamarin.Forms
+{
+ internal enum DeviceOrientation
+ {
+ Portrait,
+ Landscape,
+ PortraitUp,
+ PortraitDown,
+ LandscapeLeft,
+ LandscapeRight,
+ Other
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/DeviceOrientationExtensions.cs b/Xamarin.Forms.Core/DeviceOrientationExtensions.cs
new file mode 100644
index 00000000..8dbaaa82
--- /dev/null
+++ b/Xamarin.Forms.Core/DeviceOrientationExtensions.cs
@@ -0,0 +1,15 @@
+namespace Xamarin.Forms
+{
+ internal static class DeviceOrientationExtensions
+ {
+ public static bool IsLandscape(this DeviceOrientation orientation)
+ {
+ return orientation == DeviceOrientation.Landscape || orientation == DeviceOrientation.LandscapeLeft || orientation == DeviceOrientation.LandscapeRight;
+ }
+
+ public static bool IsPortrait(this DeviceOrientation orientation)
+ {
+ return orientation == DeviceOrientation.Portrait || orientation == DeviceOrientation.PortraitDown || orientation == DeviceOrientation.PortraitUp;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Easing.cs b/Xamarin.Forms.Core/Easing.cs
new file mode 100644
index 00000000..8d64e255
--- /dev/null
+++ b/Xamarin.Forms.Core/Easing.cs
@@ -0,0 +1,98 @@
+//
+// Tweener.cs
+//
+// Author:
+// Jason Smith <jason.smith@xamarin.com>
+//
+// Copyright (c) 2012 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace Xamarin.Forms
+{
+ public class Easing
+ {
+ public static readonly Easing Linear = new Easing(x => x);
+
+ public static readonly Easing SinOut = new Easing(x => Math.Sin(x * Math.PI * 0.5f));
+ public static readonly Easing SinIn = new Easing(x => 1.0f - Math.Cos(x * Math.PI * 0.5f));
+ public static readonly Easing SinInOut = new Easing(x => -Math.Cos(Math.PI * x) / 2.0f + 0.5f);
+
+ public static readonly Easing CubicIn = new Easing(x => x * x * x);
+ public static readonly Easing CubicOut = new Easing(x => Math.Pow(x - 1.0f, 3.0f) + 1.0f);
+
+ public static readonly Easing CubicInOut = new Easing(x => x < 0.5f ? Math.Pow(x * 2.0f, 3.0f) / 2.0f : (Math.Pow((x - 1) * 2.0f, 3.0f) + 2.0f) / 2.0f);
+
+ public static readonly Easing BounceOut;
+ public static readonly Easing BounceIn;
+
+ public static readonly Easing SpringIn = new Easing(x => x * x * ((1.70158f + 1) * x - 1.70158f));
+ public static readonly Easing SpringOut = new Easing(x => (x - 1) * (x - 1) * ((1.70158f + 1) * (x - 1) + 1.70158f) + 1);
+
+ readonly Func<double, double> _easingFunc;
+
+ static Easing()
+ {
+ BounceOut = new Easing(p =>
+ {
+ if (p < 1 / 2.75f)
+ {
+ return 7.5625f * p * p;
+ }
+ if (p < 2 / 2.75f)
+ {
+ p -= 1.5f / 2.75f;
+
+ return 7.5625f * p * p + .75f;
+ }
+ if (p < 2.5f / 2.75f)
+ {
+ p -= 2.25f / 2.75f;
+
+ return 7.5625f * p * p + .9375f;
+ }
+ p -= 2.625f / 2.75f;
+
+ return 7.5625f * p * p + .984375f;
+ });
+
+ BounceIn = new Easing(p => 1.0f - BounceOut.Ease(1 - p));
+ }
+
+ public Easing(Func<double, double> easingFunc)
+ {
+ if (easingFunc == null)
+ throw new ArgumentNullException("easingFunc");
+
+ _easingFunc = easingFunc;
+ }
+
+ public double Ease(double v)
+ {
+ return _easingFunc(v);
+ }
+
+ public static implicit operator Easing(Func<double, double> func)
+ {
+ return new Easing(func);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Editor.cs b/Xamarin.Forms.Core/Editor.cs
new file mode 100644
index 00000000..949c0865
--- /dev/null
+++ b/Xamarin.Forms.Core/Editor.cs
@@ -0,0 +1,67 @@
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_EditorRenderer))]
+ public class Editor : InputView, IFontElement
+ {
+ public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(Editor), null, BindingMode.TwoWay, propertyChanged: (bindable, oldValue, newValue) =>
+ {
+ var editor = (Editor)bindable;
+ if (editor.TextChanged != null)
+ editor.TextChanged(editor, new TextChangedEventArgs((string)oldValue, (string)newValue));
+ });
+
+ public static readonly BindableProperty FontFamilyProperty = BindableProperty.Create("FontFamily", typeof(string), typeof(Editor), default(string));
+
+ public static readonly BindableProperty FontSizeProperty = BindableProperty.Create("FontSize", typeof(double), typeof(Editor), -1.0,
+ defaultValueCreator: bindable => Device.GetNamedSize(NamedSize.Default, (Editor)bindable));
+
+ public static readonly BindableProperty FontAttributesProperty = BindableProperty.Create("FontAttributes", typeof(FontAttributes), typeof(Editor), FontAttributes.None);
+
+ public static readonly BindableProperty TextColorProperty = BindableProperty.Create("TextColor", typeof(Color), typeof(Editor), Color.Default);
+
+ public string Text
+ {
+ get { return (string)GetValue(TextProperty); }
+ set { SetValue(TextProperty, value); }
+ }
+
+ public Color TextColor
+ {
+ get { return (Color)GetValue(TextColorProperty); }
+ set { SetValue(TextColorProperty, value); }
+ }
+
+ public FontAttributes FontAttributes
+ {
+ get { return (FontAttributes)GetValue(FontAttributesProperty); }
+ set { SetValue(FontAttributesProperty, value); }
+ }
+
+ public string FontFamily
+ {
+ get { return (string)GetValue(FontFamilyProperty); }
+ set { SetValue(FontFamilyProperty, value); }
+ }
+
+ [TypeConverter(typeof(FontSizeConverter))]
+ public double FontSize
+ {
+ get { return (double)GetValue(FontSizeProperty); }
+ set { SetValue(FontSizeProperty, value); }
+ }
+
+ public event EventHandler Completed;
+
+ public event EventHandler<TextChangedEventArgs> TextChanged;
+
+ internal void SendCompleted()
+ {
+ EventHandler handler = Completed;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Effect.cs b/Xamarin.Forms.Core/Effect.cs
new file mode 100644
index 00000000..9e269118
--- /dev/null
+++ b/Xamarin.Forms.Core/Effect.cs
@@ -0,0 +1,70 @@
+using System;
+using System.ComponentModel;
+
+namespace Xamarin.Forms
+{
+ public abstract class Effect
+ {
+ internal Effect()
+ {
+ }
+
+ public Element Element { get; internal set; }
+
+ public bool IsAttached { get; private set; }
+
+ public string ResolveId { get; internal set; }
+
+ #region Statics
+
+ public static Effect Resolve(string name)
+ {
+ Type effectType;
+ Effect result = null;
+ if (Registrar.Effects.TryGetValue(name, out effectType))
+ {
+ result = (Effect)Activator.CreateInstance(effectType);
+ }
+
+ if (result == null)
+ result = new NullEffect();
+ result.ResolveId = name;
+ return result;
+ }
+
+ #endregion
+
+ // Received after Control/Container/Element made valid
+ protected abstract void OnAttached();
+
+ // Received after Control/Container made invalid
+ protected abstract void OnDetached();
+
+ internal virtual void ClearEffect()
+ {
+ if (IsAttached)
+ SendDetached();
+ Element = null;
+ }
+
+ internal virtual void SendAttached()
+ {
+ if (IsAttached)
+ return;
+ OnAttached();
+ IsAttached = true;
+ }
+
+ internal virtual void SendDetached()
+ {
+ if (!IsAttached)
+ return;
+ OnDetached();
+ IsAttached = false;
+ }
+
+ internal virtual void SendOnElementPropertyChanged(PropertyChangedEventArgs args)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Element.cs b/Xamarin.Forms.Core/Element.cs
new file mode 100644
index 00000000..a85bb3fb
--- /dev/null
+++ b/Xamarin.Forms.Core/Element.cs
@@ -0,0 +1,584 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using System.Xml;
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms
+{
+ public abstract class Element : BindableObject, IElement, INameScope, IElementController
+ {
+ internal static readonly ReadOnlyCollection<Element> EmptyChildren = new ReadOnlyCollection<Element>(new Element[0]);
+
+ public static readonly BindableProperty ClassIdProperty = BindableProperty.Create("ClassId", typeof(string), typeof(View), null);
+
+ string _automationId;
+
+ List<Action<object, ResourcesChangedEventArgs>> _changeHandlers;
+
+ List<KeyValuePair<string, BindableProperty>> _dynamicResources;
+
+ IEffectControlProvider _effectControlProvider;
+
+ TrackableCollection<Effect> _effects;
+
+ Guid? _id;
+
+ Element _parentOverride;
+
+ IPlatform _platform;
+
+ string _styleId;
+
+ public string AutomationId
+ {
+ get { return _automationId; }
+ set
+ {
+ if (_automationId != null)
+ throw new InvalidOperationException("AutomationId may only be set one time");
+ _automationId = value;
+ }
+ }
+
+ public string ClassId
+ {
+ get { return (string)GetValue(ClassIdProperty); }
+ set { SetValue(ClassIdProperty, value); }
+ }
+
+ public IList<Effect> Effects
+ {
+ get
+ {
+ if (_effects == null)
+ {
+ _effects = new TrackableCollection<Effect>();
+ _effects.CollectionChanged += EffectsOnCollectionChanged;
+ _effects.Clearing += EffectsOnClearing;
+ }
+ return _effects;
+ }
+ }
+
+ public Guid Id
+ {
+ get
+ {
+ if (!_id.HasValue)
+ _id = Guid.NewGuid();
+ return _id.Value;
+ }
+ }
+
+ [Obsolete("Use Parent")]
+ public VisualElement ParentView
+ {
+ get
+ {
+ Element parent = Parent;
+ while (parent != null)
+ {
+ var parentView = parent as VisualElement;
+ if (parentView != null)
+ return parentView;
+ parent = parent.RealParent;
+ }
+ return null;
+ }
+ }
+
+ public string StyleId
+ {
+ get { return _styleId; }
+ set
+ {
+ if (_styleId == value)
+ return;
+
+ OnPropertyChanging();
+ _styleId = value;
+ OnPropertyChanged();
+ }
+ }
+
+ internal virtual ReadOnlyCollection<Element> LogicalChildren
+ {
+ get { return EmptyChildren; }
+ }
+
+ internal bool Owned { get; set; }
+
+ internal Element ParentOverride
+ {
+ get { return _parentOverride; }
+ set
+ {
+ if (_parentOverride == value)
+ return;
+
+ bool emitChange = Parent != value;
+
+ if (emitChange)
+ OnPropertyChanging(nameof(Parent));
+
+ _parentOverride = value;
+
+ if (emitChange)
+ OnPropertyChanged(nameof(Parent));
+ }
+ }
+
+ internal IPlatform Platform
+ {
+ get
+ {
+ if (_platform == null && RealParent != null)
+ return RealParent.Platform;
+ return _platform;
+ }
+ set
+ {
+ if (_platform == value)
+ return;
+ _platform = value;
+ if (PlatformSet != null)
+ PlatformSet(this, EventArgs.Empty);
+ foreach (Element descendant in Descendants())
+ {
+ descendant._platform = _platform;
+ if (descendant.PlatformSet != null)
+ descendant.PlatformSet(this, EventArgs.Empty);
+ }
+ }
+ }
+
+ // you're not my real dad
+ internal Element RealParent { get; private set; }
+
+ List<KeyValuePair<string, BindableProperty>> DynamicResources
+ {
+ get { return _dynamicResources ?? (_dynamicResources = new List<KeyValuePair<string, BindableProperty>>(4)); }
+ }
+
+ void IElement.AddResourcesChangedListener(Action<object, ResourcesChangedEventArgs> onchanged)
+ {
+ _changeHandlers = _changeHandlers ?? new List<Action<object, ResourcesChangedEventArgs>>(2);
+ _changeHandlers.Add(onchanged);
+ }
+
+ public Element Parent
+ {
+ get { return _parentOverride ?? RealParent; }
+ set
+ {
+ if (RealParent == value)
+ return;
+
+ OnPropertyChanging();
+
+ if (RealParent != null)
+ ((IElement)RealParent).RemoveResourcesChangedListener(OnParentResourcesChanged);
+ RealParent = value;
+ if (RealParent != null)
+ {
+ OnParentResourcesChanged(RealParent.GetMergedResources());
+ ((IElement)RealParent).AddResourcesChangedListener(OnParentResourcesChanged);
+ }
+
+ object context = value != null ? value.BindingContext : null;
+ if (value != null)
+ {
+ value.SetChildInheritedBindingContext(this, context);
+ }
+ else
+ {
+ SetInheritedBindingContext(this, null);
+ }
+
+ OnParentSet();
+
+ if (RealParent != null)
+ {
+ IPlatform platform = RealParent.Platform;
+ if (platform != null)
+ Platform = platform;
+ }
+
+ OnPropertyChanged();
+ }
+ }
+
+ void IElement.RemoveResourcesChangedListener(Action<object, ResourcesChangedEventArgs> onchanged)
+ {
+ if (_changeHandlers == null)
+ return;
+ _changeHandlers.Remove(onchanged);
+ }
+
+ IEffectControlProvider IElementController.EffectControlProvider
+ {
+ get { return _effectControlProvider; }
+ set
+ {
+ if (_effectControlProvider == value)
+ return;
+ if (_effectControlProvider != null && _effects != null)
+ {
+ foreach (Effect effect in _effects)
+ effect?.SendDetached();
+ }
+ _effectControlProvider = value;
+ if (_effectControlProvider != null && _effects != null)
+ {
+ foreach (Effect effect in _effects)
+ {
+ if (effect != null)
+ AttachEffect(effect);
+ }
+ }
+ }
+ }
+
+ void IElementController.SetValueFromRenderer(BindableProperty property, object value)
+ {
+ SetValueCore(property, value);
+ }
+
+ void IElementController.SetValueFromRenderer(BindablePropertyKey property, object value)
+ {
+ SetValueCore(property, value);
+ }
+
+ object INameScope.FindByName(string name)
+ {
+ INameScope namescope = GetNameScope();
+ if (namescope == null)
+ throw new InvalidOperationException("this element is not in a namescope");
+ return namescope.FindByName(name);
+ }
+
+ void INameScope.RegisterName(string name, object scopedElement)
+ {
+ INameScope namescope = GetNameScope();
+ if (namescope == null)
+ throw new InvalidOperationException("this element is not in a namescope");
+ namescope.RegisterName(name, scopedElement);
+ }
+
+ void INameScope.RegisterName(string name, object scopedElement, IXmlLineInfo xmlLineInfo)
+ {
+ INameScope namescope = GetNameScope();
+ if (namescope == null)
+ throw new InvalidOperationException("this element is not in a namescope");
+ namescope.RegisterName(name, scopedElement, xmlLineInfo);
+ }
+
+ void INameScope.UnregisterName(string name)
+ {
+ INameScope namescope = GetNameScope();
+ if (namescope == null)
+ throw new InvalidOperationException("this element is not in a namescope");
+ namescope.UnregisterName(name);
+ }
+
+ public event EventHandler<ElementEventArgs> ChildAdded;
+
+ public event EventHandler<ElementEventArgs> ChildRemoved;
+
+ public event EventHandler<ElementEventArgs> DescendantAdded;
+
+ public event EventHandler<ElementEventArgs> DescendantRemoved;
+
+ public new void RemoveDynamicResource(BindableProperty property)
+ {
+ base.RemoveDynamicResource(property);
+ }
+
+ public new void SetDynamicResource(BindableProperty property, string key)
+ {
+ base.SetDynamicResource(property, key);
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ var gotBindingContext = false;
+ object bc = null;
+
+ for (var index = 0; index < LogicalChildren.Count; index++)
+ {
+ Element child = LogicalChildren[index];
+
+ if (!gotBindingContext)
+ {
+ bc = BindingContext;
+ gotBindingContext = true;
+ }
+
+ SetChildInheritedBindingContext(child, bc);
+ }
+
+ base.OnBindingContextChanged();
+ }
+
+ protected virtual void OnChildAdded(Element child)
+ {
+ child.Parent = this;
+ if (Platform != null)
+ child.Platform = Platform;
+
+ child.ApplyBindings();
+
+ if (ChildAdded != null)
+ ChildAdded(this, new ElementEventArgs(child));
+
+ OnDescendantAdded(child);
+ foreach (Element element in child.Descendants())
+ OnDescendantAdded(element);
+ }
+
+ protected virtual void OnChildRemoved(Element child)
+ {
+ child.Parent = null;
+
+ if (ChildRemoved != null)
+ ChildRemoved(child, new ElementEventArgs(child));
+
+ OnDescendantRemoved(child);
+ foreach (Element element in child.Descendants())
+ OnDescendantRemoved(element);
+ }
+
+ protected virtual void OnParentSet()
+ {
+ ParentSet?.Invoke(this, EventArgs.Empty);
+ }
+
+ protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ base.OnPropertyChanged(propertyName);
+
+ if (_effects == null || _effects.Count == 0)
+ return;
+
+ var args = new PropertyChangedEventArgs(propertyName);
+ foreach (Effect effect in _effects)
+ {
+ effect?.SendOnElementPropertyChanged(args);
+ }
+ }
+
+ internal IEnumerable<Element> Descendants()
+ {
+ var queue = new Queue<Element>(16);
+ queue.Enqueue(this);
+
+ while (queue.Count > 0)
+ {
+ ReadOnlyCollection<Element> children = queue.Dequeue().LogicalChildren;
+ for (var i = 0; i < children.Count; i++)
+ {
+ Element child = children[i];
+ yield return child;
+ queue.Enqueue(child);
+ }
+ }
+ }
+
+ internal void OnParentResourcesChanged(object sender, ResourcesChangedEventArgs e)
+ {
+ OnParentResourcesChanged(e.Values);
+ }
+
+ internal virtual void OnParentResourcesChanged(IEnumerable<KeyValuePair<string, object>> values)
+ {
+ OnResourcesChanged(values);
+ }
+
+ internal override void OnRemoveDynamicResource(BindableProperty property)
+ {
+ DynamicResources.RemoveAll(kvp => kvp.Value == property);
+ if (DynamicResources.Count == 0)
+ _dynamicResources = null;
+ base.OnRemoveDynamicResource(property);
+ }
+
+ internal void OnResourcesChanged(object sender, ResourcesChangedEventArgs e)
+ {
+ OnResourcesChanged(e.Values);
+ }
+
+ internal void OnResourcesChanged(IEnumerable<KeyValuePair<string, object>> values)
+ {
+ if (values == null)
+ return;
+ if (_changeHandlers != null)
+ foreach (Action<object, ResourcesChangedEventArgs> handler in _changeHandlers)
+ handler(this, new ResourcesChangedEventArgs(values));
+ if (_dynamicResources == null)
+ return;
+ foreach (KeyValuePair<string, object> value in values)
+ {
+ List<BindableProperty> changedResources = null;
+ foreach (KeyValuePair<string, BindableProperty> dynR in DynamicResources)
+ {
+ if (dynR.Key != value.Key)
+ continue;
+ changedResources = changedResources ?? new List<BindableProperty>();
+ changedResources.Add(dynR.Value);
+ }
+ if (changedResources == null)
+ continue;
+ foreach (BindableProperty changedResource in changedResources)
+ OnResourceChanged(changedResource, value.Value);
+ }
+ }
+
+ internal override void OnSetDynamicResource(BindableProperty property, string key)
+ {
+ base.OnSetDynamicResource(property, key);
+ DynamicResources.Add(new KeyValuePair<string, BindableProperty>(key, property));
+ object value;
+ if (this.TryGetResource(key, out value))
+ OnResourceChanged(property, value);
+ }
+
+ internal event EventHandler ParentSet;
+
+ internal event EventHandler PlatformSet;
+
+ internal virtual void SetChildInheritedBindingContext(Element child, object context)
+ {
+ SetInheritedBindingContext(child, context);
+ }
+
+ internal IEnumerable<Element> VisibleDescendants()
+ {
+ var queue = new Queue<Element>(16);
+ queue.Enqueue(this);
+
+ while (queue.Count > 0)
+ {
+ ReadOnlyCollection<Element> children = queue.Dequeue().LogicalChildren;
+ for (var i = 0; i < children.Count; i++)
+ {
+ var child = children[i] as VisualElement;
+ if (child == null || !child.IsVisible)
+ continue;
+ yield return child;
+ queue.Enqueue(child);
+ }
+ }
+ }
+
+ void AttachEffect(Effect effect)
+ {
+ if (_effectControlProvider == null)
+ return;
+ if (effect.IsAttached)
+ throw new InvalidOperationException("Cannot attach Effect to multiple sources");
+
+ Effect effectToRegister = effect;
+ if (effect is RoutingEffect)
+ effectToRegister = ((RoutingEffect)effect).Inner;
+ _effectControlProvider.RegisterEffect(effectToRegister);
+ effectToRegister.Element = this;
+ effect.SendAttached();
+ }
+
+ void EffectsOnClearing(object sender, EventArgs eventArgs)
+ {
+ foreach (Effect effect in _effects)
+ {
+ effect.ClearEffect();
+ }
+ }
+
+ void EffectsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ foreach (Effect effect in e.NewItems)
+ {
+ AttachEffect(effect);
+ }
+ break;
+ case NotifyCollectionChangedAction.Move:
+ break;
+ case NotifyCollectionChangedAction.Remove:
+ foreach (Effect effect in e.OldItems)
+ {
+ effect.ClearEffect();
+ }
+ break;
+ case NotifyCollectionChangedAction.Replace:
+ foreach (Effect effect in e.NewItems)
+ {
+ AttachEffect(effect);
+ }
+ foreach (Effect effect in e.OldItems)
+ {
+ effect.ClearEffect();
+ }
+ break;
+ case NotifyCollectionChangedAction.Reset:
+ if (e.NewItems != null)
+ {
+ foreach (Effect effect in e.NewItems)
+ {
+ AttachEffect(effect);
+ }
+ }
+ if (e.OldItems != null)
+ {
+ foreach (Effect effect in e.OldItems)
+ {
+ effect.ClearEffect();
+ }
+ }
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ INameScope GetNameScope()
+ {
+ INameScope namescope = NameScope.GetNameScope(this);
+ Element p = RealParent;
+ while (namescope == null && p != null)
+ {
+ namescope = NameScope.GetNameScope(p);
+ p = p.RealParent;
+ }
+ return namescope;
+ }
+
+ void OnDescendantAdded(Element child)
+ {
+ if (DescendantAdded != null)
+ DescendantAdded(this, new ElementEventArgs(child));
+
+ if (RealParent != null)
+ RealParent.OnDescendantAdded(child);
+ }
+
+ void OnDescendantRemoved(Element child)
+ {
+ if (DescendantRemoved != null)
+ DescendantRemoved(this, new ElementEventArgs(child));
+
+ if (RealParent != null)
+ RealParent.OnDescendantRemoved(child);
+ }
+
+ void OnResourceChanged(BindableProperty property, object value)
+ {
+ SetValueCore(property, value, SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearTwoWayBindings);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ElementCollection.cs b/Xamarin.Forms.Core/ElementCollection.cs
new file mode 100644
index 00000000..37520ab6
--- /dev/null
+++ b/Xamarin.Forms.Core/ElementCollection.cs
@@ -0,0 +1,11 @@
+using System.Collections.ObjectModel;
+
+namespace Xamarin.Forms
+{
+ internal class ElementCollection<T> : ObservableWrapper<Element, T> where T : Element
+ {
+ public ElementCollection(ObservableCollection<Element> list) : base(list)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ElementEventArgs.cs b/Xamarin.Forms.Core/ElementEventArgs.cs
new file mode 100644
index 00000000..34af4e0e
--- /dev/null
+++ b/Xamarin.Forms.Core/ElementEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class ElementEventArgs : EventArgs
+ {
+ public ElementEventArgs(Element element)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ Element = element;
+ }
+
+ public Element Element { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ElementTemplate.cs b/Xamarin.Forms.Core/ElementTemplate.cs
new file mode 100644
index 00000000..016dee7e
--- /dev/null
+++ b/Xamarin.Forms.Core/ElementTemplate.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms
+{
+#pragma warning disable 612
+ public class ElementTemplate : IElement, IDataTemplate
+#pragma warning restore 612
+ {
+ List<Action<object, ResourcesChangedEventArgs>> _changeHandlers;
+ Element _parent;
+
+ internal ElementTemplate()
+ {
+ }
+
+ internal ElementTemplate(Type type) : this()
+ {
+ if (type == null)
+ throw new ArgumentNullException("type");
+
+ LoadTemplate = () => Activator.CreateInstance(type);
+ }
+
+ internal ElementTemplate(Func<object> loadTemplate) : this()
+ {
+ if (loadTemplate == null)
+ throw new ArgumentNullException("loadTemplate");
+
+ LoadTemplate = loadTemplate;
+ }
+
+ Func<object> LoadTemplate { get; set; }
+#pragma warning disable 0612
+ Func<object> IDataTemplate.LoadTemplate
+ {
+#pragma warning restore 0612
+ get { return LoadTemplate; }
+ set { LoadTemplate = value; }
+ }
+
+ void IElement.AddResourcesChangedListener(Action<object, ResourcesChangedEventArgs> onchanged)
+ {
+ _changeHandlers = _changeHandlers ?? new List<Action<object, ResourcesChangedEventArgs>>(1);
+ _changeHandlers.Add(onchanged);
+ }
+
+ Element IElement.Parent
+ {
+ get { return _parent; }
+ set
+ {
+ if (_parent == value)
+ return;
+ if (_parent != null)
+ ((IElement)_parent).RemoveResourcesChangedListener(OnResourcesChanged);
+ _parent = value;
+ if (_parent != null)
+ ((IElement)_parent).AddResourcesChangedListener(OnResourcesChanged);
+ }
+ }
+
+ void IElement.RemoveResourcesChangedListener(Action<object, ResourcesChangedEventArgs> onchanged)
+ {
+ if (_changeHandlers == null)
+ return;
+ _changeHandlers.Remove(onchanged);
+ }
+
+ public object CreateContent()
+ {
+ if (LoadTemplate == null)
+ throw new InvalidOperationException("LoadTemplate should not be null");
+ if (this is DataTemplateSelector)
+ throw new InvalidOperationException("Cannot call CreateContent directly on a DataTemplateSelector");
+
+ object item = LoadTemplate();
+ SetupContent(item);
+
+ return item;
+ }
+
+ internal virtual void SetupContent(object item)
+ {
+ }
+
+ void OnResourcesChanged(object sender, ResourcesChangedEventArgs e)
+ {
+ if (_changeHandlers == null)
+ return;
+ foreach (Action<object, ResourcesChangedEventArgs> handler in _changeHandlers)
+ handler(this, e);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/EmailKeyboard.cs b/Xamarin.Forms.Core/EmailKeyboard.cs
new file mode 100644
index 00000000..1911fd3c
--- /dev/null
+++ b/Xamarin.Forms.Core/EmailKeyboard.cs
@@ -0,0 +1,6 @@
+namespace Xamarin.Forms
+{
+ internal sealed class EmailKeyboard : Keyboard
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Entry.cs b/Xamarin.Forms.Core/Entry.cs
new file mode 100644
index 00000000..ef10e963
--- /dev/null
+++ b/Xamarin.Forms.Core/Entry.cs
@@ -0,0 +1,99 @@
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_EntryRenderer))]
+ public class Entry : InputView, IFontElement
+ {
+ public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create("Placeholder", typeof(string), typeof(Entry), default(string));
+
+ public static readonly BindableProperty IsPasswordProperty = BindableProperty.Create("IsPassword", typeof(bool), typeof(Entry), default(bool));
+
+ public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(Entry), null, BindingMode.TwoWay, propertyChanged: OnTextChanged);
+
+ public static readonly BindableProperty TextColorProperty = BindableProperty.Create("TextColor", typeof(Color), typeof(Entry), Color.Default);
+
+ public static readonly BindableProperty HorizontalTextAlignmentProperty = BindableProperty.Create("HorizontalTextAlignment", typeof(TextAlignment), typeof(Entry), TextAlignment.Start);
+
+ public static readonly BindableProperty PlaceholderColorProperty = BindableProperty.Create("PlaceholderColor", typeof(Color), typeof(Entry), Color.Default);
+
+ public static readonly BindableProperty FontFamilyProperty = BindableProperty.Create("FontFamily", typeof(string), typeof(Entry), default(string));
+
+ public static readonly BindableProperty FontSizeProperty = BindableProperty.Create("FontSize", typeof(double), typeof(Entry), -1.0,
+ defaultValueCreator: bindable => Device.GetNamedSize(NamedSize.Default, (Entry)bindable));
+
+ public static readonly BindableProperty FontAttributesProperty = BindableProperty.Create("FontAttributes", typeof(FontAttributes), typeof(Entry), FontAttributes.None);
+
+ public TextAlignment HorizontalTextAlignment
+ {
+ get { return (TextAlignment)GetValue(HorizontalTextAlignmentProperty); }
+ set { SetValue(HorizontalTextAlignmentProperty, value); }
+ }
+
+ public bool IsPassword
+ {
+ get { return (bool)GetValue(IsPasswordProperty); }
+ set { SetValue(IsPasswordProperty, value); }
+ }
+
+ public string Placeholder
+ {
+ get { return (string)GetValue(PlaceholderProperty); }
+ set { SetValue(PlaceholderProperty, value); }
+ }
+
+ public Color PlaceholderColor
+ {
+ get { return (Color)GetValue(PlaceholderColorProperty); }
+ set { SetValue(PlaceholderColorProperty, value); }
+ }
+
+ public string Text
+ {
+ get { return (string)GetValue(TextProperty); }
+ set { SetValue(TextProperty, value); }
+ }
+
+ public Color TextColor
+ {
+ get { return (Color)GetValue(TextColorProperty); }
+ set { SetValue(TextColorProperty, value); }
+ }
+
+ public FontAttributes FontAttributes
+ {
+ get { return (FontAttributes)GetValue(FontAttributesProperty); }
+ set { SetValue(FontAttributesProperty, value); }
+ }
+
+ public string FontFamily
+ {
+ get { return (string)GetValue(FontFamilyProperty); }
+ set { SetValue(FontFamilyProperty, value); }
+ }
+
+ [TypeConverter(typeof(FontSizeConverter))]
+ public double FontSize
+ {
+ get { return (double)GetValue(FontSizeProperty); }
+ set { SetValue(FontSizeProperty, value); }
+ }
+
+ public event EventHandler Completed;
+
+ public event EventHandler<TextChangedEventArgs> TextChanged;
+
+ internal void SendCompleted()
+ {
+ Completed?.Invoke(this, EventArgs.Empty);
+ }
+
+ static void OnTextChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var entry = (Entry)bindable;
+
+ entry.TextChanged?.Invoke(entry, new TextChangedEventArgs((string)oldValue, (string)newValue));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/EnumerableExtensions.cs b/Xamarin.Forms.Core/EnumerableExtensions.cs
new file mode 100644
index 00000000..066e7e91
--- /dev/null
+++ b/Xamarin.Forms.Core/EnumerableExtensions.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ internal static class EnumerableExtensions
+ {
+ public static IEnumerable<T> GetGesturesFor<T>(this IEnumerable<IGestureRecognizer> gestures, Func<T, bool> predicate = null) where T : GestureRecognizer
+ {
+ if (gestures == null)
+ yield break;
+
+ if (predicate == null)
+ predicate = x => true;
+
+ foreach (IGestureRecognizer item in gestures)
+ {
+ var gesture = item as T;
+ if (gesture != null && predicate(gesture))
+ {
+ yield return gesture;
+ }
+ }
+ }
+
+ internal static IEnumerable<T> Append<T>(this IEnumerable<T> enumerable, T item)
+ {
+ foreach (T x in enumerable)
+ yield return x;
+
+ yield return item;
+ }
+
+ internal static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
+ {
+ foreach (T item in enumeration)
+ {
+ action(item);
+ }
+ }
+
+ internal static int IndexOf<T>(this IEnumerable<T> enumerable, T item)
+ {
+ if (enumerable == null)
+ throw new ArgumentNullException("enumerable");
+
+ var i = 0;
+ foreach (T element in enumerable)
+ {
+ if (Equals(element, item))
+ return i;
+
+ i++;
+ }
+
+ return -1;
+ }
+
+ internal static int IndexOf<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
+ {
+ var i = 0;
+ foreach (T element in enumerable)
+ {
+ if (predicate(element))
+ return i;
+
+ i++;
+ }
+
+ return -1;
+ }
+
+ internal static IEnumerable<T> Prepend<T>(this IEnumerable<T> enumerable, T item)
+ {
+ yield return item;
+
+ foreach (T x in enumerable)
+ yield return x;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/EventArg.cs b/Xamarin.Forms.Core/EventArg.cs
new file mode 100644
index 00000000..9b9ea0a1
--- /dev/null
+++ b/Xamarin.Forms.Core/EventArg.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ internal class EventArg<T> : EventArgs
+ {
+ // Property variable
+
+ // Constructor
+ public EventArg(T data)
+ {
+ Data = data;
+ }
+
+ // Property for EventArgs argument
+ public T Data { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ExportEffectAttribute.cs b/Xamarin.Forms.Core/ExportEffectAttribute.cs
new file mode 100644
index 00000000..35869570
--- /dev/null
+++ b/Xamarin.Forms.Core/ExportEffectAttribute.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public class ExportEffectAttribute : Attribute
+ {
+ public ExportEffectAttribute(Type effectType, string uniqueName)
+ {
+ if (uniqueName.Contains("."))
+ throw new ArgumentException("uniqueName must not contain a .");
+ Type = effectType;
+ Id = uniqueName;
+ }
+
+ internal string Id { get; private set; }
+
+ internal Type Type { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ExpressionSearch.cs b/Xamarin.Forms.Core/ExpressionSearch.cs
new file mode 100644
index 00000000..fbbe80a8
--- /dev/null
+++ b/Xamarin.Forms.Core/ExpressionSearch.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms
+{
+ internal abstract class ExpressionSearch
+ {
+ internal static IExpressionSearch Default { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/FileAccess.cs b/Xamarin.Forms.Core/FileAccess.cs
new file mode 100644
index 00000000..3636b733
--- /dev/null
+++ b/Xamarin.Forms.Core/FileAccess.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Forms
+{
+ internal enum FileAccess
+ {
+ Read = 0x00000001,
+ Write = 0x00000002,
+ ReadWrite = Read | Write
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/FileImageSource.cs b/Xamarin.Forms.Core/FileImageSource.cs
new file mode 100644
index 00000000..9e1d1e73
--- /dev/null
+++ b/Xamarin.Forms.Core/FileImageSource.cs
@@ -0,0 +1,38 @@
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ [TypeConverter(typeof(FileImageSourceConverter))]
+ public sealed class FileImageSource : ImageSource
+ {
+ public static readonly BindableProperty FileProperty = BindableProperty.Create("File", typeof(string), typeof(FileImageSource), default(string));
+
+ public string File
+ {
+ get { return (string)GetValue(FileProperty); }
+ set { SetValue(FileProperty, value); }
+ }
+
+ public override Task<bool> Cancel()
+ {
+ return Task.FromResult(false);
+ }
+
+ public static implicit operator FileImageSource(string file)
+ {
+ return (FileImageSource)FromFile(file);
+ }
+
+ public static implicit operator string(FileImageSource file)
+ {
+ return file != null ? file.File : null;
+ }
+
+ protected override void OnPropertyChanged(string propertyName = null)
+ {
+ if (propertyName == FileProperty.PropertyName)
+ OnSourceChanged();
+ base.OnPropertyChanged(propertyName);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/FileImageSourceConverter.cs b/Xamarin.Forms.Core/FileImageSourceConverter.cs
new file mode 100644
index 00000000..25a0e22e
--- /dev/null
+++ b/Xamarin.Forms.Core/FileImageSourceConverter.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public sealed class FileImageSourceConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString(string value)
+ {
+ if (value != null)
+ return (FileImageSource)ImageSource.FromFile(value);
+
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(FileImageSource)));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/FileMode.cs b/Xamarin.Forms.Core/FileMode.cs
new file mode 100644
index 00000000..31369872
--- /dev/null
+++ b/Xamarin.Forms.Core/FileMode.cs
@@ -0,0 +1,12 @@
+namespace Xamarin.Forms
+{
+ internal enum FileMode
+ {
+ CreateNew = 1,
+ Create = 2,
+ Open = 3,
+ OpenOrCreate = 4,
+ Truncate = 5,
+ Append = 6
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/FileShare.cs b/Xamarin.Forms.Core/FileShare.cs
new file mode 100644
index 00000000..bf9fc717
--- /dev/null
+++ b/Xamarin.Forms.Core/FileShare.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [Flags]
+ internal enum FileShare
+ {
+ None = 0,
+ Read = 1,
+ Write = 2,
+ ReadWrite = 3,
+ Delete = 4,
+ Inheritable = 16
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/FocusEventArgs.cs b/Xamarin.Forms.Core/FocusEventArgs.cs
new file mode 100644
index 00000000..304fd823
--- /dev/null
+++ b/Xamarin.Forms.Core/FocusEventArgs.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class FocusEventArgs : EventArgs
+ {
+ public FocusEventArgs(VisualElement visualElement, bool isFocused)
+ {
+ if (visualElement == null)
+ throw new ArgumentNullException("visualElement");
+
+ VisualElement = visualElement;
+ IsFocused = isFocused;
+ }
+
+ public bool IsFocused { get; private set; }
+
+ public VisualElement VisualElement { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Font.cs b/Xamarin.Forms.Core/Font.cs
new file mode 100644
index 00000000..bb6da4f4
--- /dev/null
+++ b/Xamarin.Forms.Core/Font.cs
@@ -0,0 +1,145 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [TypeConverter(typeof(FontTypeConverter))]
+ public struct Font
+ {
+ public string FontFamily { get; private set; }
+
+ public double FontSize { get; private set; }
+
+ public NamedSize NamedSize { get; private set; }
+
+ public FontAttributes FontAttributes { get; private set; }
+
+ public bool IsDefault
+ {
+ get { return FontFamily == null && FontSize == 0 && NamedSize == NamedSize.Default && FontAttributes == FontAttributes.None; }
+ }
+
+ public bool UseNamedSize
+ {
+ get { return FontSize <= 0; }
+ }
+
+ public static Font Default
+ {
+ get { return default(Font); }
+ }
+
+ public Font WithSize(double size)
+ {
+ return new Font { FontFamily = FontFamily, FontSize = size, NamedSize = 0, FontAttributes = FontAttributes };
+ }
+
+ public Font WithSize(NamedSize size)
+ {
+ if (size <= 0)
+ throw new ArgumentOutOfRangeException("size");
+
+ return new Font { FontFamily = FontFamily, FontSize = 0, NamedSize = size, FontAttributes = FontAttributes };
+ }
+
+ public Font WithAttributes(FontAttributes fontAttributes)
+ {
+ return new Font { FontFamily = FontFamily, FontSize = FontSize, NamedSize = NamedSize, FontAttributes = fontAttributes };
+ }
+
+ public static Font OfSize(string name, double size)
+ {
+ var result = new Font { FontFamily = name, FontSize = size };
+ return result;
+ }
+
+ public static Font OfSize(string name, NamedSize size)
+ {
+ var result = new Font { FontFamily = name, NamedSize = size };
+ return result;
+ }
+
+ public static Font SystemFontOfSize(double size)
+ {
+ var result = new Font { FontSize = size };
+ return result;
+ }
+
+ public static Font SystemFontOfSize(NamedSize size)
+ {
+ var result = new Font { NamedSize = size };
+ return result;
+ }
+
+ public static Font SystemFontOfSize(double size, FontAttributes attributes)
+ {
+ var result = new Font { FontSize = size, FontAttributes = attributes };
+ return result;
+ }
+
+ public static Font SystemFontOfSize(NamedSize size, FontAttributes attributes)
+ {
+ var result = new Font { NamedSize = size, FontAttributes = attributes };
+ return result;
+ }
+
+ [Obsolete("BoldSystemFontOfSize is obsolete, please use SystemFontOfSize (double, FontAttributes)")]
+ public static Font BoldSystemFontOfSize(double size)
+ {
+ var result = new Font { FontSize = size, FontAttributes = FontAttributes.Bold };
+ return result;
+ }
+
+ [Obsolete("BoldSystemFontOfSize is obsolete, please use SystemFontOfSize (NamedSize, FontAttributes)")]
+ public static Font BoldSystemFontOfSize(NamedSize size)
+ {
+ var result = new Font { NamedSize = size, FontAttributes = FontAttributes.Bold };
+ return result;
+ }
+
+ bool Equals(Font other)
+ {
+ return string.Equals(FontFamily, other.FontFamily) && FontSize.Equals(other.FontSize) && NamedSize == other.NamedSize && FontAttributes == other.FontAttributes;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+ return Equals((Font)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hashCode = FontFamily != null ? FontFamily.GetHashCode() : 0;
+ hashCode = (hashCode * 397) ^ FontSize.GetHashCode();
+ hashCode = (hashCode * 397) ^ NamedSize.GetHashCode();
+ hashCode = (hashCode * 397) ^ FontAttributes.GetHashCode();
+
+ return hashCode;
+ }
+ }
+
+ public static bool operator ==(Font left, Font right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Font left, Font right)
+ {
+ return !left.Equals(right);
+ }
+
+ public override string ToString()
+ {
+ return string.Format("FontFamily: {0}, FontSize: {1}, NamedSize: {2}, FontAttributes: {3}", FontFamily, FontSize, NamedSize, FontAttributes);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/FontAttributes.cs b/Xamarin.Forms.Core/FontAttributes.cs
new file mode 100644
index 00000000..872629c5
--- /dev/null
+++ b/Xamarin.Forms.Core/FontAttributes.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [Flags]
+ public enum FontAttributes
+ {
+ None = 0,
+ Bold = 1 << 0,
+ Italic = 1 << 1
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/FontSizeConverter.cs b/Xamarin.Forms.Core/FontSizeConverter.cs
new file mode 100644
index 00000000..0d0a8865
--- /dev/null
+++ b/Xamarin.Forms.Core/FontSizeConverter.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Globalization;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms
+{
+ public class FontSizeConverter : TypeConverter, IExtendedTypeConverter
+ {
+ [Obsolete("use ConvertFromInvariantString (string, IServiceProvider)")]
+ object IExtendedTypeConverter.ConvertFrom(CultureInfo culture, object value, IServiceProvider serviceProvider)
+ {
+ return ((IExtendedTypeConverter)this).ConvertFromInvariantString(value as string, serviceProvider);
+ }
+
+ object IExtendedTypeConverter.ConvertFromInvariantString(string value, IServiceProvider serviceProvider)
+ {
+ if (value != null)
+ {
+ double size;
+ if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out size))
+ return size;
+ NamedSize namedSize;
+ if (Enum.TryParse(value, out namedSize))
+ {
+ Type type;
+ var valueTargetProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
+ type = valueTargetProvider != null ? valueTargetProvider.TargetObject.GetType() : typeof(Label);
+ return Device.GetNamedSize(namedSize, type, false);
+ }
+ }
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(double)));
+ }
+
+ public override object ConvertFromInvariantString(string value)
+ {
+ if (value != null)
+ {
+ double size;
+ if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out size))
+ return size;
+ NamedSize namedSize;
+ if (Enum.TryParse(value, out namedSize))
+ return Device.GetNamedSize(namedSize, typeof(Label), false);
+ }
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(double)));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/FontTypeConverter.cs b/Xamarin.Forms.Core/FontTypeConverter.cs
new file mode 100644
index 00000000..464cf4ab
--- /dev/null
+++ b/Xamarin.Forms.Core/FontTypeConverter.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+
+namespace Xamarin.Forms
+{
+ public sealed class FontTypeConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString(string value)
+ {
+ // string should be formatted as "[name],[attributes],[size]" there may be multiple attributes, e.g. "Georgia, Bold, Italic, 42"
+ if (value != null)
+ {
+ // trim because mono implements Enum.Parse incorrectly and fails to trim correctly.
+ List<string> parts = value.Split(',').Select(s => s.Trim()).ToList();
+
+ string name = null;
+ var bold = false;
+ var italic = false;
+ double size = -1;
+ NamedSize namedSize = 0;
+
+ // check if last is a size
+ string last = parts.Last();
+
+ double trySize;
+ NamedSize tryNamedSize;
+ if (double.TryParse(last, NumberStyles.Number, CultureInfo.InvariantCulture, out trySize))
+ {
+ size = trySize;
+ parts.RemoveAt(parts.Count - 1);
+ }
+ else if (Enum.TryParse(last, out tryNamedSize))
+ {
+ namedSize = tryNamedSize;
+ parts.RemoveAt(parts.Count - 1);
+ }
+
+ // check if first is a name
+ foreach (string part in parts)
+ {
+ FontAttributes tryAttibute;
+ if (Enum.TryParse(part, out tryAttibute))
+ {
+ // they did not provide a font name
+ if (tryAttibute == FontAttributes.Bold)
+ bold = true;
+ else if (tryAttibute == FontAttributes.Italic)
+ italic = true;
+ }
+ else
+ {
+ // they may have provided a font name
+ if (name != null)
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(Font)));
+
+ name = part;
+ }
+ }
+
+ FontAttributes attributes = 0;
+ if (bold)
+ attributes = attributes | FontAttributes.Bold;
+ if (italic)
+ attributes = attributes | FontAttributes.Italic;
+ if (size == -1 && namedSize == 0)
+ namedSize = NamedSize.Medium;
+
+ if (name != null)
+ {
+ if (size == -1)
+ {
+ return Font.OfSize(name, namedSize).WithAttributes(attributes);
+ }
+ return Font.OfSize(name, size).WithAttributes(attributes);
+ }
+ if (size == -1)
+ {
+ return Font.SystemFontOfSize(namedSize, attributes);
+ }
+ return Font.SystemFontOfSize(size, attributes);
+ }
+
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(Font)));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/FormattedString.cs b/Xamarin.Forms.Core/FormattedString.cs
new file mode 100644
index 00000000..14839ab3
--- /dev/null
+++ b/Xamarin.Forms.Core/FormattedString.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("Spans")]
+ public class FormattedString : INotifyPropertyChanged
+ {
+ readonly SpanCollection _spans = new SpanCollection();
+
+ public FormattedString()
+ {
+ _spans.CollectionChanged += OnCollectionChanged;
+ }
+
+ public IList<Span> Spans
+ {
+ get { return _spans; }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public static explicit operator string(FormattedString formatted)
+ {
+ return formatted.ToString();
+ }
+
+ public static implicit operator FormattedString(string text)
+ {
+ return new FormattedString { Spans = { new Span { Text = text } } };
+ }
+
+ public override string ToString()
+ {
+ return string.Concat(Spans.Select(span => span.Text));
+ }
+
+ void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ if (e.OldItems != null)
+ {
+ foreach (object item in e.OldItems)
+ {
+ var bo = item as Span;
+ if (bo != null)
+ bo.PropertyChanged -= OnItemPropertyChanged;
+ }
+ }
+
+ if (e.NewItems != null)
+ {
+ foreach (object item in e.NewItems)
+ {
+ var bo = item as Span;
+ if (bo != null)
+ bo.PropertyChanged += OnItemPropertyChanged;
+ }
+ }
+
+ OnPropertyChanged("Spans");
+ }
+
+ void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ OnPropertyChanged("Spans");
+ }
+
+ void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler(this, new PropertyChangedEventArgs(propertyName));
+ }
+
+ class SpanCollection : ObservableCollection<Span>
+ {
+ protected override void InsertItem(int index, Span item)
+ {
+ if (item == null)
+ throw new ArgumentNullException("item");
+
+ base.InsertItem(index, item);
+ }
+
+ protected override void SetItem(int index, Span item)
+ {
+ if (item == null)
+ throw new ArgumentNullException("item");
+
+ base.SetItem(index, item);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Frame.cs b/Xamarin.Forms.Core/Frame.cs
new file mode 100644
index 00000000..01f409e4
--- /dev/null
+++ b/Xamarin.Forms.Core/Frame.cs
@@ -0,0 +1,30 @@
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("Content")]
+ [RenderWith(typeof(_FrameRenderer))]
+ public class Frame : ContentView
+ {
+ public static readonly BindableProperty OutlineColorProperty = BindableProperty.Create("OutlineColor", typeof(Color), typeof(Frame), Color.Default);
+
+ public static readonly BindableProperty HasShadowProperty = BindableProperty.Create("HasShadow", typeof(bool), typeof(Frame), true);
+
+ public Frame()
+ {
+ Padding = new Size(20, 20);
+ }
+
+ public bool HasShadow
+ {
+ get { return (bool)GetValue(HasShadowProperty); }
+ set { SetValue(HasShadowProperty, value); }
+ }
+
+ public Color OutlineColor
+ {
+ get { return (Color)GetValue(OutlineColorProperty); }
+ set { SetValue(OutlineColorProperty, value); }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/GestureRecognizer.cs b/Xamarin.Forms.Core/GestureRecognizer.cs
new file mode 100644
index 00000000..f68c996d
--- /dev/null
+++ b/Xamarin.Forms.Core/GestureRecognizer.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Forms
+{
+ public class GestureRecognizer : Element, IGestureRecognizer
+ {
+ internal GestureRecognizer()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/GestureState.cs b/Xamarin.Forms.Core/GestureState.cs
new file mode 100644
index 00000000..a6c110f2
--- /dev/null
+++ b/Xamarin.Forms.Core/GestureState.cs
@@ -0,0 +1,12 @@
+namespace Xamarin.Forms
+{
+ public enum GestureState
+ {
+ Began,
+ Update,
+ Ended,
+ Failed,
+ Cancelled,
+ Possible
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/GestureStatus.cs b/Xamarin.Forms.Core/GestureStatus.cs
new file mode 100644
index 00000000..22f24460
--- /dev/null
+++ b/Xamarin.Forms.Core/GestureStatus.cs
@@ -0,0 +1,10 @@
+namespace Xamarin.Forms
+{
+ public enum GestureStatus
+ {
+ Started = 0,
+ Running = 1,
+ Completed = 2,
+ Canceled = 3
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Grid.cs b/Xamarin.Forms.Core/Grid.cs
new file mode 100644
index 00000000..442146c2
--- /dev/null
+++ b/Xamarin.Forms.Core/Grid.cs
@@ -0,0 +1,359 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+
+namespace Xamarin.Forms
+{
+ public partial class Grid : Layout<View>
+ {
+ public static readonly BindableProperty RowProperty = BindableProperty.CreateAttached("Row", typeof(int), typeof(Grid), default(int), validateValue: (bindable, value) => (int)value >= 0);
+
+ public static readonly BindableProperty RowSpanProperty = BindableProperty.CreateAttached("RowSpan", typeof(int), typeof(Grid), 1, validateValue: (bindable, value) => (int)value >= 1);
+
+ public static readonly BindableProperty ColumnProperty = BindableProperty.CreateAttached("Column", typeof(int), typeof(Grid), default(int), validateValue: (bindable, value) => (int)value >= 0);
+
+ public static readonly BindableProperty ColumnSpanProperty = BindableProperty.CreateAttached("ColumnSpan", typeof(int), typeof(Grid), 1, validateValue: (bindable, value) => (int)value >= 1);
+
+ public static readonly BindableProperty RowSpacingProperty = BindableProperty.Create("RowSpacing", typeof(double), typeof(Grid), 6d,
+ propertyChanged: (bindable, oldValue, newValue) => ((Grid)bindable).InvalidateMeasure(InvalidationTrigger.MeasureChanged));
+
+ public static readonly BindableProperty ColumnSpacingProperty = BindableProperty.Create("ColumnSpacing", typeof(double), typeof(Grid), 6d,
+ propertyChanged: (bindable, oldValue, newValue) => ((Grid)bindable).InvalidateMeasure(InvalidationTrigger.MeasureChanged));
+
+ public static readonly BindableProperty ColumnDefinitionsProperty = BindableProperty.Create("ColumnDefinitions", typeof(ColumnDefinitionCollection), typeof(Grid), null,
+ validateValue: (bindable, value) => value != null, propertyChanged: (bindable, oldvalue, newvalue) =>
+ {
+ if (oldvalue != null)
+ ((ColumnDefinitionCollection)oldvalue).ItemSizeChanged -= ((Grid)bindable).OnDefinitionChanged;
+ if (newvalue != null)
+ ((ColumnDefinitionCollection)newvalue).ItemSizeChanged += ((Grid)bindable).OnDefinitionChanged;
+ }, defaultValueCreator: bindable =>
+ {
+ var colDef = new ColumnDefinitionCollection();
+ colDef.ItemSizeChanged += ((Grid)bindable).OnDefinitionChanged;
+ return colDef;
+ });
+
+ public static readonly BindableProperty RowDefinitionsProperty = BindableProperty.Create("RowDefinitions", typeof(RowDefinitionCollection), typeof(Grid), null,
+ validateValue: (bindable, value) => value != null, propertyChanged: (bindable, oldvalue, newvalue) =>
+ {
+ if (oldvalue != null)
+ ((RowDefinitionCollection)oldvalue).ItemSizeChanged -= ((Grid)bindable).OnDefinitionChanged;
+ if (newvalue != null)
+ ((RowDefinitionCollection)newvalue).ItemSizeChanged += ((Grid)bindable).OnDefinitionChanged;
+ }, defaultValueCreator: bindable =>
+ {
+ var rowDef = new RowDefinitionCollection();
+ rowDef.ItemSizeChanged += ((Grid)bindable).OnDefinitionChanged;
+ return rowDef;
+ });
+
+ readonly GridElementCollection _children;
+
+ public Grid()
+ {
+ _children = new GridElementCollection(InternalChildren, this) { Parent = this };
+ }
+
+ public new IGridList<View> Children
+ {
+ get { return _children; }
+ }
+
+ public ColumnDefinitionCollection ColumnDefinitions
+ {
+ get { return (ColumnDefinitionCollection)GetValue(ColumnDefinitionsProperty); }
+ set { SetValue(ColumnDefinitionsProperty, value); }
+ }
+
+ public double ColumnSpacing
+ {
+ get { return (double)GetValue(ColumnSpacingProperty); }
+ set { SetValue(ColumnSpacingProperty, value); }
+ }
+
+ public RowDefinitionCollection RowDefinitions
+ {
+ get { return (RowDefinitionCollection)GetValue(RowDefinitionsProperty); }
+ set { SetValue(RowDefinitionsProperty, value); }
+ }
+
+ public double RowSpacing
+ {
+ get { return (double)GetValue(RowSpacingProperty); }
+ set { SetValue(RowSpacingProperty, value); }
+ }
+
+ public static int GetColumn(BindableObject bindable)
+ {
+ return (int)bindable.GetValue(ColumnProperty);
+ }
+
+ public static int GetColumnSpan(BindableObject bindable)
+ {
+ return (int)bindable.GetValue(ColumnSpanProperty);
+ }
+
+ public static int GetRow(BindableObject bindable)
+ {
+ return (int)bindable.GetValue(RowProperty);
+ }
+
+ public static int GetRowSpan(BindableObject bindable)
+ {
+ return (int)bindable.GetValue(RowSpanProperty);
+ }
+
+ public static void SetColumn(BindableObject bindable, int value)
+ {
+ bindable.SetValue(ColumnProperty, value);
+ }
+
+ public static void SetColumnSpan(BindableObject bindable, int value)
+ {
+ bindable.SetValue(ColumnSpanProperty, value);
+ }
+
+ public static void SetRow(BindableObject bindable, int value)
+ {
+ bindable.SetValue(RowProperty, value);
+ }
+
+ public static void SetRowSpan(BindableObject bindable, int value)
+ {
+ bindable.SetValue(RowSpanProperty, value);
+ }
+
+ protected override void OnAdded(View view)
+ {
+ base.OnAdded(view);
+ view.PropertyChanged += OnItemPropertyChanged;
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ UpdateInheritedBindingContexts();
+ base.OnBindingContextChanged();
+ }
+
+ protected override void OnRemoved(View view)
+ {
+ base.OnRemoved(view);
+ view.PropertyChanged -= OnItemPropertyChanged;
+ }
+
+ internal override void ComputeConstraintForView(View view)
+ {
+ LayoutOptions vOptions = view.VerticalOptions;
+ LayoutOptions hOptions = view.HorizontalOptions;
+
+ var result = LayoutConstraint.None;
+
+ if (_rows == null || _columns == null)
+ EnsureRowsColumnsInitialized();
+
+ if (vOptions.Alignment == LayoutAlignment.Fill)
+ {
+ int row = GetRow(view);
+ int rowSpan = GetRowSpan(view);
+ List<RowDefinition> rowDefinitions = _rows;
+
+ var canFix = true;
+
+ for (int i = row; i < row + rowSpan && i < rowDefinitions.Count; i++)
+ {
+ GridLength height = rowDefinitions[i].Height;
+ if (height.IsAuto)
+ {
+ canFix = false;
+ break;
+ }
+ if ((Constraint & LayoutConstraint.VerticallyFixed) == 0 && height.IsStar)
+ {
+ canFix = false;
+ break;
+ }
+ }
+
+ if (canFix)
+ result |= LayoutConstraint.VerticallyFixed;
+ }
+
+ if (hOptions.Alignment == LayoutAlignment.Fill)
+ {
+ int col = GetColumn(view);
+ int colSpan = GetColumnSpan(view);
+ List<ColumnDefinition> columnDefinitions = _columns;
+
+ var canFix = true;
+
+ for (int i = col; i < col + colSpan && i < columnDefinitions.Count; i++)
+ {
+ GridLength width = columnDefinitions[i].Width;
+ if (width.IsAuto)
+ {
+ canFix = false;
+ break;
+ }
+ if ((Constraint & LayoutConstraint.HorizontallyFixed) == 0 && width.IsStar)
+ {
+ canFix = false;
+ break;
+ }
+ }
+
+ if (canFix)
+ result |= LayoutConstraint.HorizontallyFixed;
+ }
+
+ view.ComputedConstraint = result;
+ }
+
+ internal override void InvalidateMeasure(InvalidationTrigger trigger)
+ {
+ base.InvalidateMeasure(trigger);
+ _columns = null;
+ _rows = null;
+ }
+
+ void OnDefinitionChanged(object sender, EventArgs args)
+ {
+ ComputeConstrainsForChildren();
+ UpdateInheritedBindingContexts();
+ InvalidateLayout();
+ }
+
+ void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == ColumnProperty.PropertyName || e.PropertyName == ColumnSpanProperty.PropertyName || e.PropertyName == RowProperty.PropertyName ||
+ e.PropertyName == RowSpanProperty.PropertyName)
+ {
+ var child = sender as View;
+ if (child != null)
+ {
+ ComputeConstraintForView(child);
+ }
+
+ InvalidateLayout();
+ }
+ }
+
+ void UpdateInheritedBindingContexts()
+ {
+ object bindingContext = BindingContext;
+ RowDefinitionCollection rowDefs = RowDefinitions;
+ if (rowDefs != null)
+ {
+ for (var i = 0; i < rowDefs.Count; i++)
+ {
+ RowDefinition rowdef = rowDefs[i];
+ SetInheritedBindingContext(rowdef, bindingContext);
+ }
+ }
+
+ ColumnDefinitionCollection colDefs = ColumnDefinitions;
+ if (colDefs != null)
+ {
+ for (var i = 0; i < colDefs.Count; i++)
+ {
+ ColumnDefinition coldef = colDefs[i];
+ SetInheritedBindingContext(coldef, bindingContext);
+ }
+ }
+ }
+
+ public interface IGridList<T> : IList<T> where T : View
+ {
+ void Add(View view, int left, int top);
+ void Add(View view, int left, int right, int top, int bottom);
+ void AddHorizontal(IEnumerable<View> views);
+ void AddHorizontal(View view);
+ void AddVertical(IEnumerable<View> views);
+ void AddVertical(View view);
+ }
+
+ class GridElementCollection : ElementCollection<View>, IGridList<View>
+ {
+ public GridElementCollection(ObservableCollection<Element> inner, Grid parent) : base(inner)
+ {
+ Parent = parent;
+ }
+
+ internal Grid Parent { get; set; }
+
+ public void Add(View view, int left, int top)
+ {
+ if (left < 0)
+ throw new ArgumentOutOfRangeException("left");
+ if (top < 0)
+ throw new ArgumentOutOfRangeException("top");
+ Add(view, left, left + 1, top, top + 1);
+ }
+
+ public void Add(View view, int left, int right, int top, int bottom)
+ {
+ if (left < 0)
+ throw new ArgumentOutOfRangeException("left");
+ if (top < 0)
+ throw new ArgumentOutOfRangeException("top");
+ if (left >= right)
+ throw new ArgumentOutOfRangeException("right");
+ if (top >= bottom)
+ throw new ArgumentOutOfRangeException("bottom");
+ if (view == null)
+ throw new ArgumentNullException("view");
+
+ SetRow(view, top);
+ SetRowSpan(view, bottom - top);
+ SetColumn(view, left);
+ SetColumnSpan(view, right - left);
+
+ Add(view);
+ }
+
+ public void AddHorizontal(IEnumerable<View> views)
+ {
+ if (views == null)
+ throw new ArgumentNullException("views");
+
+ views.ForEach(AddHorizontal);
+ }
+
+ public void AddHorizontal(View view)
+ {
+ if (view == null)
+ throw new ArgumentNullException("view");
+
+ int lastRow = this.Any() ? this.Max(w => GetRow(w) + GetRowSpan(w) - 1) : -1;
+ lastRow = Math.Max(lastRow, Parent.RowDefinitions.Count - 1);
+ int lastCol = this.Any() ? this.Max(w => GetColumn(w) + GetColumnSpan(w) - 1) : -1;
+ lastCol = Math.Max(lastCol, Parent.ColumnDefinitions.Count - 1);
+
+ Add(view, lastCol + 1, lastCol + 2, 0, Math.Max(1, lastRow));
+ }
+
+ public void AddVertical(IEnumerable<View> views)
+ {
+ if (views == null)
+ throw new ArgumentNullException("views");
+
+ views.ForEach(AddVertical);
+ }
+
+ public void AddVertical(View view)
+ {
+ if (view == null)
+ throw new ArgumentNullException("view");
+
+ int lastRow = this.Any() ? this.Max(w => GetRow(w) + GetRowSpan(w) - 1) : -1;
+ lastRow = Math.Max(lastRow, Parent.RowDefinitions.Count - 1);
+ int lastCol = this.Any() ? this.Max(w => GetColumn(w) + GetColumnSpan(w) - 1) : -1;
+ lastCol = Math.Max(lastCol, Parent.ColumnDefinitions.Count - 1);
+
+ Add(view, 0, Math.Max(1, lastCol), lastRow + 1, lastRow + 2);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/GridCalc.cs b/Xamarin.Forms.Core/GridCalc.cs
new file mode 100644
index 00000000..778e188e
--- /dev/null
+++ b/Xamarin.Forms.Core/GridCalc.cs
@@ -0,0 +1,698 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Xamarin.Forms
+{
+ public partial class Grid
+ {
+ List<ColumnDefinition> _columns;
+ List<RowDefinition> _rows;
+
+ protected override void LayoutChildren(double x, double y, double width, double height)
+ {
+ if (!InternalChildren.Any())
+ return;
+
+ MeasureGrid(width, height);
+
+ // Make copies so if InvalidateMeasure is called during layout we dont crash when these get nulled
+ List<ColumnDefinition> columnsCopy = _columns;
+ List<RowDefinition> rowsCopy = _rows;
+
+ for (var index = 0; index < InternalChildren.Count; index++)
+ {
+ var child = (View)InternalChildren[index];
+ if (!child.IsVisible)
+ continue;
+ int r = GetRow(child);
+ int c = GetColumn(child);
+ int rs = GetRowSpan(child);
+ int cs = GetColumnSpan(child);
+
+ double posx = x + c * ColumnSpacing;
+ for (var i = 0; i < c; i++)
+ posx += columnsCopy[i].ActualWidth;
+ double posy = y + r * RowSpacing;
+ for (var i = 0; i < r; i++)
+ posy += rowsCopy[i].ActualHeight;
+
+ double w = columnsCopy[c].ActualWidth;
+ for (var i = 1; i < cs; i++)
+ w += ColumnSpacing + columnsCopy[c + i].ActualWidth;
+ double h = rowsCopy[r].ActualHeight;
+ for (var i = 1; i < rs; i++)
+ h += RowSpacing + rowsCopy[r + i].ActualHeight;
+
+ // in the future we can might maybe optimize by passing the already calculated size request
+ LayoutChildIntoBoundingRegion(child, new Rectangle(posx, posy, w, h));
+ }
+ }
+
+ [Obsolete("Use OnMeasure")]
+ protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ if (!InternalChildren.Any())
+ return new SizeRequest(new Size(0, 0));
+
+ MeasureGrid(widthConstraint, heightConstraint, true);
+
+ double columnWidthSum = 0;
+ double nonStarColumnWidthSum = 0;
+ for (var index = 0; index < _columns.Count; index++)
+ {
+ ColumnDefinition c = _columns[index];
+ columnWidthSum += c.ActualWidth;
+ if (!c.Width.IsStar)
+ nonStarColumnWidthSum += c.ActualWidth;
+ }
+ double rowHeightSum = 0;
+ double nonStarRowHeightSum = 0;
+ for (var index = 0; index < _rows.Count; index++)
+ {
+ RowDefinition r = _rows[index];
+ rowHeightSum += r.ActualHeight;
+ if (!r.Height.IsStar)
+ nonStarRowHeightSum += r.ActualHeight;
+ }
+
+ var request = new Size(columnWidthSum + (_columns.Count - 1) * ColumnSpacing, rowHeightSum + (_rows.Count - 1) * RowSpacing);
+ var minimum = new Size(nonStarColumnWidthSum + (_columns.Count - 1) * ColumnSpacing, nonStarRowHeightSum + (_rows.Count - 1) * RowSpacing);
+
+ var result = new SizeRequest(request, minimum);
+ return result;
+ }
+
+ void AssignAbsoluteCells()
+ {
+ for (var index = 0; index < _rows.Count; index++)
+ {
+ RowDefinition row = _rows[index];
+ if (row.Height.IsAbsolute)
+ row.ActualHeight = row.Height.Value;
+ }
+
+ for (var index = 0; index < _columns.Count; index++)
+ {
+ ColumnDefinition col = _columns[index];
+ if (col.Width.IsAbsolute)
+ col.ActualWidth = col.Width.Value;
+ }
+ }
+
+ void CalculateAutoCells(double width, double height)
+ {
+ // this require multiple passes. First process the 1-span, then 2, 3, ...
+ // And this needs to be run twice, just in case a lower-span column can be determined by a larger span
+ for (var iteration = 0; iteration < 2; iteration++)
+ {
+ for (var rowspan = 1; rowspan <= _rows.Count; rowspan++)
+ {
+ for (var i = 0; i < _rows.Count; i++)
+ {
+ RowDefinition row = _rows[i];
+ if (!row.Height.IsAuto)
+ continue;
+ if (row.ActualHeight >= 0) // if Actual is already set (by a smaller span), skip till pass 3
+ continue;
+
+ double actualHeight = row.ActualHeight;
+ double minimumHeight = row.MinimumHeight;
+ for (var index = 0; index < InternalChildren.Count; index++)
+ {
+ var child = (View)InternalChildren[index];
+ if (!child.IsVisible || GetRowSpan(child) != rowspan || !IsInRow(child, i) || NumberOfUnsetRowHeight(child) > 1)
+ continue;
+ double assignedWidth = GetAssignedColumnWidth(child);
+ double assignedHeight = GetAssignedRowHeight(child);
+ double widthRequest = assignedWidth + GetUnassignedWidth(width);
+ double heightRequest = double.IsPositiveInfinity(height) ? double.PositiveInfinity : assignedHeight + GetUnassignedHeight(height);
+
+ SizeRequest sizeRequest = child.Measure(widthRequest, heightRequest, MeasureFlags.IncludeMargins);
+ actualHeight = Math.Max(actualHeight, sizeRequest.Request.Height - assignedHeight - RowSpacing * (GetRowSpan(child) - 1));
+ minimumHeight = Math.Max(minimumHeight, sizeRequest.Minimum.Height - assignedHeight - RowSpacing * (GetRowSpan(child) - 1));
+ }
+ if (actualHeight >= 0)
+ row.ActualHeight = actualHeight;
+ if (minimumHeight >= 0)
+ row.MinimumHeight = minimumHeight;
+ }
+ }
+
+ for (var colspan = 1; colspan <= _columns.Count; colspan++)
+ {
+ for (var i = 0; i < _columns.Count; i++)
+ {
+ ColumnDefinition col = _columns[i];
+ if (!col.Width.IsAuto)
+ continue;
+ if (col.ActualWidth >= 0) // if Actual is already set (by a smaller span), skip
+ continue;
+
+ double actualWidth = col.ActualWidth;
+ double minimumWidth = col.MinimumWidth;
+ for (var index = 0; index < InternalChildren.Count; index++)
+ {
+ var child = (View)InternalChildren[index];
+ if (!child.IsVisible || GetColumnSpan(child) != colspan || !IsInColumn(child, i) || NumberOfUnsetColumnWidth(child) > 1)
+ continue;
+ double assignedWidth = GetAssignedColumnWidth(child);
+ double assignedHeight = GetAssignedRowHeight(child);
+ double widthRequest = double.IsPositiveInfinity(width) ? double.PositiveInfinity : assignedWidth + GetUnassignedWidth(width);
+ double heightRequest = assignedHeight + GetUnassignedHeight(height);
+
+ SizeRequest sizeRequest = child.Measure(widthRequest, heightRequest, MeasureFlags.IncludeMargins);
+ actualWidth = Math.Max(actualWidth, sizeRequest.Request.Width - assignedWidth - (GetColumnSpan(child) - 1) * ColumnSpacing);
+ minimumWidth = Math.Max(minimumWidth, sizeRequest.Minimum.Width - assignedWidth - (GetColumnSpan(child) - 1) * ColumnSpacing);
+ }
+ if (actualWidth >= 0)
+ col.ActualWidth = actualWidth;
+ if (minimumWidth >= 0)
+ col.MinimumWidth = actualWidth;
+ }
+ }
+ }
+ }
+
+ void CalculateStarCells(double width, double height, double totalStarsWidth, double totalStarsHeight)
+ {
+ double starColWidth = GetUnassignedWidth(width) / totalStarsWidth;
+ double starRowHeight = GetUnassignedHeight(height) / totalStarsHeight;
+
+ for (var index = 0; index < _columns.Count; index++)
+ {
+ ColumnDefinition col = _columns[index];
+ if (col.Width.IsStar)
+ col.ActualWidth = col.Width.Value * starColWidth;
+ }
+
+ for (var index = 0; index < _rows.Count; index++)
+ {
+ RowDefinition row = _rows[index];
+ if (row.Height.IsStar)
+ row.ActualHeight = row.Height.Value * starRowHeight;
+ }
+ }
+
+ void ContractColumnsIfNeeded(double width, Func<ColumnDefinition, bool> predicate)
+ {
+ double columnWidthSum = 0;
+ for (var index = 0; index < _columns.Count; index++)
+ {
+ ColumnDefinition c = _columns[index];
+ columnWidthSum += c.ActualWidth;
+ }
+
+ double rowHeightSum = 0;
+ for (var index = 0; index < _rows.Count; index++)
+ {
+ RowDefinition r = _rows[index];
+ rowHeightSum += r.ActualHeight;
+ }
+
+ var request = new Size(columnWidthSum + (_columns.Count - 1) * ColumnSpacing, rowHeightSum + (_rows.Count - 1) * RowSpacing);
+ if (request.Width > width)
+ {
+ double contractionSpace = 0;
+ for (var index = 0; index < _columns.Count; index++)
+ {
+ ColumnDefinition c = _columns[index];
+ if (predicate(c))
+ contractionSpace += c.ActualWidth - c.MinimumWidth;
+ }
+ if (contractionSpace > 0)
+ {
+ // contract as much as we can but no more
+ double contractionNeeded = Math.Min(contractionSpace, Math.Max(request.Width - width, 0));
+ double contractFactor = contractionNeeded / contractionSpace;
+ for (var index = 0; index < _columns.Count; index++)
+ {
+ ColumnDefinition col = _columns[index];
+ if (!predicate(col))
+ continue;
+ double availableSpace = col.ActualWidth - col.MinimumWidth;
+ double contraction = availableSpace * contractFactor;
+ col.ActualWidth -= contraction;
+ contractionNeeded -= contraction;
+ }
+ }
+ }
+ }
+
+ void ContractRowsIfNeeded(double height, Func<RowDefinition, bool> predicate)
+ {
+ double columnSum = 0;
+ for (var index = 0; index < _columns.Count; index++)
+ {
+ ColumnDefinition c = _columns[index];
+ columnSum += Math.Max(0, c.ActualWidth);
+ }
+ double rowSum = 0;
+ for (var index = 0; index < _rows.Count; index++)
+ {
+ RowDefinition r = _rows[index];
+ rowSum += Math.Max(0, r.ActualHeight);
+ }
+
+ var request = new Size(columnSum + (_columns.Count - 1) * ColumnSpacing, rowSum + (_rows.Count - 1) * RowSpacing);
+ if (request.Height <= height)
+ return;
+ double contractionSpace = 0;
+ for (var index = 0; index < _rows.Count; index++)
+ {
+ RowDefinition r = _rows[index];
+ if (predicate(r))
+ contractionSpace += r.ActualHeight - r.MinimumHeight;
+ }
+ if (!(contractionSpace > 0))
+ return;
+ // contract as much as we can but no more
+ double contractionNeeded = Math.Min(contractionSpace, Math.Max(request.Height - height, 0));
+ double contractFactor = contractionNeeded / contractionSpace;
+ for (var index = 0; index < _rows.Count; index++)
+ {
+ RowDefinition row = _rows[index];
+ if (!predicate(row))
+ continue;
+ double availableSpace = row.ActualHeight - row.MinimumHeight;
+ double contraction = availableSpace * contractFactor;
+ row.ActualHeight -= contraction;
+ contractionNeeded -= contraction;
+ }
+ }
+
+ void EnsureRowsColumnsInitialized()
+ {
+ _columns = ColumnDefinitions == null ? new List<ColumnDefinition>() : ColumnDefinitions.ToList();
+ _rows = RowDefinitions == null ? new List<RowDefinition>() : RowDefinitions.ToList();
+
+ int lastRow = -1;
+ for (var index = 0; index < InternalChildren.Count; index++)
+ {
+ Element w = InternalChildren[index];
+ lastRow = Math.Max(lastRow, GetRow(w) + GetRowSpan(w) - 1);
+ }
+ lastRow = Math.Max(lastRow, RowDefinitions.Count - 1);
+
+ int lastCol = -1;
+ for (var index = 0; index < InternalChildren.Count; index++)
+ {
+ Element w = InternalChildren[index];
+ lastCol = Math.Max(lastCol, GetColumn(w) + GetColumnSpan(w) - 1);
+ }
+ lastCol = Math.Max(lastCol, ColumnDefinitions.Count - 1);
+
+ while (_columns.Count <= lastCol)
+ _columns.Add(new ColumnDefinition());
+ while (_rows.Count <= lastRow)
+ _rows.Add(new RowDefinition());
+
+ for (var index = 0; index < _columns.Count; index++)
+ {
+ ColumnDefinition col = _columns[index];
+ col.ActualWidth = -1;
+ }
+ for (var index = 0; index < _rows.Count; index++)
+ {
+ RowDefinition row = _rows[index];
+ row.ActualHeight = -1;
+ }
+ }
+
+ void ExpandLastAutoColumnIfNeeded(double width, bool expandToRequest)
+ {
+ for (var index = 0; index < InternalChildren.Count; index++)
+ {
+ Element element = InternalChildren[index];
+ var child = (View)element;
+ if (!child.IsVisible)
+ continue;
+
+ ColumnDefinition col = GetLastAutoColumn(child);
+ if (col == null)
+ continue;
+
+ double assignedWidth = GetAssignedColumnWidth(child);
+ double w = double.IsPositiveInfinity(width) ? double.PositiveInfinity : assignedWidth + GetUnassignedWidth(width);
+ SizeRequest sizeRequest = child.Measure(w, GetAssignedRowHeight(child), MeasureFlags.IncludeMargins);
+ double requiredWidth = expandToRequest ? sizeRequest.Request.Width : sizeRequest.Minimum.Width;
+ double deltaWidth = requiredWidth - assignedWidth - (GetColumnSpan(child) - 1) * ColumnSpacing;
+ if (deltaWidth > 0)
+ {
+ col.ActualWidth += deltaWidth;
+ }
+ }
+ }
+
+ void ExpandLastAutoRowIfNeeded(double height, bool expandToRequest)
+ {
+ for (var index = 0; index < InternalChildren.Count; index++)
+ {
+ Element element = InternalChildren[index];
+ var child = (View)element;
+ if (!child.IsVisible)
+ continue;
+
+ RowDefinition row = GetLastAutoRow(child);
+ if (row == null)
+ continue;
+
+ double assignedHeight = GetAssignedRowHeight(child);
+ double h = double.IsPositiveInfinity(height) ? double.PositiveInfinity : assignedHeight + GetUnassignedHeight(height);
+ SizeRequest sizeRequest = child.Measure(GetAssignedColumnWidth(child), h, MeasureFlags.IncludeMargins);
+ double requiredHeight = expandToRequest ? sizeRequest.Request.Height : sizeRequest.Minimum.Height;
+ double deltaHeight = requiredHeight - assignedHeight - (GetRowSpan(child) - 1) * RowSpacing;
+ if (deltaHeight > 0)
+ {
+ row.ActualHeight += deltaHeight;
+ }
+ }
+ }
+
+ void MeasureAndContractStarredColumns(double width, double height, double totalStarsWidth)
+ {
+ double starColWidth;
+ starColWidth = MeasuredStarredColumns();
+
+ if (!double.IsPositiveInfinity(width) && double.IsPositiveInfinity(height))
+ {
+ // re-zero columns so GetUnassignedWidth returns correctly
+ for (var index = 0; index < _columns.Count; index++)
+ {
+ ColumnDefinition col = _columns[index];
+ if (col.Width.IsStar)
+ col.ActualWidth = 0;
+ }
+
+ starColWidth = Math.Max(starColWidth, GetUnassignedWidth(width) / totalStarsWidth);
+ }
+
+ for (var index = 0; index < _columns.Count; index++)
+ {
+ ColumnDefinition col = _columns[index];
+ if (col.Width.IsStar)
+ col.ActualWidth = col.Width.Value * starColWidth;
+ }
+
+ ContractColumnsIfNeeded(width, c => c.Width.IsStar);
+ }
+
+ void MeasureAndContractStarredRows(double width, double height, double totalStarsHeight)
+ {
+ double starRowHeight;
+ starRowHeight = MeasureStarredRows();
+
+ if (!double.IsPositiveInfinity(height) && double.IsPositiveInfinity(width))
+ {
+ for (var index = 0; index < _rows.Count; index++)
+ {
+ RowDefinition row = _rows[index];
+ if (row.Height.IsStar)
+ row.ActualHeight = 0;
+ }
+
+ starRowHeight = Math.Max(starRowHeight, GetUnassignedHeight(height) / totalStarsHeight);
+ }
+
+ for (var index = 0; index < _rows.Count; index++)
+ {
+ RowDefinition row = _rows[index];
+ if (row.Height.IsStar)
+ row.ActualHeight = row.Height.Value * starRowHeight;
+ }
+
+ ContractRowsIfNeeded(height, r => r.Height.IsStar);
+ }
+
+ double MeasuredStarredColumns()
+ {
+ double starColWidth;
+ for (var iteration = 0; iteration < 2; iteration++)
+ {
+ for (var colspan = 1; colspan <= _columns.Count; colspan++)
+ {
+ for (var i = 0; i < _columns.Count; i++)
+ {
+ ColumnDefinition col = _columns[i];
+ if (!col.Width.IsStar)
+ continue;
+ if (col.ActualWidth >= 0) // if Actual is already set (by a smaller span), skip
+ continue;
+
+ double actualWidth = col.ActualWidth;
+ double minimumWidth = col.MinimumWidth;
+ for (var index = 0; index < InternalChildren.Count; index++)
+ {
+ var child = (View)InternalChildren[index];
+ if (!child.IsVisible || GetColumnSpan(child) != colspan || !IsInColumn(child, i) || NumberOfUnsetColumnWidth(child) > 1)
+ continue;
+ double assignedWidth = GetAssignedColumnWidth(child);
+
+ SizeRequest sizeRequest = child.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.IncludeMargins);
+ actualWidth = Math.Max(actualWidth, sizeRequest.Request.Width - assignedWidth - (GetColumnSpan(child) - 1) * ColumnSpacing);
+ minimumWidth = Math.Max(minimumWidth, sizeRequest.Minimum.Width - assignedWidth - (GetColumnSpan(child) - 1) * ColumnSpacing);
+ }
+ if (actualWidth >= 0)
+ col.ActualWidth = actualWidth;
+
+ if (minimumWidth >= 0)
+ col.MinimumWidth = minimumWidth;
+ }
+ }
+ }
+
+ //Measure the stars
+ starColWidth = 1;
+ for (var index = 0; index < _columns.Count; index++)
+ {
+ ColumnDefinition col = _columns[index];
+ if (!col.Width.IsStar)
+ continue;
+ starColWidth = Math.Max(starColWidth, col.ActualWidth / col.Width.Value);
+ }
+
+ return starColWidth;
+ }
+
+ void MeasureGrid(double width, double height, bool requestSize = false)
+ {
+ EnsureRowsColumnsInitialized();
+
+ AssignAbsoluteCells();
+
+ CalculateAutoCells(width, height);
+
+ if (!requestSize)
+ {
+ ContractColumnsIfNeeded(width, c => c.Width.IsAuto);
+ ContractRowsIfNeeded(height, r => r.Height.IsAuto);
+ }
+
+ double totalStarsHeight = 0;
+ for (var index = 0; index < _rows.Count; index++)
+ {
+ RowDefinition row = _rows[index];
+ if (row.Height.IsStar)
+ totalStarsHeight += row.Height.Value;
+ }
+
+ double totalStarsWidth = 0;
+ for (var index = 0; index < _columns.Count; index++)
+ {
+ ColumnDefinition col = _columns[index];
+ if (col.Width.IsStar)
+ totalStarsWidth += col.Width.Value;
+ }
+
+ if (requestSize)
+ {
+ MeasureAndContractStarredColumns(width, height, totalStarsWidth);
+ MeasureAndContractStarredRows(width, height, totalStarsHeight);
+ }
+ else
+ {
+ CalculateStarCells(width, height, totalStarsWidth, totalStarsHeight);
+ }
+
+ ZeroUnassignedCells();
+
+ ExpandLastAutoRowIfNeeded(height, requestSize);
+ ExpandLastAutoColumnIfNeeded(width, requestSize);
+ }
+
+ double MeasureStarredRows()
+ {
+ double starRowHeight;
+ for (var iteration = 0; iteration < 2; iteration++)
+ {
+ for (var rowspan = 1; rowspan <= _rows.Count; rowspan++)
+ {
+ for (var i = 0; i < _rows.Count; i++)
+ {
+ RowDefinition row = _rows[i];
+ if (!row.Height.IsStar)
+ continue;
+ if (row.ActualHeight >= 0) // if Actual is already set (by a smaller span), skip till pass 3
+ continue;
+
+ double actualHeight = row.ActualHeight;
+ double minimumHeight = row.MinimumHeight;
+ for (var index = 0; index < InternalChildren.Count; index++)
+ {
+ var child = (View)InternalChildren[index];
+ if (!child.IsVisible || GetRowSpan(child) != rowspan || !IsInRow(child, i) || NumberOfUnsetRowHeight(child) > 1)
+ continue;
+ double assignedHeight = GetAssignedRowHeight(child);
+ double assignedWidth = GetAssignedColumnWidth(child);
+
+ SizeRequest sizeRequest = child.Measure(assignedWidth, double.PositiveInfinity, MeasureFlags.IncludeMargins);
+ actualHeight = Math.Max(actualHeight, sizeRequest.Request.Height - assignedHeight - RowSpacing * (GetRowSpan(child) - 1));
+ minimumHeight = Math.Max(minimumHeight, sizeRequest.Minimum.Height - assignedHeight - RowSpacing * (GetRowSpan(child) - 1));
+ }
+ if (actualHeight >= 0)
+ row.ActualHeight = actualHeight;
+
+ if (minimumHeight >= 0)
+ row.MinimumHeight = minimumHeight;
+ }
+ }
+ }
+
+ // 3. Star columns:
+
+ //Measure the stars
+ starRowHeight = 1;
+ for (var index = 0; index < _rows.Count; index++)
+ {
+ RowDefinition row = _rows[index];
+ if (!row.Height.IsStar)
+ continue;
+ starRowHeight = Math.Max(starRowHeight, row.ActualHeight / row.Height.Value);
+ }
+
+ return starRowHeight;
+ }
+
+ void ZeroUnassignedCells()
+ {
+ for (var index = 0; index < _columns.Count; index++)
+ {
+ ColumnDefinition col = _columns[index];
+ if (col.ActualWidth < 0)
+ col.ActualWidth = 0;
+ }
+ for (var index = 0; index < _rows.Count; index++)
+ {
+ RowDefinition row = _rows[index];
+ if (row.ActualHeight < 0)
+ row.ActualHeight = 0;
+ }
+ }
+
+ #region Helpers
+
+ static bool IsInColumn(BindableObject child, int column)
+ {
+ int childColumn = GetColumn(child);
+ int span = GetColumnSpan(child);
+ return childColumn <= column && column < childColumn + span;
+ }
+
+ static bool IsInRow(BindableObject child, int row)
+ {
+ int childRow = GetRow(child);
+ int span = GetRowSpan(child);
+ return childRow <= row && row < childRow + span;
+ }
+
+ int NumberOfUnsetColumnWidth(BindableObject child)
+ {
+ var n = 0;
+ int index = GetColumn(child);
+ int span = GetColumnSpan(child);
+ for (int i = index; i < index + span; i++)
+ if (_columns[i].ActualWidth <= 0)
+ n++;
+ return n;
+ }
+
+ int NumberOfUnsetRowHeight(BindableObject child)
+ {
+ var n = 0;
+ int index = GetRow(child);
+ int span = GetRowSpan(child);
+ for (int i = index; i < index + span; i++)
+ if (_rows[i].ActualHeight <= 0)
+ n++;
+ return n;
+ }
+
+ double GetAssignedColumnWidth(BindableObject child)
+ {
+ var actual = 0d;
+ int index = GetColumn(child);
+ int span = GetColumnSpan(child);
+ for (int i = index; i < index + span; i++)
+ if (_columns[i].ActualWidth >= 0)
+ actual += _columns[i].ActualWidth;
+ return actual;
+ }
+
+ double GetAssignedRowHeight(BindableObject child)
+ {
+ var actual = 0d;
+ int index = GetRow(child);
+ int span = GetRowSpan(child);
+ for (int i = index; i < index + span; i++)
+ if (_rows[i].ActualHeight >= 0)
+ actual += _rows[i].ActualHeight;
+ return actual;
+ }
+
+ ColumnDefinition GetLastAutoColumn(BindableObject child)
+ {
+ int index = GetColumn(child);
+ int span = GetColumnSpan(child);
+ for (int i = index + span - 1; i >= index; i--)
+ if (_columns[i].Width.IsAuto)
+ return _columns[i];
+ return null;
+ }
+
+ RowDefinition GetLastAutoRow(BindableObject child)
+ {
+ int index = GetRow(child);
+ int span = GetRowSpan(child);
+ for (int i = index + span - 1; i >= index; i--)
+ if (_rows[i].Height.IsAuto)
+ return _rows[i];
+ return null;
+ }
+
+ double GetUnassignedHeight(double heightRequest)
+ {
+ double assigned = (_rows.Count - 1) * RowSpacing;
+ for (var i = 0; i < _rows.Count; i++)
+ {
+ double actual = _rows[i].ActualHeight;
+ if (actual >= 0)
+ assigned += actual;
+ }
+ return heightRequest - assigned;
+ }
+
+ double GetUnassignedWidth(double widthRequest)
+ {
+ double assigned = (_columns.Count - 1) * ColumnSpacing;
+ for (var i = 0; i < _columns.Count; i++)
+ {
+ double actual = _columns[i].ActualWidth;
+ if (actual >= 0)
+ assigned += actual;
+ }
+ return widthRequest - assigned;
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/GridLength.cs b/Xamarin.Forms.Core/GridLength.cs
new file mode 100644
index 00000000..5d569d08
--- /dev/null
+++ b/Xamarin.Forms.Core/GridLength.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Diagnostics;
+
+namespace Xamarin.Forms
+{
+ [TypeConverter(typeof(GridLengthTypeConverter))]
+ [DebuggerDisplay("{Value}.{GridUnitType}")]
+ public struct GridLength
+ {
+ public static GridLength Auto
+ {
+ get { return new GridLength(1, GridUnitType.Auto); }
+ }
+
+ public double Value { get; }
+
+ public GridUnitType GridUnitType { get; }
+
+ public bool IsAbsolute
+ {
+ get { return GridUnitType == GridUnitType.Absolute; }
+ }
+
+ public bool IsAuto
+ {
+ get { return GridUnitType == GridUnitType.Auto; }
+ }
+
+ public bool IsStar
+ {
+ get { return GridUnitType == GridUnitType.Star; }
+ }
+
+ public GridLength(double value) : this(value, GridUnitType.Absolute)
+ {
+ }
+
+ public GridLength(double value, GridUnitType type)
+ {
+ if (value < 0 || double.IsNaN(value))
+ throw new ArgumentException("value is less than 0 or is not a number", "value");
+ if ((int)type < (int)GridUnitType.Absolute || (int)type > (int)GridUnitType.Auto)
+ throw new ArgumentException("type is not a valid GridUnitType", "type");
+
+ Value = value;
+ GridUnitType = type;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj != null && obj is GridLength && Equals((GridLength)obj);
+ }
+
+ bool Equals(GridLength other)
+ {
+ return GridUnitType == other.GridUnitType && Math.Abs(Value - other.Value) < double.Epsilon;
+ }
+
+ public override int GetHashCode()
+ {
+ return GridUnitType.GetHashCode() * 397 ^ Value.GetHashCode();
+ }
+
+ public static implicit operator GridLength(double absoluteValue)
+ {
+ return new GridLength(absoluteValue);
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{0}.{1}", Value, GridUnitType);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/GridLengthTypeConverter.cs b/Xamarin.Forms.Core/GridLengthTypeConverter.cs
new file mode 100644
index 00000000..7c58b417
--- /dev/null
+++ b/Xamarin.Forms.Core/GridLengthTypeConverter.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Globalization;
+
+namespace Xamarin.Forms
+{
+ public class GridLengthTypeConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString(string value)
+ {
+ if (value == null)
+ return null;
+
+ double length;
+ value = value.Trim();
+ if (string.Compare(value, "auto", StringComparison.OrdinalIgnoreCase) == 0)
+ return GridLength.Auto;
+ if (string.Compare(value, "*", StringComparison.OrdinalIgnoreCase) == 0)
+ return new GridLength(1, GridUnitType.Star);
+ if (value.EndsWith("*", StringComparison.Ordinal) && double.TryParse(value.Substring(0, value.Length - 1), NumberStyles.Number, CultureInfo.InvariantCulture, out length))
+ return new GridLength(length, GridUnitType.Star);
+ if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out length))
+ return new GridLength(length);
+
+ throw new FormatException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/GridUnitType.cs b/Xamarin.Forms.Core/GridUnitType.cs
new file mode 100644
index 00000000..372c1804
--- /dev/null
+++ b/Xamarin.Forms.Core/GridUnitType.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Forms
+{
+ public enum GridUnitType
+ {
+ Absolute,
+ Star,
+ Auto
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/HandlerAttribute.cs b/Xamarin.Forms.Core/HandlerAttribute.cs
new file mode 100644
index 00000000..b9dc9ecb
--- /dev/null
+++ b/Xamarin.Forms.Core/HandlerAttribute.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public abstract class HandlerAttribute : Attribute
+ {
+ protected HandlerAttribute(Type handler, Type target)
+ {
+ TargetType = target;
+ HandlerType = handler;
+ }
+
+ internal Type HandlerType { get; private set; }
+
+ internal Type TargetType { get; private set; }
+
+ public virtual bool ShouldRegister()
+ {
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/HtmlWebViewSource.cs b/Xamarin.Forms.Core/HtmlWebViewSource.cs
new file mode 100644
index 00000000..157e5054
--- /dev/null
+++ b/Xamarin.Forms.Core/HtmlWebViewSource.cs
@@ -0,0 +1,28 @@
+namespace Xamarin.Forms
+{
+ public class HtmlWebViewSource : WebViewSource
+ {
+ public static readonly BindableProperty HtmlProperty = BindableProperty.Create("Html", typeof(string), typeof(HtmlWebViewSource), default(string),
+ propertyChanged: (bindable, oldvalue, newvalue) => ((HtmlWebViewSource)bindable).OnSourceChanged());
+
+ public static readonly BindableProperty BaseUrlProperty = BindableProperty.Create("BaseUrl", typeof(string), typeof(HtmlWebViewSource), default(string),
+ propertyChanged: (bindable, oldvalue, newvalue) => ((HtmlWebViewSource)bindable).OnSourceChanged());
+
+ public string BaseUrl
+ {
+ get { return (string)GetValue(BaseUrlProperty); }
+ set { SetValue(BaseUrlProperty, value); }
+ }
+
+ public string Html
+ {
+ get { return (string)GetValue(HtmlProperty); }
+ set { SetValue(HtmlProperty, value); }
+ }
+
+ internal override void Load(IWebViewRenderer renderer)
+ {
+ renderer.LoadHtml(Html, BaseUrl);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IAnimatable.cs b/Xamarin.Forms.Core/IAnimatable.cs
new file mode 100644
index 00000000..2e57c2e5
--- /dev/null
+++ b/Xamarin.Forms.Core/IAnimatable.cs
@@ -0,0 +1,34 @@
+//
+// IAnimatable.cs
+//
+// Author:
+// Jason Smith <jason.smith@xamarin.com>
+//
+// Copyright (c) 2012 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+namespace Xamarin.Forms
+{
+ public interface IAnimatable
+ {
+ void BatchBegin();
+ void BatchCommit();
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IApplicationController.cs b/Xamarin.Forms.Core/IApplicationController.cs
new file mode 100644
index 00000000..201032f9
--- /dev/null
+++ b/Xamarin.Forms.Core/IApplicationController.cs
@@ -0,0 +1,6 @@
+namespace Xamarin.Forms
+{
+ public interface IApplicationController
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IButtonController.cs b/Xamarin.Forms.Core/IButtonController.cs
new file mode 100644
index 00000000..2fa1737f
--- /dev/null
+++ b/Xamarin.Forms.Core/IButtonController.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms
+{
+ internal interface IButtonController : IViewController
+ {
+ void SendClicked();
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ICarouselViewController.cs b/Xamarin.Forms.Core/ICarouselViewController.cs
new file mode 100644
index 00000000..f59bc3d3
--- /dev/null
+++ b/Xamarin.Forms.Core/ICarouselViewController.cs
@@ -0,0 +1,10 @@
+namespace Xamarin.Forms
+{
+ public interface ICarouselViewController : IItemViewController
+ {
+ void SendPositionAppearing(int position);
+ void SendPositionDisappearing(int position);
+ void SendSelectedItemChanged(object item);
+ void SendSelectedPositionChanged(int position);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IControlTemplated.cs b/Xamarin.Forms.Core/IControlTemplated.cs
new file mode 100644
index 00000000..f5798c2e
--- /dev/null
+++ b/Xamarin.Forms.Core/IControlTemplated.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ internal interface IControlTemplated
+ {
+ ControlTemplate ControlTemplate { get; set; }
+
+ IList<Element> InternalChildren { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IDefinition.cs b/Xamarin.Forms.Core/IDefinition.cs
new file mode 100644
index 00000000..6971d611
--- /dev/null
+++ b/Xamarin.Forms.Core/IDefinition.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public interface IDefinition
+ {
+ event EventHandler SizeChanged;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IDeserializer.cs b/Xamarin.Forms.Core/IDeserializer.cs
new file mode 100644
index 00000000..60478e1b
--- /dev/null
+++ b/Xamarin.Forms.Core/IDeserializer.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ internal interface IDeserializer
+ {
+ Task<IDictionary<string, object>> DeserializePropertiesAsync();
+ Task SerializePropertiesAsync(IDictionary<string, object> properties);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IEffectControlProvider.cs b/Xamarin.Forms.Core/IEffectControlProvider.cs
new file mode 100644
index 00000000..f1882f5f
--- /dev/null
+++ b/Xamarin.Forms.Core/IEffectControlProvider.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms
+{
+ public interface IEffectControlProvider
+ {
+ void RegisterEffect(Effect effect);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IElement.cs b/Xamarin.Forms.Core/IElement.cs
new file mode 100644
index 00000000..ee302b5f
--- /dev/null
+++ b/Xamarin.Forms.Core/IElement.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ internal interface IElement
+ {
+ Element Parent { get; set; }
+
+ //Use these 2 instead of an event to avoid cloning way too much multicastdelegates on mono
+ void AddResourcesChangedListener(Action<object, ResourcesChangedEventArgs> onchanged);
+ void RemoveResourcesChangedListener(Action<object, ResourcesChangedEventArgs> onchanged);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IElementController.cs b/Xamarin.Forms.Core/IElementController.cs
new file mode 100644
index 00000000..4e1ab10d
--- /dev/null
+++ b/Xamarin.Forms.Core/IElementController.cs
@@ -0,0 +1,10 @@
+namespace Xamarin.Forms
+{
+ public interface IElementController
+ {
+ IEffectControlProvider EffectControlProvider { get; set; }
+
+ void SetValueFromRenderer(BindableProperty property, object value);
+ void SetValueFromRenderer(BindablePropertyKey propertyKey, object value);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IExpressionSearch.cs b/Xamarin.Forms.Core/IExpressionSearch.cs
new file mode 100644
index 00000000..e5d4c26f
--- /dev/null
+++ b/Xamarin.Forms.Core/IExpressionSearch.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+using System.Linq.Expressions;
+
+namespace Xamarin.Forms
+{
+ internal interface IExpressionSearch
+ {
+ List<T> FindObjects<T>(Expression expression) where T : class;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IExtendedTypeConverter.cs b/Xamarin.Forms.Core/IExtendedTypeConverter.cs
new file mode 100644
index 00000000..e3b16b52
--- /dev/null
+++ b/Xamarin.Forms.Core/IExtendedTypeConverter.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Globalization;
+
+namespace Xamarin.Forms
+{
+ public interface IExtendedTypeConverter
+ {
+ [Obsolete("use ConvertFromInvariantString (string, IServiceProvider)")]
+ object ConvertFrom(CultureInfo culture, object value, IServiceProvider serviceProvider);
+
+ object ConvertFromInvariantString(string value, IServiceProvider serviceProvider);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IFontElement.cs b/Xamarin.Forms.Core/IFontElement.cs
new file mode 100644
index 00000000..f1f3a36f
--- /dev/null
+++ b/Xamarin.Forms.Core/IFontElement.cs
@@ -0,0 +1,11 @@
+namespace Xamarin.Forms
+{
+ internal interface IFontElement
+ {
+ FontAttributes FontAttributes { get; }
+
+ string FontFamily { get; }
+
+ double FontSize { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IGestureRecognizer.cs b/Xamarin.Forms.Core/IGestureRecognizer.cs
new file mode 100644
index 00000000..4e361c0a
--- /dev/null
+++ b/Xamarin.Forms.Core/IGestureRecognizer.cs
@@ -0,0 +1,8 @@
+using System.ComponentModel;
+
+namespace Xamarin.Forms
+{
+ public interface IGestureRecognizer : INotifyPropertyChanged
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IIsolatedStorageFile.cs b/Xamarin.Forms.Core/IIsolatedStorageFile.cs
new file mode 100644
index 00000000..50899023
--- /dev/null
+++ b/Xamarin.Forms.Core/IIsolatedStorageFile.cs
@@ -0,0 +1,18 @@
+using System;
+using System.IO;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ internal interface IIsolatedStorageFile
+ {
+ Task CreateDirectoryAsync(string path);
+ Task<bool> GetDirectoryExistsAsync(string path);
+ Task<bool> GetFileExistsAsync(string path);
+
+ Task<DateTimeOffset> GetLastWriteTimeAsync(string path);
+
+ Task<Stream> OpenFileAsync(string path, FileMode mode, FileAccess access);
+ Task<Stream> OpenFileAsync(string path, FileMode mode, FileAccess access, FileShare share);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IItemViewController.cs b/Xamarin.Forms.Core/IItemViewController.cs
new file mode 100644
index 00000000..79f711e9
--- /dev/null
+++ b/Xamarin.Forms.Core/IItemViewController.cs
@@ -0,0 +1,10 @@
+namespace Xamarin.Forms
+{
+ public interface IItemViewController
+ {
+ void BindView(View view, object item);
+ View CreateView(object itemType);
+ object GetItem(int index);
+ object GetItemType(object item);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IItemsView.cs b/Xamarin.Forms.Core/IItemsView.cs
new file mode 100644
index 00000000..7f968769
--- /dev/null
+++ b/Xamarin.Forms.Core/IItemsView.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Forms
+{
+ internal interface IItemsView<T> where T : BindableObject
+ {
+ T CreateDefault(object item);
+ void SetupContent(T content, int index);
+ void UnhookContent(T content);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ILayout.cs b/Xamarin.Forms.Core/ILayout.cs
new file mode 100644
index 00000000..781111a8
--- /dev/null
+++ b/Xamarin.Forms.Core/ILayout.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public interface ILayout
+ {
+ event EventHandler LayoutChanged;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ILayoutController.cs b/Xamarin.Forms.Core/ILayoutController.cs
new file mode 100644
index 00000000..56bff7e0
--- /dev/null
+++ b/Xamarin.Forms.Core/ILayoutController.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ public interface ILayoutController
+ {
+ IReadOnlyList<Element> Children { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IListViewController.cs b/Xamarin.Forms.Core/IListViewController.cs
new file mode 100644
index 00000000..078f13b7
--- /dev/null
+++ b/Xamarin.Forms.Core/IListViewController.cs
@@ -0,0 +1,15 @@
+namespace Xamarin.Forms
+{
+ internal interface IListViewController : IViewController
+ {
+ Element FooterElement { get; }
+
+ Element HeaderElement { get; }
+
+ bool RefreshAllowed { get; }
+
+ void SendCellAppearing(Cell cell);
+ void SendCellDisappearing(Cell cell);
+ void SendRefreshing();
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IMarkupExtension.cs b/Xamarin.Forms.Core/IMarkupExtension.cs
new file mode 100644
index 00000000..24a435f9
--- /dev/null
+++ b/Xamarin.Forms.Core/IMarkupExtension.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Xamarin.Forms.Xaml
+{
+ public interface IMarkupExtension<out T> : IMarkupExtension
+ {
+ new T ProvideValue(IServiceProvider serviceProvider);
+ }
+
+ public interface IMarkupExtension
+ {
+ object ProvideValue(IServiceProvider serviceProvider);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/INavigation.cs b/Xamarin.Forms.Core/INavigation.cs
new file mode 100644
index 00000000..6ae5959d
--- /dev/null
+++ b/Xamarin.Forms.Core/INavigation.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ public interface INavigation
+ {
+ IReadOnlyList<Page> ModalStack { get; }
+
+ IReadOnlyList<Page> NavigationStack { get; }
+
+ void InsertPageBefore(Page page, Page before);
+ Task<Page> PopAsync();
+ Task<Page> PopAsync(bool animated);
+ Task<Page> PopModalAsync();
+ Task<Page> PopModalAsync(bool animated);
+ Task PopToRootAsync();
+ Task PopToRootAsync(bool animated);
+
+ Task PushAsync(Page page);
+
+ Task PushAsync(Page page, bool animated);
+ Task PushModalAsync(Page page);
+ Task PushModalAsync(Page page, bool animated);
+
+ void RemovePage(Page page);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IOpenGlViewController.cs b/Xamarin.Forms.Core/IOpenGlViewController.cs
new file mode 100644
index 00000000..d89c5fef
--- /dev/null
+++ b/Xamarin.Forms.Core/IOpenGlViewController.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public interface IOpenGlViewController : IViewController
+ {
+ event EventHandler DisplayRequested;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IPageContainer.cs b/Xamarin.Forms.Core/IPageContainer.cs
new file mode 100644
index 00000000..9582e5e2
--- /dev/null
+++ b/Xamarin.Forms.Core/IPageContainer.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms
+{
+ public interface IPageContainer<out T> where T : Page
+ {
+ T CurrentPage { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IPanGestureController.cs b/Xamarin.Forms.Core/IPanGestureController.cs
new file mode 100644
index 00000000..96283092
--- /dev/null
+++ b/Xamarin.Forms.Core/IPanGestureController.cs
@@ -0,0 +1,13 @@
+namespace Xamarin.Forms
+{
+ internal interface IPanGestureController
+ {
+ void SendPan(Element sender, double totalX, double totalY, int gestureId);
+
+ void SendPanCanceled(Element sender, int gestureId);
+
+ void SendPanCompleted(Element sender, int gestureId);
+
+ void SendPanStarted(Element sender, int gestureId);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IPinchGestureController.cs b/Xamarin.Forms.Core/IPinchGestureController.cs
new file mode 100644
index 00000000..9848fa74
--- /dev/null
+++ b/Xamarin.Forms.Core/IPinchGestureController.cs
@@ -0,0 +1,15 @@
+namespace Xamarin.Forms
+{
+ internal interface IPinchGestureController
+ {
+ bool IsPinching { get; set; }
+
+ void SendPinch(Element sender, double scale, Point currentScalePoint);
+
+ void SendPinchCanceled(Element sender);
+
+ void SendPinchEnded(Element sender);
+
+ void SendPinchStarted(Element sender, Point intialScalePoint);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IPlatform.cs b/Xamarin.Forms.Core/IPlatform.cs
new file mode 100644
index 00000000..507abcfe
--- /dev/null
+++ b/Xamarin.Forms.Core/IPlatform.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms
+{
+ internal interface IPlatform
+ {
+ SizeRequest GetNativeSize(VisualElement view, double widthConstraint, double heightConstraint);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IPlatformServices.cs b/Xamarin.Forms.Core/IPlatformServices.cs
new file mode 100644
index 00000000..e4a3ce0b
--- /dev/null
+++ b/Xamarin.Forms.Core/IPlatformServices.cs
@@ -0,0 +1,36 @@
+using System;
+using System.IO;
+using System.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ internal interface IPlatformServices
+ {
+ bool IsInvokeRequired { get; }
+
+ void BeginInvokeOnMainThread(Action action);
+
+ //this will go once Timer is included in Pcl profiles
+ ITimer CreateTimer(Action<object> callback);
+ ITimer CreateTimer(Action<object> callback, object state, int dueTime, int period);
+ ITimer CreateTimer(Action<object> callback, object state, long dueTime, long period);
+ ITimer CreateTimer(Action<object> callback, object state, TimeSpan dueTime, TimeSpan period);
+ ITimer CreateTimer(Action<object> callback, object state, uint dueTime, uint period);
+
+ Assembly[] GetAssemblies();
+
+ string GetMD5Hash(string input);
+
+ double GetNamedSize(NamedSize size, Type targetElementType, bool useOldSizes);
+
+ Task<Stream> GetStreamAsync(Uri uri, CancellationToken cancellationToken);
+
+ IIsolatedStorageFile GetUserStoreForApplication();
+
+ void OpenUriAction(Uri uri);
+
+ void StartTimer(TimeSpan interval, Func<bool> callback);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IProvideParentValues.cs b/Xamarin.Forms.Core/IProvideParentValues.cs
new file mode 100644
index 00000000..c07c606f
--- /dev/null
+++ b/Xamarin.Forms.Core/IProvideParentValues.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal interface IProvideParentValues : IProvideValueTarget
+ {
+ IEnumerable<object> ParentObjects { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IProvideValueTarget.cs b/Xamarin.Forms.Core/IProvideValueTarget.cs
new file mode 100644
index 00000000..b8324b5e
--- /dev/null
+++ b/Xamarin.Forms.Core/IProvideValueTarget.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Forms.Xaml
+{
+ public interface IProvideValueTarget
+ {
+ object TargetObject { get; }
+
+ object TargetProperty { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IRegisterable.cs b/Xamarin.Forms.Core/IRegisterable.cs
new file mode 100644
index 00000000..995ebbce
--- /dev/null
+++ b/Xamarin.Forms.Core/IRegisterable.cs
@@ -0,0 +1,6 @@
+namespace Xamarin.Forms
+{
+ public interface IRegisterable
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IResourceDictionary.cs b/Xamarin.Forms.Core/IResourceDictionary.cs
new file mode 100644
index 00000000..5fccb9d9
--- /dev/null
+++ b/Xamarin.Forms.Core/IResourceDictionary.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ internal interface IResourceDictionary : IEnumerable<KeyValuePair<string, object>>
+ {
+ bool TryGetValue(string key, out object value);
+
+ event EventHandler<ResourcesChangedEventArgs> ValuesChanged;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IResourcesProvider.cs b/Xamarin.Forms.Core/IResourcesProvider.cs
new file mode 100644
index 00000000..e06ef743
--- /dev/null
+++ b/Xamarin.Forms.Core/IResourcesProvider.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms
+{
+ internal interface IResourcesProvider
+ {
+ ResourceDictionary Resources { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IRootObjectProvider.cs b/Xamarin.Forms.Core/IRootObjectProvider.cs
new file mode 100644
index 00000000..883033a5
--- /dev/null
+++ b/Xamarin.Forms.Core/IRootObjectProvider.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms.Xaml
+{
+ public interface IRootObjectProvider
+ {
+ object RootObject { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IScrollViewController.cs b/Xamarin.Forms.Core/IScrollViewController.cs
new file mode 100644
index 00000000..c06ddc09
--- /dev/null
+++ b/Xamarin.Forms.Core/IScrollViewController.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public interface IScrollViewController : ILayoutController
+ {
+ Point GetScrollPositionForElement(VisualElement item, ScrollToPosition position);
+
+ event EventHandler<ScrollToRequestedEventArgs> ScrollToRequested;
+
+ void SendScrollFinished();
+
+ void SetScrolledPosition(double x, double y);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IStyle.cs b/Xamarin.Forms.Core/IStyle.cs
new file mode 100644
index 00000000..cdb998dc
--- /dev/null
+++ b/Xamarin.Forms.Core/IStyle.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ internal interface IStyle
+ {
+ Type TargetType { get; }
+
+ void Apply(BindableObject bindable);
+ void UnApply(BindableObject bindable);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ISystemResourcesProvider.cs b/Xamarin.Forms.Core/ISystemResourcesProvider.cs
new file mode 100644
index 00000000..9f0e5772
--- /dev/null
+++ b/Xamarin.Forms.Core/ISystemResourcesProvider.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms
+{
+ internal interface ISystemResourcesProvider
+ {
+ IResourceDictionary GetSystemResources();
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ITimer.cs b/Xamarin.Forms.Core/ITimer.cs
new file mode 100644
index 00000000..ba867dba
--- /dev/null
+++ b/Xamarin.Forms.Core/ITimer.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ //this will go once Timer is included in Pcl profiles
+ internal interface ITimer
+ {
+ void Change(int dueTime, int period);
+ void Change(long dueTime, long period);
+ void Change(TimeSpan dueTime, TimeSpan period);
+ void Change(uint dueTime, uint period);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IValueConverter.cs b/Xamarin.Forms.Core/IValueConverter.cs
new file mode 100644
index 00000000..8702ec3d
--- /dev/null
+++ b/Xamarin.Forms.Core/IValueConverter.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Globalization;
+
+namespace Xamarin.Forms
+{
+ public interface IValueConverter
+ {
+ object Convert(object value, Type targetType, object parameter, CultureInfo culture);
+ object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IValueConverterProvider.cs b/Xamarin.Forms.Core/IValueConverterProvider.cs
new file mode 100644
index 00000000..1221ce74
--- /dev/null
+++ b/Xamarin.Forms.Core/IValueConverterProvider.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Reflection;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal interface IValueConverterProvider
+ {
+ object Convert(object value, Type toType, Func<MemberInfo> minfoRetriever, IServiceProvider serviceProvider);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IValueProvider.cs b/Xamarin.Forms.Core/IValueProvider.cs
new file mode 100644
index 00000000..19d3bf93
--- /dev/null
+++ b/Xamarin.Forms.Core/IValueProvider.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Xamarin.Forms.Xaml
+{
+ public interface IValueProvider
+ {
+ object ProvideValue(IServiceProvider serviceProvider);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IViewContainer.cs b/Xamarin.Forms.Core/IViewContainer.cs
new file mode 100644
index 00000000..9b2e0570
--- /dev/null
+++ b/Xamarin.Forms.Core/IViewContainer.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ public interface IViewContainer<T> where T : VisualElement
+ {
+ IList<T> Children { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IViewController.cs b/Xamarin.Forms.Core/IViewController.cs
new file mode 100644
index 00000000..1d956387
--- /dev/null
+++ b/Xamarin.Forms.Core/IViewController.cs
@@ -0,0 +1,6 @@
+namespace Xamarin.Forms
+{
+ public interface IViewController : IVisualElementController
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IVisualElementController.cs b/Xamarin.Forms.Core/IVisualElementController.cs
new file mode 100644
index 00000000..03be293a
--- /dev/null
+++ b/Xamarin.Forms.Core/IVisualElementController.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms
+{
+ public interface IVisualElementController : IElementController
+ {
+ void NativeSizeChanged();
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IWebViewRenderer.cs b/Xamarin.Forms.Core/IWebViewRenderer.cs
new file mode 100644
index 00000000..0b1b3db5
--- /dev/null
+++ b/Xamarin.Forms.Core/IWebViewRenderer.cs
@@ -0,0 +1,8 @@
+namespace Xamarin.Forms
+{
+ internal interface IWebViewRenderer
+ {
+ void LoadHtml(string html, string baseUrl);
+ void LoadUrl(string url);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IXamlTypeResolver.cs b/Xamarin.Forms.Core/IXamlTypeResolver.cs
new file mode 100644
index 00000000..1708e0b1
--- /dev/null
+++ b/Xamarin.Forms.Core/IXamlTypeResolver.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Xamarin.Forms.Xaml
+{
+ public interface IXamlTypeResolver
+ {
+ Type Resolve(string qualifiedTypeName, IServiceProvider serviceProvider = null);
+ bool TryResolve(string qualifiedTypeName, out Type type);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/IXmlLineInfoProvider.cs b/Xamarin.Forms.Core/IXmlLineInfoProvider.cs
new file mode 100644
index 00000000..348f4d4d
--- /dev/null
+++ b/Xamarin.Forms.Core/IXmlLineInfoProvider.cs
@@ -0,0 +1,9 @@
+using System.Xml;
+
+namespace Xamarin.Forms.Xaml
+{
+ public interface IXmlLineInfoProvider
+ {
+ IXmlLineInfo XmlLineInfo { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Image.cs b/Xamarin.Forms.Core/Image.cs
new file mode 100644
index 00000000..9e329331
--- /dev/null
+++ b/Xamarin.Forms.Core/Image.cs
@@ -0,0 +1,145 @@
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_ImageRenderer))]
+ public class Image : View
+ {
+ public static readonly BindableProperty SourceProperty = BindableProperty.Create("Source", typeof(ImageSource), typeof(Image), default(ImageSource), propertyChanging: OnSourcePropertyChanging,
+ propertyChanged: OnSourcePropertyChanged);
+
+ public static readonly BindableProperty AspectProperty = BindableProperty.Create("Aspect", typeof(Aspect), typeof(Image), Aspect.AspectFit);
+
+ public static readonly BindableProperty IsOpaqueProperty = BindableProperty.Create("IsOpaque", typeof(bool), typeof(Image), false);
+
+ internal static readonly BindablePropertyKey IsLoadingPropertyKey = BindableProperty.CreateReadOnly("IsLoading", typeof(bool), typeof(Image), default(bool));
+
+ public static readonly BindableProperty IsLoadingProperty = IsLoadingPropertyKey.BindableProperty;
+
+ public Aspect Aspect
+ {
+ get { return (Aspect)GetValue(AspectProperty); }
+ set { SetValue(AspectProperty, value); }
+ }
+
+ public bool IsLoading
+ {
+ get { return (bool)GetValue(IsLoadingProperty); }
+ }
+
+ public bool IsOpaque
+ {
+ get { return (bool)GetValue(IsOpaqueProperty); }
+ set { SetValue(IsOpaqueProperty, value); }
+ }
+
+ [TypeConverter(typeof(ImageSourceConverter))]
+ public ImageSource Source
+ {
+ get { return (ImageSource)GetValue(SourceProperty); }
+ set { SetValue(SourceProperty, value); }
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ if (Source != null)
+ SetInheritedBindingContext(Source, BindingContext);
+
+ base.OnBindingContextChanged();
+ }
+
+ [Obsolete("Use OnMeasure")]
+ protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ SizeRequest desiredSize = base.OnSizeRequest(double.PositiveInfinity, double.PositiveInfinity);
+
+ double desiredAspect = desiredSize.Request.Width / desiredSize.Request.Height;
+ double constraintAspect = widthConstraint / heightConstraint;
+
+ double desiredWidth = desiredSize.Request.Width;
+ double desiredHeight = desiredSize.Request.Height;
+
+ if (desiredWidth == 0 || desiredHeight == 0)
+ return new SizeRequest(new Size(0, 0));
+
+ double width = desiredWidth;
+ double height = desiredHeight;
+ if (constraintAspect > desiredAspect)
+ {
+ // constraint area is proportionally wider than image
+ switch (Aspect)
+ {
+ case Aspect.AspectFit:
+ case Aspect.AspectFill:
+ height = Math.Min(desiredHeight, heightConstraint);
+ width = desiredWidth * (height / desiredHeight);
+ break;
+ case Aspect.Fill:
+ width = Math.Min(desiredWidth, widthConstraint);
+ height = desiredHeight * (width / desiredWidth);
+ break;
+ }
+ }
+ else if (constraintAspect < desiredAspect)
+ {
+ // constraint area is proportionally taller than image
+ switch (Aspect)
+ {
+ case Aspect.AspectFit:
+ case Aspect.AspectFill:
+ width = Math.Min(desiredWidth, widthConstraint);
+ height = desiredHeight * (width / desiredWidth);
+ break;
+ case Aspect.Fill:
+ height = Math.Min(desiredHeight, heightConstraint);
+ width = desiredWidth * (height / desiredHeight);
+ break;
+ }
+ }
+ else
+ {
+ // constraint area is same aspect as image
+ width = Math.Min(desiredWidth, widthConstraint);
+ height = desiredHeight * (width / desiredWidth);
+ }
+
+ return new SizeRequest(new Size(width, height));
+ }
+
+ void OnSourceChanged(object sender, EventArgs eventArgs)
+ {
+ OnPropertyChanged(SourceProperty.PropertyName);
+ InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+
+ static void OnSourcePropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
+ {
+ ((Image)bindable).OnSourcePropertyChanged((ImageSource)oldvalue, (ImageSource)newvalue);
+ }
+
+ void OnSourcePropertyChanged(ImageSource oldvalue, ImageSource newvalue)
+ {
+ if (newvalue != null)
+ {
+ newvalue.SourceChanged += OnSourceChanged;
+ SetInheritedBindingContext(newvalue, BindingContext);
+ }
+ InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+
+ static void OnSourcePropertyChanging(BindableObject bindable, object oldvalue, object newvalue)
+ {
+ ((Image)bindable).OnSourcePropertyChanging((ImageSource)oldvalue, (ImageSource)newvalue);
+ }
+
+ async void OnSourcePropertyChanging(ImageSource oldvalue, ImageSource newvalue)
+ {
+ if (oldvalue == null)
+ return;
+
+ oldvalue.SourceChanged -= OnSourceChanged;
+ await oldvalue.Cancel();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ImageSource.cs b/Xamarin.Forms.Core/ImageSource.cs
new file mode 100644
index 00000000..71e75952
--- /dev/null
+++ b/Xamarin.Forms.Core/ImageSource.cs
@@ -0,0 +1,142 @@
+using System;
+using System.IO;
+using System.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ [TypeConverter(typeof(ImageSourceConverter))]
+ public abstract class ImageSource : Element
+ {
+ readonly object _synchandle = new object();
+ CancellationTokenSource _cancellationTokenSource;
+
+ TaskCompletionSource<bool> _completionSource;
+
+ internal ImageSource()
+ {
+ }
+
+ protected CancellationTokenSource CancellationTokenSource
+ {
+ get { return _cancellationTokenSource; }
+ private set
+ {
+ if (_cancellationTokenSource == value)
+ return;
+ if (_cancellationTokenSource != null)
+ _cancellationTokenSource.Cancel();
+ _cancellationTokenSource = value;
+ }
+ }
+
+ bool IsLoading
+ {
+ get { return _cancellationTokenSource != null; }
+ }
+
+ public virtual Task<bool> Cancel()
+ {
+ if (!IsLoading)
+ return Task.FromResult(false);
+
+ var tcs = new TaskCompletionSource<bool>();
+ TaskCompletionSource<bool> original = Interlocked.CompareExchange(ref _completionSource, tcs, null);
+ if (original == null)
+ {
+ _cancellationTokenSource.Cancel();
+ }
+ else
+ tcs = original;
+
+ return tcs.Task;
+ }
+
+ public static ImageSource FromFile(string file)
+ {
+ return new FileImageSource { File = file };
+ }
+
+ public static ImageSource FromResource(string resource, Type resolvingType)
+ {
+ return FromResource(resource, resolvingType.GetTypeInfo().Assembly);
+ }
+
+ public static ImageSource FromResource(string resource, Assembly sourceAssembly = null)
+ {
+ if (sourceAssembly == null)
+ {
+ MethodInfo callingAssemblyMethod = typeof(Assembly).GetTypeInfo().GetDeclaredMethod("GetCallingAssembly");
+ if (callingAssemblyMethod != null)
+ {
+ sourceAssembly = (Assembly)callingAssemblyMethod.Invoke(null, new object[0]);
+ }
+ else
+ {
+ Log.Warning("Warning", "Can not find CallingAssembly, pass resolvingType to FromResource to ensure proper resolution");
+ return null;
+ }
+ }
+
+ return FromStream(() => sourceAssembly.GetManifestResourceStream(resource));
+ }
+
+ public static ImageSource FromStream(Func<Stream> stream)
+ {
+ return new StreamImageSource { Stream = token => Task.Run(stream, token) };
+ }
+
+ public static ImageSource FromUri(Uri uri)
+ {
+ if (!uri.IsAbsoluteUri)
+ throw new ArgumentException("uri is relative");
+ return new UriImageSource { Uri = uri };
+ }
+
+ public static implicit operator ImageSource(string source)
+ {
+ Uri uri;
+ return Uri.TryCreate(source, UriKind.Absolute, out uri) && uri.Scheme != "file" ? FromUri(uri) : FromFile(source);
+ }
+
+ public static implicit operator ImageSource(Uri uri)
+ {
+ if (!uri.IsAbsoluteUri)
+ throw new ArgumentException("uri is relative");
+ return FromUri(uri);
+ }
+
+ protected void OnLoadingCompleted(bool cancelled)
+ {
+ if (!IsLoading || _completionSource == null)
+ return;
+
+ TaskCompletionSource<bool> tcs = Interlocked.Exchange(ref _completionSource, null);
+ if (tcs != null)
+ tcs.SetResult(cancelled);
+
+ lock(_synchandle)
+ {
+ CancellationTokenSource = null;
+ }
+ }
+
+ protected void OnLoadingStarted()
+ {
+ lock(_synchandle)
+ {
+ CancellationTokenSource = new CancellationTokenSource();
+ }
+ }
+
+ protected void OnSourceChanged()
+ {
+ EventHandler eh = SourceChanged;
+ if (eh != null)
+ eh(this, EventArgs.Empty);
+ }
+
+ internal event EventHandler SourceChanged;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ImageSourceConverter.cs b/Xamarin.Forms.Core/ImageSourceConverter.cs
new file mode 100644
index 00000000..8ca829f7
--- /dev/null
+++ b/Xamarin.Forms.Core/ImageSourceConverter.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public sealed class ImageSourceConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString(string value)
+ {
+ if (value != null)
+ {
+ Uri uri;
+ return Uri.TryCreate(value, UriKind.Absolute, out uri) && uri.Scheme != "file" ? ImageSource.FromUri(uri) : ImageSource.FromFile(value);
+ }
+
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(ImageSource)));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/InputView.cs b/Xamarin.Forms.Core/InputView.cs
new file mode 100644
index 00000000..58b75c42
--- /dev/null
+++ b/Xamarin.Forms.Core/InputView.cs
@@ -0,0 +1,18 @@
+namespace Xamarin.Forms
+{
+ public class InputView : View
+ {
+ public static readonly BindableProperty KeyboardProperty = BindableProperty.Create("Keyboard", typeof(Keyboard), typeof(InputView), Keyboard.Default,
+ coerceValue: (o, v) => (Keyboard)v ?? Keyboard.Default);
+
+ internal InputView()
+ {
+ }
+
+ public Keyboard Keyboard
+ {
+ get { return (Keyboard)GetValue(KeyboardProperty); }
+ set { SetValue(KeyboardProperty, value); }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Interactivity/AttachedCollection.cs b/Xamarin.Forms.Core/Interactivity/AttachedCollection.cs
new file mode 100644
index 00000000..6aff5147
--- /dev/null
+++ b/Xamarin.Forms.Core/Interactivity/AttachedCollection.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace Xamarin.Forms
+{
+ internal class AttachedCollection<T> : ObservableCollection<T>, ICollection<T>, IAttachedObject where T : BindableObject, IAttachedObject
+ {
+ readonly List<WeakReference> _associatedObjects = new List<WeakReference>();
+
+ public AttachedCollection()
+ {
+ }
+
+ public AttachedCollection(IEnumerable<T> collection) : base(collection)
+ {
+ }
+
+ public AttachedCollection(IList<T> list) : base(list)
+ {
+ }
+
+ public void AttachTo(BindableObject bindable)
+ {
+ if (bindable == null)
+ throw new ArgumentNullException("bindable");
+ OnAttachedTo(bindable);
+ }
+
+ public void DetachFrom(BindableObject bindable)
+ {
+ OnDetachingFrom(bindable);
+ }
+
+ protected override void ClearItems()
+ {
+ foreach (WeakReference weakbindable in _associatedObjects)
+ {
+ foreach (T item in this)
+ {
+ var bindable = weakbindable.Target as BindableObject;
+ if (bindable == null)
+ continue;
+ item.DetachFrom(bindable);
+ }
+ }
+ base.ClearItems();
+ }
+
+ protected override void InsertItem(int index, T item)
+ {
+ base.InsertItem(index, item);
+ foreach (WeakReference weakbindable in _associatedObjects)
+ {
+ var bindable = weakbindable.Target as BindableObject;
+ if (bindable == null)
+ continue;
+ item.AttachTo(bindable);
+ }
+ }
+
+ protected virtual void OnAttachedTo(BindableObject bindable)
+ {
+ lock(_associatedObjects)
+ {
+ _associatedObjects.Add(new WeakReference(bindable));
+ }
+ foreach (T item in this)
+ item.AttachTo(bindable);
+ }
+
+ protected virtual void OnDetachingFrom(BindableObject bindable)
+ {
+ foreach (T item in this)
+ item.DetachFrom(bindable);
+ lock(_associatedObjects)
+ {
+ for (var i = 0; i < _associatedObjects.Count; i++)
+ {
+ object target = _associatedObjects[i].Target;
+
+ if (target == null || target == bindable)
+ {
+ _associatedObjects.RemoveAt(i);
+ i--;
+ }
+ }
+ }
+ }
+
+ protected override void RemoveItem(int index)
+ {
+ T item = this[index];
+ foreach (WeakReference weakbindable in _associatedObjects)
+ {
+ var bindable = weakbindable.Target as BindableObject;
+ if (bindable == null)
+ continue;
+ item.DetachFrom(bindable);
+ }
+
+ base.RemoveItem(index);
+ }
+
+ protected override void SetItem(int index, T item)
+ {
+ T old = this[index];
+ foreach (WeakReference weakbindable in _associatedObjects)
+ {
+ var bindable = weakbindable.Target as BindableObject;
+ if (bindable == null)
+ continue;
+ old.DetachFrom(bindable);
+ }
+
+ base.SetItem(index, item);
+
+ foreach (WeakReference weakbindable in _associatedObjects)
+ {
+ var bindable = weakbindable.Target as BindableObject;
+ if (bindable == null)
+ continue;
+ item.AttachTo(bindable);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Interactivity/Behavior.cs b/Xamarin.Forms.Core/Interactivity/Behavior.cs
new file mode 100644
index 00000000..f8689041
--- /dev/null
+++ b/Xamarin.Forms.Core/Interactivity/Behavior.cs
@@ -0,0 +1,65 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public abstract class Behavior : BindableObject, IAttachedObject
+ {
+ internal Behavior(Type associatedType)
+ {
+ if (associatedType == null)
+ throw new ArgumentNullException("associatedType");
+ AssociatedType = associatedType;
+ }
+
+ protected Type AssociatedType { get; }
+
+ void IAttachedObject.AttachTo(BindableObject bindable)
+ {
+ if (bindable == null)
+ throw new ArgumentNullException("bindable");
+ if (!AssociatedType.IsInstanceOfType(bindable))
+ throw new InvalidOperationException("bindable not an instance of AssociatedType");
+ OnAttachedTo(bindable);
+ }
+
+ void IAttachedObject.DetachFrom(BindableObject bindable)
+ {
+ OnDetachingFrom(bindable);
+ }
+
+ protected virtual void OnAttachedTo(BindableObject bindable)
+ {
+ }
+
+ protected virtual void OnDetachingFrom(BindableObject bindable)
+ {
+ }
+ }
+
+ public abstract class Behavior<T> : Behavior where T : BindableObject
+ {
+ protected Behavior() : base(typeof(T))
+ {
+ }
+
+ protected override void OnAttachedTo(BindableObject bindable)
+ {
+ base.OnAttachedTo(bindable);
+ OnAttachedTo((T)bindable);
+ }
+
+ protected virtual void OnAttachedTo(T bindable)
+ {
+ }
+
+ protected override void OnDetachingFrom(BindableObject bindable)
+ {
+ OnDetachingFrom((T)bindable);
+ base.OnDetachingFrom(bindable);
+ }
+
+ protected virtual void OnDetachingFrom(T bindable)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Interactivity/BindingCondition.cs b/Xamarin.Forms.Core/Interactivity/BindingCondition.cs
new file mode 100644
index 00000000..88b7cf36
--- /dev/null
+++ b/Xamarin.Forms.Core/Interactivity/BindingCondition.cs
@@ -0,0 +1,100 @@
+using System;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms
+{
+ public sealed class BindingCondition : Condition, IValueProvider
+ {
+ readonly BindableProperty _boundProperty;
+
+ BindingBase _binding;
+ object _triggerValue;
+
+ public BindingCondition()
+ {
+ _boundProperty = BindableProperty.CreateAttached("Bound", typeof(object), typeof(DataTrigger), null, propertyChanged: OnBoundPropertyChanged);
+ }
+
+ public BindingBase Binding
+ {
+ get { return _binding; }
+ set
+ {
+ if (_binding == value)
+ return;
+ if (IsSealed)
+ throw new InvalidOperationException("Can not change Binding once the Trigger has been applied.");
+ _binding = value;
+ }
+ }
+
+ public object Value
+ {
+ get { return _triggerValue; }
+ set
+ {
+ if (_triggerValue == value)
+ return;
+ if (IsSealed)
+ throw new InvalidOperationException("Can not change Value once the Trigger has been applied.");
+ _triggerValue = value;
+ }
+ }
+
+ internal IServiceProvider ServiceProvider { get; set; }
+
+ internal IValueConverterProvider ValueConverter { get; set; }
+
+ object IValueProvider.ProvideValue(IServiceProvider serviceProvider)
+ {
+ ValueConverter = serviceProvider.GetService(typeof(IValueConverterProvider)) as IValueConverterProvider;
+ ServiceProvider = serviceProvider;
+
+ return this;
+ }
+
+ internal override bool GetState(BindableObject bindable)
+ {
+ object newValue = bindable.GetValue(_boundProperty);
+ return EqualsToValue(newValue);
+ }
+
+ internal override void SetUp(BindableObject bindable)
+ {
+ if (Binding != null)
+ bindable.SetBinding(_boundProperty, Binding.Clone());
+ }
+
+ internal override void TearDown(BindableObject bindable)
+ {
+ bindable.RemoveBinding(_boundProperty);
+ bindable.ClearValue(_boundProperty);
+ }
+
+ bool EqualsToValue(object other)
+ {
+ if ((other == Value) || (other != null && other.Equals(Value)))
+ return true;
+
+ object converted = null;
+ if (ValueConverter != null)
+ converted = ValueConverter.Convert(Value, other != null ? other.GetType() : typeof(object), null, ServiceProvider);
+ else
+ return false;
+
+ return (other == converted) || (other != null && other.Equals(converted));
+ }
+
+ void OnBoundPropertyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ bool oldState = EqualsToValue(oldValue);
+ bool newState = EqualsToValue(newValue);
+
+ if (newState == oldState)
+ return;
+
+ if (ConditionChanged != null)
+ ConditionChanged(bindable, oldState, newState);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Interactivity/Condition.cs b/Xamarin.Forms.Core/Interactivity/Condition.cs
new file mode 100644
index 00000000..aad921cf
--- /dev/null
+++ b/Xamarin.Forms.Core/Interactivity/Condition.cs
@@ -0,0 +1,51 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public abstract class Condition
+ {
+ Action<BindableObject, bool, bool> _conditionChanged;
+
+ bool _isSealed;
+
+ internal Condition()
+ {
+ }
+
+ internal Action<BindableObject, bool, bool> ConditionChanged
+ {
+ get { return _conditionChanged; }
+ set
+ {
+ if (_conditionChanged == value)
+ return;
+ if (_conditionChanged != null)
+ throw new InvalidOperationException("The same condition instance can not be reused");
+ _conditionChanged = value;
+ }
+ }
+
+ internal bool IsSealed
+ {
+ get { return _isSealed; }
+ set
+ {
+ if (_isSealed == value)
+ return;
+ if (!value)
+ throw new InvalidOperationException("What is sealed can not be unsealed.");
+ _isSealed = value;
+ OnSealed();
+ }
+ }
+
+ internal abstract bool GetState(BindableObject bindable);
+
+ internal virtual void OnSealed()
+ {
+ }
+
+ internal abstract void SetUp(BindableObject bindable);
+ internal abstract void TearDown(BindableObject bindable);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Interactivity/DataTrigger.cs b/Xamarin.Forms.Core/Interactivity/DataTrigger.cs
new file mode 100644
index 00000000..e27ec134
--- /dev/null
+++ b/Xamarin.Forms.Core/Interactivity/DataTrigger.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("Setters")]
+ public sealed class DataTrigger : TriggerBase, IValueProvider
+ {
+ public DataTrigger([TypeConverter(typeof(TypeTypeConverter))] [Parameter("TargetType")] Type targetType) : base(new BindingCondition(), targetType)
+ {
+ }
+
+ public BindingBase Binding
+ {
+ get { return ((BindingCondition)Condition).Binding; }
+ set
+ {
+ if (((BindingCondition)Condition).Binding == value)
+ return;
+ if (IsSealed)
+ throw new InvalidOperationException("Can not change Binding once the Trigger has been applied.");
+ OnPropertyChanging();
+ ((BindingCondition)Condition).Binding = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public new IList<Setter> Setters
+ {
+ get { return base.Setters; }
+ }
+
+ public object Value
+ {
+ get { return ((BindingCondition)Condition).Value; }
+ set
+ {
+ if (((BindingCondition)Condition).Value == value)
+ return;
+ if (IsSealed)
+ throw new InvalidOperationException("Can not change Value once the Trigger has been applied.");
+ OnPropertyChanging();
+ ((BindingCondition)Condition).Value = value;
+ OnPropertyChanged();
+ }
+ }
+
+ object IValueProvider.ProvideValue(IServiceProvider serviceProvider)
+ {
+ var valueconverter = serviceProvider.GetService(typeof(IValueConverterProvider)) as IValueConverterProvider;
+ (Condition as BindingCondition).ValueConverter = valueconverter;
+
+ return this;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Interactivity/EventTrigger.cs b/Xamarin.Forms.Core/Interactivity/EventTrigger.cs
new file mode 100644
index 00000000..52e221a0
--- /dev/null
+++ b/Xamarin.Forms.Core/Interactivity/EventTrigger.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("Actions")]
+ public sealed class EventTrigger : TriggerBase
+ {
+ static readonly MethodInfo s_handlerinfo = typeof(EventTrigger).GetRuntimeMethods().Single(mi => mi.Name == "OnEventTriggered" && mi.IsPublic == false);
+ readonly List<BindableObject> _associatedObjects = new List<BindableObject>();
+
+ EventInfo _eventinfo;
+
+ string _eventname;
+ Delegate _handlerdelegate;
+
+ public EventTrigger() : base(typeof(BindableObject))
+ {
+ Actions = new SealedList<TriggerAction>();
+ }
+
+ public IList<TriggerAction> Actions { get; }
+
+ public string Event
+ {
+ get { return _eventname; }
+ set
+ {
+ if (_eventname == value)
+ return;
+ if (IsSealed)
+ throw new InvalidOperationException("Event cannot be changed once the Trigger has been applied");
+ OnPropertyChanging();
+ _eventname = value;
+ OnPropertyChanged();
+ }
+ }
+
+ internal override void OnAttachedTo(BindableObject bindable)
+ {
+ base.OnAttachedTo(bindable);
+ if (!string.IsNullOrEmpty(Event))
+ AttachHandlerTo(bindable);
+ _associatedObjects.Add(bindable);
+ }
+
+ internal override void OnDetachingFrom(BindableObject bindable)
+ {
+ _associatedObjects.Remove(bindable);
+ DetachHandlerFrom(bindable);
+ base.OnDetachingFrom(bindable);
+ }
+
+ internal override void OnSeal()
+ {
+ base.OnSeal();
+ ((SealedList<TriggerAction>)Actions).IsReadOnly = true;
+ }
+
+ void AttachHandlerTo(BindableObject bindable)
+ {
+ try
+ {
+ _eventinfo = bindable.GetType().GetRuntimeEvent(Event);
+ _handlerdelegate = s_handlerinfo.CreateDelegate(_eventinfo.EventHandlerType, this);
+ }
+ catch (Exception)
+ {
+ Log.Warning("EventTrigger", "Can not attach EventTrigger to {0}.{1}. Check if the handler exists and if the signature is right.", bindable.GetType(), Event);
+ }
+ if (_eventinfo != null && _handlerdelegate != null)
+ _eventinfo.AddEventHandler(bindable, _handlerdelegate);
+ }
+
+ void DetachHandlerFrom(BindableObject bindable)
+ {
+ if (_eventinfo != null && _handlerdelegate != null)
+ _eventinfo.RemoveEventHandler(bindable, _handlerdelegate);
+ }
+
+ [Preserve]
+ void OnEventTriggered(object sender, EventArgs e)
+ {
+ var bindable = (BindableObject)sender;
+ foreach (TriggerAction action in Actions)
+ action.DoInvoke(bindable);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Interactivity/IAttachedObject.cs b/Xamarin.Forms.Core/Interactivity/IAttachedObject.cs
new file mode 100644
index 00000000..09748873
--- /dev/null
+++ b/Xamarin.Forms.Core/Interactivity/IAttachedObject.cs
@@ -0,0 +1,8 @@
+namespace Xamarin.Forms
+{
+ internal interface IAttachedObject
+ {
+ void AttachTo(BindableObject bindable);
+ void DetachFrom(BindableObject bindable);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Interactivity/MultiCondition.cs b/Xamarin.Forms.Core/Interactivity/MultiCondition.cs
new file mode 100644
index 00000000..23ca41c5
--- /dev/null
+++ b/Xamarin.Forms.Core/Interactivity/MultiCondition.cs
@@ -0,0 +1,66 @@
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ internal sealed class MultiCondition : Condition
+ {
+ readonly BindableProperty _aggregatedStateProperty;
+
+ public MultiCondition()
+ {
+ _aggregatedStateProperty = BindableProperty.CreateAttached("AggregatedState", typeof(bool), typeof(DataTrigger), false, propertyChanged: OnAggregatedStatePropertyChanged);
+ Conditions = new TriggerBase.SealedList<Condition>();
+ }
+
+ public IList<Condition> Conditions { get; }
+
+ internal override bool GetState(BindableObject bindable)
+ {
+ return (bool)bindable.GetValue(_aggregatedStateProperty);
+ }
+
+ internal override void OnSealed()
+ {
+ ((TriggerBase.SealedList<Condition>)Conditions).IsReadOnly = true;
+ foreach (Condition condition in Conditions)
+ condition.ConditionChanged = OnConditionChanged;
+ }
+
+ internal override void SetUp(BindableObject bindable)
+ {
+ foreach (Condition condition in Conditions)
+ condition.SetUp(bindable);
+ }
+
+ internal override void TearDown(BindableObject bindable)
+ {
+ foreach (Condition condition in Conditions)
+ condition.TearDown(bindable);
+ }
+
+ void OnAggregatedStatePropertyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ if ((bool)oldValue == (bool)newValue)
+ return;
+
+ if (ConditionChanged != null)
+ ConditionChanged(bindable, (bool)oldValue, (bool)newValue);
+ }
+
+ void OnConditionChanged(BindableObject bindable, bool oldValue, bool newValue)
+ {
+ var oldState = (bool)bindable.GetValue(_aggregatedStateProperty);
+ var newState = true;
+ foreach (Condition condition in Conditions)
+ {
+ if (!condition.GetState(bindable))
+ {
+ newState = false;
+ break;
+ }
+ }
+ if (newState != oldState)
+ bindable.SetValue(_aggregatedStateProperty, newState);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Interactivity/MultiTrigger.cs b/Xamarin.Forms.Core/Interactivity/MultiTrigger.cs
new file mode 100644
index 00000000..3c85467c
--- /dev/null
+++ b/Xamarin.Forms.Core/Interactivity/MultiTrigger.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("Setters")]
+ public sealed class MultiTrigger : TriggerBase
+ {
+ public MultiTrigger([TypeConverter(typeof(TypeTypeConverter))] [Parameter("TargetType")] Type targetType) : base(new MultiCondition(), targetType)
+ {
+ }
+
+ public IList<Condition> Conditions
+ {
+ get { return ((MultiCondition)Condition).Conditions; }
+ }
+
+ public new IList<Setter> Setters
+ {
+ get { return base.Setters; }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Interactivity/PropertyCondition.cs b/Xamarin.Forms.Core/Interactivity/PropertyCondition.cs
new file mode 100644
index 00000000..be37d48f
--- /dev/null
+++ b/Xamarin.Forms.Core/Interactivity/PropertyCondition.cs
@@ -0,0 +1,100 @@
+using System;
+using System.ComponentModel;
+using System.Reflection;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms
+{
+ public sealed class PropertyCondition : Condition, IValueProvider
+ {
+ readonly BindableProperty _stateProperty;
+
+ BindableProperty _property;
+ object _triggerValue;
+
+ public PropertyCondition()
+ {
+ _stateProperty = BindableProperty.CreateAttached("State", typeof(bool), typeof(DataTrigger), false, propertyChanged: OnStatePropertyChanged);
+ }
+
+ public BindableProperty Property
+ {
+ get { return _property; }
+ set
+ {
+ if (_property == value)
+ return;
+ if (IsSealed)
+ throw new InvalidOperationException("Can not change Property once the Trigger has been applied.");
+ _property = value;
+ }
+ }
+
+ public object Value
+ {
+ get { return _triggerValue; }
+ set
+ {
+ if (_triggerValue == value)
+ return;
+ if (IsSealed)
+ throw new InvalidOperationException("Can not change Value once the Trigger has been applied.");
+ _triggerValue = value;
+ }
+ }
+
+ object IValueProvider.ProvideValue(IServiceProvider serviceProvider)
+ {
+ var valueconverter = serviceProvider.GetService(typeof(IValueConverterProvider)) as IValueConverterProvider;
+ Func<MemberInfo> minforetriever = () => Property.DeclaringType.GetRuntimeProperty(Property.PropertyName);
+
+ object value = valueconverter.Convert(Value, Property.ReturnType, minforetriever, serviceProvider);
+ Value = value;
+ return this;
+ }
+
+ internal override bool GetState(BindableObject bindable)
+ {
+ return (bool)bindable.GetValue(_stateProperty);
+ }
+
+ internal override void SetUp(BindableObject bindable)
+ {
+ object newvalue = bindable.GetValue(Property);
+
+ bool newState = (newvalue == Value) || (newvalue != null && newvalue.Equals(Value));
+ bindable.SetValue(_stateProperty, newState);
+ bindable.PropertyChanged += OnAttachedObjectPropertyChanged;
+ }
+
+ internal override void TearDown(BindableObject bindable)
+ {
+ bindable.ClearValue(_stateProperty);
+ bindable.PropertyChanged -= OnAttachedObjectPropertyChanged;
+ }
+
+ void OnAttachedObjectPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ var bindable = (BindableObject)sender;
+ var oldState = (bool)bindable.GetValue(_stateProperty);
+
+ if (Property == null)
+ return;
+ if (e.PropertyName != Property.PropertyName)
+ return;
+ object newvalue = bindable.GetValue(Property);
+ bool newstate = (newvalue == Value) || (newvalue != null && newvalue.Equals(Value));
+ if (oldState != newstate)
+ bindable.SetValue(_stateProperty, newstate);
+ }
+
+ void OnStatePropertyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ if ((bool)oldValue == (bool)newValue)
+ return;
+
+ if (ConditionChanged != null)
+ ConditionChanged(bindable, (bool)oldValue, (bool)newValue);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Interactivity/Trigger.cs b/Xamarin.Forms.Core/Interactivity/Trigger.cs
new file mode 100644
index 00000000..ea3dc5ae
--- /dev/null
+++ b/Xamarin.Forms.Core/Interactivity/Trigger.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("Setters")]
+ public sealed class Trigger : TriggerBase, IValueProvider
+ {
+ public Trigger([TypeConverter(typeof(TypeTypeConverter))] [Parameter("TargetType")] Type targetType) : base(new PropertyCondition(), targetType)
+ {
+ }
+
+ public BindableProperty Property
+ {
+ get { return ((PropertyCondition)Condition).Property; }
+ set
+ {
+ if (((PropertyCondition)Condition).Property == value)
+ return;
+ if (IsSealed)
+ throw new InvalidOperationException("Can not change Property once the Trigger has been applied.");
+ OnPropertyChanging();
+ ((PropertyCondition)Condition).Property = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public new IList<Setter> Setters
+ {
+ get { return base.Setters; }
+ }
+
+ public object Value
+ {
+ get { return ((PropertyCondition)Condition).Value; }
+ set
+ {
+ if (((PropertyCondition)Condition).Value == value)
+ return;
+ if (IsSealed)
+ throw new InvalidOperationException("Can not change Value once the Trigger has been applied.");
+ OnPropertyChanging();
+ ((PropertyCondition)Condition).Value = value;
+ OnPropertyChanged();
+ }
+ }
+
+ object IValueProvider.ProvideValue(IServiceProvider serviceProvider)
+ {
+ var valueconverter = serviceProvider.GetService(typeof(IValueConverterProvider)) as IValueConverterProvider;
+ Func<MemberInfo> minforetriever = () => Property.DeclaringType.GetRuntimeProperty(Property.PropertyName);
+
+ object value = valueconverter.Convert(Value, Property.ReturnType, minforetriever, serviceProvider);
+ Value = value;
+ return this;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Interactivity/TriggerAction.cs b/Xamarin.Forms.Core/Interactivity/TriggerAction.cs
new file mode 100644
index 00000000..bb9dc08f
--- /dev/null
+++ b/Xamarin.Forms.Core/Interactivity/TriggerAction.cs
@@ -0,0 +1,37 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public abstract class TriggerAction
+ {
+ internal TriggerAction(Type associatedType)
+ {
+ if (associatedType == null)
+ throw new ArgumentNullException("associatedType");
+ AssociatedType = associatedType;
+ }
+
+ protected Type AssociatedType { get; private set; }
+
+ protected abstract void Invoke(object sender);
+
+ internal virtual void DoInvoke(object sender)
+ {
+ Invoke(sender);
+ }
+ }
+
+ public abstract class TriggerAction<T> : TriggerAction where T : BindableObject
+ {
+ protected TriggerAction() : base(typeof(T))
+ {
+ }
+
+ protected override void Invoke(object sender)
+ {
+ Invoke((T)sender);
+ }
+
+ protected abstract void Invoke(T sender);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Interactivity/TriggerBase.cs b/Xamarin.Forms.Core/Interactivity/TriggerBase.cs
new file mode 100644
index 00000000..9418c7ae
--- /dev/null
+++ b/Xamarin.Forms.Core/Interactivity/TriggerBase.cs
@@ -0,0 +1,212 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ public abstract class TriggerBase : BindableObject, IAttachedObject
+ {
+ bool _isSealed;
+
+ internal TriggerBase(Type targetType)
+ {
+ if (targetType == null)
+ throw new ArgumentNullException("targetType");
+ TargetType = targetType;
+
+ EnterActions = new SealedList<TriggerAction>();
+ ExitActions = new SealedList<TriggerAction>();
+ }
+
+ internal TriggerBase(Condition condition, Type targetType) : this(targetType)
+ {
+ Setters = new SealedList<Setter>();
+ Condition = condition;
+ Condition.ConditionChanged = OnConditionChanged;
+ }
+
+ public IList<TriggerAction> EnterActions { get; }
+
+ public IList<TriggerAction> ExitActions { get; }
+
+ public bool IsSealed
+ {
+ get { return _isSealed; }
+ private set
+ {
+ if (_isSealed == value)
+ return;
+ if (!value)
+ throw new InvalidOperationException("What is sealed can not be unsealed.");
+ _isSealed = value;
+ OnSeal();
+ }
+ }
+
+ public Type TargetType { get; }
+
+ internal Condition Condition { get; }
+
+ //Setters and Condition are used by Trigger, DataTrigger and MultiTrigger
+ internal IList<Setter> Setters { get; }
+
+ void IAttachedObject.AttachTo(BindableObject bindable)
+ {
+ IsSealed = true;
+
+ if (bindable == null)
+ throw new ArgumentNullException("bindable");
+ if (!TargetType.IsInstanceOfType(bindable))
+ throw new InvalidOperationException("bindable not an instance of AssociatedType");
+ OnAttachedTo(bindable);
+ }
+
+ void IAttachedObject.DetachFrom(BindableObject bindable)
+ {
+ if (bindable == null)
+ throw new ArgumentNullException("bindable");
+ OnDetachingFrom(bindable);
+ }
+
+ internal virtual void OnAttachedTo(BindableObject bindable)
+ {
+ if (Condition != null)
+ Condition.SetUp(bindable);
+ }
+
+ internal virtual void OnDetachingFrom(BindableObject bindable)
+ {
+ if (Condition != null)
+ Condition.TearDown(bindable);
+ }
+
+ internal virtual void OnSeal()
+ {
+ ((SealedList<TriggerAction>)EnterActions).IsReadOnly = true;
+ ((SealedList<TriggerAction>)ExitActions).IsReadOnly = true;
+ if (Setters != null)
+ ((SealedList<Setter>)Setters).IsReadOnly = true;
+ if (Condition != null)
+ Condition.IsSealed = true;
+ }
+
+ void OnConditionChanged(BindableObject bindable, bool oldValue, bool newValue)
+ {
+ if (newValue)
+ {
+ foreach (TriggerAction action in EnterActions)
+ action.DoInvoke(bindable);
+ foreach (Setter setter in Setters)
+ setter.Apply(bindable);
+ }
+ else
+ {
+ foreach (Setter setter in Setters)
+ setter.UnApply(bindable);
+ foreach (TriggerAction action in ExitActions)
+ action.DoInvoke(bindable);
+ }
+ }
+
+ internal class SealedList<T> : IList<T>
+ {
+ readonly IList<T> _actual;
+
+ bool _isReadOnly;
+
+ public SealedList()
+ {
+ _actual = new List<T>();
+ }
+
+ public void Add(T item)
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException("This list is ReadOnly");
+ _actual.Add(item);
+ }
+
+ public void Clear()
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException("This list is ReadOnly");
+ _actual.Clear();
+ }
+
+ public bool Contains(T item)
+ {
+ return _actual.Contains(item);
+ }
+
+ public void CopyTo(T[] array, int arrayIndex)
+ {
+ _actual.CopyTo(array, arrayIndex);
+ }
+
+ public int Count
+ {
+ get { return _actual.Count; }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return _isReadOnly; }
+ set
+ {
+ if (_isReadOnly == value)
+ return;
+ if (!value)
+ throw new InvalidOperationException("Can't change this back to non readonly");
+ _isReadOnly = value;
+ }
+ }
+
+ public bool Remove(T item)
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException("This list is ReadOnly");
+ return _actual.Remove(item);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable)_actual).GetEnumerator();
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ return _actual.GetEnumerator();
+ }
+
+ public int IndexOf(T item)
+ {
+ return _actual.IndexOf(item);
+ }
+
+ public void Insert(int index, T item)
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException("This list is ReadOnly");
+ _actual.Insert(index, item);
+ }
+
+ public T this[int index]
+ {
+ get { return _actual[index]; }
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException("This list is ReadOnly");
+ _actual[index] = value;
+ }
+ }
+
+ public void RemoveAt(int index)
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException("This list is ReadOnly");
+ _actual.RemoveAt(index);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Internals/DynamicResource.cs b/Xamarin.Forms.Core/Internals/DynamicResource.cs
new file mode 100644
index 00000000..3724daec
--- /dev/null
+++ b/Xamarin.Forms.Core/Internals/DynamicResource.cs
@@ -0,0 +1,12 @@
+namespace Xamarin.Forms.Internals
+{
+ public class DynamicResource
+ {
+ public DynamicResource(string key)
+ {
+ Key = key;
+ }
+
+ public string Key { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Internals/IDataTemplate.cs b/Xamarin.Forms.Core/Internals/IDataTemplate.cs
new file mode 100644
index 00000000..d6947ae8
--- /dev/null
+++ b/Xamarin.Forms.Core/Internals/IDataTemplate.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Xamarin.Forms.Internals
+{
+ [Obsolete]
+ public interface IDataTemplate
+ {
+ Func<object> LoadTemplate { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Internals/IDynamicResourceHandler.cs b/Xamarin.Forms.Core/Internals/IDynamicResourceHandler.cs
new file mode 100644
index 00000000..1885d8ab
--- /dev/null
+++ b/Xamarin.Forms.Core/Internals/IDynamicResourceHandler.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms.Internals
+{
+ public interface IDynamicResourceHandler
+ {
+ void SetDynamicResource(BindableProperty property, string key);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Internals/INameScope.cs b/Xamarin.Forms.Core/Internals/INameScope.cs
new file mode 100644
index 00000000..ca520605
--- /dev/null
+++ b/Xamarin.Forms.Core/Internals/INameScope.cs
@@ -0,0 +1,12 @@
+using System.Xml;
+
+namespace Xamarin.Forms.Internals
+{
+ public interface INameScope
+ {
+ object FindByName(string name);
+ void RegisterName(string name, object scopedElement);
+ void RegisterName(string name, object scopedElement, IXmlLineInfo xmlLineInfo);
+ void UnregisterName(string name);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Internals/NameScope.cs b/Xamarin.Forms.Core/Internals/NameScope.cs
new file mode 100644
index 00000000..b29534b6
--- /dev/null
+++ b/Xamarin.Forms.Core/Internals/NameScope.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Xml;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Internals
+{
+ public class NameScope : INameScope
+ {
+ public static readonly BindableProperty NameScopeProperty = BindableProperty.CreateAttached("NameScope", typeof(INameScope), typeof(NameScope), default(INameScope));
+
+ readonly Dictionary<string, object> _names = new Dictionary<string, object>();
+
+ object INameScope.FindByName(string name)
+ {
+ if (_names.ContainsKey(name))
+ return _names[name];
+ return null;
+ }
+
+ void INameScope.RegisterName(string name, object scopedElement)
+ {
+ if (_names.ContainsKey(name))
+ throw new ArgumentException("An element with the same key already exists in NameScope", "name");
+
+ _names[name] = scopedElement;
+ }
+
+ void INameScope.RegisterName(string name, object scopedElement, IXmlLineInfo xmlLineInfo)
+ {
+ try
+ {
+ ((INameScope)this).RegisterName(name, scopedElement);
+ }
+ catch (ArgumentException)
+ {
+ throw new XamlParseException(string.Format("An element with the name \"{0}\" already exists in this NameScope", name), xmlLineInfo);
+ }
+ }
+
+ void INameScope.UnregisterName(string name)
+ {
+ _names.Remove(name);
+ }
+
+ public static INameScope GetNameScope(BindableObject bindable)
+ {
+ return (INameScope)bindable.GetValue(NameScopeProperty);
+ }
+
+ public static void SetNameScope(BindableObject bindable, INameScope value)
+ {
+ bindable.SetValue(NameScopeProperty, value);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/InvalidNavigationException.cs b/Xamarin.Forms.Core/InvalidNavigationException.cs
new file mode 100644
index 00000000..fce5b314
--- /dev/null
+++ b/Xamarin.Forms.Core/InvalidNavigationException.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ internal class InvalidNavigationException : Exception
+ {
+ public InvalidNavigationException(string message) : base(message)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/InvalidationEventArgs.cs b/Xamarin.Forms.Core/InvalidationEventArgs.cs
new file mode 100644
index 00000000..d88e2519
--- /dev/null
+++ b/Xamarin.Forms.Core/InvalidationEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ internal class InvalidationEventArgs : EventArgs
+ {
+ public InvalidationEventArgs(InvalidationTrigger trigger)
+ {
+ Trigger = trigger;
+ }
+
+ public InvalidationTrigger Trigger { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/InvalidationTrigger.cs b/Xamarin.Forms.Core/InvalidationTrigger.cs
new file mode 100644
index 00000000..e7db534e
--- /dev/null
+++ b/Xamarin.Forms.Core/InvalidationTrigger.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [Flags]
+ internal enum InvalidationTrigger
+ {
+ Undefined = 0,
+ MeasureChanged = 1 << 0,
+ HorizontalOptionsChanged = 1 << 1,
+ VerticalOptionsChanged = 1 << 2,
+ SizeRequestChanged = 1 << 3,
+ RendererReady = 1 << 4,
+ MarginChanged = 1 << 5
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ItemTappedEventArgs.cs b/Xamarin.Forms.Core/ItemTappedEventArgs.cs
new file mode 100644
index 00000000..9fde19bd
--- /dev/null
+++ b/Xamarin.Forms.Core/ItemTappedEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class ItemTappedEventArgs : EventArgs
+ {
+ public ItemTappedEventArgs(object group, object item)
+ {
+ Group = group;
+ Item = item;
+ }
+
+ public object Group { get; private set; }
+
+ public object Item { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ItemVisibilityEventArgs.cs b/Xamarin.Forms.Core/ItemVisibilityEventArgs.cs
new file mode 100644
index 00000000..48166c13
--- /dev/null
+++ b/Xamarin.Forms.Core/ItemVisibilityEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public sealed class ItemVisibilityEventArgs : EventArgs
+ {
+ public ItemVisibilityEventArgs(object item)
+ {
+ Item = item;
+ }
+
+ public object Item { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ItemsView.cs b/Xamarin.Forms.Core/ItemsView.cs
new file mode 100644
index 00000000..51c105bd
--- /dev/null
+++ b/Xamarin.Forms.Core/ItemsView.cs
@@ -0,0 +1,92 @@
+using System.Collections;
+
+namespace Xamarin.Forms
+{
+ public abstract class ItemsView<TVisual> : View, IItemsView<TVisual> where TVisual : BindableObject
+ {
+ /*
+ public static readonly BindableProperty InfiniteScrollingProperty =
+ BindableProperty.Create<ItemsView, bool> (lv => lv.InfiniteScrolling, false);
+
+ public bool InfiniteScrolling
+ {
+ get { return (bool) GetValue (InfiniteScrollingProperty); }
+ set { SetValue (InfiniteScrollingProperty, value); }
+ }*/
+
+ public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(ItemsView<TVisual>), null, propertyChanged: OnItemsSourceChanged);
+
+ public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create("ItemTemplate", typeof(DataTemplate), typeof(ItemsView<TVisual>), null, validateValue: ValidateItemTemplate);
+
+ internal ItemsView()
+ {
+ TemplatedItems = new TemplatedItemsList<ItemsView<TVisual>, TVisual>(this, ItemsSourceProperty, ItemTemplateProperty);
+ }
+
+ public IEnumerable ItemsSource
+ {
+ get { return (IEnumerable)GetValue(ItemsSourceProperty); }
+ set { SetValue(ItemsSourceProperty, value); }
+ }
+
+ public DataTemplate ItemTemplate
+ {
+ get { return (DataTemplate)GetValue(ItemTemplateProperty); }
+ set { SetValue(ItemTemplateProperty, value); }
+ }
+
+ /*public void UpdateNonNotifyingList()
+ {
+ this.templatedItems.ForceUpdate();
+ }*/
+
+ internal ListProxy ListProxy
+ {
+ get { return TemplatedItems.ListProxy; }
+ }
+
+ internal TemplatedItemsList<ItemsView<TVisual>, TVisual> TemplatedItems { get; }
+
+ TVisual IItemsView<TVisual>.CreateDefault(object item)
+ {
+ return CreateDefault(item);
+ }
+
+ void IItemsView<TVisual>.SetupContent(TVisual content, int index)
+ {
+ SetupContent(content, index);
+ }
+
+ void IItemsView<TVisual>.UnhookContent(TVisual content)
+ {
+ UnhookContent(content);
+ }
+
+ protected abstract TVisual CreateDefault(object item);
+
+ protected virtual void SetupContent(TVisual content, int index)
+ {
+ }
+
+ protected virtual void UnhookContent(TVisual content)
+ {
+ }
+
+ static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var element = newValue as Element;
+ if (element == null)
+ return;
+ element.Parent = (Element)bindable;
+ }
+
+ static bool ValidateItemTemplate(BindableObject b, object v)
+ {
+ var lv = b as ListView;
+ if (lv == null)
+ return true;
+
+ return !(lv.CachingStrategy == ListViewCachingStrategy.RetainElement && lv.ItemTemplate is DataTemplateSelector);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ItemsViewSimple.cs b/Xamarin.Forms.Core/ItemsViewSimple.cs
new file mode 100644
index 00000000..fd631838
--- /dev/null
+++ b/Xamarin.Forms.Core/ItemsViewSimple.cs
@@ -0,0 +1,335 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Xamarin.Forms
+{
+ public abstract class ItemsView : View, IItemViewController
+ {
+ public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(ItemsView), Enumerable.Empty<object>());
+
+ public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create("ItemTemplate", typeof(DataTemplate), typeof(ItemsView));
+
+ ItemSource _itemSource;
+
+ internal ItemsView()
+ {
+ }
+
+ public int Count => _itemSource.Count;
+
+ public IEnumerable ItemsSource
+ {
+ get { return (IEnumerable)GetValue(ItemsSourceProperty); }
+ set { SetValue(ItemsSourceProperty, value); }
+ }
+
+ public DataTemplate ItemTemplate
+ {
+ get { return (DataTemplate)GetValue(ItemTemplateProperty); }
+ set { SetValue(ItemTemplateProperty, value); }
+ }
+
+ void IItemViewController.BindView(View view, object item)
+ {
+ view.BindingContext = item;
+ }
+
+ View IItemViewController.CreateView(object type)
+ {
+ var dataTemplate = (DataTemplate)type;
+ object content = dataTemplate.CreateContent();
+ var view = (View)content;
+ view.Parent = this;
+ return view;
+ }
+
+ object IItemViewController.GetItem(int index) => _itemSource[index];
+
+ object IItemViewController.GetItemType(object item)
+ {
+ DataTemplate dataTemplate = ItemTemplate;
+ var dataTemplateSelector = dataTemplate as DataTemplateSelector;
+ if (dataTemplateSelector != null)
+ dataTemplate = dataTemplateSelector.SelectTemplate(item, this);
+
+ if (item == null)
+ throw new ArgumentException($"No DataTemplate resolved for item: {item}.");
+
+ return dataTemplate;
+ }
+
+ protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ if (propertyName == nameof(ItemsSource))
+ {
+ // abstract enumerable, IList, IList<T>, and IReadOnlyList<T>
+ _itemSource = new ItemSource(ItemsSource);
+
+ // subscribe to collection changed events
+ var dynamicItemSource = _itemSource as INotifyCollectionChanged;
+ if (dynamicItemSource != null)
+ {
+ new WeakNotifyCollectionChanged(dynamicItemSource, OnCollectionChange);
+ }
+ }
+
+ base.OnPropertyChanged(propertyName);
+ }
+
+ internal event NotifyCollectionChangedEventHandler CollectionChanged;
+
+ void OnCollectionChange(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ CollectionChanged?.Invoke(sender, e);
+ }
+
+ sealed class WeakNotifyCollectionChanged
+ {
+ readonly INotifyCollectionChanged _source;
+ // prevent the itemSource from keeping the itemsView alive
+ readonly WeakReference<NotifyCollectionChangedEventHandler> _weakTarget;
+
+ public WeakNotifyCollectionChanged(INotifyCollectionChanged source, NotifyCollectionChangedEventHandler target)
+ {
+ _weakTarget = new WeakReference<NotifyCollectionChangedEventHandler>(target);
+ _source = source;
+ _source.CollectionChanged += OnCollectionChanged;
+ }
+
+ public void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ NotifyCollectionChangedEventHandler weakTarget;
+ if (!_weakTarget.TryGetTarget(out weakTarget))
+ {
+ _source.CollectionChanged -= OnCollectionChanged;
+ return;
+ }
+
+ weakTarget(sender, e);
+ }
+ }
+
+ sealed class ItemSource : IEnumerable<object>, INotifyCollectionChanged
+ {
+ IndexableCollection _indexable;
+
+ internal ItemSource(IEnumerable enumerable)
+ {
+ _indexable = new IndexableCollection(enumerable);
+ var dynamicItemSource = enumerable as INotifyCollectionChanged;
+ if (dynamicItemSource != null)
+ dynamicItemSource.CollectionChanged += OnCollectionChanged;
+ }
+
+ public int Count => _indexable.Count;
+
+ public IEnumerable Enumerable => _indexable.Enumerable;
+
+ public object this[int index]
+ {
+ get
+ {
+ // madness ported from listProxy
+ CollectionSynchronizationContext syncContext = SyncContext;
+ if (syncContext != null)
+ {
+ object value = null;
+ syncContext.Callback(Enumerable, SyncContext.Context, () => value = _indexable[index], false);
+
+ return value;
+ }
+
+ return _indexable[index];
+ }
+ }
+
+ CollectionSynchronizationContext SyncContext
+ {
+ get
+ {
+ CollectionSynchronizationContext syncContext;
+ BindingBase.TryGetSynchronizedCollection(Enumerable, out syncContext);
+ return syncContext;
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ IEnumerator<object> IEnumerable<object>.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public event NotifyCollectionChangedEventHandler CollectionChanged;
+
+ public Enumerator GetEnumerator()
+ {
+ return new Enumerator(this);
+ }
+
+ public int IndexOf(object item)
+ {
+ // madness ported from listProxy
+ CollectionSynchronizationContext syncContext = SyncContext;
+ if (syncContext != null)
+ {
+ int value = -1;
+ syncContext.Callback(Enumerable, SyncContext.Context, () => value = _indexable.IndexOf(item), false);
+
+ return value;
+ }
+
+ return _indexable.IndexOf(item);
+ }
+
+ void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ Action onCollectionChanged = () =>
+ {
+ if (CollectionChanged != null)
+ CollectionChanged(this, e);
+ };
+
+ // madness ported from listProxy
+ CollectionSynchronizationContext syncContext = SyncContext;
+ if (syncContext != null)
+ {
+ syncContext.Callback(Enumerable, syncContext.Context, () => Device.BeginInvokeOnMainThread(onCollectionChanged), false);
+ }
+
+ else if (Device.IsInvokeRequired)
+ Device.BeginInvokeOnMainThread(onCollectionChanged);
+
+ else
+ onCollectionChanged();
+ }
+
+ internal struct Enumerator : IEnumerator<object>
+ {
+ readonly ItemSource _itemSource;
+ int _index;
+
+ internal Enumerator(ItemSource itemSource) : this()
+ {
+ _itemSource = itemSource;
+ }
+
+ public bool MoveNext()
+ {
+ if (_index == _itemSource.Count)
+ return false;
+
+ Current = _itemSource[_index++];
+ return true;
+ }
+
+ public object Current { get; private set; }
+
+ public void Reset()
+ {
+ Current = null;
+ _index = 0;
+ }
+
+ public void Dispose()
+ {
+ }
+ }
+
+ struct IndexableCollection : IEnumerable<object>
+ {
+ internal IndexableCollection(IEnumerable list)
+ {
+ Enumerable = list;
+
+ if (list is IList)
+ return;
+
+ if (list is IList<object>)
+ return;
+
+ if (list is IReadOnlyList<object>)
+ return;
+
+ Enumerable = list.Cast<object>().ToArray();
+ }
+
+ internal IEnumerable Enumerable { get; }
+
+ internal int Count
+ {
+ get
+ {
+ var list = Enumerable as IList;
+ if (list != null)
+ return list.Count;
+
+ var listOf = Enumerable as IList<object>;
+ if (listOf != null)
+ return listOf.Count;
+
+ var readOnlyList = (IReadOnlyList<object>)Enumerable;
+ return readOnlyList.Count;
+ }
+ }
+
+ internal object this[int index]
+ {
+ get
+ {
+ var list = Enumerable as IList;
+ if (list != null)
+ return list[index];
+
+ var listOf = Enumerable as IList<object>;
+ if (listOf != null)
+ return listOf[index];
+
+ var readOnlyList = (IReadOnlyList<object>)Enumerable;
+ return readOnlyList[index];
+ }
+ }
+
+ internal int IndexOf(object item)
+ {
+ var list = Enumerable as IList;
+ if (list != null)
+ return list.IndexOf(item);
+
+ var listOf = Enumerable as IList<object>;
+ if (listOf != null)
+ return listOf.IndexOf(item);
+
+ var readOnlyList = (IReadOnlyList<object>)Enumerable;
+ return readOnlyList.IndexOf(item);
+ }
+
+ public IEnumerator<object> GetEnumerator()
+ {
+ var list = Enumerable as IList;
+ if (list != null)
+ return list.Cast<object>().GetEnumerator();
+
+ var listOf = Enumerable as IList<object>;
+ if (listOf != null)
+ return listOf.GetEnumerator();
+
+ var readOnlyList = (IReadOnlyList<object>)Enumerable;
+ return readOnlyList.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Keyboard.cs b/Xamarin.Forms.Core/Keyboard.cs
new file mode 100644
index 00000000..56d5ca8c
--- /dev/null
+++ b/Xamarin.Forms.Core/Keyboard.cs
@@ -0,0 +1,64 @@
+namespace Xamarin.Forms
+{
+ [TypeConverter(typeof(KeyboardTypeConverter))]
+ public class Keyboard
+ {
+ static Keyboard s_def;
+
+ static Keyboard s_email;
+
+ static Keyboard s_text;
+
+ static Keyboard s_url;
+
+ static Keyboard s_numeric;
+
+ static Keyboard s_telephone;
+
+ static Keyboard s_chat;
+
+ internal Keyboard()
+ {
+ }
+
+ public static Keyboard Chat
+ {
+ get { return s_chat ?? (s_chat = new ChatKeyboard()); }
+ }
+
+ public static Keyboard Default
+ {
+ get { return s_def ?? (s_def = new Keyboard()); }
+ }
+
+ public static Keyboard Email
+ {
+ get { return s_email ?? (s_email = new EmailKeyboard()); }
+ }
+
+ public static Keyboard Numeric
+ {
+ get { return s_numeric ?? (s_numeric = new NumericKeyboard()); }
+ }
+
+ public static Keyboard Telephone
+ {
+ get { return s_telephone ?? (s_telephone = new TelephoneKeyboard()); }
+ }
+
+ public static Keyboard Text
+ {
+ get { return s_text ?? (s_text = new TextKeyboard()); }
+ }
+
+ public static Keyboard Url
+ {
+ get { return s_url ?? (s_url = new UrlKeyboard()); }
+ }
+
+ public static Keyboard Create(KeyboardFlags flags)
+ {
+ return new CustomKeyboard(flags);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/KeyboardFlags.cs b/Xamarin.Forms.Core/KeyboardFlags.cs
new file mode 100644
index 00000000..5ac2f1cc
--- /dev/null
+++ b/Xamarin.Forms.Core/KeyboardFlags.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [Flags]
+ public enum KeyboardFlags
+ {
+ CapitalizeSentence = 1,
+ Spellcheck = 1 << 1,
+ Suggestions = 1 << 2,
+ All = ~0
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/KeyboardTypeConverter.cs b/Xamarin.Forms.Core/KeyboardTypeConverter.cs
new file mode 100644
index 00000000..4a93010b
--- /dev/null
+++ b/Xamarin.Forms.Core/KeyboardTypeConverter.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Linq;
+using System.Reflection;
+
+namespace Xamarin.Forms
+{
+ public class KeyboardTypeConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString(string value)
+ {
+ if (value != null)
+ {
+ string[] parts = value.Split('.');
+ if (parts.Length == 1 || (parts.Length == 2 && parts[0] == "Keyboard"))
+ {
+ string keyboard = parts[parts.Length - 1];
+ FieldInfo field = typeof(Keyboard).GetFields().FirstOrDefault(fi => fi.IsStatic && fi.Name == keyboard);
+ if (field != null)
+ return (Keyboard)field.GetValue(null);
+ PropertyInfo property = typeof(Keyboard).GetProperties().FirstOrDefault(pi => pi.Name == keyboard && pi.CanRead && pi.GetMethod.IsStatic);
+ if (property != null)
+ return (Keyboard)property.GetValue(null, null);
+ }
+ }
+
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(Keyboard)));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Label.cs b/Xamarin.Forms.Core/Label.cs
new file mode 100644
index 00000000..fed021f8
--- /dev/null
+++ b/Xamarin.Forms.Core/Label.cs
@@ -0,0 +1,270 @@
+using System;
+using System.ComponentModel;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("Text")]
+ [RenderWith(typeof(_LabelRenderer))]
+ public class Label : View, IFontElement
+ {
+ public static readonly BindableProperty HorizontalTextAlignmentProperty = BindableProperty.Create("HorizontalTextAlignment", typeof(TextAlignment), typeof(Label), TextAlignment.Start,
+ propertyChanged: OnHorizontalTextAlignmentPropertyChanged);
+
+ [Obsolete("XAlignProperty is obsolete. Please use HorizontalTextAlignmentProperty instead.")] public static readonly BindableProperty XAlignProperty = HorizontalTextAlignmentProperty;
+
+ public static readonly BindableProperty VerticalTextAlignmentProperty = BindableProperty.Create("VerticalTextAlignment", typeof(TextAlignment), typeof(Label), TextAlignment.Start,
+ propertyChanged: OnVerticalTextAlignmentPropertyChanged);
+
+ [Obsolete("YAlignProperty is obsolete. Please use VerticalTextAlignmentProperty instead.")] public static readonly BindableProperty YAlignProperty = VerticalTextAlignmentProperty;
+
+ public static readonly BindableProperty TextColorProperty = BindableProperty.Create("TextColor", typeof(Color), typeof(Label), Color.Default);
+
+ public static readonly BindableProperty FontProperty = BindableProperty.Create("Font", typeof(Font), typeof(Label), default(Font), propertyChanged: FontStructPropertyChanged);
+
+ public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(Label), default(string), propertyChanged: OnTextPropertyChanged);
+
+ public static readonly BindableProperty FontFamilyProperty = BindableProperty.Create("FontFamily", typeof(string), typeof(Label), default(string), propertyChanged: OnFontFamilyChanged);
+
+ public static readonly BindableProperty FontSizeProperty = BindableProperty.Create("FontSize", typeof(double), typeof(Label), -1.0, propertyChanged: OnFontSizeChanged,
+ defaultValueCreator: bindable => Device.GetNamedSize(NamedSize.Default, (Label)bindable));
+
+ public static readonly BindableProperty FontAttributesProperty = BindableProperty.Create("FontAttributes", typeof(FontAttributes), typeof(Label), FontAttributes.None,
+ propertyChanged: OnFontAttributesChanged);
+
+ public static readonly BindableProperty FormattedTextProperty = BindableProperty.Create("FormattedText", typeof(FormattedString), typeof(Label), default(FormattedString),
+ propertyChanging: (bindable, oldvalue, newvalue) =>
+ {
+ if (oldvalue != null)
+ ((FormattedString)oldvalue).PropertyChanged -= ((Label)bindable).OnFormattedTextChanged;
+ }, propertyChanged: (bindable, oldvalue, newvalue) =>
+ {
+ if (newvalue != null)
+ ((FormattedString)newvalue).PropertyChanged += ((Label)bindable).OnFormattedTextChanged;
+ ((Label)bindable).InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ if (newvalue != null)
+ ((Label)bindable).Text = null;
+ });
+
+ public static readonly BindableProperty LineBreakModeProperty = BindableProperty.Create("LineBreakMode", typeof(LineBreakMode), typeof(Label), LineBreakMode.WordWrap,
+ propertyChanged: (bindable, oldvalue, newvalue) => ((Label)bindable).InvalidateMeasure(InvalidationTrigger.MeasureChanged));
+
+ bool _cancelEvents;
+
+ [Obsolete("Please use the Font attributes which are on the class itself. Obsoleted in v1.3.0")]
+ public Font Font
+ {
+ get { return (Font)GetValue(FontProperty); }
+ set { SetValue(FontProperty, value); }
+ }
+
+ public FormattedString FormattedText
+ {
+ get { return (FormattedString)GetValue(FormattedTextProperty); }
+ set { SetValue(FormattedTextProperty, value); }
+ }
+
+ public TextAlignment HorizontalTextAlignment
+ {
+ get { return (TextAlignment)GetValue(HorizontalTextAlignmentProperty); }
+ set { SetValue(HorizontalTextAlignmentProperty, value); }
+ }
+
+ public LineBreakMode LineBreakMode
+ {
+ get { return (LineBreakMode)GetValue(LineBreakModeProperty); }
+ set { SetValue(LineBreakModeProperty, value); }
+ }
+
+ public string Text
+ {
+ get { return (string)GetValue(TextProperty); }
+ set { SetValue(TextProperty, value); }
+ }
+
+ public Color TextColor
+ {
+ get { return (Color)GetValue(TextColorProperty); }
+ set { SetValue(TextColorProperty, value); }
+ }
+
+ public TextAlignment VerticalTextAlignment
+ {
+ get { return (TextAlignment)GetValue(VerticalTextAlignmentProperty); }
+ set { SetValue(VerticalTextAlignmentProperty, value); }
+ }
+
+ [Obsolete("XAlign is obsolete. Please use HorizontalTextAlignment instead.")]
+ public TextAlignment XAlign
+ {
+ get { return (TextAlignment)GetValue(XAlignProperty); }
+ set { SetValue(XAlignProperty, value); }
+ }
+
+ [Obsolete("YAlign is obsolete. Please use VerticalTextAlignment instead.")]
+ public TextAlignment YAlign
+ {
+ get { return (TextAlignment)GetValue(YAlignProperty); }
+ set { SetValue(YAlignProperty, value); }
+ }
+
+ public FontAttributes FontAttributes
+ {
+ get { return (FontAttributes)GetValue(FontAttributesProperty); }
+ set { SetValue(FontAttributesProperty, value); }
+ }
+
+ public string FontFamily
+ {
+ get { return (string)GetValue(FontFamilyProperty); }
+ set { SetValue(FontFamilyProperty, value); }
+ }
+
+ [TypeConverter(typeof(FontSizeConverter))]
+ public double FontSize
+ {
+ get { return (double)GetValue(FontSizeProperty); }
+ set { SetValue(FontSizeProperty, value); }
+ }
+
+ static void FontStructPropertyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var label = (Label)bindable;
+ if (label._cancelEvents)
+ return;
+
+ label._cancelEvents = true;
+
+ var font = (Font)newValue;
+ if (font == Font.Default)
+ {
+ label.FontFamily = null;
+ label.FontSize = Device.GetNamedSize(NamedSize.Default, label);
+ label.FontAttributes = FontAttributes.None;
+ }
+ else
+ {
+ label.FontFamily = font.FontFamily;
+ if (font.UseNamedSize)
+ {
+ label.FontSize = Device.GetNamedSize(font.NamedSize, label.GetType(), true);
+ }
+ else
+ {
+ label.FontSize = font.FontSize;
+ }
+ label.FontAttributes = font.FontAttributes;
+ }
+
+ label._cancelEvents = false;
+
+ label.InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+
+ static void OnFontAttributesChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var label = (Label)bindable;
+
+ if (label._cancelEvents)
+ return;
+
+ label._cancelEvents = true;
+
+ var attributes = (FontAttributes)newValue;
+
+ object[] values = label.GetValues(FontFamilyProperty, FontSizeProperty);
+ var family = (string)values[0];
+ if (family != null)
+ {
+ label.Font = Font.OfSize(family, (double)values[1]).WithAttributes(attributes);
+ }
+ else
+ {
+ label.Font = Font.SystemFontOfSize((double)values[1], attributes);
+ }
+
+ label._cancelEvents = false;
+
+ label.InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+
+ static void OnFontFamilyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var label = (Label)bindable;
+ if (label._cancelEvents)
+ return;
+
+ label._cancelEvents = true;
+
+ object[] values = label.GetValues(FontSizeProperty, FontAttributesProperty);
+
+ var family = (string)newValue;
+ if (family != null)
+ {
+ label.Font = Font.OfSize(family, (double)values[0]).WithAttributes((FontAttributes)values[1]);
+ }
+ else
+ {
+ label.Font = Font.SystemFontOfSize((double)values[0], (FontAttributes)values[1]);
+ }
+
+ label._cancelEvents = false;
+ label.InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+
+ static void OnFontSizeChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var label = (Label)bindable;
+ if (label._cancelEvents)
+ return;
+
+ label._cancelEvents = true;
+
+ object[] values = label.GetValues(FontFamilyProperty, FontAttributesProperty);
+
+ var size = (double)newValue;
+ var family = (string)values[0];
+ if (family != null)
+ {
+ label.Font = Font.OfSize(family, size).WithAttributes((FontAttributes)values[1]);
+ }
+ else
+ {
+ label.Font = Font.SystemFontOfSize(size, (FontAttributes)values[1]);
+ }
+
+ label._cancelEvents = false;
+
+ label.InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+
+ void OnFormattedTextChanged(object sender, PropertyChangedEventArgs e)
+ {
+ OnPropertyChanged("FormattedText");
+ }
+
+ static void OnHorizontalTextAlignmentPropertyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var label = (Label)bindable;
+ label.OnPropertyChanged(nameof(XAlign));
+ }
+
+ static void OnTextPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
+ {
+ var label = (Label)bindable;
+ LineBreakMode breakMode = label.LineBreakMode;
+ bool isVerticallyFixed = (label.Constraint & LayoutConstraint.VerticallyFixed) != 0;
+ bool isSingleLine = !(breakMode == LineBreakMode.CharacterWrap || breakMode == LineBreakMode.WordWrap);
+ if (!isVerticallyFixed || !isSingleLine)
+ ((Label)bindable).InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ if (newvalue != null)
+ ((Label)bindable).FormattedText = null;
+ }
+
+ static void OnVerticalTextAlignmentPropertyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var label = (Label)bindable;
+ label.OnPropertyChanged(nameof(YAlign));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Layout.cs b/Xamarin.Forms.Core/Layout.cs
new file mode 100644
index 00000000..c611777c
--- /dev/null
+++ b/Xamarin.Forms.Core/Layout.cs
@@ -0,0 +1,433 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("Children")]
+ public abstract class Layout<T> : Layout, IViewContainer<T> where T : View
+ {
+ readonly ElementCollection<T> _children;
+
+ protected Layout()
+ {
+ _children = new ElementCollection<T>(InternalChildren);
+ }
+
+ public IList<T> Children
+ {
+ get { return _children; }
+ }
+
+ protected virtual void OnAdded(T view)
+ {
+ }
+
+ protected override void OnChildAdded(Element child)
+ {
+ base.OnChildAdded(child);
+
+ var typedChild = child as T;
+ if (typedChild != null)
+ OnAdded(typedChild);
+ }
+
+ protected override void OnChildRemoved(Element child)
+ {
+ base.OnChildRemoved(child);
+
+ var typedChild = child as T;
+ if (typedChild != null)
+ OnRemoved(typedChild);
+ }
+
+ protected virtual void OnRemoved(T view)
+ {
+ }
+ }
+
+ public abstract class Layout : View, ILayout, ILayoutController
+ {
+ public static readonly BindableProperty IsClippedToBoundsProperty = BindableProperty.Create("IsClippedToBounds", typeof(bool), typeof(Layout), false);
+
+ public static readonly BindableProperty PaddingProperty = BindableProperty.Create("Padding", typeof(Thickness), typeof(Layout), default(Thickness), propertyChanged: (bindable, old, newValue) =>
+ {
+ var layout = (Layout)bindable;
+ layout.UpdateChildrenLayout();
+ });
+
+ static IList<KeyValuePair<Layout, int>> s_resolutionList = new List<KeyValuePair<Layout, int>>();
+ static bool s_relayoutInProgress;
+ bool _allocatedFlag;
+
+ bool _hasDoneLayout;
+ Size _lastLayoutSize = new Size(-1, -1);
+
+ ReadOnlyCollection<Element> _logicalChildren;
+
+ protected Layout()
+ {
+ InternalChildren.CollectionChanged += InternalChildrenOnCollectionChanged;
+ }
+
+ public bool IsClippedToBounds
+ {
+ get { return (bool)GetValue(IsClippedToBoundsProperty); }
+ set { SetValue(IsClippedToBoundsProperty, value); }
+ }
+
+ public Thickness Padding
+ {
+ get { return (Thickness)GetValue(PaddingProperty); }
+ set { SetValue(PaddingProperty, value); }
+ }
+
+ internal ObservableCollection<Element> InternalChildren { get; } = new ObservableCollection<Element>();
+
+ internal override ReadOnlyCollection<Element> LogicalChildren
+ {
+ get { return _logicalChildren ?? (_logicalChildren = new ReadOnlyCollection<Element>(InternalChildren)); }
+ }
+
+ public event EventHandler LayoutChanged;
+
+ IReadOnlyList<Element> ILayoutController.Children
+ {
+ get { return InternalChildren; }
+ }
+
+ public void ForceLayout()
+ {
+ SizeAllocated(Width, Height);
+ }
+
+ [Obsolete("Use Measure")]
+ public sealed override SizeRequest GetSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ SizeRequest size = base.GetSizeRequest(widthConstraint - Padding.HorizontalThickness, heightConstraint - Padding.VerticalThickness);
+ return new SizeRequest(new Size(size.Request.Width + Padding.HorizontalThickness, size.Request.Height + Padding.VerticalThickness),
+ new Size(size.Minimum.Width + Padding.HorizontalThickness, size.Minimum.Height + Padding.VerticalThickness));
+ }
+
+ public static void LayoutChildIntoBoundingRegion(VisualElement child, Rectangle region)
+ {
+ var view = child as View;
+ if (view == null)
+ {
+ child.Layout(region);
+ return;
+ }
+
+ LayoutOptions horizontalOptions = view.HorizontalOptions;
+ if (horizontalOptions.Alignment != LayoutAlignment.Fill)
+ {
+ SizeRequest request = child.Measure(region.Width, region.Height, MeasureFlags.IncludeMargins);
+ double diff = Math.Max(0, region.Width - request.Request.Width);
+ region.X += (int)(diff * horizontalOptions.Alignment.ToDouble());
+ region.Width -= diff;
+ }
+
+ LayoutOptions verticalOptions = view.VerticalOptions;
+ if (verticalOptions.Alignment != LayoutAlignment.Fill)
+ {
+ SizeRequest request = child.Measure(region.Width, region.Height, MeasureFlags.IncludeMargins);
+ double diff = Math.Max(0, region.Height - request.Request.Height);
+ region.Y += (int)(diff * verticalOptions.Alignment.ToDouble());
+ region.Height -= diff;
+ }
+
+ Thickness margin = view.Margin;
+ region.X += margin.Left;
+ region.Width -= margin.HorizontalThickness;
+ region.Y += margin.Top;
+ region.Height -= margin.VerticalThickness;
+
+ child.Layout(region);
+ }
+
+ public void LowerChild(View view)
+ {
+ if (!InternalChildren.Contains(view) || InternalChildren.First() == view)
+ return;
+
+ InternalChildren.Move(InternalChildren.IndexOf(view), 0);
+ OnChildrenReordered();
+ }
+
+ public void RaiseChild(View view)
+ {
+ if (!InternalChildren.Contains(view) || InternalChildren.Last() == view)
+ return;
+
+ InternalChildren.Move(InternalChildren.IndexOf(view), InternalChildren.Count - 1);
+ OnChildrenReordered();
+ }
+
+ protected virtual void InvalidateLayout()
+ {
+ _hasDoneLayout = false;
+ InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ if (!_hasDoneLayout)
+ ForceLayout();
+ }
+
+ protected abstract void LayoutChildren(double x, double y, double width, double height);
+
+ protected void OnChildMeasureInvalidated(object sender, EventArgs e)
+ {
+ InvalidationTrigger trigger = (e as InvalidationEventArgs)?.Trigger ?? InvalidationTrigger.Undefined;
+ OnChildMeasureInvalidated((VisualElement)sender, trigger);
+ OnChildMeasureInvalidated();
+ }
+
+ protected virtual void OnChildMeasureInvalidated()
+ {
+ }
+
+ protected override void OnSizeAllocated(double width, double height)
+ {
+ _allocatedFlag = true;
+ base.OnSizeAllocated(width, height);
+ UpdateChildrenLayout();
+ }
+
+ protected virtual bool ShouldInvalidateOnChildAdded(View child)
+ {
+ return true;
+ }
+
+ protected virtual bool ShouldInvalidateOnChildRemoved(View child)
+ {
+ return true;
+ }
+
+ protected void UpdateChildrenLayout()
+ {
+ _hasDoneLayout = true;
+
+ if (!ShouldLayoutChildren())
+ return;
+
+ var oldBounds = new Rectangle[LogicalChildren.Count];
+ for (var index = 0; index < oldBounds.Length; index++)
+ {
+ var c = (VisualElement)LogicalChildren[index];
+ oldBounds[index] = c.Bounds;
+ }
+
+ double width = Width;
+ double height = Height;
+
+ double x = Padding.Left;
+ double y = Padding.Top;
+ double w = Math.Max(0, width - Padding.HorizontalThickness);
+ double h = Math.Max(0, height - Padding.VerticalThickness);
+
+ LayoutChildren(x, y, w, h);
+
+ for (var i = 0; i < oldBounds.Length; i++)
+ {
+ Rectangle oldBound = oldBounds[i];
+ Rectangle newBound = ((VisualElement)LogicalChildren[i]).Bounds;
+ if (oldBound != newBound)
+ {
+ EventHandler handler = LayoutChanged;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ return;
+ }
+ }
+
+ _lastLayoutSize = new Size(width, height);
+ }
+
+ internal static void LayoutChildIntoBoundingRegion(View child, Rectangle region, SizeRequest childSizeRequest)
+ {
+ if (region.Size != childSizeRequest.Request)
+ {
+ bool canUseAlreadyDoneRequest = region.Width >= childSizeRequest.Request.Width && region.Height >= childSizeRequest.Request.Height;
+
+ if (child.HorizontalOptions.Alignment != LayoutAlignment.Fill)
+ {
+ SizeRequest request = canUseAlreadyDoneRequest ? childSizeRequest : child.Measure(region.Width, region.Height, MeasureFlags.IncludeMargins);
+ double diff = Math.Max(0, region.Width - request.Request.Width);
+ region.X += (int)(diff * child.HorizontalOptions.Alignment.ToDouble());
+ region.Width -= diff;
+ }
+
+ if (child.VerticalOptions.Alignment != LayoutAlignment.Fill)
+ {
+ SizeRequest request = canUseAlreadyDoneRequest ? childSizeRequest : child.Measure(region.Width, region.Height, MeasureFlags.IncludeMargins);
+ double diff = Math.Max(0, region.Height - request.Request.Height);
+ region.Y += (int)(diff * child.VerticalOptions.Alignment.ToDouble());
+ region.Height -= diff;
+ }
+ }
+
+ Thickness margin = child.Margin;
+ region.X += margin.Left;
+ region.Width -= margin.HorizontalThickness;
+ region.Y += margin.Top;
+ region.Height -= margin.VerticalThickness;
+
+ child.Layout(region);
+ }
+
+ internal virtual void OnChildMeasureInvalidated(VisualElement child, InvalidationTrigger trigger)
+ {
+ ReadOnlyCollection<Element> children = LogicalChildren;
+ int count = children.Count;
+ for (var index = 0; index < count; index++)
+ {
+ var v = LogicalChildren[index] as VisualElement;
+ if (v != null && v.IsVisible && (!v.IsPlatformEnabled || !v.IsNativeStateConsistent))
+ return;
+ }
+
+ var view = child as View;
+ if (view != null)
+ {
+ // we can ignore the request if we are either fully constrained or when the size request changes and we were already fully constrainted
+ if ((trigger == InvalidationTrigger.MeasureChanged && view.Constraint == LayoutConstraint.Fixed) ||
+ (trigger == InvalidationTrigger.SizeRequestChanged && view.ComputedConstraint == LayoutConstraint.Fixed))
+ {
+ return;
+ }
+ if (trigger == InvalidationTrigger.HorizontalOptionsChanged || trigger == InvalidationTrigger.VerticalOptionsChanged)
+ {
+ ComputeConstraintForView(view);
+ }
+ }
+
+ _allocatedFlag = false;
+ if (trigger == InvalidationTrigger.RendererReady)
+ {
+ InvalidateMeasure(InvalidationTrigger.RendererReady);
+ }
+ else
+ {
+ InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+
+ s_resolutionList.Add(new KeyValuePair<Layout, int>(this, GetElementDepth(this)));
+ if (!s_relayoutInProgress)
+ {
+ s_relayoutInProgress = true;
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ // if thread safety mattered we would need to lock this and compareexchange above
+ IList<KeyValuePair<Layout, int>> copy = s_resolutionList;
+ s_resolutionList = new List<KeyValuePair<Layout, int>>();
+ s_relayoutInProgress = false;
+
+ foreach (KeyValuePair<Layout, int> kvp in copy.OrderBy(kvp => kvp.Value))
+ {
+ Layout layout = kvp.Key;
+ double width = layout.Width, height = layout.Height;
+ if (!layout._allocatedFlag && width >= 0 && height >= 0)
+ {
+ layout.SizeAllocated(width, height);
+ }
+ }
+ });
+ }
+ }
+
+ internal override void OnIsVisibleChanged(bool oldValue, bool newValue)
+ {
+ base.OnIsVisibleChanged(oldValue, newValue);
+ if (newValue)
+ {
+ if (_lastLayoutSize != new Size(Width, Height))
+ {
+ UpdateChildrenLayout();
+ }
+ }
+ }
+
+ static int GetElementDepth(Element view)
+ {
+ var result = 0;
+ while (view.Parent != null)
+ {
+ result++;
+ view = view.Parent;
+ }
+ return result;
+ }
+
+ void InternalChildrenOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ if (e.Action == NotifyCollectionChangedAction.Move)
+ {
+ return;
+ }
+
+ if (e.OldItems != null)
+ {
+ foreach (object item in e.OldItems)
+ {
+ var v = item as View;
+ if (v == null)
+ continue;
+
+ OnInternalRemoved(v);
+ }
+ }
+
+ if (e.NewItems != null)
+ {
+ foreach (object item in e.NewItems)
+ {
+ var v = item as View;
+ if (v == null)
+ continue;
+
+ if (item == this)
+ throw new InvalidOperationException("Can not add self to own child collection.");
+
+ OnInternalAdded(v);
+ }
+ }
+ }
+
+ void OnInternalAdded(View view)
+ {
+ OnChildAdded(view);
+ if (ShouldInvalidateOnChildAdded(view))
+ InvalidateLayout();
+
+ view.MeasureInvalidated += OnChildMeasureInvalidated;
+ }
+
+ void OnInternalRemoved(View view)
+ {
+ view.MeasureInvalidated -= OnChildMeasureInvalidated;
+
+ OnChildRemoved(view);
+ if (ShouldInvalidateOnChildRemoved(view))
+ InvalidateLayout();
+ }
+
+ bool ShouldLayoutChildren()
+ {
+ if (!LogicalChildren.Any() || Width <= 0 || Height <= 0 || !IsVisible || !IsNativeStateConsistent || DisableLayout)
+ return false;
+
+ foreach (Element element in VisibleDescendants())
+ {
+ var visual = element as VisualElement;
+ if (visual == null || !visual.IsVisible)
+ continue;
+
+ if (!visual.IsPlatformEnabled || !visual.IsNativeStateConsistent)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/LayoutAlignment.cs b/Xamarin.Forms.Core/LayoutAlignment.cs
new file mode 100644
index 00000000..04b03e95
--- /dev/null
+++ b/Xamarin.Forms.Core/LayoutAlignment.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [Flags]
+ public enum LayoutAlignment
+ {
+ Start = 0,
+ Center = 1,
+ End = 2,
+ Fill = 3
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/LayoutAlignmentExtensions.cs b/Xamarin.Forms.Core/LayoutAlignmentExtensions.cs
new file mode 100644
index 00000000..a7efcf39
--- /dev/null
+++ b/Xamarin.Forms.Core/LayoutAlignmentExtensions.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ internal static class LayoutAlignmentExtensions
+ {
+ public static double ToDouble(this LayoutAlignment align)
+ {
+ switch (align)
+ {
+ case LayoutAlignment.Start:
+ return 0;
+ case LayoutAlignment.Center:
+ return 0.5;
+ case LayoutAlignment.End:
+ return 1;
+ }
+ throw new ArgumentOutOfRangeException("align");
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/LayoutConstraint.cs b/Xamarin.Forms.Core/LayoutConstraint.cs
new file mode 100644
index 00000000..a9ddc8ec
--- /dev/null
+++ b/Xamarin.Forms.Core/LayoutConstraint.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [Flags]
+ internal enum LayoutConstraint
+ {
+ None = 0,
+ HorizontallyFixed = 1 << 0,
+ VerticallyFixed = 1 << 1,
+ Fixed = HorizontallyFixed | VerticallyFixed
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/LayoutExpandFlag.cs b/Xamarin.Forms.Core/LayoutExpandFlag.cs
new file mode 100644
index 00000000..613d0b4a
--- /dev/null
+++ b/Xamarin.Forms.Core/LayoutExpandFlag.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [Flags]
+ internal enum LayoutExpandFlag
+ {
+ Expand = 4
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/LayoutOptions.cs b/Xamarin.Forms.Core/LayoutOptions.cs
new file mode 100644
index 00000000..a3a900b0
--- /dev/null
+++ b/Xamarin.Forms.Core/LayoutOptions.cs
@@ -0,0 +1,39 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [TypeConverter(typeof(LayoutOptionsConverter))]
+ public struct LayoutOptions
+ {
+ int _flags;
+
+ public static readonly LayoutOptions Start = new LayoutOptions(LayoutAlignment.Start, false);
+ public static readonly LayoutOptions Center = new LayoutOptions(LayoutAlignment.Center, false);
+ public static readonly LayoutOptions End = new LayoutOptions(LayoutAlignment.End, false);
+ public static readonly LayoutOptions Fill = new LayoutOptions(LayoutAlignment.Fill, false);
+ public static readonly LayoutOptions StartAndExpand = new LayoutOptions(LayoutAlignment.Start, true);
+ public static readonly LayoutOptions CenterAndExpand = new LayoutOptions(LayoutAlignment.Center, true);
+ public static readonly LayoutOptions EndAndExpand = new LayoutOptions(LayoutAlignment.End, true);
+ public static readonly LayoutOptions FillAndExpand = new LayoutOptions(LayoutAlignment.Fill, true);
+
+ public LayoutOptions(LayoutAlignment alignment, bool expands)
+ {
+ var a = (int)alignment;
+ if (a < 0 || a > 3)
+ throw new ArgumentOutOfRangeException();
+ _flags = (int)alignment | (expands ? (int)LayoutExpandFlag.Expand : 0);
+ }
+
+ public LayoutAlignment Alignment
+ {
+ get { return (LayoutAlignment)(_flags & 3); }
+ set { _flags = (_flags & ~3) | (int)value; }
+ }
+
+ public bool Expands
+ {
+ get { return (_flags & (int)LayoutExpandFlag.Expand) != 0; }
+ set { _flags = (_flags & 3) | (value ? (int)LayoutExpandFlag.Expand : 0); }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/LayoutOptionsConverter.cs b/Xamarin.Forms.Core/LayoutOptionsConverter.cs
new file mode 100644
index 00000000..746e56ce
--- /dev/null
+++ b/Xamarin.Forms.Core/LayoutOptionsConverter.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Linq;
+using System.Reflection;
+
+namespace Xamarin.Forms
+{
+ public sealed class LayoutOptionsConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString(string value)
+ {
+ if (value != null)
+ {
+ string[] parts = value.Split('.');
+ if (parts.Length > 2 || (parts.Length == 2 && parts[0] != "LayoutOptions"))
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(LayoutOptions)));
+ value = parts[parts.Length - 1];
+ FieldInfo field = typeof(LayoutOptions).GetFields().FirstOrDefault(fi => fi.IsStatic && fi.Name == value);
+ if (field != null)
+ return (LayoutOptions)field.GetValue(null);
+ }
+
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(LayoutOptions)));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/LineBreakMode.cs b/Xamarin.Forms.Core/LineBreakMode.cs
new file mode 100644
index 00000000..c7a36bb8
--- /dev/null
+++ b/Xamarin.Forms.Core/LineBreakMode.cs
@@ -0,0 +1,12 @@
+namespace Xamarin.Forms
+{
+ public enum LineBreakMode
+ {
+ NoWrap,
+ WordWrap,
+ CharacterWrap,
+ HeadTruncation,
+ TailTruncation,
+ MiddleTruncation
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ListProxy.cs b/Xamarin.Forms.Core/ListProxy.cs
new file mode 100644
index 00000000..229dcb6b
--- /dev/null
+++ b/Xamarin.Forms.Core/ListProxy.cs
@@ -0,0 +1,488 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Linq;
+
+namespace Xamarin.Forms
+{
+ internal sealed class ListProxy : IReadOnlyList<object>, IList, INotifyCollectionChanged
+ {
+ readonly ICollection _collection;
+ readonly IList _list;
+ readonly int _windowSize;
+
+ IEnumerator _enumerator;
+ int _enumeratorIndex;
+
+ bool _finished;
+ HashSet<int> _indexesCounted;
+
+ Dictionary<int, object> _items;
+ int _version;
+
+ int _windowIndex;
+
+ internal ListProxy(IEnumerable enumerable, int windowSize = int.MaxValue)
+ {
+ _windowSize = windowSize;
+
+ ProxiedEnumerable = enumerable;
+ _collection = enumerable as ICollection;
+
+ if (_collection == null && enumerable is IReadOnlyCollection<object>)
+ _collection = new ReadOnlyListAdapter((IReadOnlyCollection<object>)enumerable);
+
+ _list = enumerable as IList;
+ if (_list == null && enumerable is IReadOnlyList<object>)
+ _list = new ReadOnlyListAdapter((IReadOnlyList<object>)enumerable);
+
+ var changed = enumerable as INotifyCollectionChanged;
+ if (changed != null)
+ new WeakNotifyProxy(this, changed);
+ }
+
+ public IEnumerable ProxiedEnumerable { get; }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public IEnumerator<object> GetEnumerator()
+ {
+ return new ProxyEnumerator(this);
+ }
+
+ /// <summary>
+ /// Gets whether or not the current window contains the <paramref name="item" />.
+ /// </summary>
+ /// <param name="item">The item to search for.</param>
+ /// <returns><c>true</c> if the item was found in a list or the current window, <c>false</c> otherwise.</returns>
+ public bool Contains(object item)
+ {
+ if (_list != null)
+ return _list.Contains(item);
+
+ EnsureWindowCreated();
+
+ if (_items != null)
+ return _items.Values.Contains(item);
+
+ return false;
+ }
+
+ /// <summary>
+ /// Gets the index for the <paramref name="item" /> if in a list or the current window.
+ /// </summary>
+ /// <param name="item">The item to search for.</param>
+ /// <returns>The index of the item if in a list or the current window, -1 otherwise.</returns>
+ public int IndexOf(object item)
+ {
+ if (_list != null)
+ return _list.IndexOf(item);
+
+ EnsureWindowCreated();
+
+ if (_items != null)
+ {
+ foreach (KeyValuePair<int, object> kvp in _items)
+ {
+ if (Equals(kvp.Value, item))
+ return kvp.Key;
+ }
+ }
+
+ return -1;
+ }
+
+ public event NotifyCollectionChangedEventHandler CollectionChanged;
+
+ public int Count
+ {
+ get
+ {
+ if (_collection != null)
+ return _collection.Count;
+
+ EnsureWindowCreated();
+
+ if (_indexesCounted != null)
+ return _indexesCounted.Count;
+
+ return 0;
+ }
+ }
+
+ public object this[int index]
+ {
+ get
+ {
+ object value;
+ if (!TryGetValue(index, out value))
+ throw new ArgumentOutOfRangeException("index");
+
+ return value;
+ }
+ }
+
+ public void Clear()
+ {
+ _version++;
+ _finished = false;
+ _windowIndex = 0;
+ _enumeratorIndex = 0;
+
+ if (_enumerator != null)
+ {
+ var dispose = _enumerator as IDisposable;
+ if (dispose != null)
+ dispose.Dispose();
+
+ _enumerator = null;
+ }
+
+ if (_items != null)
+ _items.Clear();
+ if (_indexesCounted != null)
+ _indexesCounted.Clear();
+
+ OnCountChanged();
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ }
+
+ public event EventHandler CountChanged;
+
+ void ClearRange(int index, int clearCount)
+ {
+ if (_items == null)
+ return;
+
+ for (int i = index; i < index + clearCount; i++)
+ _items.Remove(i);
+ }
+
+ bool CountIndex(int index)
+ {
+ if (_collection != null)
+ return false;
+
+ // A collection is used in case TryGetValue is called out of order.
+ if (_indexesCounted == null)
+ _indexesCounted = new HashSet<int>();
+
+ if (_indexesCounted.Contains(index))
+ return false;
+
+ _indexesCounted.Add(index);
+ return true;
+ }
+
+ void EnsureWindowCreated()
+ {
+ if (_items != null && _items.Count > 0)
+ return;
+
+ object value;
+ TryGetValue(0, out value);
+ }
+
+ void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ Action action;
+ if (_list == null)
+ {
+ action = Clear;
+ }
+ else
+ {
+ action = () =>
+ {
+ _version++;
+ OnCollectionChanged(e);
+ };
+ }
+
+ CollectionSynchronizationContext sync;
+ if (BindingBase.TryGetSynchronizedCollection(ProxiedEnumerable, out sync))
+ {
+ sync.Callback(ProxiedEnumerable, sync.Context, () =>
+ {
+ e = e.WithCount(Count);
+ Device.BeginInvokeOnMainThread(action);
+ }, false);
+ }
+ else
+ {
+ e = e.WithCount(Count);
+ if (Device.IsInvokeRequired)
+ Device.BeginInvokeOnMainThread(action);
+ else
+ action();
+ }
+ }
+
+ void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
+ {
+ NotifyCollectionChangedEventHandler changed = CollectionChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ void OnCountChanged()
+ {
+ EventHandler changed = CountChanged;
+ if (changed != null)
+ changed(this, EventArgs.Empty);
+ }
+
+ bool TryGetValue(int index, out object value)
+ {
+ value = null;
+
+ CollectionSynchronizationContext syncContext;
+ BindingBase.TryGetSynchronizedCollection(ProxiedEnumerable, out syncContext);
+
+ if (_list != null)
+ {
+ object indexedValue = null;
+ var inRange = false;
+ Action getFromList = () =>
+ {
+ if (index >= _list.Count)
+ return;
+
+ indexedValue = _list[index];
+ inRange = true;
+ };
+
+ if (syncContext != null)
+ syncContext.Callback(ProxiedEnumerable, syncContext.Context, getFromList, false);
+ else
+ getFromList();
+
+ value = indexedValue;
+ return inRange;
+ }
+
+ if (_collection != null && index >= _collection.Count)
+ return false;
+ if (_items != null)
+ {
+ bool found = _items.TryGetValue(index, out value);
+ if (found || _finished)
+ return found;
+ }
+
+ if (index >= _windowIndex + _windowSize)
+ {
+ int newIndex = index - _windowSize / 2;
+ ClearRange(_windowIndex, newIndex - _windowIndex);
+ _windowIndex = newIndex;
+ }
+ else if (index < _windowIndex)
+ {
+ int clearIndex = _windowIndex;
+ int clearSize = _windowSize;
+ if (clearIndex <= index + clearSize)
+ {
+ int diff = index + clearSize - clearIndex;
+ clearIndex += diff + 1;
+ clearSize -= diff;
+ }
+
+ ClearRange(clearIndex, clearSize);
+ _windowIndex = 0;
+
+ var dispose = _enumerator as IDisposable;
+ if (dispose != null)
+ dispose.Dispose();
+
+ _enumerator = null;
+ _enumeratorIndex = 0;
+ }
+
+ if (_enumerator == null)
+ _enumerator = ProxiedEnumerable.GetEnumerator();
+ if (_items == null)
+ _items = new Dictionary<int, object>();
+
+ var countChanged = false;
+ int end = _windowIndex + _windowSize;
+
+ for (; _enumeratorIndex < end; _enumeratorIndex++)
+ {
+ var moved = false;
+ Action move = () =>
+ {
+ try
+ {
+ moved = _enumerator.MoveNext();
+ }
+ catch (InvalidOperationException ioex)
+ {
+ throw new InvalidOperationException("You must call UpdateNonNotifyingList() after updating a list that does not implement INotifyCollectionChanged", ioex);
+ }
+
+ if (!moved)
+ {
+ var dispose = _enumerator as IDisposable;
+ if (dispose != null)
+ dispose.Dispose();
+
+ _enumerator = null;
+ _enumeratorIndex = 0;
+ _finished = true;
+ }
+ };
+
+ if (syncContext == null)
+ move();
+ else
+ syncContext.Callback(ProxiedEnumerable, syncContext.Context, move, false);
+
+ if (!moved)
+ break;
+
+ if (CountIndex(_enumeratorIndex))
+ countChanged = true;
+
+ if (_enumeratorIndex >= _windowIndex)
+ _items.Add(_enumeratorIndex, _enumerator.Current);
+ }
+
+ if (countChanged)
+ OnCountChanged();
+
+ return _items.TryGetValue(index, out value);
+ }
+
+ class WeakNotifyProxy
+ {
+ readonly WeakReference<INotifyCollectionChanged> _weakCollection;
+ readonly WeakReference<ListProxy> _weakProxy;
+
+ public WeakNotifyProxy(ListProxy proxy, INotifyCollectionChanged incc)
+ {
+ incc.CollectionChanged += OnCollectionChanged;
+
+ _weakProxy = new WeakReference<ListProxy>(proxy);
+ _weakCollection = new WeakReference<INotifyCollectionChanged>(incc);
+ }
+
+ void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ ListProxy proxy;
+ if (!_weakProxy.TryGetTarget(out proxy))
+ {
+ INotifyCollectionChanged collection;
+ if (_weakCollection.TryGetTarget(out collection))
+ collection.CollectionChanged -= OnCollectionChanged;
+
+ return;
+ }
+
+ proxy.OnCollectionChanged(sender, e);
+ }
+ }
+
+ class ProxyEnumerator : IEnumerator<object>
+ {
+ readonly ListProxy _proxy;
+ readonly int _version;
+
+ int _index;
+
+ public ProxyEnumerator(ListProxy proxy)
+ {
+ _proxy = proxy;
+ _version = proxy._version;
+ }
+
+ public void Dispose()
+ {
+ }
+
+ public bool MoveNext()
+ {
+ if (_proxy._version != _version)
+ throw new InvalidOperationException();
+
+ object value;
+ bool next = _proxy.TryGetValue(_index++, out value);
+ if (next)
+ Current = value;
+
+ return next;
+ }
+
+ public void Reset()
+ {
+ _index = 0;
+ Current = null;
+ }
+
+ public object Current { get; private set; }
+ }
+
+ #region IList
+
+ object IList.this[int index]
+ {
+ get { return this[index]; }
+ set { throw new NotSupportedException(); }
+ }
+
+ bool IList.IsReadOnly
+ {
+ get { return true; }
+ }
+
+ bool IList.IsFixedSize
+ {
+ get { return false; }
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ get { return false; }
+ }
+
+ object ICollection.SyncRoot
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ void ICollection.CopyTo(Array array, int index)
+ {
+ throw new NotSupportedException();
+ }
+
+ int IList.Add(object item)
+ {
+ throw new NotSupportedException();
+ }
+
+ void IList.Remove(object item)
+ {
+ throw new NotSupportedException();
+ }
+
+ void IList.Insert(int index, object item)
+ {
+ throw new NotSupportedException();
+ }
+
+ void IList.RemoveAt(int index)
+ {
+ throw new NotSupportedException();
+ }
+
+ void IList.Clear()
+ {
+ throw new NotSupportedException();
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ListView.cs b/Xamarin.Forms.Core/ListView.cs
new file mode 100644
index 00000000..3d29033a
--- /dev/null
+++ b/Xamarin.Forms.Core/ListView.cs
@@ -0,0 +1,540 @@
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.Windows.Input;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_ListViewRenderer))]
+ public class ListView : ItemsView<Cell>, IListViewController
+
+ {
+ public static readonly BindableProperty IsPullToRefreshEnabledProperty = BindableProperty.Create("IsPullToRefreshEnabled", typeof(bool), typeof(ListView), false);
+
+ public static readonly BindableProperty IsRefreshingProperty = BindableProperty.Create("IsRefreshing", typeof(bool), typeof(ListView), false, BindingMode.TwoWay);
+
+ public static readonly BindableProperty RefreshCommandProperty = BindableProperty.Create("RefreshCommand", typeof(ICommand), typeof(ListView), null, propertyChanged: OnRefreshCommandChanged);
+
+ public static readonly BindableProperty HeaderProperty = BindableProperty.Create("Header", typeof(object), typeof(ListView), null, propertyChanged: OnHeaderChanged);
+
+ public static readonly BindableProperty HeaderTemplateProperty = BindableProperty.Create("HeaderTemplate", typeof(DataTemplate), typeof(ListView), null, propertyChanged: OnHeaderTemplateChanged,
+ validateValue: ValidateHeaderFooterTemplate);
+
+ public static readonly BindableProperty FooterProperty = BindableProperty.Create("Footer", typeof(object), typeof(ListView), null, propertyChanged: OnFooterChanged);
+
+ public static readonly BindableProperty FooterTemplateProperty = BindableProperty.Create("FooterTemplate", typeof(DataTemplate), typeof(ListView), null, propertyChanged: OnFooterTemplateChanged,
+ validateValue: ValidateHeaderFooterTemplate);
+
+ public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create("SelectedItem", typeof(object), typeof(ListView), null, BindingMode.OneWayToSource,
+ propertyChanged: OnSelectedItemChanged);
+
+ public static readonly BindableProperty HasUnevenRowsProperty = BindableProperty.Create("HasUnevenRows", typeof(bool), typeof(ListView), false);
+
+ public static readonly BindableProperty RowHeightProperty = BindableProperty.Create("RowHeight", typeof(int), typeof(ListView), -1);
+
+ public static readonly BindableProperty GroupHeaderTemplateProperty = BindableProperty.Create("GroupHeaderTemplate", typeof(DataTemplate), typeof(ListView), null,
+ propertyChanged: OnGroupHeaderTemplateChanged);
+
+ public static readonly BindableProperty IsGroupingEnabledProperty = BindableProperty.Create("IsGroupingEnabled", typeof(bool), typeof(ListView), false);
+
+ public static readonly BindableProperty SeparatorVisibilityProperty = BindableProperty.Create("SeparatorVisibility", typeof(SeparatorVisibility), typeof(ListView), SeparatorVisibility.Default);
+
+ public static readonly BindableProperty SeparatorColorProperty = BindableProperty.Create("SeparatorColor", typeof(Color), typeof(ListView), Color.Default);
+
+ BindingBase _groupDisplayBinding;
+
+ BindingBase _groupShortNameBinding;
+ Element _headerElement;
+ Element _footerElement;
+
+ ScrollToRequestedEventArgs _pendingScroll;
+ int _previousGroupSelected = -1;
+ int _previousRowSelected = -1;
+
+ /// <summary>
+ /// Controls whether anything happens in BeginRefresh(), is set based on RefreshCommand.CanExecute
+ /// </summary>
+ bool _refreshAllowed = true;
+
+ public ListView()
+ {
+ TakePerformanceHit = false;
+
+ VerticalOptions = HorizontalOptions = LayoutOptions.FillAndExpand;
+
+ TemplatedItems.IsGroupingEnabledProperty = IsGroupingEnabledProperty;
+ TemplatedItems.GroupHeaderTemplateProperty = GroupHeaderTemplateProperty;
+ }
+
+ public ListView([Parameter("CachingStrategy")] ListViewCachingStrategy cachingStrategy) : this()
+ {
+ if (Device.OS == TargetPlatform.Android || Device.OS == TargetPlatform.iOS)
+ CachingStrategy = cachingStrategy;
+ }
+
+ public object Footer
+ {
+ get { return GetValue(FooterProperty); }
+ set { SetValue(FooterProperty, value); }
+ }
+
+ public DataTemplate FooterTemplate
+ {
+ get { return (DataTemplate)GetValue(FooterTemplateProperty); }
+ set { SetValue(FooterTemplateProperty, value); }
+ }
+
+ public BindingBase GroupDisplayBinding
+ {
+ get { return _groupDisplayBinding; }
+ set
+ {
+ if (_groupDisplayBinding == value)
+ return;
+
+ OnPropertyChanging();
+ BindingBase oldValue = value;
+ _groupDisplayBinding = value;
+ OnGroupDisplayBindingChanged(this, oldValue, _groupDisplayBinding);
+ TemplatedItems.GroupDisplayBinding = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public DataTemplate GroupHeaderTemplate
+ {
+ get { return (DataTemplate)GetValue(GroupHeaderTemplateProperty); }
+ set { SetValue(GroupHeaderTemplateProperty, value); }
+ }
+
+ public BindingBase GroupShortNameBinding
+ {
+ get { return _groupShortNameBinding; }
+ set
+ {
+ if (_groupShortNameBinding == value)
+ return;
+
+ OnPropertyChanging();
+ _groupShortNameBinding = value;
+ TemplatedItems.GroupShortNameBinding = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public bool HasUnevenRows
+ {
+ get { return (bool)GetValue(HasUnevenRowsProperty); }
+ set { SetValue(HasUnevenRowsProperty, value); }
+ }
+
+ public object Header
+ {
+ get { return GetValue(HeaderProperty); }
+ set { SetValue(HeaderProperty, value); }
+ }
+
+ public DataTemplate HeaderTemplate
+ {
+ get { return (DataTemplate)GetValue(HeaderTemplateProperty); }
+ set { SetValue(HeaderTemplateProperty, value); }
+ }
+
+ public bool IsGroupingEnabled
+ {
+ get { return (bool)GetValue(IsGroupingEnabledProperty); }
+ set { SetValue(IsGroupingEnabledProperty, value); }
+ }
+
+ public bool IsPullToRefreshEnabled
+ {
+ get { return (bool)GetValue(IsPullToRefreshEnabledProperty); }
+ set { SetValue(IsPullToRefreshEnabledProperty, value); }
+ }
+
+ public bool IsRefreshing
+ {
+ get { return (bool)GetValue(IsRefreshingProperty); }
+ set { SetValue(IsRefreshingProperty, value); }
+ }
+
+ public ICommand RefreshCommand
+ {
+ get { return (ICommand)GetValue(RefreshCommandProperty); }
+ set { SetValue(RefreshCommandProperty, value); }
+ }
+
+ public int RowHeight
+ {
+ get { return (int)GetValue(RowHeightProperty); }
+ set { SetValue(RowHeightProperty, value); }
+ }
+
+ public object SelectedItem
+ {
+ get { return GetValue(SelectedItemProperty); }
+ set { SetValue(SelectedItemProperty, value); }
+ }
+
+ public Color SeparatorColor
+ {
+ get { return (Color)GetValue(SeparatorColorProperty); }
+ set { SetValue(SeparatorColorProperty, value); }
+ }
+
+ public SeparatorVisibility SeparatorVisibility
+ {
+ get { return (SeparatorVisibility)GetValue(SeparatorVisibilityProperty); }
+ set { SetValue(SeparatorVisibilityProperty, value); }
+ }
+
+ internal ListViewCachingStrategy CachingStrategy { get; private set; }
+
+ internal bool TakePerformanceHit { get; set; }
+
+ bool RefreshAllowed
+ {
+ set
+ {
+ if (_refreshAllowed == value)
+ return;
+
+ _refreshAllowed = value;
+ OnPropertyChanged();
+ }
+ get { return _refreshAllowed; }
+ }
+
+ Element IListViewController.FooterElement
+ {
+ get { return _footerElement; }
+ }
+
+ Element IListViewController.HeaderElement
+ {
+ get { return _headerElement; }
+ }
+
+ bool IListViewController.RefreshAllowed
+ {
+ get { return RefreshAllowed; }
+ }
+
+ void IListViewController.SendCellAppearing(Cell cell)
+ {
+ EventHandler<ItemVisibilityEventArgs> handler = ItemAppearing;
+ if (handler != null)
+ handler(this, new ItemVisibilityEventArgs(cell.BindingContext));
+ }
+
+ void IListViewController.SendCellDisappearing(Cell cell)
+ {
+ EventHandler<ItemVisibilityEventArgs> handler = ItemDisappearing;
+ if (handler != null)
+ handler(this, new ItemVisibilityEventArgs(cell.BindingContext));
+ }
+
+ void IListViewController.SendRefreshing()
+ {
+ BeginRefresh();
+ }
+
+ public void BeginRefresh()
+ {
+ if (!RefreshAllowed)
+ return;
+
+ SetValueCore(IsRefreshingProperty, true);
+ OnRefreshing(EventArgs.Empty);
+
+ ICommand command = RefreshCommand;
+ if (command != null)
+ command.Execute(null);
+ }
+
+ public void EndRefresh()
+ {
+ SetValueCore(IsRefreshingProperty, false);
+ }
+
+ public event EventHandler<ItemVisibilityEventArgs> ItemAppearing;
+
+ public event EventHandler<ItemVisibilityEventArgs> ItemDisappearing;
+
+ public event EventHandler<SelectedItemChangedEventArgs> ItemSelected;
+
+ public event EventHandler<ItemTappedEventArgs> ItemTapped;
+
+ public event EventHandler Refreshing;
+
+ public void ScrollTo(object item, ScrollToPosition position, bool animated)
+ {
+ if (!Enum.IsDefined(typeof(ScrollToPosition), position))
+ throw new ArgumentException("position is not a valid ScrollToPosition", "position");
+
+ var args = new ScrollToRequestedEventArgs(item, position, animated);
+ if (IsPlatformEnabled)
+ OnScrollToRequested(args);
+ else
+ _pendingScroll = args;
+ }
+
+ public void ScrollTo(object item, object group, ScrollToPosition position, bool animated)
+ {
+ if (!IsGroupingEnabled)
+ throw new InvalidOperationException("Grouping is not enabled");
+ if (!Enum.IsDefined(typeof(ScrollToPosition), position))
+ throw new ArgumentException("position is not a valid ScrollToPosition", "position");
+
+ var args = new ScrollToRequestedEventArgs(item, group, position, animated);
+ if (IsPlatformEnabled)
+ OnScrollToRequested(args);
+ else
+ _pendingScroll = args;
+ }
+
+ protected override Cell CreateDefault(object item)
+ {
+ string text = null;
+ if (item != null)
+ text = item.ToString();
+
+ return new TextCell { Text = text };
+ }
+
+ [Obsolete("Use OnMeasure")]
+ protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ var minimumSize = new Size(40, 40);
+ Size request;
+
+ double width = Math.Min(Device.Info.ScaledScreenSize.Width, Device.Info.ScaledScreenSize.Height);
+
+ var list = ItemsSource as IList;
+ if (list != null && HasUnevenRows == false && RowHeight > 0 && !IsGroupingEnabled)
+ {
+ // we can calculate this
+ request = new Size(width, list.Count * RowHeight);
+ }
+ else
+ {
+ // probably not worth it
+ request = new Size(width, Math.Max(Device.Info.ScaledScreenSize.Width, Device.Info.ScaledScreenSize.Height));
+ }
+
+ return new SizeRequest(request, minimumSize);
+ }
+
+ protected override void SetupContent(Cell content, int index)
+ {
+ base.SetupContent(content, index);
+ content.Parent = this;
+ }
+
+ protected override void UnhookContent(Cell content)
+ {
+ base.UnhookContent(content);
+ content.Parent = null;
+ }
+
+ internal Cell CreateDefaultCell(object item)
+ {
+ return CreateDefault(item);
+ }
+
+ internal void NotifyRowTapped(int groupIndex, int inGroupIndex, Cell cell = null)
+ {
+ TemplatedItemsList<ItemsView<Cell>, Cell> group = TemplatedItems.GetGroup(groupIndex);
+
+ bool changed = _previousGroupSelected != groupIndex || _previousRowSelected != inGroupIndex;
+
+ _previousRowSelected = inGroupIndex;
+ _previousGroupSelected = groupIndex;
+ if (cell == null)
+ {
+ cell = group[inGroupIndex];
+ }
+
+ // Set SelectedItem before any events so we don't override any changes they may have made.
+ SetValueCore(SelectedItemProperty, cell.BindingContext, SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearDynamicResource | (changed ? SetValueFlags.RaiseOnEqual : 0));
+
+ cell.OnTapped();
+
+ ItemTapped?.Invoke(this, new ItemTappedEventArgs(group, cell.BindingContext));
+ }
+
+ internal void NotifyRowTapped(int index, Cell cell = null)
+ {
+ if (IsGroupingEnabled)
+ {
+ int leftOver;
+ int groupIndex = TemplatedItems.GetGroupIndexFromGlobal(index, out leftOver);
+
+ NotifyRowTapped(groupIndex, leftOver - 1, cell);
+ }
+ else
+ NotifyRowTapped(0, index, cell);
+ }
+
+ internal override void OnIsPlatformEnabledChanged()
+ {
+ base.OnIsPlatformEnabledChanged();
+
+ if (IsPlatformEnabled && _pendingScroll != null)
+ {
+ OnScrollToRequested(_pendingScroll);
+ _pendingScroll = null;
+ }
+ }
+
+ internal event EventHandler<ScrollToRequestedEventArgs> ScrollToRequested;
+
+ void OnCommandCanExecuteChanged(object sender, EventArgs eventArgs)
+ {
+ RefreshAllowed = RefreshCommand.CanExecute(null);
+ }
+
+ static void OnFooterChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var lv = (ListView)bindable;
+ lv.OnHeaderOrFooterChanged(ref lv._footerElement, "FooterElement", newValue, lv.FooterTemplate, false);
+ }
+
+ static void OnFooterTemplateChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var lv = (ListView)bindable;
+ lv.OnHeaderOrFooterChanged(ref lv._footerElement, "FooterElement", lv.Footer, (DataTemplate)newValue, true);
+ }
+
+ static void OnGroupDisplayBindingChanged(BindableObject bindable, BindingBase oldValue, BindingBase newValue)
+ {
+ var lv = (ListView)bindable;
+ if (newValue != null && lv.GroupHeaderTemplate != null)
+ {
+ lv.GroupHeaderTemplate = null;
+ Log.Warning("ListView", "GroupHeaderTemplate and GroupDisplayBinding can not be set at the same time, setting GroupHeaderTemplate to null");
+ }
+ }
+
+ static void OnGroupHeaderTemplateChanged(BindableObject bindable, object oldvalue, object newValue)
+ {
+ var lv = (ListView)bindable;
+ if (newValue != null && lv.GroupDisplayBinding != null)
+ {
+ lv.GroupDisplayBinding = null;
+ Debug.WriteLine("GroupHeaderTemplate and GroupDisplayBinding can not be set at the same time, setting GroupDisplayBinding to null");
+ }
+ }
+
+ static void OnHeaderChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var lv = (ListView)bindable;
+ lv.OnHeaderOrFooterChanged(ref lv._headerElement, "HeaderElement", newValue, lv.HeaderTemplate, false);
+ }
+
+ void OnHeaderOrFooterChanged(ref Element storage, string property, object dataObject, DataTemplate template, bool templateChanged)
+ {
+ if (dataObject == null)
+ {
+ if (!templateChanged)
+ {
+ OnPropertyChanging(property);
+ storage = null;
+ OnPropertyChanged(property);
+ }
+
+ return;
+ }
+
+ if (template == null)
+ {
+ var view = dataObject as Element;
+ if (view == null || view is Page)
+ view = new Label { Text = dataObject.ToString() };
+
+ view.Parent = this;
+ OnPropertyChanging(property);
+ storage = view;
+ OnPropertyChanged(property);
+ }
+ else if (storage == null || templateChanged)
+ {
+ OnPropertyChanging(property);
+ storage = template.CreateContent() as Element;
+ if (storage != null)
+ {
+ storage.BindingContext = dataObject;
+ storage.Parent = this;
+ }
+ OnPropertyChanged(property);
+ }
+ else
+ {
+ storage.BindingContext = dataObject;
+ }
+ }
+
+ static void OnHeaderTemplateChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var lv = (ListView)bindable;
+ lv.OnHeaderOrFooterChanged(ref lv._headerElement, "HeaderElement", lv.Header, (DataTemplate)newValue, true);
+ }
+
+ static void OnRefreshCommandChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var lv = (ListView)bindable;
+ var oldCommand = (ICommand)oldValue;
+ var command = (ICommand)newValue;
+
+ lv.OnRefreshCommandChanged(oldCommand, command);
+ }
+
+ void OnRefreshCommandChanged(ICommand oldCommand, ICommand newCommand)
+ {
+ if (oldCommand != null)
+ {
+ oldCommand.CanExecuteChanged -= OnCommandCanExecuteChanged;
+ }
+
+ if (newCommand != null)
+ {
+ newCommand.CanExecuteChanged += OnCommandCanExecuteChanged;
+ RefreshAllowed = newCommand.CanExecute(null);
+ }
+ else
+ {
+ RefreshAllowed = true;
+ }
+ }
+
+ void OnRefreshing(EventArgs e)
+ {
+ EventHandler handler = Refreshing;
+ if (handler != null)
+ handler(this, e);
+ }
+
+ void OnScrollToRequested(ScrollToRequestedEventArgs e)
+ {
+ EventHandler<ScrollToRequestedEventArgs> handler = ScrollToRequested;
+ if (handler != null)
+ handler(this, e);
+ }
+
+ static void OnSelectedItemChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var list = (ListView)bindable;
+ if (list.ItemSelected != null)
+ list.ItemSelected(list, new SelectedItemChangedEventArgs(newValue));
+ }
+
+ static bool ValidateHeaderFooterTemplate(BindableObject bindable, object value)
+ {
+ if (value == null)
+ return true;
+ var template = (DataTemplate)value;
+ return template.CreateContent() is View;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ListViewCachingStrategy.cs b/Xamarin.Forms.Core/ListViewCachingStrategy.cs
new file mode 100644
index 00000000..7dd90196
--- /dev/null
+++ b/Xamarin.Forms.Core/ListViewCachingStrategy.cs
@@ -0,0 +1,8 @@
+namespace Xamarin.Forms
+{
+ public enum ListViewCachingStrategy
+ {
+ RetainElement = 0,
+ RecycleElement
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/LockingSemaphore.cs b/Xamarin.Forms.Core/LockingSemaphore.cs
new file mode 100644
index 00000000..b9fd20a9
--- /dev/null
+++ b/Xamarin.Forms.Core/LockingSemaphore.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ internal class LockingSemaphore
+ {
+ static readonly Task Completed = Task.FromResult(true);
+ readonly Queue<TaskCompletionSource<bool>> _waiters = new Queue<TaskCompletionSource<bool>>();
+ int _currentCount;
+
+ public LockingSemaphore(int initialCount)
+ {
+ if (initialCount < 0)
+ throw new ArgumentOutOfRangeException("initialCount");
+ _currentCount = initialCount;
+ }
+
+ public void Release()
+ {
+ TaskCompletionSource<bool> toRelease = null;
+ lock(_waiters)
+ {
+ if (_waiters.Count > 0)
+ toRelease = _waiters.Dequeue();
+ else
+ ++_currentCount;
+ }
+ if (toRelease != null)
+ toRelease.TrySetResult(true);
+ }
+
+ public Task WaitAsync(CancellationToken token)
+ {
+ lock(_waiters)
+ {
+ if (_currentCount > 0)
+ {
+ --_currentCount;
+ return Completed;
+ }
+ var waiter = new TaskCompletionSource<bool>();
+ _waiters.Enqueue(waiter);
+ token.Register(() => waiter.TrySetCanceled());
+ return waiter.Task;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Log.cs b/Xamarin.Forms.Core/Log.cs
new file mode 100644
index 00000000..b8053e5d
--- /dev/null
+++ b/Xamarin.Forms.Core/Log.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ internal static class Log
+ {
+ static Log()
+ {
+ Listeners = new SynchronizedList<LogListener>();
+ }
+
+ public static IList<LogListener> Listeners { get; }
+
+ public static void Warning(string category, string message)
+ {
+ foreach (LogListener listener in Listeners)
+ listener.Warning(category, message);
+ }
+
+ public static void Warning(string category, string format, params object[] args)
+ {
+ Warning(category, string.Format(format, args));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/LogListener.cs b/Xamarin.Forms.Core/LogListener.cs
new file mode 100644
index 00000000..78222565
--- /dev/null
+++ b/Xamarin.Forms.Core/LogListener.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms
+{
+ internal abstract class LogListener
+ {
+ public abstract void Warning(string category, string message);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/MasterBehavior.cs b/Xamarin.Forms.Core/MasterBehavior.cs
new file mode 100644
index 00000000..cd2dae2f
--- /dev/null
+++ b/Xamarin.Forms.Core/MasterBehavior.cs
@@ -0,0 +1,11 @@
+namespace Xamarin.Forms
+{
+ public enum MasterBehavior
+ {
+ Default = 0,
+ SplitOnLandscape = 1,
+ Split = 2,
+ Popover = 3,
+ SplitOnPortrait = 4
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/MasterDetailPage.cs b/Xamarin.Forms.Core/MasterDetailPage.cs
new file mode 100644
index 00000000..a0849aa4
--- /dev/null
+++ b/Xamarin.Forms.Core/MasterDetailPage.cs
@@ -0,0 +1,229 @@
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_MasterDetailPageRenderer))]
+ public class MasterDetailPage : Page
+ {
+ public static readonly BindableProperty IsGestureEnabledProperty = BindableProperty.Create("IsGestureEnabled", typeof(bool), typeof(MasterDetailPage), true);
+
+ public static readonly BindableProperty IsPresentedProperty = BindableProperty.Create("IsPresented", typeof(bool), typeof(MasterDetailPage), default(bool),
+ propertyChanged: OnIsPresentedPropertyChanged, propertyChanging: OnIsPresentedPropertyChanging);
+
+ public static readonly BindableProperty MasterBehaviorProperty = BindableProperty.Create("MasterBehavior", typeof(MasterBehavior), typeof(MasterDetailPage), default(MasterBehavior),
+ propertyChanged: OnMasterBehaviorPropertyChanged);
+
+ Page _detail;
+
+ Rectangle _detailBounds;
+
+ Page _master;
+
+ Rectangle _masterBounds;
+
+ public Page Detail
+ {
+ get { return _detail; }
+ set
+ {
+ if (_detail != null && value == null)
+ throw new ArgumentNullException("value", "Detail cannot be set to null once a value is set.");
+
+ if (_detail == value)
+ return;
+
+ if (value.RealParent != null)
+ throw new InvalidOperationException("Detail must not already have a parent.");
+
+ OnPropertyChanging();
+ if (_detail != null)
+ InternalChildren.Remove(_detail);
+ _detail = value;
+ InternalChildren.Add(_detail);
+ OnPropertyChanged();
+ }
+ }
+
+ public bool IsGestureEnabled
+ {
+ get { return (bool)GetValue(IsGestureEnabledProperty); }
+ set { SetValue(IsGestureEnabledProperty, value); }
+ }
+
+ public bool IsPresented
+ {
+ get { return (bool)GetValue(IsPresentedProperty); }
+ set { SetValue(IsPresentedProperty, value); }
+ }
+
+ public Page Master
+ {
+ get { return _master; }
+ set
+ {
+ if (_master != null && value == null)
+ throw new ArgumentNullException("value", "Master cannot be set to null once a value is set");
+
+ if (string.IsNullOrEmpty(value.Title))
+ throw new InvalidOperationException("Title property must be set on Master page");
+
+ if (_master == value)
+ return;
+
+ if (value.RealParent != null)
+ throw new InvalidOperationException("Master must not already have a parent.");
+
+ OnPropertyChanging();
+ if (_master != null)
+ InternalChildren.Remove(_master);
+ _master = value;
+ InternalChildren.Add(_master);
+ OnPropertyChanged();
+ }
+ }
+
+ public MasterBehavior MasterBehavior
+ {
+ get { return (MasterBehavior)GetValue(MasterBehaviorProperty); }
+ set { SetValue(MasterBehaviorProperty, value); }
+ }
+
+ internal bool CanChangeIsPresented { get; set; } = true;
+
+ internal Rectangle DetailBounds
+ {
+ get { return _detailBounds; }
+ set
+ {
+ _detailBounds = value;
+ if (_detail == null)
+ throw new InvalidOperationException("Detail must be set before using a MasterDetailPage");
+ _detail.Layout(value);
+ }
+ }
+
+ internal Rectangle MasterBounds
+ {
+ get { return _masterBounds; }
+ set
+ {
+ _masterBounds = value;
+ if (_master == null)
+ throw new InvalidOperationException("Master must be set before using a MasterDetailPage");
+ _master.Layout(value);
+ }
+ }
+
+ internal bool ShouldShowSplitMode
+ {
+ get
+ {
+ if (Device.Idiom == TargetIdiom.Phone)
+ return false;
+
+ MasterBehavior behavior = MasterBehavior;
+ DeviceOrientation orientation = Device.Info.CurrentOrientation;
+
+ bool isSplitOnLandscape = (behavior == MasterBehavior.SplitOnLandscape || behavior == MasterBehavior.Default) && orientation.IsLandscape();
+ bool isSplitOnPortrait = behavior == MasterBehavior.SplitOnPortrait && orientation.IsPortrait();
+ return behavior == MasterBehavior.Split || isSplitOnLandscape || isSplitOnPortrait;
+ }
+ }
+
+ public event EventHandler IsPresentedChanged;
+
+ public virtual bool ShouldShowToolbarButton()
+ {
+ if (Device.Idiom == TargetIdiom.Phone)
+ return true;
+
+ MasterBehavior behavior = MasterBehavior;
+ DeviceOrientation orientation = Device.Info.CurrentOrientation;
+
+ bool isSplitOnLandscape = (behavior == MasterBehavior.SplitOnLandscape || behavior == MasterBehavior.Default) && orientation.IsLandscape();
+ bool isSplitOnPortrait = behavior == MasterBehavior.SplitOnPortrait && orientation.IsPortrait();
+ return behavior != MasterBehavior.Split && !isSplitOnLandscape && !isSplitOnPortrait;
+ }
+
+ protected override void LayoutChildren(double x, double y, double width, double height)
+ {
+ if (Master == null || Detail == null)
+ throw new InvalidOperationException("Master and Detail must be set before using a MasterDetailPage");
+ _master.Layout(_masterBounds);
+ _detail.Layout(_detailBounds);
+ }
+
+ protected override void OnAppearing()
+ {
+ CanChangeIsPresented = true;
+ UpdateMasterBehavior(this);
+ base.OnAppearing();
+ }
+
+ protected override bool OnBackButtonPressed()
+ {
+ if (IsPresented)
+ {
+ if (Master.SendBackButtonPressed())
+ return true;
+ }
+
+ EventHandler<BackButtonPressedEventArgs> handler = BackButtonPressed;
+ if (handler != null)
+ {
+ var args = new BackButtonPressedEventArgs();
+ handler(this, args);
+ if (args.Handled)
+ return true;
+ }
+
+ if (Detail.SendBackButtonPressed())
+ {
+ return true;
+ }
+
+ return base.OnBackButtonPressed();
+ }
+
+ protected override void OnParentSet()
+ {
+ if (RealParent != null && (Master == null || Detail == null))
+ throw new InvalidOperationException("Master and Detail must be set before adding MasterDetailPage to a container");
+ base.OnParentSet();
+ }
+
+ internal event EventHandler<BackButtonPressedEventArgs> BackButtonPressed;
+
+ internal static void UpdateMasterBehavior(MasterDetailPage page)
+ {
+ if (page.ShouldShowSplitMode)
+ {
+ page.SetValueCore(IsPresentedProperty, true);
+ if (page.MasterBehavior != MasterBehavior.Default)
+ page.CanChangeIsPresented = false;
+ }
+ }
+
+ static void OnIsPresentedPropertyChanged(BindableObject sender, object oldValue, object newValue)
+ {
+ var page = (MasterDetailPage)sender;
+ EventHandler handler = page.IsPresentedChanged;
+ if (handler != null)
+ handler(page, EventArgs.Empty);
+ }
+
+ static void OnIsPresentedPropertyChanging(BindableObject sender, object oldValue, object newValue)
+ {
+ var page = (MasterDetailPage)sender;
+ if (!page.CanChangeIsPresented)
+ throw new InvalidOperationException(string.Format("Can't change IsPresented when setting {0}", page.MasterBehavior));
+ }
+
+ static void OnMasterBehaviorPropertyChanged(BindableObject sender, object oldValue, object newValue)
+ {
+ var page = (MasterDetailPage)sender;
+ UpdateMasterBehavior(page);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/MeasureFlags.cs b/Xamarin.Forms.Core/MeasureFlags.cs
new file mode 100644
index 00000000..c2e5c80a
--- /dev/null
+++ b/Xamarin.Forms.Core/MeasureFlags.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [Flags]
+ public enum MeasureFlags
+ {
+ None = 0,
+ IncludeMargins = 1 << 0
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/MenuItem.cs b/Xamarin.Forms.Core/MenuItem.cs
new file mode 100644
index 00000000..3e830445
--- /dev/null
+++ b/Xamarin.Forms.Core/MenuItem.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Windows.Input;
+
+namespace Xamarin.Forms
+{
+ public class MenuItem : BaseMenuItem
+ {
+ public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(MenuItem), null);
+
+ public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(MenuItem), null,
+ propertyChanging: (bo, o, n) => ((MenuItem)bo).OnCommandChanging(), propertyChanged: (bo, o, n) => ((MenuItem)bo).OnCommandChanged());
+
+ public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create("CommandParameter", typeof(object), typeof(MenuItem), null,
+ propertyChanged: (bo, o, n) => ((MenuItem)bo).OnCommandParameterChanged());
+
+ public static readonly BindableProperty IsDestructiveProperty = BindableProperty.Create("IsDestructive", typeof(bool), typeof(MenuItem), false);
+
+ public static readonly BindableProperty IconProperty = BindableProperty.Create("Icon", typeof(FileImageSource), typeof(MenuItem), default(FileImageSource));
+
+ internal static readonly BindableProperty IsEnabledProperty = BindableProperty.Create("IsEnabled", typeof(bool), typeof(ToolbarItem), true);
+
+ public ICommand Command
+ {
+ get { return (ICommand)GetValue(CommandProperty); }
+ set { SetValue(CommandProperty, value); }
+ }
+
+ public object CommandParameter
+ {
+ get { return GetValue(CommandParameterProperty); }
+ set { SetValue(CommandParameterProperty, value); }
+ }
+
+ public FileImageSource Icon
+ {
+ get { return (FileImageSource)GetValue(IconProperty); }
+ set { SetValue(IconProperty, value); }
+ }
+
+ public bool IsDestructive
+ {
+ get { return (bool)GetValue(IsDestructiveProperty); }
+ set { SetValue(IsDestructiveProperty, value); }
+ }
+
+ public string Text
+ {
+ get { return (string)GetValue(TextProperty); }
+ set { SetValue(TextProperty, value); }
+ }
+
+ internal bool IsEnabled
+ {
+ get { return (bool)GetValue(IsEnabledProperty); }
+ set { SetValue(IsEnabledProperty, value); }
+ }
+
+ bool IsEnabledCore
+ {
+ set { SetValueCore(IsEnabledProperty, value); }
+ }
+
+ public event EventHandler Clicked;
+
+ protected virtual void OnClicked()
+ {
+ EventHandler handler = Clicked;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+
+ internal void Activate()
+ {
+ if (Command != null)
+ {
+ if (IsEnabled)
+ Command.Execute(CommandParameter);
+ }
+
+ OnClicked();
+ }
+
+ void OnCommandCanExecuteChanged(object sender, EventArgs eventArgs)
+ {
+ IsEnabledCore = Command.CanExecute(CommandParameter);
+ }
+
+ void OnCommandChanged()
+ {
+ if (Command == null)
+ {
+ IsEnabledCore = true;
+ return;
+ }
+
+ IsEnabledCore = Command.CanExecute(CommandParameter);
+
+ Command.CanExecuteChanged += OnCommandCanExecuteChanged;
+ }
+
+ void OnCommandChanging()
+ {
+ if (Command == null)
+ return;
+
+ Command.CanExecuteChanged -= OnCommandCanExecuteChanged;
+ }
+
+ void OnCommandParameterChanged()
+ {
+ if (Command == null)
+ return;
+
+ IsEnabledCore = Command.CanExecute(CommandParameter);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/MergedStyle.cs b/Xamarin.Forms.Core/MergedStyle.cs
new file mode 100644
index 00000000..9f9c68bf
--- /dev/null
+++ b/Xamarin.Forms.Core/MergedStyle.cs
@@ -0,0 +1,162 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Xamarin.Forms
+{
+ public partial class VisualElement
+ {
+ sealed class MergedStyle : IStyle
+ {
+ ////If the base type is one of these, stop registering dynamic resources further
+ ////The last one (typeof(Element)) is a safety guard as we might be creating VisualElement directly in internal code
+ static readonly IList<Type> s_stopAtTypes = new List<Type> { typeof(View), typeof(Layout<>), typeof(VisualElement), typeof(Element) };
+
+ readonly BindableProperty _classStyleProperty = BindableProperty.Create("ClassStyle", typeof(IList<Style>), typeof(VisualElement), default(IList<Style>),
+ propertyChanged: (bindable, oldvalue, newvalue) => ((VisualElement)bindable)._mergedStyle.OnClassStyleChanged());
+
+ readonly List<BindableProperty> _implicitStyles = new List<BindableProperty>();
+
+ IStyle _classStyle;
+
+ IStyle _implicitStyle;
+
+ IStyle _style;
+
+ string _styleClass;
+
+ public MergedStyle(Type targetType, BindableObject target)
+ {
+ Target = target;
+ TargetType = targetType;
+ RegisterImplicitStyles();
+ Apply(Target);
+ }
+
+ public IStyle Style
+ {
+ get { return _style; }
+ set { SetStyle(ImplicitStyle, ClassStyle, value); }
+ }
+
+ public string StyleClass
+ {
+ get { return _styleClass; }
+ set
+ {
+ string val = string.IsNullOrWhiteSpace(value) ? null : value.Trim();
+ if (_styleClass == val)
+ return;
+
+ if (_styleClass != null)
+ Target.RemoveDynamicResource(_classStyleProperty);
+
+ _styleClass = val;
+
+ if (_styleClass != null)
+ Target.SetDynamicResource(_classStyleProperty, Forms.Style.StyleClassPrefix + _styleClass);
+ }
+ }
+
+ public BindableObject Target { get; }
+
+ IStyle ClassStyle
+ {
+ get { return _classStyle; }
+ set { SetStyle(ImplicitStyle, value, Style); }
+ }
+
+ IStyle ImplicitStyle
+ {
+ get { return _implicitStyle; }
+ set { SetStyle(value, ClassStyle, Style); }
+ }
+
+ public void Apply(BindableObject bindable)
+ {
+ ImplicitStyle?.Apply(bindable);
+ ClassStyle?.Apply(bindable);
+ Style?.Apply(bindable);
+ }
+
+ public Type TargetType { get; }
+
+ public void UnApply(BindableObject bindable)
+ {
+ Style?.UnApply(bindable);
+ ClassStyle?.UnApply(bindable);
+ ImplicitStyle?.UnApply(bindable);
+ }
+
+ void OnClassStyleChanged()
+ {
+ var classStyles = Target.GetValue(_classStyleProperty) as IList<Style>;
+ if (classStyles == null)
+ ClassStyle = null;
+ else
+ {
+ ClassStyle = classStyles.FirstOrDefault(s => s.CanBeAppliedTo(TargetType));
+ }
+ }
+
+ void OnImplicitStyleChanged()
+ {
+ var first = true;
+ foreach (BindableProperty implicitStyleProperty in _implicitStyles)
+ {
+ var implicitStyle = (Style)Target.GetValue(implicitStyleProperty);
+ if (implicitStyle != null)
+ {
+ if (first || implicitStyle.ApplyToDerivedTypes)
+ {
+ ImplicitStyle = implicitStyle;
+ return;
+ }
+ }
+ first = false;
+ }
+ }
+
+ void RegisterImplicitStyles()
+ {
+ Type type = TargetType;
+ while (true)
+ {
+ BindableProperty implicitStyleProperty = BindableProperty.Create("ImplicitStyle", typeof(Style), typeof(VisualElement), default(Style),
+ propertyChanged: (bindable, oldvalue, newvalue) => ((VisualElement)bindable)._mergedStyle.OnImplicitStyleChanged());
+ Target.SetDynamicResource(implicitStyleProperty, type.FullName);
+ _implicitStyles.Add(implicitStyleProperty);
+ type = type.GetTypeInfo().BaseType;
+ if (s_stopAtTypes.Contains(type))
+ return;
+ }
+ }
+
+ void SetStyle(IStyle implicitStyle, IStyle classStyle, IStyle style)
+ {
+ bool shouldReApplyStyle = implicitStyle != ImplicitStyle || classStyle != ClassStyle || Style != style;
+ bool shouldReApplyClassStyle = implicitStyle != ImplicitStyle || classStyle != ClassStyle;
+ bool shouldReApplyImplicitStyle = implicitStyle != ImplicitStyle && (Style as Style == null || ((Style)Style).CanCascade);
+
+ if (shouldReApplyStyle)
+ Style?.UnApply(Target);
+ if (shouldReApplyClassStyle)
+ ClassStyle?.UnApply(Target);
+ if (shouldReApplyImplicitStyle)
+ ImplicitStyle?.UnApply(Target);
+
+ _implicitStyle = implicitStyle;
+ _classStyle = classStyle;
+ _style = style;
+
+ if (shouldReApplyImplicitStyle)
+ ImplicitStyle?.Apply(Target);
+ if (shouldReApplyClassStyle)
+ ClassStyle?.Apply(Target);
+ if (shouldReApplyStyle)
+ Style?.Apply(Target);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/MessagingCenter.cs b/Xamarin.Forms.Core/MessagingCenter.cs
new file mode 100644
index 00000000..973531ab
--- /dev/null
+++ b/Xamarin.Forms.Core/MessagingCenter.cs
@@ -0,0 +1,131 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Xamarin.Forms
+{
+ public static class MessagingCenter
+ {
+ static readonly Dictionary<Tuple<string, Type, Type>, List<Tuple<WeakReference, Action<object, object>>>> s_callbacks =
+ new Dictionary<Tuple<string, Type, Type>, List<Tuple<WeakReference, Action<object, object>>>>();
+
+ public static void Send<TSender, TArgs>(TSender sender, string message, TArgs args) where TSender : class
+ {
+ if (sender == null)
+ throw new ArgumentNullException("sender");
+ InnerSend(message, typeof(TSender), typeof(TArgs), sender, args);
+ }
+
+ public static void Send<TSender>(TSender sender, string message) where TSender : class
+ {
+ if (sender == null)
+ throw new ArgumentNullException("sender");
+ InnerSend(message, typeof(TSender), null, sender, null);
+ }
+
+ public static void Subscribe<TSender, TArgs>(object subscriber, string message, Action<TSender, TArgs> callback, TSender source = null) where TSender : class
+ {
+ if (subscriber == null)
+ throw new ArgumentNullException("subscriber");
+ if (callback == null)
+ throw new ArgumentNullException("callback");
+
+ Action<object, object> wrap = (sender, args) =>
+ {
+ var send = (TSender)sender;
+ if (source == null || send == source)
+ callback((TSender)sender, (TArgs)args);
+ };
+
+ InnerSubscribe(subscriber, message, typeof(TSender), typeof(TArgs), wrap);
+ }
+
+ public static void Subscribe<TSender>(object subscriber, string message, Action<TSender> callback, TSender source = null) where TSender : class
+ {
+ if (subscriber == null)
+ throw new ArgumentNullException("subscriber");
+ if (callback == null)
+ throw new ArgumentNullException("callback");
+
+ Action<object, object> wrap = (sender, args) =>
+ {
+ var send = (TSender)sender;
+ if (source == null || send == source)
+ callback((TSender)sender);
+ };
+
+ InnerSubscribe(subscriber, message, typeof(TSender), null, wrap);
+ }
+
+ public static void Unsubscribe<TSender, TArgs>(object subscriber, string message) where TSender : class
+ {
+ InnerUnsubscribe(message, typeof(TSender), typeof(TArgs), subscriber);
+ }
+
+ public static void Unsubscribe<TSender>(object subscriber, string message) where TSender : class
+ {
+ InnerUnsubscribe(message, typeof(TSender), null, subscriber);
+ }
+
+ internal static void ClearSubscribers()
+ {
+ s_callbacks.Clear();
+ }
+
+ static void InnerSend(string message, Type senderType, Type argType, object sender, object args)
+ {
+ if (message == null)
+ throw new ArgumentNullException("message");
+ var key = new Tuple<string, Type, Type>(message, senderType, argType);
+ if (!s_callbacks.ContainsKey(key))
+ return;
+ List<Tuple<WeakReference, Action<object, object>>> actions = s_callbacks[key];
+ if (actions == null || !actions.Any())
+ return; // should not be reachable
+
+ // ok so this code looks a bit funky but here is the gist of the problem. It is possible that in the course
+ // of executing the callbacks for this message someone will subscribe/unsubscribe from the same message in
+ // the callback. This would invalidate the enumerator. To work around this we make a copy. However if you unsubscribe
+ // from a message you can fairly reasonably expect that you will therefor not receive a call. To fix this we then
+ // check that the item we are about to send the message to actually exists in the live list.
+ List<Tuple<WeakReference, Action<object, object>>> actionsCopy = actions.ToList();
+ foreach (Tuple<WeakReference, Action<object, object>> action in actionsCopy)
+ {
+ if (action.Item1.IsAlive && actions.Contains(action))
+ action.Item2(sender, args);
+ }
+ }
+
+ static void InnerSubscribe(object subscriber, string message, Type senderType, Type argType, Action<object, object> callback)
+ {
+ if (message == null)
+ throw new ArgumentNullException("message");
+ var key = new Tuple<string, Type, Type>(message, senderType, argType);
+ var value = new Tuple<WeakReference, Action<object, object>>(new WeakReference(subscriber), callback);
+ if (s_callbacks.ContainsKey(key))
+ {
+ s_callbacks[key].Add(value);
+ }
+ else
+ {
+ var list = new List<Tuple<WeakReference, Action<object, object>>> { value };
+ s_callbacks[key] = list;
+ }
+ }
+
+ static void InnerUnsubscribe(string message, Type senderType, Type argType, object subscriber)
+ {
+ if (subscriber == null)
+ throw new ArgumentNullException("subscriber");
+ if (message == null)
+ throw new ArgumentNullException("message");
+
+ var key = new Tuple<string, Type, Type>(message, senderType, argType);
+ if (!s_callbacks.ContainsKey(key))
+ return;
+ s_callbacks[key].RemoveAll(tuple => !tuple.Item1.IsAlive || tuple.Item1.Target == subscriber);
+ if (!s_callbacks[key].Any())
+ s_callbacks.Remove(key);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ModalEventArgs.cs b/Xamarin.Forms.Core/ModalEventArgs.cs
new file mode 100644
index 00000000..483ea5ad
--- /dev/null
+++ b/Xamarin.Forms.Core/ModalEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public abstract class ModalEventArgs : EventArgs
+ {
+ protected ModalEventArgs(Page modal)
+ {
+ Modal = modal;
+ }
+
+ public Page Modal { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ModalPoppedEventArgs.cs b/Xamarin.Forms.Core/ModalPoppedEventArgs.cs
new file mode 100644
index 00000000..3c17f009
--- /dev/null
+++ b/Xamarin.Forms.Core/ModalPoppedEventArgs.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Forms
+{
+ public class ModalPoppedEventArgs : ModalEventArgs
+ {
+ public ModalPoppedEventArgs(Page modal) : base(modal)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ModalPoppingEventArgs.cs b/Xamarin.Forms.Core/ModalPoppingEventArgs.cs
new file mode 100644
index 00000000..57c7a657
--- /dev/null
+++ b/Xamarin.Forms.Core/ModalPoppingEventArgs.cs
@@ -0,0 +1,11 @@
+namespace Xamarin.Forms
+{
+ public class ModalPoppingEventArgs : ModalEventArgs
+ {
+ public ModalPoppingEventArgs(Page modal) : base(modal)
+ {
+ }
+
+ public bool Cancel { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ModalPushedEventArgs.cs b/Xamarin.Forms.Core/ModalPushedEventArgs.cs
new file mode 100644
index 00000000..d09caf4d
--- /dev/null
+++ b/Xamarin.Forms.Core/ModalPushedEventArgs.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Forms
+{
+ public class ModalPushedEventArgs : ModalEventArgs
+ {
+ public ModalPushedEventArgs(Page modal) : base(modal)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ModalPushingEventArgs.cs b/Xamarin.Forms.Core/ModalPushingEventArgs.cs
new file mode 100644
index 00000000..12396c9e
--- /dev/null
+++ b/Xamarin.Forms.Core/ModalPushingEventArgs.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Forms
+{
+ public class ModalPushingEventArgs : ModalEventArgs
+ {
+ public ModalPushingEventArgs(Page modal) : base(modal)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/MultiPage.cs b/Xamarin.Forms.Core/MultiPage.cs
new file mode 100644
index 00000000..89fd7e9c
--- /dev/null
+++ b/Xamarin.Forms.Core/MultiPage.cs
@@ -0,0 +1,359 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("Children")]
+ public abstract class MultiPage<T> : Page, IViewContainer<T>, IPageContainer<T>, IItemsView<T> where T : Page
+ {
+ public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(MultiPage<>), null);
+
+ public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create("ItemTemplate", typeof(DataTemplate), typeof(MultiPage<>), null);
+
+ public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create("SelectedItem", typeof(object), typeof(MultiPage<>), null, BindingMode.TwoWay);
+
+ internal static readonly BindableProperty IndexProperty = BindableProperty.Create("Index", typeof(int), typeof(Page), -1);
+
+ readonly ElementCollection<T> _children;
+ readonly TemplatedItemsList<MultiPage<T>, T> _templatedItems;
+
+ T _current;
+
+ protected MultiPage()
+ {
+ _templatedItems = new TemplatedItemsList<MultiPage<T>, T>(this, ItemsSourceProperty, ItemTemplateProperty);
+ _templatedItems.CollectionChanged += OnTemplatedItemsChanged;
+
+ _children = new ElementCollection<T>(InternalChildren);
+ InternalChildren.CollectionChanged += OnChildrenChanged;
+ }
+
+ public IEnumerable ItemsSource
+ {
+ get { return (IEnumerable)GetValue(ItemsSourceProperty); }
+ set { SetValue(ItemsSourceProperty, value); }
+ }
+
+ public DataTemplate ItemTemplate
+ {
+ get { return (DataTemplate)GetValue(ItemTemplateProperty); }
+ set { SetValue(ItemTemplateProperty, value); }
+ }
+
+ public object SelectedItem
+ {
+ get { return GetValue(SelectedItemProperty); }
+ set { SetValue(SelectedItemProperty, value); }
+ }
+
+ T IItemsView<T>.CreateDefault(object item)
+ {
+ return CreateDefault(item);
+ }
+
+ void IItemsView<T>.SetupContent(T content, int index)
+ {
+ SetupContent(content, index);
+ }
+
+ void IItemsView<T>.UnhookContent(T content)
+ {
+ UnhookContent(content);
+ }
+
+ public T CurrentPage
+ {
+ get { return _current; }
+ set
+ {
+ if (_current == value)
+ return;
+
+ OnPropertyChanging();
+ _current = value;
+ OnPropertyChanged();
+ OnCurrentPageChanged();
+ }
+ }
+
+ public IList<T> Children
+ {
+ get { return _children; }
+ }
+
+ public event EventHandler CurrentPageChanged;
+
+ public event NotifyCollectionChangedEventHandler PagesChanged;
+
+ protected abstract T CreateDefault(object item);
+
+ protected override bool OnBackButtonPressed()
+ {
+ if (CurrentPage != null)
+ {
+ bool handled = CurrentPage.SendBackButtonPressed();
+ if (handled)
+ return true;
+ }
+
+ return base.OnBackButtonPressed();
+ }
+
+ protected override void OnChildAdded(Element child)
+ {
+ base.OnChildAdded(child);
+
+ ForceLayout();
+ }
+
+ protected virtual void OnCurrentPageChanged()
+ {
+ EventHandler changed = CurrentPageChanged;
+ if (changed != null)
+ changed(this, EventArgs.Empty);
+ }
+
+ protected virtual void OnPagesChanged(NotifyCollectionChangedEventArgs e)
+ {
+ NotifyCollectionChangedEventHandler handler = PagesChanged;
+ if (handler != null)
+ handler(this, e);
+ }
+
+ protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ if (propertyName == ItemsSourceProperty.PropertyName)
+ _children.IsReadOnly = ItemsSource != null;
+ else if (propertyName == SelectedItemProperty.PropertyName)
+ {
+ UpdateCurrentPage();
+ }
+ else if (propertyName == "CurrentPage" && ItemsSource != null)
+ {
+ if (CurrentPage == null)
+ {
+ SelectedItem = null;
+ }
+ else
+ {
+ int index = _templatedItems.IndexOf(CurrentPage);
+ SelectedItem = index != -1 ? _templatedItems.ListProxy[index] : null;
+ }
+ }
+
+ base.OnPropertyChanged(propertyName);
+ }
+
+ protected virtual void SetupContent(T content, int index)
+ {
+ }
+
+ protected virtual void UnhookContent(T content)
+ {
+ }
+
+ internal static int GetIndex(T page)
+ {
+ if (page == null)
+ throw new ArgumentNullException("page");
+
+ return (int)page.GetValue(IndexProperty);
+ }
+
+ internal T GetPageByIndex(int index)
+ {
+ foreach (T page in InternalChildren)
+ {
+ if (index == GetIndex(page))
+ return page;
+ }
+ return null;
+ }
+
+ internal static void SetIndex(Page page, int index)
+ {
+ if (page == null)
+ throw new ArgumentNullException("page");
+
+ page.SetValue(IndexProperty, index);
+ }
+
+ void OnChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ if (Children.IsReadOnly)
+ return;
+
+ var i = 0;
+ foreach (T page in Children)
+ SetIndex(page, i++);
+
+ OnPagesChanged(e);
+
+ if (CurrentPage == null || Children.IndexOf(CurrentPage) == -1)
+ CurrentPage = Children.FirstOrDefault();
+ }
+
+ void OnTemplatedItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ if (e.NewStartingIndex < 0)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ for (int i = e.NewStartingIndex; i < Children.Count; i++)
+ SetIndex((T)InternalChildren[i], i + e.NewItems.Count);
+
+ for (var i = 0; i < e.NewItems.Count; i++)
+ {
+ var page = (T)e.NewItems[i];
+ page.Owned = true;
+ int index = i + e.NewStartingIndex;
+ SetIndex(page, index);
+ InternalChildren.Insert(index, (T)e.NewItems[i]);
+ }
+
+ break;
+
+ case NotifyCollectionChangedAction.Remove:
+ if (e.OldStartingIndex < 0)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ int removeIndex = e.OldStartingIndex;
+ for (int i = removeIndex + e.OldItems.Count; i < Children.Count; i++)
+ SetIndex((T)InternalChildren[i], removeIndex++);
+
+ for (var i = 0; i < e.OldItems.Count; i++)
+ {
+ Element element = InternalChildren[e.OldStartingIndex];
+ InternalChildren.RemoveAt(e.OldStartingIndex);
+ element.Owned = false;
+ }
+
+ break;
+
+ case NotifyCollectionChangedAction.Move:
+ if (e.NewStartingIndex < 0 || e.OldStartingIndex < 0)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ if (e.NewStartingIndex == e.OldStartingIndex)
+ return;
+
+ bool movingForward = e.OldStartingIndex < e.NewStartingIndex;
+
+ if (movingForward)
+ {
+ int moveIndex = e.OldStartingIndex;
+ for (int i = moveIndex + e.OldItems.Count; i <= e.NewStartingIndex; i++)
+ SetIndex((T)InternalChildren[i], moveIndex++);
+ }
+ else
+ {
+ for (var i = 0; i < e.OldStartingIndex - e.NewStartingIndex; i++)
+ {
+ var page = (T)InternalChildren[i + e.NewStartingIndex];
+ SetIndex(page, GetIndex(page) + e.OldItems.Count);
+ }
+ }
+
+ for (var i = 0; i < e.OldItems.Count; i++)
+ InternalChildren.RemoveAt(e.OldStartingIndex);
+
+ int insertIndex = e.NewStartingIndex;
+ if (movingForward)
+ insertIndex -= e.OldItems.Count - 1;
+
+ for (var i = 0; i < e.OldItems.Count; i++)
+ {
+ var page = (T)e.OldItems[i];
+ SetIndex(page, insertIndex + i);
+ InternalChildren.Insert(insertIndex + i, page);
+ }
+
+ break;
+
+ case NotifyCollectionChangedAction.Replace:
+ if (e.OldStartingIndex < 0)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ for (int i = e.OldStartingIndex; i - e.OldStartingIndex < e.OldItems.Count; i++)
+ {
+ Element element = InternalChildren[i];
+ InternalChildren.RemoveAt(i);
+ element.Owned = false;
+
+ T page = _templatedItems.GetOrCreateContent(i, e.NewItems[i - e.OldStartingIndex]);
+ page.Owned = true;
+ SetIndex(page, i);
+ InternalChildren.Insert(i, page);
+ }
+
+ break;
+
+ case NotifyCollectionChangedAction.Reset:
+ Reset();
+ return;
+ }
+
+ OnPagesChanged(e);
+ UpdateCurrentPage();
+ }
+
+ void Reset()
+ {
+ List<Element> snapshot = InternalChildren.ToList();
+
+ InternalChildren.Clear();
+
+ foreach (Element element in snapshot)
+ element.Owned = false;
+
+ for (var i = 0; i < _templatedItems.Count; i++)
+ {
+ T page = _templatedItems.GetOrCreateContent(i, _templatedItems.ListProxy[i]);
+ page.Owned = true;
+ SetIndex(page, i);
+ InternalChildren.Add(page);
+ }
+
+ var currentNeedsUpdate = true;
+
+ BatchBegin();
+
+ if (ItemsSource != null)
+ {
+ object selected = SelectedItem;
+ if (selected == null || !ItemsSource.Cast<object>().Contains(selected))
+ {
+ SelectedItem = ItemsSource.Cast<object>().FirstOrDefault();
+ currentNeedsUpdate = false;
+ }
+ }
+
+ if (currentNeedsUpdate)
+ UpdateCurrentPage();
+
+ OnPagesChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+
+ BatchCommit();
+ }
+
+ void UpdateCurrentPage()
+ {
+ if (ItemsSource != null)
+ {
+ int index = _templatedItems.ListProxy.IndexOf(SelectedItem);
+ if (index == -1)
+ CurrentPage = (T)InternalChildren.FirstOrDefault();
+ else
+ CurrentPage = _templatedItems.GetOrCreateContent(index, SelectedItem);
+ }
+ else if (SelectedItem is T)
+ CurrentPage = (T)SelectedItem;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/NameScopeExtensions.cs b/Xamarin.Forms.Core/NameScopeExtensions.cs
new file mode 100644
index 00000000..b9acb460
--- /dev/null
+++ b/Xamarin.Forms.Core/NameScopeExtensions.cs
@@ -0,0 +1,17 @@
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms
+{
+ public static class NameScopeExtensions
+ {
+ public static T FindByName<T>(this Element element, string name)
+ {
+ return ((INameScope)element).FindByName<T>(name);
+ }
+
+ internal static T FindByName<T>(this INameScope namescope, string name)
+ {
+ return (T)namescope.FindByName(name);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/NamedSize.cs b/Xamarin.Forms.Core/NamedSize.cs
new file mode 100644
index 00000000..92f7a579
--- /dev/null
+++ b/Xamarin.Forms.Core/NamedSize.cs
@@ -0,0 +1,11 @@
+namespace Xamarin.Forms
+{
+ public enum NamedSize
+ {
+ Default = 0,
+ Micro = 1,
+ Small = 2,
+ Medium = 3,
+ Large = 4
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/NavigationEventArgs.cs b/Xamarin.Forms.Core/NavigationEventArgs.cs
new file mode 100644
index 00000000..0ccd4343
--- /dev/null
+++ b/Xamarin.Forms.Core/NavigationEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class NavigationEventArgs : EventArgs
+ {
+ public NavigationEventArgs(Page page)
+ {
+ if (page == null)
+ throw new ArgumentNullException("page");
+
+ Page = page;
+ }
+
+ public Page Page { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/NavigationMenu.cs b/Xamarin.Forms.Core/NavigationMenu.cs
new file mode 100644
index 00000000..2386dd29
--- /dev/null
+++ b/Xamarin.Forms.Core/NavigationMenu.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ // Mark as internal until renderers are ready for release after 1.0
+ [RenderWith(typeof(_NavigationMenuRenderer))]
+ internal class NavigationMenu : View
+ {
+ readonly List<Page> _targets = new List<Page>();
+
+ public IEnumerable<Page> Targets
+ {
+ get { return _targets; }
+ set
+ {
+ if (_targets.AsEnumerable().SequenceEqual(value))
+ return;
+
+ foreach (Page page in value)
+ {
+ VerifyTarget(page);
+ }
+
+ OnPropertyChanging();
+ _targets.Clear();
+ _targets.AddRange(value);
+ OnPropertyChanged();
+ }
+ }
+
+ public void Add(Page target)
+ {
+ if (_targets.Contains(target))
+ return;
+ VerifyTarget(target);
+
+ OnPropertyChanging("Targets");
+ _targets.Add(target);
+ OnPropertyChanged("Targets");
+ }
+
+ public void Remove(Page target)
+ {
+ if (_targets.Contains(target))
+ {
+ OnPropertyChanging("Targets");
+ if (_targets.Remove(target))
+ OnPropertyChanged("Targets");
+ }
+ }
+
+ internal void SendTargetSelected(Page target)
+ {
+ TargetSelected(target);
+ }
+
+ void TargetSelected(Page target)
+ {
+ Navigation.PushAsync(target);
+ }
+
+ void VerifyTarget(Page target)
+ {
+ if (target.Icon == null || string.IsNullOrWhiteSpace(target.Icon.File))
+ throw new Exception("Icon must be set for each page before adding them to a Navigation Menu");
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/NavigationModel.cs b/Xamarin.Forms.Core/NavigationModel.cs
new file mode 100644
index 00000000..4591d4a4
--- /dev/null
+++ b/Xamarin.Forms.Core/NavigationModel.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Xamarin.Forms
+{
+ internal class NavigationModel
+ {
+ readonly List<Page> _modalStack = new List<Page>();
+ readonly List<List<Page>> _navTree = new List<List<Page>>();
+
+ public Page CurrentPage
+ {
+ get
+ {
+ if (_navTree.Any())
+ return _navTree.Last().Last();
+ return null;
+ }
+ }
+
+ public IEnumerable<Page> Modals
+ {
+ get { return _modalStack; }
+ }
+
+ public IEnumerable<Page> Roots
+ {
+ get
+ {
+ foreach (List<Page> list in _navTree)
+ {
+ yield return list[0];
+ }
+ }
+ }
+
+ public IReadOnlyList<IReadOnlyList<Page>> Tree
+ {
+ get { return _navTree; }
+ }
+
+ public void Clear()
+ {
+ _navTree.Clear();
+ }
+
+ public void InsertPageBefore(Page page, Page before)
+ {
+ List<Page> currentStack = _navTree.Last();
+ int index = currentStack.IndexOf(before);
+
+ if (index == -1)
+ throw new ArgumentException("before must be in the current navigation context");
+
+ currentStack.Insert(index, page);
+ }
+
+ public Page Pop(Page ancestralNav)
+ {
+ ancestralNav = AncestorToRoot(ancestralNav);
+ foreach (List<Page> stack in _navTree)
+ {
+ if (stack.Contains(ancestralNav))
+ {
+ if (stack.Count <= 1)
+ throw new InvalidNavigationException("Can not pop final item in stack");
+ Page result = stack.Last();
+ stack.Remove(result);
+ return result;
+ }
+ }
+
+ throw new InvalidNavigationException("Popped from unpushed item?");
+ }
+
+ public Page PopModal()
+ {
+ if (_navTree.Count <= 1)
+ throw new InvalidNavigationException("Can't pop modal without any modals pushed");
+ Page modal = _navTree.Last().First();
+ _modalStack.Remove(modal);
+ _navTree.Remove(_navTree.Last());
+ return modal;
+ }
+
+ public Page PopTopPage()
+ {
+ Page itemToRemove;
+ if (_navTree.Count == 1)
+ {
+ if (_navTree[0].Count > 1)
+ {
+ itemToRemove = _navTree[0].Last();
+ _navTree[0].Remove(itemToRemove);
+ return itemToRemove;
+ }
+ return null;
+ }
+ itemToRemove = _navTree.Last().Last();
+ _navTree.Last().Remove(itemToRemove);
+ if (!_navTree.Last().Any())
+ {
+ _navTree.RemoveAt(_navTree.Count - 1);
+ }
+ return itemToRemove;
+ }
+
+ public void PopToRoot(Page ancestralNav)
+ {
+ ancestralNav = AncestorToRoot(ancestralNav);
+ foreach (List<Page> stack in _navTree)
+ {
+ if (stack.Contains(ancestralNav))
+ {
+ if (stack.Count <= 1)
+ throw new InvalidNavigationException("Can not pop final item in stack");
+ stack.RemoveRange(1, stack.Count - 1);
+ return;
+ }
+ }
+
+ throw new InvalidNavigationException("Popped from unpushed item?");
+ }
+
+ public void Push(Page page, Page ancestralNav)
+ {
+ if (ancestralNav == null)
+ {
+ if (_navTree.Any())
+ throw new InvalidNavigationException("Ancestor must be provided for all pushes except first");
+ _navTree.Add(new List<Page> { page });
+ return;
+ }
+
+ ancestralNav = AncestorToRoot(ancestralNav);
+
+ foreach (List<Page> stack in _navTree)
+ {
+ if (stack.Contains(ancestralNav))
+ {
+ stack.Add(page);
+ return;
+ }
+ }
+
+ throw new InvalidNavigationException("Invalid ancestor passed");
+ }
+
+ public void PushModal(Page page)
+ {
+ _navTree.Add(new List<Page> { page });
+ _modalStack.Add(page);
+ }
+
+ public bool RemovePage(Page page)
+ {
+ bool found;
+ List<Page> currentStack = _navTree.Last();
+ var i = 0;
+ while (!(found = currentStack.Remove(page)) && i < _navTree.Count - 1)
+ {
+ currentStack = _navTree[i++];
+ }
+
+ return found;
+ }
+
+ Page AncestorToRoot(Page ancestor)
+ {
+ Page result = ancestor;
+ while (!Application.IsApplicationOrNull(result.RealParent))
+ result = (Page)result.RealParent;
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/NavigationPage.cs b/Xamarin.Forms.Core/NavigationPage.cs
new file mode 100644
index 00000000..61545b11
--- /dev/null
+++ b/Xamarin.Forms.Core/NavigationPage.cs
@@ -0,0 +1,411 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_NavigationPageRenderer))]
+ public class NavigationPage : Page, IPageContainer<Page>
+ {
+ public static readonly BindableProperty BackButtonTitleProperty = BindableProperty.CreateAttached("BackButtonTitle", typeof(string), typeof(Page), null);
+
+ public static readonly BindableProperty HasNavigationBarProperty = BindableProperty.CreateAttached("HasNavigationBar", typeof(bool), typeof(Page), true);
+
+ public static readonly BindableProperty HasBackButtonProperty = BindableProperty.CreateAttached("HasBackButton", typeof(bool), typeof(NavigationPage), true);
+
+ [Obsolete("Use BarBackgroundColorProperty and BarTextColorProperty to change NavigationPage bar color properties")] public static readonly BindableProperty TintProperty =
+ BindableProperty.Create("Tint", typeof(Color), typeof(NavigationPage), Color.Default);
+
+ public static readonly BindableProperty BarBackgroundColorProperty = BindableProperty.Create("BarBackgroundColor", typeof(Color), typeof(NavigationPage), Color.Default);
+
+ public static readonly BindableProperty BarTextColorProperty = BindableProperty.Create("BarTextColor", typeof(Color), typeof(NavigationPage), Color.Default);
+
+ public static readonly BindableProperty TitleIconProperty = BindableProperty.CreateAttached("TitleIcon", typeof(FileImageSource), typeof(NavigationPage), default(FileImageSource));
+
+ static readonly BindablePropertyKey CurrentPagePropertyKey = BindableProperty.CreateReadOnly("CurrentPage", typeof(Page), typeof(NavigationPage), null);
+ public static readonly BindableProperty CurrentPageProperty = CurrentPagePropertyKey.BindableProperty;
+
+ public NavigationPage()
+ {
+ Navigation = new NavigationImpl(this);
+ }
+
+ public NavigationPage(Page root) : this()
+ {
+ PushPage(root);
+ }
+
+ public Color BarBackgroundColor
+ {
+ get { return (Color)GetValue(BarBackgroundColorProperty); }
+ set { SetValue(BarBackgroundColorProperty, value); }
+ }
+
+ public Color BarTextColor
+ {
+ get { return (Color)GetValue(BarTextColorProperty); }
+ set { SetValue(BarTextColorProperty, value); }
+ }
+
+ [Obsolete("Use BarBackgroundColor and BarTextColor to change NavigationPage bar color properties")]
+ public Color Tint
+ {
+ get { return (Color)GetValue(TintProperty); }
+ set { SetValue(TintProperty, value); }
+ }
+
+ internal Task CurrentNavigationTask { get; set; }
+
+ internal Stack<Page> StackCopy
+ {
+ get
+ {
+ var result = new Stack<Page>(InternalChildren.Count);
+ foreach (Page page in InternalChildren)
+ result.Push(page);
+ return result;
+ }
+ }
+
+ internal int StackDepth
+ {
+ get { return InternalChildren.Count; }
+ }
+
+ public Page CurrentPage
+ {
+ get { return (Page)GetValue(CurrentPageProperty); }
+ private set { SetValue(CurrentPagePropertyKey, value); }
+ }
+
+ public static string GetBackButtonTitle(BindableObject page)
+ {
+ return (string)page.GetValue(BackButtonTitleProperty);
+ }
+
+ public static bool GetHasBackButton(Page page)
+ {
+ if (page == null)
+ throw new ArgumentNullException("page");
+ return (bool)page.GetValue(HasBackButtonProperty);
+ }
+
+ public static bool GetHasNavigationBar(BindableObject page)
+ {
+ return (bool)page.GetValue(HasNavigationBarProperty);
+ }
+
+ public static FileImageSource GetTitleIcon(BindableObject bindable)
+ {
+ return (FileImageSource)bindable.GetValue(TitleIconProperty);
+ }
+
+ public Task<Page> PopAsync()
+ {
+ return PopAsync(true);
+ }
+
+ public async Task<Page> PopAsync(bool animated)
+ {
+ if (CurrentNavigationTask != null && !CurrentNavigationTask.IsCompleted)
+ {
+ var tcs = new TaskCompletionSource<bool>();
+ Task oldTask = CurrentNavigationTask;
+ CurrentNavigationTask = tcs.Task;
+ await oldTask;
+
+ Page page = await PopAsyncInner(animated);
+ tcs.SetResult(true);
+ return page;
+ }
+
+ Task<Page> result = PopAsyncInner(animated);
+ CurrentNavigationTask = result;
+ return await result;
+ }
+
+ public event EventHandler<NavigationEventArgs> Popped;
+
+ public event EventHandler<NavigationEventArgs> PoppedToRoot;
+
+ public Task PopToRootAsync()
+ {
+ return PopToRootAsync(true);
+ }
+
+ public async Task PopToRootAsync(bool animated)
+ {
+ if (CurrentNavigationTask != null && !CurrentNavigationTask.IsCompleted)
+ {
+ var tcs = new TaskCompletionSource<bool>();
+ Task oldTask = CurrentNavigationTask;
+ CurrentNavigationTask = tcs.Task;
+ await oldTask;
+
+ await PopToRootAsyncInner(animated);
+ tcs.SetResult(true);
+ return;
+ }
+
+ Task result = PopToRootAsyncInner(animated);
+ CurrentNavigationTask = result;
+ await result;
+ }
+
+ public Task PushAsync(Page page)
+ {
+ return PushAsync(page, true);
+ }
+
+ public async Task PushAsync(Page page, bool animated)
+ {
+ if (CurrentNavigationTask != null && !CurrentNavigationTask.IsCompleted)
+ {
+ var tcs = new TaskCompletionSource<bool>();
+ Task oldTask = CurrentNavigationTask;
+ CurrentNavigationTask = tcs.Task;
+ await oldTask;
+
+ await PushAsyncInner(page, animated);
+ tcs.SetResult(true);
+ return;
+ }
+
+ CurrentNavigationTask = PushAsyncInner(page, animated);
+ await CurrentNavigationTask;
+ }
+
+ public event EventHandler<NavigationEventArgs> Pushed;
+
+ public static void SetBackButtonTitle(BindableObject page, string value)
+ {
+ page.SetValue(BackButtonTitleProperty, value);
+ }
+
+ public static void SetHasBackButton(Page page, bool value)
+ {
+ if (page == null)
+ throw new ArgumentNullException("page");
+ page.SetValue(HasBackButtonProperty, value);
+ }
+
+ public static void SetHasNavigationBar(BindableObject page, bool value)
+ {
+ page.SetValue(HasNavigationBarProperty, value);
+ }
+
+ public static void SetTitleIcon(BindableObject bindable, FileImageSource value)
+ {
+ bindable.SetValue(TitleIconProperty, value);
+ }
+
+ protected override bool OnBackButtonPressed()
+ {
+ if (CurrentPage.SendBackButtonPressed())
+ return true;
+
+ if (StackDepth > 1)
+ {
+ SafePop();
+ return true;
+ }
+
+ return base.OnBackButtonPressed();
+ }
+
+ internal event EventHandler<NavigationRequestedEventArgs> InsertPageBeforeRequested;
+
+ internal async Task<Page> PopAsyncInner(bool animated, bool fast = false)
+ {
+ if (StackDepth == 1)
+ {
+ return null;
+ }
+
+ var page = (Page)InternalChildren.Last();
+
+ var args = new NavigationRequestedEventArgs(page, animated);
+
+ var removed = true;
+
+ EventHandler<NavigationRequestedEventArgs> requestPop = PopRequested;
+ if (requestPop != null)
+ {
+ requestPop(this, args);
+
+ if (args.Task != null && !fast)
+ removed = await args.Task;
+ }
+
+ if (!removed && !fast)
+ return CurrentPage;
+
+ InternalChildren.Remove(page);
+
+ CurrentPage = (Page)InternalChildren.Last();
+
+ if (Popped != null)
+ Popped(this, args);
+
+ return page;
+ }
+
+ internal event EventHandler<NavigationRequestedEventArgs> PopRequested;
+
+ internal event EventHandler<NavigationRequestedEventArgs> PopToRootRequested;
+
+ internal event EventHandler<NavigationRequestedEventArgs> PushRequested;
+
+ internal event EventHandler<NavigationRequestedEventArgs> RemovePageRequested;
+
+ void InsertPageBefore(Page page, Page before)
+ {
+ if (!InternalChildren.Contains(before))
+ throw new ArgumentException("before must be a child of the NavigationPage", "before");
+
+ if (InternalChildren.Contains(page))
+ throw new ArgumentException("Cannot insert page which is already in the navigation stack");
+
+ EventHandler<NavigationRequestedEventArgs> handler = InsertPageBeforeRequested;
+ if (handler != null)
+ handler(this, new NavigationRequestedEventArgs(page, before, false));
+
+ int index = InternalChildren.IndexOf(before);
+ InternalChildren.Insert(index, page);
+
+ // Shouldn't be required?
+ if (Width > 0 && Height > 0)
+ ForceLayout();
+ }
+
+ async Task PopToRootAsyncInner(bool animated)
+ {
+ if (StackDepth == 1)
+ return;
+
+ var root = (Page)InternalChildren.First();
+
+ InternalChildren.ToArray().Where(c => c != root).ForEach(c => InternalChildren.Remove(c));
+
+ CurrentPage = root;
+
+ var args = new NavigationRequestedEventArgs(root, animated);
+
+ EventHandler<NavigationRequestedEventArgs> requestPopToRoot = PopToRootRequested;
+ if (requestPopToRoot != null)
+ {
+ requestPopToRoot(this, args);
+
+ if (args.Task != null)
+ await args.Task;
+ }
+
+ if (PoppedToRoot != null)
+ PoppedToRoot(this, new NavigationEventArgs(root));
+ }
+
+ async Task PushAsyncInner(Page page, bool animated)
+ {
+ if (InternalChildren.Contains(page))
+ return;
+
+ PushPage(page);
+
+ var args = new NavigationRequestedEventArgs(page, animated);
+
+ EventHandler<NavigationRequestedEventArgs> requestPush = PushRequested;
+ if (requestPush != null)
+ {
+ requestPush(this, args);
+
+ if (args.Task != null)
+ await args.Task;
+ }
+
+ if (Pushed != null)
+ Pushed(this, args);
+ }
+
+ void PushPage(Page page)
+ {
+ InternalChildren.Add(page);
+
+ CurrentPage = page;
+ }
+
+ void RemovePage(Page page)
+ {
+ if (page == CurrentPage && StackDepth <= 1)
+ throw new InvalidOperationException("Cannot remove root page when it is also the currently displayed page.");
+ if (page == CurrentPage)
+ {
+ Log.Warning("NavigationPage", "RemovePage called for CurrentPage object. This can result in undesired behavior, consider called PopAsync instead.");
+ PopAsync();
+ return;
+ }
+
+ if (!InternalChildren.Contains(page))
+ throw new ArgumentException("Page to remove must be contained on this Navigation Page");
+
+ EventHandler<NavigationRequestedEventArgs> handler = RemovePageRequested;
+ if (handler != null)
+ handler(this, new NavigationRequestedEventArgs(page, true));
+
+ InternalChildren.Remove(page);
+ }
+
+ void SafePop()
+ {
+ PopAsync(true).ContinueWith(t =>
+ {
+ if (t.IsFaulted)
+ throw t.Exception;
+ });
+ }
+
+ class NavigationImpl : NavigationProxy
+ {
+ readonly Lazy<ReadOnlyCastingList<Page, Element>> _castingList;
+
+ public NavigationImpl(NavigationPage owner)
+ {
+ Owner = owner;
+ _castingList = new Lazy<ReadOnlyCastingList<Page, Element>>(() => new ReadOnlyCastingList<Page, Element>(Owner.InternalChildren));
+ }
+
+ NavigationPage Owner { get; }
+
+ protected override IReadOnlyList<Page> GetNavigationStack()
+ {
+ return _castingList.Value;
+ }
+
+ protected override void OnInsertPageBefore(Page page, Page before)
+ {
+ Owner.InsertPageBefore(page, before);
+ }
+
+ protected override Task<Page> OnPopAsync(bool animated)
+ {
+ return Owner.PopAsync(animated);
+ }
+
+ protected override Task OnPopToRootAsync(bool animated)
+ {
+ return Owner.PopToRootAsync(animated);
+ }
+
+ protected override Task OnPushAsync(Page root, bool animated)
+ {
+ return Owner.PushAsync(root, animated);
+ }
+
+ protected override void OnRemovePage(Page page)
+ {
+ Owner.RemovePage(page);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/NavigationProxy.cs b/Xamarin.Forms.Core/NavigationProxy.cs
new file mode 100644
index 00000000..65e2fee9
--- /dev/null
+++ b/Xamarin.Forms.Core/NavigationProxy.cs
@@ -0,0 +1,233 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ internal class NavigationProxy : INavigation
+ {
+ INavigation _inner;
+ Lazy<List<Page>> _modalStack = new Lazy<List<Page>>(() => new List<Page>());
+
+ Lazy<List<Page>> _pushStack = new Lazy<List<Page>>(() => new List<Page>());
+
+ public INavigation Inner
+ {
+ get { return _inner; }
+ set
+ {
+ if (_inner == value)
+ return;
+ _inner = value;
+ // reverse so that things go into the new stack in the same order
+ // null out to release memory that will likely never be needed again
+
+ if (ReferenceEquals(_inner, null))
+ {
+ _pushStack = new Lazy<List<Page>>(() => new List<Page>());
+ _modalStack = new Lazy<List<Page>>(() => new List<Page>());
+ }
+ else
+ {
+ if (_pushStack != null && _pushStack.IsValueCreated)
+ {
+ foreach (Page page in _pushStack.Value)
+ {
+ _inner.PushAsync(page);
+ }
+ }
+
+ if (_modalStack != null && _modalStack.IsValueCreated)
+ {
+ foreach (Page page in _modalStack.Value)
+ {
+ _inner.PushModalAsync(page);
+ }
+ }
+
+ _pushStack = null;
+ _modalStack = null;
+ }
+ }
+ }
+
+ public void InsertPageBefore(Page page, Page before)
+ {
+ OnInsertPageBefore(page, before);
+ }
+
+ public IReadOnlyList<Page> ModalStack
+ {
+ get { return GetModalStack(); }
+ }
+
+ public IReadOnlyList<Page> NavigationStack
+ {
+ get { return GetNavigationStack(); }
+ }
+
+ public Task<Page> PopAsync()
+ {
+ return OnPopAsync(true);
+ }
+
+ public Task<Page> PopAsync(bool animated)
+ {
+ return OnPopAsync(animated);
+ }
+
+ public Task<Page> PopModalAsync()
+ {
+ return OnPopModal(true);
+ }
+
+ public Task<Page> PopModalAsync(bool animated)
+ {
+ return OnPopModal(animated);
+ }
+
+ public Task PopToRootAsync()
+ {
+ return OnPopToRootAsync(true);
+ }
+
+ public Task PopToRootAsync(bool animated)
+ {
+ return OnPopToRootAsync(animated);
+ }
+
+ public Task PushAsync(Page root)
+ {
+ return PushAsync(root, true);
+ }
+
+ public Task PushAsync(Page root, bool animated)
+ {
+ if (root.RealParent != null)
+ throw new InvalidOperationException("Page must not already have a parent.");
+ return OnPushAsync(root, animated);
+ }
+
+ public Task PushModalAsync(Page modal)
+ {
+ return PushModalAsync(modal, true);
+ }
+
+ public Task PushModalAsync(Page modal, bool animated)
+ {
+ if (modal.RealParent != null)
+ throw new InvalidOperationException("Page must not already have a parent.");
+ return OnPushModal(modal, animated);
+ }
+
+ public void RemovePage(Page page)
+ {
+ OnRemovePage(page);
+ }
+
+ protected virtual IReadOnlyList<Page> GetModalStack()
+ {
+ INavigation currentInner = Inner;
+ return currentInner == null ? _modalStack.Value : currentInner.ModalStack;
+ }
+
+ protected virtual IReadOnlyList<Page> GetNavigationStack()
+ {
+ INavigation currentInner = Inner;
+ return currentInner == null ? _pushStack.Value : currentInner.NavigationStack;
+ }
+
+ protected virtual void OnInsertPageBefore(Page page, Page before)
+ {
+ INavigation currentInner = Inner;
+ if (currentInner == null)
+ {
+ int index = _pushStack.Value.IndexOf(before);
+ if (index == -1)
+ throw new ArgumentException("before must be in the pushed stack of the current context");
+ _pushStack.Value.Insert(index, page);
+ }
+ else
+ {
+ currentInner.InsertPageBefore(page, before);
+ }
+ }
+
+ protected virtual Task<Page> OnPopAsync(bool animated)
+ {
+ INavigation inner = Inner;
+ return inner == null ? Task.FromResult(Pop()) : inner.PopAsync(animated);
+ }
+
+ protected virtual Task<Page> OnPopModal(bool animated)
+ {
+ INavigation innerNav = Inner;
+ return innerNav == null ? Task.FromResult(PopModal()) : innerNav.PopModalAsync(animated);
+ }
+
+ protected virtual Task OnPopToRootAsync(bool animated)
+ {
+ INavigation currentInner = Inner;
+ if (currentInner == null)
+ {
+ Page root = _pushStack.Value.Last();
+ _pushStack.Value.Clear();
+ _pushStack.Value.Add(root);
+ return Task.FromResult(root);
+ }
+ return currentInner.PopToRootAsync(animated);
+ }
+
+ protected virtual Task OnPushAsync(Page page, bool animated)
+ {
+ INavigation currentInner = Inner;
+ if (currentInner == null)
+ {
+ _pushStack.Value.Add(page);
+ return Task.FromResult(page);
+ }
+ return currentInner.PushAsync(page, animated);
+ }
+
+ protected virtual Task OnPushModal(Page modal, bool animated)
+ {
+ INavigation currentInner = Inner;
+ if (currentInner == null)
+ {
+ _modalStack.Value.Add(modal);
+ return Task.FromResult<object>(null);
+ }
+ return currentInner.PushModalAsync(modal, animated);
+ }
+
+ protected virtual void OnRemovePage(Page page)
+ {
+ INavigation currentInner = Inner;
+ if (currentInner == null)
+ {
+ _pushStack.Value.Remove(page);
+ }
+ else
+ {
+ currentInner.RemovePage(page);
+ }
+ }
+
+ Page Pop()
+ {
+ List<Page> list = _pushStack.Value;
+ Page result = list[list.Count - 1];
+ list.RemoveAt(list.Count - 1);
+ return result;
+ }
+
+ Page PopModal()
+ {
+ List<Page> list = _modalStack.Value;
+ Page result = list[list.Count - 1];
+ list.RemoveAt(list.Count - 1);
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/NavigationRequestedEventArgs.cs b/Xamarin.Forms.Core/NavigationRequestedEventArgs.cs
new file mode 100644
index 00000000..b21cffce
--- /dev/null
+++ b/Xamarin.Forms.Core/NavigationRequestedEventArgs.cs
@@ -0,0 +1,26 @@
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ internal class NavigationRequestedEventArgs : NavigationEventArgs
+ {
+ public NavigationRequestedEventArgs(Page page, bool animated, bool realize = true) : base(page)
+ {
+ Animated = animated;
+ Realize = realize;
+ }
+
+ public NavigationRequestedEventArgs(Page page, Page before, bool animated) : this(page, animated)
+ {
+ BeforePage = before;
+ }
+
+ public bool Animated { get; set; }
+
+ public Page BeforePage { get; set; }
+
+ public bool Realize { get; set; }
+
+ public Task<bool> Task { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/NotifyCollectionChangedEventArgsEx.cs b/Xamarin.Forms.Core/NotifyCollectionChangedEventArgsEx.cs
new file mode 100644
index 00000000..bb6a2b84
--- /dev/null
+++ b/Xamarin.Forms.Core/NotifyCollectionChangedEventArgsEx.cs
@@ -0,0 +1,65 @@
+using System.Collections;
+using System.Collections.Specialized;
+
+namespace Xamarin.Forms
+{
+ internal class NotifyCollectionChangedEventArgsEx : NotifyCollectionChangedEventArgs
+ {
+ public NotifyCollectionChangedEventArgsEx(int count, NotifyCollectionChangedAction action) : base(action)
+ {
+ Count = count;
+ }
+
+ public NotifyCollectionChangedEventArgsEx(int count, NotifyCollectionChangedAction action, IList changedItems) : base(action, changedItems)
+ {
+ Count = count;
+ }
+
+ public NotifyCollectionChangedEventArgsEx(int count, NotifyCollectionChangedAction action, IList newItems, IList oldItems) : base(action, newItems, oldItems)
+ {
+ Count = count;
+ }
+
+ public NotifyCollectionChangedEventArgsEx(int count, NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex) : base(action, newItems, oldItems, startingIndex)
+ {
+ Count = count;
+ }
+
+ public NotifyCollectionChangedEventArgsEx(int count, NotifyCollectionChangedAction action, IList changedItems, int startingIndex) : base(action, changedItems, startingIndex)
+ {
+ Count = count;
+ }
+
+ public NotifyCollectionChangedEventArgsEx(int count, NotifyCollectionChangedAction action, IList changedItems, int index, int oldIndex) : base(action, changedItems, index, oldIndex)
+ {
+ Count = count;
+ }
+
+ public NotifyCollectionChangedEventArgsEx(int count, NotifyCollectionChangedAction action, object changedItem) : base(action, changedItem)
+ {
+ Count = count;
+ }
+
+ public NotifyCollectionChangedEventArgsEx(int count, NotifyCollectionChangedAction action, object changedItem, int index) : base(action, changedItem, index)
+ {
+ Count = count;
+ }
+
+ public NotifyCollectionChangedEventArgsEx(int count, NotifyCollectionChangedAction action, object changedItem, int index, int oldIndex) : base(action, changedItem, index, oldIndex)
+ {
+ Count = count;
+ }
+
+ public NotifyCollectionChangedEventArgsEx(int count, NotifyCollectionChangedAction action, object newItem, object oldItem) : base(action, newItem, oldItem)
+ {
+ Count = count;
+ }
+
+ public NotifyCollectionChangedEventArgsEx(int count, NotifyCollectionChangedAction action, object newItem, object oldItem, int index) : base(action, newItem, oldItem, index)
+ {
+ Count = count;
+ }
+
+ public int Count { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/NotifyCollectionChangedEventArgsExtensions.cs b/Xamarin.Forms.Core/NotifyCollectionChangedEventArgsExtensions.cs
new file mode 100644
index 00000000..2ddf92c4
--- /dev/null
+++ b/Xamarin.Forms.Core/NotifyCollectionChangedEventArgsExtensions.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+
+namespace Xamarin.Forms
+{
+ internal static class NotifyCollectionChangedEventArgsExtensions
+ {
+ public static void Apply<TFrom>(this NotifyCollectionChangedEventArgs self, IList<TFrom> from, IList<object> to)
+ {
+ self.Apply((o, i, b) => to.Insert(i, o), (o, i) => to.RemoveAt(i), () =>
+ {
+ to.Clear();
+ for (var i = 0; i < from.Count; i++)
+ to.Add(from[i]);
+ });
+ }
+
+ public static NotifyCollectionChangedAction Apply(this NotifyCollectionChangedEventArgs self, Action<object, int, bool> insert, Action<object, int> removeAt, Action reset)
+ {
+ if (self == null)
+ throw new ArgumentNullException("self");
+ if (reset == null)
+ throw new ArgumentNullException("reset");
+ if (insert == null)
+ throw new ArgumentNullException("insert");
+ if (removeAt == null)
+ throw new ArgumentNullException("removeAt");
+
+ switch (self.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ if (self.NewStartingIndex < 0)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ for (var i = 0; i < self.NewItems.Count; i++)
+ insert(self.NewItems[i], i + self.NewStartingIndex, true);
+
+ break;
+
+ case NotifyCollectionChangedAction.Move:
+ if (self.NewStartingIndex < 0 || self.OldStartingIndex < 0)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ for (var i = 0; i < self.OldItems.Count; i++)
+ removeAt(self.OldItems[i], self.OldStartingIndex);
+
+ int insertIndex = self.NewStartingIndex;
+ if (self.OldStartingIndex < self.NewStartingIndex)
+ insertIndex -= self.OldItems.Count - 1;
+
+ for (var i = 0; i < self.OldItems.Count; i++)
+ insert(self.OldItems[i], insertIndex + i, false);
+
+ break;
+
+ case NotifyCollectionChangedAction.Remove:
+ if (self.OldStartingIndex < 0)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ for (var i = 0; i < self.OldItems.Count; i++)
+ removeAt(self.OldItems[i], self.OldStartingIndex);
+ break;
+
+ case NotifyCollectionChangedAction.Replace:
+ if (self.OldStartingIndex < 0)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ for (var i = 0; i < self.OldItems.Count; i++)
+ {
+ removeAt(self.OldItems[i], i + self.OldStartingIndex);
+ insert(self.OldItems[i], i + self.OldStartingIndex, true);
+ }
+ break;
+
+ case NotifyCollectionChangedAction.Reset:
+ reset();
+ return NotifyCollectionChangedAction.Reset;
+ }
+
+ return self.Action;
+ }
+
+ public static NotifyCollectionChangedEventArgsEx WithCount(this NotifyCollectionChangedEventArgs e, int count)
+ {
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ return new NotifyCollectionChangedEventArgsEx(count, NotifyCollectionChangedAction.Add, e.NewItems, e.NewStartingIndex);
+
+ case NotifyCollectionChangedAction.Remove:
+ return new NotifyCollectionChangedEventArgsEx(count, NotifyCollectionChangedAction.Remove, e.OldItems, e.OldStartingIndex);
+
+ case NotifyCollectionChangedAction.Move:
+ return new NotifyCollectionChangedEventArgsEx(count, NotifyCollectionChangedAction.Move, e.OldItems, e.NewStartingIndex, e.OldStartingIndex);
+
+ case NotifyCollectionChangedAction.Replace:
+ return new NotifyCollectionChangedEventArgsEx(count, NotifyCollectionChangedAction.Replace, e.NewItems, e.OldItems, e.OldStartingIndex);
+
+ default:
+ return new NotifyCollectionChangedEventArgsEx(count, NotifyCollectionChangedAction.Reset);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/NullEffect.cs b/Xamarin.Forms.Core/NullEffect.cs
new file mode 100644
index 00000000..509405d7
--- /dev/null
+++ b/Xamarin.Forms.Core/NullEffect.cs
@@ -0,0 +1,13 @@
+namespace Xamarin.Forms
+{
+ internal class NullEffect : Effect
+ {
+ protected override void OnAttached()
+ {
+ }
+
+ protected override void OnDetached()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/NumericExtensions.cs b/Xamarin.Forms.Core/NumericExtensions.cs
new file mode 100644
index 00000000..6333c360
--- /dev/null
+++ b/Xamarin.Forms.Core/NumericExtensions.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ internal static class NumericExtensions
+ {
+ public static double Clamp(this double self, double min, double max)
+ {
+ return Math.Min(max, Math.Max(self, min));
+ }
+
+ public static int Clamp(this int self, int min, int max)
+ {
+ return Math.Min(max, Math.Max(self, min));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/NumericKeyboard.cs b/Xamarin.Forms.Core/NumericKeyboard.cs
new file mode 100644
index 00000000..08096bde
--- /dev/null
+++ b/Xamarin.Forms.Core/NumericKeyboard.cs
@@ -0,0 +1,6 @@
+namespace Xamarin.Forms
+{
+ internal sealed class NumericKeyboard : Keyboard
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ObservableList.cs b/Xamarin.Forms.Core/ObservableList.cs
new file mode 100644
index 00000000..82a6c493
--- /dev/null
+++ b/Xamarin.Forms.Core/ObservableList.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
+
+namespace Xamarin.Forms
+{
+ internal class ObservableList<T> : ObservableCollection<T>
+ {
+ // There's lots of special-casing optimizations that could be done here
+ // but right now this is only being used for tests.
+
+ public void AddRange(IEnumerable<T> range)
+ {
+ if (range == null)
+ throw new ArgumentNullException("range");
+
+ List<T> items = range.ToList();
+ int index = Items.Count;
+ foreach (T item in items)
+ Items.Add(item);
+
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, items, index));
+ }
+
+ public void InsertRange(int index, IEnumerable<T> range)
+ {
+ if (index < 0 || index > Count)
+ throw new ArgumentOutOfRangeException("index");
+ if (range == null)
+ throw new ArgumentNullException("range");
+
+ int originalIndex = index;
+
+ List<T> items = range.ToList();
+ foreach (T item in items)
+ Items.Insert(index++, item);
+
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, items, originalIndex));
+ }
+
+ public void Move(int oldIndex, int newIndex, int count)
+ {
+ if (oldIndex < 0 || oldIndex + count > Count)
+ throw new ArgumentOutOfRangeException("oldIndex");
+ if (newIndex < 0 || newIndex + count > Count)
+ throw new ArgumentOutOfRangeException("newIndex");
+
+ var items = new List<T>(count);
+ for (var i = 0; i < count; i++)
+ {
+ T item = Items[oldIndex];
+ items.Add(item);
+ Items.RemoveAt(oldIndex);
+ }
+
+ int index = newIndex;
+ if (newIndex > oldIndex)
+ index -= items.Count - 1;
+
+ for (var i = 0; i < items.Count; i++)
+ Items.Insert(index + i, items[i]);
+
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, items, newIndex, oldIndex));
+ }
+
+ public void RemoveAt(int index, int count)
+ {
+ if (index < 0 || index + count > Count)
+ throw new ArgumentOutOfRangeException("index");
+
+ T[] items = Items.Skip(index).Take(count).ToArray();
+ for (int i = index; i < count; i++)
+ Items.RemoveAt(i);
+
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, items, index));
+ }
+
+ public void RemoveRange(IEnumerable<T> range)
+ {
+ if (range == null)
+ throw new ArgumentNullException("range");
+
+ List<T> items = range.ToList();
+ foreach (T item in items)
+ Items.Remove(item);
+
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, items));
+ }
+
+ public void ReplaceRange(int startIndex, IEnumerable<T> items)
+ {
+ if (items == null)
+ throw new ArgumentNullException("items");
+
+ T[] ritems = items.ToArray();
+
+ if (startIndex < 0 || startIndex + ritems.Length > Count)
+ throw new ArgumentOutOfRangeException("startIndex");
+
+ var oldItems = new T[ritems.Length];
+ for (var i = 0; i < ritems.Length; i++)
+ {
+ oldItems[i] = Items[i + startIndex];
+ Items[i + startIndex] = ritems[i];
+ }
+
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, ritems, oldItems, startIndex));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ObservableWrapper.cs b/Xamarin.Forms.Core/ObservableWrapper.cs
new file mode 100644
index 00000000..e8fc0c5b
--- /dev/null
+++ b/Xamarin.Forms.Core/ObservableWrapper.cs
@@ -0,0 +1,256 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
+
+namespace Xamarin.Forms
+{
+ internal class ObservableWrapper<TTrack, TRestrict> : IList<TRestrict>, INotifyCollectionChanged where TTrack : Element where TRestrict : TTrack
+ {
+ readonly ObservableCollection<TTrack> _list;
+
+ public ObservableWrapper(ObservableCollection<TTrack> list)
+ {
+ if (list == null)
+ throw new ArgumentNullException("list");
+
+ _list = list;
+
+ list.CollectionChanged += ListOnCollectionChanged;
+ }
+
+ public void Add(TRestrict item)
+ {
+ if (item == null)
+ throw new ArgumentNullException("item");
+ if (IsReadOnly)
+ throw new NotSupportedException("The collection is read-only.");
+
+ if (_list.Contains(item))
+ return;
+
+ item.Owned = true;
+ _list.Add(item);
+ }
+
+ public void Clear()
+ {
+ if (IsReadOnly)
+ throw new NotSupportedException("The collection is read-only.");
+
+ foreach (TRestrict item in _list.OfType<TRestrict>().ToArray())
+ {
+ _list.Remove(item);
+ item.Owned = false;
+ }
+ }
+
+ public bool Contains(TRestrict item)
+ {
+ return item.Owned && _list.Contains(item);
+ }
+
+ public void CopyTo(TRestrict[] array, int destIndex)
+ {
+ if (array.Length - destIndex < Count)
+ throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
+ foreach (TRestrict item in this)
+ {
+ array[destIndex] = item;
+ destIndex++;
+ }
+ }
+
+ public int Count
+ {
+ get { return _list.Where(i => i.Owned).OfType<TRestrict>().Count(); }
+ }
+
+ public bool IsReadOnly { get; internal set; }
+
+ public bool Remove(TRestrict item)
+ {
+ if (item == null)
+ throw new ArgumentNullException("item");
+ if (IsReadOnly)
+ throw new NotSupportedException("The collection is read-only.");
+
+ if (!item.Owned)
+ return false;
+
+ if (_list.Remove(item))
+ {
+ item.Owned = false;
+ return true;
+ }
+ return false;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public IEnumerator<TRestrict> GetEnumerator()
+ {
+ return _list.Where(i => i.Owned).OfType<TRestrict>().GetEnumerator();
+ }
+
+ public int IndexOf(TRestrict value)
+ {
+ int innerIndex = _list.IndexOf(value);
+ if (innerIndex == -1)
+ return -1;
+ return ToOuterIndex(innerIndex);
+ }
+
+ public void Insert(int index, TRestrict item)
+ {
+ if (item == null)
+ throw new ArgumentNullException("item");
+ if (IsReadOnly)
+ throw new NotSupportedException("The collection is read-only.");
+
+ item.Owned = true;
+ _list.Insert(ToInnerIndex(index), item);
+ }
+
+ public TRestrict this[int index]
+ {
+ get { return (TRestrict)_list[ToInnerIndex(index)]; }
+ set
+ {
+ int innerIndex = ToInnerIndex(index);
+ if (value != null)
+ value.Owned = true;
+ TTrack old = _list[innerIndex];
+ _list[innerIndex] = value;
+
+ if (old != null)
+ old.Owned = false;
+ }
+ }
+
+ public void RemoveAt(int index)
+ {
+ if (IsReadOnly)
+ throw new NotSupportedException("The collection is read-only");
+ int innerIndex = ToInnerIndex(index);
+ TTrack item = _list[innerIndex];
+ if (item.Owned)
+ {
+ _list.RemoveAt(innerIndex);
+ item.Owned = false;
+ }
+ }
+
+ public event NotifyCollectionChangedEventHandler CollectionChanged;
+
+ void ListOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ NotifyCollectionChangedEventHandler handler = CollectionChanged;
+ if (handler == null)
+ return;
+
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ if (e.NewStartingIndex == -1 || e.NewItems.Count > 1)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ var newItem = e.NewItems[0] as TRestrict;
+ if (newItem == null || !newItem.Owned)
+ break;
+
+ int outerIndex = ToOuterIndex(e.NewStartingIndex);
+ handler(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, e.NewItems, outerIndex));
+ break;
+ case NotifyCollectionChangedAction.Move:
+ if (e.NewStartingIndex == -1 || e.OldStartingIndex == -1 || e.NewItems.Count > 1)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ var movedItem = e.NewItems[0] as TRestrict;
+ if (movedItem == null || !movedItem.Owned)
+ break;
+
+ int outerOldIndex = ToOuterIndex(e.OldStartingIndex);
+ int outerNewIndex = ToOuterIndex(e.NewStartingIndex);
+ handler(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, e.NewItems, outerNewIndex, outerOldIndex));
+ break;
+ case NotifyCollectionChangedAction.Remove:
+ if (e.OldStartingIndex == -1 || e.OldItems.Count > 1)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ var removedItem = e.OldItems[0] as TRestrict;
+ if (removedItem == null || !removedItem.Owned)
+ break;
+
+ int outerRemovedIndex = ToOuterIndex(e.OldStartingIndex);
+ var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removedItem, outerRemovedIndex);
+ handler(this, args);
+ break;
+ case NotifyCollectionChangedAction.Replace:
+ if (e.NewStartingIndex == -1 || e.OldStartingIndex == -1 || e.NewItems.Count > 1)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ var newReplaceItem = e.NewItems[0] as TRestrict;
+ var oldReplaceItem = e.OldItems[0] as TRestrict;
+
+ if ((newReplaceItem == null || !newReplaceItem.Owned) && (oldReplaceItem == null || !oldReplaceItem.Owned))
+ {
+ break;
+ }
+ if (newReplaceItem == null || !newReplaceItem.Owned || oldReplaceItem == null || !oldReplaceItem.Owned)
+ {
+ goto case NotifyCollectionChangedAction.Reset;
+ }
+
+ int index = ToOuterIndex(e.NewStartingIndex);
+
+ var replaceArgs = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newReplaceItem, oldReplaceItem, index);
+ handler(this, replaceArgs);
+ break;
+ case NotifyCollectionChangedAction.Reset:
+ handler(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ int ToInnerIndex(int outterIndex)
+ {
+ var outerIndex = 0;
+ int innerIndex;
+ for (innerIndex = 0; innerIndex < _list.Count; innerIndex++)
+ {
+ TTrack item = _list[innerIndex];
+ if (item is TRestrict && item.Owned)
+ {
+ if (outerIndex == outterIndex)
+ return innerIndex;
+ outerIndex++;
+ }
+ }
+
+ return innerIndex;
+ }
+
+ int ToOuterIndex(int innerIndex)
+ {
+ var outerIndex = 0;
+ for (var index = 0; index < innerIndex; index++)
+ {
+ TTrack item = _list[index];
+ if (item is TRestrict && item.Owned)
+ {
+ outerIndex++;
+ }
+ }
+
+ return outerIndex;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/OnIdiom.cs b/Xamarin.Forms.Core/OnIdiom.cs
new file mode 100644
index 00000000..9376d5b9
--- /dev/null
+++ b/Xamarin.Forms.Core/OnIdiom.cs
@@ -0,0 +1,21 @@
+namespace Xamarin.Forms
+{
+ public class OnIdiom<T>
+ {
+ public T Phone { get; set; }
+
+ public T Tablet { get; set; }
+
+ public static implicit operator T(OnIdiom<T> onIdiom)
+ {
+ switch (Device.Idiom)
+ {
+ default:
+ case TargetIdiom.Phone:
+ return onIdiom.Phone;
+ case TargetIdiom.Tablet:
+ return onIdiom.Tablet;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/OnPlatform.cs b/Xamarin.Forms.Core/OnPlatform.cs
new file mode 100644
index 00000000..b66167fa
--- /dev/null
+++ b/Xamarin.Forms.Core/OnPlatform.cs
@@ -0,0 +1,27 @@
+namespace Xamarin.Forms
+{
+ public class OnPlatform<T>
+ {
+ public T Android { get; set; }
+
+ public T iOS { get; set; }
+
+ public T WinPhone { get; set; }
+
+ public static implicit operator T(OnPlatform<T> onPlatform)
+ {
+ switch (Device.OS)
+ {
+ case TargetPlatform.iOS:
+ return onPlatform.iOS;
+ case TargetPlatform.Android:
+ return onPlatform.Android;
+ case TargetPlatform.Windows:
+ case TargetPlatform.WinPhone:
+ return onPlatform.WinPhone;
+ }
+
+ return onPlatform.iOS;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/OpenGLView.cs b/Xamarin.Forms.Core/OpenGLView.cs
new file mode 100644
index 00000000..530a2f0d
--- /dev/null
+++ b/Xamarin.Forms.Core/OpenGLView.cs
@@ -0,0 +1,38 @@
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_OpenGLViewRenderer))]
+ public sealed class OpenGLView : View, IOpenGlViewController
+ {
+ #region Statics
+
+ public static readonly BindableProperty HasRenderLoopProperty = BindableProperty.Create("HasRenderLoop", typeof(bool), typeof(OpenGLView), default(bool));
+
+ #endregion
+
+ public bool HasRenderLoop
+ {
+ get { return (bool)GetValue(HasRenderLoopProperty); }
+ set { SetValue(HasRenderLoopProperty, value); }
+ }
+
+ public Action<Rectangle> OnDisplay { get; set; }
+
+ event EventHandler IOpenGlViewController.DisplayRequested
+ {
+ add { DisplayRequested += value; }
+ remove { DisplayRequested -= value; }
+ }
+
+ public void Display()
+ {
+ EventHandler handler = DisplayRequested;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+
+ event EventHandler DisplayRequested;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/OrderedDictionary.cs b/Xamarin.Forms.Core/OrderedDictionary.cs
new file mode 100644
index 00000000..028979c5
--- /dev/null
+++ b/Xamarin.Forms.Core/OrderedDictionary.cs
@@ -0,0 +1,451 @@
+//
+// OrderedDictionary.cs
+//
+// Author:
+// Eric Maupin <me@ermau.com>
+//
+// Copyright (c) 2009 Eric Maupin (http://www.ermau.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using Xamarin.Forms;
+
+namespace Cadenza.Collections
+{
+ internal sealed class OrderedDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IList<KeyValuePair<TKey, TValue>>
+ {
+ readonly Dictionary<TKey, TValue> _dict;
+ readonly List<TKey> _keyOrder;
+ readonly ICollection<KeyValuePair<TKey, TValue>> _kvpCollection;
+ readonly ReadOnlyCollection<TKey> _roKeys;
+
+ readonly ReadOnlyValueCollection _roValues;
+
+ public OrderedDictionary() : this(0)
+ {
+ }
+
+ public OrderedDictionary(int capacity) : this(capacity, EqualityComparer<TKey>.Default)
+ {
+ }
+
+ public OrderedDictionary(IEqualityComparer<TKey> equalityComparer) : this(0, equalityComparer)
+ {
+ }
+
+ public OrderedDictionary(int capacity, IEqualityComparer<TKey> equalityComparer)
+ {
+ _dict = new Dictionary<TKey, TValue>(capacity, equalityComparer);
+ _kvpCollection = _dict;
+ _keyOrder = new List<TKey>(capacity);
+ _roKeys = new ReadOnlyCollection<TKey>(_keyOrder);
+ _roValues = new ReadOnlyValueCollection(this);
+ }
+
+ public OrderedDictionary(ICollection<KeyValuePair<TKey, TValue>> dictionary) : this(dictionary, EqualityComparer<TKey>.Default)
+ {
+ }
+
+ public OrderedDictionary(ICollection<KeyValuePair<TKey, TValue>> dictionary, IEqualityComparer<TKey> equalityComparer) : this(dictionary != null ? dictionary.Count : 0, equalityComparer)
+ {
+ if (dictionary == null)
+ throw new ArgumentNullException("dictionary");
+
+ foreach (KeyValuePair<TKey, TValue> kvp in dictionary)
+ Add(kvp.Key, kvp.Value);
+ }
+
+ /// <summary>
+ /// Gets the equality comparer being used for
+ /// <typeparam name="TKey" />
+ /// .
+ /// </summary>
+ public IEqualityComparer<TKey> Comparer
+ {
+ get { return _dict.Comparer; }
+ }
+
+ /// <summary>
+ /// Gets the value at the specified index.
+ /// </summary>
+ /// <param name="index">The index to get the value at.</param>
+ /// <returns>The value at the specified index.</returns>
+ /// <exception cref="IndexOutOfRangeException">
+ /// <paramref name="index" /> is less than 0 or greater than
+ /// <see cref="Count" />.
+ /// </exception>
+ public TValue this[int index]
+ {
+ get { return _dict[_keyOrder[index]]; }
+ }
+
+ void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
+ {
+ Add(item.Key, item.Value);
+ }
+
+ /// <summary>
+ /// Clears the dictionary.
+ /// </summary>
+ public void Clear()
+ {
+ _dict.Clear();
+ _keyOrder.Clear();
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
+ {
+ return _kvpCollection.Contains(item);
+ }
+
+ void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException("array");
+ if (Count > array.Length - arrayIndex)
+ throw new ArgumentException("Not enough space in array to copy");
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException("arrayIndex");
+
+ for (var i = 0; i < _keyOrder.Count; ++i)
+ {
+ TKey key = _keyOrder[i];
+ array[arrayIndex++] = new KeyValuePair<TKey, TValue>(key, _dict[key]);
+ }
+ }
+
+ /// <summary>
+ /// Gets the number of items in the dictionary.
+ /// </summary>
+ public int Count
+ {
+ get { return _dict.Count; }
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
+ {
+ get { return false; }
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
+ {
+ return _kvpCollection.Remove(item) && _keyOrder.Remove(item.Key);
+ }
+
+ /// <summary>
+ /// Adds the <paramref name="key" /> and <paramref name="value" /> to the dictionary.
+ /// </summary>
+ /// <param name="key">The key to associate with the <paramref name="value" />.</param>
+ /// <param name="value">The value to add.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="key" /> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentException"><paramref name="key" /> already exists in the dictionary.</exception>
+ public void Add(TKey key, TValue value)
+ {
+ _dict.Add(key, value);
+ _keyOrder.Add(key);
+ }
+
+ /// <summary>
+ /// Gets whether or not <paramref name="key" /> is in the dictionary.
+ /// </summary>
+ /// <param name="key">The key to look for.</param>
+ /// <returns><c>true</c> if the key was found, <c>false</c> if not.</returns>
+ /// <exception cref="ArgumentNullException">If <paramref name="key" /> is <c>null</c>.</exception>
+ public bool ContainsKey(TKey key)
+ {
+ return _dict.ContainsKey(key);
+ }
+
+ /// <summary>
+ /// Gets or sets the value associated with <paramref name="key" />.
+ /// </summary>
+ /// <param name="key">The key to get or set the value for.</param>
+ /// <returns>The value associated with the key.</returns>
+ /// <exception cref="KeyNotFoundException"><paramref name="key" /> was not found attempting to get.</exception>
+ public TValue this[TKey key]
+ {
+ get { return _dict[key]; }
+ set
+ {
+ if (!_dict.ContainsKey(key))
+ _keyOrder.Add(key);
+
+ _dict[key] = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets a read only collection of keys in the dictionary.
+ /// </summary>
+ public ICollection<TKey> Keys
+ {
+ get { return _roKeys; }
+ }
+
+ /// <summary>
+ /// Removes the key and associated value from the dictionary if found.
+ /// </summary>
+ /// <param name="key">The key to remove.</param>
+ /// <returns><c>true</c> if the key was found, <c>false</c> if not.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="key" /> is <c>null</c>.</exception>
+ public bool Remove(TKey key)
+ {
+ return _dict.Remove(key) && _keyOrder.Remove(key);
+ }
+
+ /// <summary>
+ /// Attempts to get the <paramref name="value" /> for the <paramref name="key" />.
+ /// </summary>
+ /// <param name="key">The key to search for.</param>
+ /// <param name="value">The value, if found.</param>
+ /// <returns><c>true</c> if the key was found, <c>false</c> otherwise.</returns>
+ /// <exception cref="ArgumentNullException">If <paramref name="key" /> is <c>null</c>.</exception>
+ public bool TryGetValue(TKey key, out TValue value)
+ {
+ return _dict.TryGetValue(key, out value);
+ }
+
+ /// <summary>
+ /// Gets a read only collection of values in the dictionary.
+ /// </summary>
+ public ICollection<TValue> Values
+ {
+ get { return _roValues; }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
+ {
+ foreach (TKey key in _keyOrder)
+ yield return new KeyValuePair<TKey, TValue>(key, this[key]);
+ }
+
+ int IList<KeyValuePair<TKey, TValue>>.IndexOf(KeyValuePair<TKey, TValue> item)
+ {
+ return _keyOrder.IndexOf(item.Key);
+ }
+
+ void IList<KeyValuePair<TKey, TValue>>.Insert(int index, KeyValuePair<TKey, TValue> item)
+ {
+ Insert(index, item.Key, item.Value);
+ }
+
+ KeyValuePair<TKey, TValue> IList<KeyValuePair<TKey, TValue>>.this[int index]
+ {
+ get { return new KeyValuePair<TKey, TValue>(_keyOrder[index], this[index]); }
+ set
+ {
+ _keyOrder[index] = value.Key;
+ _dict[value.Key] = value.Value;
+ }
+ }
+
+ /// <summary>
+ /// Removes they key and associated value from the dictionary located at <paramref name="index" />.
+ /// </summary>
+ /// <param name="index">The index at which to remove an item.</param>
+ public void RemoveAt(int index)
+ {
+ TKey key = _keyOrder[index];
+ Remove(key);
+ }
+
+ /// <summary>
+ /// Gets whether or not <paramref name="value" /> is in the dictionary.
+ /// </summary>
+ /// <param name="value">The value to look for.</param>
+ /// <returns><c>true</c> if the value was found, <c>false</c> if not.</returns>
+ public bool ContainsValue(TValue value)
+ {
+ return _dict.ContainsValue(value);
+ }
+
+ /// <summary>
+ /// Gets the index of <paramref name="key" />.
+ /// </summary>
+ /// <param name="key">The key to find the index of.</param>
+ /// <returns>-1 if the key was not found, the index otherwise.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="key" /> is <c>null</c>.</exception>
+ public int IndexOf(TKey key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ return _keyOrder.IndexOf(key);
+ }
+
+ /// <summary>
+ /// Gets the index of <paramref name="key" /> starting with <paramref name="startIndex" />.
+ /// </summary>
+ /// <param name="key">The key to find the index of.</param>
+ /// <param name="startIndex">The index to start the search at.</param>
+ /// <returns>-1 if the key was not found, the index otherwise.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="key" /> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex" /> is not within the valid range of indexes.</exception>
+ public int IndexOf(TKey key, int startIndex)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ return _keyOrder.IndexOf(key, startIndex);
+ }
+
+ /// <summary>
+ /// Gets the index of <paramref name="key" /> between the range given by <paramref name="startIndex" /> and
+ /// <paramref name="count" />.
+ /// </summary>
+ /// <param name="key">The key to find the index of.</param>
+ /// <param name="startIndex">The index to start the search at.</param>
+ /// <param name="count">How many items to search, including the <paramref name="startIndex" />.</param>
+ /// <returns>-1 if the key was not found, the index otherwise.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="key" /> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex" /> is not within the valid range of indexes.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="startIndex" /> and <paramref name="count" /> are not a
+ /// valid range.
+ /// </exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="count" /> is less than 0.</exception>
+ public int IndexOf(TKey key, int startIndex, int count)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ return _keyOrder.IndexOf(key, startIndex, count);
+ }
+
+ /// <summary>
+ /// Inserts the <paramref name="key" /> and <paramref name="value" /> at the specified index.
+ /// </summary>
+ /// <param name="index">The index to insert the key and value at.</param>
+ /// <param name="key">The key to assicate with the <paramref name="value" />.</param>
+ /// <param name="value">The value to insert.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="key" /> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index" /> is less than 0 or greater than
+ /// <see cref="Count" />
+ /// </exception>
+ public void Insert(int index, TKey key, TValue value)
+ {
+ _keyOrder.Insert(index, key);
+ _dict.Add(key, value);
+ }
+
+ public void Move(int oldIndex, int newIndex)
+ {
+ TKey key = _keyOrder[oldIndex];
+ _keyOrder.RemoveAt(oldIndex);
+ _keyOrder.Insert(newIndex, key);
+ }
+
+ class ReadOnlyValueCollection : IList<TValue>
+ {
+ readonly OrderedDictionary<TKey, TValue> _odict;
+
+ public ReadOnlyValueCollection(OrderedDictionary<TKey, TValue> dict)
+ {
+ _odict = dict;
+ }
+
+ public void Add(TValue item)
+ {
+ throw new NotSupportedException();
+ }
+
+ public void Clear()
+ {
+ throw new NotSupportedException();
+ }
+
+ public bool Contains(TValue item)
+ {
+ return _odict.ContainsValue(item);
+ }
+
+ public void CopyTo(TValue[] array, int arrayIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException("array");
+ if (Count > array.Length - arrayIndex)
+ throw new ArgumentException("Not enough space in array to copy");
+ if (arrayIndex < 0 || arrayIndex > array.Length)
+ throw new ArgumentOutOfRangeException("arrayIndex");
+
+ for (var i = 0; i < _odict.Count; ++i)
+ array[arrayIndex++] = _odict[i];
+ }
+
+ public int Count
+ {
+ get { return _odict.Count; }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return true; }
+ }
+
+ public bool Remove(TValue item)
+ {
+ throw new NotSupportedException();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public IEnumerator<TValue> GetEnumerator()
+ {
+ for (var i = 0; i < _odict._keyOrder.Count; ++i)
+ yield return _odict[i];
+ }
+
+ public int IndexOf(TValue item)
+ {
+ return _odict._dict.Values.IndexOf(item);
+ }
+
+ public void Insert(int index, TValue item)
+ {
+ throw new NotSupportedException();
+ }
+
+ public TValue this[int index]
+ {
+ get { return _odict[index]; }
+ set { throw new NotSupportedException(); }
+ }
+
+ public void RemoveAt(int index)
+ {
+ throw new NotSupportedException();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Page.cs b/Xamarin.Forms.Core/Page.cs
new file mode 100644
index 00000000..903f4b53
--- /dev/null
+++ b/Xamarin.Forms.Core/Page.cs
@@ -0,0 +1,403 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_PageRenderer))]
+ public class Page : VisualElement, ILayout
+ {
+ internal const string BusySetSignalName = "Xamarin.BusySet";
+
+ internal const string AlertSignalName = "Xamarin.SendAlert";
+
+ internal const string ActionSheetSignalName = "Xamarin.ShowActionSheet";
+
+ internal static readonly BindableProperty IgnoresContainerAreaProperty = BindableProperty.Create("IgnoresContainerArea", typeof(bool), typeof(Page), false);
+
+ public static readonly BindableProperty BackgroundImageProperty = BindableProperty.Create("BackgroundImage", typeof(string), typeof(Page), default(string));
+
+ public static readonly BindableProperty IsBusyProperty = BindableProperty.Create("IsBusy", typeof(bool), typeof(Page), false, propertyChanged: (bo, o, n) => ((Page)bo).OnPageBusyChanged());
+
+ public static readonly BindableProperty PaddingProperty = BindableProperty.Create("Padding", typeof(Thickness), typeof(Page), default(Thickness), propertyChanged: (bindable, old, newValue) =>
+ {
+ var layout = (Page)bindable;
+ layout.UpdateChildrenLayout();
+ });
+
+ public static readonly BindableProperty TitleProperty = BindableProperty.Create("Title", typeof(string), typeof(Page), null);
+
+ public static readonly BindableProperty IconProperty = BindableProperty.Create("Icon", typeof(FileImageSource), typeof(Page), default(FileImageSource));
+
+ bool _allocatedFlag;
+ Rectangle _containerArea;
+
+ bool _containerAreaSet;
+
+ bool _hasAppeared;
+
+ ReadOnlyCollection<Element> _logicalChildren;
+
+ public Page()
+ {
+ var toolbarItems = new ObservableCollection<ToolbarItem>();
+ toolbarItems.CollectionChanged += OnToolbarItemsCollectionChanged;
+ ToolbarItems = toolbarItems;
+ InternalChildren.CollectionChanged += InternalChildrenOnCollectionChanged;
+ }
+
+ public string BackgroundImage
+ {
+ get { return (string)GetValue(BackgroundImageProperty); }
+ set { SetValue(BackgroundImageProperty, value); }
+ }
+
+ public FileImageSource Icon
+ {
+ get { return (FileImageSource)GetValue(IconProperty); }
+ set { SetValue(IconProperty, value); }
+ }
+
+ public bool IsBusy
+ {
+ get { return (bool)GetValue(IsBusyProperty); }
+ set { SetValue(IsBusyProperty, value); }
+ }
+
+ public Thickness Padding
+ {
+ get { return (Thickness)GetValue(PaddingProperty); }
+ set { SetValue(PaddingProperty, value); }
+ }
+
+ public string Title
+ {
+ get { return (string)GetValue(TitleProperty); }
+ set { SetValue(TitleProperty, value); }
+ }
+
+ public IList<ToolbarItem> ToolbarItems { get; internal set; }
+
+ internal Rectangle ContainerArea
+ {
+ get { return _containerArea; }
+ set
+ {
+ if (_containerArea == value)
+ return;
+ _containerAreaSet = true;
+ _containerArea = value;
+ ForceLayout();
+ }
+ }
+
+ internal bool IgnoresContainerArea
+ {
+ get { return (bool)GetValue(IgnoresContainerAreaProperty); }
+ set { SetValue(IgnoresContainerAreaProperty, value); }
+ }
+
+ internal ObservableCollection<Element> InternalChildren { get; } = new ObservableCollection<Element>();
+
+ internal override ReadOnlyCollection<Element> LogicalChildren
+ {
+ get { return _logicalChildren ?? (_logicalChildren = new ReadOnlyCollection<Element>(InternalChildren)); }
+ }
+
+ public event EventHandler LayoutChanged;
+
+ public event EventHandler Appearing;
+
+ public event EventHandler Disappearing;
+
+ public Task<string> DisplayActionSheet(string title, string cancel, string destruction, params string[] buttons)
+ {
+ var args = new ActionSheetArguments(title, cancel, destruction, buttons);
+ MessagingCenter.Send(this, ActionSheetSignalName, args);
+ return args.Result.Task;
+ }
+
+ public Task DisplayAlert(string title, string message, string cancel)
+ {
+ return DisplayAlert(title, message, null, cancel);
+ }
+
+ public Task<bool> DisplayAlert(string title, string message, string accept, string cancel)
+ {
+ if (string.IsNullOrEmpty(cancel))
+ throw new ArgumentNullException("cancel");
+
+ var args = new AlertArguments(title, message, accept, cancel);
+ MessagingCenter.Send(this, AlertSignalName, args);
+ return args.Result.Task;
+ }
+
+ public void ForceLayout()
+ {
+ SizeAllocated(Width, Height);
+ }
+
+ public bool SendBackButtonPressed()
+ {
+ return OnBackButtonPressed();
+ }
+
+ protected virtual void LayoutChildren(double x, double y, double width, double height)
+ {
+ var area = new Rectangle(x, y, width, height);
+ Rectangle originalArea = area;
+ if (_containerAreaSet)
+ {
+ area = ContainerArea;
+ area.X += Padding.Left;
+ area.Y += Padding.Right;
+ area.Width -= Padding.HorizontalThickness;
+ area.Height -= Padding.VerticalThickness;
+ area.Width = Math.Max(0, area.Width);
+ area.Height = Math.Max(0, area.Height);
+ }
+
+ foreach (Element element in LogicalChildren)
+ {
+ var child = element as VisualElement;
+ if (child == null)
+ continue;
+ var page = child as Page;
+ if (page != null && page.IgnoresContainerArea)
+ {
+ Forms.Layout.LayoutChildIntoBoundingRegion(child, originalArea);
+ }
+ else
+ {
+ Forms.Layout.LayoutChildIntoBoundingRegion(child, area);
+ }
+ }
+ }
+
+ protected virtual void OnAppearing()
+ {
+ }
+
+ protected virtual bool OnBackButtonPressed()
+ {
+ var application = RealParent as Application;
+ if (application == null || this == application.MainPage)
+ return false;
+
+ var canceled = false;
+ EventHandler handler = (sender, args) => { canceled = true; };
+ application.PopCanceled += handler;
+ Navigation.PopModalAsync().ContinueWith(t => { throw t.Exception; }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.FromCurrentSynchronizationContext());
+
+ application.PopCanceled -= handler;
+ return !canceled;
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ base.OnBindingContextChanged();
+ foreach (ToolbarItem toolbarItem in ToolbarItems)
+ {
+ SetInheritedBindingContext(toolbarItem, BindingContext);
+ }
+ }
+
+ protected virtual void OnChildMeasureInvalidated(object sender, EventArgs e)
+ {
+ InvalidationTrigger trigger = (e as InvalidationEventArgs)?.Trigger ?? InvalidationTrigger.Undefined;
+ OnChildMeasureInvalidated((VisualElement)sender, trigger);
+ }
+
+ protected virtual void OnDisappearing()
+ {
+ }
+
+ protected override void OnParentSet()
+ {
+ if (!Application.IsApplicationOrNull(RealParent) && !(RealParent is Page))
+ throw new InvalidOperationException("Parent of a Page must also be a Page");
+ base.OnParentSet();
+ }
+
+ protected override void OnSizeAllocated(double width, double height)
+ {
+ _allocatedFlag = true;
+ base.OnSizeAllocated(width, height);
+ UpdateChildrenLayout();
+ }
+
+ protected void UpdateChildrenLayout()
+ {
+ if (!ShouldLayoutChildren())
+ return;
+
+ var startingLayout = new List<Rectangle>(LogicalChildren.Count);
+ foreach (VisualElement c in LogicalChildren)
+ {
+ startingLayout.Add(c.Bounds);
+ }
+
+ double x = Padding.Left;
+ double y = Padding.Top;
+ double w = Math.Max(0, Width - Padding.HorizontalThickness);
+ double h = Math.Max(0, Height - Padding.VerticalThickness);
+
+ LayoutChildren(x, y, w, h);
+
+ for (var i = 0; i < LogicalChildren.Count; i++)
+ {
+ var c = (VisualElement)LogicalChildren[i];
+
+ if (c.Bounds != startingLayout[i])
+ {
+ EventHandler handler = LayoutChanged;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ return;
+ }
+ }
+ }
+
+ internal virtual void OnChildMeasureInvalidated(VisualElement child, InvalidationTrigger trigger)
+ {
+ var container = this as IPageContainer<Page>;
+ if (container != null)
+ {
+ Page page = container.CurrentPage;
+ if (page != null && page.IsVisible && (!page.IsPlatformEnabled || !page.IsNativeStateConsistent))
+ return;
+ }
+ else
+ {
+ for (var i = 0; i < LogicalChildren.Count; i++)
+ {
+ var v = LogicalChildren[i] as VisualElement;
+ if (v != null && v.IsVisible && (!v.IsPlatformEnabled || !v.IsNativeStateConsistent))
+ return;
+ }
+ }
+
+ _allocatedFlag = false;
+ InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ if (!_allocatedFlag && Width >= 0 && Height >= 0)
+ {
+ SizeAllocated(Width, Height);
+ }
+ }
+
+ internal void SendAppearing()
+ {
+ if (_hasAppeared)
+ return;
+
+ _hasAppeared = true;
+
+ if (IsBusy)
+ MessagingCenter.Send(this, BusySetSignalName, true);
+
+ OnAppearing();
+ EventHandler handler = Appearing;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+
+ var pageContainer = this as IPageContainer<Page>;
+ pageContainer?.CurrentPage?.SendAppearing();
+ }
+
+ internal void SendDisappearing()
+ {
+ if (!_hasAppeared)
+ return;
+
+ _hasAppeared = false;
+
+ if (IsBusy)
+ MessagingCenter.Send(this, BusySetSignalName, false);
+
+ var pageContainer = this as IPageContainer<Page>;
+ pageContainer?.CurrentPage?.SendDisappearing();
+
+ OnDisappearing();
+ EventHandler handler = Disappearing;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+
+ void InternalChildrenOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ if (e.OldItems != null)
+ {
+ foreach (VisualElement item in e.OldItems.OfType<VisualElement>())
+ OnInternalRemoved(item);
+ }
+
+ if (e.NewItems != null)
+ {
+ foreach (VisualElement item in e.NewItems.OfType<VisualElement>())
+ OnInternalAdded(item);
+ }
+ }
+
+ void OnInternalAdded(VisualElement view)
+ {
+ view.MeasureInvalidated += OnChildMeasureInvalidated;
+
+ OnChildAdded(view);
+ InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+
+ void OnInternalRemoved(VisualElement view)
+ {
+ view.MeasureInvalidated -= OnChildMeasureInvalidated;
+
+ OnChildRemoved(view);
+ }
+
+ void OnPageBusyChanged()
+ {
+ if (!_hasAppeared)
+ return;
+
+ MessagingCenter.Send(this, BusySetSignalName, IsBusy);
+ }
+
+ void OnToolbarItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
+ {
+ if (args.Action != NotifyCollectionChangedAction.Add)
+ return;
+ foreach (IElement item in args.NewItems)
+ item.Parent = this;
+ }
+
+ bool ShouldLayoutChildren()
+ {
+ if (!LogicalChildren.Any() || Width <= 0 || Height <= 0 || !IsNativeStateConsistent)
+ return false;
+
+ var container = this as IPageContainer<Page>;
+ if (container != null && container.CurrentPage != null)
+ {
+ if (InternalChildren.Contains(container.CurrentPage))
+ return container.CurrentPage.IsPlatformEnabled && container.CurrentPage.IsNativeStateConsistent;
+ return true;
+ }
+
+ var any = false;
+ for (var i = 0; i < LogicalChildren.Count; i++)
+ {
+ var v = LogicalChildren[i] as VisualElement;
+ if (v != null && (!v.IsPlatformEnabled || !v.IsNativeStateConsistent))
+ {
+ any = true;
+ break;
+ }
+ }
+ return !any;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/PanGestureRecognizer.cs b/Xamarin.Forms.Core/PanGestureRecognizer.cs
new file mode 100644
index 00000000..3fbf2f62
--- /dev/null
+++ b/Xamarin.Forms.Core/PanGestureRecognizer.cs
@@ -0,0 +1,37 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class PanGestureRecognizer : GestureRecognizer, IPanGestureController
+ {
+ public static readonly BindableProperty TouchPointsProperty = BindableProperty.Create("TouchPoints", typeof(int), typeof(PanGestureRecognizer), 1);
+
+ public int TouchPoints
+ {
+ get { return (int)GetValue(TouchPointsProperty); }
+ set { SetValue(TouchPointsProperty, value); }
+ }
+
+ void IPanGestureController.SendPan(Element sender, double totalX, double totalY, int gestureId)
+ {
+ PanUpdated?.Invoke(sender, new PanUpdatedEventArgs(GestureStatus.Running, gestureId, totalX, totalY));
+ }
+
+ void IPanGestureController.SendPanCanceled(Element sender, int gestureId)
+ {
+ PanUpdated?.Invoke(sender, new PanUpdatedEventArgs(GestureStatus.Canceled, gestureId));
+ }
+
+ void IPanGestureController.SendPanCompleted(Element sender, int gestureId)
+ {
+ PanUpdated?.Invoke(sender, new PanUpdatedEventArgs(GestureStatus.Completed, gestureId));
+ }
+
+ void IPanGestureController.SendPanStarted(Element sender, int gestureId)
+ {
+ PanUpdated?.Invoke(sender, new PanUpdatedEventArgs(GestureStatus.Started, gestureId));
+ }
+
+ public event EventHandler<PanUpdatedEventArgs> PanUpdated;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/PanUpdatedEventArgs.cs b/Xamarin.Forms.Core/PanUpdatedEventArgs.cs
new file mode 100644
index 00000000..4c9e9481
--- /dev/null
+++ b/Xamarin.Forms.Core/PanUpdatedEventArgs.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class PanUpdatedEventArgs : EventArgs
+ {
+ public PanUpdatedEventArgs(GestureStatus type, int gestureId, double totalx, double totaly) : this(type, gestureId)
+ {
+ TotalX = totalx;
+ TotalY = totaly;
+ }
+
+ public PanUpdatedEventArgs(GestureStatus type, int gestureId)
+ {
+ StatusType = type;
+ GestureId = gestureId;
+ }
+
+ public int GestureId { get; }
+
+ public GestureStatus StatusType { get; }
+
+ public double TotalX { get; }
+
+ public double TotalY { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ParameterAttribute.cs b/Xamarin.Forms.Core/ParameterAttribute.cs
new file mode 100644
index 00000000..d8a07267
--- /dev/null
+++ b/Xamarin.Forms.Core/ParameterAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Parameter)]
+ internal sealed class ParameterAttribute : Attribute
+ {
+ public ParameterAttribute(string name)
+ {
+ Name = name;
+ }
+
+ public string Name { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Performance.cs b/Xamarin.Forms.Core/Performance.cs
new file mode 100644
index 00000000..e627817b
--- /dev/null
+++ b/Xamarin.Forms.Core/Performance.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace Xamarin.Forms
+{
+ internal static class Performance
+ {
+ static readonly Dictionary<string, Stats> Statistics = new Dictionary<string, Stats>();
+
+ [Conditional("PERF")]
+ public static void Clear()
+ {
+ Statistics.Clear();
+ }
+
+ public static void Count(string tag = null, [CallerFilePath] string path = null, [CallerMemberName] string member = null)
+ {
+ string id = path + ":" + member + (tag != null ? "-" + tag : string.Empty);
+
+ Stats stats;
+ if (!Statistics.TryGetValue(id, out stats))
+ Statistics[id] = stats = new Stats();
+
+ stats.CallCount++;
+ }
+
+ [Conditional("PERF")]
+ public static void DumpStats()
+ {
+ Debug.WriteLine(GetStats());
+ }
+
+ public static string GetStats()
+ {
+ var b = new StringBuilder();
+ b.AppendLine("ID | Call Count | Total Time | Avg Time");
+ foreach (KeyValuePair<string, Stats> kvp in Statistics.OrderBy(kvp => kvp.Key))
+ {
+ string key = ShortenPath(kvp.Key);
+ double total = TimeSpan.FromTicks(kvp.Value.TotalTime).TotalMilliseconds;
+ double avg = total / kvp.Value.CallCount;
+ b.AppendFormat("{0,-80} | {1,-10} | {2,-10}ms | {3,-8}ms", key, kvp.Value.CallCount, total, avg);
+ b.AppendLine();
+ }
+ return b.ToString();
+ }
+
+ [Conditional("PERF")]
+ public static void Start(string tag = null, [CallerFilePath] string path = null, [CallerMemberName] string member = null)
+ {
+ string id = path + ":" + member + (tag != null ? "-" + tag : string.Empty);
+
+ Stats stats;
+ if (!Statistics.TryGetValue(id, out stats))
+ Statistics[id] = stats = new Stats();
+
+ stats.CallCount++;
+ stats.StartTimes.Push(Stopwatch.GetTimestamp());
+ }
+
+ [Conditional("PERF")]
+ public static void Stop(string tag = null, [CallerFilePath] string path = null, [CallerMemberName] string member = null)
+ {
+ string id = path + ":" + member + (tag != null ? "-" + tag : string.Empty);
+ long stop = Stopwatch.GetTimestamp();
+
+ Stats stats = Statistics[id];
+ long start = stats.StartTimes.Pop();
+ if (!stats.StartTimes.Any())
+ stats.TotalTime += stop - start;
+ }
+
+ static string ShortenPath(string path)
+ {
+ int index = path.IndexOf("Xamarin.Forms.");
+ if (index > -1)
+ path = path.Substring(index + 14);
+
+ return path;
+ }
+
+ class Stats
+ {
+ public readonly Stack<long> StartTimes = new Stack<long>();
+ public int CallCount;
+ public long TotalTime;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Picker.cs b/Xamarin.Forms.Core/Picker.cs
new file mode 100644
index 00000000..733f2079
--- /dev/null
+++ b/Xamarin.Forms.Core/Picker.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_PickerRenderer))]
+ public class Picker : View
+ {
+ public static readonly BindableProperty TitleProperty = BindableProperty.Create("Title", typeof(string), typeof(Picker), default(string));
+
+ public static readonly BindableProperty SelectedIndexProperty = BindableProperty.Create("SelectedIndex", typeof(int), typeof(Picker), -1, BindingMode.TwoWay,
+ propertyChanged: (bindable, oldvalue, newvalue) =>
+ {
+ EventHandler eh = ((Picker)bindable).SelectedIndexChanged;
+ if (eh != null)
+ eh(bindable, EventArgs.Empty);
+ }, coerceValue: CoerceSelectedIndex);
+
+ public Picker()
+ {
+ Items = new ObservableList<string>();
+ ((ObservableList<string>)Items).CollectionChanged += OnItemsCollectionChanged;
+ }
+
+ public IList<string> Items { get; }
+
+ public int SelectedIndex
+ {
+ get { return (int)GetValue(SelectedIndexProperty); }
+ set { SetValue(SelectedIndexProperty, value); }
+ }
+
+ public string Title
+ {
+ get { return (string)GetValue(TitleProperty); }
+ set { SetValue(TitleProperty, value); }
+ }
+
+ public event EventHandler SelectedIndexChanged;
+
+ static object CoerceSelectedIndex(BindableObject bindable, object value)
+ {
+ var picker = (Picker)bindable;
+ return picker.Items == null ? -1 : ((int)value).Clamp(-1, picker.Items.Count - 1);
+ }
+
+ void OnItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ SelectedIndex = SelectedIndex.Clamp(-1, Items.Count - 1);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/PinchGestureRecognizer.cs b/Xamarin.Forms.Core/PinchGestureRecognizer.cs
new file mode 100644
index 00000000..aef07fbb
--- /dev/null
+++ b/Xamarin.Forms.Core/PinchGestureRecognizer.cs
@@ -0,0 +1,51 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public sealed class PinchGestureRecognizer : GestureRecognizer, IPinchGestureController
+ {
+ bool IPinchGestureController.IsPinching { get; set; }
+
+ void IPinchGestureController.SendPinch(Element sender, double delta, Point currentScalePoint)
+ {
+ EventHandler<PinchGestureUpdatedEventArgs> handler = PinchUpdated;
+ if (handler != null)
+ {
+ handler(sender, new PinchGestureUpdatedEventArgs(GestureStatus.Running, delta, currentScalePoint));
+ }
+ ((IPinchGestureController)this).IsPinching = true;
+ }
+
+ void IPinchGestureController.SendPinchCanceled(Element sender)
+ {
+ EventHandler<PinchGestureUpdatedEventArgs> handler = PinchUpdated;
+ if (handler != null)
+ {
+ handler(sender, new PinchGestureUpdatedEventArgs(GestureStatus.Canceled));
+ }
+ ((IPinchGestureController)this).IsPinching = false;
+ }
+
+ void IPinchGestureController.SendPinchEnded(Element sender)
+ {
+ EventHandler<PinchGestureUpdatedEventArgs> handler = PinchUpdated;
+ if (handler != null)
+ {
+ handler(sender, new PinchGestureUpdatedEventArgs(GestureStatus.Completed));
+ }
+ ((IPinchGestureController)this).IsPinching = false;
+ }
+
+ void IPinchGestureController.SendPinchStarted(Element sender, Point initialScalePoint)
+ {
+ EventHandler<PinchGestureUpdatedEventArgs> handler = PinchUpdated;
+ if (handler != null)
+ {
+ handler(sender, new PinchGestureUpdatedEventArgs(GestureStatus.Started, 1, initialScalePoint));
+ }
+ ((IPinchGestureController)this).IsPinching = true;
+ }
+
+ public event EventHandler<PinchGestureUpdatedEventArgs> PinchUpdated;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/PinchGestureUpdatedEventArgs.cs b/Xamarin.Forms.Core/PinchGestureUpdatedEventArgs.cs
new file mode 100644
index 00000000..a5c0eacb
--- /dev/null
+++ b/Xamarin.Forms.Core/PinchGestureUpdatedEventArgs.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class PinchGestureUpdatedEventArgs : EventArgs
+ {
+ public PinchGestureUpdatedEventArgs(GestureStatus status, double scale, Point origin) : this(status)
+ {
+ ScaleOrigin = origin;
+ Scale = scale;
+ }
+
+ public PinchGestureUpdatedEventArgs(GestureStatus status)
+ {
+ Status = status;
+ }
+
+ public double Scale { get; } = 1;
+
+ public Point ScaleOrigin { get; }
+
+ public GestureStatus Status { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/PlatformEffect.cs b/Xamarin.Forms.Core/PlatformEffect.cs
new file mode 100644
index 00000000..e92231ce
--- /dev/null
+++ b/Xamarin.Forms.Core/PlatformEffect.cs
@@ -0,0 +1,28 @@
+using System.ComponentModel;
+
+namespace Xamarin.Forms
+{
+ public abstract class PlatformEffect<TContainer, TControl> : Effect where TContainer : class where TControl : class
+ {
+ public TContainer Container { get; internal set; }
+
+ public TControl Control { get; internal set; }
+
+ protected virtual void OnElementPropertyChanged(PropertyChangedEventArgs args)
+ {
+ }
+
+ internal override void SendDetached()
+ {
+ base.SendDetached();
+ Container = null;
+ Control = null;
+ }
+
+ internal override void SendOnElementPropertyChanged(PropertyChangedEventArgs args)
+ {
+ if (IsAttached)
+ OnElementPropertyChanged(args);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Point.cs b/Xamarin.Forms.Core/Point.cs
new file mode 100644
index 00000000..5c6f5471
--- /dev/null
+++ b/Xamarin.Forms.Core/Point.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Xamarin.Forms
+{
+ [DebuggerDisplay("X={X}, Y={Y}")]
+ [TypeConverter(typeof(PointTypeConverter))]
+ public struct Point
+ {
+ public double X { get; set; }
+
+ public double Y { get; set; }
+
+ public static Point Zero = new Point();
+
+ public override string ToString()
+ {
+ return string.Format("{{X={0} Y={1}}}", X.ToString(CultureInfo.InvariantCulture), Y.ToString(CultureInfo.InvariantCulture));
+ }
+
+ public Point(double x, double y) : this()
+ {
+ X = x;
+ Y = y;
+ }
+
+ public Point(Size sz) : this()
+ {
+ X = sz.Width;
+ Y = sz.Height;
+ }
+
+ public override bool Equals(object o)
+ {
+ if (!(o is Point))
+ return false;
+
+ return this == (Point)o;
+ }
+
+ public override int GetHashCode()
+ {
+ return X.GetHashCode() ^ (Y.GetHashCode() * 397);
+ }
+
+ public Point Offset(double dx, double dy)
+ {
+ Point p = this;
+ p.X += dx;
+ p.Y += dy;
+ return p;
+ }
+
+ public Point Round()
+ {
+ return new Point(Math.Round(X), Math.Round(Y));
+ }
+
+ public bool IsEmpty
+ {
+ get { return (X == 0) && (Y == 0); }
+ }
+
+ public static explicit operator Size(Point pt)
+ {
+ return new Size(pt.X, pt.Y);
+ }
+
+ public static Point operator +(Point pt, Size sz)
+ {
+ return new Point(pt.X + sz.Width, pt.Y + sz.Height);
+ }
+
+ public static Point operator -(Point pt, Size sz)
+ {
+ return new Point(pt.X - sz.Width, pt.Y - sz.Height);
+ }
+
+ public static bool operator ==(Point ptA, Point ptB)
+ {
+ return (ptA.X == ptB.X) && (ptA.Y == ptB.Y);
+ }
+
+ public static bool operator !=(Point ptA, Point ptB)
+ {
+ return (ptA.X != ptB.X) || (ptA.Y != ptB.Y);
+ }
+
+ public double Distance(Point other)
+ {
+ return Math.Sqrt(Math.Pow(X - other.X, 2) + Math.Pow(Y - other.Y, 2));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/PointTypeConverter.cs b/Xamarin.Forms.Core/PointTypeConverter.cs
new file mode 100644
index 00000000..9b949988
--- /dev/null
+++ b/Xamarin.Forms.Core/PointTypeConverter.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Globalization;
+
+namespace Xamarin.Forms
+{
+ public class PointTypeConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString(string value)
+ {
+ if (value != null)
+ {
+ double x, y;
+ string[] xy = value.Split(',');
+ if (xy.Length == 2 && double.TryParse(xy[0], NumberStyles.Number, CultureInfo.InvariantCulture, out x) && double.TryParse(xy[1], NumberStyles.Number, CultureInfo.InvariantCulture, out y))
+ return new Point(x, y);
+ }
+
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(Point)));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/PreserveAttribute.cs b/Xamarin.Forms.Core/PreserveAttribute.cs
new file mode 100644
index 00000000..41487c86
--- /dev/null
+++ b/Xamarin.Forms.Core/PreserveAttribute.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(
+ AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field |
+ AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate | AttributeTargets.All)]
+ internal class PreserveAttribute : Attribute
+ {
+ public bool AllMembers;
+ public bool Conditional;
+
+ public PreserveAttribute(bool allMembers, bool conditional)
+ {
+ AllMembers = allMembers;
+ Conditional = conditional;
+ }
+
+ public PreserveAttribute()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ProgressBar.cs b/Xamarin.Forms.Core/ProgressBar.cs
new file mode 100644
index 00000000..cd8addf6
--- /dev/null
+++ b/Xamarin.Forms.Core/ProgressBar.cs
@@ -0,0 +1,26 @@
+using System.Threading.Tasks;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_ProgressBarRenderer))]
+ public class ProgressBar : View
+ {
+ public static readonly BindableProperty ProgressProperty = BindableProperty.Create("Progress", typeof(double), typeof(ProgressBar), 0d, coerceValue: (bo, v) => ((double)v).Clamp(0, 1));
+
+ public double Progress
+ {
+ get { return (double)GetValue(ProgressProperty); }
+ set { SetValue(ProgressProperty, value); }
+ }
+
+ public Task<bool> ProgressTo(double value, uint length, Easing easing)
+ {
+ var tcs = new TaskCompletionSource<bool>();
+
+ this.Animate("Progress", d => Progress = d, Progress, value, length: length, easing: easing, finished: (d, finished) => tcs.SetResult(finished));
+
+ return tcs.Task;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Properties/AssemblyInfo.cs b/Xamarin.Forms.Core/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..b64ecc4d
--- /dev/null
+++ b/Xamarin.Forms.Core/Properties/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Xamarin.Forms;
+
+[assembly: AssemblyTitle("Xamarin.Forms.Core")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The Page "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+//[assembly: AssemblyVersion("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
+[assembly: InternalsVisibleTo("Xamarin.Forms.Platform.iOS")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Platform.iOS.Classic")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Platform.Android")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Platform.UAP")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Platform.WinRT")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Platform.WinRT.Tablet")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Platform.WinRT.Phone")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Platform.WP8")]
+[assembly: InternalsVisibleTo("iOSUnitTests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Controls")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Core.Design")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Core.UnitTests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Core.Android.UnitTests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Core.WP8.UnitTests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Xaml")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Maps")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Maps.iOS")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Maps.iOS.Classic")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Maps.Android")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Xaml.UnitTests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.UITests")]
+//[assembly:InternalsVisibleTo("Xamarin.Forms.Core.UITests")]
+
+[assembly: InternalsVisibleTo("Xamarin.Forms.Core.iOS.UITests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Core.Android.UITests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Core.Windows.UITests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.iOS.UITests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Android.UITests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Loader")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.UITest.Validator")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Build.Tasks")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Platform")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Pages")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Pages.UnitTests")]
+[assembly: Preserve] \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Properties/GlobalAssemblyInfo.cs b/Xamarin.Forms.Core/Properties/GlobalAssemblyInfo.cs
new file mode 100644
index 00000000..358bc29b
--- /dev/null
+++ b/Xamarin.Forms.Core/Properties/GlobalAssemblyInfo.cs
@@ -0,0 +1,8 @@
+using System.Reflection;
+
+[assembly: AssemblyCompany("Xamarin Inc.")]
+[assembly: AssemblyProduct("Xamarin.Forms")]
+[assembly: AssemblyCopyright("Copyright Xamarin Inc. 2013-2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyVersion("2.0.0.0")]
+[assembly: AssemblyFileVersion("2.0.0.0")] \ No newline at end of file
diff --git a/Xamarin.Forms.Core/PropertyChangingEventArgs.cs b/Xamarin.Forms.Core/PropertyChangingEventArgs.cs
new file mode 100644
index 00000000..75c78994
--- /dev/null
+++ b/Xamarin.Forms.Core/PropertyChangingEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class PropertyChangingEventArgs : EventArgs
+ {
+ public PropertyChangingEventArgs(string propertyName)
+ {
+ PropertyName = propertyName;
+ }
+
+ public virtual string PropertyName { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/PropertyChangingEventHandler.cs b/Xamarin.Forms.Core/PropertyChangingEventHandler.cs
new file mode 100644
index 00000000..06227c76
--- /dev/null
+++ b/Xamarin.Forms.Core/PropertyChangingEventHandler.cs
@@ -0,0 +1,4 @@
+namespace Xamarin.Forms
+{
+ public delegate void PropertyChangingEventHandler(object sender, PropertyChangingEventArgs e);
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ReadOnlyCastingList.cs b/Xamarin.Forms.Core/ReadOnlyCastingList.cs
new file mode 100644
index 00000000..a3f880c3
--- /dev/null
+++ b/Xamarin.Forms.Core/ReadOnlyCastingList.cs
@@ -0,0 +1,35 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ internal class ReadOnlyCastingList<T, TFrom> : IReadOnlyList<T> where T : class where TFrom : class
+ {
+ readonly IList<TFrom> _list;
+
+ public ReadOnlyCastingList(IList<TFrom> list)
+ {
+ _list = list;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable)_list).GetEnumerator();
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ return new CastingEnumerator<T, TFrom>(_list.GetEnumerator());
+ }
+
+ public int Count
+ {
+ get { return _list.Count; }
+ }
+
+ public T this[int index]
+ {
+ get { return _list[index] as T; }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ReadOnlyListAdapter.cs b/Xamarin.Forms.Core/ReadOnlyListAdapter.cs
new file mode 100644
index 00000000..0ffdaef5
--- /dev/null
+++ b/Xamarin.Forms.Core/ReadOnlyListAdapter.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Xamarin.Forms
+{
+ internal sealed class ReadOnlyListAdapter : IList
+ {
+ readonly IReadOnlyCollection<object> _collection;
+ readonly IReadOnlyList<object> _list;
+
+ public ReadOnlyListAdapter(IReadOnlyList<object> list)
+ {
+ _list = list;
+ _collection = list;
+ }
+
+ public ReadOnlyListAdapter(IReadOnlyCollection<object> collection)
+ {
+ _collection = collection;
+ }
+
+ public void CopyTo(Array array, int index)
+ {
+ throw new NotImplementedException();
+ }
+
+ public int Count
+ {
+ get { return _collection.Count; }
+ }
+
+ public bool IsSynchronized
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public object SyncRoot
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _collection.GetEnumerator();
+ }
+
+ public int Add(object value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Clear()
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool Contains(object value)
+ {
+ return _list.Contains(value);
+ }
+
+ public int IndexOf(object value)
+ {
+ return _list.IndexOf(value);
+ }
+
+ public void Insert(int index, object value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool IsFixedSize
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return true; }
+ }
+
+ public object this[int index]
+ {
+ get { return _list[index]; }
+ set { throw new NotImplementedException(); }
+ }
+
+ public void Remove(object value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void RemoveAt(int index)
+ {
+ throw new NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Rectangle.cs b/Xamarin.Forms.Core/Rectangle.cs
new file mode 100644
index 00000000..ac5460cb
--- /dev/null
+++ b/Xamarin.Forms.Core/Rectangle.cs
@@ -0,0 +1,244 @@
+//
+// Rectangle.cs
+//
+// Author:
+// Lluis Sanchez <lluis@xamarin.com>
+//
+// Copyright (c) 2011 Xamarin Inc
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Xamarin.Forms
+{
+ [DebuggerDisplay("X={X}, Y={Y}, Width={Width}, Height={Height}")]
+ [TypeConverter(typeof(RectangleTypeConverter))]
+ public struct Rectangle
+ {
+ public double X { get; set; }
+
+ public double Y { get; set; }
+
+ public double Width { get; set; }
+
+ public double Height { get; set; }
+
+ public static Rectangle Zero = new Rectangle();
+
+ public override string ToString()
+ {
+ return string.Format("{{X={0} Y={1} Width={2} Height={3}}}", X.ToString(CultureInfo.InvariantCulture), Y.ToString(CultureInfo.InvariantCulture), Width.ToString(CultureInfo.InvariantCulture),
+ Height.ToString(CultureInfo.InvariantCulture));
+ }
+
+ // constructors
+ public Rectangle(double x, double y, double width, double height) : this()
+ {
+ X = x;
+ Y = y;
+ Width = width;
+ Height = height;
+ }
+
+ public Rectangle(Point loc, Size sz) : this(loc.X, loc.Y, sz.Width, sz.Height)
+ {
+ }
+
+ public static Rectangle FromLTRB(double left, double top, double right, double bottom)
+ {
+ return new Rectangle(left, top, right - left, bottom - top);
+ }
+
+ public bool Equals(Rectangle other)
+ {
+ return X.Equals(other.X) && Y.Equals(other.Y) && Width.Equals(other.Width) && Height.Equals(other.Height);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ return false;
+ return obj is Rectangle && Equals((Rectangle)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hashCode = X.GetHashCode();
+ hashCode = (hashCode * 397) ^ Y.GetHashCode();
+ hashCode = (hashCode * 397) ^ Width.GetHashCode();
+ hashCode = (hashCode * 397) ^ Height.GetHashCode();
+ return hashCode;
+ }
+ }
+
+ public static bool operator ==(Rectangle r1, Rectangle r2)
+ {
+ return (r1.Location == r2.Location) && (r1.Size == r2.Size);
+ }
+
+ public static bool operator !=(Rectangle r1, Rectangle r2)
+ {
+ return !(r1 == r2);
+ }
+
+ // Hit Testing / Intersection / Union
+ public bool Contains(Rectangle rect)
+ {
+ return X <= rect.X && Right >= rect.Right && Y <= rect.Y && Bottom >= rect.Bottom;
+ }
+
+ public bool Contains(Point pt)
+ {
+ return Contains(pt.X, pt.Y);
+ }
+
+ public bool Contains(double x, double y)
+ {
+ return (x >= Left) && (x < Right) && (y >= Top) && (y < Bottom);
+ }
+
+ public bool IntersectsWith(Rectangle r)
+ {
+ return !((Left >= r.Right) || (Right <= r.Left) || (Top >= r.Bottom) || (Bottom <= r.Top));
+ }
+
+ public Rectangle Union(Rectangle r)
+ {
+ return Union(this, r);
+ }
+
+ public static Rectangle Union(Rectangle r1, Rectangle r2)
+ {
+ return FromLTRB(Math.Min(r1.Left, r2.Left), Math.Min(r1.Top, r2.Top), Math.Max(r1.Right, r2.Right), Math.Max(r1.Bottom, r2.Bottom));
+ }
+
+ public Rectangle Intersect(Rectangle r)
+ {
+ return Intersect(this, r);
+ }
+
+ public static Rectangle Intersect(Rectangle r1, Rectangle r2)
+ {
+ double x = Math.Max(r1.X, r2.X);
+ double y = Math.Max(r1.Y, r2.Y);
+ double width = Math.Min(r1.Right, r2.Right) - x;
+ double height = Math.Min(r1.Bottom, r2.Bottom) - y;
+
+ if (width < 0 || height < 0)
+ {
+ return Zero;
+ }
+ return new Rectangle(x, y, width, height);
+ }
+
+ // Position/Size
+ public double Top
+ {
+ get { return Y; }
+ set { Y = value; }
+ }
+
+ public double Bottom
+ {
+ get { return Y + Height; }
+ set { Height = value - Y; }
+ }
+
+ public double Right
+ {
+ get { return X + Width; }
+ set { Width = value - X; }
+ }
+
+ public double Left
+ {
+ get { return X; }
+ set { X = value; }
+ }
+
+ public bool IsEmpty
+ {
+ get { return (Width <= 0) || (Height <= 0); }
+ }
+
+ public Size Size
+ {
+ get { return new Size(Width, Height); }
+ set
+ {
+ Width = value.Width;
+ Height = value.Height;
+ }
+ }
+
+ public Point Location
+ {
+ get { return new Point(X, Y); }
+ set
+ {
+ X = value.X;
+ Y = value.Y;
+ }
+ }
+
+ public Point Center
+ {
+ get { return new Point(X + Width / 2, Y + Height / 2); }
+ }
+
+ // Inflate and Offset
+ public Rectangle Inflate(Size sz)
+ {
+ return Inflate(sz.Width, sz.Height);
+ }
+
+ public Rectangle Inflate(double width, double height)
+ {
+ Rectangle r = this;
+ r.X -= width;
+ r.Y -= height;
+ r.Width += width * 2;
+ r.Height += height * 2;
+ return r;
+ }
+
+ public Rectangle Offset(double dx, double dy)
+ {
+ Rectangle r = this;
+ r.X += dx;
+ r.Y += dy;
+ return r;
+ }
+
+ public Rectangle Offset(Point dr)
+ {
+ return Offset(dr.X, dr.Y);
+ }
+
+ public Rectangle Round()
+ {
+ return new Rectangle(Math.Round(X), Math.Round(Y), Math.Round(Width), Math.Round(Height));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/RectangleTypeConverter.cs b/Xamarin.Forms.Core/RectangleTypeConverter.cs
new file mode 100644
index 00000000..b17a8c26
--- /dev/null
+++ b/Xamarin.Forms.Core/RectangleTypeConverter.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Globalization;
+
+namespace Xamarin.Forms
+{
+ public class RectangleTypeConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString(string value)
+ {
+ if (value != null)
+ {
+ double x, y, w, h;
+ string[] xywh = value.Split(',');
+ if (xywh.Length == 4 && double.TryParse(xywh[0], NumberStyles.Number, CultureInfo.InvariantCulture, out x) && double.TryParse(xywh[1], NumberStyles.Number, CultureInfo.InvariantCulture, out y) &&
+ double.TryParse(xywh[2], NumberStyles.Number, CultureInfo.InvariantCulture, out w) && double.TryParse(xywh[3], NumberStyles.Number, CultureInfo.InvariantCulture, out h))
+ return new Rectangle(x, y, w, h);
+ }
+
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(Rectangle)));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ReflectionExtensions.cs b/Xamarin.Forms.Core/ReflectionExtensions.cs
new file mode 100644
index 00000000..ab26fde5
--- /dev/null
+++ b/Xamarin.Forms.Core/ReflectionExtensions.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Xamarin.Forms
+{
+ internal static class ReflectionExtensions
+ {
+ public static FieldInfo GetField(this Type type, Func<FieldInfo, bool> predicate)
+ {
+ return GetFields(type).SingleOrDefault(predicate);
+ }
+
+ public static FieldInfo GetField(this Type type, string name)
+ {
+ return type.GetField(fi => fi.Name == name);
+ }
+
+ public static IEnumerable<FieldInfo> GetFields(this Type type)
+ {
+ return GetParts(type, i => i.DeclaredFields);
+ }
+
+ public static IEnumerable<PropertyInfo> GetProperties(this Type type)
+ {
+ return GetParts(type, ti => ti.DeclaredProperties);
+ }
+
+ public static PropertyInfo GetProperty(this Type type, string name)
+ {
+ Type t = type;
+ while (t != null)
+ {
+ TypeInfo ti = t.GetTypeInfo();
+ PropertyInfo property = ti.GetDeclaredProperty(name);
+ if (property != null)
+ return property;
+
+ t = ti.BaseType;
+ }
+
+ return null;
+ }
+
+ public static bool IsAssignableFrom(this Type self, Type c)
+ {
+ return self.GetTypeInfo().IsAssignableFrom(c.GetTypeInfo());
+ }
+
+ public static bool IsInstanceOfType(this Type self, object o)
+ {
+ return self.GetTypeInfo().IsAssignableFrom(o.GetType().GetTypeInfo());
+ }
+
+ static IEnumerable<T> GetParts<T>(Type type, Func<TypeInfo, IEnumerable<T>> selector)
+ {
+ Type t = type;
+ while (t != null)
+ {
+ TypeInfo ti = t.GetTypeInfo();
+ foreach (T f in selector(ti))
+ yield return f;
+ t = ti.BaseType;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Registrar.cs b/Xamarin.Forms.Core/Registrar.cs
new file mode 100644
index 00000000..92c2e533
--- /dev/null
+++ b/Xamarin.Forms.Core/Registrar.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Xamarin.Forms
+{
+ internal class Registrar<TRegistrable> where TRegistrable : class
+ {
+ readonly Dictionary<Type, Type> _handlers = new Dictionary<Type, Type>();
+
+ public void Register(Type tview, Type trender)
+ {
+ _handlers[tview] = trender;
+ }
+
+ internal TRegistrable GetHandler(Type type)
+ {
+ Type handlerType = GetHandlerType(type);
+ if (handlerType == null)
+ return null;
+
+ object handler = Activator.CreateInstance(handlerType);
+ return (TRegistrable)handler;
+ }
+
+ internal TOut GetHandler<TOut>(Type type) where TOut : TRegistrable
+ {
+ return (TOut)GetHandler(type);
+ }
+
+ internal Type GetHandlerType(Type viewType)
+ {
+ Type type = LookupHandlerType(viewType);
+ if (type != null)
+ return type;
+
+ // lazy load render-view association with RenderWithAttribute (as opposed to using ExportRenderer)
+ // TODO: change Registrar to a LazyImmutableDictionary and pass this logic to ctor as a delegate.
+ var attribute = viewType.GetTypeInfo().GetCustomAttribute<RenderWithAttribute>();
+ if (attribute == null)
+ return null;
+ type = attribute.Type;
+
+ if (type.Name.StartsWith("_"))
+ {
+ // TODO: Remove attribute2 once renderer names have been unified across all platforms
+ var attribute2 = type.GetTypeInfo().GetCustomAttribute<RenderWithAttribute>();
+ if (attribute2 != null)
+ type = attribute2.Type;
+
+ if (type.Name.StartsWith("_"))
+ {
+ //var attrs = type.GetTypeInfo ().GetCustomAttributes ().ToArray ();
+ return null;
+ }
+ }
+
+ Register(viewType, type);
+ return LookupHandlerType(viewType);
+ }
+
+ Type LookupHandlerType(Type viewType)
+ {
+ Type type = viewType;
+
+ while (true)
+ {
+ if (_handlers.ContainsKey(type))
+ return _handlers[type];
+
+ type = type.GetTypeInfo().BaseType;
+ if (type == null)
+ break;
+ }
+
+ return null;
+ }
+ }
+
+ internal static class Registrar
+ {
+ static Registrar()
+ {
+ Registered = new Registrar<IRegisterable>();
+ }
+
+ internal static Dictionary<string, Type> Effects { get; } = new Dictionary<string, Type>();
+
+ internal static IEnumerable<Assembly> ExtraAssemblies { get; set; }
+
+ internal static Registrar<IRegisterable> Registered { get; }
+
+ internal static void RegisterAll(Type[] attrTypes)
+ {
+ Assembly[] assemblies = Device.GetAssemblies();
+ if (ExtraAssemblies != null)
+ {
+ assemblies = assemblies.Union(ExtraAssemblies).ToArray();
+ }
+
+ Assembly defaultRendererAssembly = Device.PlatformServices.GetType().GetTypeInfo().Assembly;
+ int indexOfExecuting = Array.IndexOf(assemblies, defaultRendererAssembly);
+
+ if (indexOfExecuting > 0)
+ {
+ assemblies[indexOfExecuting] = assemblies[0];
+ assemblies[0] = defaultRendererAssembly;
+ }
+
+ // Don't use LINQ for performance reasons
+ // Naive implementation can easily take over a second to run
+ foreach (Assembly assembly in assemblies)
+ {
+ foreach (Type attrType in attrTypes)
+ {
+ Attribute[] attributes = assembly.GetCustomAttributes(attrType).ToArray();
+ if (attributes.Length == 0)
+ continue;
+
+ foreach (HandlerAttribute attribute in attributes)
+ {
+ if (attribute.ShouldRegister())
+ Registered.Register(attribute.HandlerType, attribute.TargetType);
+ }
+ }
+
+ string resolutionName = assembly.FullName;
+ var resolutionNameAttribute = (ResolutionGroupNameAttribute)assembly.GetCustomAttribute(typeof(ResolutionGroupNameAttribute));
+ if (resolutionNameAttribute != null)
+ {
+ resolutionName = resolutionNameAttribute.ShortName;
+ }
+
+ Attribute[] effectAttributes = assembly.GetCustomAttributes(typeof(ExportEffectAttribute)).ToArray();
+ if (effectAttributes.Length > 0)
+ {
+ foreach (Attribute attribute in effectAttributes)
+ {
+ var effect = (ExportEffectAttribute)attribute;
+ Effects.Add(resolutionName + "." + effect.Id, effect.Type);
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/RelativeLayout.cs b/Xamarin.Forms.Core/RelativeLayout.cs
new file mode 100644
index 00000000..b3a1b615
--- /dev/null
+++ b/Xamarin.Forms.Core/RelativeLayout.cs
@@ -0,0 +1,317 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Linq.Expressions;
+
+namespace Xamarin.Forms
+{
+ public class RelativeLayout : Layout<View>
+ {
+ public static readonly BindableProperty XConstraintProperty = BindableProperty.CreateAttached("XConstraint", typeof(Constraint), typeof(RelativeLayout), null);
+
+ public static readonly BindableProperty YConstraintProperty = BindableProperty.CreateAttached("YConstraint", typeof(Constraint), typeof(RelativeLayout), null);
+
+ public static readonly BindableProperty WidthConstraintProperty = BindableProperty.CreateAttached("WidthConstraint", typeof(Constraint), typeof(RelativeLayout), null);
+
+ public static readonly BindableProperty HeightConstraintProperty = BindableProperty.CreateAttached("HeightConstraint", typeof(Constraint), typeof(RelativeLayout), null);
+
+ public static readonly BindableProperty BoundsConstraintProperty = BindableProperty.CreateAttached("BoundsConstraint", typeof(BoundsConstraint), typeof(RelativeLayout), null);
+
+ readonly RelativeElementCollection _children;
+
+ IEnumerable<View> _childrenInSolveOrder;
+
+ public RelativeLayout()
+ {
+ VerticalOptions = HorizontalOptions = LayoutOptions.FillAndExpand;
+ _children = new RelativeElementCollection(InternalChildren, this);
+ _children.Parent = this;
+ }
+
+ public new IRelativeList<View> Children
+ {
+ get { return _children; }
+ }
+
+ IEnumerable<View> ChildrenInSolveOrder
+ {
+ get
+ {
+ if (_childrenInSolveOrder != null)
+ return _childrenInSolveOrder;
+
+ var result = new List<View>();
+ var solveTable = new Dictionary<View, bool>();
+ foreach (View child in Children.Cast<View>())
+ {
+ solveTable[child] = false;
+ }
+
+ List<View> unsolvedChildren = Children.Cast<View>().ToList();
+ while (unsolvedChildren.Any())
+ {
+ List<View> copy = unsolvedChildren.ToList();
+ var solvedChild = false;
+ foreach (View child in copy)
+ {
+ if (CanSolveView(child, solveTable))
+ {
+ result.Add(child);
+ solveTable[child] = true;
+ unsolvedChildren.Remove(child);
+ solvedChild = true;
+ }
+ }
+ if (!solvedChild)
+ throw new UnsolvableConstraintsException("Constraints as specified contain an unsolvable loop.");
+ }
+
+ _childrenInSolveOrder = result;
+ return _childrenInSolveOrder;
+ }
+ }
+
+ public static BoundsConstraint GetBoundsConstraint(BindableObject bindable)
+ {
+ return (BoundsConstraint)bindable.GetValue(BoundsConstraintProperty);
+ }
+
+ public static Constraint GetHeightConstraint(BindableObject bindable)
+ {
+ return (Constraint)bindable.GetValue(HeightConstraintProperty);
+ }
+
+ public static Constraint GetWidthConstraint(BindableObject bindable)
+ {
+ return (Constraint)bindable.GetValue(WidthConstraintProperty);
+ }
+
+ public static Constraint GetXConstraint(BindableObject bindable)
+ {
+ return (Constraint)bindable.GetValue(XConstraintProperty);
+ }
+
+ public static Constraint GetYConstraint(BindableObject bindable)
+ {
+ return (Constraint)bindable.GetValue(YConstraintProperty);
+ }
+
+ public static void SetBoundsConstraint(BindableObject bindable, BoundsConstraint value)
+ {
+ bindable.SetValue(BoundsConstraintProperty, value);
+ }
+
+ protected override void LayoutChildren(double x, double y, double width, double height)
+ {
+ foreach (View child in ChildrenInSolveOrder)
+ {
+ LayoutChildIntoBoundingRegion(child, SolveView(child));
+ }
+ }
+
+ protected override void OnAdded(View view)
+ {
+ BoundsConstraint boundsConstraint = GetBoundsConstraint(view);
+ if (boundsConstraint == null)
+ {
+ // user probably added the view through the strict Add method.
+ CreateBoundsFromConstraints(view, GetXConstraint(view), GetYConstraint(view), GetWidthConstraint(view), GetHeightConstraint(view));
+ }
+
+ _childrenInSolveOrder = null;
+ base.OnAdded(view);
+ }
+
+ protected override void OnRemoved(View view)
+ {
+ _childrenInSolveOrder = null;
+ base.OnRemoved(view);
+ }
+
+ [Obsolete("Use OnMeasure")]
+ protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ double mockWidth = double.IsPositiveInfinity(widthConstraint) ? ParentView.Width : widthConstraint;
+ double mockHeight = double.IsPositiveInfinity(heightConstraint) ? ParentView.Height : heightConstraint;
+ MockBounds(new Rectangle(0, 0, mockWidth, mockHeight));
+
+ var boundsRectangle = new Rectangle();
+ var set = false;
+ foreach (View child in ChildrenInSolveOrder)
+ {
+ Rectangle bounds = SolveView(child);
+ child.MockBounds(bounds);
+ if (!set)
+ {
+ boundsRectangle = bounds;
+ set = true;
+ }
+ else
+ {
+ boundsRectangle.Left = Math.Min(boundsRectangle.Left, bounds.Left);
+ boundsRectangle.Top = Math.Min(boundsRectangle.Top, bounds.Top);
+ boundsRectangle.Right = Math.Max(boundsRectangle.Right, bounds.Right);
+ boundsRectangle.Bottom = Math.Max(boundsRectangle.Bottom, bounds.Bottom);
+ }
+ }
+
+ foreach (View child in ChildrenInSolveOrder)
+ child.UnmockBounds();
+
+ UnmockBounds();
+
+ return new SizeRequest(new Size(boundsRectangle.Right, boundsRectangle.Bottom));
+ }
+
+ bool CanSolveView(View view, Dictionary<View, bool> solveTable)
+ {
+ BoundsConstraint boundsConstraint = GetBoundsConstraint(view);
+ var parents = new List<View>();
+ if (boundsConstraint == null)
+ {
+ throw new Exception("BoundsConstraint should not be null at this point");
+ }
+ parents.AddRange(boundsConstraint.RelativeTo);
+ // expressions probably referenced the base layout somewhere
+ while (parents.Remove(this)) // because winphone does not have RemoveAll...
+ ;
+
+ if (!parents.Any())
+ return true;
+
+ for (var i = 0; i < parents.Count; i++)
+ {
+ View p = parents[i];
+
+ bool solvable;
+ if (!solveTable.TryGetValue(p, out solvable))
+ {
+ throw new InvalidOperationException("Views that have relationships to or from them must be kept in the RelativeLayout.");
+ }
+
+ if (!solvable)
+ return false;
+ }
+
+ return true;
+ }
+
+ void CreateBoundsFromConstraints(View view, Constraint xConstraint, Constraint yConstraint, Constraint widthConstraint, Constraint heightConstraint)
+ {
+ var parents = new List<View>();
+
+ Func<double> x;
+ if (xConstraint != null)
+ {
+ x = () => xConstraint.Compute(this);
+ if (xConstraint.RelativeTo != null)
+ parents.AddRange(xConstraint.RelativeTo);
+ }
+ else
+ x = () => 0;
+
+ Func<double> y;
+ if (yConstraint != null)
+ {
+ y = () => yConstraint.Compute(this);
+ if (yConstraint.RelativeTo != null)
+ parents.AddRange(yConstraint.RelativeTo);
+ }
+ else
+ y = () => 0;
+
+ Func<double> width;
+ if (widthConstraint != null)
+ {
+ width = () => widthConstraint.Compute(this);
+ if (widthConstraint.RelativeTo != null)
+ parents.AddRange(widthConstraint.RelativeTo);
+ }
+ else
+ width = () => view.Measure(Width, Height, MeasureFlags.IncludeMargins).Request.Width;
+
+ Func<double> height;
+ if (heightConstraint != null)
+ {
+ height = () => heightConstraint.Compute(this);
+ if (heightConstraint.RelativeTo != null)
+ parents.AddRange(heightConstraint.RelativeTo);
+ }
+ else
+ height = () => view.Measure(Width, Height, MeasureFlags.IncludeMargins).Request.Height;
+
+ BoundsConstraint bounds = BoundsConstraint.FromExpression(() => new Rectangle(x(), y(), width(), height()), parents.Distinct().ToArray());
+ SetBoundsConstraint(view, bounds);
+ }
+
+ static Rectangle SolveView(View view)
+ {
+ BoundsConstraint boundsConstraint = GetBoundsConstraint(view);
+ var result = new Rectangle();
+
+ if (boundsConstraint == null)
+ {
+ throw new Exception("BoundsConstraint should not be null at this point");
+ }
+ result = boundsConstraint.Compute();
+
+ return result;
+ }
+
+ public interface IRelativeList<T> : IList<T> where T : View
+ {
+ void Add(T view, Expression<Func<Rectangle>> bounds);
+
+ void Add(T view, Expression<Func<double>> x = null, Expression<Func<double>> y = null, Expression<Func<double>> width = null, Expression<Func<double>> height = null);
+
+ void Add(T view, Constraint xConstraint = null, Constraint yConstraint = null, Constraint widthConstraint = null, Constraint heightConstraint = null);
+ }
+
+ class RelativeElementCollection : ElementCollection<View>, IRelativeList<View>
+ {
+ public RelativeElementCollection(ObservableCollection<Element> inner, RelativeLayout parent) : base(inner)
+ {
+ Parent = parent;
+ }
+
+ internal RelativeLayout Parent { get; set; }
+
+ public void Add(View view, Expression<Func<Rectangle>> bounds)
+ {
+ if (bounds == null)
+ throw new ArgumentNullException("bounds");
+ SetBoundsConstraint(view, BoundsConstraint.FromExpression(bounds));
+
+ base.Add(view);
+ }
+
+ public void Add(View view, Expression<Func<double>> x = null, Expression<Func<double>> y = null, Expression<Func<double>> width = null, Expression<Func<double>> height = null)
+ {
+ Func<double> xCompiled = x != null ? x.Compile() : () => 0;
+ Func<double> yCompiled = y != null ? y.Compile() : () => 0;
+ Func<double> widthCompiled = width != null ? width.Compile() : () => view.Measure(Parent.Width, Parent.Height, MeasureFlags.IncludeMargins).Request.Width;
+ Func<double> heightCompiled = height != null ? height.Compile() : () => view.Measure(Parent.Width, Parent.Height, MeasureFlags.IncludeMargins).Request.Height;
+
+ var parents = new List<View>();
+ parents.AddRange(ExpressionSearch.Default.FindObjects<View>(x));
+ parents.AddRange(ExpressionSearch.Default.FindObjects<View>(y));
+ parents.AddRange(ExpressionSearch.Default.FindObjects<View>(width));
+ parents.AddRange(ExpressionSearch.Default.FindObjects<View>(height));
+
+ BoundsConstraint bounds = BoundsConstraint.FromExpression(() => new Rectangle(xCompiled(), yCompiled(), widthCompiled(), heightCompiled()), parents.Distinct().ToArray());
+
+ SetBoundsConstraint(view, bounds);
+
+ base.Add(view);
+ }
+
+ public void Add(View view, Constraint xConstraint = null, Constraint yConstraint = null, Constraint widthConstraint = null, Constraint heightConstraint = null)
+ {
+ Parent.CreateBoundsFromConstraints(view, xConstraint, yConstraint, widthConstraint, heightConstraint);
+
+ base.Add(view);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/RenderWithAttribute.cs b/Xamarin.Forms.Core/RenderWithAttribute.cs
new file mode 100644
index 00000000..75175306
--- /dev/null
+++ b/Xamarin.Forms.Core/RenderWithAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Class)]
+ public sealed class RenderWithAttribute : Attribute
+ {
+ public RenderWithAttribute(Type type)
+ {
+ Type = type;
+ }
+
+ public Type Type { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ResolutionGroupNameAttribute.cs b/Xamarin.Forms.Core/ResolutionGroupNameAttribute.cs
new file mode 100644
index 00000000..eee92e76
--- /dev/null
+++ b/Xamarin.Forms.Core/ResolutionGroupNameAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Assembly)]
+ public class ResolutionGroupNameAttribute : Attribute
+ {
+ public ResolutionGroupNameAttribute(string name)
+ {
+ ShortName = name;
+ }
+
+ internal string ShortName { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ResourceDictionary.cs b/Xamarin.Forms.Core/ResourceDictionary.cs
new file mode 100644
index 00000000..b19773ff
--- /dev/null
+++ b/Xamarin.Forms.Core/ResourceDictionary.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace Xamarin.Forms
+{
+ public sealed class ResourceDictionary : IResourceDictionary, IDictionary<string, object>
+ {
+ readonly Dictionary<string, object> _innerDictionary = new Dictionary<string, object>();
+
+ void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> item)
+ {
+ ((ICollection<KeyValuePair<string, object>>)_innerDictionary).Add(item);
+ OnValuesChanged(item);
+ }
+
+ public void Clear()
+ {
+ _innerDictionary.Clear();
+ }
+
+ bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item)
+ {
+ return ((ICollection<KeyValuePair<string, object>>)_innerDictionary).Contains(item);
+ }
+
+ void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
+ {
+ ((ICollection<KeyValuePair<string, object>>)_innerDictionary).CopyTo(array, arrayIndex);
+ }
+
+ public int Count
+ {
+ get { return _innerDictionary.Count; }
+ }
+
+ bool ICollection<KeyValuePair<string, object>>.IsReadOnly
+ {
+ get { return ((ICollection<KeyValuePair<string, object>>)_innerDictionary).IsReadOnly; }
+ }
+
+ bool ICollection<KeyValuePair<string, object>>.Remove(KeyValuePair<string, object> item)
+ {
+ return ((ICollection<KeyValuePair<string, object>>)_innerDictionary).Remove(item);
+ }
+
+ public void Add(string key, object value)
+ {
+ _innerDictionary.Add(key, value);
+ OnValueChanged(key, value);
+ }
+
+ public bool ContainsKey(string key)
+ {
+ return _innerDictionary.ContainsKey(key);
+ }
+
+ [IndexerName("Item")]
+ public object this[string index]
+ {
+ get { return _innerDictionary[index]; }
+ set
+ {
+ _innerDictionary[index] = value;
+ OnValueChanged(index, value);
+ }
+ }
+
+ public ICollection<string> Keys
+ {
+ get { return _innerDictionary.Keys; }
+ }
+
+ public bool Remove(string key)
+ {
+ return _innerDictionary.Remove(key);
+ }
+
+ public ICollection<object> Values
+ {
+ get { return _innerDictionary.Values; }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable)_innerDictionary).GetEnumerator();
+ }
+
+ public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
+ {
+ return _innerDictionary.GetEnumerator();
+ }
+
+ public bool TryGetValue(string key, out object value)
+ {
+ return _innerDictionary.TryGetValue(key, out value);
+ }
+
+ event EventHandler<ResourcesChangedEventArgs> IResourceDictionary.ValuesChanged
+ {
+ add { ValuesChanged += value; }
+ remove { ValuesChanged -= value; }
+ }
+
+ public void Add(Style style)
+ {
+ if (string.IsNullOrEmpty(style.Class))
+ Add(style.TargetType.FullName, style);
+ else
+ {
+ IList<Style> classes;
+ object outclasses;
+ if (!TryGetValue(Style.StyleClassPrefix + style.Class, out outclasses) || (classes = outclasses as IList<Style>) == null)
+ classes = new List<Style>();
+ classes.Add(style);
+ this[Style.StyleClassPrefix + style.Class] = classes;
+ }
+ }
+
+ void OnValueChanged(string key, object value)
+ {
+ OnValuesChanged(new KeyValuePair<string, object>(key, value));
+ }
+
+ void OnValuesChanged(params KeyValuePair<string, object>[] values)
+ {
+ if (values == null || values.Length == 0)
+ return;
+ ValuesChanged?.Invoke(this, new ResourcesChangedEventArgs(values));
+ }
+
+ event EventHandler<ResourcesChangedEventArgs> ValuesChanged;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ResourcesChangedEventArgs.cs b/Xamarin.Forms.Core/ResourcesChangedEventArgs.cs
new file mode 100644
index 00000000..2bab8565
--- /dev/null
+++ b/Xamarin.Forms.Core/ResourcesChangedEventArgs.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ internal class ResourcesChangedEventArgs : EventArgs
+ {
+ public ResourcesChangedEventArgs(IEnumerable<KeyValuePair<string, object>> values)
+ {
+ Values = values;
+ }
+
+ public IEnumerable<KeyValuePair<string, object>> Values { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ResourcesExtensions.cs b/Xamarin.Forms.Core/ResourcesExtensions.cs
new file mode 100644
index 00000000..a75e264a
--- /dev/null
+++ b/Xamarin.Forms.Core/ResourcesExtensions.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ internal static class ResourcesExtensions
+ {
+ public static IEnumerable<KeyValuePair<string, object>> GetMergedResources(this IElement element)
+ {
+ Dictionary<string, object> resources = null;
+ while (element != null)
+ {
+ var ve = element as IResourcesProvider;
+ if (ve != null && ve.Resources != null && ve.Resources.Count != 0)
+ {
+ resources = resources ?? new Dictionary<string, object>(ve.Resources.Count);
+ foreach (KeyValuePair<string, object> res in ve.Resources)
+ if (!resources.ContainsKey(res.Key))
+ resources.Add(res.Key, res.Value);
+ else if (res.Key.StartsWith(Style.StyleClassPrefix, StringComparison.Ordinal))
+ {
+ var mergedClassStyles = new List<Style>(resources[res.Key] as List<Style>);
+ mergedClassStyles.AddRange(res.Value as List<Style>);
+ resources[res.Key] = mergedClassStyles;
+ }
+ }
+ var app = element as Application;
+ if (app != null && app.SystemResources != null)
+ {
+ resources = resources ?? new Dictionary<string, object>(8);
+ foreach (KeyValuePair<string, object> res in app.SystemResources)
+ if (!resources.ContainsKey(res.Key))
+ resources.Add(res.Key, res.Value);
+ else if (res.Key.StartsWith(Style.StyleClassPrefix, StringComparison.Ordinal))
+ {
+ var mergedClassStyles = new List<Style>(resources[res.Key] as List<Style>);
+ mergedClassStyles.AddRange(res.Value as List<Style>);
+ resources[res.Key] = mergedClassStyles;
+ }
+ }
+ element = element.Parent;
+ }
+ return resources;
+ }
+
+ public static bool TryGetResource(this IElement element, string key, out object value)
+ {
+ while (element != null)
+ {
+ var ve = element as IResourcesProvider;
+ if (ve != null && ve.Resources != null && ve.Resources.TryGetValue(key, out value))
+ return true;
+ var app = element as Application;
+ if (app != null && app.SystemResources != null && app.SystemResources.TryGetValue(key, out value))
+ return true;
+ element = element.Parent;
+ }
+ value = null;
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/RoutingEffect.cs b/Xamarin.Forms.Core/RoutingEffect.cs
new file mode 100644
index 00000000..41f040b9
--- /dev/null
+++ b/Xamarin.Forms.Core/RoutingEffect.cs
@@ -0,0 +1,42 @@
+using System.ComponentModel;
+
+namespace Xamarin.Forms
+{
+ public class RoutingEffect : Effect
+ {
+ internal readonly Effect Inner;
+
+ protected RoutingEffect(string effectId)
+ {
+ Inner = Resolve(effectId);
+ }
+
+ protected override void OnAttached()
+ {
+ }
+
+ protected override void OnDetached()
+ {
+ }
+
+ internal override void ClearEffect()
+ {
+ Inner?.ClearEffect();
+ }
+
+ internal override void SendAttached()
+ {
+ Inner?.SendAttached();
+ }
+
+ internal override void SendDetached()
+ {
+ Inner?.SendDetached();
+ }
+
+ internal override void SendOnElementPropertyChanged(PropertyChangedEventArgs args)
+ {
+ Inner?.SendOnElementPropertyChanged(args);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/RowDefinition.cs b/Xamarin.Forms.Core/RowDefinition.cs
new file mode 100644
index 00000000..746332ea
--- /dev/null
+++ b/Xamarin.Forms.Core/RowDefinition.cs
@@ -0,0 +1,34 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public sealed class RowDefinition : BindableObject, IDefinition
+ {
+ public static readonly BindableProperty HeightProperty = BindableProperty.Create("Height", typeof(GridLength), typeof(RowDefinition), new GridLength(1, GridUnitType.Star),
+ propertyChanged: (bindable, oldValue, newValue) => ((RowDefinition)bindable).OnSizeChanged());
+
+ public RowDefinition()
+ {
+ MinimumHeight = -1;
+ }
+
+ public GridLength Height
+ {
+ get { return (GridLength)GetValue(HeightProperty); }
+ set { SetValue(HeightProperty, value); }
+ }
+
+ internal double ActualHeight { get; set; }
+
+ internal double MinimumHeight { get; set; }
+
+ public event EventHandler SizeChanged;
+
+ void OnSizeChanged()
+ {
+ EventHandler eh = SizeChanged;
+ if (eh != null)
+ eh(this, EventArgs.Empty);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/RowDefinitionCollection.cs b/Xamarin.Forms.Core/RowDefinitionCollection.cs
new file mode 100644
index 00000000..4b979be5
--- /dev/null
+++ b/Xamarin.Forms.Core/RowDefinitionCollection.cs
@@ -0,0 +1,6 @@
+namespace Xamarin.Forms
+{
+ public sealed class RowDefinitionCollection : DefinitionCollection<RowDefinition>
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ScrollOrientation.cs b/Xamarin.Forms.Core/ScrollOrientation.cs
new file mode 100644
index 00000000..71cb335f
--- /dev/null
+++ b/Xamarin.Forms.Core/ScrollOrientation.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Forms
+{
+ public enum ScrollOrientation
+ {
+ Vertical,
+ Horizontal,
+ Both
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ScrollToMode.cs b/Xamarin.Forms.Core/ScrollToMode.cs
new file mode 100644
index 00000000..741f5df0
--- /dev/null
+++ b/Xamarin.Forms.Core/ScrollToMode.cs
@@ -0,0 +1,10 @@
+namespace Xamarin.Forms
+{
+ public enum ScrollToMode
+ {
+ Element = 0,
+ Position = 1
+ // Item = 2,
+ // GroupAndItem = 3,
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ScrollToPosition.cs b/Xamarin.Forms.Core/ScrollToPosition.cs
new file mode 100644
index 00000000..adc13771
--- /dev/null
+++ b/Xamarin.Forms.Core/ScrollToPosition.cs
@@ -0,0 +1,10 @@
+namespace Xamarin.Forms
+{
+ public enum ScrollToPosition
+ {
+ MakeVisible = 0,
+ Start = 1,
+ Center = 2,
+ End = 3
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ScrollToRequestedEventArgs.cs b/Xamarin.Forms.Core/ScrollToRequestedEventArgs.cs
new file mode 100644
index 00000000..28231df7
--- /dev/null
+++ b/Xamarin.Forms.Core/ScrollToRequestedEventArgs.cs
@@ -0,0 +1,56 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class ScrollToRequestedEventArgs : EventArgs
+ {
+ internal ScrollToRequestedEventArgs(double scrollX, double scrollY, bool shouldAnimate)
+ {
+ ScrollX = scrollX;
+ ScrollY = scrollY;
+ ShouldAnimate = shouldAnimate;
+ Mode = ScrollToMode.Position;
+ }
+
+ internal ScrollToRequestedEventArgs(Element element, ScrollToPosition position, bool shouldAnimate)
+ {
+ Element = element;
+ Position = position;
+ ShouldAnimate = shouldAnimate;
+ Mode = ScrollToMode.Element;
+ }
+
+ internal ScrollToRequestedEventArgs(object item, ScrollToPosition position, bool shouldAnimate)
+ {
+ Item = item;
+ Position = position;
+ ShouldAnimate = shouldAnimate;
+ //Mode = ScrollToMode.Item;
+ }
+
+ internal ScrollToRequestedEventArgs(object item, object group, ScrollToPosition position, bool shouldAnimate)
+ {
+ Item = item;
+ Group = group;
+ Position = position;
+ ShouldAnimate = shouldAnimate;
+ //Mode = ScrollToMode.GroupAndIem;
+ }
+
+ public Element Element { get; private set; }
+
+ public ScrollToMode Mode { get; private set; }
+
+ public ScrollToPosition Position { get; private set; }
+
+ public double ScrollX { get; private set; }
+
+ public double ScrollY { get; private set; }
+
+ public bool ShouldAnimate { get; private set; }
+
+ internal object Group { get; private set; }
+
+ internal object Item { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ScrollView.cs b/Xamarin.Forms.Core/ScrollView.cs
new file mode 100644
index 00000000..143d0a61
--- /dev/null
+++ b/Xamarin.Forms.Core/ScrollView.cs
@@ -0,0 +1,287 @@
+using System;
+using System.Threading.Tasks;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("Content")]
+ [RenderWith(typeof(_ScrollViewRenderer))]
+ public class ScrollView : Layout, IScrollViewController
+ {
+ public static readonly BindableProperty OrientationProperty = BindableProperty.Create("Orientation", typeof(ScrollOrientation), typeof(ScrollView), ScrollOrientation.Vertical);
+
+ static readonly BindablePropertyKey ScrollXPropertyKey = BindableProperty.CreateReadOnly("ScrollX", typeof(double), typeof(ScrollView), 0d);
+
+ public static readonly BindableProperty ScrollXProperty = ScrollXPropertyKey.BindableProperty;
+
+ static readonly BindablePropertyKey ScrollYPropertyKey = BindableProperty.CreateReadOnly("ScrollY", typeof(double), typeof(ScrollView), 0d);
+
+ public static readonly BindableProperty ScrollYProperty = ScrollYPropertyKey.BindableProperty;
+
+ static readonly BindablePropertyKey ContentSizePropertyKey = BindableProperty.CreateReadOnly("ContentSize", typeof(Size), typeof(ScrollView), default(Size));
+
+ public static readonly BindableProperty ContentSizeProperty = ContentSizePropertyKey.BindableProperty;
+
+ View _content;
+
+ TaskCompletionSource<bool> _scrollCompletionSource;
+
+ public View Content
+ {
+ get { return _content; }
+ set
+ {
+ if (_content == value)
+ return;
+
+ OnPropertyChanging();
+ if (_content != null)
+ InternalChildren.Remove(_content);
+ _content = value;
+ if (_content != null)
+ InternalChildren.Add(_content);
+ OnPropertyChanged();
+ }
+ }
+
+ public Size ContentSize
+ {
+ get { return (Size)GetValue(ContentSizeProperty); }
+ private set { SetValue(ContentSizePropertyKey, value); }
+ }
+
+ public ScrollOrientation Orientation
+ {
+ get { return (ScrollOrientation)GetValue(OrientationProperty); }
+ set { SetValue(OrientationProperty, value); }
+ }
+
+ public double ScrollX
+ {
+ get { return (double)GetValue(ScrollXProperty); }
+ private set { SetValue(ScrollXPropertyKey, value); }
+ }
+
+ public double ScrollY
+ {
+ get { return (double)GetValue(ScrollYProperty); }
+ private set { SetValue(ScrollYPropertyKey, value); }
+ }
+
+ Point IScrollViewController.GetScrollPositionForElement(VisualElement item, ScrollToPosition pos)
+ {
+ ScrollToPosition position = pos;
+ double y = GetCoordinate(item, "Y", 0);
+ double x = GetCoordinate(item, "X", 0);
+
+ if (position == ScrollToPosition.MakeVisible)
+ {
+ bool isItemVisible = ScrollX < y && ScrollY + Height > y;
+ if (isItemVisible)
+ return new Point(ScrollX, ScrollY);
+ switch (Orientation)
+ {
+ case ScrollOrientation.Vertical:
+ position = y > ScrollY ? ScrollToPosition.End : ScrollToPosition.Start;
+ break;
+ case ScrollOrientation.Horizontal:
+ position = x > ScrollX ? ScrollToPosition.End : ScrollToPosition.Start;
+ break;
+ case ScrollOrientation.Both:
+ position = x > ScrollX || y > ScrollY ? ScrollToPosition.End : ScrollToPosition.Start;
+ break;
+ }
+ }
+ switch (position)
+ {
+ case ScrollToPosition.Center:
+ y = y - Height / 2 + item.Height / 2;
+ x = x - Width / 2 + item.Width / 2;
+ break;
+ case ScrollToPosition.End:
+ y = y - Height + item.Height;
+ x = x - Width + item.Width;
+ break;
+ }
+ return new Point(x, y);
+ }
+
+ event EventHandler<ScrollToRequestedEventArgs> IScrollViewController.ScrollToRequested
+ {
+ add { ScrollToRequested += value; }
+ remove { ScrollToRequested -= value; }
+ }
+
+ void IScrollViewController.SendScrollFinished()
+ {
+ if (_scrollCompletionSource != null)
+ _scrollCompletionSource.TrySetResult(true);
+ }
+
+ void IScrollViewController.SetScrolledPosition(double x, double y)
+ {
+ if (ScrollX == x && ScrollY == y)
+ return;
+
+ ScrollX = x;
+ ScrollY = y;
+
+ EventHandler<ScrolledEventArgs> handler = Scrolled;
+ if (handler != null)
+ handler(this, new ScrolledEventArgs(x, y));
+ }
+
+ public event EventHandler<ScrolledEventArgs> Scrolled;
+
+ public Task ScrollToAsync(double x, double y, bool animated)
+ {
+ var args = new ScrollToRequestedEventArgs(x, y, animated);
+ OnScrollToRequested(args);
+ return _scrollCompletionSource.Task;
+ }
+
+ public Task ScrollToAsync(Element element, ScrollToPosition position, bool animated)
+ {
+ if (!Enum.IsDefined(typeof(ScrollToPosition), position))
+ throw new ArgumentException("position is not a valid ScrollToPosition", "position");
+
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ if (!CheckElementBelongsToScrollViewer(element))
+ throw new ArgumentException("element does not belong to this ScrollVIew", "element");
+
+ var args = new ScrollToRequestedEventArgs(element, position, animated);
+ OnScrollToRequested(args);
+ return _scrollCompletionSource.Task;
+ }
+
+ protected override void LayoutChildren(double x, double y, double width, double height)
+ {
+ if (_content != null)
+ {
+ SizeRequest size;
+ switch (Orientation)
+ {
+ case ScrollOrientation.Horizontal:
+ size = _content.Measure(double.PositiveInfinity, height, MeasureFlags.IncludeMargins);
+ LayoutChildIntoBoundingRegion(_content, new Rectangle(x, y, GetMaxWidth(width, size), height));
+ ContentSize = new Size(GetMaxWidth(width), height);
+ break;
+ case ScrollOrientation.Vertical:
+ size = _content.Measure(width, double.PositiveInfinity, MeasureFlags.IncludeMargins);
+ LayoutChildIntoBoundingRegion(_content, new Rectangle(x, y, width, GetMaxHeight(height, size)));
+ ContentSize = new Size(width, GetMaxHeight(height));
+ break;
+ case ScrollOrientation.Both:
+ size = _content.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.IncludeMargins);
+ LayoutChildIntoBoundingRegion(_content, new Rectangle(x, y, GetMaxWidth(width, size), GetMaxHeight(height, size)));
+ ContentSize = new Size(GetMaxWidth(width), GetMaxHeight(height));
+ break;
+ }
+ }
+ }
+
+ [Obsolete("Use OnMeasure")]
+ protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ if (Content == null)
+ return new SizeRequest();
+
+ switch (Orientation)
+ {
+ case ScrollOrientation.Horizontal:
+ widthConstraint = double.PositiveInfinity;
+ break;
+ case ScrollOrientation.Vertical:
+ heightConstraint = double.PositiveInfinity;
+ break;
+ case ScrollOrientation.Both:
+ widthConstraint = double.PositiveInfinity;
+ heightConstraint = double.PositiveInfinity;
+ break;
+ }
+
+ SizeRequest contentRequest = Content.Measure(widthConstraint, heightConstraint, MeasureFlags.IncludeMargins);
+ contentRequest.Minimum = new Size(Math.Min(40, contentRequest.Minimum.Width), Math.Min(40, contentRequest.Minimum.Height));
+ return contentRequest;
+ }
+
+ internal override void ComputeConstraintForView(View view)
+ {
+ switch (Orientation)
+ {
+ case ScrollOrientation.Horizontal:
+ LayoutOptions vOptions = view.VerticalOptions;
+ if (vOptions.Alignment == LayoutAlignment.Fill && (Constraint & LayoutConstraint.VerticallyFixed) != 0)
+ {
+ view.ComputedConstraint = LayoutConstraint.VerticallyFixed;
+ }
+ break;
+ case ScrollOrientation.Vertical:
+ LayoutOptions hOptions = view.HorizontalOptions;
+ if (hOptions.Alignment == LayoutAlignment.Fill && (Constraint & LayoutConstraint.HorizontallyFixed) != 0)
+ {
+ view.ComputedConstraint = LayoutConstraint.HorizontallyFixed;
+ }
+ break;
+ case ScrollOrientation.Both:
+ view.ComputedConstraint = LayoutConstraint.None;
+ break;
+ }
+ }
+
+ bool CheckElementBelongsToScrollViewer(Element element)
+ {
+ return Equals(element, this) || element.RealParent != null && CheckElementBelongsToScrollViewer(element.RealParent);
+ }
+
+ void CheckTaskCompletionSource()
+ {
+ if (_scrollCompletionSource != null && _scrollCompletionSource.Task.Status == TaskStatus.Running)
+ {
+ _scrollCompletionSource.TrySetCanceled();
+ }
+ _scrollCompletionSource = new TaskCompletionSource<bool>();
+ }
+
+ double GetCoordinate(Element item, string coordinateName, double coordinate)
+ {
+ if (item == this)
+ return coordinate;
+ coordinate += (double)typeof(VisualElement).GetProperty(coordinateName).GetValue(item, null);
+ var visualParentElement = item.RealParent as VisualElement;
+ return visualParentElement != null ? GetCoordinate(visualParentElement, coordinateName, coordinate) : coordinate;
+ }
+
+ double GetMaxHeight(double height)
+ {
+ return Math.Max(height, _content.Bounds.Bottom + Padding.Bottom);
+ }
+
+ static double GetMaxHeight(double height, SizeRequest size)
+ {
+ return Math.Max(size.Request.Height, height);
+ }
+
+ double GetMaxWidth(double width)
+ {
+ return Math.Max(width, _content.Bounds.Right + Padding.Right);
+ }
+
+ static double GetMaxWidth(double width, SizeRequest size)
+ {
+ return Math.Max(size.Request.Width, width);
+ }
+
+ void OnScrollToRequested(ScrollToRequestedEventArgs e)
+ {
+ CheckTaskCompletionSource();
+ EventHandler<ScrollToRequestedEventArgs> handler = ScrollToRequested;
+ if (handler != null)
+ handler(this, e);
+ }
+
+ event EventHandler<ScrollToRequestedEventArgs> ScrollToRequested;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ScrolledEventArgs.cs b/Xamarin.Forms.Core/ScrolledEventArgs.cs
new file mode 100644
index 00000000..bc1d1f36
--- /dev/null
+++ b/Xamarin.Forms.Core/ScrolledEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class ScrolledEventArgs : EventArgs
+ {
+ public ScrolledEventArgs(double x, double y)
+ {
+ ScrollX = x;
+ ScrollY = y;
+ }
+
+ public double ScrollX { get; private set; }
+
+ public double ScrollY { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/SearchBar.cs b/Xamarin.Forms.Core/SearchBar.cs
new file mode 100644
index 00000000..089d9427
--- /dev/null
+++ b/Xamarin.Forms.Core/SearchBar.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Windows.Input;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_SearchBarRenderer))]
+ public class SearchBar : View, IFontElement
+ {
+ public static readonly BindableProperty SearchCommandProperty = BindableProperty.Create("SearchCommand", typeof(ICommand), typeof(SearchBar), null, propertyChanged: OnCommandChanged);
+
+ public static readonly BindableProperty SearchCommandParameterProperty = BindableProperty.Create("SearchCommandParameter", typeof(object), typeof(SearchBar), null);
+
+ public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(SearchBar), default(string), BindingMode.TwoWay,
+ propertyChanged: (bindable, oldValue, newValue) =>
+ {
+ var searchBar = (SearchBar)bindable;
+ EventHandler<TextChangedEventArgs> eh = searchBar.TextChanged;
+ if (eh != null)
+ eh(searchBar, new TextChangedEventArgs((string)oldValue, (string)newValue));
+ });
+
+ public static readonly BindableProperty CancelButtonColorProperty = BindableProperty.Create("CancelButtonColor", typeof(Color), typeof(SearchBar), default(Color));
+
+ public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create("Placeholder", typeof(string), typeof(SearchBar), null);
+
+ public static readonly BindableProperty FontFamilyProperty = BindableProperty.Create("FontFamily", typeof(string), typeof(SearchBar), default(string));
+
+ public static readonly BindableProperty FontSizeProperty = BindableProperty.Create("FontSize", typeof(double), typeof(SearchBar), -1.0,
+ defaultValueCreator: bindable => Device.GetNamedSize(NamedSize.Default, (SearchBar)bindable));
+
+ public static readonly BindableProperty FontAttributesProperty = BindableProperty.Create("FontAttributes", typeof(FontAttributes), typeof(SearchBar), FontAttributes.None);
+
+ public static readonly BindableProperty HorizontalTextAlignmentProperty = BindableProperty.Create("HorizontalTextAlignment", typeof(TextAlignment), typeof(SearchBar), TextAlignment.Start);
+
+ public static readonly BindableProperty TextColorProperty = BindableProperty.Create("TextColor", typeof(Color), typeof(SearchBar), Color.Default);
+
+ public static readonly BindableProperty PlaceholderColorProperty = BindableProperty.Create("PlaceholderColor", typeof(Color), typeof(SearchBar), Color.Default);
+
+ public Color CancelButtonColor
+ {
+ get { return (Color)GetValue(CancelButtonColorProperty); }
+ set { SetValue(CancelButtonColorProperty, value); }
+ }
+
+ public TextAlignment HorizontalTextAlignment
+ {
+ get { return (TextAlignment)GetValue(HorizontalTextAlignmentProperty); }
+ set { SetValue(HorizontalTextAlignmentProperty, value); }
+ }
+
+ public string Placeholder
+ {
+ get { return (string)GetValue(PlaceholderProperty); }
+ set { SetValue(PlaceholderProperty, value); }
+ }
+
+ public Color PlaceholderColor
+ {
+ get { return (Color)GetValue(PlaceholderColorProperty); }
+ set { SetValue(PlaceholderColorProperty, value); }
+ }
+
+ public ICommand SearchCommand
+ {
+ get { return (ICommand)GetValue(SearchCommandProperty); }
+ set { SetValue(SearchCommandProperty, value); }
+ }
+
+ public object SearchCommandParameter
+ {
+ get { return GetValue(SearchCommandParameterProperty); }
+ set { SetValue(SearchCommandParameterProperty, value); }
+ }
+
+ public string Text
+ {
+ get { return (string)GetValue(TextProperty); }
+ set { SetValue(TextProperty, value); }
+ }
+
+ public Color TextColor
+ {
+ get { return (Color)GetValue(TextColorProperty); }
+ set { SetValue(TextColorProperty, value); }
+ }
+
+ bool IsEnabledCore
+ {
+ set { SetValueCore(IsEnabledProperty, value); }
+ }
+
+ public FontAttributes FontAttributes
+ {
+ get { return (FontAttributes)GetValue(FontAttributesProperty); }
+ set { SetValue(FontAttributesProperty, value); }
+ }
+
+ public string FontFamily
+ {
+ get { return (string)GetValue(FontFamilyProperty); }
+ set { SetValue(FontFamilyProperty, value); }
+ }
+
+ [TypeConverter(typeof(FontSizeConverter))]
+ public double FontSize
+ {
+ get { return (double)GetValue(FontSizeProperty); }
+ set { SetValue(FontSizeProperty, value); }
+ }
+
+ public event EventHandler SearchButtonPressed;
+
+ public event EventHandler<TextChangedEventArgs> TextChanged;
+
+ internal void OnSearchButtonPressed()
+ {
+ ICommand cmd = SearchCommand;
+
+ if (cmd != null && !cmd.CanExecute(SearchCommandParameter))
+ return;
+
+ cmd?.Execute(SearchCommandParameter);
+ SearchButtonPressed?.Invoke(this, EventArgs.Empty);
+ }
+
+ void CommandCanExecuteChanged(object sender, EventArgs eventArgs)
+ {
+ ICommand cmd = SearchCommand;
+ if (cmd != null)
+ IsEnabledCore = cmd.CanExecute(SearchCommandParameter);
+ }
+
+ static void OnCommandChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var self = (SearchBar)bindable;
+ var newCommand = (Command)newValue;
+ var oldCommand = (Command)oldValue;
+
+ if (oldCommand != null)
+ {
+ oldCommand.CanExecuteChanged -= self.CommandCanExecuteChanged;
+ }
+
+ if (newCommand != null)
+ {
+ newCommand.CanExecuteChanged += self.CommandCanExecuteChanged;
+ self.CommandCanExecuteChanged(self, EventArgs.Empty);
+ }
+ else
+ {
+ self.IsEnabledCore = true;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/SelectedItemChangedEventArgs.cs b/Xamarin.Forms.Core/SelectedItemChangedEventArgs.cs
new file mode 100644
index 00000000..c37881f5
--- /dev/null
+++ b/Xamarin.Forms.Core/SelectedItemChangedEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class SelectedItemChangedEventArgs : EventArgs
+ {
+ public SelectedItemChangedEventArgs(object selectedItem)
+ {
+ SelectedItem = selectedItem;
+ }
+
+ public object SelectedItem { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/SelectedPositionChangedEventArgs.cs b/Xamarin.Forms.Core/SelectedPositionChangedEventArgs.cs
new file mode 100644
index 00000000..5f696b28
--- /dev/null
+++ b/Xamarin.Forms.Core/SelectedPositionChangedEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class SelectedPositionChangedEventArgs : EventArgs
+ {
+ public SelectedPositionChangedEventArgs(int selectedPosition)
+ {
+ SelectedPosition = selectedPosition;
+ }
+
+ public object SelectedPosition { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/SeparatorMenuItem.cs b/Xamarin.Forms.Core/SeparatorMenuItem.cs
new file mode 100644
index 00000000..5ddf70ae
--- /dev/null
+++ b/Xamarin.Forms.Core/SeparatorMenuItem.cs
@@ -0,0 +1,6 @@
+namespace Xamarin.Forms
+{
+ internal class SeparatorMenuItem : BaseMenuItem
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/SeparatorVisibility.cs b/Xamarin.Forms.Core/SeparatorVisibility.cs
new file mode 100644
index 00000000..6d2fdfc1
--- /dev/null
+++ b/Xamarin.Forms.Core/SeparatorVisibility.cs
@@ -0,0 +1,8 @@
+namespace Xamarin.Forms
+{
+ public enum SeparatorVisibility
+ {
+ Default = 0,
+ None = 1
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Setter.cs b/Xamarin.Forms.Core/Setter.cs
new file mode 100644
index 00000000..b260e8f0
--- /dev/null
+++ b/Xamarin.Forms.Core/Setter.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Xml;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("Value")]
+ public sealed class Setter : IValueProvider
+ {
+ readonly ConditionalWeakTable<BindableObject, object> _originalValues = new ConditionalWeakTable<BindableObject, object>();
+
+ public BindableProperty Property { get; set; }
+
+ public object Value { get; set; }
+
+ object IValueProvider.ProvideValue(IServiceProvider serviceProvider)
+ {
+ if (Property == null)
+ {
+ var lineInfoProvider = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) as IXmlLineInfoProvider;
+ IXmlLineInfo lineInfo = lineInfoProvider != null ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+ throw new XamlParseException("Property not set", lineInfo);
+ }
+ var valueconverter = serviceProvider.GetService(typeof(IValueConverterProvider)) as IValueConverterProvider;
+
+ Func<MemberInfo> minforetriever =
+ () =>
+ (MemberInfo)Property.DeclaringType.GetRuntimeProperty(Property.PropertyName) ?? (MemberInfo)Property.DeclaringType.GetRuntimeMethod("Get" + Property.PropertyName, new[] { typeof(BindableObject) });
+
+ object value = valueconverter.Convert(Value, Property.ReturnType, minforetriever, serviceProvider);
+ Value = value;
+ return this;
+ }
+
+ internal void Apply(BindableObject target, bool fromStyle = false)
+ {
+ if (target == null)
+ throw new ArgumentNullException("target");
+ if (Property == null)
+ return;
+
+ object originalValue = target.GetValue(Property);
+ if (!Equals(originalValue, Property.DefaultValue))
+ {
+ _originalValues.Remove(target);
+ _originalValues.Add(target, originalValue);
+ }
+
+ var dynamicResource = Value as DynamicResource;
+ var binding = Value as BindingBase;
+ if (binding != null)
+ target.SetBinding(Property, binding.Clone(), fromStyle);
+ else if (dynamicResource != null)
+ target.SetDynamicResource(Property, dynamicResource.Key, fromStyle);
+ else
+ target.SetValue(Property, Value, fromStyle);
+ }
+
+ internal void UnApply(BindableObject target, bool fromStyle = false)
+ {
+ if (target == null)
+ throw new ArgumentNullException("target");
+ if (Property == null)
+ return;
+
+ object actual = target.GetValue(Property);
+ if (!fromStyle && !Equals(actual, Value))
+ {
+ //Do not reset default value if the value has been changed
+ _originalValues.Remove(target);
+ return;
+ }
+
+ object defaultValue;
+ if (_originalValues.TryGetValue(target, out defaultValue))
+ {
+ //reset default value, unapply bindings and dynamicResource
+ target.SetValue(Property, defaultValue, fromStyle);
+ _originalValues.Remove(target);
+ }
+ else
+ target.ClearValue(Property);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/SettersExtensions.cs b/Xamarin.Forms.Core/SettersExtensions.cs
new file mode 100644
index 00000000..8f94e6d8
--- /dev/null
+++ b/Xamarin.Forms.Core/SettersExtensions.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms
+{
+ public static class SettersExtensions
+ {
+ public static void Add(this IList<Setter> setters, BindableProperty property, object value)
+ {
+ setters.Add(new Setter { Property = property, Value = value });
+ }
+
+ public static void AddBinding(this IList<Setter> setters, BindableProperty property, Binding binding)
+ {
+ if (binding == null)
+ throw new ArgumentNullException("binding");
+
+ setters.Add(new Setter { Property = property, Value = binding });
+ }
+
+ public static void AddDynamicResource(this IList<Setter> setters, BindableProperty property, string key)
+ {
+ if (string.IsNullOrEmpty(key))
+ throw new ArgumentNullException("key");
+ setters.Add(new Setter { Property = property, Value = new DynamicResource(key) });
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Size.cs b/Xamarin.Forms.Core/Size.cs
new file mode 100644
index 00000000..4e709a10
--- /dev/null
+++ b/Xamarin.Forms.Core/Size.cs
@@ -0,0 +1,110 @@
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Xamarin.Forms
+{
+ [DebuggerDisplay("Width={Width}, Height={Height}")]
+ public struct Size
+ {
+ double _width;
+ double _height;
+
+ public static readonly Size Zero;
+
+ public Size(double width, double height)
+ {
+ if (double.IsNaN(width))
+ throw new ArgumentException("NaN is not a valid value for width");
+ if (double.IsNaN(height))
+ throw new ArgumentException("NaN is not a valid value for height");
+ _width = width;
+ _height = height;
+ }
+
+ public bool IsZero
+ {
+ get { return (_width == 0) && (_height == 0); }
+ }
+
+ [DefaultValue(0d)]
+ public double Width
+ {
+ get { return _width; }
+ set
+ {
+ if (double.IsNaN(value))
+ throw new ArgumentException("NaN is not a valid value for Width");
+ _width = value;
+ }
+ }
+
+ [DefaultValue(0d)]
+ public double Height
+ {
+ get { return _height; }
+ set
+ {
+ if (double.IsNaN(value))
+ throw new ArgumentException("NaN is not a valid value for Height");
+ _height = value;
+ }
+ }
+
+ public static Size operator +(Size s1, Size s2)
+ {
+ return new Size(s1._width + s2._width, s1._height + s2._height);
+ }
+
+ public static Size operator -(Size s1, Size s2)
+ {
+ return new Size(s1._width - s2._width, s1._height - s2._height);
+ }
+
+ public static Size operator *(Size s1, double value)
+ {
+ return new Size(s1._width * value, s1._height * value);
+ }
+
+ public static bool operator ==(Size s1, Size s2)
+ {
+ return (s1._width == s2._width) && (s1._height == s2._height);
+ }
+
+ public static bool operator !=(Size s1, Size s2)
+ {
+ return (s1._width != s2._width) || (s1._height != s2._height);
+ }
+
+ public static explicit operator Point(Size size)
+ {
+ return new Point(size.Width, size.Height);
+ }
+
+ public bool Equals(Size other)
+ {
+ return _width.Equals(other._width) && _height.Equals(other._height);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ return false;
+ return obj is Size && Equals((Size)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return (_width.GetHashCode() * 397) ^ _height.GetHashCode();
+ }
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{{Width={0} Height={1}}}", _width.ToString(CultureInfo.InvariantCulture), _height.ToString(CultureInfo.InvariantCulture));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/SizeRequest.cs b/Xamarin.Forms.Core/SizeRequest.cs
new file mode 100644
index 00000000..3a54aca2
--- /dev/null
+++ b/Xamarin.Forms.Core/SizeRequest.cs
@@ -0,0 +1,29 @@
+using System.Diagnostics;
+
+namespace Xamarin.Forms
+{
+ [DebuggerDisplay("Request={Request.Width}x{Request.Height}, Minimum={Minimum.Width}x{Minimum.Height}")]
+ public struct SizeRequest
+ {
+ public Size Request { get; set; }
+
+ public Size Minimum { get; set; }
+
+ public SizeRequest(Size request, Size minimum)
+ {
+ Request = request;
+ Minimum = minimum;
+ }
+
+ public SizeRequest(Size request)
+ {
+ Request = request;
+ Minimum = request;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{{Request={0} Minimum={1}}}", Request, Minimum);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Slider.cs b/Xamarin.Forms.Core/Slider.cs
new file mode 100644
index 00000000..6363c410
--- /dev/null
+++ b/Xamarin.Forms.Core/Slider.cs
@@ -0,0 +1,85 @@
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_SliderRenderer))]
+ public class Slider : View
+ {
+ public static readonly BindableProperty MinimumProperty = BindableProperty.Create("Minimum", typeof(double), typeof(Slider), 0d, validateValue: (bindable, value) =>
+ {
+ var slider = (Slider)bindable;
+ return (double)value < slider.Maximum;
+ }, coerceValue: (bindable, value) =>
+ {
+ var slider = (Slider)bindable;
+ slider.Value = slider.Value.Clamp((double)value, slider.Maximum);
+ return value;
+ });
+
+ public static readonly BindableProperty MaximumProperty = BindableProperty.Create("Maximum", typeof(double), typeof(Slider), 1d, validateValue: (bindable, value) =>
+ {
+ var slider = (Slider)bindable;
+ return (double)value > slider.Minimum;
+ }, coerceValue: (bindable, value) =>
+ {
+ var slider = (Slider)bindable;
+ slider.Value = slider.Value.Clamp(slider.Minimum, (double)value);
+ return value;
+ });
+
+ public static readonly BindableProperty ValueProperty = BindableProperty.Create("Value", typeof(double), typeof(Slider), 0d, BindingMode.TwoWay, coerceValue: (bindable, value) =>
+ {
+ var slider = (Slider)bindable;
+ return ((double)value).Clamp(slider.Minimum, slider.Maximum);
+ }, propertyChanged: (bindable, oldValue, newValue) =>
+ {
+ var slider = (Slider)bindable;
+ EventHandler<ValueChangedEventArgs> eh = slider.ValueChanged;
+ if (eh != null)
+ eh(slider, new ValueChangedEventArgs((double)oldValue, (double)newValue));
+ });
+
+ public Slider()
+ {
+ }
+
+ public Slider(double min, double max, double val)
+ {
+ if (min >= max)
+ throw new ArgumentOutOfRangeException("min");
+
+ if (max > Minimum)
+ {
+ Maximum = max;
+ Minimum = min;
+ }
+ else
+ {
+ Minimum = min;
+ Maximum = max;
+ }
+ Value = val.Clamp(min, max);
+ }
+
+ public double Maximum
+ {
+ get { return (double)GetValue(MaximumProperty); }
+ set { SetValue(MaximumProperty, value); }
+ }
+
+ public double Minimum
+ {
+ get { return (double)GetValue(MinimumProperty); }
+ set { SetValue(MinimumProperty, value); }
+ }
+
+ public double Value
+ {
+ get { return (double)GetValue(ValueProperty); }
+ set { SetValue(ValueProperty, value); }
+ }
+
+ public event EventHandler<ValueChangedEventArgs> ValueChanged;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Span.cs b/Xamarin.Forms.Core/Span.cs
new file mode 100644
index 00000000..3789ddff
--- /dev/null
+++ b/Xamarin.Forms.Core/Span.cs
@@ -0,0 +1,169 @@
+using System;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("Text")]
+ public sealed class Span : INotifyPropertyChanged, IFontElement
+ {
+ Color _backgroundColor;
+
+ Font _font;
+ FontAttributes _fontAttributes;
+ string _fontFamily;
+ double _fontSize;
+
+ Color _foregroundColor;
+ bool _inUpdate; // if we ever make this thread safe we need to move to a mutex
+
+ string _text;
+
+ public Span()
+ {
+ _fontFamily = null;
+ _fontAttributes = FontAttributes.None;
+ _fontSize = Device.GetNamedSize(NamedSize.Default, typeof(Label), true);
+ _font = Font.SystemFontOfSize(_fontSize);
+ }
+
+ public Color BackgroundColor
+ {
+ get { return _backgroundColor; }
+ set
+ {
+ if (_backgroundColor == value)
+ return;
+ _backgroundColor = value;
+ OnPropertyChanged();
+ }
+ }
+
+ [Obsolete("Please use the Font properties directly. Obsolete in 1.3.0")]
+ public Font Font
+ {
+ get { return _font; }
+ set
+ {
+ if (_font == value)
+ return;
+ _font = value;
+ OnPropertyChanged();
+ UpdateFontPropertiesFromStruct();
+ }
+ }
+
+ public Color ForegroundColor
+ {
+ get { return _foregroundColor; }
+ set
+ {
+ if (_foregroundColor == value)
+ return;
+ _foregroundColor = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public string Text
+ {
+ get { return _text; }
+ set
+ {
+ if (_text == value)
+ return;
+ _text = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public FontAttributes FontAttributes
+ {
+ get { return _fontAttributes; }
+ set
+ {
+ if (_fontAttributes == value)
+ return;
+ _fontAttributes = value;
+ OnPropertyChanged();
+ UpdateStructFromFontProperties();
+ }
+ }
+
+ public string FontFamily
+ {
+ get { return _fontFamily; }
+ set
+ {
+ if (_fontFamily == value)
+ return;
+ _fontFamily = value;
+ OnPropertyChanged();
+ UpdateStructFromFontProperties();
+ }
+ }
+
+ [TypeConverter(typeof(FontSizeConverter))]
+ public double FontSize
+ {
+ get { return _fontSize; }
+ set
+ {
+ if (_fontSize == value)
+ return;
+ _fontSize = value;
+ OnPropertyChanged();
+ UpdateStructFromFontProperties();
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler(this, new PropertyChangedEventArgs(propertyName));
+ }
+
+ void UpdateFontPropertiesFromStruct()
+ {
+ if (_inUpdate)
+ return;
+ _inUpdate = true;
+
+ if (Font == Font.Default)
+ {
+ FontSize = Device.GetNamedSize(NamedSize.Default, typeof(Label), true);
+ FontFamily = null;
+ FontAttributes = FontAttributes.None;
+ }
+ else
+ {
+ FontSize = Font.UseNamedSize ? Device.GetNamedSize(Font.NamedSize, typeof(Label), true) : Font.FontSize;
+ FontFamily = Font.FontFamily;
+ FontAttributes = Font.FontAttributes;
+ }
+
+ _inUpdate = false;
+ }
+
+ void UpdateStructFromFontProperties()
+ {
+ if (_inUpdate)
+ return;
+ _inUpdate = true;
+
+ if (FontFamily != null)
+ {
+ Font = Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes);
+ }
+ else
+ {
+ Font = Font.SystemFontOfSize(FontSize).WithAttributes(FontAttributes);
+ }
+
+ _inUpdate = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/SplitOrderedList.cs b/Xamarin.Forms.Core/SplitOrderedList.cs
new file mode 100644
index 00000000..6f423210
--- /dev/null
+++ b/Xamarin.Forms.Core/SplitOrderedList.cs
@@ -0,0 +1,497 @@
+// SplitOrderedList.cs
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Xamarin.Forms
+{
+ internal class SplitOrderedList<TKey, T>
+ {
+ const int MaxLoad = 5;
+ const uint BucketSize = 512;
+
+ static readonly byte[] ReverseTable =
+ {
+ 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, 4,
+ 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210,
+ 50, 178, 114, 242, 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, 14, 142, 78, 206, 46, 174, 110,
+ 238, 30, 158, 94, 222, 62, 190, 126, 254, 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, 5, 133, 69,
+ 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179,
+ 115, 243, 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, 15, 143, 79, 207, 47, 175, 111, 239, 31,
+ 159, 95, 223, 63, 191, 127, 255
+ };
+
+ static readonly byte[] LogTable =
+ {
+ 0xFF, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7
+ };
+
+ readonly IEqualityComparer<TKey> _comparer;
+
+ readonly Node _head;
+ readonly Node _tail;
+
+ Node[] _buckets = new Node[BucketSize];
+ int _count;
+ int _size = 2;
+
+ SimpleRwLock _slim = new SimpleRwLock();
+
+ public SplitOrderedList(IEqualityComparer<TKey> comparer)
+ {
+ _comparer = comparer;
+ _head = new Node().Init(0);
+ _tail = new Node().Init(ulong.MaxValue);
+ _head.Next = _tail;
+ SetBucket(0, _head);
+ }
+
+ public int Count
+ {
+ get { return _count; }
+ }
+
+ public bool CompareExchange(uint key, TKey subKey, T data, Func<T, bool> check)
+ {
+ Node node;
+ uint b = key % (uint)_size;
+ Node bucket;
+
+ if ((bucket = GetBucket(b)) == null)
+ bucket = InitializeBucket(b);
+
+ if (!ListFind(ComputeRegularKey(key), subKey, bucket, out node))
+ return false;
+
+ if (!check(node.Data))
+ return false;
+
+ node.Data = data;
+
+ return true;
+ }
+
+ public bool Delete(uint key, TKey subKey, out T data)
+ {
+ uint b = key % (uint)_size;
+ Node bucket;
+
+ if ((bucket = GetBucket(b)) == null)
+ bucket = InitializeBucket(b);
+
+ if (!ListDelete(bucket, ComputeRegularKey(key), subKey, out data))
+ return false;
+
+ Interlocked.Decrement(ref _count);
+ return true;
+ }
+
+ public bool Find(uint key, TKey subKey, out T data)
+ {
+ Node node;
+ uint b = key % (uint)_size;
+ data = default(T);
+ Node bucket;
+
+ if ((bucket = GetBucket(b)) == null)
+ bucket = InitializeBucket(b);
+
+ if (!ListFind(ComputeRegularKey(key), subKey, bucket, out node))
+ return false;
+
+ data = node.Data;
+
+ return !node.Marked;
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ Node node = _head.Next;
+
+ while (node != _tail)
+ {
+ while (node.Marked || (node.Key & 1) == 0)
+ {
+ node = node.Next;
+ if (node == _tail)
+ yield break;
+ }
+ yield return node.Data;
+ node = node.Next;
+ }
+ }
+
+ public bool Insert(uint key, TKey subKey, T data)
+ {
+ Node current;
+ return InsertInternal(key, subKey, data, null, out current);
+ }
+
+ public T InsertOrGet(uint key, TKey subKey, T data, Func<T> dataCreator)
+ {
+ Node current;
+ InsertInternal(key, subKey, data, dataCreator, out current);
+ return current.Data;
+ }
+
+ public T InsertOrUpdate(uint key, TKey subKey, Func<T> addGetter, Func<T, T> updateGetter)
+ {
+ Node current;
+ bool result = InsertInternal(key, subKey, default(T), addGetter, out current);
+
+ if (result)
+ return current.Data;
+
+ // FIXME: this should have a CAS-like behavior
+ return current.Data = updateGetter(current.Data);
+ }
+
+ public T InsertOrUpdate(uint key, TKey subKey, T addValue, T updateValue)
+ {
+ Node current;
+ if (InsertInternal(key, subKey, addValue, null, out current))
+ return current.Data;
+
+ // FIXME: this should have a CAS-like behavior
+ return current.Data = updateValue;
+ }
+
+ // When we run out of space for bucket storage, we use a lock-based array resize
+ void CheckSegment(uint segment, bool readLockTaken)
+ {
+ if (segment < _buckets.Length)
+ return;
+
+ if (readLockTaken)
+ _slim.ExitReadLock();
+ try
+ {
+ _slim.EnterWriteLock();
+ while (segment >= _buckets.Length)
+ Array.Resize(ref _buckets, _buckets.Length * 2);
+ }
+ finally
+ {
+ _slim.ExitWriteLock();
+ }
+ if (readLockTaken)
+ _slim.EnterReadLock();
+ }
+
+ // Reverse integer bits
+ static ulong ComputeDummyKey(uint key)
+ {
+ return (ulong)(((uint)ReverseTable[key & 0xff] << 24) | ((uint)ReverseTable[(key >> 8) & 0xff] << 16) | ((uint)ReverseTable[(key >> 16) & 0xff] << 8) | ReverseTable[(key >> 24) & 0xff]) << 1;
+ }
+
+ // Reverse integer bits and make sure LSB is set
+ static ulong ComputeRegularKey(uint key)
+ {
+ return ComputeDummyKey(key) | 1;
+ }
+
+ // Bucket storage is abstracted in a simple two-layer tree to avoid too much memory resize
+ Node GetBucket(uint index)
+ {
+ if (index >= _buckets.Length)
+ return null;
+ return _buckets[index];
+ }
+
+ // Turn v's MSB off
+ static uint GetParent(uint v)
+ {
+ uint t, tt;
+
+ // Find MSB position in v
+ int pos = (tt = v >> 16) > 0 ? (t = tt >> 8) > 0 ? 24 + LogTable[t] : 16 + LogTable[tt] : (t = v >> 8) > 0 ? 8 + LogTable[t] : LogTable[v];
+
+ return (uint)(v & ~(1 << pos));
+ }
+
+ Node InitializeBucket(uint b)
+ {
+ Node current;
+ uint parent = GetParent(b);
+ Node bucket;
+
+ if ((bucket = GetBucket(parent)) == null)
+ bucket = InitializeBucket(parent);
+
+ Node dummy = new Node().Init(ComputeDummyKey(b));
+ if (!ListInsert(dummy, bucket, out current, null))
+ return current;
+
+ return SetBucket(b, dummy);
+ }
+
+ bool InsertInternal(uint key, TKey subKey, T data, Func<T> dataCreator, out Node current)
+ {
+ Node node = new Node().Init(ComputeRegularKey(key), subKey, data);
+
+ uint b = key % (uint)_size;
+ Node bucket;
+
+ if ((bucket = GetBucket(b)) == null)
+ bucket = InitializeBucket(b);
+
+ if (!ListInsert(node, bucket, out current, dataCreator))
+ return false;
+
+ int csize = _size;
+ if (Interlocked.Increment(ref _count) / csize > MaxLoad && (csize & 0x40000000) == 0)
+ Interlocked.CompareExchange(ref _size, 2 * csize, csize);
+
+ current = node;
+
+ return true;
+ }
+
+ bool ListDelete(Node startPoint, ulong key, TKey subKey, out T data)
+ {
+ Node rightNode = null, rightNodeNext = null, leftNode = null;
+ data = default(T);
+ Node markedNode = null;
+
+ do
+ {
+ rightNode = ListSearch(key, subKey, ref leftNode, startPoint);
+ if (rightNode == _tail || rightNode.Key != key || !_comparer.Equals(subKey, rightNode.SubKey))
+ return false;
+
+ data = rightNode.Data;
+ rightNodeNext = rightNode.Next;
+
+ if (!rightNodeNext.Marked)
+ {
+ if (markedNode == null)
+ markedNode = new Node();
+ markedNode.Init(rightNodeNext);
+
+ if (Interlocked.CompareExchange(ref rightNode.Next, markedNode, rightNodeNext) == rightNodeNext)
+ break;
+ }
+ } while (true);
+
+ if (Interlocked.CompareExchange(ref leftNode.Next, rightNodeNext, rightNode) != rightNode)
+ ListSearch(rightNode.Key, subKey, ref leftNode, startPoint);
+
+ return true;
+ }
+
+ bool ListFind(ulong key, TKey subKey, Node startPoint, out Node data)
+ {
+ Node rightNode = null, leftNode = null;
+ data = null;
+
+ rightNode = ListSearch(key, subKey, ref leftNode, startPoint);
+ data = rightNode;
+
+ return rightNode != _tail && rightNode.Key == key && _comparer.Equals(subKey, rightNode.SubKey);
+ }
+
+ bool ListInsert(Node newNode, Node startPoint, out Node current, Func<T> dataCreator)
+ {
+ ulong key = newNode.Key;
+ Node rightNode = null, leftNode = null;
+
+ do
+ {
+ rightNode = current = ListSearch(key, newNode.SubKey, ref leftNode, startPoint);
+ if (rightNode != _tail && rightNode.Key == key && _comparer.Equals(newNode.SubKey, rightNode.SubKey))
+ return false;
+
+ newNode.Next = rightNode;
+ if (dataCreator != null)
+ newNode.Data = dataCreator();
+ if (Interlocked.CompareExchange(ref leftNode.Next, newNode, rightNode) == rightNode)
+ return true;
+ } while (true);
+ }
+
+ Node ListSearch(ulong key, TKey subKey, ref Node left, Node h)
+ {
+ Node leftNodeNext = null, rightNode = null;
+
+ do
+ {
+ Node t = h;
+ Node tNext = t.Next;
+ do
+ {
+ if (!tNext.Marked)
+ {
+ left = t;
+ leftNodeNext = tNext;
+ }
+ t = tNext.Marked ? tNext.Next : tNext;
+ if (t == _tail)
+ break;
+
+ tNext = t.Next;
+ } while (tNext.Marked || t.Key < key || (tNext.Key == key && !_comparer.Equals(subKey, t.SubKey)));
+
+ rightNode = t;
+
+ if (leftNodeNext == rightNode)
+ {
+ if (rightNode != _tail && rightNode.Next.Marked)
+ continue;
+ return rightNode;
+ }
+
+ if (Interlocked.CompareExchange(ref left.Next, rightNode, leftNodeNext) == leftNodeNext)
+ {
+ if (rightNode != _tail && rightNode.Next.Marked)
+ continue;
+ return rightNode;
+ }
+ } while (true);
+ }
+
+ Node SetBucket(uint index, Node node)
+ {
+ try
+ {
+ _slim.EnterReadLock();
+ CheckSegment(index, true);
+
+ Interlocked.CompareExchange(ref _buckets[index], node, null);
+ return _buckets[index];
+ }
+ finally
+ {
+ _slim.ExitReadLock();
+ }
+ }
+
+ class Node
+ {
+ public T Data;
+ public ulong Key;
+ public bool Marked;
+ public Node Next;
+ public TKey SubKey;
+
+ public Node Init(ulong key, TKey subKey, T data)
+ {
+ Key = key;
+ SubKey = subKey;
+ Data = data;
+
+ Marked = false;
+ Next = null;
+
+ return this;
+ }
+
+ // Used to create dummy node
+ public Node Init(ulong key)
+ {
+ Key = key;
+ Data = default(T);
+
+ Next = null;
+ Marked = false;
+ SubKey = default(TKey);
+
+ return this;
+ }
+
+ // Used to create marked node
+ public Node Init(Node wrapped)
+ {
+ Marked = true;
+ Next = wrapped;
+
+ Key = 0;
+ Data = default(T);
+ SubKey = default(TKey);
+
+ return this;
+ }
+ }
+
+ struct SimpleRwLock
+ {
+ const int RwWait = 1;
+ const int RwWrite = 2;
+ const int RwRead = 4;
+
+ int _rwlock;
+
+ public void EnterReadLock()
+ {
+ var sw = new SpinWait();
+ do
+ {
+ while ((_rwlock & (RwWrite | RwWait)) > 0)
+ sw.SpinOnce();
+
+ if ((Interlocked.Add(ref _rwlock, RwRead) & (RwWait | RwWait)) == 0)
+ return;
+
+ Interlocked.Add(ref _rwlock, -RwRead);
+ } while (true);
+ }
+
+ public void ExitReadLock()
+ {
+ Interlocked.Add(ref _rwlock, -RwRead);
+ }
+
+ public void EnterWriteLock()
+ {
+ var sw = new SpinWait();
+ do
+ {
+ int state = _rwlock;
+ if (state < RwWrite)
+ {
+ if (Interlocked.CompareExchange(ref _rwlock, RwWrite, state) == state)
+ return;
+ state = _rwlock;
+ }
+ // We register our interest in taking the Write lock (if upgradeable it's already done)
+ while ((state & RwWait) == 0 && Interlocked.CompareExchange(ref _rwlock, state | RwWait, state) != state)
+ state = _rwlock;
+ // Before falling to sleep
+ while (_rwlock > RwWait)
+ sw.SpinOnce();
+ } while (true);
+ }
+
+ public void ExitWriteLock()
+ {
+ Interlocked.Add(ref _rwlock, -RwWrite);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/StackLayout.cs b/Xamarin.Forms.Core/StackLayout.cs
new file mode 100644
index 00000000..4dc7bfa3
--- /dev/null
+++ b/Xamarin.Forms.Core/StackLayout.cs
@@ -0,0 +1,460 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class StackLayout : Layout<View>
+ {
+ public static readonly BindableProperty OrientationProperty = BindableProperty.Create("Orientation", typeof(StackOrientation), typeof(StackLayout), StackOrientation.Vertical,
+ propertyChanged: (bindable, oldvalue, newvalue) => ((StackLayout)bindable).InvalidateLayout());
+
+ public static readonly BindableProperty SpacingProperty = BindableProperty.Create("Spacing", typeof(double), typeof(StackLayout), 6d,
+ propertyChanged: (bindable, oldvalue, newvalue) => ((StackLayout)bindable).InvalidateLayout());
+
+ LayoutInformation _layoutInformation = new LayoutInformation();
+
+ public StackOrientation Orientation
+ {
+ get { return (StackOrientation)GetValue(OrientationProperty); }
+ set { SetValue(OrientationProperty, value); }
+ }
+
+ public double Spacing
+ {
+ get { return (double)GetValue(SpacingProperty); }
+ set { SetValue(SpacingProperty, value); }
+ }
+
+ protected override void LayoutChildren(double x, double y, double width, double height)
+ {
+ if (!HasVisibileChildren())
+ {
+ return;
+ }
+
+ if (width == _layoutInformation.Constraint.Width && height == _layoutInformation.Constraint.Height)
+ {
+ StackOrientation orientation = Orientation;
+
+ AlignOffAxis(_layoutInformation, orientation, width, height);
+ ProcessExpanders(_layoutInformation, orientation, x, y, width, height);
+ }
+ else
+ {
+ CalculateLayout(_layoutInformation, x, y, width, height, true);
+ }
+
+ LayoutInformation layoutInformationCopy = _layoutInformation;
+
+ for (var i = 0; i < LogicalChildren.Count; i++)
+ {
+ var child = (View)LogicalChildren[i];
+ if (child.IsVisible)
+ LayoutChildIntoBoundingRegion(child, layoutInformationCopy.Plots[i], layoutInformationCopy.Requests[i]);
+ }
+ }
+
+ [Obsolete("Use OnMeasure")]
+ protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ if (!HasVisibileChildren())
+ {
+ return new SizeRequest();
+ }
+
+ // calculate with padding inset for X,Y so we can hopefully re-use this in the layout pass
+ Thickness padding = Padding;
+ CalculateLayout(_layoutInformation, padding.Left, padding.Top, widthConstraint, heightConstraint, false);
+ var result = new SizeRequest(_layoutInformation.Bounds.Size, _layoutInformation.MinimumSize);
+ return result;
+ }
+
+ internal override void ComputeConstraintForView(View view)
+ {
+ ComputeConstraintForView(view, false);
+ }
+
+ internal override void InvalidateMeasure(InvalidationTrigger trigger)
+ {
+ _layoutInformation = new LayoutInformation();
+ base.InvalidateMeasure(trigger);
+ }
+
+ void AlignOffAxis(LayoutInformation layout, StackOrientation orientation, double widthConstraint, double heightConstraint)
+ {
+ for (var i = 0; i < layout.Plots.Length; i++)
+ {
+ if (!((View)LogicalChildren[i]).IsVisible)
+ continue;
+ if (orientation == StackOrientation.Vertical)
+ {
+ layout.Plots[i].Width = widthConstraint;
+ }
+ else
+ {
+ layout.Plots[i].Height = heightConstraint;
+ }
+ }
+ }
+
+ void CalculateLayout(LayoutInformation layout, double x, double y, double widthConstraint, double heightConstraint, bool processExpanders)
+ {
+ layout.Constraint = new Size(widthConstraint, heightConstraint);
+ layout.Expanders = 0;
+ layout.CompressionSpace = 0;
+ layout.Plots = new Rectangle[Children.Count];
+ layout.Requests = new SizeRequest[Children.Count];
+
+ StackOrientation orientation = Orientation;
+
+ CalculateNaiveLayout(layout, orientation, x, y, widthConstraint, heightConstraint);
+ CompressNaiveLayout(layout, orientation, widthConstraint, heightConstraint);
+
+ if (processExpanders)
+ {
+ AlignOffAxis(layout, orientation, widthConstraint, heightConstraint);
+ ProcessExpanders(layout, orientation, x, y, widthConstraint, heightConstraint);
+ }
+ }
+
+ void CalculateNaiveLayout(LayoutInformation layout, StackOrientation orientation, double x, double y, double widthConstraint, double heightConstraint)
+ {
+ layout.CompressionSpace = 0;
+
+ double xOffset = x;
+ double yOffset = y;
+ double boundsWidth = 0;
+ double boundsHeight = 0;
+ double minimumWidth = 0;
+ double minimumHeight = 0;
+ double spacing = Spacing;
+ if (orientation == StackOrientation.Vertical)
+ {
+ View expander = null;
+ for (var i = 0; i < LogicalChildren.Count; i++)
+ {
+ var child = (View)LogicalChildren[i];
+ if (!child.IsVisible)
+ continue;
+
+ if (child.VerticalOptions.Expands)
+ {
+ layout.Expanders++;
+ if (expander != null)
+ {
+ // we have multiple expanders, make sure previous expanders are reset to not be fixed because they no logner are
+ ComputeConstraintForView(child, false);
+ }
+ expander = child;
+ }
+ SizeRequest request = child.Measure(widthConstraint, double.PositiveInfinity, MeasureFlags.IncludeMargins);
+
+ var bounds = new Rectangle(x, yOffset, request.Request.Width, request.Request.Height);
+ layout.Plots[i] = bounds;
+ layout.Requests[i] = request;
+ layout.CompressionSpace += Math.Max(0, request.Request.Height - request.Minimum.Height);
+ yOffset = bounds.Bottom + spacing;
+
+ boundsWidth = Math.Max(boundsWidth, request.Request.Width);
+ boundsHeight = bounds.Bottom - y;
+ minimumHeight += request.Minimum.Height + spacing;
+ minimumWidth = Math.Max(minimumWidth, request.Minimum.Width);
+ }
+ minimumHeight -= spacing;
+ if (expander != null)
+ ComputeConstraintForView(expander, layout.Expanders == 1); // warning : slightly obtuse, but we either need to setup the expander or clear the last one
+ }
+ else
+ {
+ View expander = null;
+ for (var i = 0; i < LogicalChildren.Count; i++)
+ {
+ var child = (View)LogicalChildren[i];
+ if (!child.IsVisible)
+ continue;
+
+ if (child.HorizontalOptions.Expands)
+ {
+ layout.Expanders++;
+ if (expander != null)
+ {
+ ComputeConstraintForView(child, false);
+ }
+ expander = child;
+ }
+ SizeRequest request = child.Measure(double.PositiveInfinity, heightConstraint, MeasureFlags.IncludeMargins);
+
+ var bounds = new Rectangle(xOffset, y, request.Request.Width, request.Request.Height);
+ layout.Plots[i] = bounds;
+ layout.Requests[i] = request;
+ layout.CompressionSpace += Math.Max(0, request.Request.Width - request.Minimum.Width);
+ xOffset = bounds.Right + spacing;
+
+ boundsWidth = bounds.Right - x;
+ boundsHeight = Math.Max(boundsHeight, request.Request.Height);
+ minimumWidth += request.Minimum.Width + spacing;
+ minimumHeight = Math.Max(minimumHeight, request.Minimum.Height);
+ }
+ minimumWidth -= spacing;
+ if (expander != null)
+ ComputeConstraintForView(expander, layout.Expanders == 1);
+ }
+
+ layout.Bounds = new Rectangle(x, y, boundsWidth, boundsHeight);
+ layout.MinimumSize = new Size(minimumWidth, minimumHeight);
+ }
+
+ void CompressHorizontalLayout(LayoutInformation layout, double widthConstraint, double heightConstraint)
+ {
+ double xOffset = 0;
+
+ if (widthConstraint >= layout.Bounds.Width)
+ {
+ // no need to compress
+ return;
+ }
+
+ double requiredCompression = layout.Bounds.Width - widthConstraint;
+ double compressionSpace = layout.CompressionSpace;
+ double compressionPressure = (requiredCompression / layout.CompressionSpace).Clamp(0, 1);
+
+ for (var i = 0; i < layout.Plots.Length; i++)
+ {
+ var child = (View)LogicalChildren[i];
+ if (!child.IsVisible)
+ continue;
+
+ Size minimum = layout.Requests[i].Minimum;
+
+ layout.Plots[i].X -= xOffset;
+
+ Rectangle plot = layout.Plots[i];
+ double availableSpace = plot.Width - minimum.Width;
+ if (availableSpace <= 0)
+ continue;
+
+ compressionSpace -= availableSpace;
+
+ double compression = availableSpace * compressionPressure;
+ xOffset += compression;
+
+ double newWidth = plot.Width - compression;
+ SizeRequest newRequest = child.Measure(newWidth, heightConstraint, MeasureFlags.IncludeMargins);
+
+ layout.Requests[i] = newRequest;
+
+ plot.Height = newRequest.Request.Height;
+
+ if (newRequest.Request.Width < newWidth)
+ {
+ double delta = newWidth - newRequest.Request.Width;
+ newWidth = newRequest.Request.Width;
+ xOffset += delta;
+ requiredCompression = requiredCompression - xOffset;
+ compressionPressure = (requiredCompression / compressionSpace).Clamp(0, 1);
+ }
+ plot.Width = newWidth;
+
+ layout.Bounds.Height = Math.Max(layout.Bounds.Height, plot.Height);
+
+ layout.Plots[i] = plot;
+ }
+ }
+
+ void CompressNaiveLayout(LayoutInformation layout, StackOrientation orientation, double widthConstraint, double heightConstraint)
+ {
+ if (layout.CompressionSpace <= 0)
+ return;
+
+ if (orientation == StackOrientation.Vertical)
+ {
+ CompressVerticalLayout(layout, widthConstraint, heightConstraint);
+ }
+ else
+ {
+ CompressHorizontalLayout(layout, widthConstraint, heightConstraint);
+ }
+ }
+
+ void CompressVerticalLayout(LayoutInformation layout, double widthConstraint, double heightConstraint)
+ {
+ double yOffset = 0;
+
+ if (heightConstraint >= layout.Bounds.Height)
+ {
+ // no need to compress
+ return;
+ }
+
+ double requiredCompression = layout.Bounds.Height - heightConstraint;
+ double compressionSpace = layout.CompressionSpace;
+ double compressionPressure = (requiredCompression / layout.CompressionSpace).Clamp(0, 1);
+
+ for (var i = 0; i < layout.Plots.Length; i++)
+ {
+ var child = (View)LogicalChildren[i];
+ if (!child.IsVisible)
+ continue;
+
+ Size minimum = layout.Requests[i].Minimum;
+
+ layout.Plots[i].Y -= yOffset;
+
+ Rectangle plot = layout.Plots[i];
+ double availableSpace = plot.Height - minimum.Height;
+ if (availableSpace <= 0)
+ continue;
+
+ compressionSpace -= availableSpace;
+
+ double compression = availableSpace * compressionPressure;
+ yOffset += compression;
+
+ double newHeight = plot.Height - compression;
+ SizeRequest newRequest = child.Measure(widthConstraint, newHeight, MeasureFlags.IncludeMargins);
+
+ layout.Requests[i] = newRequest;
+
+ plot.Width = newRequest.Request.Width;
+
+ if (newRequest.Request.Height < newHeight)
+ {
+ double delta = newHeight - newRequest.Request.Height;
+ newHeight = newRequest.Request.Height;
+ yOffset += delta;
+ requiredCompression = requiredCompression - yOffset;
+ compressionPressure = (requiredCompression / compressionSpace).Clamp(0, 1);
+ }
+ plot.Height = newHeight;
+
+ layout.Bounds.Width = Math.Max(layout.Bounds.Width, plot.Width);
+
+ layout.Plots[i] = plot;
+ }
+ }
+
+ void ComputeConstraintForView(View view, bool isOnlyExpander)
+ {
+ if (Orientation == StackOrientation.Horizontal)
+ {
+ if ((Constraint & LayoutConstraint.VerticallyFixed) != 0 && view.VerticalOptions.Alignment == LayoutAlignment.Fill)
+ {
+ if (isOnlyExpander && view.HorizontalOptions.Alignment == LayoutAlignment.Fill && Constraint == LayoutConstraint.Fixed)
+ {
+ view.ComputedConstraint = LayoutConstraint.Fixed;
+ }
+ else
+ {
+ view.ComputedConstraint = LayoutConstraint.VerticallyFixed;
+ }
+ }
+ else
+ {
+ view.ComputedConstraint = LayoutConstraint.None;
+ }
+ }
+ else
+ {
+ if ((Constraint & LayoutConstraint.HorizontallyFixed) != 0 && view.HorizontalOptions.Alignment == LayoutAlignment.Fill)
+ {
+ if (isOnlyExpander && view.VerticalOptions.Alignment == LayoutAlignment.Fill && Constraint == LayoutConstraint.Fixed)
+ {
+ view.ComputedConstraint = LayoutConstraint.Fixed;
+ }
+ else
+ {
+ view.ComputedConstraint = LayoutConstraint.HorizontallyFixed;
+ }
+ }
+ else
+ {
+ view.ComputedConstraint = LayoutConstraint.None;
+ }
+ }
+ }
+
+ bool HasVisibileChildren()
+ {
+ for (var index = 0; index < InternalChildren.Count; index++)
+ {
+ var child = (VisualElement)InternalChildren[index];
+ if (child.IsVisible)
+ return true;
+ }
+ return false;
+ }
+
+ void ProcessExpanders(LayoutInformation layout, StackOrientation orientation, double x, double y, double widthConstraint, double heightConstraint)
+ {
+ if (layout.Expanders <= 0)
+ return;
+
+ if (orientation == StackOrientation.Vertical)
+ {
+ double extraSpace = heightConstraint - layout.Bounds.Height;
+ if (extraSpace <= 0)
+ return;
+
+ double spacePerExpander = extraSpace / layout.Expanders;
+ double yOffset = 0;
+
+ for (var i = 0; i < LogicalChildren.Count; i++)
+ {
+ var child = (View)LogicalChildren[i];
+ if (!child.IsVisible)
+ continue;
+ Rectangle plot = layout.Plots[i];
+ plot.Y += yOffset;
+
+ if (child.VerticalOptions.Expands)
+ {
+ plot.Height += spacePerExpander;
+ yOffset += spacePerExpander;
+ }
+
+ layout.Plots[i] = plot;
+ }
+
+ layout.Bounds.Height = heightConstraint;
+ }
+ else
+ {
+ double extraSpace = widthConstraint - layout.Bounds.Width;
+ if (extraSpace <= 0)
+ return;
+
+ double spacePerExpander = extraSpace / layout.Expanders;
+ double xOffset = 0;
+
+ for (var i = 0; i < LogicalChildren.Count; i++)
+ {
+ var child = (View)LogicalChildren[i];
+ if (!child.IsVisible)
+ continue;
+ Rectangle plot = layout.Plots[i];
+ plot.X += xOffset;
+
+ if (child.HorizontalOptions.Expands)
+ {
+ plot.Width += spacePerExpander;
+ xOffset += spacePerExpander;
+ }
+
+ layout.Plots[i] = plot;
+ }
+
+ layout.Bounds.Width = widthConstraint;
+ }
+ }
+
+ class LayoutInformation
+ {
+ public Rectangle Bounds;
+ public double CompressionSpace;
+ public Size Constraint;
+ public int Expanders;
+ public Size MinimumSize;
+ public Rectangle[] Plots;
+ public SizeRequest[] Requests;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/StackOrientation.cs b/Xamarin.Forms.Core/StackOrientation.cs
new file mode 100644
index 00000000..4ab00fd2
--- /dev/null
+++ b/Xamarin.Forms.Core/StackOrientation.cs
@@ -0,0 +1,8 @@
+namespace Xamarin.Forms
+{
+ public enum StackOrientation
+ {
+ Vertical,
+ Horizontal
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Stepper.cs b/Xamarin.Forms.Core/Stepper.cs
new file mode 100644
index 00000000..2a3de841
--- /dev/null
+++ b/Xamarin.Forms.Core/Stepper.cs
@@ -0,0 +1,94 @@
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_StepperRenderer))]
+ public class Stepper : View
+ {
+ public static readonly BindableProperty MaximumProperty = BindableProperty.Create("Maximum", typeof(double), typeof(Stepper), 100.0, validateValue: (bindable, value) =>
+ {
+ var stepper = (Stepper)bindable;
+ return (double)value > stepper.Minimum;
+ }, coerceValue: (bindable, value) =>
+ {
+ var stepper = (Stepper)bindable;
+ stepper.Value = stepper.Value.Clamp(stepper.Minimum, (double)value);
+ return value;
+ });
+
+ public static readonly BindableProperty MinimumProperty = BindableProperty.Create("Minimum", typeof(double), typeof(Stepper), 0.0, validateValue: (bindable, value) =>
+ {
+ var stepper = (Stepper)bindable;
+ return (double)value < stepper.Maximum;
+ }, coerceValue: (bindable, value) =>
+ {
+ var stepper = (Stepper)bindable;
+ stepper.Value = stepper.Value.Clamp((double)value, stepper.Maximum);
+ return value;
+ });
+
+ public static readonly BindableProperty ValueProperty = BindableProperty.Create("Value", typeof(double), typeof(Stepper), 0.0, BindingMode.TwoWay, coerceValue: (bindable, value) =>
+ {
+ var stepper = (Stepper)bindable;
+ return ((double)value).Clamp(stepper.Minimum, stepper.Maximum);
+ }, propertyChanged: (bindable, oldValue, newValue) =>
+ {
+ var stepper = (Stepper)bindable;
+ EventHandler<ValueChangedEventArgs> eh = stepper.ValueChanged;
+ if (eh != null)
+ eh(stepper, new ValueChangedEventArgs((double)oldValue, (double)newValue));
+ });
+
+ public static readonly BindableProperty IncrementProperty = BindableProperty.Create("Increment", typeof(double), typeof(Stepper), 1.0);
+
+ public Stepper()
+ {
+ }
+
+ public Stepper(double min, double max, double val, double increment)
+ {
+ if (min >= max)
+ throw new ArgumentOutOfRangeException("min");
+ if (max > Minimum)
+ {
+ Maximum = max;
+ Minimum = min;
+ }
+ else
+ {
+ Minimum = min;
+ Maximum = max;
+ }
+
+ Value = val.Clamp(min, max);
+ Increment = increment;
+ }
+
+ public double Increment
+ {
+ get { return (double)GetValue(IncrementProperty); }
+ set { SetValue(IncrementProperty, value); }
+ }
+
+ public double Maximum
+ {
+ get { return (double)GetValue(MaximumProperty); }
+ set { SetValue(MaximumProperty, value); }
+ }
+
+ public double Minimum
+ {
+ get { return (double)GetValue(MinimumProperty); }
+ set { SetValue(MinimumProperty, value); }
+ }
+
+ public double Value
+ {
+ get { return (double)GetValue(ValueProperty); }
+ set { SetValue(ValueProperty, value); }
+ }
+
+ public event EventHandler<ValueChangedEventArgs> ValueChanged;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/StreamImageSource.cs b/Xamarin.Forms.Core/StreamImageSource.cs
new file mode 100644
index 00000000..ae59ea3c
--- /dev/null
+++ b/Xamarin.Forms.Core/StreamImageSource.cs
@@ -0,0 +1,47 @@
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ public class StreamImageSource : ImageSource
+ {
+ public static readonly BindableProperty StreamProperty = BindableProperty.Create("Stream", typeof(Func<CancellationToken, Task<Stream>>), typeof(StreamImageSource),
+ default(Func<CancellationToken, Task<Stream>>));
+
+ public virtual Func<CancellationToken, Task<Stream>> Stream
+ {
+ get { return (Func<CancellationToken, Task<Stream>>)GetValue(StreamProperty); }
+ set { SetValue(StreamProperty, value); }
+ }
+
+ protected override void OnPropertyChanged(string propertyName)
+ {
+ if (propertyName == StreamProperty.PropertyName)
+ OnSourceChanged();
+ base.OnPropertyChanged(propertyName);
+ }
+
+ internal async Task<Stream> GetStreamAsync(CancellationToken userToken = default(CancellationToken))
+ {
+ if (Stream == null)
+ return null;
+
+ OnLoadingStarted();
+ userToken.Register(CancellationTokenSource.Cancel);
+ Stream stream = null;
+ try
+ {
+ stream = await Stream(CancellationTokenSource.Token);
+ OnLoadingCompleted(false);
+ }
+ catch (OperationCanceledException)
+ {
+ OnLoadingCompleted(true);
+ throw;
+ }
+ return stream;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/StreamWrapper.cs b/Xamarin.Forms.Core/StreamWrapper.cs
new file mode 100644
index 00000000..5d4e2cae
--- /dev/null
+++ b/Xamarin.Forms.Core/StreamWrapper.cs
@@ -0,0 +1,81 @@
+using System;
+using System.IO;
+
+namespace Xamarin.Forms
+{
+ internal class StreamWrapper : Stream
+ {
+ readonly Stream _wrapped;
+
+ public StreamWrapper(Stream wrapped)
+ {
+ if (wrapped == null)
+ throw new ArgumentNullException("wrapped");
+
+ _wrapped = wrapped;
+ }
+
+ public override bool CanRead
+ {
+ get { return _wrapped.CanRead; }
+ }
+
+ public override bool CanSeek
+ {
+ get { return _wrapped.CanSeek; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return _wrapped.CanWrite; }
+ }
+
+ public override long Length
+ {
+ get { return _wrapped.Length; }
+ }
+
+ public override long Position
+ {
+ get { return _wrapped.Position; }
+ set { _wrapped.Position = value; }
+ }
+
+ public event EventHandler Disposed;
+
+ public override void Flush()
+ {
+ _wrapped.Flush();
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ return _wrapped.Read(buffer, offset, count);
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ return _wrapped.Seek(offset, origin);
+ }
+
+ public override void SetLength(long value)
+ {
+ _wrapped.SetLength(value);
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ _wrapped.Write(buffer, offset, count);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ _wrapped.Dispose();
+ EventHandler eh = Disposed;
+ if (eh != null)
+ eh(this, EventArgs.Empty);
+
+ base.Dispose(disposing);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Style.cs b/Xamarin.Forms.Core/Style.cs
new file mode 100644
index 00000000..8d27f010
--- /dev/null
+++ b/Xamarin.Forms.Core/Style.cs
@@ -0,0 +1,184 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("Setters")]
+ public sealed class Style : IStyle
+ {
+ internal const string StyleClassPrefix = "Xamarin.Forms.StyleClass.";
+
+ readonly BindableProperty _basedOnResourceProperty = BindableProperty.CreateAttached("BasedOnResource", typeof(Style), typeof(Style), default(Style),
+ propertyChanged: OnBasedOnResourceChanged);
+
+ readonly List<WeakReference<BindableObject>> _targets = new List<WeakReference<BindableObject>>(4);
+
+ Style _basedOnStyle;
+
+ string _baseResourceKey;
+
+ IList<Behavior> _behaviors;
+
+ IList<TriggerBase> _triggers;
+
+ public Style([TypeConverter(typeof(TypeTypeConverter))] [Parameter("TargetType")] Type targetType)
+ {
+ if (targetType == null)
+ throw new ArgumentNullException("targetType");
+
+ TargetType = targetType;
+ Setters = new List<Setter>();
+ }
+
+ public bool ApplyToDerivedTypes { get; set; }
+
+ public Style BasedOn
+ {
+ get { return _basedOnStyle; }
+ set
+ {
+ if (_basedOnStyle == value)
+ return;
+ if (!ValidateBasedOn(value))
+ throw new ArgumentException("BasedOn.TargetType is not compatible with TargetType");
+ Style oldValue = _basedOnStyle;
+ _basedOnStyle = value;
+ BasedOnChanged(oldValue, value);
+ if (value != null)
+ BaseResourceKey = null;
+ }
+ }
+
+ public string BaseResourceKey
+ {
+ get { return _baseResourceKey; }
+ set
+ {
+ if (_baseResourceKey == value)
+ return;
+ _baseResourceKey = value;
+ //update all DynamicResources
+ foreach (WeakReference<BindableObject> bindableWr in _targets)
+ {
+ BindableObject target;
+ if (!bindableWr.TryGetTarget(out target))
+ continue;
+ target.RemoveDynamicResource(_basedOnResourceProperty);
+ if (value != null)
+ target.SetDynamicResource(_basedOnResourceProperty, value);
+ }
+ if (value != null)
+ BasedOn = null;
+ }
+ }
+
+ public IList<Behavior> Behaviors
+ {
+ get { return _behaviors ?? (_behaviors = new AttachedCollection<Behavior>()); }
+ }
+
+ public bool CanCascade { get; set; }
+
+ public string Class { get; set; }
+
+ public IList<Setter> Setters { get; }
+
+ public IList<TriggerBase> Triggers
+ {
+ get { return _triggers ?? (_triggers = new AttachedCollection<TriggerBase>()); }
+ }
+
+ void IStyle.Apply(BindableObject bindable)
+ {
+ _targets.Add(new WeakReference<BindableObject>(bindable));
+ if (BaseResourceKey != null)
+ bindable.SetDynamicResource(_basedOnResourceProperty, BaseResourceKey);
+ ApplyCore(bindable, BasedOn ?? GetBasedOnResource(bindable));
+ }
+
+ public Type TargetType { get; }
+
+ void IStyle.UnApply(BindableObject bindable)
+ {
+ UnApplyCore(bindable, BasedOn ?? GetBasedOnResource(bindable));
+ bindable.RemoveDynamicResource(_basedOnResourceProperty);
+ _targets.RemoveAll(wr =>
+ {
+ BindableObject target;
+ return wr.TryGetTarget(out target) && target == bindable;
+ });
+ }
+
+ internal bool CanBeAppliedTo(Type targetType)
+ {
+ if (TargetType == targetType)
+ return true;
+ if (!ApplyToDerivedTypes)
+ return false;
+ do
+ {
+ targetType = targetType.GetTypeInfo().BaseType;
+ if (TargetType == targetType)
+ return true;
+ } while (targetType != typeof(Element));
+ return false;
+ }
+
+ void ApplyCore(BindableObject bindable, Style basedOn)
+ {
+ if (basedOn != null)
+ ((IStyle)basedOn).Apply(bindable);
+
+ foreach (Setter setter in Setters)
+ setter.Apply(bindable, true);
+ ((AttachedCollection<Behavior>)Behaviors).AttachTo(bindable);
+ ((AttachedCollection<TriggerBase>)Triggers).AttachTo(bindable);
+ }
+
+ void BasedOnChanged(Style oldValue, Style newValue)
+ {
+ foreach (WeakReference<BindableObject> bindableRef in _targets)
+ {
+ BindableObject bindable;
+ if (!bindableRef.TryGetTarget(out bindable))
+ continue;
+
+ UnApplyCore(bindable, oldValue);
+ ApplyCore(bindable, newValue);
+ }
+ }
+
+ Style GetBasedOnResource(BindableObject bindable)
+ {
+ return (Style)bindable.GetValue(_basedOnResourceProperty);
+ }
+
+ static void OnBasedOnResourceChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ Style style = (bindable as VisualElement).Style;
+ if (style == null)
+ return;
+ style.UnApplyCore(bindable, (Style)oldValue);
+ style.ApplyCore(bindable, (Style)newValue);
+ }
+
+ void UnApplyCore(BindableObject bindable, Style basedOn)
+ {
+ ((AttachedCollection<TriggerBase>)Triggers).DetachFrom(bindable);
+ ((AttachedCollection<Behavior>)Behaviors).DetachFrom(bindable);
+ foreach (Setter setter in Setters)
+ setter.UnApply(bindable, true);
+
+ if (basedOn != null)
+ ((IStyle)basedOn).UnApply(bindable);
+ }
+
+ bool ValidateBasedOn(Style value)
+ {
+ if (value == null)
+ return true;
+ return value.TargetType.IsAssignableFrom(TargetType);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Switch.cs b/Xamarin.Forms.Core/Switch.cs
new file mode 100644
index 00000000..394e050a
--- /dev/null
+++ b/Xamarin.Forms.Core/Switch.cs
@@ -0,0 +1,24 @@
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_SwitchRenderer))]
+ public class Switch : View
+ {
+ public static readonly BindableProperty IsToggledProperty = BindableProperty.Create("IsToggled", typeof(bool), typeof(Switch), false, propertyChanged: (bindable, oldValue, newValue) =>
+ {
+ EventHandler<ToggledEventArgs> eh = ((Switch)bindable).Toggled;
+ if (eh != null)
+ eh(bindable, new ToggledEventArgs((bool)newValue));
+ }, defaultBindingMode: BindingMode.TwoWay);
+
+ public bool IsToggled
+ {
+ get { return (bool)GetValue(IsToggledProperty); }
+ set { SetValue(IsToggledProperty, value); }
+ }
+
+ public event EventHandler<ToggledEventArgs> Toggled;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/SynchronizedList.cs b/Xamarin.Forms.Core/SynchronizedList.cs
new file mode 100644
index 00000000..edc6f575
--- /dev/null
+++ b/Xamarin.Forms.Core/SynchronizedList.cs
@@ -0,0 +1,130 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+
+namespace Xamarin.Forms
+{
+ internal class SynchronizedList<T> : IList<T>, IReadOnlyList<T>
+ {
+ readonly List<T> _list = new List<T>();
+ ReadOnlyCollection<T> _snapshot;
+
+ public void Add(T item)
+ {
+ lock(_list)
+ {
+ _list.Add(item);
+ _snapshot = null;
+ }
+ }
+
+ public void Clear()
+ {
+ lock(_list)
+ {
+ _list.Clear();
+ _snapshot = null;
+ }
+ }
+
+ public bool Contains(T item)
+ {
+ lock(_list)
+ return _list.Contains(item);
+ }
+
+ public void CopyTo(T[] array, int arrayIndex)
+ {
+ lock(_list)
+ _list.CopyTo(array, arrayIndex);
+ }
+
+ public int Count
+ {
+ get { return _list.Count; }
+ }
+
+ bool ICollection<T>.IsReadOnly
+ {
+ get { return false; }
+ }
+
+ public bool Remove(T item)
+ {
+ lock(_list)
+ {
+ if (_list.Remove(item))
+ {
+ _snapshot = null;
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ ReadOnlyCollection<T> snap = _snapshot;
+ if (snap == null)
+ {
+ lock(_list)
+ _snapshot = snap = new ReadOnlyCollection<T>(_list.ToList());
+ }
+
+ return snap.GetEnumerator();
+ }
+
+ public int IndexOf(T item)
+ {
+ lock(_list)
+ return _list.IndexOf(item);
+ }
+
+ public void Insert(int index, T item)
+ {
+ lock(_list)
+ {
+ _list.Insert(index, item);
+ _snapshot = null;
+ }
+ }
+
+ public T this[int index]
+ {
+ get
+ {
+ ReadOnlyCollection<T> snap = _snapshot;
+ if (snap != null)
+ return snap[index];
+
+ lock(_list)
+ return _list[index];
+ }
+
+ set
+ {
+ lock(_list)
+ {
+ _list[index] = value;
+ _snapshot = null;
+ }
+ }
+ }
+
+ public void RemoveAt(int index)
+ {
+ lock(_list)
+ {
+ _list.RemoveAt(index);
+ _snapshot = null;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TabbedPage.cs b/Xamarin.Forms.Core/TabbedPage.cs
new file mode 100644
index 00000000..53b736cb
--- /dev/null
+++ b/Xamarin.Forms.Core/TabbedPage.cs
@@ -0,0 +1,17 @@
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_TabbedPageRenderer))]
+ public class TabbedPage : MultiPage<Page>
+ {
+ protected override Page CreateDefault(object item)
+ {
+ var page = new Page();
+ if (item != null)
+ page.Title = item.ToString();
+
+ return page;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TableIntent.cs b/Xamarin.Forms.Core/TableIntent.cs
new file mode 100644
index 00000000..7d4737ca
--- /dev/null
+++ b/Xamarin.Forms.Core/TableIntent.cs
@@ -0,0 +1,10 @@
+namespace Xamarin.Forms
+{
+ public enum TableIntent
+ {
+ Menu,
+ Settings,
+ Form,
+ Data
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TableModel.cs b/Xamarin.Forms.Core/TableModel.cs
new file mode 100644
index 00000000..866b7a69
--- /dev/null
+++ b/Xamarin.Forms.Core/TableModel.cs
@@ -0,0 +1,76 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ internal abstract class TableModel
+ {
+ public virtual Cell GetCell(int section, int row)
+ {
+ object item = GetItem(section, row);
+ var cell = item as Cell;
+ if (cell != null)
+ return cell;
+
+ return new TextCell { Text = item.ToString() };
+ }
+
+ public virtual Cell GetHeaderCell(int section)
+ {
+ return null;
+ }
+
+ public abstract object GetItem(int section, int row);
+
+ public abstract int GetRowCount(int section);
+
+ public abstract int GetSectionCount();
+
+ public virtual string[] GetSectionIndexTitles()
+ {
+ return null;
+ }
+
+ public virtual string GetSectionTitle(int section)
+ {
+ return null;
+ }
+
+ public event EventHandler<EventArg<object>> ItemLongPressed;
+
+ public event EventHandler<EventArg<object>> ItemSelected;
+
+ public void RowLongPressed(int section, int row)
+ {
+ RowLongPressed(GetItem(section, row));
+ }
+
+ public void RowLongPressed(object item)
+ {
+ if (ItemLongPressed != null)
+ ItemLongPressed(this, new EventArg<object>(item));
+
+ OnRowLongPressed(item);
+ }
+
+ public void RowSelected(int section, int row)
+ {
+ RowSelected(GetItem(section, row));
+ }
+
+ public void RowSelected(object item)
+ {
+ if (ItemSelected != null)
+ ItemSelected(this, new EventArg<object>(item));
+
+ OnRowSelected(item);
+ }
+
+ protected virtual void OnRowLongPressed(object item)
+ {
+ }
+
+ protected virtual void OnRowSelected(object item)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TableRoot.cs b/Xamarin.Forms.Core/TableRoot.cs
new file mode 100644
index 00000000..60ef6d95
--- /dev/null
+++ b/Xamarin.Forms.Core/TableRoot.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+
+namespace Xamarin.Forms
+{
+ public sealed class TableRoot : TableSectionBase<TableSection>
+ {
+ public TableRoot()
+ {
+ SetupEvents();
+ }
+
+ public TableRoot(string title) : base(title)
+ {
+ SetupEvents();
+ }
+
+ internal event EventHandler<ChildCollectionChangedEventArgs> SectionCollectionChanged;
+
+ void ChildCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
+ {
+ EventHandler<ChildCollectionChangedEventArgs> handler = SectionCollectionChanged;
+ if (handler != null)
+ handler(this, new ChildCollectionChangedEventArgs(notifyCollectionChangedEventArgs));
+ }
+
+ void ChildPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
+ {
+ if (propertyChangedEventArgs.PropertyName == TitleProperty.PropertyName)
+ {
+ OnPropertyChanged(TitleProperty.PropertyName);
+ }
+ }
+
+ void SetupEvents()
+ {
+ CollectionChanged += (sender, args) =>
+ {
+ if (args.NewItems != null)
+ {
+ foreach (TableSection section in args.NewItems)
+ {
+ section.CollectionChanged += ChildCollectionChanged;
+ section.PropertyChanged += ChildPropertyChanged;
+ }
+ }
+
+ if (args.OldItems != null)
+ {
+ foreach (TableSection section in args.OldItems)
+ {
+ section.CollectionChanged -= ChildCollectionChanged;
+ section.PropertyChanged -= ChildPropertyChanged;
+ }
+ }
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TableSection.cs b/Xamarin.Forms.Core/TableSection.cs
new file mode 100644
index 00000000..9ae7caf5
--- /dev/null
+++ b/Xamarin.Forms.Core/TableSection.cs
@@ -0,0 +1,137 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+
+namespace Xamarin.Forms
+{
+ public abstract class TableSectionBase<T> : TableSectionBase, IList<T>, INotifyCollectionChanged where T : BindableObject
+ {
+ readonly ObservableCollection<T> _children = new ObservableCollection<T>();
+
+ /// <summary>
+ /// Constructs a Section without an empty header.
+ /// </summary>
+ protected TableSectionBase()
+ {
+ _children.CollectionChanged += OnChildrenChanged;
+ }
+
+ /// <summary>
+ /// Constructs a Section with the specified header.
+ /// </summary>
+ protected TableSectionBase(string title) : base(title)
+ {
+ _children.CollectionChanged += OnChildrenChanged;
+ }
+
+ public void Add(T item)
+ {
+ _children.Add(item);
+ }
+
+ public void Clear()
+ {
+ _children.Clear();
+ }
+
+ public bool Contains(T item)
+ {
+ return _children.Contains(item);
+ }
+
+ public void CopyTo(T[] array, int arrayIndex)
+ {
+ _children.CopyTo(array, arrayIndex);
+ }
+
+ public int Count
+ {
+ get { return _children.Count; }
+ }
+
+ bool ICollection<T>.IsReadOnly
+ {
+ get { return false; }
+ }
+
+ public bool Remove(T item)
+ {
+ return _children.Remove(item);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ return _children.GetEnumerator();
+ }
+
+ public int IndexOf(T item)
+ {
+ return _children.IndexOf(item);
+ }
+
+ public void Insert(int index, T item)
+ {
+ _children.Insert(index, item);
+ }
+
+ public T this[int index]
+ {
+ get { return _children[index]; }
+ set { _children[index] = value; }
+ }
+
+ public void RemoveAt(int index)
+ {
+ _children.RemoveAt(index);
+ }
+
+ public event NotifyCollectionChangedEventHandler CollectionChanged
+ {
+ add { _children.CollectionChanged += value; }
+ remove { _children.CollectionChanged -= value; }
+ }
+
+ public void Add(IEnumerable<T> items)
+ {
+ items.ForEach(_children.Add);
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ base.OnBindingContextChanged();
+
+ object bc = BindingContext;
+ foreach (T child in _children)
+ SetInheritedBindingContext(child, bc);
+ }
+
+ void OnChildrenChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
+ {
+ // We need to hook up the binding context for new items.
+ if (notifyCollectionChangedEventArgs.NewItems == null)
+ return;
+ object bc = BindingContext;
+ foreach (BindableObject item in notifyCollectionChangedEventArgs.NewItems)
+ {
+ SetInheritedBindingContext(item, bc);
+ }
+ }
+ }
+
+ public sealed class TableSection : TableSectionBase<Cell>
+ {
+ public TableSection()
+ {
+ }
+
+ public TableSection(string title) : base(title)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TableSectionBase.cs b/Xamarin.Forms.Core/TableSectionBase.cs
new file mode 100644
index 00000000..9cfa5351
--- /dev/null
+++ b/Xamarin.Forms.Core/TableSectionBase.cs
@@ -0,0 +1,33 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public abstract class TableSectionBase : BindableObject
+ {
+ public static readonly BindableProperty TitleProperty = BindableProperty.Create("Title", typeof(string), typeof(TableSectionBase), null);
+
+ /// <summary>
+ /// Constructs a Section without an empty header.
+ /// </summary>
+ protected TableSectionBase()
+ {
+ }
+
+ /// <summary>
+ /// Constructs a Section with the specified header.
+ /// </summary>
+ protected TableSectionBase(string title)
+ {
+ if (title == null)
+ throw new ArgumentNullException("title");
+
+ Title = title;
+ }
+
+ public string Title
+ {
+ get { return (string)GetValue(TitleProperty); }
+ set { SetValue(TitleProperty, value); }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TableView.cs b/Xamarin.Forms.Core/TableView.cs
new file mode 100644
index 00000000..a88999b7
--- /dev/null
+++ b/Xamarin.Forms.Core/TableView.cs
@@ -0,0 +1,228 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [ContentProperty("Root")]
+ [RenderWith(typeof(_TableViewRenderer))]
+ public class TableView : View
+ {
+ public static readonly BindableProperty RowHeightProperty = BindableProperty.Create("RowHeight", typeof(int), typeof(TableView), -1);
+
+ public static readonly BindableProperty HasUnevenRowsProperty = BindableProperty.Create("HasUnevenRows", typeof(bool), typeof(TableView), false);
+
+ readonly TableSectionModel _tableModel;
+
+ TableIntent _intent = TableIntent.Data;
+
+ TableModel _model;
+
+ public TableView() : this(null)
+ {
+ }
+
+ public TableView(TableRoot root)
+ {
+ VerticalOptions = HorizontalOptions = LayoutOptions.FillAndExpand;
+ Model = _tableModel = new TableSectionModel(this, root);
+ }
+
+ public bool HasUnevenRows
+ {
+ get { return (bool)GetValue(HasUnevenRowsProperty); }
+ set { SetValue(HasUnevenRowsProperty, value); }
+ }
+
+ public TableIntent Intent
+ {
+ get { return _intent; }
+ set
+ {
+ if (_intent == value)
+ return;
+
+ OnPropertyChanging();
+ _intent = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public TableRoot Root
+ {
+ get { return _tableModel.Root; }
+ set
+ {
+ if (_tableModel.Root != null)
+ {
+ _tableModel.Root.SectionCollectionChanged -= OnSectionCollectionChanged;
+ _tableModel.Root.PropertyChanged -= OnTableModelRootPropertyChanged;
+ }
+ _tableModel.Root = value ?? new TableRoot();
+ SetInheritedBindingContext(_tableModel.Root, BindingContext);
+
+ Root.SelectMany(r => r).ForEach(cell => cell.Parent = this);
+ _tableModel.Root.SectionCollectionChanged += OnSectionCollectionChanged;
+ _tableModel.Root.PropertyChanged += OnTableModelRootPropertyChanged;
+ OnModelChanged();
+ }
+ }
+
+ public int RowHeight
+ {
+ get { return (int)GetValue(RowHeightProperty); }
+ set { SetValue(RowHeightProperty, value); }
+ }
+
+ internal TableModel Model
+ {
+ get { return _model; }
+ set
+ {
+ _model = value;
+ OnModelChanged();
+ }
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ base.OnBindingContextChanged();
+ if (Root != null)
+ SetInheritedBindingContext(Root, BindingContext);
+ }
+
+ protected virtual void OnModelChanged()
+ {
+ foreach (Cell cell in Root.SelectMany(r => r))
+ cell.Parent = this;
+
+ if (ModelChanged != null)
+ ModelChanged(this, EventArgs.Empty);
+ }
+
+ [Obsolete("Use OnMeasure")]
+ protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ var minimumSize = new Size(40, 40);
+ double width = Math.Min(Device.Info.ScaledScreenSize.Width, Device.Info.ScaledScreenSize.Height);
+ var request = new Size(width, Math.Max(Device.Info.ScaledScreenSize.Width, Device.Info.ScaledScreenSize.Height));
+
+ return new SizeRequest(request, minimumSize);
+ }
+
+ internal event EventHandler ModelChanged;
+
+ void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ OnModelChanged();
+ }
+
+ void OnSectionCollectionChanged(object sender, ChildCollectionChangedEventArgs childCollectionChangedEventArgs)
+ {
+ if (childCollectionChangedEventArgs.Args.NewItems != null)
+ childCollectionChangedEventArgs.Args.NewItems.Cast<Cell>().ForEach(cell => cell.Parent = this);
+ OnModelChanged();
+ }
+
+ void OnTableModelRootPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == TableSectionBase.TitleProperty.PropertyName)
+ OnModelChanged();
+ }
+
+ internal class TableSectionModel : TableModel
+ {
+ static readonly BindableProperty PathProperty = BindableProperty.Create("Path", typeof(Tuple<int, int>), typeof(Cell), null);
+
+ readonly TableView _parent;
+ TableRoot _root;
+
+ public TableSectionModel(TableView tableParent, TableRoot tableRoot)
+ {
+ _parent = tableParent;
+ Root = tableRoot ?? new TableRoot();
+ }
+
+ public TableRoot Root
+ {
+ get { return _root; }
+ set
+ {
+ if (_root == value)
+ return;
+
+ RemoveEvents(_root);
+ _root = value;
+ ApplyEvents(_root);
+ }
+ }
+
+ public override Cell GetCell(int section, int row)
+ {
+ var cell = (Cell)GetItem(section, row);
+ SetPath(cell, new Tuple<int, int>(section, row));
+ return cell;
+ }
+
+ public override object GetItem(int section, int row)
+ {
+ return _root[section][row];
+ }
+
+ public override int GetRowCount(int section)
+ {
+ return _root[section].Count;
+ }
+
+ public override int GetSectionCount()
+ {
+ return _root.Count;
+ }
+
+ public override string GetSectionTitle(int section)
+ {
+ return _root[section].Title;
+ }
+
+ protected override void OnRowSelected(object item)
+ {
+ base.OnRowSelected(item);
+
+ ((Cell)item).OnTapped();
+ }
+
+ internal static Tuple<int, int> GetPath(Cell item)
+ {
+ if (item == null)
+ throw new ArgumentNullException("item");
+
+ return (Tuple<int, int>)item.GetValue(PathProperty);
+ }
+
+ void ApplyEvents(TableRoot tableRoot)
+ {
+ tableRoot.CollectionChanged += _parent.CollectionChanged;
+ tableRoot.SectionCollectionChanged += _parent.OnSectionCollectionChanged;
+ }
+
+ void RemoveEvents(TableRoot tableRoot)
+ {
+ if (tableRoot == null)
+ return;
+
+ tableRoot.CollectionChanged -= _parent.CollectionChanged;
+ tableRoot.SectionCollectionChanged -= _parent.OnSectionCollectionChanged;
+ }
+
+ static void SetPath(Cell item, Tuple<int, int> index)
+ {
+ if (item == null)
+ return;
+
+ item.SetValue(PathProperty, index);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TapGestureRecognizer.cs b/Xamarin.Forms.Core/TapGestureRecognizer.cs
new file mode 100644
index 00000000..0489985d
--- /dev/null
+++ b/Xamarin.Forms.Core/TapGestureRecognizer.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Windows.Input;
+
+namespace Xamarin.Forms
+{
+ public sealed class TapGestureRecognizer : GestureRecognizer
+ {
+ public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(TapGestureRecognizer), null);
+
+ public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create("CommandParameter", typeof(object), typeof(TapGestureRecognizer), null);
+
+ public static readonly BindableProperty NumberOfTapsRequiredProperty = BindableProperty.Create("NumberOfTapsRequired", typeof(int), typeof(TapGestureRecognizer), 1);
+
+ public TapGestureRecognizer()
+ {
+ }
+
+ public ICommand Command
+ {
+ get { return (ICommand)GetValue(CommandProperty); }
+ set { SetValue(CommandProperty, value); }
+ }
+
+ public object CommandParameter
+ {
+ get { return GetValue(CommandParameterProperty); }
+ set { SetValue(CommandParameterProperty, value); }
+ }
+
+ public int NumberOfTapsRequired
+ {
+ get { return (int)GetValue(NumberOfTapsRequiredProperty); }
+ set { SetValue(NumberOfTapsRequiredProperty, value); }
+ }
+
+ public event EventHandler Tapped;
+
+ internal void SendTapped(View sender)
+ {
+ ICommand cmd = Command;
+ if (cmd != null && cmd.CanExecute(CommandParameter))
+ cmd.Execute(CommandParameter);
+
+ EventHandler handler = Tapped;
+ if (handler != null)
+ handler(sender, new TappedEventArgs(CommandParameter));
+
+ Action<View, object> callback = TappedCallback;
+ if (callback != null)
+ callback(sender, TappedCallbackParameter);
+ }
+
+ #region obsolete cruft
+
+ // call empty constructor to hack around bug in mono where compiler generates invalid IL
+ [Obsolete("Obsolete in 1.0.2. Use Command instead")]
+ public TapGestureRecognizer(Action<View, object> tappedCallback) : this()
+ {
+ if (tappedCallback == null)
+ throw new ArgumentNullException("tappedCallback");
+ TappedCallback = tappedCallback;
+ }
+
+ // call empty constructor to hack around bug in mono where compiler generates invalid IL
+ [Obsolete("Obsolete in 1.0.2. Use Command instead")]
+ public TapGestureRecognizer(Action<View> tappedCallback) : this()
+ {
+ if (tappedCallback == null)
+ throw new ArgumentNullException("tappedCallback");
+ TappedCallback = (s, o) => tappedCallback(s);
+ }
+
+ [Obsolete("Obsolete in 1.0.2. Use Command instead")] public static readonly BindableProperty TappedCallbackProperty = BindableProperty.Create("TappedCallback", typeof(Action<View, object>),
+ typeof(TapGestureRecognizer), null);
+
+ [Obsolete("Obsolete in 1.0.2. Use Command instead")]
+ public Action<View, object> TappedCallback
+ {
+ get { return (Action<View, object>)GetValue(TappedCallbackProperty); }
+ set { SetValue(TappedCallbackProperty, value); }
+ }
+
+ [Obsolete("Obsolete in 1.0.2. Use Command instead")] public static readonly BindableProperty TappedCallbackParameterProperty = BindableProperty.Create("TappedCallbackParameter", typeof(object),
+ typeof(TapGestureRecognizer), null);
+
+ [Obsolete("Obsolete in 1.0.2. Use Command instead")]
+ public object TappedCallbackParameter
+ {
+ get { return GetValue(TappedCallbackParameterProperty); }
+ set { SetValue(TappedCallbackParameterProperty, value); }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TappedEventArgs.cs b/Xamarin.Forms.Core/TappedEventArgs.cs
new file mode 100644
index 00000000..9f36b7a2
--- /dev/null
+++ b/Xamarin.Forms.Core/TappedEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class TappedEventArgs : EventArgs
+ {
+ public TappedEventArgs(object parameter)
+ {
+ Parameter = parameter;
+ }
+
+ public object Parameter { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TargetIdiom.cs b/Xamarin.Forms.Core/TargetIdiom.cs
new file mode 100644
index 00000000..d19875db
--- /dev/null
+++ b/Xamarin.Forms.Core/TargetIdiom.cs
@@ -0,0 +1,10 @@
+namespace Xamarin.Forms
+{
+ public enum TargetIdiom
+ {
+ Unsupported,
+ Phone,
+ Tablet,
+ Desktop
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TargetPlatform.cs b/Xamarin.Forms.Core/TargetPlatform.cs
new file mode 100644
index 00000000..d9fe6b76
--- /dev/null
+++ b/Xamarin.Forms.Core/TargetPlatform.cs
@@ -0,0 +1,11 @@
+namespace Xamarin.Forms
+{
+ public enum TargetPlatform
+ {
+ Other,
+ iOS,
+ Android,
+ WinPhone,
+ Windows
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TelephoneKeyboard.cs b/Xamarin.Forms.Core/TelephoneKeyboard.cs
new file mode 100644
index 00000000..36f03d67
--- /dev/null
+++ b/Xamarin.Forms.Core/TelephoneKeyboard.cs
@@ -0,0 +1,6 @@
+namespace Xamarin.Forms
+{
+ internal sealed class TelephoneKeyboard : Keyboard
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TemplateBinding.cs b/Xamarin.Forms.Core/TemplateBinding.cs
new file mode 100644
index 00000000..b01f0671
--- /dev/null
+++ b/Xamarin.Forms.Core/TemplateBinding.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Globalization;
+
+namespace Xamarin.Forms
+{
+ public class TemplateBinding : BindingBase
+ {
+ internal const string SelfPath = ".";
+ IValueConverter _converter;
+ object _converterParameter;
+
+ BindingExpression _expression;
+ string _path;
+
+ public TemplateBinding()
+ {
+ }
+
+ public TemplateBinding(string path, BindingMode mode = BindingMode.Default, IValueConverter converter = null, object converterParameter = null, string stringFormat = null)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (string.IsNullOrWhiteSpace(path))
+ throw new ArgumentException("path can not be an empty string", "path");
+
+ AllowChaining = true;
+ Path = path;
+ Converter = converter;
+ ConverterParameter = converterParameter;
+ Mode = mode;
+ StringFormat = stringFormat;
+ }
+
+ public IValueConverter Converter
+ {
+ get { return _converter; }
+ set
+ {
+ ThrowIfApplied();
+
+ _converter = value;
+ }
+ }
+
+ public object ConverterParameter
+ {
+ get { return _converterParameter; }
+ set
+ {
+ ThrowIfApplied();
+
+ _converterParameter = value;
+ }
+ }
+
+ public string Path
+ {
+ get { return _path; }
+ set
+ {
+ ThrowIfApplied();
+
+ _path = value;
+ _expression = GetBindingExpression(value);
+ }
+ }
+
+ internal override void Apply(bool fromTarget)
+ {
+ base.Apply(fromTarget);
+
+ if (_expression == null)
+ _expression = new BindingExpression(this, SelfPath);
+
+ _expression.Apply(fromTarget);
+ }
+
+ internal override async void Apply(object newContext, BindableObject bindObj, BindableProperty targetProperty)
+ {
+ var view = bindObj as Element;
+ if (view == null)
+ throw new InvalidOperationException();
+
+ base.Apply(newContext, bindObj, targetProperty);
+
+ Element templatedParent = await TemplateUtilities.FindTemplatedParentAsync(view);
+ ApplyInner(templatedParent, bindObj, targetProperty);
+ }
+
+ internal override BindingBase Clone()
+ {
+ return new TemplateBinding(Path, Mode) { Converter = Converter, ConverterParameter = ConverterParameter, StringFormat = StringFormat };
+ }
+
+ internal override object GetSourceValue(object value, Type targetPropertyType)
+ {
+ if (Converter != null)
+ value = Converter.Convert(value, targetPropertyType, ConverterParameter, CultureInfo.CurrentUICulture);
+
+ return base.GetSourceValue(value, targetPropertyType);
+ }
+
+ internal override object GetTargetValue(object value, Type sourcePropertyType)
+ {
+ if (Converter != null)
+ value = Converter.ConvertBack(value, sourcePropertyType, ConverterParameter, CultureInfo.CurrentUICulture);
+
+ return base.GetTargetValue(value, sourcePropertyType);
+ }
+
+ internal override void Unapply()
+ {
+ base.Unapply();
+
+ if (_expression != null)
+ _expression.Unapply();
+ }
+
+ void ApplyInner(Element templatedParent, BindableObject bindableObject, BindableProperty targetProperty)
+ {
+ if (_expression == null && templatedParent != null)
+ _expression = new BindingExpression(this, SelfPath);
+
+ _expression?.Apply(templatedParent, bindableObject, targetProperty);
+ }
+
+ BindingExpression GetBindingExpression(string path)
+ {
+ return new BindingExpression(this, !string.IsNullOrWhiteSpace(path) ? path : SelfPath);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TemplateExtensions.cs b/Xamarin.Forms.Core/TemplateExtensions.cs
new file mode 100644
index 00000000..3e62c52d
--- /dev/null
+++ b/Xamarin.Forms.Core/TemplateExtensions.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public static class TemplateExtensions
+ {
+ public static void SetBinding(this DataTemplate self, BindableProperty targetProperty, string path)
+ {
+ if (self == null)
+ throw new ArgumentNullException("self");
+
+ self.SetBinding(targetProperty, new Binding(path));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TemplateUtilities.cs b/Xamarin.Forms.Core/TemplateUtilities.cs
new file mode 100644
index 00000000..0599e747
--- /dev/null
+++ b/Xamarin.Forms.Core/TemplateUtilities.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ internal static class TemplateUtilities
+ {
+ public static async Task<Element> FindTemplatedParentAsync(Element element)
+ {
+ if (element.RealParent is Application)
+ return null;
+
+ var skipCount = 0;
+ element = await GetRealParentAsync(element);
+ while (!Application.IsApplicationOrNull(element))
+ {
+ var controlTemplated = element as IControlTemplated;
+ if (controlTemplated?.ControlTemplate != null)
+ {
+ if (skipCount == 0)
+ return element;
+ skipCount--;
+ }
+ if (element is ContentPresenter)
+ skipCount++;
+ element = await GetRealParentAsync(element);
+ }
+
+ return null;
+ }
+
+ public static Task<Element> GetRealParentAsync(Element element)
+ {
+ Element parent = element.RealParent;
+ if (parent is Application)
+ return Task.FromResult<Element>(null);
+
+ if (parent != null)
+ return Task.FromResult(parent);
+
+ var tcs = new TaskCompletionSource<Element>();
+ EventHandler handler = null;
+ handler = (sender, args) =>
+ {
+ tcs.TrySetResult(element.RealParent);
+ element.ParentSet -= handler;
+ };
+ element.ParentSet += handler;
+
+ return tcs.Task;
+ }
+
+ public static void OnContentChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var self = (IControlTemplated)bindable;
+ var newElement = (Element)newValue;
+ if (self.ControlTemplate == null)
+ {
+ for (var i = 0; i < self.InternalChildren.Count; i++)
+ {
+ self.InternalChildren.Remove(self.InternalChildren[i]);
+ }
+
+ if (newValue != null)
+ self.InternalChildren.Add(newElement);
+ }
+ else
+ {
+ if (newElement != null)
+ {
+ BindableObject.SetInheritedBindingContext(newElement, bindable.BindingContext);
+ }
+ }
+ }
+
+ public static void OnControlTemplateChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var self = (IControlTemplated)bindable;
+
+ // First make sure any old ContentPresenters are no longer bound up. This MUST be
+ // done before we attempt to make the new template.
+ if (oldValue != null)
+ {
+ var queue = new Queue<Element>(16);
+ queue.Enqueue((Element)self);
+
+ while (queue.Count > 0)
+ {
+ ReadOnlyCollection<Element> children = queue.Dequeue().LogicalChildren;
+ for (var i = 0; i < children.Count; i++)
+ {
+ Element child = children[i];
+ var controlTemplated = child as IControlTemplated;
+
+ var presenter = child as ContentPresenter;
+ if (presenter != null)
+ presenter.Clear();
+ else if (controlTemplated == null || controlTemplated.ControlTemplate == null)
+ queue.Enqueue(child);
+ }
+ }
+ }
+
+ // Now remove all remnants of any other children just to be sure
+ for (var i = 0; i < self.InternalChildren.Count; i++)
+ {
+ self.InternalChildren.Remove(self.InternalChildren[i]);
+ }
+
+ ControlTemplate template = self.ControlTemplate;
+ var content = template.CreateContent() as View;
+
+ if (content == null)
+ {
+ throw new NotSupportedException("ControlTemplate must return a type derived from View.");
+ }
+
+ self.InternalChildren.Add(content);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TemplatedItemsList.cs b/Xamarin.Forms.Core/TemplatedItemsList.cs
new file mode 100644
index 00000000..814f5835
--- /dev/null
+++ b/Xamarin.Forms.Core/TemplatedItemsList.cs
@@ -0,0 +1,1325 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading.Tasks;
+using Cadenza.Collections;
+
+namespace Xamarin.Forms
+{
+ internal sealed class TemplatedItemsList<TView, TItem> : BindableObject, IReadOnlyList<TItem>, IList, INotifyCollectionChanged, IDisposable where TView : BindableObject, IItemsView<TItem>
+ where TItem : BindableObject
+ {
+ public static readonly BindableProperty NameProperty = BindableProperty.Create("Name", typeof(string), typeof(TemplatedItemsList<TView, TItem>), null);
+
+ public static readonly BindableProperty ShortNameProperty = BindableProperty.Create("ShortName", typeof(string), typeof(TemplatedItemsList<TView, TItem>), null);
+
+ static readonly BindablePropertyKey HeaderContentPropertyKey = BindableProperty.CreateReadOnly("HeaderContent", typeof(TItem), typeof(TemplatedItemsList<TView, TItem>), null);
+
+ internal static readonly BindablePropertyKey ListProxyPropertyKey = BindableProperty.CreateReadOnly("ListProxy", typeof(ListProxy), typeof(TemplatedItemsList<TView, TItem>), null,
+ propertyChanged: OnListProxyChanged);
+
+ static readonly BindableProperty GroupProperty = BindableProperty.Create("Group", typeof(TemplatedItemsList<TView, TItem>), typeof(TItem), null);
+
+ static readonly BindableProperty IndexProperty = BindableProperty.Create("Index", typeof(int), typeof(TItem), -1);
+
+ static readonly BindablePropertyKey IsGroupHeaderPropertyKey = BindableProperty.CreateAttachedReadOnly("IsGroupHeader", typeof(bool), typeof(Cell), false);
+
+ readonly BindableProperty _itemSourceProperty;
+ readonly BindableProperty _itemTemplateProperty;
+
+ readonly TView _itemsView;
+
+ readonly List<TItem> _templatedObjects = new List<TItem>();
+
+ bool _disposed;
+ BindingBase _groupDisplayBinding;
+ OrderedDictionary<object, TemplatedItemsList<TView, TItem>> _groupedItems;
+ DataTemplate _groupHeaderTemplate;
+ BindingBase _groupShortNameBinding;
+ ShortNamesProxy _shortNames;
+
+ internal TemplatedItemsList(TView itemsView, BindableProperty itemSourceProperty, BindableProperty itemTemplateProperty)
+ {
+ if (itemsView == null)
+ throw new ArgumentNullException("itemsView");
+ if (itemSourceProperty == null)
+ throw new ArgumentNullException("itemSourceProperty");
+ if (itemTemplateProperty == null)
+ throw new ArgumentNullException("itemTemplateProperty");
+
+ _itemsView = itemsView;
+ _itemsView.PropertyChanged += BindableOnPropertyChanged;
+
+ _itemSourceProperty = itemSourceProperty;
+ _itemTemplateProperty = itemTemplateProperty;
+
+ IEnumerable source = GetItemsViewSource();
+ if (source != null)
+ ListProxy = new ListProxy(source);
+ else
+ ListProxy = new ListProxy(new object[0]);
+ }
+
+ internal TemplatedItemsList(TemplatedItemsList<TView, TItem> parent, IEnumerable itemSource, TView itemsView, BindableProperty itemTemplateProperty, int windowSize = int.MaxValue)
+ {
+ if (itemsView == null)
+ throw new ArgumentNullException("itemsView");
+ if (itemTemplateProperty == null)
+ throw new ArgumentNullException("itemTemplateProperty");
+
+ Parent = parent;
+
+ _itemsView = itemsView;
+ _itemsView.PropertyChanged += BindableOnPropertyChanged;
+ _itemTemplateProperty = itemTemplateProperty;
+
+ if (itemSource != null)
+ {
+ ListProxy = new ListProxy(itemSource, windowSize);
+ ListProxy.CollectionChanged += OnProxyCollectionChanged;
+ }
+ else
+ ListProxy = new ListProxy(new object[0]);
+ }
+
+ public BindingBase GroupDisplayBinding
+ {
+ get { return _groupDisplayBinding; }
+ set
+ {
+ _groupDisplayBinding = value;
+ OnHeaderTemplateChanged();
+ }
+ }
+
+ public DataTemplate GroupHeaderTemplate
+ {
+ get
+ {
+ DataTemplate groupHeader = null;
+ if (GroupHeaderTemplateProperty != null)
+ groupHeader = (DataTemplate)_itemsView.GetValue(GroupHeaderTemplateProperty);
+
+ return groupHeader ?? _groupHeaderTemplate;
+ }
+
+ set
+ {
+ if (_groupHeaderTemplate == value)
+ return;
+
+ _groupHeaderTemplate = value;
+ OnHeaderTemplateChanged();
+ }
+ }
+
+ public BindableProperty GroupHeaderTemplateProperty { get; set; }
+
+ public BindingBase GroupShortNameBinding
+ {
+ get { return _groupShortNameBinding; }
+ set
+ {
+ _groupShortNameBinding = value;
+ OnShortNameBindingChanged();
+ }
+ }
+
+ public TItem HeaderContent
+ {
+ get { return (TItem)GetValue(HeaderContentPropertyKey.BindableProperty); }
+ private set { SetValue(HeaderContentPropertyKey, value); }
+ }
+
+ public bool IsGroupingEnabled
+ {
+ get { return (IsGroupingEnabledProperty != null) && (bool)_itemsView.GetValue(IsGroupingEnabledProperty); }
+ }
+
+ public BindableProperty IsGroupingEnabledProperty { get; set; }
+
+ public IEnumerable ItemsSource
+ {
+ get { return ListProxy.ProxiedEnumerable; }
+ }
+
+ public string Name
+ {
+ get { return (string)GetValue(NameProperty); }
+ set { SetValue(NameProperty, value); }
+ }
+
+ public TemplatedItemsList<TView, TItem> Parent { get; }
+
+ public BindableProperty ProgressiveLoadingProperty { get; set; }
+
+ public string ShortName
+ {
+ get { return (string)GetValue(ShortNameProperty); }
+ set { SetValue(ShortNameProperty, value); }
+ }
+
+ public IReadOnlyList<string> ShortNames
+ {
+ get { return _shortNames; }
+ }
+
+ internal ListViewCachingStrategy CachingStrategy
+ {
+ get
+ {
+ var listView = _itemsView as ListView;
+ if (listView == null)
+ return ListViewCachingStrategy.RetainElement;
+
+ return listView.CachingStrategy;
+ }
+ }
+
+ internal ListProxy ListProxy
+ {
+ get { return (ListProxy)GetValue(ListProxyPropertyKey.BindableProperty); }
+ private set { SetValue(ListProxyPropertyKey, value); }
+ }
+
+ DataTemplate ItemTemplate
+ {
+ get { return (DataTemplate)_itemsView.GetValue(_itemTemplateProperty); }
+ }
+
+ bool ProgressiveLoading
+ {
+ get { return (ProgressiveLoadingProperty != null) && (bool)_itemsView.GetValue(ProgressiveLoadingProperty); }
+ }
+
+ void ICollection.CopyTo(Array array, int arrayIndex)
+ {
+ throw new NotImplementedException();
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ get { return false; }
+ }
+
+ object ICollection.SyncRoot
+ {
+ get { return this; }
+ }
+
+ public void Dispose()
+ {
+ if (_disposed)
+ return;
+
+ _itemsView.PropertyChanged -= BindableOnPropertyChanged;
+
+ TItem header = HeaderContent;
+ if (header != null)
+ UnhookItem(header);
+
+ for (var i = 0; i < _templatedObjects.Count; i++)
+ {
+ TItem item = _templatedObjects[i];
+ if (item != null)
+ UnhookItem(item);
+ }
+
+ _disposed = true;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ if (IsGroupingEnabled)
+ return _groupedItems.Values.GetEnumerator();
+
+ return GetEnumerator();
+ }
+
+ public IEnumerator<TItem> GetEnumerator()
+ {
+ var i = 0;
+ foreach (object item in ListProxy)
+ yield return GetOrCreateContent(i++, item);
+ }
+
+ int IList.Add(object item)
+ {
+ throw new NotSupportedException();
+ }
+
+ void IList.Clear()
+ {
+ throw new NotSupportedException();
+ }
+
+ bool IList.Contains(object item)
+ {
+ throw new NotImplementedException();
+ }
+
+ int IList.IndexOf(object item)
+ {
+ if (IsGroupingEnabled)
+ {
+ var til = item as TemplatedItemsList<TView, TItem>;
+ if (til != null)
+ return _groupedItems.Values.IndexOf(til);
+ }
+
+ return IndexOf((TItem)item);
+ }
+
+ void IList.Insert(int index, object item)
+ {
+ throw new NotSupportedException();
+ }
+
+ bool IList.IsFixedSize
+ {
+ get { return false; }
+ }
+
+ bool IList.IsReadOnly
+ {
+ get { return true; }
+ }
+
+ object IList.this[int index]
+ {
+ get
+ {
+ if (IsGroupingEnabled)
+ return GetGroup(index);
+
+ return this[index];
+ }
+ set { throw new NotSupportedException(); }
+ }
+
+ void IList.Remove(object item)
+ {
+ throw new NotSupportedException();
+ }
+
+ void IList.RemoveAt(int index)
+ {
+ throw new NotSupportedException();
+ }
+
+ public event NotifyCollectionChangedEventHandler CollectionChanged;
+
+ public int Count
+ {
+ get { return ListProxy.Count; }
+ }
+
+ public TItem this[int index]
+ {
+ get { return GetOrCreateContent(index, ListProxy[index]); }
+ }
+
+ public int GetDescendantCount()
+ {
+ if (!IsGroupingEnabled)
+ return Count;
+
+ if (_groupedItems == null)
+ return 0;
+
+ int count = Count;
+ foreach (TemplatedItemsList<TView, TItem> group in _groupedItems.Values)
+ count += group.GetDescendantCount();
+
+ return count;
+ }
+
+ public int GetGlobalIndexForGroup(TemplatedItemsList<TView, TItem> group)
+ {
+ if (group == null)
+ throw new ArgumentNullException("group");
+
+ int groupIndex = _groupedItems.Values.IndexOf(group);
+
+ var index = 0;
+ for (var i = 0; i < groupIndex; i++)
+ index += _groupedItems[i].GetDescendantCount() + 1;
+
+ return index;
+ }
+
+ public int GetGlobalIndexOfGroup(object item)
+ {
+ var count = 0;
+ if (IsGroupingEnabled && _groupedItems != null)
+ {
+ foreach (object group in _groupedItems.Keys)
+ {
+ if (group == item)
+ return count;
+ count++;
+ }
+ }
+
+ return -1;
+ }
+
+ public int GetGlobalIndexOfItem(object item)
+ {
+ if (!IsGroupingEnabled)
+ return ListProxy.IndexOf(item);
+
+ var count = 0;
+ if (_groupedItems != null)
+ {
+ foreach (TemplatedItemsList<TView, TItem> children in _groupedItems.Values)
+ {
+ count++;
+
+ int index = children.GetGlobalIndexOfItem(item);
+ if (index != -1)
+ return count + index;
+
+ count += children.GetDescendantCount();
+ }
+ }
+
+ return -1;
+ }
+
+ public int GetGlobalIndexOfItem(object group, object item)
+ {
+ if (!IsGroupingEnabled)
+ return ListProxy.IndexOf(item);
+
+ var count = 0;
+ if (_groupedItems != null)
+ {
+ foreach (KeyValuePair<object, TemplatedItemsList<TView, TItem>> kvp in _groupedItems)
+ {
+ count++;
+
+ if (ReferenceEquals(group, kvp.Key))
+ {
+ int index = kvp.Value.GetGlobalIndexOfItem(item);
+ if (index != -1)
+ return count + index;
+ }
+
+ count += kvp.Value.GetDescendantCount();
+ }
+ }
+
+ return -1;
+ }
+
+ public Tuple<int, int> GetGroupAndIndexOfItem(object item)
+ {
+ if (item == null)
+ return new Tuple<int, int>(-1, -1);
+ if (!IsGroupingEnabled)
+ return new Tuple<int, int>(0, GetGlobalIndexOfItem(item));
+
+ var group = 0;
+ if (_groupedItems != null)
+ {
+ foreach (TemplatedItemsList<TView, TItem> children in _groupedItems.Values)
+ {
+ int index = children.GetGlobalIndexOfItem(item);
+ if (index != -1)
+ return new Tuple<int, int>(group, index);
+
+ group++;
+ }
+ }
+
+ return new Tuple<int, int>(-1, -1);
+ }
+
+ public Tuple<int, int> GetGroupAndIndexOfItem(object group, object item)
+ {
+ if (!IsGroupingEnabled)
+ return new Tuple<int, int>(0, GetGlobalIndexOfItem(item));
+ if (_groupedItems == null)
+ return new Tuple<int, int>(-1, -1);
+
+ var groupIndex = 0;
+ foreach (TemplatedItemsList<TView, TItem> children in _groupedItems.Values)
+ {
+ if (ReferenceEquals(children.BindingContext, group) || group == null)
+ {
+ for (var i = 0; i < children.Count; i++)
+ {
+ if (ReferenceEquals(children[i].BindingContext, item))
+ return new Tuple<int, int>(groupIndex, i);
+ }
+
+ if (group != null)
+ return new Tuple<int, int>(groupIndex, -1);
+ }
+
+ groupIndex++;
+ }
+
+ return new Tuple<int, int>(-1, -1);
+ }
+
+ public int GetGroupIndexFromGlobal(int globalIndex, out int leftOver)
+ {
+ leftOver = 0;
+
+ var index = 0;
+ for (var i = 0; i < _groupedItems.Count; i++)
+ {
+ if (index == globalIndex)
+ return i;
+
+ TemplatedItemsList<TView, TItem> group = _groupedItems[i];
+ int count = group.GetDescendantCount();
+
+ if (index + count >= globalIndex)
+ {
+ leftOver = globalIndex - index;
+ return i;
+ }
+
+ index += count + 1;
+ }
+
+ return -1;
+ }
+
+ public event NotifyCollectionChangedEventHandler GroupedCollectionChanged;
+
+ public int IndexOf(TItem item)
+ {
+ TemplatedItemsList<TView, TItem> group = GetGroup(item);
+ if (group != null && group != this)
+ return -1;
+
+ return GetIndex(item);
+ }
+
+ internal TItem CreateContent(int index, object item, bool insert = false)
+ {
+ TItem content = ItemTemplate != null ? (TItem)ItemTemplate.CreateContent(item, _itemsView) : _itemsView.CreateDefault(item);
+
+ content = UpdateContent(content, index, item);
+
+ if (CachingStrategy == ListViewCachingStrategy.RecycleElement)
+ return content;
+
+ for (int i = _templatedObjects.Count; i <= index; i++)
+ _templatedObjects.Add(null);
+
+ if (!insert)
+ _templatedObjects[index] = content;
+ else
+ _templatedObjects.Insert(index, content);
+
+ return content;
+ }
+
+ internal void ForceUpdate()
+ {
+ ListProxy.Clear();
+ }
+
+ internal TemplatedItemsList<TView, TItem> GetGroup(int index)
+ {
+ if (!IsGroupingEnabled)
+ return this;
+
+ return _groupedItems[index];
+ }
+
+ internal static TemplatedItemsList<TView, TItem> GetGroup(TItem item)
+ {
+ if (item == null)
+ throw new ArgumentNullException("item");
+
+ return (TemplatedItemsList<TView, TItem>)item.GetValue(GroupProperty);
+ }
+
+ internal static int GetIndex(TItem item)
+ {
+ if (item == null)
+ throw new ArgumentNullException("item");
+
+ return (int)item.GetValue(IndexProperty);
+ }
+
+ internal static bool GetIsGroupHeader(BindableObject bindable)
+ {
+ return (bool)bindable.GetValue(IsGroupHeaderPropertyKey.BindableProperty);
+ }
+
+ internal TItem GetOrCreateContent(int index, object item)
+ {
+ TItem content;
+ if (_templatedObjects.Count <= index || (content = _templatedObjects[index]) == null)
+ content = CreateContent(index, item);
+
+ return content;
+ }
+
+ internal static void SetIsGroupHeader(BindableObject bindable, bool value)
+ {
+ bindable.SetValue(IsGroupHeaderPropertyKey, value);
+ }
+
+ internal TItem UpdateContent(TItem content, int index, object item)
+ {
+ content.BindingContext = item;
+
+ if (Parent != null)
+ SetGroup(content, this);
+
+ SetIndex(content, index);
+
+ _itemsView.SetupContent(content, index);
+
+ return content;
+ }
+
+ internal TItem UpdateContent(TItem content, int index)
+ {
+ object item = ListProxy[index];
+ return UpdateContent(content, index, item);
+ }
+
+ internal TItem UpdateHeader(TItem content, int groupIndex)
+ {
+ if (Parent != null && Parent.GroupHeaderTemplate == null)
+ {
+ content.BindingContext = this;
+ }
+ else
+ {
+ content.BindingContext = ListProxy.ProxiedEnumerable;
+ }
+
+ SetIndex(content, groupIndex);
+
+ _itemsView.SetupContent(content, groupIndex);
+
+ return content;
+ }
+
+ void BindableOnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (_itemSourceProperty != null && e.PropertyName == _itemSourceProperty.PropertyName)
+ OnItemsSourceChanged();
+ else if (e.PropertyName == _itemTemplateProperty.PropertyName)
+ OnItemTemplateChanged();
+ else if (ProgressiveLoadingProperty != null && e.PropertyName == ProgressiveLoadingProperty.PropertyName)
+ OnInfiniteScrollingChanged();
+ else if (GroupHeaderTemplateProperty != null && e.PropertyName == GroupHeaderTemplateProperty.PropertyName)
+ OnHeaderTemplateChanged();
+ else if (IsGroupingEnabledProperty != null && e.PropertyName == IsGroupingEnabledProperty.PropertyName)
+ OnGroupingEnabledChanged();
+ }
+
+ IList ConvertContent(int startingIndex, IList items, bool forceCreate = false, bool setIndex = false)
+ {
+ var contentItems = new List<TItem>(items.Count);
+ for (var i = 0; i < items.Count; i++)
+ {
+ int index = i + startingIndex;
+ TItem content = !forceCreate ? GetOrCreateContent(index, items[i]) : CreateContent(index, items[i]);
+ if (setIndex)
+ SetIndex(content, index);
+
+ contentItems.Add(content);
+ }
+
+ return contentItems;
+ }
+
+ IEnumerable GetItemsViewSource()
+ {
+ return (IEnumerable)_itemsView.GetValue(_itemSourceProperty);
+ }
+
+ void GroupedReset()
+ {
+ if (_groupedItems != null)
+ {
+ foreach (KeyValuePair<object, TemplatedItemsList<TView, TItem>> group in _groupedItems)
+ {
+ group.Value.CollectionChanged -= OnInnerCollectionChanged;
+ group.Value.Dispose();
+ }
+ _groupedItems.Clear();
+ }
+
+ _templatedObjects.Clear();
+
+ var i = 0;
+ foreach (object item in ListProxy)
+ InsertGrouped(item, i++);
+
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ }
+
+ TemplatedItemsList<TView, TItem> InsertGrouped(object item, int index)
+ {
+ var children = item as IEnumerable;
+
+ var groupProxy = new TemplatedItemsList<TView, TItem>(this, children, _itemsView, _itemTemplateProperty);
+ if (GroupDisplayBinding != null)
+ groupProxy.SetBinding(NameProperty, GroupDisplayBinding.Clone());
+ else if (GroupHeaderTemplate == null && item != null)
+ groupProxy.Name = item.ToString();
+
+ if (GroupShortNameBinding != null)
+ groupProxy.SetBinding(ShortNameProperty, GroupShortNameBinding.Clone());
+
+ groupProxy.BindingContext = item;
+
+ if (GroupHeaderTemplate != null)
+ {
+ groupProxy.HeaderContent = (TItem)GroupHeaderTemplate.CreateContent(groupProxy.ItemsSource, _itemsView);
+ groupProxy.HeaderContent.BindingContext = groupProxy.ItemsSource;
+ //groupProxy.HeaderContent.BindingContext = groupProxy;
+ //groupProxy.HeaderContent.SetBinding (BindingContextProperty, "ItemsSource");
+ }
+ else
+ {
+ // HACK: TemplatedItemsList shouldn't assume what the default is, but it needs
+ // to be able to setup bindings. Needs some internal-API tweaking there isn't
+ // time for right now.
+ groupProxy.HeaderContent = _itemsView.CreateDefault(ListProxy.ProxiedEnumerable);
+ groupProxy.HeaderContent.BindingContext = groupProxy;
+ groupProxy.HeaderContent.SetBinding(TextCell.TextProperty, "Name");
+ }
+
+ SetIndex(groupProxy.HeaderContent, index);
+ SetIsGroupHeader(groupProxy.HeaderContent, true);
+
+ _itemsView.SetupContent(groupProxy.HeaderContent, index);
+
+ _templatedObjects.Insert(index, groupProxy.HeaderContent);
+ _groupedItems.Insert(index, item, groupProxy);
+
+ groupProxy.CollectionChanged += OnInnerCollectionChanged;
+
+ return groupProxy;
+ }
+
+ void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
+ {
+ NotifyCollectionChangedEventHandler changed = CollectionChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ void OnCollectionChangedGrouped(NotifyCollectionChangedEventArgs e)
+ {
+ if (_groupedItems == null)
+ _groupedItems = new OrderedDictionary<object, TemplatedItemsList<TView, TItem>>();
+
+ List<TemplatedItemsList<TView, TItem>> newItems = null, oldItems = null;
+
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ if (e.NewStartingIndex == -1)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ for (int i = e.NewStartingIndex; i < _templatedObjects.Count; i++)
+ SetIndex(_templatedObjects[i], i + e.NewItems.Count);
+
+ newItems = new List<TemplatedItemsList<TView, TItem>>(e.NewItems.Count);
+
+ for (var i = 0; i < e.NewItems.Count; i++)
+ {
+ TemplatedItemsList<TView, TItem> converted = InsertGrouped(e.NewItems[i], e.NewStartingIndex + i);
+ newItems.Add(converted);
+ }
+
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, newItems, e.NewStartingIndex));
+
+ break;
+
+ case NotifyCollectionChangedAction.Remove:
+ if (e.OldStartingIndex == -1)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ int removeIndex = e.OldStartingIndex;
+ for (int i = removeIndex + e.OldItems.Count; i < _templatedObjects.Count; i++)
+ SetIndex(_templatedObjects[i], removeIndex++);
+
+ oldItems = new List<TemplatedItemsList<TView, TItem>>(e.OldItems.Count);
+ for (var i = 0; i < e.OldItems.Count; i++)
+ {
+ int index = e.OldStartingIndex + i;
+ TemplatedItemsList<TView, TItem> til = _groupedItems[index];
+ til.CollectionChanged -= OnInnerCollectionChanged;
+ oldItems.Add(til);
+ _groupedItems.RemoveAt(index);
+ _templatedObjects.RemoveAt(index);
+ til.Dispose();
+ }
+
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, oldItems, e.OldStartingIndex));
+
+ break;
+
+ case NotifyCollectionChangedAction.Replace:
+ if (e.OldStartingIndex == -1)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ oldItems = new List<TemplatedItemsList<TView, TItem>>(e.OldItems.Count);
+ newItems = new List<TemplatedItemsList<TView, TItem>>(e.NewItems.Count);
+
+ for (var i = 0; i < e.OldItems.Count; i++)
+ {
+ int index = e.OldStartingIndex + i;
+
+ TemplatedItemsList<TView, TItem> til = _groupedItems[index];
+ til.CollectionChanged -= OnInnerCollectionChanged;
+ oldItems.Add(til);
+
+ _groupedItems.RemoveAt(index);
+ _templatedObjects.RemoveAt(index);
+
+ newItems.Add(InsertGrouped(e.NewItems[i], index));
+ til.Dispose();
+ }
+
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newItems, oldItems, e.OldStartingIndex));
+
+ break;
+
+ case NotifyCollectionChangedAction.Move:
+ if (e.OldStartingIndex == -1 || e.NewStartingIndex == -1)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ bool movingForward = e.OldStartingIndex < e.NewStartingIndex;
+
+ if (movingForward)
+ {
+ int moveIndex = e.OldStartingIndex;
+ for (int i = moveIndex + e.OldItems.Count; i <= e.NewStartingIndex; i++)
+ SetIndex(_templatedObjects[i], moveIndex++);
+ }
+ else
+ {
+ for (var i = 0; i < e.OldStartingIndex - e.NewStartingIndex; i++)
+ {
+ TItem item = _templatedObjects[i + e.NewStartingIndex];
+ SetIndex(item, GetIndex(item) + e.OldItems.Count);
+ }
+ }
+
+ oldItems = new List<TemplatedItemsList<TView, TItem>>(e.OldItems.Count);
+
+ for (var i = 0; i < e.OldItems.Count; i++)
+ {
+ oldItems.Add(_groupedItems[e.OldStartingIndex]);
+
+ _templatedObjects.RemoveAt(e.OldStartingIndex);
+ _groupedItems.RemoveAt(e.OldStartingIndex);
+ }
+
+ int insertIndex = e.NewStartingIndex;
+ if (e.OldStartingIndex < e.NewStartingIndex)
+ insertIndex -= e.OldItems.Count - 1;
+
+ for (var i = 0; i < oldItems.Count; i++)
+ {
+ TemplatedItemsList<TView, TItem> til = oldItems[i];
+ _templatedObjects.Insert(insertIndex + i, til.HeaderContent);
+ _groupedItems.Insert(insertIndex + i, til.BindingContext, til);
+ SetIndex(til.HeaderContent, insertIndex + i);
+ }
+
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, oldItems, e.OldStartingIndex, e.NewStartingIndex));
+
+ break;
+
+ case NotifyCollectionChangedAction.Reset:
+ GroupedReset();
+ break;
+ }
+ }
+
+ void OnGroupingEnabledChanged()
+ {
+ if (CachingStrategy == ListViewCachingStrategy.RecycleElement)
+ _templatedObjects.Clear();
+
+ OnItemsSourceChanged(true);
+
+ if (!IsGroupingEnabled && _shortNames != null)
+ {
+ _shortNames.Dispose();
+ _shortNames = null;
+ }
+ else
+ OnShortNameBindingChanged();
+ }
+
+ void OnHeaderTemplateChanged()
+ {
+ OnItemTemplateChanged();
+ }
+
+ void OnInfiniteScrollingChanged()
+ {
+ OnItemsSourceChanged();
+ }
+
+ void OnInnerCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ NotifyCollectionChangedEventHandler handler = GroupedCollectionChanged;
+ if (handler != null)
+ handler(sender, e);
+ }
+
+ void OnItemsSourceChanged(bool fromGrouping = false)
+ {
+ ListProxy.CollectionChanged -= OnProxyCollectionChanged;
+
+ IEnumerable itemSource = GetItemsViewSource();
+ if (itemSource == null)
+ ListProxy = new ListProxy(new object[0]);
+ else
+ ListProxy = new ListProxy(itemSource);
+
+ ListProxy.CollectionChanged += OnProxyCollectionChanged;
+ OnProxyCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ }
+
+ void OnItemTemplateChanged()
+ {
+ if (ListProxy.Count == 0)
+ return;
+
+ OnProxyCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ }
+
+ static void OnListProxyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ var til = (TemplatedItemsList<TView, TItem>)bindable;
+ til.OnPropertyChanged("ItemsSource");
+ }
+
+ void OnProxyCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ OnProxyCollectionChanged(sender, e, true);
+ }
+
+ void OnProxyCollectionChanged(object sender, NotifyCollectionChangedEventArgs e, bool fixWindows = true)
+ {
+ if (IsGroupingEnabled)
+ {
+ OnCollectionChangedGrouped(e);
+ return;
+ }
+
+ if (CachingStrategy == ListViewCachingStrategy.RecycleElement)
+ {
+ OnCollectionChanged(e);
+ return;
+ }
+
+ /* HACKAHACKHACK: LongListSelector on WP SL has a bug in that it completely fails to deal with
+ * INCC notifications that include more than 1 item. */
+ if (fixWindows && Device.OS == TargetPlatform.WinPhone)
+ {
+ SplitCollectionChangedItems(e);
+ return;
+ }
+
+ int count = Count;
+ var ex = e as NotifyCollectionChangedEventArgsEx;
+ if (ex != null)
+ count = ex.Count;
+
+ var maxindex = 0;
+ if (e.NewStartingIndex >= 0 && e.NewItems != null)
+ maxindex = Math.Max(maxindex, e.NewStartingIndex + e.NewItems.Count);
+ if (e.OldStartingIndex >= 0 && e.OldItems != null)
+ maxindex = Math.Max(maxindex, e.OldStartingIndex + e.OldItems.Count);
+ if (maxindex > _templatedObjects.Count)
+ _templatedObjects.InsertRange(_templatedObjects.Count, Enumerable.Repeat<TItem>(null, maxindex - _templatedObjects.Count));
+
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ if (e.NewStartingIndex >= 0)
+ {
+ for (int i = e.NewStartingIndex; i < _templatedObjects.Count; i++)
+ SetIndex(_templatedObjects[i], i + e.NewItems.Count);
+
+ _templatedObjects.InsertRange(e.NewStartingIndex, Enumerable.Repeat<TItem>(null, e.NewItems.Count));
+
+ IList items = ConvertContent(e.NewStartingIndex, e.NewItems, true, true);
+ e = new NotifyCollectionChangedEventArgsEx(count, NotifyCollectionChangedAction.Add, items, e.NewStartingIndex);
+ }
+ else
+ {
+ goto case NotifyCollectionChangedAction.Reset;
+ }
+
+ break;
+
+ case NotifyCollectionChangedAction.Move:
+ if (e.NewStartingIndex < 0 || e.OldStartingIndex < 0)
+ goto case NotifyCollectionChangedAction.Reset;
+
+ bool movingForward = e.OldStartingIndex < e.NewStartingIndex;
+
+ if (movingForward)
+ {
+ int moveIndex = e.OldStartingIndex;
+ for (int i = moveIndex + e.OldItems.Count; i <= e.NewStartingIndex; i++)
+ SetIndex(_templatedObjects[i], moveIndex++);
+ }
+ else
+ {
+ for (var i = 0; i < e.OldStartingIndex - e.NewStartingIndex; i++)
+ {
+ TItem item = _templatedObjects[i + e.NewStartingIndex];
+ if (item != null)
+ SetIndex(item, GetIndex(item) + e.OldItems.Count);
+ }
+ }
+
+ TItem[] itemsToMove = _templatedObjects.Skip(e.OldStartingIndex).Take(e.OldItems.Count).ToArray();
+
+ _templatedObjects.RemoveRange(e.OldStartingIndex, e.OldItems.Count);
+ _templatedObjects.InsertRange(e.NewStartingIndex, itemsToMove);
+ for (var i = 0; i < itemsToMove.Length; i++)
+ SetIndex(itemsToMove[i], e.NewStartingIndex + i);
+
+ e = new NotifyCollectionChangedEventArgsEx(count, NotifyCollectionChangedAction.Move, itemsToMove, e.NewStartingIndex, e.OldStartingIndex);
+ break;
+
+ case NotifyCollectionChangedAction.Remove:
+ if (e.OldStartingIndex >= 0)
+ {
+ int removeIndex = e.OldStartingIndex;
+ for (int i = removeIndex + e.OldItems.Count; i < _templatedObjects.Count; i++)
+ SetIndex(_templatedObjects[i], removeIndex++);
+
+ var items = new TItem[e.OldItems.Count];
+ for (var i = 0; i < items.Length; i++)
+ {
+ TItem item = _templatedObjects[e.OldStartingIndex + i];
+ if (item == null)
+ continue;
+
+ UnhookItem(item);
+ items[i] = item;
+ }
+
+ _templatedObjects.RemoveRange(e.OldStartingIndex, e.OldItems.Count);
+ e = new NotifyCollectionChangedEventArgsEx(count, NotifyCollectionChangedAction.Remove, items, e.OldStartingIndex);
+ }
+ else
+ {
+ goto case NotifyCollectionChangedAction.Reset;
+ }
+ break;
+
+ case NotifyCollectionChangedAction.Replace:
+ if (e.NewStartingIndex >= 0)
+ {
+ IList oldItems = ConvertContent(e.NewStartingIndex, e.OldItems);
+ IList newItems = ConvertContent(e.NewStartingIndex, e.NewItems, true, true);
+
+ for (var i = 0; i < oldItems.Count; i++)
+ {
+ UnhookItem((TItem)oldItems[i]);
+ }
+
+ e = new NotifyCollectionChangedEventArgsEx(count, NotifyCollectionChangedAction.Replace, newItems, oldItems, e.NewStartingIndex);
+ }
+ else
+ {
+ goto case NotifyCollectionChangedAction.Reset;
+ }
+
+ break;
+
+ case NotifyCollectionChangedAction.Reset:
+ e = new NotifyCollectionChangedEventArgsEx(count, NotifyCollectionChangedAction.Reset);
+ UnhookAndClear();
+ break;
+
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+
+ OnCollectionChanged(e);
+ }
+
+ void OnShortNameBindingChanged()
+ {
+ if (!IsGroupingEnabled)
+ return;
+
+ if (GroupShortNameBinding != null && _shortNames == null)
+ _shortNames = new ShortNamesProxy(this);
+ else if (GroupShortNameBinding == null && _shortNames != null)
+ {
+ _shortNames.Dispose();
+ _shortNames = null;
+ }
+
+ if (_groupedItems != null)
+ {
+ if (GroupShortNameBinding == null)
+ {
+ foreach (TemplatedItemsList<TView, TItem> list in _groupedItems.Values)
+ list.SetValue(ShortNameProperty, null);
+
+ return;
+ }
+
+ foreach (TemplatedItemsList<TView, TItem> list in _groupedItems.Values)
+ list.SetBinding(ShortNameProperty, GroupShortNameBinding.Clone());
+ }
+
+ if (_shortNames != null)
+ _shortNames.Reset();
+ }
+
+ static void SetGroup(TItem item, TemplatedItemsList<TView, TItem> group)
+ {
+ if (item == null)
+ throw new ArgumentNullException("item");
+
+ item.SetValue(GroupProperty, group);
+ }
+
+ static void SetIndex(TItem item, int index)
+ {
+ if (item == null)
+ return;
+
+ item.SetValue(IndexProperty, index);
+ }
+
+ void SplitCollectionChangedItems(NotifyCollectionChangedEventArgs e)
+ {
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ if (e.NewStartingIndex < 0)
+ goto default;
+
+ for (var i = 0; i < e.NewItems.Count; i++)
+ OnProxyCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, e.NewItems[i], e.NewStartingIndex + i), false);
+
+ break;
+
+ case NotifyCollectionChangedAction.Remove:
+ if (e.OldStartingIndex < 0)
+ goto default;
+
+ for (var i = 0; i < e.OldItems.Count; i++)
+ OnProxyCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, e.OldItems[i], e.OldStartingIndex + i), false);
+
+ break;
+
+ case NotifyCollectionChangedAction.Replace:
+ if (e.OldStartingIndex < 0)
+ goto default;
+
+ for (var i = 0; i < e.OldItems.Count; i++)
+ OnProxyCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, e.NewItems[i], e.OldItems[i], e.OldStartingIndex + i), false);
+
+ break;
+
+ default:
+ OnProxyCollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset), false);
+ break;
+ }
+ }
+
+ void UnhookAndClear()
+ {
+ for (var i = 0; i < _templatedObjects.Count; i++)
+ {
+ TItem item = _templatedObjects[i];
+ if (item == null)
+ continue;
+
+ UnhookItem(item);
+ }
+
+ _templatedObjects.Clear();
+ }
+
+ async void UnhookItem(TItem item)
+ {
+ SetIndex(item, -1);
+ _itemsView.UnhookContent(item);
+
+ //Hack: the cell could still be visible on iOS because the cells are reloaded after this unhook
+ //this causes some visual updates caused by a null datacontext and default values like IsVisible
+ if (Device.OS == TargetPlatform.iOS && CachingStrategy == ListViewCachingStrategy.RetainElement)
+ await Task.Delay(100);
+ item.BindingContext = null;
+ }
+
+ class ShortNamesProxy : IReadOnlyList<string>, INotifyCollectionChanged, IDisposable
+ {
+ readonly HashSet<TemplatedItemsList<TView, TItem>> _attachedItems = new HashSet<TemplatedItemsList<TView, TItem>>();
+ readonly TemplatedItemsList<TView, TItem> _itemsList;
+
+ readonly Dictionary<TemplatedItemsList<TView, TItem>, string> _oldNames = new Dictionary<TemplatedItemsList<TView, TItem>, string>();
+
+ bool _disposed;
+
+ internal ShortNamesProxy(TemplatedItemsList<TView, TItem> itemsList)
+ {
+ _itemsList = itemsList;
+ _itemsList.CollectionChanged += OnItemsListCollectionChanged;
+ }
+
+ public void Dispose()
+ {
+ if (_disposed)
+ return;
+ _disposed = true;
+
+ _itemsList.CollectionChanged -= OnItemsListCollectionChanged;
+
+ ResetCore(false);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public IEnumerator<string> GetEnumerator()
+ {
+ if (_itemsList._groupedItems == null)
+ yield break;
+
+ foreach (TemplatedItemsList<TView, TItem> item in _itemsList._groupedItems.Values)
+ {
+ AttachList(item);
+ yield return item.ShortName;
+ }
+ }
+
+ public event NotifyCollectionChangedEventHandler CollectionChanged;
+
+ public int Count
+ {
+ get { return _itemsList._groupedItems.Count; }
+ }
+
+ public string this[int index]
+ {
+ get
+ {
+ TemplatedItemsList<TView, TItem> list = _itemsList._groupedItems[index];
+ AttachList(list);
+
+ return list.ShortName;
+ }
+ }
+
+ public void Reset()
+ {
+ ResetCore(true);
+ }
+
+ void AttachList(TemplatedItemsList<TView, TItem> list)
+ {
+ if (_attachedItems.Contains(list))
+ return;
+
+ list.PropertyChanging += OnChildListPropertyChanging;
+ list.PropertyChanged += OnChildListPropertyChanged;
+ _attachedItems.Add(list);
+ }
+
+ List<string> ConvertItems(IList list)
+ {
+ var newList = new List<string>(list.Count);
+ newList.AddRange(list.Cast<TemplatedItemsList<TView, TItem>>().Select(tl => tl.ShortName));
+ return newList;
+ }
+
+ void OnChildListPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName != ShortNameProperty.PropertyName)
+ return;
+
+ var list = (TemplatedItemsList<TView, TItem>)sender;
+ string old = _oldNames[list];
+ _oldNames.Remove(list);
+
+ int index = _itemsList._groupedItems.Values.IndexOf(list);
+
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, list.ShortName, old, index));
+ }
+
+ void OnChildListPropertyChanging(object sender, PropertyChangingEventArgs e)
+ {
+ if (e.PropertyName != ShortNameProperty.PropertyName)
+ return;
+
+ var list = (TemplatedItemsList<TView, TItem>)sender;
+ _oldNames[list] = list.ShortName;
+ }
+
+ void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
+ {
+ NotifyCollectionChangedEventHandler changed = CollectionChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ void OnItemsListCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, ConvertItems(e.NewItems), e.NewStartingIndex);
+ break;
+
+ case NotifyCollectionChangedAction.Move:
+ e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, ConvertItems(e.OldItems), e.NewStartingIndex, e.OldStartingIndex);
+ break;
+
+ case NotifyCollectionChangedAction.Remove:
+ e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, ConvertItems(e.OldItems), e.OldStartingIndex);
+ break;
+
+ case NotifyCollectionChangedAction.Replace:
+ e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, ConvertItems(e.NewItems), ConvertItems(e.OldItems), e.OldStartingIndex);
+ break;
+ }
+
+ OnCollectionChanged(e);
+ }
+
+ void ResetCore(bool raiseReset)
+ {
+ foreach (TemplatedItemsList<TView, TItem> list in _attachedItems)
+ {
+ list.PropertyChanged -= OnChildListPropertyChanged;
+ list.PropertyChanging -= OnChildListPropertyChanging;
+ }
+
+ _attachedItems.Clear();
+
+ if (raiseReset)
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TemplatedPage.cs b/Xamarin.Forms.Core/TemplatedPage.cs
new file mode 100644
index 00000000..69c2d58b
--- /dev/null
+++ b/Xamarin.Forms.Core/TemplatedPage.cs
@@ -0,0 +1,38 @@
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ public class TemplatedPage : Page, IControlTemplated
+ {
+ public static readonly BindableProperty ControlTemplateProperty = BindableProperty.Create(nameof(ControlTemplate), typeof(ControlTemplate), typeof(TemplatedPage), null,
+ propertyChanged: TemplateUtilities.OnControlTemplateChanged);
+
+ public ControlTemplate ControlTemplate
+ {
+ get { return (ControlTemplate)GetValue(ControlTemplateProperty); }
+ set { SetValue(ControlTemplateProperty, value); }
+ }
+
+ IList<Element> IControlTemplated.InternalChildren => InternalChildren;
+
+ internal override void ComputeConstraintForView(View view)
+ {
+ LayoutOptions vOptions = view.VerticalOptions;
+ LayoutOptions hOptions = view.HorizontalOptions;
+
+ var result = LayoutConstraint.None;
+ if (vOptions.Alignment == LayoutAlignment.Fill)
+ result |= LayoutConstraint.VerticallyFixed;
+ if (hOptions.Alignment == LayoutAlignment.Fill)
+ result |= LayoutConstraint.HorizontallyFixed;
+
+ view.ComputedConstraint = result;
+ }
+
+ internal override void SetChildInheritedBindingContext(Element child, object context)
+ {
+ if (ControlTemplate == null)
+ base.SetChildInheritedBindingContext(child, context);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TemplatedView.cs b/Xamarin.Forms.Core/TemplatedView.cs
new file mode 100644
index 00000000..30dadb92
--- /dev/null
+++ b/Xamarin.Forms.Core/TemplatedView.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ public class TemplatedView : Layout, IControlTemplated
+ {
+ public static readonly BindableProperty ControlTemplateProperty = BindableProperty.Create(nameof(ControlTemplate), typeof(ControlTemplate), typeof(TemplatedView), null,
+ propertyChanged: TemplateUtilities.OnControlTemplateChanged);
+
+ public ControlTemplate ControlTemplate
+ {
+ get { return (ControlTemplate)GetValue(ControlTemplateProperty); }
+ set { SetValue(ControlTemplateProperty, value); }
+ }
+
+ IList<Element> IControlTemplated.InternalChildren => InternalChildren;
+
+ protected override void LayoutChildren(double x, double y, double width, double height)
+ {
+ for (var i = 0; i < LogicalChildren.Count; i++)
+ {
+ Element element = LogicalChildren[i];
+ var child = element as View;
+ if (child != null)
+ LayoutChildIntoBoundingRegion(child, new Rectangle(x, y, width, height));
+ }
+ }
+
+ [Obsolete("Use OnMeasure")]
+ protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ double widthRequest = WidthRequest;
+ double heightRequest = HeightRequest;
+ var childRequest = new SizeRequest();
+
+ if ((widthRequest == -1 || heightRequest == -1) && InternalChildren.Count > 0)
+ {
+ childRequest = ((View)InternalChildren[0]).Measure(widthConstraint, heightConstraint, MeasureFlags.IncludeMargins);
+ }
+
+ return new SizeRequest
+ {
+ Request = new Size { Width = widthRequest != -1 ? widthRequest : childRequest.Request.Width, Height = heightRequest != -1 ? heightRequest : childRequest.Request.Height },
+ Minimum = childRequest.Minimum
+ };
+ }
+
+ internal override void ComputeConstraintForView(View view)
+ {
+ bool isFixedHorizontally = (Constraint & LayoutConstraint.HorizontallyFixed) != 0;
+ bool isFixedVertically = (Constraint & LayoutConstraint.VerticallyFixed) != 0;
+
+ var result = LayoutConstraint.None;
+ if (isFixedVertically && view.VerticalOptions.Alignment == LayoutAlignment.Fill)
+ result |= LayoutConstraint.VerticallyFixed;
+ if (isFixedHorizontally && view.HorizontalOptions.Alignment == LayoutAlignment.Fill)
+ result |= LayoutConstraint.HorizontallyFixed;
+ view.ComputedConstraint = result;
+ }
+
+ internal override void SetChildInheritedBindingContext(Element child, object context)
+ {
+ if (ControlTemplate == null)
+ base.SetChildInheritedBindingContext(child, context);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TextAlignment.cs b/Xamarin.Forms.Core/TextAlignment.cs
new file mode 100644
index 00000000..cee32c97
--- /dev/null
+++ b/Xamarin.Forms.Core/TextAlignment.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Forms
+{
+ public enum TextAlignment
+ {
+ Start,
+ Center,
+ End
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TextChangedEventArgs.cs b/Xamarin.Forms.Core/TextChangedEventArgs.cs
new file mode 100644
index 00000000..dc4202ae
--- /dev/null
+++ b/Xamarin.Forms.Core/TextChangedEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class TextChangedEventArgs : EventArgs
+ {
+ public TextChangedEventArgs(string oldTextValue, string newTextValue)
+ {
+ OldTextValue = oldTextValue;
+ NewTextValue = newTextValue;
+ }
+
+ public string NewTextValue { get; private set; }
+
+ public string OldTextValue { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TextKeyboard.cs b/Xamarin.Forms.Core/TextKeyboard.cs
new file mode 100644
index 00000000..d2d1942f
--- /dev/null
+++ b/Xamarin.Forms.Core/TextKeyboard.cs
@@ -0,0 +1,6 @@
+namespace Xamarin.Forms
+{
+ internal sealed class TextKeyboard : Keyboard
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Thickness.cs b/Xamarin.Forms.Core/Thickness.cs
new file mode 100644
index 00000000..ee1850df
--- /dev/null
+++ b/Xamarin.Forms.Core/Thickness.cs
@@ -0,0 +1,92 @@
+using System.Diagnostics;
+
+namespace Xamarin.Forms
+{
+ [DebuggerDisplay("Left={Left}, Top={Top}, Right={Right}, Bottom={Bottom}, HorizontalThickness={HorizontalThickness}, VerticalThickness={VerticalThickness}")]
+ [TypeConverter(typeof(ThicknessTypeConverter))]
+ public struct Thickness
+ {
+ public double Left { get; set; }
+
+ public double Top { get; set; }
+
+ public double Right { get; set; }
+
+ public double Bottom { get; set; }
+
+ public double HorizontalThickness
+ {
+ get { return Left + Right; }
+ }
+
+ public double VerticalThickness
+ {
+ get { return Top + Bottom; }
+ }
+
+ internal bool IsDefault
+ {
+ get { return Left == 0 && Top == 0 && Right == 0 && Left == 0; }
+ }
+
+ public Thickness(double uniformSize) : this(uniformSize, uniformSize, uniformSize, uniformSize)
+ {
+ }
+
+ public Thickness(double horizontalSize, double verticalSize) : this(horizontalSize, verticalSize, horizontalSize, verticalSize)
+ {
+ }
+
+ public Thickness(double left, double top, double right, double bottom) : this()
+ {
+ Left = left;
+ Top = top;
+ Right = right;
+ Bottom = bottom;
+ }
+
+ public static implicit operator Thickness(Size size)
+ {
+ return new Thickness(size.Width, size.Height, size.Width, size.Height);
+ }
+
+ public static implicit operator Thickness(double uniformSize)
+ {
+ return new Thickness(uniformSize);
+ }
+
+ bool Equals(Thickness other)
+ {
+ return Left.Equals(other.Left) && Top.Equals(other.Top) && Right.Equals(other.Right) && Bottom.Equals(other.Bottom);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ return false;
+ return obj is Thickness && Equals((Thickness)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hashCode = Left.GetHashCode();
+ hashCode = (hashCode * 397) ^ Top.GetHashCode();
+ hashCode = (hashCode * 397) ^ Right.GetHashCode();
+ hashCode = (hashCode * 397) ^ Bottom.GetHashCode();
+ return hashCode;
+ }
+ }
+
+ public static bool operator ==(Thickness left, Thickness right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Thickness left, Thickness right)
+ {
+ return !left.Equals(right);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ThicknessTypeConverter.cs b/Xamarin.Forms.Core/ThicknessTypeConverter.cs
new file mode 100644
index 00000000..5e79d25c
--- /dev/null
+++ b/Xamarin.Forms.Core/ThicknessTypeConverter.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Globalization;
+
+namespace Xamarin.Forms
+{
+ public class ThicknessTypeConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString(string value)
+ {
+ if (value != null)
+ {
+ double l, t, r, b;
+ string[] thickness = value.Split(',');
+ switch (thickness.Length)
+ {
+ case 1:
+ if (double.TryParse(thickness[0], NumberStyles.Number, CultureInfo.InvariantCulture, out l))
+ return new Thickness(l);
+ break;
+ case 2:
+ if (double.TryParse(thickness[0], NumberStyles.Number, CultureInfo.InvariantCulture, out l) && double.TryParse(thickness[1], NumberStyles.Number, CultureInfo.InvariantCulture, out t))
+ return new Thickness(l, t);
+ break;
+ case 4:
+ if (double.TryParse(thickness[0], NumberStyles.Number, CultureInfo.InvariantCulture, out l) && double.TryParse(thickness[1], NumberStyles.Number, CultureInfo.InvariantCulture, out t) &&
+ double.TryParse(thickness[2], NumberStyles.Number, CultureInfo.InvariantCulture, out r) && double.TryParse(thickness[3], NumberStyles.Number, CultureInfo.InvariantCulture, out b))
+ return new Thickness(l, t, r, b);
+ break;
+ }
+ }
+
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(Thickness)));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Ticker.cs b/Xamarin.Forms.Core/Ticker.cs
new file mode 100644
index 00000000..ed828f8a
--- /dev/null
+++ b/Xamarin.Forms.Core/Ticker.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+
+namespace Xamarin.Forms
+{
+ internal class Ticker
+ {
+ static Ticker s_ticker;
+ readonly Stopwatch _stopwatch;
+ readonly SynchronizationContext _sync;
+ readonly List<Tuple<int, Func<long, bool>>> _timeouts;
+
+ readonly ITimer _timer;
+ int _count;
+ bool _enabled;
+
+ internal Ticker()
+ {
+ _sync = SynchronizationContext.Current;
+ _count = 0;
+ _timer = Device.PlatformServices.CreateTimer(HandleElapsed, null, Timeout.Infinite, Timeout.Infinite);
+ _timeouts = new List<Tuple<int, Func<long, bool>>>();
+
+ _stopwatch = new Stopwatch();
+ }
+
+ public static Ticker Default
+ {
+ internal set { s_ticker = value; }
+ get { return s_ticker ?? (s_ticker = new Ticker()); }
+ }
+
+ public virtual int Insert(Func<long, bool> timeout)
+ {
+ _count++;
+ _timeouts.Add(new Tuple<int, Func<long, bool>>(_count, timeout));
+
+ if (!_enabled)
+ {
+ _enabled = true;
+ Enable();
+ }
+
+ return _count;
+ }
+
+ public virtual void Remove(int handle)
+ {
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ _timeouts.RemoveAll(t => t.Item1 == handle);
+
+ if (!_timeouts.Any())
+ {
+ _enabled = false;
+ Disable();
+ }
+ });
+ }
+
+ protected virtual void DisableTimer()
+ {
+ _timer.Change(Timeout.Infinite, Timeout.Infinite);
+ }
+
+ protected virtual void EnableTimer()
+ {
+ _timer.Change(16, 16);
+ }
+
+ protected void SendSignals(int timestep = -1)
+ {
+ long step = timestep >= 0 ? timestep : _stopwatch.ElapsedMilliseconds;
+ _stopwatch.Reset();
+ _stopwatch.Start();
+
+ var localCopy = new List<Tuple<int, Func<long, bool>>>(_timeouts);
+ foreach (Tuple<int, Func<long, bool>> timeout in localCopy)
+ {
+ bool remove = !timeout.Item2(step);
+ if (remove)
+ _timeouts.RemoveAll(t => t.Item1 == timeout.Item1);
+ }
+
+ if (!_timeouts.Any())
+ {
+ _enabled = false;
+ Disable();
+ }
+ }
+
+ void Disable()
+ {
+ _stopwatch.Reset();
+ DisableTimer();
+ }
+
+ void Enable()
+ {
+ _stopwatch.Start();
+ EnableTimer();
+ }
+
+ void HandleElapsed(object state)
+ {
+ if (_timeouts.Count > 0)
+ {
+ _sync.Post(o => SendSignals(), null);
+ _stopwatch.Reset();
+ _stopwatch.Start();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TimePicker.cs b/Xamarin.Forms.Core/TimePicker.cs
new file mode 100644
index 00000000..a9cf2e19
--- /dev/null
+++ b/Xamarin.Forms.Core/TimePicker.cs
@@ -0,0 +1,29 @@
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_TimePickerRenderer))]
+ public class TimePicker : View
+ {
+ public static readonly BindableProperty FormatProperty = BindableProperty.Create("Format", typeof(string), typeof(TimePicker), "t");
+
+ public static readonly BindableProperty TimeProperty = BindableProperty.Create("Time", typeof(TimeSpan), typeof(TimePicker), new TimeSpan(0), BindingMode.TwoWay, (bindable, value) =>
+ {
+ var time = (TimeSpan)value;
+ return time.TotalHours < 24 && time.TotalMilliseconds >= 0;
+ });
+
+ public string Format
+ {
+ get { return (string)GetValue(FormatProperty); }
+ set { SetValue(FormatProperty, value); }
+ }
+
+ public TimeSpan Time
+ {
+ get { return (TimeSpan)GetValue(TimeProperty); }
+ set { SetValue(TimeProperty, value); }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ToggledEventArgs.cs b/Xamarin.Forms.Core/ToggledEventArgs.cs
new file mode 100644
index 00000000..227e93cb
--- /dev/null
+++ b/Xamarin.Forms.Core/ToggledEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class ToggledEventArgs : EventArgs
+ {
+ public ToggledEventArgs(bool value)
+ {
+ Value = value;
+ }
+
+ public bool Value { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Toolbar.cs b/Xamarin.Forms.Core/Toolbar.cs
new file mode 100644
index 00000000..4405d1f6
--- /dev/null
+++ b/Xamarin.Forms.Core/Toolbar.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ // Marked as internal for 1.0 release until we are ready to release this
+ [RenderWith(typeof(_ToolbarRenderer))]
+ internal class Toolbar : View
+ {
+ readonly List<ToolbarItem> _items = new List<ToolbarItem>();
+
+ public ReadOnlyCollection<ToolbarItem> Items
+ {
+ get { return new ReadOnlyCollection<ToolbarItem>(_items); }
+ }
+
+ public void Add(ToolbarItem item)
+ {
+ if (_items.Contains(item))
+ return;
+ _items.Add(item);
+ if (ItemAdded != null)
+ ItemAdded(this, new ToolbarItemEventArgs(item));
+ }
+
+ public void Clear()
+ {
+ _items.Clear();
+ }
+
+ public event EventHandler<ToolbarItemEventArgs> ItemAdded;
+
+ public event EventHandler<ToolbarItemEventArgs> ItemRemoved;
+
+ public void Remove(ToolbarItem item)
+ {
+ if (_items.Remove(item))
+ {
+ if (ItemRemoved != null)
+ ItemRemoved(this, new ToolbarItemEventArgs(item));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ToolbarItem.cs b/Xamarin.Forms.Core/ToolbarItem.cs
new file mode 100644
index 00000000..0a0a2e05
--- /dev/null
+++ b/Xamarin.Forms.Core/ToolbarItem.cs
@@ -0,0 +1,57 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class ToolbarItem : MenuItem
+ {
+ static readonly BindableProperty OrderProperty = BindableProperty.Create("Order", typeof(ToolbarItemOrder), typeof(ToolbarItem), ToolbarItemOrder.Default, validateValue: (bo, o) =>
+ {
+ var order = (ToolbarItemOrder)o;
+ return order == ToolbarItemOrder.Default || order == ToolbarItemOrder.Primary || order == ToolbarItemOrder.Secondary;
+ });
+
+ static readonly BindableProperty PriorityProperty = BindableProperty.Create("Priority", typeof(int), typeof(ToolbarItem), 0);
+
+ public ToolbarItem()
+ {
+ }
+
+ public ToolbarItem(string name, string icon, Action activated, ToolbarItemOrder order = ToolbarItemOrder.Default, int priority = 0)
+ {
+ if (activated == null)
+ throw new ArgumentNullException("activated");
+
+ Text = name;
+ Icon = icon;
+ Clicked += (s, e) => activated();
+ Order = order;
+ Priority = priority;
+ }
+
+ [Obsolete("Now that ToolbarItem is based on MenuItem, .Text has replaced .Name")]
+ public string Name
+ {
+ get { return Text; }
+ set { Text = value; }
+ }
+
+ public ToolbarItemOrder Order
+ {
+ get { return (ToolbarItemOrder)GetValue(OrderProperty); }
+ set { SetValue(OrderProperty, value); }
+ }
+
+ public int Priority
+ {
+ get { return (int)GetValue(PriorityProperty); }
+ set { SetValue(PriorityProperty, value); }
+ }
+
+ [Obsolete("Activated has been replaced by the more consistent 'Clicked'")]
+ public event EventHandler Activated
+ {
+ add { Clicked += value; }
+ remove { Clicked -= value; }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ToolbarItemEventArgs.cs b/Xamarin.Forms.Core/ToolbarItemEventArgs.cs
new file mode 100644
index 00000000..8a6e0124
--- /dev/null
+++ b/Xamarin.Forms.Core/ToolbarItemEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ internal class ToolbarItemEventArgs : EventArgs
+ {
+ public ToolbarItemEventArgs(ToolbarItem item)
+ {
+ ToolbarItem = item;
+ }
+
+ public ToolbarItem ToolbarItem { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ToolbarItemOrder.cs b/Xamarin.Forms.Core/ToolbarItemOrder.cs
new file mode 100644
index 00000000..0fbf6c17
--- /dev/null
+++ b/Xamarin.Forms.Core/ToolbarItemOrder.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Forms
+{
+ public enum ToolbarItemOrder
+ {
+ Default,
+ Primary,
+ Secondary
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ToolbarTracker.cs b/Xamarin.Forms.Core/ToolbarTracker.cs
new file mode 100644
index 00000000..74580065
--- /dev/null
+++ b/Xamarin.Forms.Core/ToolbarTracker.cs
@@ -0,0 +1,184 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+
+namespace Xamarin.Forms
+{
+ internal class ToolbarTracker
+ {
+ int _masterDetails;
+ Page _target;
+
+ public IEnumerable<Page> AdditionalTargets { get; set; }
+
+ public bool HaveMasterDetail
+ {
+ get { return _masterDetails > 0; }
+ }
+
+ public bool SeparateMasterDetail { get; set; }
+
+ public Page Target
+ {
+ get { return _target; }
+ set
+ {
+ if (_target == value)
+ return;
+
+ UntrackTarget(_target);
+ _target = value;
+
+ if (_target != null)
+ TrackTarget(_target);
+ EmitCollectionChanged();
+ }
+ }
+
+ public IEnumerable<ToolbarItem> ToolbarItems
+ {
+ get
+ {
+ if (Target == null)
+ return Enumerable.Empty<ToolbarItem>();
+ IEnumerable<ToolbarItem> items = GetCurrentToolbarItems(Target);
+ if (AdditionalTargets != null)
+ items = items.Concat(AdditionalTargets.SelectMany(t => t.ToolbarItems));
+
+ return items.OrderBy(ti => ti.Priority);
+ }
+ }
+
+ public event EventHandler CollectionChanged;
+
+ void EmitCollectionChanged()
+ {
+ if (CollectionChanged != null)
+ CollectionChanged(this, EventArgs.Empty);
+ }
+
+ IEnumerable<ToolbarItem> GetCurrentToolbarItems(Page page)
+ {
+ var result = new List<ToolbarItem>();
+ result.AddRange(page.ToolbarItems);
+
+ if (page is MasterDetailPage)
+ {
+ var masterDetail = (MasterDetailPage)page;
+ if (SeparateMasterDetail)
+ {
+ if (masterDetail.IsPresented)
+ {
+ if (masterDetail.Master != null)
+ result.AddRange(GetCurrentToolbarItems(masterDetail.Master));
+ }
+ else
+ {
+ if (masterDetail.Detail != null)
+ result.AddRange(GetCurrentToolbarItems(masterDetail.Detail));
+ }
+ }
+ else
+ {
+ if (masterDetail.Master != null)
+ result.AddRange(GetCurrentToolbarItems(masterDetail.Master));
+ if (masterDetail.Detail != null)
+ result.AddRange(GetCurrentToolbarItems(masterDetail.Detail));
+ }
+ }
+ else if (page is IPageContainer<Page>)
+ {
+ var container = (IPageContainer<Page>)page;
+ if (container.CurrentPage != null)
+ result.AddRange(GetCurrentToolbarItems(container.CurrentPage));
+ }
+
+ return result;
+ }
+
+ void OnChildAdded(object sender, ElementEventArgs eventArgs)
+ {
+ var page = eventArgs.Element as Page;
+ if (page == null)
+ return;
+
+ RegisterChildPage(page);
+ }
+
+ void OnChildRemoved(object sender, ElementEventArgs eventArgs)
+ {
+ var page = eventArgs.Element as Page;
+ if (page == null)
+ return;
+
+ UnregisterChildPage(page);
+ }
+
+ void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
+ {
+ EmitCollectionChanged();
+ }
+
+ void OnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
+ {
+ if (propertyChangedEventArgs.PropertyName == NavigationPage.CurrentPageProperty.PropertyName || propertyChangedEventArgs.PropertyName == MasterDetailPage.IsPresentedProperty.PropertyName ||
+ propertyChangedEventArgs.PropertyName == "Detail" || propertyChangedEventArgs.PropertyName == "Master")
+ {
+ EmitCollectionChanged();
+ }
+ }
+
+ void RegisterChildPage(Page page)
+ {
+ if (page is MasterDetailPage)
+ _masterDetails++;
+
+ ((ObservableCollection<ToolbarItem>)page.ToolbarItems).CollectionChanged += OnCollectionChanged;
+ page.PropertyChanged += OnPropertyChanged;
+ }
+
+ void TrackTarget(Page page)
+ {
+ if (page == null)
+ return;
+
+ if (page is MasterDetailPage)
+ _masterDetails++;
+
+ ((ObservableCollection<ToolbarItem>)page.ToolbarItems).CollectionChanged += OnCollectionChanged;
+ page.Descendants().OfType<Page>().ForEach(RegisterChildPage);
+
+ page.DescendantAdded += OnChildAdded;
+ page.DescendantRemoved += OnChildRemoved;
+ page.PropertyChanged += OnPropertyChanged;
+ }
+
+ void UnregisterChildPage(Page page)
+ {
+ if (page is MasterDetailPage)
+ _masterDetails--;
+
+ ((ObservableCollection<ToolbarItem>)page.ToolbarItems).CollectionChanged -= OnCollectionChanged;
+ page.PropertyChanged -= OnPropertyChanged;
+ }
+
+ void UntrackTarget(Page page)
+ {
+ if (page == null)
+ return;
+
+ if (page is MasterDetailPage)
+ _masterDetails--;
+
+ ((ObservableCollection<ToolbarItem>)page.ToolbarItems).CollectionChanged -= OnCollectionChanged;
+ page.Descendants().OfType<Page>().ForEach(UnregisterChildPage);
+
+ page.DescendantAdded -= OnChildAdded;
+ page.DescendantRemoved -= OnChildRemoved;
+ page.PropertyChanged -= OnPropertyChanged;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TrackableCollection.cs b/Xamarin.Forms.Core/TrackableCollection.cs
new file mode 100644
index 00000000..959007ad
--- /dev/null
+++ b/Xamarin.Forms.Core/TrackableCollection.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.ObjectModel;
+
+namespace Xamarin.Forms
+{
+ internal class TrackableCollection<T> : ObservableCollection<T>
+ {
+ public event EventHandler Clearing;
+
+ protected override void ClearItems()
+ {
+ Clearing?.Invoke(this, EventArgs.Empty);
+ base.ClearItems();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Tweener.cs b/Xamarin.Forms.Core/Tweener.cs
new file mode 100644
index 00000000..73ed7853
--- /dev/null
+++ b/Xamarin.Forms.Core/Tweener.cs
@@ -0,0 +1,124 @@
+//
+// Tweener.cs
+//
+// Author:
+// Jason Smith <jason.smith@xamarin.com>
+//
+// Copyright (c) 2012 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace Xamarin.Forms
+{
+ internal class Tweener
+ {
+ long _lastMilliseconds;
+
+ int _timer;
+
+ public Tweener(uint length)
+ {
+ Value = 0.0f;
+ Length = length;
+ Loop = false;
+ }
+
+ public AnimatableKey Handle { get; set; }
+
+ public uint Length { get; }
+
+ public bool Loop { get; set; }
+
+ public double Value { get; private set; }
+
+ public event EventHandler Finished;
+
+ public void Pause()
+ {
+ if (_timer != 0)
+ {
+ Ticker.Default.Remove(_timer);
+ _timer = 0;
+ }
+ }
+
+ public void Start()
+ {
+ Pause();
+
+ _lastMilliseconds = 0;
+ _timer = Ticker.Default.Insert(step =>
+ {
+ long ms = step + _lastMilliseconds;
+
+ Value = Math.Min(1.0f, ms / (double)Length);
+
+ _lastMilliseconds = ms;
+
+ if (ValueUpdated != null)
+ ValueUpdated(this, EventArgs.Empty);
+
+ if (Value >= 1.0f)
+ {
+ if (Loop)
+ {
+ _lastMilliseconds = 0;
+ Value = 0.0f;
+ return true;
+ }
+
+ if (Finished != null)
+ Finished(this, EventArgs.Empty);
+ Value = 0.0f;
+ _timer = 0;
+ return false;
+ }
+ return true;
+ });
+ }
+
+ public void Stop()
+ {
+ Pause();
+ Value = 1.0f;
+ if (Finished != null)
+ Finished(this, EventArgs.Empty);
+ Value = 0.0f;
+ }
+
+ public event EventHandler ValueUpdated;
+
+ ~Tweener()
+ {
+ if (_timer != 0)
+ {
+ try
+ {
+ Ticker.Default.Remove(_timer);
+ }
+ catch (InvalidOperationException)
+ {
+ }
+ }
+ _timer = 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TypeConverter.cs b/Xamarin.Forms.Core/TypeConverter.cs
new file mode 100644
index 00000000..7bbf221f
--- /dev/null
+++ b/Xamarin.Forms.Core/TypeConverter.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Globalization;
+
+namespace Xamarin.Forms
+{
+ public abstract class TypeConverter
+ {
+ public virtual bool CanConvertFrom(Type sourceType)
+ {
+ if (sourceType == null)
+ throw new ArgumentNullException("sourceType");
+
+ return sourceType == typeof(string);
+ }
+
+ [Obsolete("use ConvertFromInvariantString (string)")]
+ public virtual object ConvertFrom(object o)
+ {
+ return null;
+ }
+
+ [Obsolete("use ConvertFromInvariantString (string)")]
+ public virtual object ConvertFrom(CultureInfo culture, object o)
+ {
+ return null;
+ }
+
+ public virtual object ConvertFromInvariantString(string value)
+ {
+ return ConvertFrom(CultureInfo.InvariantCulture, value);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TypeConverterAttribute.cs b/Xamarin.Forms.Core/TypeConverterAttribute.cs
new file mode 100644
index 00000000..261b00e0
--- /dev/null
+++ b/Xamarin.Forms.Core/TypeConverterAttribute.cs
@@ -0,0 +1,74 @@
+//
+// System.ComponentModel.TypeConverterAttribute
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
+//
+// (C) 2002 Ximian, Inc (http://www.ximian.com)
+// (C) 2003 Andreas Nahr
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public sealed class TypeConverterAttribute : Attribute
+ {
+ internal static string[] TypeConvertersType = { "Xamarin.Forms.TypeConverterAttribute", "System.ComponentModel.TypeConverterAttribute" };
+
+ public static readonly TypeConverterAttribute Default = new TypeConverterAttribute();
+
+ public TypeConverterAttribute()
+ {
+ ConverterTypeName = "";
+ }
+
+ public TypeConverterAttribute(string typeName)
+ {
+ ConverterTypeName = typeName;
+ }
+
+ public TypeConverterAttribute(Type type)
+ {
+ ConverterTypeName = type.AssemblyQualifiedName;
+ }
+
+ public string ConverterTypeName { get; }
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is TypeConverterAttribute))
+ return false;
+
+ return ((TypeConverterAttribute)obj).ConverterTypeName == ConverterTypeName;
+ }
+
+ public override int GetHashCode()
+ {
+ return ConverterTypeName.GetHashCode();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TypeTypeConverter.cs b/Xamarin.Forms.Core/TypeTypeConverter.cs
new file mode 100644
index 00000000..115f1d96
--- /dev/null
+++ b/Xamarin.Forms.Core/TypeTypeConverter.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Globalization;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms
+{
+ public sealed class TypeTypeConverter : TypeConverter, IExtendedTypeConverter
+ {
+ [Obsolete("Use ConvertFromInvariantString (string, IServiceProvider)")]
+ object IExtendedTypeConverter.ConvertFrom(CultureInfo culture, object value, IServiceProvider serviceProvider)
+ {
+ return ((IExtendedTypeConverter)this).ConvertFromInvariantString((string)value, serviceProvider);
+ }
+
+ object IExtendedTypeConverter.ConvertFromInvariantString(string value, IServiceProvider serviceProvider)
+ {
+ if (serviceProvider == null)
+ throw new ArgumentNullException("serviceProvider");
+ var typeResolver = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;
+ if (typeResolver == null)
+ throw new ArgumentException("No IXamlTypeResolver in IServiceProvider");
+
+ return typeResolver.Resolve(value, serviceProvider);
+ }
+
+ public override object ConvertFromInvariantString(string value)
+ {
+ throw new NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/UnsolvableConstraintsException.cs b/Xamarin.Forms.Core/UnsolvableConstraintsException.cs
new file mode 100644
index 00000000..40e37812
--- /dev/null
+++ b/Xamarin.Forms.Core/UnsolvableConstraintsException.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class UnsolvableConstraintsException : Exception
+ {
+ public UnsolvableConstraintsException(string message) : base(message)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/UriImageSource.cs b/Xamarin.Forms.Core/UriImageSource.cs
new file mode 100644
index 00000000..f6b3ead1
--- /dev/null
+++ b/Xamarin.Forms.Core/UriImageSource.cs
@@ -0,0 +1,223 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ public sealed class UriImageSource : ImageSource
+ {
+ internal const string CacheName = "ImageLoaderCache";
+
+ public static readonly BindableProperty UriProperty = BindableProperty.Create("Uri", typeof(Uri), typeof(UriImageSource), default(Uri),
+ propertyChanged: (bindable, oldvalue, newvalue) => ((UriImageSource)bindable).OnUriChanged(), validateValue: (bindable, value) => value == null || ((Uri)value).IsAbsoluteUri);
+
+ static readonly IIsolatedStorageFile Store = Device.PlatformServices.GetUserStoreForApplication();
+
+ static readonly object s_syncHandle = new object();
+ static readonly Dictionary<string, LockingSemaphore> s_semaphores = new Dictionary<string, LockingSemaphore>();
+
+ TimeSpan _cacheValidity = TimeSpan.FromDays(1);
+
+ bool _cachingEnabled = true;
+
+ static UriImageSource()
+ {
+ if (!Store.GetDirectoryExistsAsync(CacheName).Result)
+ Store.CreateDirectoryAsync(CacheName).Wait();
+ }
+
+ public TimeSpan CacheValidity
+ {
+ get { return _cacheValidity; }
+ set
+ {
+ if (_cacheValidity == value)
+ return;
+
+ OnPropertyChanging();
+ _cacheValidity = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public bool CachingEnabled
+ {
+ get { return _cachingEnabled; }
+ set
+ {
+ if (_cachingEnabled == value)
+ return;
+
+ OnPropertyChanging();
+ _cachingEnabled = value;
+ OnPropertyChanged();
+ }
+ }
+
+ [TypeConverter(typeof(UriTypeConverter))]
+ public Uri Uri
+ {
+ get { return (Uri)GetValue(UriProperty); }
+ set { SetValue(UriProperty, value); }
+ }
+
+ internal async Task<Stream> GetStreamAsync(CancellationToken userToken = default(CancellationToken))
+ {
+ OnLoadingStarted();
+ userToken.Register(CancellationTokenSource.Cancel);
+ Stream stream = null;
+ try
+ {
+ stream = await GetStreamAsync(Uri, CancellationTokenSource.Token);
+ OnLoadingCompleted(false);
+ }
+ catch (OperationCanceledException)
+ {
+ OnLoadingCompleted(true);
+ throw;
+#if DEBUG
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine(e);
+ throw;
+#endif
+ }
+ return stream;
+ }
+
+ static string GetCacheKey(Uri uri)
+ {
+ return Device.PlatformServices.GetMD5Hash(uri.AbsoluteUri);
+ }
+
+ async Task<bool> GetHasLocallyCachedCopyAsync(string key, bool checkValidity = true)
+ {
+ DateTime now = DateTime.UtcNow;
+ DateTime? lastWriteTime = await GetLastWriteTimeUtcAsync(key).ConfigureAwait(false);
+ return lastWriteTime.HasValue && now - lastWriteTime.Value < CacheValidity;
+ }
+
+ static async Task<DateTime?> GetLastWriteTimeUtcAsync(string key)
+ {
+ string path = Path.Combine(CacheName, key);
+ if (!await Store.GetFileExistsAsync(path).ConfigureAwait(false))
+ return null;
+
+ return (await Store.GetLastWriteTimeAsync(path).ConfigureAwait(false)).UtcDateTime;
+ }
+
+ async Task<Stream> GetStreamAsync(Uri uri, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ Stream stream;
+ if (!CachingEnabled)
+ {
+ try
+ {
+ stream = await Device.GetStreamAsync(uri, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception)
+ {
+ stream = null;
+ }
+ }
+ else
+ stream = await GetStreamFromCacheAsync(uri, cancellationToken).ConfigureAwait(false);
+ return stream;
+ }
+
+ async Task<Stream> GetStreamAsyncUnchecked(string key, Uri uri, CancellationToken cancellationToken)
+ {
+ if (await GetHasLocallyCachedCopyAsync(key).ConfigureAwait(false))
+ {
+ var retry = 5;
+ while (retry >= 0)
+ {
+ int backoff;
+ try
+ {
+ Stream result = await Store.OpenFileAsync(Path.Combine(CacheName, key), FileMode.Open, FileAccess.Read).ConfigureAwait(false);
+ return result;
+ }
+ catch (IOException)
+ {
+ // iOS seems to not like 2 readers opening the file at the exact same time, back off for random amount of time
+ backoff = new Random().Next(1, 5);
+ retry--;
+ }
+
+ if (backoff > 0)
+ {
+ await Task.Delay(backoff);
+ }
+ }
+ return null;
+ }
+
+ Stream stream;
+ try
+ {
+ stream = await Device.GetStreamAsync(uri, cancellationToken).ConfigureAwait(false);
+ if (stream == null)
+ return null;
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+
+ Stream writeStream = await Store.OpenFileAsync(Path.Combine(CacheName, key), FileMode.Create, FileAccess.Write).ConfigureAwait(false);
+ await stream.CopyToAsync(writeStream, 16384, cancellationToken).ConfigureAwait(false);
+ if (writeStream != null)
+ writeStream.Dispose();
+
+ stream.Dispose();
+
+ return await Store.OpenFileAsync(Path.Combine(CacheName, key), FileMode.Open, FileAccess.Read).ConfigureAwait(false);
+ }
+
+ async Task<Stream> GetStreamFromCacheAsync(Uri uri, CancellationToken cancellationToken)
+ {
+ string key = GetCacheKey(uri);
+ LockingSemaphore sem;
+ lock(s_syncHandle)
+ {
+ if (s_semaphores.ContainsKey(key))
+ sem = s_semaphores[key];
+ else
+ s_semaphores.Add(key, sem = new LockingSemaphore(1));
+ }
+
+ try
+ {
+ await sem.WaitAsync(cancellationToken);
+ Stream stream = await GetStreamAsyncUnchecked(key, uri, cancellationToken);
+ if (stream == null)
+ {
+ sem.Release();
+ return null;
+ }
+ var wrapped = new StreamWrapper(stream);
+ wrapped.Disposed += (o, e) => sem.Release();
+ return wrapped;
+ }
+ catch (OperationCanceledException)
+ {
+ sem.Release();
+ throw;
+ }
+ }
+
+ void OnUriChanged()
+ {
+ if (CancellationTokenSource != null)
+ CancellationTokenSource.Cancel();
+ OnSourceChanged();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/UriTypeConverter.cs b/Xamarin.Forms.Core/UriTypeConverter.cs
new file mode 100644
index 00000000..0a24cab3
--- /dev/null
+++ b/Xamarin.Forms.Core/UriTypeConverter.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class UriTypeConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString(string value)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ return null;
+ return new Uri(value, UriKind.RelativeOrAbsolute);
+ }
+
+ bool CanConvert(Type type)
+ {
+ if (type == typeof(string))
+ return true;
+ if (type == typeof(Uri))
+ return true;
+
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/UrlKeyboard.cs b/Xamarin.Forms.Core/UrlKeyboard.cs
new file mode 100644
index 00000000..8266d95e
--- /dev/null
+++ b/Xamarin.Forms.Core/UrlKeyboard.cs
@@ -0,0 +1,6 @@
+namespace Xamarin.Forms
+{
+ internal sealed class UrlKeyboard : Keyboard
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/UrlWebViewSource.cs b/Xamarin.Forms.Core/UrlWebViewSource.cs
new file mode 100644
index 00000000..72541045
--- /dev/null
+++ b/Xamarin.Forms.Core/UrlWebViewSource.cs
@@ -0,0 +1,19 @@
+namespace Xamarin.Forms
+{
+ public class UrlWebViewSource : WebViewSource
+ {
+ public static readonly BindableProperty UrlProperty = BindableProperty.Create("Url", typeof(string), typeof(UrlWebViewSource), default(string),
+ propertyChanged: (bindable, oldvalue, newvalue) => ((UrlWebViewSource)bindable).OnSourceChanged());
+
+ public string Url
+ {
+ get { return (string)GetValue(UrlProperty); }
+ set { SetValue(UrlProperty, value); }
+ }
+
+ internal override void Load(IWebViewRenderer renderer)
+ {
+ renderer.LoadUrl(Url);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ValueChangedEventArgs.cs b/Xamarin.Forms.Core/ValueChangedEventArgs.cs
new file mode 100644
index 00000000..8ea718c4
--- /dev/null
+++ b/Xamarin.Forms.Core/ValueChangedEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class ValueChangedEventArgs : EventArgs
+ {
+ public ValueChangedEventArgs(double oldValue, double newValue)
+ {
+ OldValue = oldValue;
+ NewValue = newValue;
+ }
+
+ public double NewValue { get; private set; }
+
+ public double OldValue { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Vec2.cs b/Xamarin.Forms.Core/Vec2.cs
new file mode 100644
index 00000000..2c7512d3
--- /dev/null
+++ b/Xamarin.Forms.Core/Vec2.cs
@@ -0,0 +1,14 @@
+namespace Xamarin.Forms
+{
+ public struct Vec2
+ {
+ public double X;
+ public double Y;
+
+ public Vec2(double x, double y)
+ {
+ X = x;
+ Y = y;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/View.cs b/Xamarin.Forms.Core/View.cs
new file mode 100644
index 00000000..d03c74bb
--- /dev/null
+++ b/Xamarin.Forms.Core/View.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
+
+namespace Xamarin.Forms
+{
+ public class View : VisualElement, IViewController
+ {
+ public static readonly BindableProperty VerticalOptionsProperty = BindableProperty.Create("VerticalOptions", typeof(LayoutOptions), typeof(View), LayoutOptions.Fill,
+ propertyChanged: (bindable, oldvalue, newvalue) => ((View)bindable).InvalidateMeasure(InvalidationTrigger.VerticalOptionsChanged));
+
+ public static readonly BindableProperty HorizontalOptionsProperty = BindableProperty.Create("HorizontalOptions", typeof(LayoutOptions), typeof(View), LayoutOptions.Fill,
+ propertyChanged: (bindable, oldvalue, newvalue) => ((View)bindable).InvalidateMeasure(InvalidationTrigger.HorizontalOptionsChanged));
+
+ public static readonly BindableProperty MarginProperty = BindableProperty.Create("Margin", typeof(Thickness), typeof(View), default(Thickness), propertyChanged: MarginPropertyChanged);
+
+ readonly ObservableCollection<IGestureRecognizer> _gestureRecognizers = new ObservableCollection<IGestureRecognizer>();
+
+ protected internal View()
+ {
+ _gestureRecognizers.CollectionChanged += (sender, args) =>
+ {
+ switch (args.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ foreach (IElement item in args.NewItems.OfType<IElement>())
+ {
+ ValidateGesture(item as IGestureRecognizer);
+ item.Parent = this;
+ }
+ break;
+ case NotifyCollectionChangedAction.Remove:
+ foreach (IElement item in args.OldItems.OfType<IElement>())
+ item.Parent = null;
+ break;
+ case NotifyCollectionChangedAction.Replace:
+ foreach (IElement item in args.NewItems.OfType<IElement>())
+ {
+ ValidateGesture(item as IGestureRecognizer);
+ item.Parent = this;
+ }
+ foreach (IElement item in args.OldItems.OfType<IElement>())
+ item.Parent = null;
+ break;
+ case NotifyCollectionChangedAction.Reset:
+ foreach (IElement item in _gestureRecognizers.OfType<IElement>())
+ item.Parent = this;
+ break;
+ }
+ };
+ }
+
+ public IList<IGestureRecognizer> GestureRecognizers
+ {
+ get { return _gestureRecognizers; }
+ }
+
+ public LayoutOptions HorizontalOptions
+ {
+ get { return (LayoutOptions)GetValue(HorizontalOptionsProperty); }
+ set { SetValue(HorizontalOptionsProperty, value); }
+ }
+
+ public Thickness Margin
+ {
+ get { return (Thickness)GetValue(MarginProperty); }
+ set { SetValue(MarginProperty, value); }
+ }
+
+ public LayoutOptions VerticalOptions
+ {
+ get { return (LayoutOptions)GetValue(VerticalOptionsProperty); }
+ set { SetValue(VerticalOptionsProperty, value); }
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ var gotBindingContext = false;
+ object bc = null;
+
+ for (var i = 0; i < GestureRecognizers.Count; i++)
+ {
+ var bo = GestureRecognizers[i] as BindableObject;
+ if (bo == null)
+ continue;
+
+ if (!gotBindingContext)
+ {
+ bc = BindingContext;
+ gotBindingContext = true;
+ }
+
+ SetInheritedBindingContext(bo, bc);
+ }
+
+ base.OnBindingContextChanged();
+ }
+
+ static void MarginPropertyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ ((View)bindable).InvalidateMeasure(InvalidationTrigger.MarginChanged);
+ }
+
+ void ValidateGesture(IGestureRecognizer gesture)
+ {
+ if (gesture == null)
+ return;
+ if (gesture is PinchGestureRecognizer && _gestureRecognizers.GetGesturesFor<PinchGestureRecognizer>().Count() > 1)
+ throw new InvalidOperationException($"Only one {nameof(PinchGestureRecognizer)} per view is allowed");
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ViewExtensions.cs b/Xamarin.Forms.Core/ViewExtensions.cs
new file mode 100644
index 00000000..14a70868
--- /dev/null
+++ b/Xamarin.Forms.Core/ViewExtensions.cs
@@ -0,0 +1,197 @@
+using System;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms
+{
+ public static class ViewExtensions
+ {
+ public static void CancelAnimations(VisualElement view)
+ {
+ if (view == null)
+ throw new ArgumentNullException("view");
+ view.AbortAnimation("LayoutTo");
+ view.AbortAnimation("TranslateTo");
+ view.AbortAnimation("RotateTo");
+ view.AbortAnimation("RotateYTo");
+ view.AbortAnimation("RotateXTo");
+ view.AbortAnimation("ScaleTo");
+ view.AbortAnimation("FadeTo");
+ view.AbortAnimation("SizeTo");
+ }
+
+ public static Task<bool> FadeTo(this VisualElement view, double opacity, uint length = 250, Easing easing = null)
+ {
+ if (view == null)
+ throw new ArgumentNullException("view");
+ if (easing == null)
+ easing = Easing.Linear;
+
+ var tcs = new TaskCompletionSource<bool>();
+ var weakView = new WeakReference<VisualElement>(view);
+ Action<double> fade = f =>
+ {
+ VisualElement v;
+ if (weakView.TryGetTarget(out v))
+ v.Opacity = f;
+ };
+
+ new Animation(fade, view.Opacity, opacity, easing).Commit(view, "FadeTo", 16, length, finished: (f, a) => tcs.SetResult(a));
+
+ return tcs.Task;
+ }
+
+ public static Task<bool> LayoutTo(this VisualElement view, Rectangle bounds, uint length = 250, Easing easing = null)
+ {
+ if (view == null)
+ throw new ArgumentNullException("view");
+ if (easing == null)
+ easing = Easing.Linear;
+
+ var tcs = new TaskCompletionSource<bool>();
+ Rectangle start = view.Bounds;
+ Func<double, Rectangle> computeBounds = progress =>
+ {
+ double x = start.X + (bounds.X - start.X) * progress;
+ double y = start.Y + (bounds.Y - start.Y) * progress;
+ double w = start.Width + (bounds.Width - start.Width) * progress;
+ double h = start.Height + (bounds.Height - start.Height) * progress;
+
+ return new Rectangle(x, y, w, h);
+ };
+ var weakView = new WeakReference<VisualElement>(view);
+ Action<double> layout = f =>
+ {
+ VisualElement v;
+ if (weakView.TryGetTarget(out v))
+ v.Layout(computeBounds(f));
+ };
+ new Animation(layout, 0, 1, easing).Commit(view, "LayoutTo", 16, length, finished: (f, a) => tcs.SetResult(a));
+
+ return tcs.Task;
+ }
+
+ public static Task<bool> RelRotateTo(this VisualElement view, double drotation, uint length = 250, Easing easing = null)
+ {
+ if (view == null)
+ throw new ArgumentNullException("view");
+ return view.RotateTo(view.Rotation + drotation, length, easing);
+ }
+
+ public static Task<bool> RelScaleTo(this VisualElement view, double dscale, uint length = 250, Easing easing = null)
+ {
+ if (view == null)
+ throw new ArgumentNullException("view");
+ return view.ScaleTo(view.Scale + dscale, length, easing);
+ }
+
+ public static Task<bool> RotateTo(this VisualElement view, double rotation, uint length = 250, Easing easing = null)
+ {
+ if (view == null)
+ throw new ArgumentNullException("view");
+ if (easing == null)
+ easing = Easing.Linear;
+
+ var tcs = new TaskCompletionSource<bool>();
+ var weakView = new WeakReference<VisualElement>(view);
+ Action<double> rotate = f =>
+ {
+ VisualElement v;
+ if (weakView.TryGetTarget(out v))
+ v.Rotation = f;
+ };
+
+ new Animation(rotate, view.Rotation, rotation, easing).Commit(view, "RotateTo", 16, length, finished: (f, a) => tcs.SetResult(a));
+
+ return tcs.Task;
+ }
+
+ public static Task<bool> RotateXTo(this VisualElement view, double rotation, uint length = 250, Easing easing = null)
+ {
+ if (view == null)
+ throw new ArgumentNullException("view");
+ if (easing == null)
+ easing = Easing.Linear;
+
+ var tcs = new TaskCompletionSource<bool>();
+ var weakView = new WeakReference<VisualElement>(view);
+ Action<double> rotatex = f =>
+ {
+ VisualElement v;
+ if (weakView.TryGetTarget(out v))
+ v.RotationX = f;
+ };
+
+ new Animation(rotatex, view.RotationX, rotation, easing).Commit(view, "RotateXTo", 16, length, finished: (f, a) => tcs.SetResult(a));
+
+ return tcs.Task;
+ }
+
+ public static Task<bool> RotateYTo(this VisualElement view, double rotation, uint length = 250, Easing easing = null)
+ {
+ if (view == null)
+ throw new ArgumentNullException("view");
+ if (easing == null)
+ easing = Easing.Linear;
+
+ var tcs = new TaskCompletionSource<bool>();
+ var weakView = new WeakReference<VisualElement>(view);
+ Action<double> rotatey = f =>
+ {
+ VisualElement v;
+ if (weakView.TryGetTarget(out v))
+ v.RotationY = f;
+ };
+
+ new Animation(rotatey, view.RotationY, rotation, easing).Commit(view, "RotateYTo", 16, length, finished: (f, a) => tcs.SetResult(a));
+
+ return tcs.Task;
+ }
+
+ public static Task<bool> ScaleTo(this VisualElement view, double scale, uint length = 250, Easing easing = null)
+ {
+ if (view == null)
+ throw new ArgumentNullException("view");
+ if (easing == null)
+ easing = Easing.Linear;
+
+ var tcs = new TaskCompletionSource<bool>();
+ var weakView = new WeakReference<VisualElement>(view);
+ Action<double> _scale = f =>
+ {
+ VisualElement v;
+ if (weakView.TryGetTarget(out v))
+ v.Scale = f;
+ };
+
+ new Animation(_scale, view.Scale, scale, easing).Commit(view, "ScaleTo", 16, length, finished: (f, a) => tcs.SetResult(a));
+
+ return tcs.Task;
+ }
+
+ public static Task<bool> TranslateTo(this VisualElement view, double x, double y, uint length = 250, Easing easing = null)
+ {
+ if (view == null)
+ throw new ArgumentNullException("view");
+ easing = easing ?? Easing.Linear;
+
+ var tcs = new TaskCompletionSource<bool>();
+ var weakView = new WeakReference<VisualElement>(view);
+ Action<double> translateX = f =>
+ {
+ VisualElement v;
+ if (weakView.TryGetTarget(out v))
+ v.TranslationX = f;
+ };
+ Action<double> translateY = f =>
+ {
+ VisualElement v;
+ if (weakView.TryGetTarget(out v))
+ v.TranslationY = f;
+ };
+ new Animation { { 0, 1, new Animation(translateX, view.TranslationX, x) }, { 0, 1, new Animation(translateY, view.TranslationY, y) } }.Commit(view, "TranslateTo", 16, length, easing,
+ (f, a) => tcs.SetResult(a));
+
+ return tcs.Task;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ViewState.cs b/Xamarin.Forms.Core/ViewState.cs
new file mode 100644
index 00000000..e7db908a
--- /dev/null
+++ b/Xamarin.Forms.Core/ViewState.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [Flags]
+ public enum ViewState
+ {
+ Default = 0,
+ Prelight = 1,
+ Pressed = 1 << 1
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/VisualElement.cs b/Xamarin.Forms.Core/VisualElement.cs
new file mode 100644
index 00000000..16efe730
--- /dev/null
+++ b/Xamarin.Forms.Core/VisualElement.cs
@@ -0,0 +1,764 @@
+using System;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms
+{
+ public partial class VisualElement : Element, IAnimatable, IVisualElementController, IResourcesProvider
+ {
+ internal static readonly BindablePropertyKey NavigationPropertyKey = BindableProperty.CreateReadOnly("Navigation", typeof(INavigation), typeof(VisualElement), default(INavigation));
+
+ public static readonly BindableProperty NavigationProperty = NavigationPropertyKey.BindableProperty;
+
+ public static readonly BindableProperty InputTransparentProperty = BindableProperty.Create("InputTransparent", typeof(bool), typeof(VisualElement), default(bool));
+
+ public static readonly BindableProperty IsEnabledProperty = BindableProperty.Create("IsEnabled", typeof(bool), typeof(VisualElement), true);
+
+ static readonly BindablePropertyKey XPropertyKey = BindableProperty.CreateReadOnly("X", typeof(double), typeof(VisualElement), default(double));
+
+ public static readonly BindableProperty XProperty = XPropertyKey.BindableProperty;
+
+ static readonly BindablePropertyKey YPropertyKey = BindableProperty.CreateReadOnly("Y", typeof(double), typeof(VisualElement), default(double));
+
+ public static readonly BindableProperty YProperty = YPropertyKey.BindableProperty;
+
+ public static readonly BindableProperty AnchorXProperty = BindableProperty.Create("AnchorX", typeof(double), typeof(VisualElement), .5d);
+
+ public static readonly BindableProperty AnchorYProperty = BindableProperty.Create("AnchorY", typeof(double), typeof(VisualElement), .5d);
+
+ public static readonly BindableProperty TranslationXProperty = BindableProperty.Create("TranslationX", typeof(double), typeof(VisualElement), 0d);
+
+ public static readonly BindableProperty TranslationYProperty = BindableProperty.Create("TranslationY", typeof(double), typeof(VisualElement), 0d);
+
+ static readonly BindablePropertyKey WidthPropertyKey = BindableProperty.CreateReadOnly("Width", typeof(double), typeof(VisualElement), -1d,
+ coerceValue: (bindable, value) => double.IsNaN((double)value) ? 0d : value);
+
+ public static readonly BindableProperty WidthProperty = WidthPropertyKey.BindableProperty;
+
+ static readonly BindablePropertyKey HeightPropertyKey = BindableProperty.CreateReadOnly("Height", typeof(double), typeof(VisualElement), -1d,
+ coerceValue: (bindable, value) => double.IsNaN((double)value) ? 0d : value);
+
+ public static readonly BindableProperty HeightProperty = HeightPropertyKey.BindableProperty;
+
+ public static readonly BindableProperty RotationProperty = BindableProperty.Create("Rotation", typeof(double), typeof(VisualElement), default(double));
+
+ public static readonly BindableProperty RotationXProperty = BindableProperty.Create("RotationX", typeof(double), typeof(VisualElement), default(double));
+
+ public static readonly BindableProperty RotationYProperty = BindableProperty.Create("RotationY", typeof(double), typeof(VisualElement), default(double));
+
+ public static readonly BindableProperty ScaleProperty = BindableProperty.Create("Scale", typeof(double), typeof(VisualElement), 1d);
+
+ public static readonly BindableProperty IsVisibleProperty = BindableProperty.Create("IsVisible", typeof(bool), typeof(VisualElement), true,
+ propertyChanged: (bindable, oldvalue, newvalue) => ((VisualElement)bindable).OnIsVisibleChanged((bool)oldvalue, (bool)newvalue));
+
+ public static readonly BindableProperty OpacityProperty = BindableProperty.Create("Opacity", typeof(double), typeof(VisualElement), 1d, coerceValue: (bindable, value) => ((double)value).Clamp(0, 1));
+
+ public static readonly BindableProperty BackgroundColorProperty = BindableProperty.Create("BackgroundColor", typeof(Color), typeof(VisualElement), Color.Default);
+
+ internal static readonly BindablePropertyKey BehaviorsPropertyKey = BindableProperty.CreateReadOnly("Behaviors", typeof(IList<Behavior>), typeof(VisualElement), default(IList<Behavior>),
+ defaultValueCreator: bindable =>
+ {
+ var collection = new AttachedCollection<Behavior>();
+ collection.AttachTo(bindable);
+ return collection;
+ });
+
+ public static readonly BindableProperty BehaviorsProperty = BehaviorsPropertyKey.BindableProperty;
+
+ internal static readonly BindablePropertyKey TriggersPropertyKey = BindableProperty.CreateReadOnly("Triggers", typeof(IList<TriggerBase>), typeof(VisualElement), default(IList<TriggerBase>),
+ defaultValueCreator: bindable =>
+ {
+ var collection = new AttachedCollection<TriggerBase>();
+ collection.AttachTo(bindable);
+ return collection;
+ });
+
+ public static readonly BindableProperty TriggersProperty = TriggersPropertyKey.BindableProperty;
+
+ public static readonly BindableProperty StyleProperty = BindableProperty.Create("Style", typeof(Style), typeof(VisualElement), default(Style),
+ propertyChanged: (bindable, oldvalue, newvalue) => ((VisualElement)bindable)._mergedStyle.Style = (Style)newvalue);
+
+ public static readonly BindableProperty WidthRequestProperty = BindableProperty.Create("WidthRequest", typeof(double), typeof(VisualElement), -1d, propertyChanged: OnRequestChanged);
+
+ public static readonly BindableProperty HeightRequestProperty = BindableProperty.Create("HeightRequest", typeof(double), typeof(VisualElement), -1d, propertyChanged: OnRequestChanged);
+
+ public static readonly BindableProperty MinimumWidthRequestProperty = BindableProperty.Create("MinimumWidthRequest", typeof(double), typeof(VisualElement), -1d, propertyChanged: OnRequestChanged);
+
+ public static readonly BindableProperty MinimumHeightRequestProperty = BindableProperty.Create("MinimumHeightRequest", typeof(double), typeof(VisualElement), -1d, propertyChanged: OnRequestChanged);
+
+ internal static readonly BindablePropertyKey IsFocusedPropertyKey = BindableProperty.CreateReadOnly("IsFocused", typeof(bool), typeof(VisualElement), default(bool),
+ propertyChanged: OnIsFocusedPropertyChanged);
+
+ public static readonly BindableProperty IsFocusedProperty = IsFocusedPropertyKey.BindableProperty;
+
+ readonly Dictionary<Size, SizeRequest> _measureCache = new Dictionary<Size, SizeRequest>();
+
+ readonly MergedStyle _mergedStyle;
+
+ int _batched;
+ LayoutConstraint _computedConstraint;
+
+ bool _isInNativeLayout;
+
+ bool _isNativeStateConsistent = true;
+
+ bool _isPlatformEnabled;
+
+ double _mockHeight = -1;
+
+ double _mockWidth = -1;
+
+ double _mockX = -1;
+
+ double _mockY = -1;
+
+ ResourceDictionary _resources;
+ LayoutConstraint _selfConstraint;
+
+ internal VisualElement()
+ {
+ Navigation = new NavigationProxy();
+ _mergedStyle = new MergedStyle(GetType(), this);
+ }
+
+ public double AnchorX
+ {
+ get { return (double)GetValue(AnchorXProperty); }
+ set { SetValue(AnchorXProperty, value); }
+ }
+
+ public double AnchorY
+ {
+ get { return (double)GetValue(AnchorYProperty); }
+ set { SetValue(AnchorYProperty, value); }
+ }
+
+ public Color BackgroundColor
+ {
+ get { return (Color)GetValue(BackgroundColorProperty); }
+ set { SetValue(BackgroundColorProperty, value); }
+ }
+
+ public IList<Behavior> Behaviors
+ {
+ get { return (IList<Behavior>)GetValue(BehaviorsProperty); }
+ }
+
+ public Rectangle Bounds
+ {
+ get { return new Rectangle(X, Y, Width, Height); }
+ private set
+ {
+ if (value.X == X && value.Y == Y && value.Height == Height && value.Width == Width)
+ return;
+ BatchBegin();
+ X = value.X;
+ Y = value.Y;
+ SetSize(value.Width, value.Height);
+ BatchCommit();
+ }
+ }
+
+ public double Height
+ {
+ get { return _mockHeight == -1 ? (double)GetValue(HeightProperty) : _mockHeight; }
+ private set { SetValue(HeightPropertyKey, value); }
+ }
+
+ public double HeightRequest
+ {
+ get { return (double)GetValue(HeightRequestProperty); }
+ set { SetValue(HeightRequestProperty, value); }
+ }
+
+ public bool InputTransparent
+ {
+ get { return (bool)GetValue(InputTransparentProperty); }
+ set { SetValue(InputTransparentProperty, value); }
+ }
+
+ public bool IsEnabled
+ {
+ get { return (bool)GetValue(IsEnabledProperty); }
+ set { SetValue(IsEnabledProperty, value); }
+ }
+
+ public bool IsFocused
+ {
+ get { return (bool)GetValue(IsFocusedProperty); }
+ }
+
+ public bool IsVisible
+ {
+ get { return (bool)GetValue(IsVisibleProperty); }
+ set { SetValue(IsVisibleProperty, value); }
+ }
+
+ public double MinimumHeightRequest
+ {
+ get { return (double)GetValue(MinimumHeightRequestProperty); }
+ set { SetValue(MinimumHeightRequestProperty, value); }
+ }
+
+ public double MinimumWidthRequest
+ {
+ get { return (double)GetValue(MinimumWidthRequestProperty); }
+ set { SetValue(MinimumWidthRequestProperty, value); }
+ }
+
+ public INavigation Navigation
+ {
+ get { return (INavigation)GetValue(NavigationProperty); }
+ internal set { SetValue(NavigationPropertyKey, value); }
+ }
+
+ public double Opacity
+ {
+ get { return (double)GetValue(OpacityProperty); }
+ set { SetValue(OpacityProperty, value); }
+ }
+
+ public double Rotation
+ {
+ get { return (double)GetValue(RotationProperty); }
+ set { SetValue(RotationProperty, value); }
+ }
+
+ public double RotationX
+ {
+ get { return (double)GetValue(RotationXProperty); }
+ set { SetValue(RotationXProperty, value); }
+ }
+
+ public double RotationY
+ {
+ get { return (double)GetValue(RotationYProperty); }
+ set { SetValue(RotationYProperty, value); }
+ }
+
+ public double Scale
+ {
+ get { return (double)GetValue(ScaleProperty); }
+ set { SetValue(ScaleProperty, value); }
+ }
+
+ public Style Style
+ {
+ get { return (Style)GetValue(StyleProperty); }
+ set { SetValue(StyleProperty, value); }
+ }
+
+ public string StyleClass
+ {
+ get { return _mergedStyle.StyleClass; }
+ set { _mergedStyle.StyleClass = value; }
+ }
+
+ public double TranslationX
+ {
+ get { return (double)GetValue(TranslationXProperty); }
+ set { SetValue(TranslationXProperty, value); }
+ }
+
+ public double TranslationY
+ {
+ get { return (double)GetValue(TranslationYProperty); }
+ set { SetValue(TranslationYProperty, value); }
+ }
+
+ public IList<TriggerBase> Triggers
+ {
+ get { return (IList<TriggerBase>)GetValue(TriggersProperty); }
+ }
+
+ public double Width
+ {
+ get { return _mockWidth == -1 ? (double)GetValue(WidthProperty) : _mockWidth; }
+ private set { SetValue(WidthPropertyKey, value); }
+ }
+
+ public double WidthRequest
+ {
+ get { return (double)GetValue(WidthRequestProperty); }
+ set { SetValue(WidthRequestProperty, value); }
+ }
+
+ public double X
+ {
+ get { return _mockX == -1 ? (double)GetValue(XProperty) : _mockX; }
+ private set { SetValue(XPropertyKey, value); }
+ }
+
+ public double Y
+ {
+ get { return _mockY == -1 ? (double)GetValue(YProperty) : _mockY; }
+ private set { SetValue(YPropertyKey, value); }
+ }
+
+ internal bool Batched
+ {
+ get { return _batched > 0; }
+ }
+
+ internal LayoutConstraint ComputedConstraint
+ {
+ get { return _computedConstraint; }
+ set
+ {
+ if (_computedConstraint == value)
+ return;
+
+ LayoutConstraint oldConstraint = Constraint;
+ _computedConstraint = value;
+ LayoutConstraint newConstraint = Constraint;
+ if (oldConstraint != newConstraint)
+ OnConstraintChanged(oldConstraint, newConstraint);
+ }
+ }
+
+ internal LayoutConstraint Constraint
+ {
+ get { return ComputedConstraint | SelfConstraint; }
+ }
+
+ internal bool DisableLayout { get; set; }
+
+ internal bool IsInNativeLayout
+ {
+ get
+ {
+ if (_isInNativeLayout)
+ return true;
+
+ Element parent = RealParent;
+ while (parent != null)
+ {
+ var visualElement = parent as VisualElement;
+ if (visualElement != null && visualElement.IsInNativeLayout)
+ return true;
+ parent = parent.RealParent;
+ }
+
+ return false;
+ }
+ set { _isInNativeLayout = value; }
+ }
+
+ internal bool IsNativeStateConsistent
+ {
+ get { return _isNativeStateConsistent; }
+ set
+ {
+ if (_isNativeStateConsistent == value)
+ return;
+ _isNativeStateConsistent = value;
+ if (value && IsPlatformEnabled)
+ InvalidateMeasure(InvalidationTrigger.RendererReady);
+ }
+ }
+
+ internal bool IsPlatformEnabled
+ {
+ get { return _isPlatformEnabled; }
+ set
+ {
+ if (value == _isPlatformEnabled)
+ return;
+
+ _isPlatformEnabled = value;
+ if (value && IsNativeStateConsistent)
+ InvalidateMeasure(InvalidationTrigger.RendererReady);
+
+ OnIsPlatformEnabledChanged();
+ }
+ }
+
+ internal NavigationProxy NavigationProxy
+ {
+ get { return Navigation as NavigationProxy; }
+ }
+
+ internal LayoutConstraint SelfConstraint
+ {
+ get { return _selfConstraint; }
+ set
+ {
+ if (_selfConstraint == value)
+ return;
+
+ LayoutConstraint oldConstraint = Constraint;
+ _selfConstraint = value;
+ LayoutConstraint newConstraint = Constraint;
+ if (oldConstraint != newConstraint)
+ {
+ OnConstraintChanged(oldConstraint, newConstraint);
+ }
+ }
+ }
+
+ public void BatchBegin()
+ {
+ _batched++;
+ }
+
+ public void BatchCommit()
+ {
+ _batched = Math.Max(0, _batched - 1);
+ if (!Batched && BatchCommitted != null)
+ BatchCommitted(this, new EventArg<VisualElement>(this));
+ }
+
+ public ResourceDictionary Resources
+ {
+ get { return _resources; }
+ set
+ {
+ if (_resources == value)
+ return;
+ OnPropertyChanging();
+ if (_resources != null)
+ ((IResourceDictionary)_resources).ValuesChanged -= OnResourcesChanged;
+ _resources = value;
+ OnResourcesChanged(value);
+ if (_resources != null)
+ ((IResourceDictionary)_resources).ValuesChanged += OnResourcesChanged;
+ OnPropertyChanged();
+ }
+ }
+
+ void IVisualElementController.NativeSizeChanged()
+ {
+ InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+
+ public event EventHandler ChildrenReordered;
+
+ public bool Focus()
+ {
+ if (IsFocused)
+ return true;
+
+ if (FocusChangeRequested == null)
+ return false;
+
+ var arg = new FocusRequestArgs { Focus = true };
+ FocusChangeRequested(this, arg);
+ return arg.Result;
+ }
+
+ public event EventHandler<FocusEventArgs> Focused;
+
+ [Obsolete("Use Measure")]
+ public virtual SizeRequest GetSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ SizeRequest cachedResult;
+ var constraintSize = new Size(widthConstraint, heightConstraint);
+ if (_measureCache.TryGetValue(constraintSize, out cachedResult))
+ {
+ return cachedResult;
+ }
+
+ double widthRequest = WidthRequest;
+ double heightRequest = HeightRequest;
+ if (widthRequest >= 0)
+ widthConstraint = Math.Min(widthConstraint, widthRequest);
+ if (heightRequest >= 0)
+ heightConstraint = Math.Min(heightConstraint, heightRequest);
+
+ SizeRequest result = OnMeasure(widthConstraint, heightConstraint);
+ bool hasMinimum = result.Minimum != result.Request;
+ Size request = result.Request;
+ Size minimum = result.Minimum;
+
+ if (heightRequest != -1)
+ {
+ request.Height = heightRequest;
+ if (!hasMinimum)
+ minimum.Height = heightRequest;
+ }
+
+ if (widthRequest != -1)
+ {
+ request.Width = widthRequest;
+ if (!hasMinimum)
+ minimum.Width = widthRequest;
+ }
+
+ double minimumHeightRequest = MinimumHeightRequest;
+ double minimumWidthRequest = MinimumWidthRequest;
+
+ if (minimumHeightRequest != -1)
+ minimum.Height = minimumHeightRequest;
+ if (minimumWidthRequest != -1)
+ minimum.Width = minimumWidthRequest;
+
+ minimum.Height = Math.Min(request.Height, minimum.Height);
+ minimum.Width = Math.Min(request.Width, minimum.Width);
+
+ var r = new SizeRequest(request, minimum);
+
+ if (r.Request.Width > 0 && r.Request.Height > 0)
+ {
+ _measureCache[constraintSize] = r;
+ }
+
+ return r;
+ }
+
+ public void Layout(Rectangle bounds)
+ {
+ Bounds = bounds;
+ }
+
+ public SizeRequest Measure(double widthConstraint, double heightConstraint, MeasureFlags flags = MeasureFlags.None)
+ {
+ SizeRequest result = GetSizeRequest(widthConstraint, heightConstraint);
+
+ if ((flags & MeasureFlags.IncludeMargins) != 0)
+ {
+ Thickness margin = default(Thickness);
+ var view = this as View;
+ if (view != null)
+ margin = view.Margin;
+
+ if (!margin.IsDefault)
+ {
+ result.Minimum = new Size(result.Minimum.Width + margin.HorizontalThickness, result.Minimum.Height + margin.VerticalThickness);
+ result.Request = new Size(result.Request.Width + margin.HorizontalThickness, result.Request.Height + margin.VerticalThickness);
+ }
+ }
+
+ return result;
+ }
+
+ public event EventHandler MeasureInvalidated;
+
+ public event EventHandler SizeChanged;
+
+ public void Unfocus()
+ {
+ if (!IsFocused)
+ return;
+
+ EventHandler<FocusRequestArgs> unfocus = FocusChangeRequested;
+ if (unfocus != null)
+ {
+ unfocus(this, new FocusRequestArgs());
+ }
+ }
+
+ public event EventHandler<FocusEventArgs> Unfocused;
+
+ protected virtual void InvalidateMeasure()
+ {
+ InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+
+ protected override void OnChildAdded(Element child)
+ {
+ base.OnChildAdded(child);
+ var view = child as View;
+ if (view != null)
+ ComputeConstraintForView(view);
+ }
+
+ protected override void OnChildRemoved(Element child)
+ {
+ base.OnChildRemoved(child);
+ var view = child as View;
+ if (view != null)
+ view.ComputedConstraint = LayoutConstraint.None;
+ }
+
+ protected void OnChildrenReordered()
+ {
+ if (ChildrenReordered != null)
+ ChildrenReordered(this, EventArgs.Empty);
+ }
+
+ protected virtual SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
+ {
+ return OnSizeRequest(widthConstraint, heightConstraint);
+ }
+
+ protected override void OnParentSet()
+ {
+ base.OnParentSet();
+
+ if (ParentView != null)
+ {
+ NavigationProxy.Inner = ParentView.NavigationProxy;
+ }
+ else
+ {
+ NavigationProxy.Inner = null;
+ }
+ }
+
+ protected virtual void OnSizeAllocated(double width, double height)
+ {
+ }
+
+ [Obsolete("Use OnMeasure")]
+ protected virtual SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ if (Platform == null || !IsPlatformEnabled)
+ {
+ return new SizeRequest(new Size(-1, -1));
+ }
+ return Platform.GetNativeSize(this, widthConstraint, heightConstraint);
+ }
+
+ protected void SizeAllocated(double width, double height)
+ {
+ OnSizeAllocated(width, height);
+ }
+
+ internal event EventHandler<EventArg<VisualElement>> BatchCommitted;
+
+ internal void ComputeConstrainsForChildren()
+ {
+ for (var i = 0; i < LogicalChildren.Count; i++)
+ {
+ var child = LogicalChildren[i] as View;
+ if (child != null)
+ ComputeConstraintForView(child);
+ }
+ }
+
+ internal virtual void ComputeConstraintForView(View view)
+ {
+ view.ComputedConstraint = LayoutConstraint.None;
+ }
+
+ internal event EventHandler<FocusRequestArgs> FocusChangeRequested;
+
+ internal virtual void InvalidateMeasure(InvalidationTrigger trigger)
+ {
+ _measureCache.Clear();
+ MeasureInvalidated?.Invoke(this, new InvalidationEventArgs(trigger));
+ }
+
+ internal void MockBounds(Rectangle bounds)
+ {
+ _mockX = bounds.X;
+ _mockY = bounds.Y;
+ _mockWidth = bounds.Width;
+ _mockHeight = bounds.Height;
+ }
+
+ internal virtual void OnConstraintChanged(LayoutConstraint oldConstraint, LayoutConstraint newConstraint)
+ {
+ ComputeConstrainsForChildren();
+ }
+
+ internal virtual void OnIsPlatformEnabledChanged()
+ {
+ }
+
+ internal virtual void OnIsVisibleChanged(bool oldValue, bool newValue)
+ {
+ InvalidateMeasure(InvalidationTrigger.Undefined);
+ }
+
+ internal override void OnParentResourcesChanged(IEnumerable<KeyValuePair<string, object>> values)
+ {
+ if (values == null)
+ return;
+
+ if (Resources == null || Resources.Count == 0)
+ {
+ base.OnParentResourcesChanged(values);
+ return;
+ }
+
+ var innerKeys = new HashSet<string>();
+ var changedResources = new List<KeyValuePair<string, object>>();
+ foreach (KeyValuePair<string, object> c in Resources)
+ innerKeys.Add(c.Key);
+ foreach (KeyValuePair<string, object> value in values)
+ {
+ if (innerKeys.Add(value.Key))
+ changedResources.Add(value);
+ else if (value.Key.StartsWith(Style.StyleClassPrefix, StringComparison.Ordinal))
+ {
+ var mergedClassStyles = new List<Style>(Resources[value.Key] as List<Style>);
+ mergedClassStyles.AddRange(value.Value as List<Style>);
+ changedResources.Add(new KeyValuePair<string, object>(value.Key, mergedClassStyles));
+ }
+ }
+ if (changedResources.Count != 0)
+ OnResourcesChanged(changedResources);
+ }
+
+ internal void UnmockBounds()
+ {
+ _mockX = _mockY = _mockWidth = _mockHeight = -1;
+ }
+
+ void OnFocused()
+ {
+ EventHandler<FocusEventArgs> focus = Focused;
+ if (focus != null)
+ focus(this, new FocusEventArgs(this, true));
+ }
+
+ static void OnIsFocusedPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
+ {
+ var element = bindable as VisualElement;
+
+ var isFocused = (bool)newvalue;
+ if (isFocused)
+ {
+ element.OnFocused();
+ }
+ else
+ {
+ element.OnUnfocus();
+ }
+ }
+
+ static void OnRequestChanged(BindableObject bindable, object oldvalue, object newvalue)
+ {
+ var constraint = LayoutConstraint.None;
+ var element = (VisualElement)bindable;
+ if (element.WidthRequest >= 0 && element.MinimumWidthRequest >= 0)
+ {
+ constraint |= LayoutConstraint.HorizontallyFixed;
+ }
+ if (element.HeightRequest >= 0 && element.MinimumHeightRequest >= 0)
+ {
+ constraint |= LayoutConstraint.VerticallyFixed;
+ }
+
+ element.SelfConstraint = constraint;
+ ((VisualElement)bindable).InvalidateMeasure(InvalidationTrigger.SizeRequestChanged);
+ }
+
+ void OnUnfocus()
+ {
+ EventHandler<FocusEventArgs> unFocus = Unfocused;
+ if (unFocus != null)
+ unFocus(this, new FocusEventArgs(this, false));
+ }
+
+ void SetSize(double width, double height)
+ {
+ if (Width == width && Height == height)
+ return;
+
+ Width = width;
+ Height = height;
+
+ SizeAllocated(width, height);
+ if (SizeChanged != null)
+ SizeChanged(this, EventArgs.Empty);
+ }
+
+ internal class FocusRequestArgs : EventArgs
+ {
+ public bool Focus { get; set; }
+
+ public bool Result { get; set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/WeakReferenceExtensions.cs b/Xamarin.Forms.Core/WeakReferenceExtensions.cs
new file mode 100644
index 00000000..e4e883a4
--- /dev/null
+++ b/Xamarin.Forms.Core/WeakReferenceExtensions.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ internal static class WeakReferenceExtensions
+ {
+ internal static bool TryGetTarget<T>(this WeakReference self, out T target) where T : class
+ {
+ if (self == null)
+ throw new ArgumentNullException("self");
+
+ target = (T)self.Target;
+ return target != null;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/WebNavigatedEventArgs.cs b/Xamarin.Forms.Core/WebNavigatedEventArgs.cs
new file mode 100644
index 00000000..29bc3d11
--- /dev/null
+++ b/Xamarin.Forms.Core/WebNavigatedEventArgs.cs
@@ -0,0 +1,12 @@
+namespace Xamarin.Forms
+{
+ public class WebNavigatedEventArgs : WebNavigationEventArgs
+ {
+ public WebNavigatedEventArgs(WebNavigationEvent navigationEvent, WebViewSource source, string url, WebNavigationResult result) : base(navigationEvent, source, url)
+ {
+ Result = result;
+ }
+
+ public WebNavigationResult Result { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/WebNavigatingEventArgs.cs b/Xamarin.Forms.Core/WebNavigatingEventArgs.cs
new file mode 100644
index 00000000..49aa2dc1
--- /dev/null
+++ b/Xamarin.Forms.Core/WebNavigatingEventArgs.cs
@@ -0,0 +1,11 @@
+namespace Xamarin.Forms
+{
+ public class WebNavigatingEventArgs : WebNavigationEventArgs
+ {
+ public WebNavigatingEventArgs(WebNavigationEvent navigationEvent, WebViewSource source, string url) : base(navigationEvent, source, url)
+ {
+ }
+
+ public bool Cancel { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/WebNavigationEvent.cs b/Xamarin.Forms.Core/WebNavigationEvent.cs
new file mode 100644
index 00000000..b47bd0ea
--- /dev/null
+++ b/Xamarin.Forms.Core/WebNavigationEvent.cs
@@ -0,0 +1,10 @@
+namespace Xamarin.Forms
+{
+ public enum WebNavigationEvent
+ {
+ Back = 1,
+ Forward = 2,
+ NewPage = 3,
+ Refresh = 4
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/WebNavigationEventArgs.cs b/Xamarin.Forms.Core/WebNavigationEventArgs.cs
new file mode 100644
index 00000000..e6124c31
--- /dev/null
+++ b/Xamarin.Forms.Core/WebNavigationEventArgs.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class WebNavigationEventArgs : EventArgs
+ {
+ protected WebNavigationEventArgs(WebNavigationEvent navigationEvent, WebViewSource source, string url)
+ {
+ NavigationEvent = navigationEvent;
+ Source = source;
+ Url = url;
+ }
+
+ public WebNavigationEvent NavigationEvent { get; internal set; }
+
+ public WebViewSource Source { get; internal set; }
+
+ public string Url { get; internal set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/WebNavigationResult.cs b/Xamarin.Forms.Core/WebNavigationResult.cs
new file mode 100644
index 00000000..eb0f6e73
--- /dev/null
+++ b/Xamarin.Forms.Core/WebNavigationResult.cs
@@ -0,0 +1,10 @@
+namespace Xamarin.Forms
+{
+ public enum WebNavigationResult
+ {
+ Success = 1,
+ Cancel = 2,
+ Timeout = 3,
+ Failure = 4
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/WebView.cs b/Xamarin.Forms.Core/WebView.cs
new file mode 100644
index 00000000..06a5f72c
--- /dev/null
+++ b/Xamarin.Forms.Core/WebView.cs
@@ -0,0 +1,126 @@
+using System;
+using Xamarin.Forms.Platform;
+
+namespace Xamarin.Forms
+{
+ [RenderWith(typeof(_WebViewRenderer))]
+ public class WebView : View
+ {
+ public static readonly BindableProperty SourceProperty = BindableProperty.Create("Source", typeof(WebViewSource), typeof(WebView), default(WebViewSource),
+ propertyChanging: (bindable, oldvalue, newvalue) =>
+ {
+ var source = oldvalue as WebViewSource;
+ if (source != null)
+ source.SourceChanged -= ((WebView)bindable).OnSourceChanged;
+ }, propertyChanged: (bindable, oldvalue, newvalue) =>
+ {
+ var source = newvalue as WebViewSource;
+ var webview = (WebView)bindable;
+ if (source != null)
+ {
+ source.SourceChanged += webview.OnSourceChanged;
+ SetInheritedBindingContext(source, webview.BindingContext);
+ }
+ });
+
+ static readonly BindablePropertyKey CanGoBackPropertyKey = BindableProperty.CreateReadOnly("CanGoBack", typeof(bool), typeof(WebView), false);
+
+ public static readonly BindableProperty CanGoBackProperty = CanGoBackPropertyKey.BindableProperty;
+
+ static readonly BindablePropertyKey CanGoForwardPropertyKey = BindableProperty.CreateReadOnly("CanGoForward", typeof(bool), typeof(WebView), false);
+
+ public static readonly BindableProperty CanGoForwardProperty = CanGoForwardPropertyKey.BindableProperty;
+
+ public bool CanGoBack
+ {
+ get { return (bool)GetValue(CanGoBackProperty); }
+ internal set { SetValue(CanGoBackPropertyKey, value); }
+ }
+
+ public bool CanGoForward
+ {
+ get { return (bool)GetValue(CanGoForwardProperty); }
+ internal set { SetValue(CanGoForwardPropertyKey, value); }
+ }
+
+ [TypeConverter(typeof(WebViewSourceTypeConverter))]
+ public WebViewSource Source
+ {
+ get { return (WebViewSource)GetValue(SourceProperty); }
+ set { SetValue(SourceProperty, value); }
+ }
+
+ public void Eval(string script)
+ {
+ EventHandler<EventArg<string>> handler = EvalRequested;
+ if (handler != null)
+ handler(this, new EventArg<string>(script));
+ }
+
+ public void GoBack()
+ {
+ EventHandler handler = GoBackRequested;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+
+ public void GoForward()
+ {
+ EventHandler handler = GoForwardRequested;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+
+ public event EventHandler<WebNavigatedEventArgs> Navigated;
+
+ public event EventHandler<WebNavigatingEventArgs> Navigating;
+
+ protected override void OnBindingContextChanged()
+ {
+ base.OnBindingContextChanged();
+
+ WebViewSource source = Source;
+ if (source != null)
+ {
+ SetInheritedBindingContext(source, BindingContext);
+ }
+ }
+
+ protected override void OnPropertyChanged(string propertyName)
+ {
+ if (propertyName == "BindingContext")
+ {
+ WebViewSource source = Source;
+ if (source != null)
+ SetInheritedBindingContext(source, BindingContext);
+ }
+
+ base.OnPropertyChanged(propertyName);
+ }
+
+ protected void OnSourceChanged(object sender, EventArgs e)
+ {
+ OnPropertyChanged(SourceProperty.PropertyName);
+ }
+
+ internal event EventHandler<EventArg<string>> EvalRequested;
+
+ internal event EventHandler GoBackRequested;
+
+ internal event EventHandler GoForwardRequested;
+
+ internal void SendNavigated(WebNavigatedEventArgs args)
+ {
+ EventHandler<WebNavigatedEventArgs> handler = Navigated;
+ if (handler != null)
+ handler(this, args);
+ }
+
+ internal void SendNavigating(WebNavigatingEventArgs args)
+ {
+ EventHandler<WebNavigatingEventArgs> handler = Navigating;
+ if (handler != null)
+ handler(this, args);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/WebViewSource.cs b/Xamarin.Forms.Core/WebViewSource.cs
new file mode 100644
index 00000000..6dc2635f
--- /dev/null
+++ b/Xamarin.Forms.Core/WebViewSource.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public abstract class WebViewSource : BindableObject
+ {
+ public static implicit operator WebViewSource(Uri url)
+ {
+ return new UrlWebViewSource { Url = url?.AbsoluteUri };
+ }
+
+ public static implicit operator WebViewSource(string url)
+ {
+ return new UrlWebViewSource { Url = url };
+ }
+
+ protected void OnSourceChanged()
+ {
+ EventHandler eh = SourceChanged;
+ if (eh != null)
+ eh(this, EventArgs.Empty);
+ }
+
+ internal abstract void Load(IWebViewRenderer renderer);
+
+ internal event EventHandler SourceChanged;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/WebViewSourceTypeConverter.cs b/Xamarin.Forms.Core/WebViewSourceTypeConverter.cs
new file mode 100644
index 00000000..5955eb14
--- /dev/null
+++ b/Xamarin.Forms.Core/WebViewSourceTypeConverter.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class WebViewSourceTypeConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString(string value)
+ {
+ if (value != null)
+ return new UrlWebViewSource { Url = value };
+
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(Color)));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Xamarin.Forms.Core.csproj b/Xamarin.Forms.Core/Xamarin.Forms.Core.csproj
new file mode 100644
index 00000000..ce2a3b57
--- /dev/null
+++ b/Xamarin.Forms.Core/Xamarin.Forms.Core.csproj
@@ -0,0 +1,408 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</ProjectGuid>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <RootNamespace>Xamarin.Forms</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <NoWarn>0618</NoWarn>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>full</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <NoWarn>0618</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="AbsoluteLayoutFlags.cs" />
+ <Compile Include="ActionSheetArguments.cs" />
+ <Compile Include="AlertArguments.cs" />
+ <Compile Include="AnimatableKey.cs" />
+ <Compile Include="Application.cs" />
+ <Compile Include="Aspect.cs" />
+ <Compile Include="BackButtonPressedEventArgs.cs" />
+ <Compile Include="BaseMenuItem.cs" />
+ <Compile Include="BindablePropertyConverter.cs" />
+ <Compile Include="BindingMode.cs" />
+ <Compile Include="BindingTypeConverter.cs" />
+ <Compile Include="BoundsConstraint.cs" />
+ <Compile Include="BoundsTypeConverter.cs" />
+ <Compile Include="CarouselView.cs" />
+ <Compile Include="CastingEnumerator.cs" />
+ <Compile Include="Cells\EntryCell.cs" />
+ <Compile Include="Cells\ImageCell.cs" />
+ <Compile Include="Cells\INativeElementView.cs" />
+ <Compile Include="ChatKeyboard.cs" />
+ <Compile Include="ChildCollectionChangedEventArgs.cs" />
+ <Compile Include="CollectionSynchronizationCallback.cs" />
+ <Compile Include="CollectionSynchronizationContext.cs" />
+ <Compile Include="ColorTypeConverter.cs" />
+ <Compile Include="ColumnDefinition.cs" />
+ <Compile Include="ColumnDefinitionCollection.cs" />
+ <Compile Include="Constraint.cs" />
+ <Compile Include="ConstraintExpression.cs" />
+ <Compile Include="ConstraintType.cs" />
+ <Compile Include="ConstraintTypeConverter.cs" />
+ <Compile Include="ContentPresenter.cs" />
+ <Compile Include="ControlTemplate.cs" />
+ <Compile Include="CustomKeyboard.cs" />
+ <Compile Include="DataTemplateExtensions.cs" />
+ <Compile Include="DataTemplateSelector.cs" />
+ <Compile Include="DateChangedEventArgs.cs" />
+ <Compile Include="DelegateLogListener.cs" />
+ <Compile Include="DependencyAttribute.cs" />
+ <Compile Include="DependencyFetchTarget.cs" />
+ <Compile Include="DeviceOrientation.cs" />
+ <Compile Include="DeviceOrientationExtensions.cs" />
+ <Compile Include="Effect.cs" />
+ <Compile Include="ElementEventArgs.cs" />
+ <Compile Include="ElementTemplate.cs" />
+ <Compile Include="EmailKeyboard.cs" />
+ <Compile Include="ExportEffectAttribute.cs" />
+ <Compile Include="ExpressionSearch.cs" />
+ <Compile Include="FileAccess.cs" />
+ <Compile Include="FileImageSourceConverter.cs" />
+ <Compile Include="FileMode.cs" />
+ <Compile Include="FileShare.cs" />
+ <Compile Include="FontAttributes.cs" />
+ <Compile Include="FontSizeConverter.cs" />
+ <Compile Include="FontTypeConverter.cs" />
+ <Compile Include="GestureRecognizer.cs" />
+ <Compile Include="GridLength.cs" />
+ <Compile Include="GridLengthTypeConverter.cs" />
+ <Compile Include="GridUnitType.cs" />
+ <Compile Include="HandlerAttribute.cs" />
+ <Compile Include="HtmlWebViewSource.cs" />
+ <Compile Include="IButtonController.cs" />
+ <Compile Include="ICarouselViewController.cs" />
+ <Compile Include="IControlTemplated.cs" />
+ <Compile Include="IDefinition.cs" />
+ <Compile Include="IEffectControlProvider.cs" />
+ <Compile Include="IElementController.cs" />
+ <Compile Include="IExpressionSearch.cs" />
+ <Compile Include="IExtendedTypeConverter.cs" />
+ <Compile Include="IFontElement.cs" />
+ <Compile Include="IGestureRecognizer.cs" />
+ <Compile Include="IItemsView.cs" />
+ <Compile Include="IItemViewController.cs" />
+ <Compile Include="ILayoutController.cs" />
+ <Compile Include="IListViewController.cs" />
+ <Compile Include="ImageSourceConverter.cs" />
+ <Compile Include="INavigation.cs" />
+ <Compile Include="InvalidationEventArgs.cs" />
+ <Compile Include="InvalidationTrigger.cs" />
+ <Compile Include="InvalidNavigationException.cs" />
+ <Compile Include="IOpenGlViewController.cs" />
+ <Compile Include="IPanGestureController.cs" />
+ <Compile Include="IPinchGestureController.cs" />
+ <Compile Include="IProvideParentValues.cs" />
+ <Compile Include="IProvideValueTarget.cs" />
+ <Compile Include="IRegisterable.cs" />
+ <Compile Include="IResourceDictionary.cs" />
+ <Compile Include="IResourcesProvider.cs" />
+ <Compile Include="IRootObjectProvider.cs" />
+ <Compile Include="IScrollViewController.cs" />
+ <Compile Include="ItemsViewSimple.cs" />
+ <Compile Include="ItemTappedEventArgs.cs" />
+ <Compile Include="ItemVisibilityEventArgs.cs" />
+ <Compile Include="IValueConverterProvider.cs" />
+ <Compile Include="IValueProvider.cs" />
+ <Compile Include="IViewController.cs" />
+ <Compile Include="IVisualElementController.cs" />
+ <Compile Include="IWebViewRenderer.cs" />
+ <Compile Include="IXamlTypeResolver.cs" />
+ <Compile Include="IXmlLineInfoProvider.cs" />
+ <Compile Include="KeyboardFlags.cs" />
+ <Compile Include="KeyboardTypeConverter.cs" />
+ <Compile Include="LayoutAlignment.cs" />
+ <Compile Include="LayoutAlignmentExtensions.cs" />
+ <Compile Include="LayoutConstraint.cs" />
+ <Compile Include="LayoutExpandFlag.cs" />
+ <Compile Include="LayoutOptionsConverter.cs" />
+ <Compile Include="ListViewCachingStrategy.cs" />
+ <Compile Include="LockingSemaphore.cs" />
+ <Compile Include="Log.cs" />
+ <Compile Include="LogListener.cs" />
+ <Compile Include="MasterBehavior.cs" />
+ <Compile Include="MeasureFlags.cs" />
+ <Compile Include="MenuItem.cs" />
+ <Compile Include="ModalEventArgs.cs" />
+ <Compile Include="ModalPoppedEventArgs.cs" />
+ <Compile Include="ModalPoppingEventArgs.cs" />
+ <Compile Include="ModalPushedEventArgs.cs" />
+ <Compile Include="ModalPushingEventArgs.cs" />
+ <Compile Include="NavigationEventArgs.cs" />
+ <Compile Include="NavigationModel.cs" />
+ <Compile Include="NavigationRequestedEventArgs.cs" />
+ <Compile Include="NotifyCollectionChangedEventArgsEx.cs" />
+ <Compile Include="NotifyCollectionChangedEventArgsExtensions.cs" />
+ <Compile Include="NullEffect.cs" />
+ <Compile Include="NumericKeyboard.cs" />
+ <Compile Include="ObservableList.cs" />
+ <Compile Include="OrderedDictionary.cs" />
+ <Compile Include="PanGestureRecognizer.cs" />
+ <Compile Include="PanUpdatedEventArgs.cs" />
+ <Compile Include="Performance.cs" />
+ <Compile Include="PinchGestureUpdatedEventArgs.cs" />
+ <Compile Include="PlatformEffect.cs" />
+ <Compile Include="PointTypeConverter.cs" />
+ <Compile Include="PreserveAttribute.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="BindableObject.cs" />
+ <Compile Include="BindableObjectExtensions.cs" />
+ <Compile Include="BindableProperty.cs" />
+ <Compile Include="Binding.cs" />
+ <Compile Include="BindingBase.cs" />
+ <Compile Include="BindingBaseExtensions.cs" />
+ <Compile Include="BindingExpression.cs" />
+ <Compile Include="Properties\GlobalAssemblyInfo.cs" />
+ <Compile Include="PropertyChangingEventArgs.cs" />
+ <Compile Include="IValueConverter.cs" />
+ <Compile Include="ConcurrentDictionary.cs" />
+ <Compile Include="PropertyChangingEventHandler.cs" />
+ <Compile Include="ReadOnlyCastingList.cs" />
+ <Compile Include="ReadOnlyListAdapter.cs" />
+ <Compile Include="RectangleTypeConverter.cs" />
+ <Compile Include="RenderWithAttribute.cs" />
+ <Compile Include="ResolutionGroupNameAttribute.cs" />
+ <Compile Include="ResourcesChangedEventArgs.cs" />
+ <Compile Include="ResourcesExtensions.cs" />
+ <Compile Include="RoutingEffect.cs" />
+ <Compile Include="RowDefinition.cs" />
+ <Compile Include="RowDefinitionCollection.cs" />
+ <Compile Include="ScrollOrientation.cs" />
+ <Compile Include="ScrollToMode.cs" />
+ <Compile Include="ScrollToPosition.cs" />
+ <Compile Include="SelectedItemChangedEventArgs.cs" />
+ <Compile Include="SelectedPositionChangedEventArgs.cs" />
+ <Compile Include="SeparatorMenuItem.cs" />
+ <Compile Include="SeparatorVisibility.cs" />
+ <Compile Include="SizeRequest.cs" />
+ <Compile Include="Span.cs" />
+ <Compile Include="SplitOrderedList.cs" />
+ <Compile Include="StackOrientation.cs" />
+ <Compile Include="StreamWrapper.cs" />
+ <Compile Include="SynchronizedList.cs" />
+ <Compile Include="TableIntent.cs" />
+ <Compile Include="TableRoot.cs" />
+ <Compile Include="TableSectionBase.cs" />
+ <Compile Include="TapGestureRecognizer.cs" />
+ <Compile Include="TelephoneKeyboard.cs" />
+ <Compile Include="TemplateBinding.cs" />
+ <Compile Include="TemplatedItemsList.cs" />
+ <Compile Include="TemplatedPage.cs" />
+ <Compile Include="TemplatedView.cs" />
+ <Compile Include="TemplateUtilities.cs" />
+ <Compile Include="TextChangedEventArgs.cs" />
+ <Compile Include="TextKeyboard.cs" />
+ <Compile Include="ThicknessTypeConverter.cs" />
+ <Compile Include="Ticker.cs" />
+ <Compile Include="ToggledEventArgs.cs" />
+ <Compile Include="ToolbarItemEventArgs.cs" />
+ <Compile Include="ToolbarItemOrder.cs" />
+ <Compile Include="TrackableCollection.cs" />
+ <Compile Include="TypeConverterAttribute.cs" />
+ <Compile Include="TypeConverter.cs" />
+ <Compile Include="ReflectionExtensions.cs" />
+ <Compile Include="Device.cs" />
+ <Compile Include="TargetPlatform.cs" />
+ <Compile Include="TargetIdiom.cs" />
+ <Compile Include="UnsolvableConstraintsException.cs" />
+ <Compile Include="UrlKeyboard.cs" />
+ <Compile Include="UrlWebViewSource.cs" />
+ <Compile Include="ValueChangedEventArgs.cs" />
+ <Compile Include="Vec2.cs" />
+ <Compile Include="View.cs" />
+ <Compile Include="IElement.cs" />
+ <Compile Include="IAnimatable.cs" />
+ <Compile Include="Easing.cs" />
+ <Compile Include="NavigationProxy.cs" />
+ <Compile Include="NavigationPage.cs" />
+ <Compile Include="Page.cs" />
+ <Compile Include="LayoutOptions.cs" />
+ <Compile Include="CarouselPage.cs" />
+ <Compile Include="Rectangle.cs" />
+ <Compile Include="Color.cs" />
+ <Compile Include="ResourceDictionary.cs" />
+ <Compile Include="EventArg.cs" />
+ <Compile Include="IPlatform.cs" />
+ <Compile Include="EnumerableExtensions.cs" />
+ <Compile Include="Size.cs" />
+ <Compile Include="GestureState.cs" />
+ <Compile Include="Point.cs" />
+ <Compile Include="Thickness.cs" />
+ <Compile Include="ToolbarItem.cs" />
+ <Compile Include="ContentPropertyAttribute.cs" />
+ <Compile Include="MessagingCenter.cs" />
+ <Compile Include="Cells\Cell.cs" />
+ <Compile Include="Cells\SwitchCell.cs" />
+ <Compile Include="Cells\TextCell.cs" />
+ <Compile Include="Cells\ViewCell.cs" />
+ <Compile Include="ListView.cs" />
+ <Compile Include="TableView.cs" />
+ <Compile Include="ItemsView.cs" />
+ <Compile Include="TableModel.cs" />
+ <Compile Include="TableSection.cs" />
+ <Compile Include="DataTemplate.cs" />
+ <Compile Include="ListProxy.cs" />
+ <Compile Include="AbsoluteLayout.cs" />
+ <Compile Include="Registrar.cs" />
+ <Compile Include="ActivityIndicator.cs" />
+ <Compile Include="BoxView.cs" />
+ <Compile Include="Button.cs" />
+ <Compile Include="Command.cs" />
+ <Compile Include="ContentView.cs" />
+ <Compile Include="DatePicker.cs" />
+ <Compile Include="DependencyService.cs" />
+ <Compile Include="Editor.cs" />
+ <Compile Include="Entry.cs" />
+ <Compile Include="Frame.cs" />
+ <Compile Include="Image.cs" />
+ <Compile Include="UriImageSource.cs" />
+ <Compile Include="IMarkupExtension.cs" />
+ <Compile Include="InputView.cs" />
+ <Compile Include="Keyboard.cs" />
+ <Compile Include="Label.cs" />
+ <Compile Include="LineBreakMode.cs" />
+ <Compile Include="MasterDetailPage.cs" />
+ <Compile Include="NavigationMenu.cs" />
+ <Compile Include="OpenGLView.cs" />
+ <Compile Include="ProgressBar.cs" />
+ <Compile Include="RelativeLayout.cs" />
+ <Compile Include="ScrollView.cs" />
+ <Compile Include="SearchBar.cs" />
+ <Compile Include="Slider.cs" />
+ <Compile Include="StackLayout.cs" />
+ <Compile Include="Stepper.cs" />
+ <Compile Include="Switch.cs" />
+ <Compile Include="TabbedPage.cs" />
+ <Compile Include="TemplateExtensions.cs" />
+ <Compile Include="TimePicker.cs" />
+ <Compile Include="Toolbar.cs" />
+ <Compile Include="ToolbarTracker.cs" />
+ <Compile Include="ViewExtensions.cs" />
+ <Compile Include="ViewState.cs" />
+ <Compile Include="WeakReferenceExtensions.cs" />
+ <Compile Include="WebNavigatedEventArgs.cs" />
+ <Compile Include="WebNavigatingEventArgs.cs" />
+ <Compile Include="WebNavigationEvent.cs" />
+ <Compile Include="WebNavigationEventArgs.cs" />
+ <Compile Include="WebNavigationResult.cs" />
+ <Compile Include="WebView.cs" />
+ <Compile Include="Animation.cs" />
+ <Compile Include="AnimationExtensions.cs" />
+ <Compile Include="Tweener.cs" />
+ <Compile Include="IPlatformServices.cs" />
+ <Compile Include="UriTypeConverter.cs" />
+ <Compile Include="ITimer.cs" />
+ <Compile Include="IIsolatedStorageFile.cs" />
+ <Compile Include="Grid.cs" />
+ <Compile Include="GridCalc.cs" />
+ <Compile Include="DefinitionCollection.cs" />
+ <Compile Include="Element.cs" />
+ <Compile Include="ObservableWrapper.cs" />
+ <Compile Include="ElementCollection.cs" />
+ <Compile Include="IViewContainer.cs" />
+ <Compile Include="Layout.cs" />
+ <Compile Include="ContentPage.cs" />
+ <Compile Include="IPageContainer.cs" />
+ <Compile Include="MultiPage.cs" />
+ <Compile Include="ILayout.cs" />
+ <Compile Include="FocusEventArgs.cs" />
+ <Compile Include="VisualElement.cs" />
+ <Compile Include="NameScopeExtensions.cs" />
+ <Compile Include="NamedSize.cs" />
+ <Compile Include="TextAlignment.cs" />
+ <Compile Include="Font.cs" />
+ <Compile Include="Picker.cs" />
+ <Compile Include="NumericExtensions.cs" />
+ <Compile Include="BindablePropertyKey.cs" />
+ <Compile Include="ImageSource.cs" />
+ <Compile Include="FileImageSource.cs" />
+ <Compile Include="StreamImageSource.cs" />
+ <Compile Include="OnPlatform.cs" />
+ <Compile Include="OnIdiom.cs" />
+ <Compile Include="TappedEventArgs.cs" />
+ <Compile Include="FormattedString.cs" />
+ <Compile Include="Interactivity\Behavior.cs" />
+ <Compile Include="Interactivity\IAttachedObject.cs" />
+ <Compile Include="Interactivity\AttachedCollection.cs" />
+ <Compile Include="Interactivity\TriggerAction.cs" />
+ <Compile Include="Interactivity\EventTrigger.cs" />
+ <Compile Include="Interactivity\TriggerBase.cs" />
+ <Compile Include="Interactivity\Trigger.cs" />
+ <Compile Include="Setter.cs" />
+ <Compile Include="Style.cs" />
+ <Compile Include="ParameterAttribute.cs" />
+ <Compile Include="TypeTypeConverter.cs" />
+ <Compile Include="SettersExtensions.cs" />
+ <Compile Include="IDeserializer.cs" />
+ <Compile Include="ISystemResourcesProvider.cs" />
+ <Compile Include="Interactivity\DataTrigger.cs" />
+ <Compile Include="Interactivity\Condition.cs" />
+ <Compile Include="Interactivity\BindingCondition.cs" />
+ <Compile Include="Interactivity\PropertyCondition.cs" />
+ <Compile Include="Interactivity\MultiTrigger.cs" />
+ <Compile Include="Interactivity\MultiCondition.cs" />
+ <Compile Include="DeviceInfo.cs" />
+ <Compile Include="WebViewSource.cs" />
+ <Compile Include="WebViewSourceTypeConverter.cs" />
+ <Compile Include="XamlParseException.cs" />
+ <Compile Include="ScrolledEventArgs.cs" />
+ <Compile Include="ScrollToRequestedEventArgs.cs" />
+ <Compile Include="XmlLineInfo.cs" />
+ <Compile Include="GestureStatus.cs" />
+ <Compile Include="Internals\INameScope.cs" />
+ <Compile Include="Internals\NameScope.cs" />
+ <Compile Include="Internals\IDataTemplate.cs" />
+ <Compile Include="Internals\IDynamicResourceHandler.cs" />
+ <Compile Include="Internals\DynamicResource.cs" />
+ <Compile Include="PinchGestureRecognizer.cs" />
+ <Compile Include="IStyle.cs" />
+ <Compile Include="MergedStyle.cs" />
+ <Compile Include="IApplicationController.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Platform\Xamarin.Forms.Platform.csproj">
+ <Project>{67f9d3a8-f71e-4428-913f-c37ae82cdb24}</Project>
+ <Name>Xamarin.Forms.Platform</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup />
+ <PropertyGroup>
+ <PostBuildEvent>
+ </PostBuildEvent>
+ </PropertyGroup>
+ <ItemGroup />
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Core/Xamarin.Forms.Core.nuspec b/Xamarin.Forms.Core/Xamarin.Forms.Core.nuspec
new file mode 100644
index 00000000..b5dff885
--- /dev/null
+++ b/Xamarin.Forms.Core/Xamarin.Forms.Core.nuspec
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<package >
+ <metadata>
+ <id>Xamarin.Forms.Core</id>
+ <version>$version$</version>
+ <title>Xamarin.Forms (.NET 4.5)</title>
+ <authors>Xamarin Inc.</authors>
+ <owners>Xamarin Inc.</owners>
+ <requireLicenseAcceptance>false</requireLicenseAcceptance>
+ <description>Xamarin.Forms platform abstruction library for mobile applications.</description>
+ <releaseNotes></releaseNotes>
+ <copyright>Copyright 2013</copyright>
+ </metadata>
+</package>
diff --git a/Xamarin.Forms.Core/XamlParseException.cs b/Xamarin.Forms.Core/XamlParseException.cs
new file mode 100644
index 00000000..42e8b618
--- /dev/null
+++ b/Xamarin.Forms.Core/XamlParseException.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Xml;
+
+namespace Xamarin.Forms.Xaml
+{
+ public class XamlParseException : Exception
+ {
+ readonly string _unformattedMessage;
+
+ public XamlParseException(string message, IXmlLineInfo xmlInfo) : base(FormatMessage(message, xmlInfo))
+ {
+ _unformattedMessage = message;
+ XmlInfo = xmlInfo;
+ }
+
+ public IXmlLineInfo XmlInfo { get; private set; }
+
+ internal string UnformattedMessage
+ {
+ get { return _unformattedMessage ?? Message; }
+ }
+
+ static string FormatMessage(string message, IXmlLineInfo xmlinfo)
+ {
+ if (xmlinfo == null || !xmlinfo.HasLineInfo())
+ return message;
+ return string.Format("Position {0}:{1}. {2}", xmlinfo.LineNumber, xmlinfo.LinePosition, message);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/XmlLineInfo.cs b/Xamarin.Forms.Core/XmlLineInfo.cs
new file mode 100644
index 00000000..eb11e316
--- /dev/null
+++ b/Xamarin.Forms.Core/XmlLineInfo.cs
@@ -0,0 +1,29 @@
+using System.Xml;
+
+namespace Xamarin.Forms.Xaml
+{
+ public class XmlLineInfo : IXmlLineInfo
+ {
+ readonly bool _hasLineInfo;
+
+ public XmlLineInfo()
+ {
+ }
+
+ public XmlLineInfo(int linenumber, int lineposition)
+ {
+ _hasLineInfo = true;
+ LineNumber = linenumber;
+ LinePosition = lineposition;
+ }
+
+ public bool HasLineInfo()
+ {
+ return _hasLineInfo;
+ }
+
+ public int LineNumber { get; }
+
+ public int LinePosition { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.CustomAttributes/Properties/AssemblyInfo.cs b/Xamarin.Forms.CustomAttributes/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..ce51278d
--- /dev/null
+++ b/Xamarin.Forms.CustomAttributes/Properties/AssemblyInfo.cs
@@ -0,0 +1,30 @@
+using System.Resources;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Xamarin.Forms.CustomAttributes")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Forms.CustomAttributes")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: NeutralResourcesLanguage("en")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Xamarin.Forms.CustomAttributes/TestAttributes.cs b/Xamarin.Forms.CustomAttributes/TestAttributes.cs
new file mode 100644
index 00000000..7aa9fb04
--- /dev/null
+++ b/Xamarin.Forms.CustomAttributes/TestAttributes.cs
@@ -0,0 +1,737 @@
+using System;
+using System.Diagnostics;
+
+namespace Xamarin.Forms.CustomAttributes
+{
+ [Conditional ("DEBUG")]
+ [AttributeUsage (
+ AttributeTargets.Class |
+ AttributeTargets.Event |
+ AttributeTargets.Property |
+ AttributeTargets.Method |
+ AttributeTargets.Delegate,
+ AllowMultiple = true
+ )]
+ public class PlatformAttribute : Attribute
+ {
+ readonly string _platform;
+ public PlatformAttribute (object platform)
+ {
+ _platform = platform.ToString ();
+ }
+
+ public string Platform => "Issue: " + _platform;
+ }
+
+ public enum IssueTracker
+ {
+ Github,
+ Bugzilla,
+ None
+ }
+
+ public enum NavigationBehavior
+ {
+ PushAsync,
+ PushModalAsync,
+ SetApplicationRoot,
+ Default
+ }
+
+ [Conditional ("DEBUG")]
+ [AttributeUsage (
+ AttributeTargets.Class |
+ AttributeTargets.Method,
+ AllowMultiple = true
+ )]
+ public class IssueAttribute : Attribute
+ {
+ bool _modal;
+
+ public IssueAttribute (IssueTracker issueTracker, int issueNumber, string description, NavigationBehavior navigationBehavior = NavigationBehavior.Default)
+ {
+ IssueTracker = issueTracker;
+ IssueNumber = issueNumber;
+ Description = description;
+ PlatformsAffected = PlatformAffected.Default;
+ NavigationBehavior = navigationBehavior;
+ }
+
+ public IssueAttribute (IssueTracker issueTracker, int issueNumber, string description, PlatformAffected platformsAffected, NavigationBehavior navigationBehavior = NavigationBehavior.Default)
+ {
+ IssueTracker = issueTracker;
+ IssueNumber = issueNumber;
+ Description = description;
+ PlatformsAffected = platformsAffected;
+ NavigationBehavior = navigationBehavior;
+ }
+
+ public IssueTracker IssueTracker { get; }
+
+ public int IssueNumber { get; }
+
+ public string Description { get; }
+
+ public PlatformAffected PlatformsAffected { get; }
+
+ public NavigationBehavior NavigationBehavior { get; }
+ }
+
+ [Conditional ("DEBUG")]
+ public class UiTestExemptAttribute : Attribute
+ {
+ // optional string reason
+ readonly string _exemptReason;
+ readonly string _description;
+
+ public UiTestExemptAttribute (ExemptReason exemptReason, string description = null)
+ {
+ _exemptReason = Enum.GetName (typeof(ExemptReason), exemptReason);
+ _description = description;
+ }
+
+ public string ExemptReason => "Exempt: " + _exemptReason;
+
+ public string Description => "Description: " + _description;
+ }
+
+ [Conditional ("DEBUG")]
+ public class UiTestFragileAttribute : Attribute
+ {
+ // optional string reason
+ readonly string _description;
+
+ public UiTestFragileAttribute (string description = null)
+ {
+ _description = description;
+ }
+
+ public string Description => "Description: " + _description;
+ }
+
+ [Conditional ("DEBUG")]
+ [AttributeUsage (AttributeTargets.All, AllowMultiple = true)]
+ public class UiTestBrokenAttribute : Attribute
+ {
+ // optional string reason
+ readonly string _exemptReason;
+ readonly string _description;
+
+ public UiTestBrokenAttribute (BrokenReason exemptReason, string description = null)
+ {
+ _exemptReason = Enum.GetName (typeof(ExemptReason), exemptReason);
+ _description = description;
+ }
+
+ public string ExemptReason => "Exempt: " + _exemptReason;
+
+ public string Description => "Description: " + _description;
+ }
+
+ [Flags]
+ public enum PlatformAffected
+ {
+ iOS = 1 << 0,
+ Android = 1 << 1,
+ WinPhone = 1 << 2,
+ WinRT = 1 << 3,
+ All = ~0,
+ Default = 0
+ }
+
+ public enum ExemptReason
+ {
+ None,
+ AbstractClass,
+ IsUnitTested,
+ NeedsUnitTest,
+ BaseClass,
+ TimeConsuming,
+ CannotTest
+ }
+
+ public enum BrokenReason
+ {
+ UITestBug,
+ CalabashBug,
+ CalabashUnsupported,
+ CalabashiOSUnsupported,
+ CalabashAndroidUnsupported,
+ }
+
+ public static class Test
+ {
+ public enum Features
+ {
+ Binding,
+ XAML,
+ Maps
+ }
+
+ public enum Views
+ {
+ Label,
+ TableView,
+ SwitchCell,
+ ViewCell,
+ Image,
+ ListView,
+ ScrollView,
+ Switch,
+ Button,
+ TextCell,
+ Entry,
+ SearchBar,
+ ImageCell,
+ EntryCell,
+ Editor,
+ DatePicker
+ }
+
+ public enum Layouts
+ {
+ StackLayout,
+ Grid
+ }
+
+ public enum Pages
+ {
+ NavigationPage,
+ MasterDetailPage,
+ TabbedPage,
+ ContentPage,
+ CarouselPage
+ }
+
+ public enum Button
+ {
+ Clicked,
+ Command,
+ Text,
+ TextColor,
+ Font,
+ BorderWidth,
+ BorderColor,
+ BorderRadius,
+ Image,
+ }
+
+ public enum VisualElement
+ {
+ IsEnabled,
+ Navigation,
+ InputTransparent,
+ Layout,
+ X,
+ Y,
+ AnchorX,
+ AnchorY,
+ TranslationX,
+ TranslationY,
+ Width,
+ Height,
+ Bounds,
+ Rotation,
+ RotationX,
+ RotationY,
+ Scale,
+ IsVisible,
+ Opacity,
+ BackgroundColor,
+ IsFocused,
+ Focus,
+ Unfocus,
+ Focused,
+ Unfocused,
+ Default
+ }
+
+ public enum Cell
+ {
+ Tapped,
+ Appearing,
+ Disappearing,
+ IsEnabled,
+ RenderHeight,
+ Height,
+ ContextActions,
+ }
+
+ public enum EntryCell
+ {
+ Completed,
+ Text,
+ Label,
+ Placeholder,
+ LabelColor,
+ Keyboard,
+ XAlign,
+ }
+
+ public enum TextCell
+ {
+ Command,
+ Text,
+ Detail,
+ TextColor,
+ DetailColor,
+ }
+
+ public enum ImageCell
+ {
+ ImageSource,
+ }
+
+ public enum GestureRecognizer
+ {
+ Parent,
+ }
+
+ public enum Binding
+ {
+ Path,
+ Converter,
+ ConverterParameter,
+ Create,
+ }
+
+ public enum TapGestureRecognizer
+ {
+ Tapped,
+ Command,
+ CommandParameter,
+ NumberOfTapsRequired,
+ TappedCallBack,
+ TappedCallBackParameter
+ }
+
+ public enum Device
+ {
+ OS,
+ Idiom,
+ OnPlatform,
+ OnPlatformGeneric,
+ OpenUri,
+ BeginInvokeOnMainThread,
+ StartTimer,
+ Styles
+ }
+
+ public enum ValueChangedEventArgs
+ {
+ OldValue,
+ NewValue,
+ }
+
+ public enum View
+ {
+ GestureRecognizers,
+ }
+
+ public enum Page
+ {
+ BackgroundImage,
+ ToolbarItems,
+ IsBusy,
+ DisplayAlert,
+ DisplayAlertAccept,
+ DisplayActionSheet,
+ Title,
+ Icon,
+ Appearing,
+ Disappearing,
+ }
+
+ public enum NavigationPage
+ {
+ GetBackButtonTitle,
+ SetBackButtonTitle,
+ GetHasNavigationBar,
+ SetHasNavigationBar,
+ Tint,
+ BarBackgroundColor,
+ BarTextColor,
+ BarGetTitleIcon,
+ BarSetTitleIcon,
+ Popped,
+ PushAsync,
+ PopAsync,
+ PopToRootAsync,
+ }
+
+ public enum MultiPage
+ {
+ CurrentPageChanged,
+ CurrentPagesChanged,
+ ItemsSource,
+ ItemTemplate,
+ SelectedItem,
+ CurrentPage,
+ Children,
+ }
+
+ public enum MenuItem
+ {
+ Text,
+ Command,
+ IsDestructive,
+ Icon,
+ Clicked,
+ IsEnabled
+ }
+
+ public enum ToolbarItem
+ {
+ Activated,
+ Name,
+ Order,
+ Priority
+ }
+
+ public enum SwitchCell
+ {
+ OnChanged,
+ On,
+ Text,
+ }
+
+ public enum ViewCell
+ {
+ View,
+ }
+
+ public enum ListView
+ {
+ ItemAppearing,
+ ItemDisappearing,
+ ItemSelected,
+ ItemTapped,
+ SelectedItem,
+ HasUnevenRows,
+ RowHeight,
+ GroupHeaderTemplate,
+ IsGroupingEnabled,
+ GroupDisplayBinding,
+ GroupShortNameBinding,
+ ScrollTo
+ }
+
+ public enum TableView
+ {
+ Root,
+ Intent,
+ RowHeight,
+ HasUnevenRows,
+ }
+
+ public enum TableSectionBase
+ {
+ Title,
+ }
+
+ public enum Layout
+ {
+ IsClippedToBounds,
+ Padding,
+ RaiseChild,
+ LowerChild,
+ GenericChildren,
+ }
+
+ public enum AbsoluteLayout
+ {
+ Children,
+ SetLayoutFlags,
+ SetLayoutBounds,
+ }
+
+ public enum ActivityIndicator
+ {
+ IsRunning,
+ Color,
+ }
+
+ public enum ContentView
+ {
+ View,
+ }
+
+ public enum DatePicker
+ {
+ DateSelected,
+ Format,
+ Date,
+ MinimumDate,
+ MaximumDate,
+ Focus,
+ IsVisible
+ }
+
+ public enum InputView
+ {
+ Keyboard,
+ }
+
+ public enum Editor
+ {
+ Completed,
+ TextChanged,
+ Text,
+ TextColor,
+ FontAttributes,
+ FontFamily,
+ FontSize
+ }
+
+ public enum Entry
+ {
+ Completed,
+ TextChanged,
+ Placeholder,
+ IsPassword,
+ Text,
+ TextColor,
+ Keyboard,
+ HorizontalTextAlignmentStart,
+ HorizontalTextAlignmentCenter,
+ HorizontalTextAlignmentEnd,
+ HorizontalTextAlignmentPlaceholderStart,
+ HorizontalTextAlignmentPlaceholderCenter,
+ HorizontalTextAlignmentPlaceholderEnd,
+ FontAttributes,
+ FontFamily,
+ FontSize,
+ PlaceholderColor,
+ TextDisabledColor,
+ PlaceholderDisabledColor,
+ PasswordColor
+ }
+
+ public enum Frame
+ {
+ OutlineColor,
+ HasShadow
+ }
+
+ public enum Image
+ {
+ Source,
+ Aspect,
+ IsOpaque,
+ IsLoading,
+ AspectFill,
+ AspectFit,
+ Fill
+ }
+
+ public enum ImageSource
+ {
+ FromFile,
+ FromStream,
+ FromResource,
+ FromUri,
+ Cancel,
+ }
+
+ public enum UriImageSource
+ {
+ Uri,
+ CachingEnabled,
+ CacheValidity,
+ }
+
+ public enum Keyboard
+ {
+ Create,
+ Default,
+ Email,
+ Text,
+ Url,
+ Numeric,
+ Telephone,
+ Chat,
+ }
+
+ public enum Label
+ {
+ TextColor,
+ Text,
+ FormattedText,
+ FontAttibutesBold,
+ FontAttributesItalic,
+ FontNamedSizeMicro,
+ FontNamedSizeSmall,
+ FontNamedSizeMedium,
+ FontNamedSizeLarge,
+ LineBreakModeNoWrap,
+ LineBreakModeWordWrap,
+ LineBreakModeCharacterWrap,
+ LineBreakModeHeadTruncation,
+ LineBreakModeTailTruncation,
+ LineBreakModeMiddleTruncation,
+ HorizontalTextAlignmentStart,
+ HorizontalTextAlignmentCenter,
+ HorizontalTextAlignmentEnd,
+ VerticalTextAlignmentStart,
+ VerticalTextAlignmentCenter,
+ VerticalTextAlignmentEnd,
+ }
+
+ public enum MasterDetailPage {
+ Master,
+ Detail,
+ IsGestureEnabled,
+ IsPresented,
+ MasterBehavior
+ }
+
+ public enum OpenGlView {
+ OnDisplay,
+ HasRenderLoop,
+ Display
+ }
+
+ public enum ProgressBar {
+ Progress
+ }
+
+ public enum RelativeLayout {
+ Children,
+ SetBoundsConstraint
+ }
+
+ public enum ScrollView {
+ ContentSize,
+ Orientation,
+ Content
+ }
+
+ public enum SearchBar
+ {
+ SearchButtonPressed,
+ TextChanged,
+ SearchCommand,
+ Text,
+ PlaceHolder,
+ CancelButtonColor,
+ FontAttributes,
+ FontFamily,
+ FontSize,
+ TextAlignmentStart,
+ TextAlignmentCenter,
+ TextAlignmentEnd,
+ PlaceholderAlignmentStart,
+ PlaceholderAlignmentCenter,
+ PlaceholderAlignmentEnd,
+ TextColor,
+ PlaceholderColor
+ }
+
+ public enum Slider {
+ Minimum,
+ Maximum,
+ Value
+ }
+
+ public enum StackLayout {
+ Orientation,
+ Spacing
+ }
+
+ public enum Stepper {
+ Maximum,
+ Minimum,
+ Value,
+ Increment
+ }
+
+ public enum Switch {
+ IsToggled
+ }
+
+ public enum TimePicker {
+ Format,
+ Time,
+ Focus
+ }
+
+ public enum WebView {
+ UrlWebViewSource,
+ HtmlWebViewSource,
+ LoadHtml
+ }
+
+ public enum UrlWebViewSource {
+ Url
+ }
+
+ public enum HtmlWebViewSource {
+ BaseUrl,
+ Html
+ }
+
+ public enum Grid {
+ Children,
+ SetRow,
+ SetRowSpan,
+ SetColumn,
+ SetColumnSpan,
+ RowSpacing,
+ ColumnSpacing,
+ ColumnDefinitions,
+ RowDefinitions
+ }
+
+ public enum ContentPage {
+ Content
+ }
+
+ public enum Picker {
+ Title,
+ Items,
+ SelectedIndex,
+ Focus
+ }
+
+ public enum FileImageSource {
+ File,
+ Cancel
+ }
+
+ public enum StreamImageSource {
+ Stream
+ }
+
+ public enum OnPlatform {
+ WinPhone,
+ Android,
+ iOS
+ }
+
+ public enum OnIdiom {
+ Phone,
+ Tablet
+ }
+
+ public enum Span {
+ Text,
+ ForeGroundColor,
+ BackgroundColor,
+ Font,
+ PropertyChanged
+ }
+
+ public enum FormattedString {
+ ToStringOverride,
+ Spans,
+ PropertyChanged
+ }
+
+ public enum BoxView
+ {
+ Color
+ }
+
+ }
+}
+
diff --git a/Xamarin.Forms.CustomAttributes/UiTestAttribute.cs b/Xamarin.Forms.CustomAttributes/UiTestAttribute.cs
new file mode 100644
index 00000000..0eef90eb
--- /dev/null
+++ b/Xamarin.Forms.CustomAttributes/UiTestAttribute.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Diagnostics;
+
+namespace Xamarin.Forms.CustomAttributes
+{
+ [Conditional ("DEBUG")]
+ [AttributeUsage (
+ AttributeTargets.Class |
+ AttributeTargets.Event |
+ AttributeTargets.Property |
+ AttributeTargets.Method |
+ AttributeTargets.Delegate,
+ AllowMultiple = true
+ )]
+ public class UiTestAttribute : Attribute
+ {
+ public UiTestAttribute (Type formsType)
+ {
+ Type = formsType;
+ MemberName = "";
+ }
+
+ public UiTestAttribute (Type formsType, string memberName)
+ {
+ Type = formsType;
+ MemberName = memberName;
+ }
+
+ public Type Type { get; }
+
+ public string MemberName { get; }
+ }
+}
diff --git a/Xamarin.Forms.CustomAttributes/Xamarin.Forms.CustomAttributes.csproj b/Xamarin.Forms.CustomAttributes/Xamarin.Forms.CustomAttributes.csproj
new file mode 100644
index 00000000..229f3029
--- /dev/null
+++ b/Xamarin.Forms.CustomAttributes/Xamarin.Forms.CustomAttributes.csproj
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{4DCD0420-1168-4B77-86DB-6196EE4BD491}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.CustomAttributes</RootNamespace>
+ <AssemblyName>Xamarin.Forms.CustomAttributes</AssemblyName>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .NET Framework is automatically included -->
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="TestAttributes.cs" />
+ <Compile Include="UiTestAttribute.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/ExemptMembers.cs b/Xamarin.Forms.Loader/ExemptMembers.cs
new file mode 100644
index 00000000..da997f79
--- /dev/null
+++ b/Xamarin.Forms.Loader/ExemptMembers.cs
@@ -0,0 +1,157 @@
+using System;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Loader
+{
+ internal static class ExemptMembers
+ {
+ public static Dictionary<Type, IEnumerable<string>> UnitTestedTypes = new Dictionary<Type, IEnumerable<string>>
+ {
+ // Unit tested
+ { typeof (BindingTypeConverter), new[] { "CanConvertFrom", "ConvertFrom" } },
+ { typeof (DateChangedEventArgs), new[] { "OldDate", "NewDate" } },
+ { typeof (ElementEventArgs), new[] { "Element" } },
+ { typeof (ItemTappedEventArgs), new[] { "Group", "Item" } },
+ { typeof (ItemVisibilityEventArgs), new[] { "Item" } },
+ { typeof (NavigationEventArgs), new[] { "Page" } },
+ {
+ typeof (BindableObject),
+ new[]
+ {
+ "SetValue", "SetValue", "GetValue", "ClearValue", "ClearValue", "SetBinding", "RemoveBinding", "BindingContext",
+ "PropertyChanging", "PropertyChanged", "BindingContextChanged"
+ }
+ },
+ { typeof (BindableObjectExtensions), new[] { "SetBinding", "SetBinding" } },
+ {
+ typeof (BindableProperty),
+ new[]
+ {
+ "Create", "CreateReadOnly", "Create", "CreateReadOnly", "CreateAttached", "CreateAttachedReadOnly",
+ "CreateAttachedReadOnly", "CreateAttached", "PropertyName", "ReturnType", "DeclaringType", "DefaultValue",
+ "DefaultBindingMode", "IsReadOnly"
+ }
+ },
+ {
+ typeof (BindingBase),
+ new[] { "EnableCollectionSynchronization", "DisableCollectionSynchronization", "Mode", "StringFormat" }
+ },
+ { typeof (PropertyChangingEventArgs), new[] { "PropertyName" } },
+ { typeof (SelectedItemChangedEventArgs), new[] { "SelectedItem" } },
+ { typeof (TextChangedEventArgs), new[] { "OldTextValue", "NewTextValue" } },
+ { typeof (ToggledEventArgs), new[] { "Value" } },
+ { typeof (TypeConverter), new[] { "CanConvertFrom", "ConvertFrom", "ConvertFrom" } },
+ { typeof (View), new[] { "VerticalOptions", "HorizontalOptions" } },
+ { typeof (Easing), new[] { "Ease" } },
+ { typeof (NavigationPage), new[] { "CurrentPage", "Pushed", "PoppedToRoot" } },
+ { typeof (Page), new[] { "ForceLayout", "Padding", "LayoutChanged" } },
+ { typeof (RectangleTypeConverter), new[] { "CanConvertFrom", "ConvertFrom" } },
+ { typeof (ColorTypeConverter), new[] { "CanConvertFrom", "ConvertFrom" } },
+ {
+ typeof (ResourceDictionary),
+ new[] { "Add", "Clear", "ContainsKey", "GetEnumerator", "Remove", "TryGetValue", "Item", "Count", "Keys", "Values" }
+ },
+ { typeof (PointTypeConverter), new[] { "CanConvertFrom", "ConvertFrom" } },
+ { typeof (ThicknessTypeConverter), new[] { "CanConvertFrom", "ConvertFrom" } },
+ { typeof (ToolbarItem), new[] { "CommandParameter" } },
+ { typeof (MessagingCenter), new[] { "Subscribe", "Subscribe", "Unsubscribe", "Unsubscribe", "Send", "Send" } },
+ { typeof (TextCell), new[] { "CommandParameter" } },
+ { typeof (ItemsView<>), new[] { "ItemsSource", "ItemTemplate" } },
+ {
+ typeof (TableSectionBase),
+ new[]
+ {
+ "GetEnumerator", "Add", "Add", "Clear", "Contains", "CopyTo", "Remove", "IndexOf", "Insert", "RemoveAt", "Count",
+ "Item", "CollectionChanged"
+ }
+ },
+ { typeof (DataTemplate), new[] { "CreateContent", "SetBinding", "SetValue", "Bindings", "Values" } },
+ { typeof (AbsoluteLayout), new[] { "GetLayoutFlags", "GetLayoutBounds", "AutoSize" } },
+ { typeof (BoundsTypeConverter), new[] { "CanConvertFrom", "ConvertFrom" } },
+ { typeof (Button), new[] { "CommandParameter" } },
+ { typeof (Command), new[] { "Execute", "CanExecute", "ChangeCanExecute", "CanExecuteChanged" } },
+ { typeof (DependencyService), new[] { "Get" } },
+ { typeof (KeyboardTypeConverter), new[] { "CanConvertFrom", "ConvertFrom" } },
+ { typeof (MasterDetailPage), new[] { "IsPresentedChanged" } },
+ { typeof (ProgressBar), new[] { "ProgressTo" } },
+ { typeof (Constraint), new[] { "Constant", "RelativeToParent", "RelativeToView", "FromExpression" } },
+ { typeof (ConstraintExpression), new[] { "ProvideValue", "Type", "Constant", "Factor", "Property", "ElementName" } },
+ { typeof (ConstraintTypeConverter), new[] { "CanConvertFrom", "ConvertFrom" } },
+ { typeof (BoundsConstraint), new[] { "FromExpression" } },
+ {
+ typeof (RelativeLayout),
+ new[] { "GetXConstraint", "GetYConstraint", "GetWidthConstraint", "GetHeightConstraint", "GetBoundsConstraint" }
+ },
+ { typeof (ScrollView), new[] { "ContentSize" } },
+ { typeof (SearchBar), new[] { "SearchCommandParameter" } },
+ { typeof (Slider), new[] { "ValueChanged" } },
+ { typeof (Stepper), new[] { "ValueChanged" } },
+ { typeof (Switch), new[] { "Toggled" } },
+ { typeof (TemplateExtensions), new[] { "SetBinding" } },
+ {
+ typeof (ViewExtensions),
+ new[]
+ {
+ "TranslateTo", "LayoutTo", "RelRotateTo", "RelScaleTo", "RotateTo", "RotateYTo", "RotateXTo", "ScaleTo", "FadeTo",
+ "CancelAnimations"
+ }
+ },
+ { typeof (WebView), new[] { "Eval", "GoBack", "GoForward", "CanGoBack", "CanGoForward", "Navigating", "Navigated" } },
+ { typeof (WebViewSourceTypeConverter), new[] { "CanConvertFrom", "ConvertFrom" } },
+ {
+ typeof (Animation),
+ new[] { "GetEnumerator", "Insert", "Commit", "Add", "WithConcurrent", "WithConcurrent", "GetCallback" }
+ },
+ {
+ typeof (AnimationExtensions),
+ new[]
+ {
+ "AnimateKinetic", "Animate", "Interpolate", "Animate", "Animate", "Animate", "AbortAnimation",
+ "AnimationIsRunning"
+ }
+ },
+ { typeof (UriTypeConverter), new[] { "CanConvertFrom", "ConvertFrom" } },
+ { typeof (GridLengthTypeConverter), new[] { "CanConvertFrom", "ConvertFrom" } },
+ { typeof (Grid), new[] { "GetRow", "GetRowSpan", "GetColumn", "GetColumnSpan" } },
+ { typeof (RowDefinition), new[] { "Height", "SizeChanged" } },
+ { typeof (ColumnDefinition), new[] { "Width", "SizeChanged" } },
+ {
+ typeof (DefinitionCollection<>),
+ new[]
+ {
+ "IndexOf", "Insert", "RemoveAt", "Add", "Clear", "Contains", "CopyTo", "Remove", "GetEnumerator", "Item", "Count",
+ "IsReadOnly", "ItemSizeChanged"
+ }
+ },
+ {
+ typeof (Element),
+ new[]
+ {
+ "Parent", "ParentView", "ClassId", "StyleId", "Id", "ChildAdded", "ChildRemoved", "DescendantAdded",
+ "DescendantRemoved"
+ }
+ },
+ { typeof (Layout), new[] { "GetSizeRequest", "ForceLayout", "LayoutChildIntoBoundingRegion", "LayoutChanged" } },
+ { typeof (FocusEventArgs), new[] { "IsFocused", "VisualElement" } },
+ {
+ typeof (VisualElement),
+ new[]
+ {
+ "BatchBegin", "BatchCommit", "GetSizeRequest", "WidthRequest", "HeightRequest", "MinimumWidthRequest",
+ "MinimumHeightRequest", "Resources", "ChildrenReordered", "SizeChanged", "MeasureInvalidated", "Focused",
+ "Unfocused"
+ }
+ },
+ { typeof (NameScopeExtensions), new[] { "FindByName" } },
+ { typeof (FontTypeConverter), new[] { "CanConvertFrom", "ConvertFrom" } },
+ { typeof (Picker), new[] { "SelectedIndexChanged" } },
+ { typeof (BindablePropertyKey), new[] { "BindableProperty" } },
+ { typeof (TappedEventArgs), new[] { "Parameter" } }
+ };
+
+ public static Dictionary<Type, IEnumerable<string>> CannotTestTypes = new Dictionary<Type, IEnumerable<string>>
+ {
+ { typeof (Button), new[] { "BorderColor", "BorderRadius", "BorderWidth", "Image" } }
+ };
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/FormsLoader.cs b/Xamarin.Forms.Loader/FormsLoader.cs
new file mode 100644
index 00000000..d6826830
--- /dev/null
+++ b/Xamarin.Forms.Loader/FormsLoader.cs
@@ -0,0 +1,51 @@
+using System.Collections.Generic;
+using System.Linq;
+using Xamarin.Forms.Core.UITests;
+
+namespace Xamarin.Forms.Loader
+{
+ internal sealed class FormsLoader
+ {
+ static IEnumerable<FormsType> formsTypes;
+ static IEnumerable<TestType> iOSTestTypes;
+ static IEnumerable<TestType> androidTestTypes;
+
+ public FormsLoader()
+ {
+ var formsCoreAssembly = typeof (View).Assembly;
+ var iOSUITestAssembly = typeof (iOSLoaderIdentifier).Assembly;
+ var androidUITestAssembly = typeof (AndroidLoaderIdentifier).Assembly;
+
+ // skip interfaces, delegates, classes that inherit from attribute
+ formsTypes =
+ from o in formsCoreAssembly.GetTypes()
+ where o.IsVisible && o.IsClass && !o.IsDelegate() && !o.InheritsFromAttribute() && !o.InheritsFromException()
+ select new FormsType(this, o);
+
+ iOSTestTypes =
+ from o in iOSUITestAssembly.GetTypes()
+ where o.IsTestFixture() && o.HasCategoryAttribute()
+ select new TestType(this, o);
+
+ androidTestTypes =
+ from o in androidUITestAssembly.GetTypes()
+ where o.IsTestFixture() && o.HasCategoryAttribute()
+ select new TestType(this, o);
+ }
+
+ public IEnumerable<FormsType> FormsTypes()
+ {
+ return formsTypes;
+ }
+
+ public IEnumerable<TestType> IOSTestTypes()
+ {
+ return iOSTestTypes;
+ }
+
+ public IEnumerable<TestType> AndroidTestTypes()
+ {
+ return androidTestTypes;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/FormsMember.cs b/Xamarin.Forms.Loader/FormsMember.cs
new file mode 100644
index 00000000..1d12ddf9
--- /dev/null
+++ b/Xamarin.Forms.Loader/FormsMember.cs
@@ -0,0 +1,17 @@
+using System.Reflection;
+
+namespace Xamarin.Forms.Loader
+{
+ internal sealed class FormsMember : ILoaderElement
+ {
+ internal FormsMember(FormsType formsType, MemberInfo memberInfo)
+ {
+ FormsType = formsType;
+ MemberInfo = memberInfo;
+ }
+
+ public FormsType FormsType { get; }
+
+ public MemberInfo MemberInfo { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/FormsType.cs b/Xamarin.Forms.Loader/FormsType.cs
new file mode 100644
index 00000000..44b4af7a
--- /dev/null
+++ b/Xamarin.Forms.Loader/FormsType.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Xamarin.Forms.Loader
+{
+ internal sealed class FormsType : ILoaderElement
+ {
+ readonly IEnumerable<FormsMember> formsMembers;
+
+ internal FormsType(FormsLoader formsLoader, Type type)
+ {
+ FormsLoader = formsLoader;
+ Type = type;
+
+ const BindingFlags bindingFlags = BindingFlags.DeclaredOnly |
+ BindingFlags.Public |
+ BindingFlags.Instance |
+ BindingFlags.Static;
+
+ const MemberTypes memberTypes = MemberTypes.Event |
+ MemberTypes.Method |
+ MemberTypes.Property;
+
+ formsMembers =
+ from o in Type.GetMember("*", memberTypes, bindingFlags)
+ where
+ o.IsPublic() &&
+ !o.IsCompilerGenerated() &&
+ !o.IsEqualityOverride() &&
+ !o.IsToStringOverride() &&
+ !LoaderExtensions.IsUnitTested(type, o)
+ select new FormsMember(this, o);
+ }
+
+ public FormsLoader FormsLoader { get; }
+
+ public Type Type { get; }
+
+ public IEnumerable<FormsMember> Members()
+ {
+ return formsMembers;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/ILoaderElement.cs b/Xamarin.Forms.Loader/ILoaderElement.cs
new file mode 100644
index 00000000..7d703fdb
--- /dev/null
+++ b/Xamarin.Forms.Loader/ILoaderElement.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms.Loader
+{
+ internal interface ILoaderElement
+ {
+ string ToString();
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/InvalidTestCloudUploadParameters.cs b/Xamarin.Forms.Loader/InvalidTestCloudUploadParameters.cs
new file mode 100644
index 00000000..a48cd587
--- /dev/null
+++ b/Xamarin.Forms.Loader/InvalidTestCloudUploadParameters.cs
@@ -0,0 +1,17 @@
+namespace Xamarin.Forms.Loader
+{
+ public sealed class InvalidTestCloudUploadParameters : LoaderException
+ {
+ readonly string parameters;
+
+ public InvalidTestCloudUploadParameters(string parameters)
+ {
+ this.parameters = parameters;
+ }
+
+ public override string Message
+ {
+ get { return "Missing Category attribute: " + parameters; }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/LoaderException.cs b/Xamarin.Forms.Loader/LoaderException.cs
new file mode 100644
index 00000000..895a5198
--- /dev/null
+++ b/Xamarin.Forms.Loader/LoaderException.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace Xamarin.Forms.Loader
+{
+ public class LoaderException : Exception
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/LoaderExtensions.cs b/Xamarin.Forms.Loader/LoaderExtensions.cs
new file mode 100644
index 00000000..9c0b91fa
--- /dev/null
+++ b/Xamarin.Forms.Loader/LoaderExtensions.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using NUnit.Framework;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Loader
+{
+ internal static class LoaderExtensions
+ {
+ public static bool InheritsFromException(this Type type)
+ {
+ if (type.IsSubclassOf(typeof (Exception)))
+ return true;
+ return false;
+ }
+
+ public static bool InheritsFromAttribute(this Type type)
+ {
+ if (type.IsSubclassOf(typeof (Attribute)))
+ return true;
+ return false;
+ }
+
+ public static bool IsDelegate(this Type type)
+ {
+ // ignore delegates
+ if (type.BaseType == typeof (MulticastDelegate))
+ return true;
+ return false;
+ }
+
+ public static bool IsTestFixture(this Type type)
+ {
+ var attributes = type.GetCustomAttributes();
+ if (attributes.OfType<TestFixtureAttribute>().Any())
+ return true;
+ return false;
+ }
+
+ public static bool HasTestAttribute(this MemberInfo memberInfo)
+ {
+ var attributes = memberInfo.GetCustomAttributes();
+ return attributes.Any(attr => attr is UiTestAttribute);
+ }
+
+ public static bool IsUnitTested(Type type, MemberInfo memberInfo)
+ {
+ if (ExemptMembers.UnitTestedTypes.ContainsKey(type))
+ {
+ if (ExemptMembers.UnitTestedTypes[type].Contains(memberInfo.Name))
+ return true;
+ }
+ return false;
+ }
+
+ public static bool HasTestExemptAttribute(this MemberInfo memberInfo)
+ {
+ var attributes = memberInfo.GetCustomAttributes();
+ return attributes.Any(attr => attr is UiTestExemptAttribute);
+ }
+
+ public static bool IsSetupOrTearDown(this MemberInfo memberInfo)
+ {
+ var attributes = memberInfo.GetCustomAttributes();
+ return
+ attributes.Any(
+ attr =>
+ attr is SetUpAttribute || attr is TearDownAttribute || attr is TestFixtureSetUpAttribute ||
+ attr is TestFixtureTearDownAttribute);
+ }
+
+ public static bool IsEqualityOverride(this MemberInfo memberInfo)
+ {
+ return
+ memberInfo.Name == "Equals" ||
+ memberInfo.Name == "GetHashCode" ||
+ memberInfo.Name == "GetType";
+ }
+
+ public static bool IsToStringOverride(this MemberInfo memberInfo)
+ {
+ return memberInfo.Name == "ToString";
+ }
+
+ public static bool HasCategoryAttribute(this Type type)
+ {
+ var attributes = type.GetCustomAttributes();
+ if (attributes.OfType<CategoryAttribute>().Any())
+ return true;
+ //throw new MissingCategoryOnTestFixtureException (type.Name);
+ return false;
+ }
+
+ public static bool IsPublic(this MemberInfo memberInfo)
+ {
+ var type = memberInfo as Type;
+ if (type != null)
+ return type.IsPublic;
+
+ var method = memberInfo as MethodInfo;
+ if (method != null)
+ return method.IsPublic;
+
+ var property = memberInfo as PropertyInfo;
+ if (property != null)
+ return true; // binding flags determine public
+
+ var evt = memberInfo as EventInfo;
+ if (evt != null)
+ return true; // binding flags determine public
+
+ throw new LoaderException();
+ }
+
+ public static bool IsCompilerGenerated(this MemberInfo memberInfo)
+ {
+ // ignore autogenerated get_ and set_ methods
+ var method = memberInfo as MethodInfo;
+ if (method != null && method.IsSpecialName)
+ return true;
+
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/Logger.cs b/Xamarin.Forms.Loader/Logger.cs
new file mode 100644
index 00000000..ad0877e8
--- /dev/null
+++ b/Xamarin.Forms.Loader/Logger.cs
@@ -0,0 +1,30 @@
+using System.IO;
+
+namespace Xamarin.Forms.Loader
+{
+ internal static class Logger
+ {
+ static StreamWriter writer;
+
+ public static void Init()
+ {
+ writer = new StreamWriter("../../Logs/Xamarin.Forms.UITest.Validator.log", false);
+ }
+
+ public static void Log(string text)
+ {
+ writer.WriteLine(text);
+ }
+
+ public static void LogLine(string line = "")
+ {
+ writer.WriteLine(line);
+ }
+
+ public static void Close()
+ {
+ writer.Flush();
+ writer.Close();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/LoggerWriter.cs b/Xamarin.Forms.Loader/LoggerWriter.cs
new file mode 100644
index 00000000..98939795
--- /dev/null
+++ b/Xamarin.Forms.Loader/LoggerWriter.cs
@@ -0,0 +1,8 @@
+namespace Xamarin.Forms.Loader
+{
+ internal enum LoggerWriter
+ {
+ Core,
+ Test
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/MissingCategoryOnTestFixtureException.cs b/Xamarin.Forms.Loader/MissingCategoryOnTestFixtureException.cs
new file mode 100644
index 00000000..a4cd4348
--- /dev/null
+++ b/Xamarin.Forms.Loader/MissingCategoryOnTestFixtureException.cs
@@ -0,0 +1,17 @@
+namespace Xamarin.Forms.Loader
+{
+ public sealed class MissingCategoryOnTestFixtureException : LoaderException
+ {
+ readonly string fixtureName;
+
+ public MissingCategoryOnTestFixtureException(string fixtureName)
+ {
+ this.fixtureName = fixtureName;
+ }
+
+ public override string Message
+ {
+ get { return "Missing Category attribute: " + fixtureName; }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/Properties/AssemblyInfo.cs b/Xamarin.Forms.Loader/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..b9ca2d1a
--- /dev/null
+++ b/Xamarin.Forms.Loader/Properties/AssemblyInfo.cs
@@ -0,0 +1,42 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Xamarin.Form.FormsLoader")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Form.FormsLoader")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("c1b9ec92-9f75-41a1-a3fa-e88d59af6794")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.UITest.Validator")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.UITest.TestCloud")] \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/TestMember.cs b/Xamarin.Forms.Loader/TestMember.cs
new file mode 100644
index 00000000..95eb0ec9
--- /dev/null
+++ b/Xamarin.Forms.Loader/TestMember.cs
@@ -0,0 +1,43 @@
+using System.Collections.Generic;
+using System.Reflection;
+using NUnit.Framework;
+using Xamarin.Forms.CustomAttributes;
+
+namespace Xamarin.Forms.Loader
+{
+ internal sealed class TestMember : ILoaderElement
+ {
+ readonly IEnumerable<CategoryAttribute> categoryAttributes;
+
+ readonly IEnumerable<UiTestAttribute> uiTestAttributes;
+
+ public TestMember(TestType uiTestType, MemberInfo memberInfo)
+ {
+ DeclaringType = uiTestType;
+ MemberInfo = memberInfo;
+
+ // handle public overrides that inherit attributes
+ uiTestAttributes = memberInfo.GetCustomAttributes<UiTestAttribute>();
+ categoryAttributes = memberInfo.GetCustomAttributes<CategoryAttribute>();
+ }
+
+ internal FormsLoader FormsLoader
+ {
+ get { return DeclaringType.FormsLoader; }
+ }
+
+ public TestType DeclaringType { get; }
+
+ public MemberInfo MemberInfo { get; }
+
+ public IEnumerable<UiTestAttribute> UiTestAttributes()
+ {
+ return uiTestAttributes;
+ }
+
+ public IEnumerable<CategoryAttribute> CategoryAttributes()
+ {
+ return categoryAttributes;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/TestType.cs b/Xamarin.Forms.Loader/TestType.cs
new file mode 100644
index 00000000..50e0e639
--- /dev/null
+++ b/Xamarin.Forms.Loader/TestType.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Loader
+{
+ internal sealed class TestType : ILoaderElement
+ {
+ readonly IEnumerable<CategoryAttribute> _categories;
+ readonly IEnumerable<TestMember> _members;
+
+ internal TestType(FormsLoader formsLoader, Type type)
+ {
+ FormsLoader = formsLoader;
+ Type = type;
+
+ _members =
+ from o in Type.GetMethods()
+ where !o.IsSetupOrTearDown() && !o.IsEqualityOverride() && !o.IsToStringOverride()
+ select new TestMember(this, o);
+
+ _categories = type.GetCustomAttributes<CategoryAttribute>();
+ }
+
+ public FormsLoader FormsLoader { get; }
+
+ public Type Type { get; }
+
+ public IEnumerable<TestMember> Members()
+ {
+ return _members;
+ }
+
+ public IEnumerable<CategoryAttribute> Categories()
+ {
+ return _categories;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/Xamarin.Forms.Loader.csproj b/Xamarin.Forms.Loader/Xamarin.Forms.Loader.csproj
new file mode 100644
index 00000000..8bb0151d
--- /dev/null
+++ b/Xamarin.Forms.Loader/Xamarin.Forms.Loader.csproj
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{00211725-2F89-4E2C-AC5A-38E5FF61BE67}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Loader</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Loader</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="ExemptMembers.cs" />
+ <Compile Include="FormsMember.cs" />
+ <Compile Include="FormsType.cs" />
+ <Compile Include="ILoaderElement.cs" />
+ <Compile Include="FormsLoader.cs" />
+ <Compile Include="InvalidTestCloudUploadParameters.cs" />
+ <Compile Include="LoaderException.cs" />
+ <Compile Include="LoaderExtensions.cs" />
+ <Compile Include="Logger.cs" />
+ <Compile Include="LoggerWriter.cs" />
+ <Compile Include="MissingCategoryOnTestFixtureException.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="TestMember.cs" />
+ <Compile Include="TestType.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core.Android.UITests\Xamarin.Forms.Core.Android.UITests.csproj">
+ <Project>{a34ebe01-25bf-4e69-a2dc-2288dc625541}</Project>
+ <Name>Xamarin.Forms.Core.Android.UITests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Core.iOS.UITests\Xamarin.Forms.Core.iOS.UITests.csproj">
+ <Project>{eadd8100-b3ae-4a31-92c4-267a64a1c6eb}</Project>
+ <Name>Xamarin.Forms.Core.iOS.UITests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.CustomAttributes\Xamarin.Forms.CustomAttributes.csproj">
+ <Project>{4dcd0420-1168-4b77-86db-6196ee4bd491}</Project>
+ <Name>Xamarin.Forms.CustomAttributes</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+ </Target>
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Loader/packages.config b/Xamarin.Forms.Loader/packages.config
new file mode 100644
index 00000000..c714ef3a
--- /dev/null
+++ b/Xamarin.Forms.Loader/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit" version="2.6.4" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.Android/FormsMaps.cs b/Xamarin.Forms.Maps.Android/FormsMaps.cs
new file mode 100644
index 00000000..76fc48d4
--- /dev/null
+++ b/Xamarin.Forms.Maps.Android/FormsMaps.cs
@@ -0,0 +1,43 @@
+using System;
+using Android.App;
+using Android.Content;
+using Android.Gms.Common;
+using Android.Gms.Maps;
+using Android.OS;
+using Xamarin.Forms.Maps.Android;
+
+namespace Xamarin
+{
+ public static class FormsMaps
+ {
+ public static bool IsInitialized { get; private set; }
+
+ public static Context Context { get; private set; }
+
+ public static void Init(Activity activity, Bundle bundle)
+ {
+ if (IsInitialized)
+ return;
+ IsInitialized = true;
+
+ Context = activity;
+
+ MapRenderer.Bundle = bundle;
+
+ if (GooglePlayServicesUtil.IsGooglePlayServicesAvailable(Context) == ConnectionResult.Success)
+ {
+ try
+ {
+ MapsInitializer.Initialize(Context);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Google Play Services Not Found");
+ Console.WriteLine("Exception: {0}", e);
+ }
+ }
+
+ GeocoderBackend.Register(Context);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.Android/GeocoderBackend.cs b/Xamarin.Forms.Maps.Android/GeocoderBackend.cs
new file mode 100644
index 00000000..34a08b0a
--- /dev/null
+++ b/Xamarin.Forms.Maps.Android/GeocoderBackend.cs
@@ -0,0 +1,36 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Android.Content;
+using Android.Locations;
+using AGeocoder = Android.Locations.Geocoder;
+
+namespace Xamarin.Forms.Maps.Android
+{
+ internal class GeocoderBackend
+ {
+ public static void Register(Context context)
+ {
+ Geocoder.GetPositionsForAddressAsyncFunc = GetPositionsForAddressAsync;
+ Geocoder.GetAddressesForPositionFuncAsync = GetAddressesForPositionAsync;
+ }
+
+ public static async Task<IEnumerable<Position>> GetPositionsForAddressAsync(string address)
+ {
+ var geocoder = new AGeocoder(Forms.Context);
+ IList<Address> addresses = await geocoder.GetFromLocationNameAsync(address, 5);
+ return addresses.Select(p => new Position(p.Latitude, p.Longitude));
+ }
+
+ public static async Task<IEnumerable<string>> GetAddressesForPositionAsync(Position position)
+ {
+ var geocoder = new AGeocoder(Forms.Context);
+ IList<Address> addresses = await geocoder.GetFromLocationAsync(position.Latitude, position.Longitude, 5);
+ return addresses.Select(p =>
+ {
+ IEnumerable<string> lines = Enumerable.Range(0, p.MaxAddressLineIndex + 1).Select(p.GetAddressLine);
+ return string.Join("\n", lines);
+ });
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.Android/MapRenderer.cs b/Xamarin.Forms.Maps.Android/MapRenderer.cs
new file mode 100644
index 00000000..20cb1229
--- /dev/null
+++ b/Xamarin.Forms.Maps.Android/MapRenderer.cs
@@ -0,0 +1,308 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using Android.Gms.Maps;
+using Android.Gms.Maps.Model;
+using Android.OS;
+using Java.Lang;
+using Xamarin.Forms.Platform.Android;
+using Math = System.Math;
+using Android.Runtime;
+using System.Collections;
+
+namespace Xamarin.Forms.Maps.Android
+{
+ public class MapRenderer : ViewRenderer,
+ GoogleMap.IOnCameraChangeListener
+ {
+ public MapRenderer ()
+ {
+ AutoPackage = false;
+ }
+
+ static Bundle s_bundle;
+ internal static Bundle Bundle { set { s_bundle = value; } }
+
+ List<Marker> _markers;
+
+ const string MoveMessageName = "MapMoveToRegion";
+
+ protected GoogleMap NativeMap => ((MapView) Control).Map;
+
+ protected Map Map => (Map) Element;
+
+ public override SizeRequest GetDesiredSize (int widthConstraint, int heightConstraint)
+ {
+ return new SizeRequest (new Size (Context.ToPixels (40), Context.ToPixels (40)));
+ }
+
+ protected override void OnElementChanged (ElementChangedEventArgs<View> e)
+ {
+ base.OnElementChanged (e);
+
+ var oldMapView = (MapView)Control;
+
+ var mapView = new MapView (Context);
+ mapView.OnCreate (s_bundle);
+ mapView.OnResume ();
+ SetNativeControl (mapView);
+
+ if (e.OldElement != null) {
+ var oldMapModel = (Map) e.OldElement;
+ ((ObservableCollection<Pin>)oldMapModel.Pins).CollectionChanged -= OnCollectionChanged;
+
+ MessagingCenter.Unsubscribe<Map, MapSpan> (this, MoveMessageName);
+
+ if (oldMapView.Map != null) {
+ oldMapView.Map.SetOnCameraChangeListener (null);
+ NativeMap.InfoWindowClick -= MapOnMarkerClick;
+ }
+
+ oldMapView.Dispose();
+ }
+
+ var map = NativeMap;
+ if (map != null) {
+ map.SetOnCameraChangeListener (this);
+ NativeMap.InfoWindowClick += MapOnMarkerClick;
+
+ map.UiSettings.ZoomControlsEnabled = Map.HasZoomEnabled;
+ map.UiSettings.ZoomGesturesEnabled = Map.HasZoomEnabled;
+ map.UiSettings.ScrollGesturesEnabled = Map.HasScrollEnabled;
+ map.MyLocationEnabled = map.UiSettings.MyLocationButtonEnabled = Map.IsShowingUser;
+ SetMapType ();
+ }
+
+ MessagingCenter.Subscribe<Map, MapSpan> (this, MoveMessageName, OnMoveToRegionMessage, Map);
+
+ var incc = Map.Pins as INotifyCollectionChanged;
+ if (incc != null)
+ incc.CollectionChanged += OnCollectionChanged;
+ }
+
+ void OnCollectionChanged (object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
+ {
+ switch (notifyCollectionChangedEventArgs.Action) {
+ case NotifyCollectionChangedAction.Add:
+ AddPins (notifyCollectionChangedEventArgs.NewItems);
+ break;
+ case NotifyCollectionChangedAction.Remove:
+ RemovePins (notifyCollectionChangedEventArgs.OldItems);
+ break;
+ case NotifyCollectionChangedAction.Replace:
+ RemovePins (notifyCollectionChangedEventArgs.OldItems);
+ AddPins (notifyCollectionChangedEventArgs.NewItems);
+ break;
+ case NotifyCollectionChangedAction.Reset:
+ _markers?.ForEach (m => m.Remove ());
+ _markers = null;
+ AddPins ((IList)(Element as Map).Pins);
+ break;
+ case NotifyCollectionChangedAction.Move:
+ //do nothing
+ break;
+ }
+ }
+
+ void OnMoveToRegionMessage (Map s, MapSpan a)
+ {
+ MoveToRegion (a, true);
+ }
+
+ void MoveToRegion (MapSpan span, bool animate)
+ {
+ var map = NativeMap;
+ if (map == null)
+ return;
+
+ span = span.ClampLatitude (85, -85);
+ var ne = new LatLng (span.Center.Latitude + span.LatitudeDegrees / 2, span.Center.Longitude + span.LongitudeDegrees / 2);
+ var sw = new LatLng (span.Center.Latitude - span.LatitudeDegrees / 2, span.Center.Longitude - span.LongitudeDegrees / 2);
+ var update = CameraUpdateFactory.NewLatLngBounds (new LatLngBounds (sw, ne), 0);
+
+ try {
+ if (animate)
+ map.AnimateCamera (update);
+ else
+ map.MoveCamera (update);
+ } catch (IllegalStateException exc) {
+ System.Diagnostics.Debug.WriteLine ("MoveToRegion exception: " + exc);
+ }
+ }
+
+ bool _init = true;
+
+ protected override void OnLayout (bool changed, int l, int t, int r, int b)
+ {
+ base.OnLayout (changed, l, t, r, b);
+
+ if (_init) {
+ MoveToRegion (((Map)Element).LastMoveToRegion, false);
+ OnCollectionChanged (((Map)Element).Pins, new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Reset));
+ _init = false;
+ } else if (changed) {
+ UpdateVisibleRegion (NativeMap.CameraPosition.Target);
+ }
+ }
+
+ protected override void OnElementPropertyChanged (object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged (sender, e);
+
+ if (e.PropertyName == Map.MapTypeProperty.PropertyName) {
+ SetMapType();
+ return;
+ }
+
+ var gmap = NativeMap;
+ if (gmap == null)
+ return;
+
+ if (e.PropertyName == Map.IsShowingUserProperty.PropertyName)
+ gmap.MyLocationEnabled = gmap.UiSettings.MyLocationButtonEnabled = Map.IsShowingUser;
+ else if (e.PropertyName == Map.HasScrollEnabledProperty.PropertyName)
+ gmap.UiSettings.ScrollGesturesEnabled = Map.HasScrollEnabled;
+ else if (e.PropertyName == Map.HasZoomEnabledProperty.PropertyName) {
+ gmap.UiSettings.ZoomControlsEnabled = Map.HasZoomEnabled;
+ gmap.UiSettings.ZoomGesturesEnabled = Map.HasZoomEnabled;
+ }
+ }
+
+ void SetMapType ()
+ {
+ var map = NativeMap;
+ if (map == null)
+ return;
+
+ switch (Map.MapType) {
+ case MapType.Street:
+ map.MapType = GoogleMap.MapTypeNormal;
+ break;
+ case MapType.Satellite:
+ map.MapType = GoogleMap.MapTypeSatellite;
+ break;
+ case MapType.Hybrid:
+ map.MapType = GoogleMap.MapTypeHybrid;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+ }
+
+ public void OnCameraChange (CameraPosition pos)
+ {
+ UpdateVisibleRegion (pos.Target);
+ }
+
+ void UpdateVisibleRegion (LatLng pos)
+ {
+ var map = NativeMap;
+ if (map == null)
+ return;
+ var projection = map.Projection;
+ var width = Control.Width;
+ var height = Control.Height;
+ var ul = projection.FromScreenLocation (new global::Android.Graphics.Point (0, 0));
+ var ur = projection.FromScreenLocation (new global::Android.Graphics.Point (width, 0));
+ var ll = projection.FromScreenLocation (new global::Android.Graphics.Point (0, height));
+ var lr = projection.FromScreenLocation (new global::Android.Graphics.Point (width, height));
+ var dlat = Math.Max (Math.Abs (ul.Latitude - lr.Latitude), Math.Abs (ur.Latitude - ll.Latitude));
+ var dlong = Math.Max (Math.Abs (ul.Longitude - lr.Longitude), Math.Abs (ur.Longitude - ll.Longitude));
+ ((Map)Element).VisibleRegion = new MapSpan (
+ new Position (
+ pos.Latitude,
+ pos.Longitude
+ ),
+ dlat,
+ dlong
+ );
+ }
+
+ void AddPins (IList pins)
+ {
+ var map = NativeMap;
+ if (map == null)
+ return;
+
+ if (_markers == null)
+ _markers = new List<Marker> ();
+
+ _markers.AddRange( pins.Cast<Pin>().Select (p => {
+ var pin = (Pin)p;
+ var opts = new MarkerOptions ();
+ opts.SetPosition (new LatLng (pin.Position.Latitude, pin.Position.Longitude));
+ opts.SetTitle (pin.Label);
+ opts.SetSnippet (pin.Address);
+ var marker = map.AddMarker (opts);
+
+ // associate pin with marker for later lookup in event handlers
+ pin.Id = marker.Id;
+ return marker;
+ }));
+ }
+
+ void RemovePins (IList pins)
+ {
+ var map = NativeMap;
+ if (map == null)
+ return;
+ if (_markers == null)
+ return;
+
+ foreach (Pin p in pins) {
+ var marker = _markers.FirstOrDefault (m => m.Id == p.Id);
+ if (marker == null)
+ continue;
+ marker.Remove ();
+ _markers.Remove (marker);
+ }
+ }
+
+ void MapOnMarkerClick (object sender, GoogleMap.InfoWindowClickEventArgs eventArgs)
+ {
+ // clicked marker
+ var marker = eventArgs.Marker;
+
+ // lookup pin
+ Pin targetPin = null;
+ for (var i = 0; i < Map.Pins.Count; i++) {
+ var pin = Map.Pins[i];
+ if ((string)pin.Id != marker.Id)
+ continue;
+
+ targetPin = pin;
+ break;
+ }
+
+ // only consider event handled if a handler is present.
+ // Else allow default behavior of displaying an info window.
+ targetPin?.SendTap ();
+ }
+
+ bool _disposed;
+ protected override void Dispose (bool disposing)
+ {
+ if (disposing && !_disposed) {
+ _disposed = true;
+
+ var mapModel = Element as Map;
+ if (mapModel != null) {
+ MessagingCenter.Unsubscribe<Map, MapSpan> (this, MoveMessageName);
+ ((ObservableCollection<Pin>)mapModel.Pins).CollectionChanged -= OnCollectionChanged;
+ }
+
+ var gmap = NativeMap;
+ if (gmap == null)
+ return;
+ gmap.MyLocationEnabled = false;
+ gmap.InfoWindowClick -= MapOnMarkerClick;
+ gmap.Dispose ();
+ }
+
+ base.Dispose (disposing);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Maps.Android/Properties/AssemblyInfo.cs b/Xamarin.Forms.Maps.Android/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..efdb17b1
--- /dev/null
+++ b/Xamarin.Forms.Maps.Android/Properties/AssemblyInfo.cs
@@ -0,0 +1,23 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Android;
+using Android.App;
+using Xamarin.Forms;
+using Xamarin.Forms.Maps;
+using Xamarin.Forms.Maps.Android;
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Xamarin.Forms.Maps.Android")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+
+// Add some common permissions, these can be removed if not needed
+
+[assembly: UsesPermission(Manifest.Permission.Internet)]
+[assembly: UsesPermission(Manifest.Permission.WriteExternalStorage)]
+[assembly: ExportRenderer(typeof (Map), typeof (MapRenderer))]
+[assembly: Preserve] \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.Android/Xamarin.Forms.Maps.Android.csproj b/Xamarin.Forms.Maps.Android/Xamarin.Forms.Maps.Android.csproj
new file mode 100644
index 00000000..293d9221
--- /dev/null
+++ b/Xamarin.Forms.Maps.Android/Xamarin.Forms.Maps.Android.csproj
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{BD50B39A-EBC5-408F-9C5E-923A8EBAE473}</ProjectGuid>
+ <ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Maps.Android</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Maps.Android</AssemblyName>
+ <FileAlignment>512</FileAlignment>
+ <AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+ <AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
+ <TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Mono.Android" />
+ <Reference Include="mscorlib" />
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Xml" />
+ <Reference Include="Xamarin.Android.Support.v4, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.Android.Support.v4.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.Android.Support.v7.AppCompat, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.Android.Support.v7.AppCompat.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.v7.AppCompat.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.Android.Support.v7.MediaRouter, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.Android.Support.v7.MediaRouter.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.v7.MediaRouter.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.GooglePlayServices.Base, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.GooglePlayServices.Base.29.0.0.1\lib\MonoAndroid41\Xamarin.GooglePlayServices.Base.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.GooglePlayServices.Basement, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.GooglePlayServices.Basement.29.0.0.1\lib\MonoAndroid41\Xamarin.GooglePlayServices.Basement.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.GooglePlayServices.Maps, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.GooglePlayServices.Maps.29.0.0.1\lib\MonoAndroid41\Xamarin.GooglePlayServices.Maps.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="MapRenderer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="FormsMaps.cs" />
+ <Compile Include="GeocoderBackend.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7d13bac2-c6a4-416a-b07e-c169b199e52b}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.Android.FormsViewGroup\Xamarin.Forms.Platform.Android.FormsViewGroup.csproj">
+ <Project>{3b72465b-acae-43ae-9327-10f372fe5f80}</Project>
+ <Name>Xamarin.Forms.Platform.Android.FormsViewGroup</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.Android\Xamarin.Forms.Platform.Android.csproj">
+ <Project>{0e16e70a-d6dd-4323-ad5d-363abff42d6a}</Project>
+ <Name>Xamarin.Forms.Platform.Android</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.Android/packages.config b/Xamarin.Forms.Maps.Android/packages.config
new file mode 100644
index 00000000..3873ad93
--- /dev/null
+++ b/Xamarin.Forms.Maps.Android/packages.config
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Xamarin.Android.Support.v4" version="23.1.1.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.Android.Support.v7.AppCompat" version="23.1.1.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.Android.Support.v7.MediaRouter" version="23.1.1.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.GooglePlayServices.Base" version="29.0.0.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.GooglePlayServices.Basement" version="29.0.0.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.GooglePlayServices.Maps" version="29.0.0.1" targetFramework="monoandroid60" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.Design/Properties/AssemblyInfo.cs b/Xamarin.Forms.Maps.Design/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..f404023d
--- /dev/null
+++ b/Xamarin.Forms.Maps.Design/Properties/AssemblyInfo.cs
@@ -0,0 +1,5 @@
+using System.Reflection;
+using Microsoft.Windows.Design.Metadata;
+
+[assembly: AssemblyTitle("Xamarin.Forms.Maps.Design")]
+[assembly: AssemblyDescription("Provides the design-time metadata for the XAML language service.")]
diff --git a/Xamarin.Forms.Maps.Design/Xamarin.Forms.Maps.Design.csproj b/Xamarin.Forms.Maps.Design/Xamarin.Forms.Maps.Design.csproj
new file mode 100644
index 00000000..5b271070
--- /dev/null
+++ b/Xamarin.Forms.Maps.Design/Xamarin.Forms.Maps.Design.csproj
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Maps.Design</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Maps.Design</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile />
+ <NuGetPackageImportStamp>
+ </NuGetPackageImportStamp>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup Condition=" '$(OS)' != 'Unix' ">
+ <Reference Include="Microsoft.Windows.Design.Extensibility, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=x86">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\lib\Microsoft.Windows.Design.Extensibility.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Xaml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup Condition=" '$(OS)' != 'Unix' ">
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7d13bac2-c6a4-416a-b07e-c169b199e52b}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="..\packages\Xamarin.Forms.Design.1.0.14-pre\build\Xamarin.Forms.Design.targets" Condition="Exists('..\packages\Xamarin.Forms.Design.1.0.14-pre\build\Xamarin.Forms.Design.targets') And '$(OS)' != 'Unix'" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild" Condition=" '$(OS)' != 'Unix' ">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('..\packages\Xamarin.Forms.Design.1.0.14-pre\build\Xamarin.Forms.Design.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Forms.Design.1.0.14-pre\build\Xamarin.Forms.Design.targets'))" />
+ </Target>
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.Design/packages.config b/Xamarin.Forms.Maps.Design/packages.config
new file mode 100644
index 00000000..6e99fb80
--- /dev/null
+++ b/Xamarin.Forms.Maps.Design/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Xamarin.Forms.Design" version="1.0.14-pre" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.UWP/FormsMaps.cs b/Xamarin.Forms.Maps.UWP/FormsMaps.cs
new file mode 100644
index 00000000..ee631355
--- /dev/null
+++ b/Xamarin.Forms.Maps.UWP/FormsMaps.cs
@@ -0,0 +1,32 @@
+#if WINDOWS_UWP
+using Xamarin.Forms.Maps.UWP;
+
+#else
+using Xamarin.Forms.Maps.WinRT;
+
+#endif
+
+namespace Xamarin
+{
+ public static class FormsMaps
+ {
+ static bool s_isInitialized;
+
+ internal static string AuthenticationToken { get; set; }
+
+ public static void Init()
+ {
+ if (s_isInitialized)
+ return;
+ GeocoderBackend.Register();
+ s_isInitialized = true;
+ }
+
+ public static void Init(string authenticationToken)
+ {
+ AuthenticationToken = authenticationToken;
+
+ Init();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.UWP/GeocoderBackend.cs b/Xamarin.Forms.Maps.UWP/GeocoderBackend.cs
new file mode 100644
index 00000000..10f624a6
--- /dev/null
+++ b/Xamarin.Forms.Maps.UWP/GeocoderBackend.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Windows.Devices.Geolocation;
+using Windows.Services.Maps;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Maps.UWP
+#else
+
+namespace Xamarin.Forms.Maps.WinRT
+#endif
+{
+ internal class GeocoderBackend
+ {
+ public static void Register()
+ {
+ Geocoder.GetPositionsForAddressAsyncFunc = GetPositionsForAddress;
+ Geocoder.GetAddressesForPositionFuncAsync = GetAddressesForPositionAsync;
+ }
+
+ static string AddressToString(MapAddress address)
+ {
+ string building = "", house = "", city = "", country = "";
+
+ var bldg = new List<string>();
+ if (!"".Equals(address.BuildingRoom))
+ bldg.Add(address.BuildingRoom);
+ if (!"".Equals(address.BuildingFloor))
+ bldg.Add(address.BuildingFloor);
+ if (!"".Equals(address.BuildingName))
+ bldg.Add(address.BuildingName);
+ if (!"".Equals(address.BuildingWing))
+ bldg.Add(address.BuildingWing);
+ if (bldg.Count > 0)
+ building = string.Join(" ", bldg) + Environment.NewLine;
+
+ var hs = new List<string>();
+ if (!"".Equals(address.StreetNumber))
+ hs.Add(address.StreetNumber);
+ if (!"".Equals(address.Street))
+ hs.Add(address.Street);
+ if (hs.Count > 0)
+ house = string.Join(" ", hs) + Environment.NewLine;
+
+ var cs = new List<string>();
+ if (!"".Equals(address.Town))
+ cs.Add(address.Town);
+ if (!"".Equals(address.Neighborhood))
+ cs.Add(address.Neighborhood);
+ else if (!"".Equals(address.Region))
+ cs.Add(address.Region);
+ if (!"".Equals(address.PostCode))
+ cs.Add(address.PostCode);
+ if (cs.Count > 0)
+ city = string.Join(" ", cs) + Environment.NewLine;
+
+ if (!"".Equals(address.Country))
+ country = address.Country;
+ return building + house + city + country;
+ }
+
+ static async Task<IEnumerable<string>> GetAddressesForPositionAsync(Position position)
+ {
+ var queryResults =
+ await
+ MapLocationFinder.FindLocationsAtAsync(
+ new Geopoint(new BasicGeoposition { Latitude = position.Latitude, Longitude = position.Longitude }));
+ var addresses = new List<string>();
+ foreach (var result in queryResults?.Locations)
+ addresses.Add(AddressToString(result.Address));
+
+ return addresses;
+ }
+
+ static async Task<IEnumerable<Position>> GetPositionsForAddress(string address)
+ {
+ var queryResults = await MapLocationFinder.FindLocationsAsync(address, null, 10);
+ var positions = new List<Position>();
+ foreach (var result in queryResults?.Locations)
+ positions.Add(new Position(result.Point.Position.Latitude, result.Point.Position.Longitude));
+ return positions;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.UWP/MapRenderer.cs b/Xamarin.Forms.Maps.UWP/MapRenderer.cs
new file mode 100644
index 00000000..4d3564e7
--- /dev/null
+++ b/Xamarin.Forms.Maps.UWP/MapRenderer.cs
@@ -0,0 +1,297 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading.Tasks;
+using Windows.Devices.Geolocation;
+using Windows.UI;
+using Windows.UI.Xaml.Controls.Maps;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Shapes;
+#if WINDOWS_UWP
+using Xamarin.Forms.Platform.UWP;
+
+#else
+using Xamarin.Forms.Platform.WinRT;
+
+#endif
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Maps.UWP
+#else
+
+namespace Xamarin.Forms.Maps.WinRT
+#endif
+{
+ public class MapRenderer : ViewRenderer<Map, MapControl>
+ {
+ protected override async void OnElementChanged(ElementChangedEventArgs<Map> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ {
+ var mapModel = e.OldElement;
+ MessagingCenter.Unsubscribe<Map, MapSpan>(this, "MapMoveToRegion");
+ ((ObservableCollection<Pin>)mapModel.Pins).CollectionChanged -= OnCollectionChanged;
+ }
+
+ if (e.NewElement != null)
+ {
+ var mapModel = e.NewElement;
+
+ if (Control == null)
+ {
+ SetNativeControl(new MapControl());
+ Control.MapServiceToken = FormsMaps.AuthenticationToken;
+ Control.ZoomLevelChanged += async (s, a) => await UpdateVisibleRegion();
+ Control.CenterChanged += async (s, a) => await UpdateVisibleRegion();
+ }
+
+ MessagingCenter.Subscribe<Map, MapSpan>(this, "MapMoveToRegion", async (s, a) => await MoveToRegion(a), mapModel);
+
+ UpdateMapType();
+ UpdateHasScrollEnabled();
+ UpdateHasZoomEnabled();
+
+ ((ObservableCollection<Pin>)mapModel.Pins).CollectionChanged += OnCollectionChanged;
+
+ if (mapModel.Pins.Any())
+ LoadPins();
+
+ await UpdateIsShowingUser();
+ }
+ }
+
+ protected override async void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Map.MapTypeProperty.PropertyName)
+ UpdateMapType();
+ else if (e.PropertyName == Map.IsShowingUserProperty.PropertyName)
+ await UpdateIsShowingUser();
+ else if (e.PropertyName == Map.HasScrollEnabledProperty.PropertyName)
+ UpdateHasScrollEnabled();
+ else if (e.PropertyName == Map.HasZoomEnabledProperty.PropertyName)
+ UpdateHasZoomEnabled();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ _disposed = true;
+
+ MessagingCenter.Unsubscribe<Map, MapSpan>(this, "MapMoveToRegion");
+
+ if (Element != null)
+ ((ObservableCollection<Pin>)Element.Pins).CollectionChanged -= OnCollectionChanged;
+ }
+ base.Dispose(disposing);
+ }
+
+ bool _disposed;
+ bool _firstZoomLevelChangeFired;
+ Ellipse _userPositionCircle;
+
+ void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ foreach (Pin pin in e.NewItems)
+ LoadPin(pin);
+ break;
+ case NotifyCollectionChangedAction.Move:
+ // no matter
+ break;
+ case NotifyCollectionChangedAction.Remove:
+ foreach (Pin pin in e.OldItems)
+ RemovePin(pin);
+ break;
+ case NotifyCollectionChangedAction.Replace:
+ foreach (Pin pin in e.OldItems)
+ RemovePin(pin);
+ foreach (Pin pin in e.NewItems)
+ LoadPin(pin);
+ break;
+ case NotifyCollectionChangedAction.Reset:
+ ClearPins();
+ break;
+ }
+ }
+
+ void LoadPins()
+ {
+ foreach (var pin in Element.Pins)
+ LoadPin(pin);
+ }
+
+ void ClearPins()
+ {
+ Control.Children.Clear();
+ UpdateIsShowingUser();
+ }
+
+ void RemovePin(Pin pinToRemove)
+ {
+ var pushPin = Control.Children.FirstOrDefault(c =>
+ {
+ var pin = (c as PushPin);
+ return (pin != null && pin.DataContext.Equals(pinToRemove));
+ });
+
+ if (pushPin != null)
+ Control.Children.Remove(pushPin);
+ }
+
+ void LoadPin(Pin pin)
+ {
+ Control.Children.Add(new PushPin(pin));
+ }
+
+ async Task UpdateIsShowingUser()
+ {
+ if (Element.IsShowingUser)
+ {
+ var myGeolocator = new Geolocator();
+ if (myGeolocator.LocationStatus != PositionStatus.NotAvailable &&
+ myGeolocator.LocationStatus != PositionStatus.Disabled)
+ {
+ var userPosition = await myGeolocator.GetGeopositionAsync();
+ if (userPosition?.Coordinate != null)
+ LoadUserPosition(userPosition.Coordinate, true);
+ }
+ }
+ else if (_userPositionCircle != null && Control.Children.Contains(_userPositionCircle))
+ Control.Children.Remove(_userPositionCircle);
+ }
+
+ async Task MoveToRegion(MapSpan span, MapAnimationKind animation = MapAnimationKind.Bow)
+ {
+ var nw = new BasicGeoposition
+ {
+ Latitude = span.Center.Latitude + span.LatitudeDegrees / 2,
+ Longitude = span.Center.Longitude - span.LongitudeDegrees / 2
+ };
+ var se = new BasicGeoposition
+ {
+ Latitude = span.Center.Latitude - span.LatitudeDegrees / 2,
+ Longitude = span.Center.Longitude + span.LongitudeDegrees / 2
+ };
+ var boundingBox = new GeoboundingBox(nw, se);
+ await Control.TrySetViewBoundsAsync(boundingBox, null, animation);
+ }
+
+ async Task UpdateVisibleRegion()
+ {
+ if (Control == null || Element == null)
+ return;
+
+ if (!_firstZoomLevelChangeFired)
+ {
+ await MoveToRegion(Element.LastMoveToRegion, MapAnimationKind.None);
+ _firstZoomLevelChangeFired = true;
+ return;
+ }
+ Geopoint nw, se = null;
+ try
+ {
+ Control.GetLocationFromOffset(new Windows.Foundation.Point(0, 0), out nw);
+ Control.GetLocationFromOffset(new Windows.Foundation.Point(Control.ActualWidth, Control.ActualHeight), out se);
+ }
+ catch (Exception)
+ {
+ return;
+ }
+
+ if (nw != null && se != null)
+ {
+ var boundingBox = new GeoboundingBox(nw.Position, se.Position);
+ var center = new Position(boundingBox.Center.Latitude, boundingBox.Center.Longitude);
+ var latitudeDelta = Math.Abs(center.Latitude - boundingBox.NorthwestCorner.Latitude);
+ var longitudeDelta = Math.Abs(center.Longitude - boundingBox.NorthwestCorner.Longitude);
+ Element.VisibleRegion = new MapSpan(center, latitudeDelta, longitudeDelta);
+ }
+ }
+
+ void LoadUserPosition(Geocoordinate userCoordinate, bool center)
+ {
+ var userPosition = new BasicGeoposition
+ {
+ Latitude = userCoordinate.Point.Position.Latitude,
+ Longitude = userCoordinate.Point.Position.Longitude
+ };
+
+ var point = new Geopoint(userPosition);
+
+ if (_userPositionCircle == null)
+ {
+ _userPositionCircle = new Ellipse
+ {
+ Stroke = new SolidColorBrush(Colors.White),
+ Fill = new SolidColorBrush(Colors.Blue),
+ StrokeThickness = 2,
+ Height = 20,
+ Width = 20,
+ Opacity = 50
+ };
+ }
+
+ if (Control.Children.Contains(_userPositionCircle))
+ Control.Children.Remove(_userPositionCircle);
+
+ MapControl.SetLocation(_userPositionCircle, point);
+ MapControl.SetNormalizedAnchorPoint(_userPositionCircle, new Windows.Foundation.Point(0.5, 0.5));
+
+ Control.Children.Add(_userPositionCircle);
+
+ if (center)
+ {
+ Control.Center = point;
+ Control.ZoomLevel = 13;
+ }
+ }
+
+ void UpdateMapType()
+ {
+ switch (Element.MapType)
+ {
+ case MapType.Street:
+ Control.Style = MapStyle.Road;
+ break;
+ case MapType.Satellite:
+ Control.Style = MapStyle.Aerial;
+ break;
+ case MapType.Hybrid:
+ Control.Style = MapStyle.AerialWithRoads;
+ break;
+ }
+ }
+
+#if WINDOWS_UWP
+ void UpdateHasZoomEnabled()
+ {
+ Control.ZoomInteractionMode = Element.HasZoomEnabled
+ ? MapInteractionMode.GestureAndControl
+ : MapInteractionMode.ControlOnly;
+ }
+
+ void UpdateHasScrollEnabled()
+ {
+ Control.PanInteractionMode = Element.HasScrollEnabled ? MapPanInteractionMode.Auto : MapPanInteractionMode.Disabled;
+ }
+#else
+ void UpdateHasZoomEnabled()
+ {
+ }
+
+ void UpdateHasScrollEnabled()
+ {
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.UWP/Properties/AssemblyInfo.cs b/Xamarin.Forms.Maps.UWP/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..5d78702b
--- /dev/null
+++ b/Xamarin.Forms.Maps.UWP/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Xamarin.Forms.Maps;
+using Xamarin.Forms.Maps.UWP;
+using Xamarin.Forms.Platform.UWP;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Xamarin.Forms.Maps.WindowsUniversal")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)]
+[assembly: ExportRenderer(typeof (Map), typeof (MapRenderer))] \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.UWP/Properties/Xamarin.Forms.Maps.UWP.rd.xml b/Xamarin.Forms.Maps.UWP/Properties/Xamarin.Forms.Maps.UWP.rd.xml
new file mode 100644
index 00000000..275268e6
--- /dev/null
+++ b/Xamarin.Forms.Maps.UWP/Properties/Xamarin.Forms.Maps.UWP.rd.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ This file contains Runtime Directives, specifications about types your application accesses
+ through reflection and other dynamic code patterns. Runtime Directives are used to control the
+ .NET Native optimizer and ensure that it does not remove code accessed by your library. If your
+ library does not do any reflection, then you generally do not need to edit this file. However,
+ if your library reflects over types, especially types passed to it or derived from its types,
+ then you should write Runtime Directives.
+
+ The most common use of reflection in libraries is to discover information about types passed
+ to the library. Runtime Directives have three ways to express requirements on types passed to
+ your library.
+
+ 1. Parameter, GenericParameter, TypeParameter, TypeEnumerableParameter
+ Use these directives to reflect over types passed as a parameter.
+
+ 2. SubTypes
+ Use a SubTypes directive to reflect over types derived from another type.
+
+ 3. AttributeImplies
+ Use an AttributeImplies directive to indicate that your library needs to reflect over
+ types or methods decorated with an attribute.
+
+ For more information on writing Runtime Directives for libraries, please visit
+ http://go.microsoft.com/fwlink/?LinkID=391919
+-->
+<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
+ <Library Name="Xamarin.Forms.Maps.WindowsUniversal">
+
+ <!-- add directives for your library here -->
+
+ </Library>
+</Directives>
diff --git a/Xamarin.Forms.Maps.UWP/PushPin.cs b/Xamarin.Forms.Maps.UWP/PushPin.cs
new file mode 100644
index 00000000..2eaaa658
--- /dev/null
+++ b/Xamarin.Forms.Maps.UWP/PushPin.cs
@@ -0,0 +1,70 @@
+using System;
+using System.ComponentModel;
+using Windows.Devices.Geolocation;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Maps;
+using Windows.UI.Xaml.Input;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Maps.UWP
+#else
+
+namespace Xamarin.Forms.Maps.WinRT
+#endif
+{
+ internal class PushPin : ContentControl
+ {
+ readonly Pin _pin;
+
+ internal PushPin(Pin pin)
+ {
+ if (pin == null)
+ throw new ArgumentNullException();
+
+ ContentTemplate = Windows.UI.Xaml.Application.Current.Resources["pushPinTemplate"] as Windows.UI.Xaml.DataTemplate;
+ DataContext = Content = _pin = pin;
+
+ UpdateLocation();
+
+ Loaded += PushPinLoaded;
+ Unloaded += PushPinUnloaded;
+ Tapped += PushPinTapped;
+ }
+
+ void PushPinLoaded(object sender, RoutedEventArgs e)
+ {
+ _pin.PropertyChanged += PinPropertyChanged;
+ }
+
+ void PushPinUnloaded(object sender, RoutedEventArgs e)
+ {
+ _pin.PropertyChanged -= PinPropertyChanged;
+ Tapped -= PushPinTapped;
+ }
+
+ void PinPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Pin.PositionProperty.PropertyName)
+ UpdateLocation();
+ }
+
+ void PushPinTapped(object sender, TappedRoutedEventArgs e)
+ {
+ _pin.SendTap();
+ }
+
+ void UpdateLocation()
+ {
+ var anchor = new Windows.Foundation.Point(0.65, 1);
+ var location = new Geopoint(new BasicGeoposition
+ {
+ Latitude = _pin.Position.Latitude,
+ Longitude = _pin.Position.Longitude
+ });
+ MapControl.SetLocation(this, location);
+ MapControl.SetNormalizedAnchorPoint(this, anchor);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.UWP/Xamarin.Forms.Maps.UWP.csproj b/Xamarin.Forms.Maps.UWP/Xamarin.Forms.Maps.UWP.csproj
new file mode 100644
index 00000000..295a95fe
--- /dev/null
+++ b/Xamarin.Forms.Maps.UWP/Xamarin.Forms.Maps.UWP.csproj
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{04D89A60-78EF-4A32-AE17-87E47E0233A5}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Maps.UWP</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Maps.UWP</AssemblyName>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
+ <TargetPlatformVersion>10.0.10240.0</TargetPlatformVersion>
+ <TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
+ <MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <PlatformTarget>x86</PlatformTarget>
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+ <PlatformTarget>ARM</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\ARM\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+ <PlatformTarget>ARM</PlatformTarget>
+ <OutputPath>bin\ARM\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ <PlatformTarget>x64</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x64\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ <PlatformTarget>x64</PlatformTarget>
+ <OutputPath>bin\x64\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
+ <None Include="project.json" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="FormsMaps.cs" />
+ <Compile Include="GeocoderBackend.cs" />
+ <Compile Include="MapRenderer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="PushPin.cs" />
+ <EmbeddedResource Include="Properties\Xamarin.Forms.Maps.UWP.rd.xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7d13bac2-c6a4-416a-b07e-c169b199e52b}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.UAP\Xamarin.Forms.Platform.UAP.csproj">
+ <Project>{00d8d049-ffaa-4759-8fc9-1eca30777f72}</Project>
+ <Name>Xamarin.Forms.Platform.UAP</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
+ <VisualStudioVersion>14.0</VisualStudioVersion>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.UWP/project.json b/Xamarin.Forms.Maps.UWP/project.json
new file mode 100644
index 00000000..c5949392
--- /dev/null
+++ b/Xamarin.Forms.Maps.UWP/project.json
@@ -0,0 +1,16 @@
+{
+ "dependencies": {
+ "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
+ },
+ "frameworks": {
+ "uap10.0": {}
+ },
+ "runtimes": {
+ "win10-arm": {},
+ "win10-arm-aot": {},
+ "win10-x86": {},
+ "win10-x86-aot": {},
+ "win10-x64": {},
+ "win10-x64-aot": {}
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.WP8/FormsMaps.cs b/Xamarin.Forms.Maps.WP8/FormsMaps.cs
new file mode 100644
index 00000000..0f169d3d
--- /dev/null
+++ b/Xamarin.Forms.Maps.WP8/FormsMaps.cs
@@ -0,0 +1,29 @@
+using Xamarin.Forms.Maps.WP8;
+
+namespace Xamarin
+{
+ public static class FormsMaps
+ {
+ static bool s_isInitialized;
+
+ internal static string ApplicationId { get; set; }
+
+ internal static string AuthenticationToken { get; set; }
+
+ public static void Init()
+ {
+ if (s_isInitialized)
+ return;
+ GeocoderBackend.Register();
+ s_isInitialized = true;
+ }
+
+ public static void Init(string applicationId, string authenticationToken)
+ {
+ ApplicationId = applicationId;
+ AuthenticationToken = authenticationToken;
+
+ Init();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.WP8/GeocoderBackend.cs b/Xamarin.Forms.Maps.WP8/GeocoderBackend.cs
new file mode 100644
index 00000000..e46ec702
--- /dev/null
+++ b/Xamarin.Forms.Maps.WP8/GeocoderBackend.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Collections.Generic;
+using System.Device.Location;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.Phone.Maps.Services;
+
+namespace Xamarin.Forms.Maps.WP8
+{
+ internal class GeocoderBackend
+ {
+ // Eventually this should be sanely set to match either where the map is centered or where the user is.
+ internal static Position PositionForGeocoding { get; set; }
+
+ public static void Register()
+ {
+ Geocoder.GetPositionsForAddressAsyncFunc = GetPositionsForAddress;
+ Geocoder.GetAddressesForPositionFuncAsync = GetAddressesForPositionAsync;
+ }
+
+ // Thank you to craig dunn
+ static string AddressToString(MapAddress address)
+ {
+ string building = "", house = "", city = "", country = "";
+
+ var bldg = new List<string>();
+ if (!"".Equals(address.BuildingRoom))
+ bldg.Add(address.BuildingRoom);
+ if (!"".Equals(address.BuildingFloor))
+ bldg.Add(address.BuildingFloor);
+ if (!"".Equals(address.BuildingName))
+ bldg.Add(address.BuildingName);
+ if (!"".Equals(address.BuildingZone))
+ bldg.Add(address.BuildingZone);
+ if (bldg.Count > 0)
+ building = string.Join(" ", bldg) + Environment.NewLine;
+
+ var hs = new List<string>();
+ if (!"".Equals(address.HouseNumber))
+ hs.Add(address.HouseNumber);
+ if (!"".Equals(address.Street))
+ hs.Add(address.Street);
+ if (hs.Count > 0)
+ house = string.Join(" ", hs) + Environment.NewLine;
+
+ var cs = new List<string>();
+ if (!"".Equals(address.City))
+ cs.Add(address.City);
+ if (!"".Equals(address.State))
+ cs.Add(address.State);
+ else if (!"".Equals(address.Province))
+ cs.Add(address.Province);
+ if (!"".Equals(address.PostalCode))
+ cs.Add(address.PostalCode);
+ if (cs.Count > 0)
+ city = string.Join(" ", cs) + Environment.NewLine;
+
+ if (!"".Equals(address.Country))
+ country = address.Country;
+ return building + house + city + country;
+ }
+
+ static Task<IEnumerable<string>> GetAddressesForPositionAsync(Position position)
+ {
+ var source = new TaskCompletionSource<IEnumerable<string>>();
+
+ var query = new ReverseGeocodeQuery
+ {
+ GeoCoordinate = new GeoCoordinate(position.Latitude, position.Longitude)
+ };
+ query.QueryCompleted +=
+ (sender, args) => source.SetResult(args.Result.Select(r => AddressToString(r.Information.Address)).ToArray());
+ query.QueryAsync();
+
+ return source.Task;
+ }
+
+ static Task<IEnumerable<Position>> GetPositionsForAddress(string s)
+ {
+ var source = new TaskCompletionSource<IEnumerable<Position>>();
+ var query = new GeocodeQuery
+ {
+ SearchTerm = s,
+ GeoCoordinate = new GeoCoordinate(PositionForGeocoding.Latitude, PositionForGeocoding.Longitude)
+ };
+ query.QueryCompleted +=
+ (sender, args) =>
+ source.SetResult(
+ args.Result.Select(r => new Position(r.GeoCoordinate.Latitude, r.GeoCoordinate.Longitude)).ToArray());
+ query.QueryAsync();
+
+ return source.Task;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.WP8/MapRenderer.cs b/Xamarin.Forms.Maps.WP8/MapRenderer.cs
new file mode 100644
index 00000000..eaac51d2
--- /dev/null
+++ b/Xamarin.Forms.Maps.WP8/MapRenderer.cs
@@ -0,0 +1,250 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Device.Location;
+using System.Linq;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Shapes;
+using Windows.Devices.Geolocation;
+using Microsoft.Phone.Maps;
+using Microsoft.Phone.Maps.Controls;
+using Microsoft.Phone.Maps.Toolkit;
+using Xamarin.Forms.Platform.WinPhone;
+
+namespace Xamarin.Forms.Maps.WP8
+{
+ public class
+ MapRenderer : ViewRenderer<Map, Microsoft.Phone.Maps.Controls.Map>
+ {
+ bool _firstZoomLevelChangeFired;
+ MapLayer _pushPinLayer;
+ MapLayer _userLocationLayer;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
+ {
+ base.OnElementChanged(e);
+
+ SetNativeControl(new Microsoft.Phone.Maps.Controls.Map());
+ UpdateMapType();
+
+ Control.Loaded += ControlOnLoaded;
+
+ _pushPinLayer = new MapLayer();
+ Control.Layers.Add(_pushPinLayer);
+
+ _userLocationLayer = new MapLayer();
+ Control.Layers.Add(_userLocationLayer);
+
+ Control.ViewChanged += (s, a) => UpdateVisibleRegion();
+ Control.ZoomLevelChanged += (sender, args) => UpdateVisibleRegion();
+ Control.CenterChanged += (s, a) => UpdateVisibleRegion();
+ //Control.ViewChangeOnFrame += (s, a) => UpdateVisibleRegion ();
+
+ MessagingCenter.Subscribe<Map, MapSpan>(this, "MapMoveToRegion", (s, a) => MoveToRegion(a), Element);
+
+ ((ObservableCollection<Pin>)Element.Pins).CollectionChanged += OnCollectionChanged;
+
+ if (Element.Pins.Any())
+ LoadPins();
+
+ UpdateShowUserLocation();
+ }
+
+ async void UpdateShowUserLocation()
+ {
+ if (Element.IsShowingUser)
+ {
+ var myGeolocator = new Geolocator();
+
+ if (myGeolocator.LocationStatus != PositionStatus.NotAvailable &&
+ myGeolocator.LocationStatus != PositionStatus.Disabled)
+ {
+ var userPosition = await myGeolocator.GetGeopositionAsync();
+ if (userPosition?.Coordinate != null)
+ LoadUserPosition(userPosition.Coordinate, true);
+ }
+ }
+ else if (_userLocationLayer.Count > 0)
+ _userLocationLayer.Clear();
+ }
+
+ void ControlOnLoaded(object sender, RoutedEventArgs routedEventArgs)
+ {
+ MapsSettings.ApplicationContext.ApplicationId = FormsMaps.ApplicationId;
+ MapsSettings.ApplicationContext.AuthenticationToken = FormsMaps.AuthenticationToken;
+ }
+
+ void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ foreach (Pin pin in e.NewItems)
+ LoadPin(pin);
+ break;
+ case NotifyCollectionChangedAction.Move:
+ // no matter
+ break;
+ case NotifyCollectionChangedAction.Remove:
+ foreach (Pin pin in e.OldItems)
+ RemovePin(pin);
+ break;
+ case NotifyCollectionChangedAction.Replace:
+ foreach (Pin pin in e.OldItems)
+ RemovePin(pin);
+ foreach (Pin pin in e.NewItems)
+ LoadPin(pin);
+ break;
+ case NotifyCollectionChangedAction.Reset:
+ _pushPinLayer.Clear();
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ void UpdateVisibleRegion()
+ {
+ if (!_firstZoomLevelChangeFired)
+ {
+ MoveToRegion(Element.LastMoveToRegion, MapAnimationKind.None);
+ _firstZoomLevelChangeFired = true;
+ return;
+ }
+
+ var center = new Position(Control.Center.Latitude, Control.Center.Longitude);
+ var topLeft = Control.ConvertViewportPointToGeoCoordinate(new System.Windows.Point(0, 0));
+ var bottomRight =
+ Control.ConvertViewportPointToGeoCoordinate(new System.Windows.Point(Control.ActualWidth, Control.ActualHeight));
+ if (topLeft == null || bottomRight == null)
+ return;
+
+ var boundingRegion = LocationRectangle.CreateBoundingRectangle(topLeft, bottomRight);
+ var result = new MapSpan(center, boundingRegion.HeightInDegrees, boundingRegion.WidthInDegrees);
+ Element.VisibleRegion = result;
+ }
+
+ void LoadPins()
+ {
+ foreach (var pin in Element.Pins)
+ LoadPin(pin);
+ }
+
+ void LoadPin(Pin pin)
+ {
+ var location = new GeoCoordinate(pin.Position.Latitude, pin.Position.Longitude);
+ var pushPin = new Pushpin
+ {
+ Content = pin.Label,
+ PositionOrigin = new System.Windows.Point(0, 1),
+ Tag = pin
+ };
+
+ pushPin.Tap += PinTap;
+
+ var pushPinOverlay = new MapOverlay
+ {
+ Content = pushPin,
+ GeoCoordinate = location,
+ PositionOrigin = new System.Windows.Point(0, 1)
+ };
+ _pushPinLayer.Add(pushPinOverlay);
+ }
+
+ void PinTap(object sender, GestureEventArgs e)
+ {
+ var pushPin = (Pushpin)sender;
+ var pin = (Pin)pushPin.Tag;
+ pin.SendTap();
+ }
+
+ void RemovePin(Pin pin)
+ {
+ var child = _pushPinLayer.FirstOrDefault(p => ((Pushpin)p.Content).Tag == pin);
+ if (child != null)
+ _pushPinLayer.Remove(child);
+ }
+
+ void MoveToRegion(MapSpan span, MapAnimationKind animation = MapAnimationKind.Parabolic)
+ {
+ // FIXME
+ var center = new GeoCoordinate(span.Center.Latitude, span.Center.Longitude);
+ var location = new LocationRectangle(center, span.LongitudeDegrees, span.LatitudeDegrees);
+ Control.SetView(location, animation);
+ }
+
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return new SizeRequest(new Size(100, 100));
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Map.MapTypeProperty.PropertyName)
+ UpdateMapType();
+ if (e.PropertyName == Map.IsShowingUserProperty.PropertyName)
+ UpdateShowUserLocation();
+ }
+
+ void UpdateMapType()
+ {
+ switch (Element.MapType)
+ {
+ case MapType.Street:
+ Control.CartographicMode = MapCartographicMode.Road;
+ break;
+ case MapType.Satellite:
+ Control.CartographicMode = MapCartographicMode.Aerial;
+ break;
+ case MapType.Hybrid:
+ Control.CartographicMode = MapCartographicMode.Hybrid;
+ break;
+ }
+ }
+
+ void LoadUserPosition(Geocoordinate userPosition, bool center = false)
+ {
+ _userLocationLayer.Clear();
+
+ var userCoordinate = new GeoCoordinate
+ (
+ userPosition.Latitude,
+ userPosition.Longitude,
+ userPosition.Altitude ?? double.NaN,
+ userPosition.Accuracy,
+ userPosition.AltitudeAccuracy ?? double.NaN,
+ userPosition.Speed ?? double.NaN,
+ userPosition.Heading ?? double.NaN
+ );
+
+ //make some preety?
+ var userPositionCircle = new Ellipse
+ {
+ Fill = new SolidColorBrush(Colors.Blue),
+ Height = 20,
+ Width = 20,
+ Opacity = 50
+ };
+
+ var userPostionOverlay = new MapOverlay
+ {
+ Content = userPositionCircle,
+ PositionOrigin = new System.Windows.Point(0.5, 0.5),
+ GeoCoordinate = userCoordinate
+ };
+
+ _userLocationLayer.Add(userPostionOverlay);
+
+ if (center)
+ {
+ Control.Center = userCoordinate;
+ Control.ZoomLevel = 13;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.WP8/Properties/AssemblyInfo.cs b/Xamarin.Forms.Maps.WP8/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..378d6520
--- /dev/null
+++ b/Xamarin.Forms.Maps.WP8/Properties/AssemblyInfo.cs
@@ -0,0 +1,26 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.InteropServices;
+using Xamarin.Forms;
+using Xamarin.Forms.Maps;
+using Xamarin.Forms.Maps.WP8;
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Xamarin.Forms.Maps.WP8")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("9222d2b8-63a4-4a36-a80e-bc34f27e0951")]
+[assembly: NeutralResourcesLanguage("en-US")]
+[assembly: ExportRenderer(typeof (Map), typeof (MapRenderer))] \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.WP8/README_FIRST.txt b/Xamarin.Forms.Maps.WP8/README_FIRST.txt
new file mode 100644
index 00000000..fc7fc06d
--- /dev/null
+++ b/Xamarin.Forms.Maps.WP8/README_FIRST.txt
@@ -0,0 +1,3 @@
+For the Windows Phone toolkit make sure that you have
+marked the icons in the "Toolkit.Content" folder as content. That way they
+can be used as the icons for the ApplicationBar control.
diff --git a/Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Add.png b/Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Add.png
new file mode 100644
index 00000000..4b524d6f
--- /dev/null
+++ b/Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Add.png
Binary files differ
diff --git a/Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Cancel.png b/Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Cancel.png
new file mode 100644
index 00000000..4dd724f0
--- /dev/null
+++ b/Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Cancel.png
Binary files differ
diff --git a/Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Check.png b/Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Check.png
new file mode 100644
index 00000000..7a074666
--- /dev/null
+++ b/Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Check.png
Binary files differ
diff --git a/Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Delete.png b/Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Delete.png
new file mode 100644
index 00000000..95bb16da
--- /dev/null
+++ b/Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Delete.png
Binary files differ
diff --git a/Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Select.png b/Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Select.png
new file mode 100644
index 00000000..995deaaa
--- /dev/null
+++ b/Xamarin.Forms.Maps.WP8/Toolkit.Content/ApplicationBar.Select.png
Binary files differ
diff --git a/Xamarin.Forms.Maps.WP8/Xamarin.Forms.Maps.WP8.csproj b/Xamarin.Forms.Maps.WP8/Xamarin.Forms.Maps.WP8.csproj
new file mode 100644
index 00000000..512244b8
--- /dev/null
+++ b/Xamarin.Forms.Maps.WP8/Xamarin.Forms.Maps.WP8.csproj
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>10.0.20506</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{9222D2B8-63A4-4A36-A80E-BC34F27E0951}</ProjectGuid>
+ <ProjectTypeGuids>{C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Maps.WP8</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Maps.WP8</AssemblyName>
+ <TargetFrameworkIdentifier>WindowsPhone</TargetFrameworkIdentifier>
+ <TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
+ <SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
+ <SilverlightApplication>false</SilverlightApplication>
+ <ValidateXaml>true</ValidateXaml>
+ <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+ <ThrowErrorsInValidation>true</ThrowErrorsInValidation>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>Bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>Bin\Release</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>Bin\x86\Debug</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>Bin\x86\Release</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>Bin\ARM\Debug</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|ARM' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>Bin\ARM\Release</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|ARM'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\ARM\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="MapRenderer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="FormsMaps.cs" />
+ <Compile Include="GeocoderBackend.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7D13BAC2-C6A4-416A-B07E-C169B199E52B}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.WP8\Xamarin.Forms.Platform.WP8.csproj">
+ <Project>{517B6AE0-792B-4665-9376-5CA33E539181}</Project>
+ <Name>Xamarin.Forms.Platform.WP8</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="README_FIRST.txt" />
+ <Content Include="Toolkit.Content\ApplicationBar.Add.png" />
+ <Content Include="Toolkit.Content\ApplicationBar.Cancel.png" />
+ <Content Include="Toolkit.Content\ApplicationBar.Check.png" />
+ <Content Include="Toolkit.Content\ApplicationBar.Delete.png" />
+ <Content Include="Toolkit.Content\ApplicationBar.Select.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="Microsoft.Phone.Controls.Toolkit">
+ <HintPath>..\packages\WPtoolkit.4.2013.08.16\lib\wp8\Microsoft.Phone.Controls.Toolkit.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).$(TargetFrameworkVersion).Overrides.targets" />
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).CSharp.targets" />
+ <ProjectExtensions />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/Xamarin.Forms.Maps.WP8/packages.config b/Xamarin.Forms.Maps.WP8/packages.config
new file mode 100644
index 00000000..d534d6e7
--- /dev/null
+++ b/Xamarin.Forms.Maps.WP8/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="WPtoolkit" version="4.2013.08.16" targetFramework="wp80" />
+</packages>
diff --git a/Xamarin.Forms.Maps.WinRT.Phone/Properties/AssemblyInfo.cs b/Xamarin.Forms.Maps.WinRT.Phone/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..16d833de
--- /dev/null
+++ b/Xamarin.Forms.Maps.WinRT.Phone/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Xamarin.Forms.Maps;
+using Xamarin.Forms.Maps.WinRT;
+using Xamarin.Forms.Platform.WinRT;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Xamarin.Forms.Maps.WinRT.Phone")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)]
+[assembly: ExportRenderer(typeof (Map), typeof (MapRenderer))] \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.WinRT.Phone/Xamarin.Forms.Maps.WinRT.Phone.csproj b/Xamarin.Forms.Maps.WinRT.Phone/Xamarin.Forms.Maps.WinRT.Phone.csproj
new file mode 100644
index 00000000..ddc72cf5
--- /dev/null
+++ b/Xamarin.Forms.Maps.WinRT.Phone/Xamarin.Forms.Maps.WinRT.Phone.csproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{2633AF57-F2CB-442A-AC19-F97BD8A06571}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Maps.WinRT</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Maps.WinRT.Phone</AssemblyName>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <TargetPlatformVersion>8.1</TargetPlatformVersion>
+ <MinimumVisualStudioVersion>12</MinimumVisualStudioVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{76F1466A-8B6D-4E39-A767-685A06062A39};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\ARM\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+ <OutputPath>bin\ARM\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7d13bac2-c6a4-416a-b07e-c169b199e52b}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.WinRT.Phone\Xamarin.Forms.Platform.WinRT.Phone.csproj">
+ <Project>{3361d52c-2e74-433e-8285-9c9a5c485977}</Project>
+ <Name>Xamarin.Forms.Platform.WinRT.Phone</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.WinRT\Xamarin.Forms.Platform.WinRT.csproj">
+ <Project>{f3fdd7ac-8899-4e41-bfd7-ec83403e736d}</Project>
+ <Name>Xamarin.Forms.Platform.WinRT</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Maps.UWP\FormsMaps.cs">
+ <Link>FormsMaps.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Maps.UWP\GeocoderBackend.cs">
+ <Link>GeocoderBackend.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Maps.UWP\MapRenderer.cs">
+ <Link>MapRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Maps.UWP\PushPin.cs">
+ <Link>PushPin.cs</Link>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '12.0' ">
+ <VisualStudioVersion>12.0</VisualStudioVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(TargetPlatformIdentifier)' == '' ">
+ <TargetPlatformIdentifier>WindowsPhoneApp</TargetPlatformIdentifier>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.WinRT.Tablet/GeocoderBackend.cs b/Xamarin.Forms.Maps.WinRT.Tablet/GeocoderBackend.cs
new file mode 100644
index 00000000..565182d4
--- /dev/null
+++ b/Xamarin.Forms.Maps.WinRT.Tablet/GeocoderBackend.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Bing.Maps;
+using Bing.Maps.Search;
+
+namespace Xamarin.Forms.Maps.WinRT
+{
+ internal class GeocoderBackend
+ {
+ public static void Register()
+ {
+ Geocoder.GetPositionsForAddressAsyncFunc = GetPositionsForAddress;
+ Geocoder.GetAddressesForPositionFuncAsync = GetAddressesForPositionAsync;
+ }
+
+ static async Task<IEnumerable<string>> GetAddressesForPositionAsync(Position position)
+ {
+ var results = new List<string>();
+ var source = new TaskCompletionSource<IEnumerable<string>>();
+ var requestOptions = new ReverseGeocodeRequestOptions(new Location(position.Latitude, position.Longitude));
+ var response =
+ await
+ new Bing.Maps.Map { Credentials = FormsMaps.AuthenticationToken }.SearchManager.ReverseGeocodeAsync(requestOptions);
+ if (!response.HasError)
+ {
+ foreach (var address in response.LocationData)
+ results.Add(address.Address.FormattedAddress);
+ }
+
+ return results;
+ }
+
+ static async Task<IEnumerable<Position>> GetPositionsForAddress(string s)
+ {
+ var results = new List<Position>();
+
+ if (string.IsNullOrEmpty(s))
+ return results;
+
+ var requestOptions = new GeocodeRequestOptions(s);
+ var response =
+ await new Bing.Maps.Map { Credentials = FormsMaps.AuthenticationToken }.SearchManager.GeocodeAsync(requestOptions);
+ if (!response.HasError)
+ {
+ foreach (var address in response.LocationData)
+ results.Add(new Position(address.Location.Latitude, address.Location.Longitude));
+ }
+ return results;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.WinRT.Tablet/MapRenderer.cs b/Xamarin.Forms.Maps.WinRT.Tablet/MapRenderer.cs
new file mode 100644
index 00000000..b3eba8ac
--- /dev/null
+++ b/Xamarin.Forms.Maps.WinRT.Tablet/MapRenderer.cs
@@ -0,0 +1,249 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading.Tasks;
+using Windows.Devices.Geolocation;
+using Windows.UI;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Shapes;
+using Bing.Maps;
+using Xamarin.Forms.Platform.WinRT;
+
+namespace Xamarin.Forms.Maps.WinRT
+{
+ public class MapRenderer : ViewRenderer<Map, Bing.Maps.Map>
+ {
+ bool _disposed;
+ bool _firstZoomLevelChangeFired;
+ Ellipse _userPositionCircle;
+
+ protected override async void OnElementChanged(ElementChangedEventArgs<Map> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ {
+ var mapModel = e.OldElement;
+ MessagingCenter.Unsubscribe<Map, MapSpan>(this, "MapMoveToRegion");
+ ((ObservableCollection<Pin>)mapModel.Pins).CollectionChanged -= OnCollectionChanged;
+ }
+
+ if (e.NewElement != null)
+ {
+ var mapModel = e.NewElement;
+
+ if (Control == null)
+ {
+ SetNativeControl(new Bing.Maps.Map());
+ Control.Credentials = FormsMaps.AuthenticationToken;
+ Control.ViewChanged += (s, a) => UpdateVisibleRegion();
+ }
+
+ MessagingCenter.Subscribe<Map, MapSpan>(this, "MapMoveToRegion", (s, a) => MoveToRegion(a), mapModel);
+
+ UpdateMapType();
+ UpdateHasScrollEnabled();
+ UpdateHasZoomEnabled();
+
+ ((ObservableCollection<Pin>)mapModel.Pins).CollectionChanged += OnCollectionChanged;
+
+ if (mapModel.Pins.Any())
+ LoadPins();
+
+ await UpdateIsShowingUser();
+ }
+ }
+
+ protected override async void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Map.MapTypeProperty.PropertyName)
+ UpdateMapType();
+ else if (e.PropertyName == Map.IsShowingUserProperty.PropertyName)
+ await UpdateIsShowingUser();
+ else if (e.PropertyName == Map.HasScrollEnabledProperty.PropertyName)
+ UpdateHasScrollEnabled();
+ else if (e.PropertyName == Map.HasZoomEnabledProperty.PropertyName)
+ UpdateHasZoomEnabled();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ _disposed = true;
+
+ MessagingCenter.Unsubscribe<Map, MapSpan>(this, "MapMoveToRegion");
+
+ if (Element != null)
+ ((ObservableCollection<Pin>)Element.Pins).CollectionChanged -= OnCollectionChanged;
+ }
+ base.Dispose(disposing);
+ }
+
+ async Task UpdateIsShowingUser()
+ {
+ if (Element.IsShowingUser)
+ {
+ var myGeolocator = new Geolocator();
+ if (myGeolocator.LocationStatus != PositionStatus.NotAvailable &&
+ myGeolocator.LocationStatus != PositionStatus.Disabled)
+ {
+ var userPosition = await myGeolocator.GetGeopositionAsync();
+ if (userPosition?.Coordinate != null)
+ LoadUserPosition(userPosition.Coordinate, true);
+ }
+ }
+ else if (_userPositionCircle != null && Control.Children.Contains(_userPositionCircle))
+ Control.Children.Remove(_userPositionCircle);
+ }
+
+ void LoadPins()
+ {
+ foreach (var pin in Element.Pins)
+ LoadPin(pin);
+ }
+
+ void ClearPins()
+ {
+ Control.Children.Clear();
+ UpdateIsShowingUser();
+ }
+
+ void RemovePin(Pin pinToRemove)
+ {
+ var pushPin = Control.Children.FirstOrDefault(c =>
+ {
+ var pin = (c as Pushpin);
+ return (pin != null && pin.DataContext.Equals(pinToRemove));
+ });
+
+ if (pushPin != null)
+ Control.Children.Remove(pushPin);
+ }
+
+ void LoadPin(Pin pin)
+ {
+ var pushPin = new Pushpin { Text = pin.Label, DataContext = pin };
+ MapLayer.SetPosition(pushPin, new Location(pin.Position.Latitude, pin.Position.Longitude));
+ pushPin.Tapped += (s, e) => ((s as Pushpin)?.DataContext as Pin)?.SendTap();
+ Control.Children.Add(pushPin);
+ }
+
+ void UpdateMapType()
+ {
+ switch (Element.MapType)
+ {
+ case MapType.Street:
+ Control.MapType = Bing.Maps.MapType.Road;
+ break;
+ case MapType.Satellite:
+ Control.MapType = Bing.Maps.MapType.Aerial;
+ break;
+ case MapType.Hybrid:
+ Control.MapType = Bing.Maps.MapType.Birdseye;
+ break;
+ }
+ }
+
+ void MoveToRegion(MapSpan span)
+ {
+ var center = new Location(span.Center.Latitude, span.Center.Longitude);
+ var location = new LocationRect(center, span.LongitudeDegrees, span.LatitudeDegrees);
+ Control.SetView(location);
+ }
+
+ void UpdateVisibleRegion()
+ {
+ if (Control == null || Element == null)
+ return;
+
+ if (!_firstZoomLevelChangeFired)
+ {
+ MoveToRegion(Element.LastMoveToRegion);
+ _firstZoomLevelChangeFired = true;
+ return;
+ }
+
+ var center = new Position(Control.Center.Latitude, Control.Center.Longitude);
+
+ var boundingRegion = Control.Bounds;
+ var result = new MapSpan(center, boundingRegion.Height, boundingRegion.Width);
+ Element.VisibleRegion = result;
+ }
+
+ void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ foreach (Pin pin in e.NewItems)
+ LoadPin(pin);
+ break;
+ case NotifyCollectionChangedAction.Move:
+ // no matter
+ break;
+ case NotifyCollectionChangedAction.Remove:
+ foreach (Pin pin in e.OldItems)
+ RemovePin(pin);
+ break;
+ case NotifyCollectionChangedAction.Replace:
+ foreach (Pin pin in e.OldItems)
+ RemovePin(pin);
+ foreach (Pin pin in e.NewItems)
+ LoadPin(pin);
+ break;
+ case NotifyCollectionChangedAction.Reset:
+ ClearPins();
+ break;
+ }
+ }
+
+ void LoadUserPosition(Geocoordinate userCoordinate, bool center)
+ {
+ var userPosition = new Location
+ {
+ Latitude = userCoordinate.Point.Position.Latitude,
+ Longitude = userCoordinate.Point.Position.Longitude
+ };
+
+ if (_userPositionCircle == null)
+ {
+ _userPositionCircle = new Ellipse
+ {
+ Stroke = new SolidColorBrush(Colors.White),
+ Fill = new SolidColorBrush(Colors.Blue),
+ StrokeThickness = 2,
+ Height = 20,
+ Width = 20,
+ Opacity = 50
+ };
+ }
+
+ if (Control.Children.Contains(_userPositionCircle))
+ Control.Children.Remove(_userPositionCircle);
+
+ MapLayer.SetPosition(_userPositionCircle, userPosition);
+ MapLayer.SetPositionAnchor(_userPositionCircle, new Windows.Foundation.Point(0.5, 0.5));
+
+ Control.Children.Add(_userPositionCircle);
+
+ if (center)
+ {
+ Control.Center = userPosition;
+ Control.ZoomLevel = 13;
+ }
+ }
+
+ void UpdateHasZoomEnabled()
+ {
+ }
+
+ void UpdateHasScrollEnabled()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.WinRT.Tablet/Properties/AssemblyInfo.cs b/Xamarin.Forms.Maps.WinRT.Tablet/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..74cc63dc
--- /dev/null
+++ b/Xamarin.Forms.Maps.WinRT.Tablet/Properties/AssemblyInfo.cs
@@ -0,0 +1,34 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Xamarin.Forms.Maps;
+using Xamarin.Forms.Maps.WinRT;
+using Xamarin.Forms.Platform.WinRT;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Xamarin.Forms.Maps.WinRT.Tablet")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Forms.Maps.WinRT.Tablet")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)]
+[assembly: ExportRenderer(typeof (Map), typeof (MapRenderer))] \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.WinRT.Tablet/Xamarin.Forms.Maps.WinRT.Tablet.csproj b/Xamarin.Forms.Maps.WinRT.Tablet/Xamarin.Forms.Maps.WinRT.Tablet.csproj
new file mode 100644
index 00000000..8251abb0
--- /dev/null
+++ b/Xamarin.Forms.Maps.WinRT.Tablet/Xamarin.Forms.Maps.WinRT.Tablet.csproj
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{E5C4698D-FB57-4EEC-98C0-89E620F6920A}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Maps.WinRT</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Maps.WinRT.Tablet</AssemblyName>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <TargetPlatformVersion>8.1</TargetPlatformVersion>
+ <MinimumVisualStudioVersion>12</MinimumVisualStudioVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\ARM\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+ <OutputPath>bin\ARM\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x64\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ <OutputPath>bin\x64\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7d13bac2-c6a4-416a-b07e-c169b199e52b}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.WinRT.Tablet\Xamarin.Forms.Platform.WinRT.Tablet.csproj">
+ <Project>{d3f9265a-30ac-43e8-a3eb-59bb76d2d0bf}</Project>
+ <Name>Xamarin.Forms.Platform.WinRT.Tablet</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.WinRT\Xamarin.Forms.Platform.WinRT.csproj">
+ <Project>{f3fdd7ac-8899-4e41-bfd7-ec83403e736d}</Project>
+ <Name>Xamarin.Forms.Platform.WinRT</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Maps.UWP\FormsMaps.cs">
+ <Link>FormsMaps.cs</Link>
+ </Compile>
+ <Compile Include="GeocoderBackend.cs" />
+ <Compile Include="MapRenderer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <SDKReference Include="Bing.Maps.Xaml, Version=1.313.0825.0">
+ <Name>Bing Maps for C#, C++, or Visual Basic</Name>
+ </SDKReference>
+ <SDKReference Include="Microsoft.VCLibs, version=12.0">
+ <Name>Microsoft Visual C++ 2013 Runtime Package for Windows</Name>
+ </SDKReference>
+ </ItemGroup>
+ <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '12.0' ">
+ <VisualStudioVersion>12.0</VisualStudioVersion>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.iOS/FormsMaps.cs b/Xamarin.Forms.Maps.iOS/FormsMaps.cs
new file mode 100644
index 00000000..91033f78
--- /dev/null
+++ b/Xamarin.Forms.Maps.iOS/FormsMaps.cs
@@ -0,0 +1,34 @@
+using Xamarin.Forms.Maps.iOS;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin
+{
+ public static class FormsMaps
+ {
+ static bool s_isInitialized;
+ static bool? s_isiOs8OrNewer;
+
+ internal static bool IsiOs8OrNewer
+ {
+ get
+ {
+ if (!s_isiOs8OrNewer.HasValue)
+ s_isiOs8OrNewer = UIDevice.CurrentDevice.CheckSystemVersion(8, 0);
+ return s_isiOs8OrNewer.Value;
+ }
+ }
+
+ public static void Init()
+ {
+ if (s_isInitialized)
+ return;
+ GeocoderBackend.Register();
+ s_isInitialized = true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.iOS/GeocoderBackend.cs b/Xamarin.Forms.Maps.iOS/GeocoderBackend.cs
new file mode 100644
index 00000000..42b96457
--- /dev/null
+++ b/Xamarin.Forms.Maps.iOS/GeocoderBackend.cs
@@ -0,0 +1,61 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+#if __UNIFIED__
+using CoreLocation;
+using AddressBookUI;
+#else
+using MonoTouch.AddressBookUI;
+using MonoTouch.CoreLocation;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=global::System.Single;
+using nint=global::System.Int32;
+using nuint=global::System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Maps.iOS
+{
+ internal class GeocoderBackend
+ {
+ public static void Register()
+ {
+ Geocoder.GetPositionsForAddressAsyncFunc = GetPositionsForAddressAsync;
+ Geocoder.GetAddressesForPositionFuncAsync = GetAddressesForPositionAsync;
+ }
+
+ static Task<IEnumerable<string>> GetAddressesForPositionAsync(Position position)
+ {
+ var location = new CLLocation(position.Latitude, position.Longitude);
+ var geocoder = new CLGeocoder();
+ var source = new TaskCompletionSource<IEnumerable<string>>();
+ geocoder.ReverseGeocodeLocation(location, (placemarks, error) =>
+ {
+ if (placemarks == null)
+ placemarks = new CLPlacemark[0];
+ IEnumerable<string> addresses = placemarks.Select(p => ABAddressFormatting.ToString(p.AddressDictionary, false));
+ source.SetResult(addresses);
+ });
+ return source.Task;
+ }
+
+ static Task<IEnumerable<Position>> GetPositionsForAddressAsync(string address)
+ {
+ var geocoder = new CLGeocoder();
+ var source = new TaskCompletionSource<IEnumerable<Position>>();
+ geocoder.GeocodeAddress(address, (placemarks, error) =>
+ {
+ if (placemarks == null)
+ placemarks = new CLPlacemark[0];
+ IEnumerable<Position> positions = placemarks.Select(p => new Position(p.Location.Coordinate.Latitude, p.Location.Coordinate.Longitude));
+ source.SetResult(positions);
+ });
+ return source.Task;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.iOS/MapRenderer.cs b/Xamarin.Forms.Maps.iOS/MapRenderer.cs
new file mode 100644
index 00000000..aa3bb447
--- /dev/null
+++ b/Xamarin.Forms.Maps.iOS/MapRenderer.cs
@@ -0,0 +1,327 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using Xamarin.Forms.Platform.iOS;
+#if __UNIFIED__
+using UIKit;
+using MapKit;
+using CoreLocation;
+using Foundation;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+using MonoTouch.CoreLocation;
+using MonoTouch.MapKit;
+using System.Drawing;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+using ObjCRuntime;
+
+#else
+using nfloat=global::System.Single;
+using nint=global::System.Int32;
+using nuint=global::System.UInt32;
+using MonoTouch.ObjCRuntime;
+#endif
+
+namespace Xamarin.Forms.Maps.iOS
+{
+ internal class MapDelegate : MKMapViewDelegate
+ {
+ // keep references alive, removing this will cause a segfault
+ static readonly List<object> List = new List<object>();
+ readonly Map _map;
+ UIView _lastTouchedView;
+
+ internal MapDelegate(Map map)
+ {
+ _map = map;
+ }
+
+#if __UNIFIED__
+ public override MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
+#else
+ public override MKAnnotationView GetViewForAnnotation (MKMapView mapView, NSObject annotation)
+#endif
+ {
+ MKPinAnnotationView mapPin = null;
+
+ // https://bugzilla.xamarin.com/show_bug.cgi?id=26416
+ var userLocationAnnotation = Runtime.GetNSObject(annotation.Handle) as MKUserLocation;
+ if (userLocationAnnotation != null)
+ return null;
+
+ const string defaultPinId = "defaultPin";
+ mapPin = (MKPinAnnotationView)mapView.DequeueReusableAnnotation(defaultPinId);
+ if (mapPin == null)
+ {
+ mapPin = new MKPinAnnotationView(annotation, defaultPinId);
+ mapPin.CanShowCallout = true;
+ }
+
+ mapPin.Annotation = annotation;
+ AttachGestureToPin(mapPin, annotation);
+
+ return mapPin;
+ }
+
+#if __UNIFIED__
+ void AttachGestureToPin(MKPinAnnotationView mapPin, IMKAnnotation annotation)
+#else
+ void AttachGestureToPin (MKPinAnnotationView mapPin, NSObject annotation)
+#endif
+ {
+ UIGestureRecognizer[] recognizers = mapPin.GestureRecognizers;
+
+ if (recognizers != null)
+ {
+ foreach (UIGestureRecognizer r in recognizers)
+ {
+ mapPin.RemoveGestureRecognizer(r);
+ }
+ }
+
+ Action<UITapGestureRecognizer> action = g => OnClick(annotation, g);
+ var recognizer = new UITapGestureRecognizer(action) { ShouldReceiveTouch = (gestureRecognizer, touch) =>
+ {
+ _lastTouchedView = touch.View;
+ return true;
+ } };
+ List.Add(action);
+ List.Add(recognizer);
+ mapPin.AddGestureRecognizer(recognizer);
+ }
+
+ void OnClick(object annotationObject, UITapGestureRecognizer recognizer)
+ {
+ // https://bugzilla.xamarin.com/show_bug.cgi?id=26416
+ NSObject annotation = Runtime.GetNSObject(((IMKAnnotation)annotationObject).Handle);
+ if (annotation == null)
+ return;
+
+ // lookup pin
+ Pin targetPin = null;
+ for (var i = 0; i < _map.Pins.Count; i++)
+ {
+ Pin pin = _map.Pins[i];
+ object target = pin.Id;
+ if (target != annotation)
+ continue;
+
+ targetPin = pin;
+ break;
+ }
+
+ // pin not found. Must have been activated outside of forms
+ if (targetPin == null)
+ return;
+
+ // if the tap happened on the annotation view itself, skip because this is what happens when the callout is showing
+ // when the callout is already visible the tap comes in on a different view
+ if (_lastTouchedView is MKAnnotationView)
+ return;
+
+ targetPin.SendTap();
+ }
+ }
+
+ public class MapRenderer : ViewRenderer
+ {
+ long _handle = 0;
+ CLLocationManager _locationManager;
+
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return Control.GetSizeRequest(widthConstraint, heightConstraint);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (Element != null)
+ {
+ var mapModel = (Map)Element;
+ MessagingCenter.Unsubscribe<Map, MapSpan>(this, "MapMoveToRegion");
+ ((ObservableCollection<Pin>)mapModel.Pins).CollectionChanged -= OnCollectionChanged;
+ }
+
+ var mkMapView = (MKMapView)Control;
+ mkMapView.RegionChanged -= MkMapViewOnRegionChanged;
+
+ if (_locationManager != null)
+ {
+ _locationManager.Dispose();
+ _locationManager = null;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<View> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ {
+ var mapModel = (Map)e.OldElement;
+ MessagingCenter.Unsubscribe<Map, MapSpan>(this, "MapMoveToRegion");
+ ((ObservableCollection<Pin>)mapModel.Pins).CollectionChanged -= OnCollectionChanged;
+ }
+
+ if (e.NewElement != null)
+ {
+ var mapModel = (Map)e.NewElement;
+
+ if (Control == null)
+ {
+ SetNativeControl(new MKMapView(RectangleF.Empty));
+ var mkMapView = (MKMapView)Control;
+ var mapDelegate = new MapDelegate(mapModel);
+ mkMapView.GetViewForAnnotation = mapDelegate.GetViewForAnnotation;
+ mkMapView.RegionChanged += MkMapViewOnRegionChanged;
+ }
+
+ MessagingCenter.Subscribe<Map, MapSpan>(this, "MapMoveToRegion", (s, a) => MoveToRegion(a), mapModel);
+ if (mapModel.LastMoveToRegion != null)
+ MoveToRegion(mapModel.LastMoveToRegion, false);
+
+ UpdateMapType();
+ UpdateIsShowingUser();
+ UpdateHasScrollEnabled();
+ UpdateHasZoomEnabled();
+
+ ((ObservableCollection<Pin>)mapModel.Pins).CollectionChanged += OnCollectionChanged;
+
+ OnCollectionChanged(((Map)Element).Pins, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Map.MapTypeProperty.PropertyName)
+ UpdateMapType();
+ else if (e.PropertyName == Map.IsShowingUserProperty.PropertyName)
+ UpdateIsShowingUser();
+ else if (e.PropertyName == Map.HasScrollEnabledProperty.PropertyName)
+ UpdateHasScrollEnabled();
+ else if (e.PropertyName == Map.HasZoomEnabledProperty.PropertyName)
+ UpdateHasZoomEnabled();
+ }
+
+ void AddPins(IList pins)
+ {
+ foreach (Pin pin in pins)
+ {
+ var annotation = new MKPointAnnotation { Title = pin.Label, Subtitle = pin.Address ?? "" };
+
+ pin.Id = annotation;
+#if __UNIFIED__
+ annotation.SetCoordinate(new CLLocationCoordinate2D(pin.Position.Latitude, pin.Position.Longitude));
+#else
+ annotation.Coordinate = new CLLocationCoordinate2D (pin.Position.Latitude, pin.Position.Longitude);
+#endif
+ ((MKMapView)Control).AddAnnotation(annotation);
+ }
+ }
+
+ void MkMapViewOnRegionChanged(object sender, MKMapViewChangeEventArgs mkMapViewChangeEventArgs)
+ {
+ if (Element == null)
+ return;
+
+ var mapModel = (Map)Element;
+ var mkMapView = (MKMapView)Control;
+
+ mapModel.VisibleRegion = new MapSpan(new Position(mkMapView.Region.Center.Latitude, mkMapView.Region.Center.Longitude), mkMapView.Region.Span.LatitudeDelta, mkMapView.Region.Span.LongitudeDelta);
+ }
+
+ void MoveToRegion(MapSpan mapSpan, bool animated = true)
+ {
+ Position center = mapSpan.Center;
+ var mapRegion = new MKCoordinateRegion(new CLLocationCoordinate2D(center.Latitude, center.Longitude), new MKCoordinateSpan(mapSpan.LatitudeDegrees, mapSpan.LongitudeDegrees));
+ ((MKMapView)Control).SetRegion(mapRegion, animated);
+ }
+
+ void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
+ {
+ switch (notifyCollectionChangedEventArgs.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ AddPins(notifyCollectionChangedEventArgs.NewItems);
+ break;
+ case NotifyCollectionChangedAction.Remove:
+ RemovePins(notifyCollectionChangedEventArgs.OldItems);
+ break;
+ case NotifyCollectionChangedAction.Replace:
+ RemovePins(notifyCollectionChangedEventArgs.OldItems);
+ AddPins(notifyCollectionChangedEventArgs.NewItems);
+ break;
+ case NotifyCollectionChangedAction.Reset:
+ var mapView = (MKMapView)Control;
+ mapView.RemoveAnnotations(mapView.Annotations);
+ AddPins((IList)(Element as Map).Pins);
+ break;
+ case NotifyCollectionChangedAction.Move:
+ //do nothing
+ break;
+ }
+ }
+
+ void RemovePins(IList pins)
+ {
+ foreach (object pin in pins)
+#if __UNIFIED__
+ ((MKMapView)Control).RemoveAnnotation((IMKAnnotation)((Pin)pin).Id);
+#else
+ ((MKMapView)Control).RemoveAnnotation ((NSObject)((Pin)pin).Id);
+#endif
+ }
+
+ void UpdateHasScrollEnabled()
+ {
+ ((MKMapView)Control).ScrollEnabled = ((Map)Element).HasScrollEnabled;
+ }
+
+ void UpdateHasZoomEnabled()
+ {
+ ((MKMapView)Control).ZoomEnabled = ((Map)Element).HasZoomEnabled;
+ }
+
+ void UpdateIsShowingUser()
+ {
+ if (FormsMaps.IsiOs8OrNewer && ((Map)Element).IsShowingUser)
+ {
+ _locationManager = new CLLocationManager();
+ _locationManager.RequestWhenInUseAuthorization();
+ }
+
+ ((MKMapView)Control).ShowsUserLocation = ((Map)Element).IsShowingUser;
+ }
+
+ void UpdateMapType()
+ {
+ switch (((Map)Element).MapType)
+ {
+ case MapType.Street:
+ ((MKMapView)Control).MapType = MKMapType.Standard;
+ break;
+ case MapType.Satellite:
+ ((MKMapView)Control).MapType = MKMapType.Satellite;
+ break;
+ case MapType.Hybrid:
+ ((MKMapView)Control).MapType = MKMapType.Hybrid;
+ break;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.iOS/Properties/AssemblyInfo.cs b/Xamarin.Forms.Maps.iOS/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..18b4256f
--- /dev/null
+++ b/Xamarin.Forms.Maps.iOS/Properties/AssemblyInfo.cs
@@ -0,0 +1,25 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Xamarin.Forms;
+using Xamarin.Forms.Maps;
+using Xamarin.Forms.Maps.iOS;
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Xamarin.Forms.Maps.iOS")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("4a5d02cd-7350-46b6-bbd5-204b727c67c9")]
+[assembly: ExportRenderer(typeof(Map), typeof(MapRenderer))]
+[assembly: Preserve] \ No newline at end of file
diff --git a/Xamarin.Forms.Maps.iOS/Xamarin.Forms.Maps.iOS.Classic.csproj b/Xamarin.Forms.Maps.iOS/Xamarin.Forms.Maps.iOS.Classic.csproj
new file mode 100644
index 00000000..d26b8649
--- /dev/null
+++ b/Xamarin.Forms.Maps.iOS/Xamarin.Forms.Maps.iOS.Classic.csproj
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{CA10FACD-22AB-463F-A20E-379C212B0858}</ProjectGuid>
+ <ProjectTypeGuids>{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <RootNamespace>Xamarin.Forms.Maps.iOS</RootNamespace>
+ <IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
+ <AssemblyName>Xamarin.Forms.Maps.iOS.Classic</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>classic_bin\iPhoneSimulator\Debug</OutputPath>
+ <BaseIntermediateOutputPath>classic_obj\</BaseIntermediateOutputPath>
+ <DefineConstants>DEBUG</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <MtouchDebug>true</MtouchDebug>
+ <CodesignKey>iPhone Developer</CodesignKey>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>classic_bin\iPhoneSimulator\Release</OutputPath>
+ <BaseIntermediateOutputPath>classic_obj\</BaseIntermediateOutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <CodesignKey>iPhone Developer</CodesignKey>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>__MOBILE__;__IOS__;DEBUG</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="MapRenderer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="FormsMaps.cs" />
+ <Compile Include="GeocoderBackend.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Core" />
+ <Reference Include="monotouch" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7D13BAC2-C6A4-416A-B07E-C169B199E52B}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.iOS\Xamarin.Forms.Platform.iOS.Classic.csproj">
+ <Project>{4a47b5df-ddfc-476b-ac41-5105ff3b9b8b}</Project>
+ <Name>Xamarin.Forms.Platform.iOS.Classic</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.MonoTouch.CSharp.targets" />
+</Project>
diff --git a/Xamarin.Forms.Maps.iOS/Xamarin.Forms.Maps.iOS.csproj b/Xamarin.Forms.Maps.iOS/Xamarin.Forms.Maps.iOS.csproj
new file mode 100644
index 00000000..a50911ba
--- /dev/null
+++ b/Xamarin.Forms.Maps.iOS/Xamarin.Forms.Maps.iOS.csproj
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}</ProjectGuid>
+ <ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <RootNamespace>Xamarin.Forms.Maps.iOS</RootNamespace>
+ <IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
+ <AssemblyName>Xamarin.Forms.Maps.iOS</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\iPhoneSimulator\Debug</OutputPath>
+ <DefineConstants>DEBUG</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <MtouchDebug>true</MtouchDebug>
+ <CodesignKey>iPhone Developer</CodesignKey>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\iPhoneSimulator\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <CodesignKey>iPhone Developer</CodesignKey>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>__UNIFIED__;__MOBILE__;__IOS__;DEBUG</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="MapRenderer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="FormsMaps.cs" />
+ <Compile Include="GeocoderBackend.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="Xamarin.iOS" />
+ <Reference Include="System" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Core" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7D13BAC2-C6A4-416A-B07E-C169B199E52B}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.iOS\Xamarin.Forms.Platform.iOS.csproj">
+ <Project>{271193c1-6e7c-429c-a36d-3f1be5267231}</Project>
+ <Name>Xamarin.Forms.Platform.iOS</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
+</Project>
diff --git a/Xamarin.Forms.Maps/Distance.cs b/Xamarin.Forms.Maps/Distance.cs
new file mode 100644
index 00000000..7125f086
--- /dev/null
+++ b/Xamarin.Forms.Maps/Distance.cs
@@ -0,0 +1,78 @@
+using System.Diagnostics;
+
+namespace Xamarin.Forms.Maps
+{
+ public struct Distance
+ {
+ const double MetersPerMile = 1609.344;
+ const double MetersPerKilometer = 1000.0;
+
+ public Distance(double meters)
+ {
+ Meters = meters;
+ }
+
+ public double Meters { get; }
+
+ public double Miles => Meters / MetersPerMile;
+
+ public double Kilometers => Meters / MetersPerKilometer;
+
+ public static Distance FromMiles(double miles)
+ {
+ if (miles < 0)
+ {
+ Debug.WriteLine("Negative values for distance not supported");
+ miles = 0;
+ }
+ return new Distance(miles * MetersPerMile);
+ }
+
+ public static Distance FromMeters(double meters)
+ {
+ if (meters < 0)
+ {
+ Debug.WriteLine("Negative values for distance not supported");
+ meters = 0;
+ }
+ return new Distance(meters);
+ }
+
+ public static Distance FromKilometers(double kilometers)
+ {
+ if (kilometers < 0)
+ {
+ Debug.WriteLine("Negative values for distance not supported");
+ kilometers = 0;
+ }
+ return new Distance(kilometers * MetersPerKilometer);
+ }
+
+ public bool Equals(Distance other)
+ {
+ return Meters.Equals(other.Meters);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ return false;
+ return obj is Distance && Equals((Distance)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return Meters.GetHashCode();
+ }
+
+ public static bool operator ==(Distance left, Distance right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Distance left, Distance right)
+ {
+ return !left.Equals(right);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps/Geocoder.cs b/Xamarin.Forms.Maps/Geocoder.cs
new file mode 100644
index 00000000..e5d6d886
--- /dev/null
+++ b/Xamarin.Forms.Maps/Geocoder.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Maps
+{
+ public class Geocoder
+ {
+ internal static Func<string, Task<IEnumerable<Position>>> GetPositionsForAddressAsyncFunc;
+
+ internal static Func<Position, Task<IEnumerable<string>>> GetAddressesForPositionFuncAsync;
+
+ public Task<IEnumerable<string>> GetAddressesForPositionAsync(Position position)
+ {
+ if (GetAddressesForPositionFuncAsync == null)
+ throw new InvalidOperationException("You MUST call Xamarin.FormsMaps.Init (); prior to using it.");
+ return GetAddressesForPositionFuncAsync(position);
+ }
+
+ public Task<IEnumerable<Position>> GetPositionsForAddressAsync(string address)
+ {
+ if (GetPositionsForAddressAsyncFunc == null)
+ throw new InvalidOperationException("You MUST call Xamarin.FormsMaps.Init (); prior to using it.");
+ return GetPositionsForAddressAsyncFunc(address);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps/Map.cs b/Xamarin.Forms.Maps/Map.cs
new file mode 100644
index 00000000..a4587a3e
--- /dev/null
+++ b/Xamarin.Forms.Maps/Map.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
+
+namespace Xamarin.Forms.Maps
+{
+ public class Map : View, IEnumerable<Pin>
+ {
+ public static readonly BindableProperty MapTypeProperty = BindableProperty.Create("MapType", typeof(MapType), typeof(Map), default(MapType));
+
+ public static readonly BindableProperty IsShowingUserProperty = BindableProperty.Create("IsShowingUser", typeof(bool), typeof(Map), default(bool));
+
+ public static readonly BindableProperty HasScrollEnabledProperty = BindableProperty.Create("HasScrollEnabled", typeof(bool), typeof(Map), true);
+
+ public static readonly BindableProperty HasZoomEnabledProperty = BindableProperty.Create("HasZoomEnabled", typeof(bool), typeof(Map), true);
+
+ readonly ObservableCollection<Pin> _pins = new ObservableCollection<Pin>();
+ MapSpan _visibleRegion;
+
+ public Map(MapSpan region)
+ {
+ LastMoveToRegion = region;
+
+ VerticalOptions = HorizontalOptions = LayoutOptions.FillAndExpand;
+
+ _pins.CollectionChanged += PinsOnCollectionChanged;
+ }
+
+ // center on Rome by default
+ public Map() : this(new MapSpan(new Position(41.890202, 12.492049), 0.1, 0.1))
+ {
+ }
+
+ public bool HasScrollEnabled
+ {
+ get { return (bool)GetValue(HasScrollEnabledProperty); }
+ set { SetValue(HasScrollEnabledProperty, value); }
+ }
+
+ public bool HasZoomEnabled
+ {
+ get { return (bool)GetValue(HasZoomEnabledProperty); }
+ set { SetValue(HasZoomEnabledProperty, value); }
+ }
+
+ public bool IsShowingUser
+ {
+ get { return (bool)GetValue(IsShowingUserProperty); }
+ set { SetValue(IsShowingUserProperty, value); }
+ }
+
+ public MapType MapType
+ {
+ get { return (MapType)GetValue(MapTypeProperty); }
+ set { SetValue(MapTypeProperty, value); }
+ }
+
+ public IList<Pin> Pins
+ {
+ get { return _pins; }
+ }
+
+ public MapSpan VisibleRegion
+ {
+ get { return _visibleRegion; }
+ internal set
+ {
+ if (_visibleRegion == value)
+ return;
+ if (value == null)
+ throw new ArgumentNullException(nameof(value));
+ OnPropertyChanging();
+ _visibleRegion = value;
+ OnPropertyChanged();
+ }
+ }
+
+ internal MapSpan LastMoveToRegion { get; private set; }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public IEnumerator<Pin> GetEnumerator()
+ {
+ return _pins.GetEnumerator();
+ }
+
+ public void MoveToRegion(MapSpan mapSpan)
+ {
+ if (mapSpan == null)
+ throw new ArgumentNullException(nameof(mapSpan));
+ LastMoveToRegion = mapSpan;
+ MessagingCenter.Send(this, "MapMoveToRegion", mapSpan);
+ }
+
+ void PinsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ if (e.NewItems != null && e.NewItems.Cast<Pin>().Any(pin => pin.Label == null))
+ throw new ArgumentException("Pin must have a Label to be added to a map");
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps/MapSpan.cs b/Xamarin.Forms.Maps/MapSpan.cs
new file mode 100644
index 00000000..883e630f
--- /dev/null
+++ b/Xamarin.Forms.Maps/MapSpan.cs
@@ -0,0 +1,116 @@
+using System;
+
+namespace Xamarin.Forms.Maps
+{
+ public sealed class MapSpan
+ {
+ const double EarthRadiusKm = 6371;
+ const double EarthCircumferenceKm = EarthRadiusKm * 2 * Math.PI;
+ const double MinimumRangeDegrees = 0.001 / EarthCircumferenceKm * 360; // 1 meter
+
+ public MapSpan(Position center, double latitudeDegrees, double longitudeDegrees)
+ {
+ Center = center;
+ LatitudeDegrees = Math.Min(Math.Max(latitudeDegrees, MinimumRangeDegrees), 90.0);
+ LongitudeDegrees = Math.Min(Math.Max(longitudeDegrees, MinimumRangeDegrees), 180.0);
+ }
+
+ public Position Center { get; }
+
+ public double LatitudeDegrees { get; }
+
+ public double LongitudeDegrees { get; }
+
+ public Distance Radius
+ {
+ get
+ {
+ double latKm = LatitudeDegreesToKm(LatitudeDegrees);
+ double longKm = LongitudeDegreesToKm(Center, LongitudeDegrees);
+ return new Distance(1000 * Math.Min(latKm, longKm) / 2);
+ }
+ }
+
+ public MapSpan ClampLatitude(double north, double south)
+ {
+ north = Math.Min(Math.Max(north, 0), 90);
+ south = Math.Max(Math.Min(south, 0), -90);
+ double lat = Math.Max(Math.Min(Center.Latitude, north), south);
+ double maxDLat = Math.Min(north - lat, -south + lat) * 2;
+ return new MapSpan(new Position(lat, Center.Longitude), Math.Min(LatitudeDegrees, maxDLat), LongitudeDegrees);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ return false;
+ if (ReferenceEquals(this, obj))
+ return true;
+ return obj is MapSpan && Equals((MapSpan)obj);
+ }
+
+ public static MapSpan FromCenterAndRadius(Position center, Distance radius)
+ {
+ return new MapSpan(center, 2 * DistanceToLatitudeDegrees(radius), 2 * DistanceToLongitudeDegrees(center, radius));
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hashCode = Center.GetHashCode();
+ hashCode = (hashCode * 397) ^ LongitudeDegrees.GetHashCode();
+ hashCode = (hashCode * 397) ^ LatitudeDegrees.GetHashCode();
+ return hashCode;
+ }
+ }
+
+ public static bool operator ==(MapSpan left, MapSpan right)
+ {
+ return Equals(left, right);
+ }
+
+ public static bool operator !=(MapSpan left, MapSpan right)
+ {
+ return !Equals(left, right);
+ }
+
+ public MapSpan WithZoom(double zoomFactor)
+ {
+ double maxDLat = Math.Min(90 - Center.Latitude, 90 + Center.Latitude) * 2;
+ return new MapSpan(Center, Math.Min(LatitudeDegrees / zoomFactor, maxDLat), LongitudeDegrees / zoomFactor);
+ }
+
+ static double DistanceToLatitudeDegrees(Distance distance)
+ {
+ return distance.Kilometers / EarthCircumferenceKm * 360;
+ }
+
+ static double DistanceToLongitudeDegrees(Position position, Distance distance)
+ {
+ double latCircumference = LatitudeCircumferenceKm(position);
+ return distance.Kilometers / latCircumference * 360;
+ }
+
+ bool Equals(MapSpan other)
+ {
+ return Center.Equals(other.Center) && LongitudeDegrees.Equals(other.LongitudeDegrees) && LatitudeDegrees.Equals(other.LatitudeDegrees);
+ }
+
+ static double LatitudeCircumferenceKm(Position position)
+ {
+ return EarthCircumferenceKm * Math.Cos(position.Latitude * Math.PI / 180.0);
+ }
+
+ static double LatitudeDegreesToKm(double latitudeDegrees)
+ {
+ return EarthCircumferenceKm * latitudeDegrees / 360;
+ }
+
+ static double LongitudeDegreesToKm(Position position, double longitudeDegrees)
+ {
+ double latCircumference = LatitudeCircumferenceKm(position);
+ return latCircumference * longitudeDegrees / 360;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps/MapType.cs b/Xamarin.Forms.Maps/MapType.cs
new file mode 100644
index 00000000..365f5afb
--- /dev/null
+++ b/Xamarin.Forms.Maps/MapType.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Forms.Maps
+{
+ public enum MapType
+ {
+ Street,
+ Satellite,
+ Hybrid
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps/Pin.cs b/Xamarin.Forms.Maps/Pin.cs
new file mode 100644
index 00000000..6c0fb556
--- /dev/null
+++ b/Xamarin.Forms.Maps/Pin.cs
@@ -0,0 +1,99 @@
+using System;
+
+namespace Xamarin.Forms.Maps
+{
+ public sealed class Pin : BindableObject
+ {
+ public static readonly BindableProperty TypeProperty = BindableProperty.Create("Type", typeof(PinType), typeof(Pin), default(PinType));
+
+ public static readonly BindableProperty PositionProperty = BindableProperty.Create("Position", typeof(Position), typeof(Pin), default(Position));
+
+ public static readonly BindableProperty AddressProperty = BindableProperty.Create("Address", typeof(string), typeof(Pin), default(string));
+
+ // introduced to store the unique id for Android markers
+
+ string _label;
+
+ public string Address
+ {
+ get { return (string)GetValue(AddressProperty); }
+ set { SetValue(AddressProperty, value); }
+ }
+
+ public string Label
+ {
+ get { return _label; }
+ set
+ {
+ if (_label == value)
+ return;
+ _label = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public Position Position
+ {
+ get { return (Position)GetValue(PositionProperty); }
+ set { SetValue(PositionProperty, value); }
+ }
+
+ public PinType Type
+ {
+ get { return (PinType)GetValue(TypeProperty); }
+ set { SetValue(TypeProperty, value); }
+ }
+
+ internal object Id { get; set; }
+
+ public event EventHandler Clicked;
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ return false;
+ if (ReferenceEquals(this, obj))
+ return true;
+ if (obj.GetType() != GetType())
+ return false;
+ return Equals((Pin)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hashCode = Label?.GetHashCode() ?? 0;
+ hashCode = (hashCode * 397) ^ Position.GetHashCode();
+ hashCode = (hashCode * 397) ^ (int)Type;
+ hashCode = (hashCode * 397) ^ (Address?.GetHashCode() ?? 0);
+ return hashCode;
+ }
+ }
+
+ public static bool operator ==(Pin left, Pin right)
+ {
+ return Equals(left, right);
+ }
+
+ public static bool operator !=(Pin left, Pin right)
+ {
+ return !Equals(left, right);
+ }
+
+ internal bool SendTap()
+ {
+ EventHandler handler = Clicked;
+ if (handler == null)
+ return false;
+
+ handler(this, EventArgs.Empty);
+ return true;
+ }
+
+ bool Equals(Pin other)
+ {
+ return string.Equals(Label, other.Label) && Equals(Position, other.Position) && Type == other.Type && string.Equals(Address, other.Address);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps/PinType.cs b/Xamarin.Forms.Maps/PinType.cs
new file mode 100644
index 00000000..a0b06fcf
--- /dev/null
+++ b/Xamarin.Forms.Maps/PinType.cs
@@ -0,0 +1,10 @@
+namespace Xamarin.Forms.Maps
+{
+ public enum PinType
+ {
+ Generic,
+ Place,
+ SavedPin,
+ SearchResult
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps/Position.cs b/Xamarin.Forms.Maps/Position.cs
new file mode 100644
index 00000000..17a86523
--- /dev/null
+++ b/Xamarin.Forms.Maps/Position.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Xamarin.Forms.Maps
+{
+ public struct Position
+ {
+ public Position(double latitude, double longitude)
+ {
+ Latitude = Math.Min(Math.Max(latitude, -90.0), 90.0);
+ Longitude = Math.Min(Math.Max(longitude, -180.0), 180.0);
+ }
+
+ public double Latitude { get; }
+
+ public double Longitude { get; }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj))
+ return false;
+ if (obj.GetType() != GetType())
+ return false;
+ var other = (Position)obj;
+ return Latitude == other.Latitude && Longitude == other.Longitude;
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hashCode = Latitude.GetHashCode();
+ hashCode = (hashCode * 397) ^ Longitude.GetHashCode();
+ return hashCode;
+ }
+ }
+
+ public static bool operator ==(Position left, Position right)
+ {
+ return Equals(left, right);
+ }
+
+ public static bool operator !=(Position left, Position right)
+ {
+ return !Equals(left, right);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Maps/Properties/AssemblyInfo.cs b/Xamarin.Forms.Maps/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..09deb1af
--- /dev/null
+++ b/Xamarin.Forms.Maps/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using Xamarin.Forms;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Xamarin.Forms.Maps")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCulture("")]
+[assembly: NeutralResourcesLanguage("en")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Maps.iOS")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Maps.iOS.Classic")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Maps.Android")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Maps.WP8")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Maps.UWP")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Maps.WinRT.Phone")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Maps.WinRT.Tablet")]
+[assembly: InternalsVisibleTo("iOSUnitTests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Core.UnitTests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Core.Android.UnitTests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Core.WP8.UnitTests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Xaml.UnitTests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Xaml")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Maps.Design")]
+[assembly: Preserve] \ No newline at end of file
diff --git a/Xamarin.Forms.Maps/Xamarin.Forms.Maps.csproj b/Xamarin.Forms.Maps/Xamarin.Forms.Maps.csproj
new file mode 100644
index 00000000..69667a33
--- /dev/null
+++ b/Xamarin.Forms.Maps/Xamarin.Forms.Maps.csproj
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{7D13BAC2-C6A4-416A-B07E-C169B199E52B}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Maps</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Maps</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .NET Framework is automatically included -->
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="Map.cs" />
+ <Compile Include="Pin.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Distance.cs" />
+ <Compile Include="MapSpan.cs" />
+ <Compile Include="MapType.cs" />
+ <Compile Include="PinType.cs" />
+ <Compile Include="Position.cs" />
+ <Compile Include="Geocoder.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android.FormsViewGroup/Jars/formsviewgroup.jar b/Xamarin.Forms.Platform.Android.FormsViewGroup/Jars/formsviewgroup.jar
new file mode 100644
index 00000000..b98d347f
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android.FormsViewGroup/Jars/formsviewgroup.jar
Binary files differ
diff --git a/Xamarin.Forms.Platform.Android.FormsViewGroup/Properties/AssemblyInfo.cs b/Xamarin.Forms.Platform.Android.FormsViewGroup/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..9274d630
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android.FormsViewGroup/Properties/AssemblyInfo.cs
@@ -0,0 +1,13 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Android.App;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle ("FormsViewGroup")]
+[assembly: AssemblyDescription ("")]
+[assembly: AssemblyConfiguration ("")]
+[assembly: AssemblyCulture ("")]
+[assembly: ComVisible (false)]
diff --git a/Xamarin.Forms.Platform.Android.FormsViewGroup/Transforms/Metadata.xml b/Xamarin.Forms.Platform.Android.FormsViewGroup/Transforms/Metadata.xml
new file mode 100644
index 00000000..33ce4700
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android.FormsViewGroup/Transforms/Metadata.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<metadata>
+ <!--
+ This sample removes the class: android.support.v4.content.AsyncTaskLoader.LoadTask:
+ <remove-node path="/api/package[@name='android.support.v4.content']/class[@name='AsyncTaskLoader.LoadTask']" />
+
+ This sample removes the method: android.support.v4.content.CursorLoader.loadInBackground:
+ <remove-node path="/api/package[@name='android.support.v4.content']/class[@name='CursorLoader']/method[@name='loadInBackground']" />
+ -->
+
+ <attr path="/api/package[@name='com.xamarin.forms.platform.android']" name="managedName">Xamarin.Forms.Platform.Android</attr>
+</metadata> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android.FormsViewGroup/Xamarin.Forms.Platform.Android.FormsViewGroup.csproj b/Xamarin.Forms.Platform.Android.FormsViewGroup/Xamarin.Forms.Platform.Android.FormsViewGroup.csproj
new file mode 100644
index 00000000..774ee324
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android.FormsViewGroup/Xamarin.Forms.Platform.Android.FormsViewGroup.csproj
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{3B72465B-ACAE-43AE-9327-10F372FE5F80}</ProjectGuid>
+ <ProjectTypeGuids>{10368E6C-D01B-4462-8E8B-01FC667A7035};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>FormsViewGroup</RootNamespace>
+ <AssemblyName>FormsViewGroup</AssemblyName>
+ <FileAlignment>512</FileAlignment>
+ <AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Mono.Android" />
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedJar Include="Jars\formsviewgroup.jar" />
+ </ItemGroup>
+ <ItemGroup>
+ <TransformFile Include="Transforms\Metadata.xml" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AndroidActivity.cs b/Xamarin.Forms.Platform.Android/AndroidActivity.cs
new file mode 100644
index 00000000..d675926f
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AndroidActivity.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ [Obsolete("AndroidActivity is obsolete as of version 1.3, please use FormsApplicationActivity")]
+ public class AndroidActivity : FormsApplicationActivity
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AndroidApplicationLifecycleState.cs b/Xamarin.Forms.Platform.Android/AndroidApplicationLifecycleState.cs
new file mode 100644
index 00000000..b0adf0de
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AndroidApplicationLifecycleState.cs
@@ -0,0 +1,14 @@
+namespace Xamarin.Forms.Platform.Android
+{
+ internal enum AndroidApplicationLifecycleState
+ {
+ Uninitialized,
+ OnCreate,
+ OnStart,
+ OnResume,
+ OnPause,
+ OnStop,
+ OnRestart,
+ OnDestroy
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AndroidTicker.cs b/Xamarin.Forms.Platform.Android/AndroidTicker.cs
new file mode 100644
index 00000000..2f5104e3
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AndroidTicker.cs
@@ -0,0 +1,43 @@
+using System;
+using Android.Animation;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class AndroidTicker : Ticker, IDisposable
+ {
+ ValueAnimator _val;
+
+ public AndroidTicker()
+ {
+ _val = new ValueAnimator();
+ _val.SetIntValues(0, 100); // avoid crash
+ _val.RepeatCount = ValueAnimator.Infinite;
+ _val.Update += OnValOnUpdate;
+ }
+
+ public void Dispose()
+ {
+ if (_val != null)
+ {
+ _val.Update -= OnValOnUpdate;
+ _val.Dispose();
+ }
+ _val = null;
+ }
+
+ protected override void DisableTimer()
+ {
+ _val?.Cancel();
+ }
+
+ protected override void EnableTimer()
+ {
+ _val?.Start();
+ }
+
+ void OnValOnUpdate(object sender, ValueAnimator.AnimatorUpdateEventArgs e)
+ {
+ SendSignals();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AndroidTitleBarVisibility.cs b/Xamarin.Forms.Platform.Android/AndroidTitleBarVisibility.cs
new file mode 100644
index 00000000..b80f54fd
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AndroidTitleBarVisibility.cs
@@ -0,0 +1,8 @@
+namespace Xamarin.Forms
+{
+ public enum AndroidTitleBarVisibility
+ {
+ Default = 0,
+ Never = 1
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/ButtonRenderer.cs b/Xamarin.Forms.Platform.Android/AppCompat/ButtonRenderer.cs
new file mode 100644
index 00000000..c6e31e18
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/ButtonRenderer.cs
@@ -0,0 +1,243 @@
+using System;
+using System.ComponentModel;
+using Android.Content;
+using Android.Content.Res;
+using Android.Graphics;
+using Android.Graphics.Drawables;
+using Android.Support.V7.Widget;
+using Android.Util;
+using GlobalResource = Android.Resource;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ public class ButtonRenderer : ViewRenderer<Button, AppCompatButton>, global::Android.Views.View.IOnAttachStateChangeListener
+ {
+ static readonly int[][] States = { new[] { GlobalResource.Attribute.StateEnabled }, new[] { -GlobalResource.Attribute.StateEnabled } };
+
+ ColorStateList _buttonDefaulTextColors;
+ Color _currentTextColor;
+ float _defaultFontSize;
+ Typeface _defaultTypeface;
+ bool _isDisposed;
+
+ public ButtonRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ global::Android.Widget.Button NativeButton => Control;
+
+ void IOnAttachStateChangeListener.OnViewAttachedToWindow(global::Android.Views.View attachedView)
+ {
+ UpdateText();
+ }
+
+ void IOnAttachStateChangeListener.OnViewDetachedFromWindow(global::Android.Views.View detachedView)
+ {
+ }
+
+ public override SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)
+ {
+ UpdateText();
+ return base.GetDesiredSize(widthConstraint, heightConstraint);
+ }
+
+ protected override AppCompatButton CreateNativeControl()
+ {
+ return new AppCompatButton(Context);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (_isDisposed)
+ return;
+
+ _isDisposed = true;
+
+ if (disposing)
+ {
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ {
+ }
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ AppCompatButton button = CreateNativeControl();
+
+ button.SetOnClickListener(ButtonClickListener.Instance.Value);
+ button.Tag = this;
+ _buttonDefaulTextColors = button.TextColors;
+ SetNativeControl(button);
+
+ button.AddOnAttachStateChangeListener(this);
+ }
+
+ UpdateAll();
+ UpdateBackgroundColor();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Button.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Button.TextColorProperty.PropertyName)
+ UpdateTextColor();
+ else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ UpdateEnabled();
+ else if (e.PropertyName == Button.FontProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Button.ImageProperty.PropertyName)
+ UpdateBitmap();
+ else if (e.PropertyName == VisualElement.IsVisibleProperty.PropertyName)
+ UpdateText();
+
+ base.OnElementPropertyChanged(sender, e);
+ }
+
+ protected override void UpdateBackgroundColor()
+ {
+ if (Element == null || Control == null)
+ return;
+
+ Color backgroundColor = Element.BackgroundColor;
+ if (backgroundColor.IsDefault)
+ {
+ if (Control.SupportBackgroundTintList != null)
+ {
+ Context context = Context;
+ int id = GlobalResource.Attribute.ButtonTint;
+ unchecked
+ {
+ using(var value = new TypedValue())
+ {
+ try
+ {
+ Resources.Theme theme = context.Theme;
+ if (theme != null && theme.ResolveAttribute(id, value, true))
+ Control.SupportBackgroundTintList = Resources.GetColorStateList(value.Data);
+ else
+ Control.SupportBackgroundTintList = new ColorStateList(States, new[] { (int)0xffd7d6d6, 0x7fd7d6d6 });
+ }
+ catch (Exception ex)
+ {
+ Control.SupportBackgroundTintList = new ColorStateList(States, new[] { (int)0xffd7d6d6, 0x7fd7d6d6 });
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ int intColor = backgroundColor.ToAndroid().ToArgb();
+ int disableColor = backgroundColor.MultiplyAlpha(0.5).ToAndroid().ToArgb();
+ Control.SupportBackgroundTintList = new ColorStateList(States, new[] { intColor, disableColor });
+ }
+ }
+
+ void UpdateAll()
+ {
+ UpdateFont();
+ UpdateText();
+ UpdateBitmap();
+ UpdateTextColor();
+ UpdateEnabled();
+ }
+
+ void UpdateBitmap()
+ {
+ FileImageSource elementImage = Element.Image;
+ string imageFile = elementImage?.File;
+ if (elementImage != null && !string.IsNullOrEmpty(imageFile))
+ {
+ Drawable image = Context.Resources.GetDrawable(imageFile);
+ Control.SetCompoundDrawablesWithIntrinsicBounds(image, null, null, null);
+ image?.Dispose();
+ }
+ else
+ Control.SetCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
+ }
+
+ void UpdateEnabled()
+ {
+ Control.Enabled = Element.IsEnabled;
+ }
+
+ void UpdateFont()
+ {
+ Button button = Element;
+ Font font = button.Font;
+
+ if (font == Font.Default && _defaultFontSize == 0f)
+ return;
+
+ if (_defaultFontSize == 0f)
+ {
+ _defaultTypeface = NativeButton.Typeface;
+ _defaultFontSize = NativeButton.TextSize;
+ }
+
+ if (font == Font.Default)
+ {
+ NativeButton.Typeface = _defaultTypeface;
+ NativeButton.SetTextSize(ComplexUnitType.Px, _defaultFontSize);
+ }
+ else
+ {
+ NativeButton.Typeface = font.ToTypeface();
+ NativeButton.SetTextSize(ComplexUnitType.Sp, font.ToScaledPixel());
+ }
+ }
+
+ void UpdateText()
+ {
+ NativeButton.Text = Element.Text;
+ }
+
+ void UpdateTextColor()
+ {
+ Color color = Element.TextColor;
+ if (color == _currentTextColor)
+ return;
+
+ _currentTextColor = color;
+
+ if (color.IsDefault)
+ NativeButton.SetTextColor(_buttonDefaulTextColors);
+ else
+ {
+ // Set the new enabled state color, preserving the default disabled state color
+ int defaultDisabledColor = _buttonDefaulTextColors.GetColorForState(States[1], color.ToAndroid());
+
+ NativeButton.SetTextColor(new ColorStateList(States, new[] { color.ToAndroid().ToArgb(), defaultDisabledColor }));
+ }
+ }
+
+ class ButtonClickListener : Object, IOnClickListener
+ {
+ #region Statics
+
+ public static readonly Lazy<ButtonClickListener> Instance = new Lazy<ButtonClickListener>(() => new ButtonClickListener());
+
+ #endregion
+
+ public void OnClick(global::Android.Views.View v)
+ {
+ var renderer = v.Tag as ButtonRenderer;
+ ((IButtonController)renderer?.Element)?.SendClicked();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/CarouselPageRenderer.cs b/Xamarin.Forms.Platform.Android/AppCompat/CarouselPageRenderer.cs
new file mode 100644
index 00000000..5e8a1b8a
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/CarouselPageRenderer.cs
@@ -0,0 +1,155 @@
+using System.Collections.Specialized;
+using System.ComponentModel;
+using Android.Content;
+using Android.Support.V4.View;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ public class CarouselPageRenderer : VisualElementRenderer<CarouselPage>, ViewPager.IOnPageChangeListener
+ {
+ bool _disposed;
+ FormsViewPager _viewPager;
+
+ public CarouselPageRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ void ViewPager.IOnPageChangeListener.OnPageScrolled(int position, float positionOffset, int positionOffsetPixels)
+ {
+ }
+
+ void ViewPager.IOnPageChangeListener.OnPageScrollStateChanged(int state)
+ {
+ }
+
+ void ViewPager.IOnPageChangeListener.OnPageSelected(int position)
+ {
+ Element.CurrentPage = Element.Children[position];
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ _disposed = true;
+ RemoveAllViews();
+ foreach (ContentPage pageToRemove in Element.Children)
+ {
+ IVisualElementRenderer pageRenderer = Android.Platform.GetRenderer(pageToRemove);
+ if (pageRenderer != null)
+ {
+ pageRenderer.ViewGroup.RemoveFromParent();
+ pageRenderer.Dispose();
+ }
+ pageToRemove.ClearValue(Android.Platform.RendererProperty);
+ }
+
+ if (_viewPager != null)
+ {
+ _viewPager.Adapter.Dispose();
+ _viewPager.Dispose();
+ _viewPager = null;
+ }
+
+ if (Element != null)
+ Element.InternalChildren.CollectionChanged -= OnChildrenCollectionChanged;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnAttachedToWindow()
+ {
+ base.OnAttachedToWindow();
+ Element.SendAppearing();
+ }
+
+ protected override void OnDetachedFromWindow()
+ {
+ base.OnDetachedFromWindow();
+ Element.SendDisappearing();
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<CarouselPage> e)
+ {
+ base.OnElementChanged(e);
+
+ var activity = (FormsAppCompatActivity)Context;
+
+ if (e.OldElement != null)
+ e.OldElement.InternalChildren.CollectionChanged -= OnChildrenCollectionChanged;
+
+ if (e.NewElement != null)
+ {
+ FormsViewPager pager =
+ _viewPager =
+ new FormsViewPager(activity)
+ {
+ OverScrollMode = OverScrollMode.Never,
+ EnableGesture = true,
+ LayoutParameters = new LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent),
+ Adapter = new FormsFragmentPagerAdapter<ContentPage>(e.NewElement, activity.SupportFragmentManager) { CountOverride = e.NewElement.Children.Count }
+ };
+ pager.Id = FormsAppCompatActivity.GetUniqueId();
+ pager.AddOnPageChangeListener(this);
+
+ AddView(pager);
+ CarouselPage carouselPage = e.NewElement;
+ if (carouselPage.CurrentPage != null)
+ ScrollToCurrentPage();
+
+ UpdateIgnoreContainerAreas();
+ carouselPage.InternalChildren.CollectionChanged += OnChildrenCollectionChanged;
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == "CurrentPage")
+ ScrollToCurrentPage();
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ FormsViewPager pager = _viewPager;
+ Context context = Context;
+ int width = r - l;
+ int height = b - t;
+
+ pager.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.AtMost), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost));
+
+ if (width > 0 && height > 0)
+ {
+ Element.ContainerArea = new Rectangle(0, 0, context.FromPixels(width), context.FromPixels(height));
+ pager.Layout(0, 0, width, b);
+ }
+
+ base.OnLayout(changed, l, t, r, b);
+ }
+
+ void OnChildrenCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ FormsViewPager pager = _viewPager;
+
+ ((FormsFragmentPagerAdapter<ContentPage>)pager.Adapter).CountOverride = Element.Children.Count;
+ pager.Adapter.NotifyDataSetChanged();
+
+ UpdateIgnoreContainerAreas();
+ }
+
+ void ScrollToCurrentPage()
+ {
+ _viewPager.SetCurrentItem(Element.Children.IndexOf(Element.CurrentPage), true);
+ }
+
+ void UpdateIgnoreContainerAreas()
+ {
+ foreach (ContentPage child in Element.Children)
+ child.IgnoresContainerArea = child is NavigationPage;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/FormsAppCompatActivity.cs b/Xamarin.Forms.Platform.Android/AppCompat/FormsAppCompatActivity.cs
new file mode 100644
index 00000000..916f1859
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/FormsAppCompatActivity.cs
@@ -0,0 +1,452 @@
+#region
+
+using System;
+using System.ComponentModel;
+using System.Linq;
+using Android.App;
+using Android.Content;
+using Android.Content.Res;
+using Android.OS;
+using Android.Runtime;
+using Android.Support.V7.App;
+using Android.Util;
+using Android.Views;
+using Android.Widget;
+using Xamarin.Forms.Platform.Android.AppCompat;
+using AToolbar = Android.Support.V7.Widget.Toolbar;
+using AColor = Android.Graphics.Color;
+using AlertDialog = Android.Support.V7.App.AlertDialog;
+using ARelativeLayout = Android.Widget.RelativeLayout;
+
+#endregion
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class FormsAppCompatActivity : AppCompatActivity, IDeviceInfoProvider, IStartActivityForResult
+ {
+ public delegate bool BackButtonPressedEventHandler(object sender, EventArgs e);
+
+ readonly ConcurrentDictionary<int, Action<Result, Intent>> _activityResultCallbacks = new ConcurrentDictionary<int, Action<Result, Intent>>();
+
+ Application _application;
+ int _busyCount;
+ AndroidApplicationLifecycleState _currentState;
+ ARelativeLayout _layout;
+
+ int _nextActivityResultCallbackKey;
+
+ AppCompat.Platform _platform;
+
+ AndroidApplicationLifecycleState _previousState;
+
+ bool _renderersAdded;
+ int _statusBarHeight = -1;
+ global::Android.Views.View _statusBarUnderlay;
+
+ protected FormsAppCompatActivity()
+ {
+ _previousState = AndroidApplicationLifecycleState.Uninitialized;
+ _currentState = AndroidApplicationLifecycleState.Uninitialized;
+ }
+
+ public event EventHandler ConfigurationChanged;
+
+ int IStartActivityForResult.RegisterActivityResultCallback(Action<Result, Intent> callback)
+ {
+ int requestCode = _nextActivityResultCallbackKey;
+
+ while (!_activityResultCallbacks.TryAdd(requestCode, callback))
+ {
+ _nextActivityResultCallbackKey += 1;
+ requestCode = _nextActivityResultCallbackKey;
+ }
+
+ _nextActivityResultCallbackKey += 1;
+
+ return requestCode;
+ }
+
+ void IStartActivityForResult.UnregisterActivityResultCallback(int requestCode)
+ {
+ Action<Result, Intent> callback;
+ _activityResultCallbacks.TryRemove(requestCode, out callback);
+ }
+
+ public override void OnBackPressed()
+ {
+ if (BackPressed != null && BackPressed(this, EventArgs.Empty))
+ return;
+ base.OnBackPressed();
+ }
+
+ public override void OnConfigurationChanged(Configuration newConfig)
+ {
+ base.OnConfigurationChanged(newConfig);
+ ConfigurationChanged?.Invoke(this, new EventArgs());
+ }
+
+ public override bool OnOptionsItemSelected(IMenuItem item)
+ {
+ if (item.ItemId == global::Android.Resource.Id.Home)
+ BackPressed?.Invoke(this, EventArgs.Empty);
+
+ return base.OnOptionsItemSelected(item);
+ }
+
+ public void SetStatusBarColor(AColor color)
+ {
+ _statusBarUnderlay.SetBackgroundColor(color);
+ }
+
+ protected void LoadApplication(Application application)
+ {
+ if (!_renderersAdded)
+ {
+ RegisterHandlerForDefaultRenderer(typeof(NavigationPage), typeof(NavigationPageRenderer), typeof(NavigationRenderer));
+ RegisterHandlerForDefaultRenderer(typeof(TabbedPage), typeof(TabbedPageRenderer), typeof(TabbedRenderer));
+ RegisterHandlerForDefaultRenderer(typeof(MasterDetailPage), typeof(MasterDetailPageRenderer), typeof(MasterDetailRenderer));
+ RegisterHandlerForDefaultRenderer(typeof(Button), typeof(AppCompat.ButtonRenderer), typeof(ButtonRenderer));
+ RegisterHandlerForDefaultRenderer(typeof(Switch), typeof(AppCompat.SwitchRenderer), typeof(SwitchRenderer));
+ RegisterHandlerForDefaultRenderer(typeof(Picker), typeof(AppCompat.PickerRenderer), typeof(PickerRenderer));
+ RegisterHandlerForDefaultRenderer(typeof(Frame), typeof(AppCompat.FrameRenderer), typeof(FrameRenderer));
+ RegisterHandlerForDefaultRenderer(typeof(CarouselPage), typeof(AppCompat.CarouselPageRenderer), typeof(CarouselPageRenderer));
+ }
+
+ if (application == null)
+ throw new ArgumentNullException("application");
+
+ _application = application;
+ Xamarin.Forms.Application.Current = application;
+
+ application.PropertyChanged += AppOnPropertyChanged;
+
+ SetMainPage();
+ }
+
+ protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
+ {
+ base.OnActivityResult(requestCode, resultCode, data);
+
+ Action<Result, Intent> callback;
+
+ if (_activityResultCallbacks.TryGetValue(requestCode, out callback))
+ callback(resultCode, data);
+ }
+
+ protected override void OnCreate(Bundle savedInstanceState)
+ {
+ base.OnCreate(savedInstanceState);
+
+ AToolbar bar;
+ if (ToolbarResource != 0)
+ {
+ bar = LayoutInflater.Inflate(ToolbarResource, null).JavaCast<AToolbar>();
+ if (bar == null)
+ throw new InvalidOperationException("ToolbarResource must be set to a Android.Support.V7.Widget.Toolbar");
+ }
+ else
+ bar = new AToolbar(this);
+
+ SetSupportActionBar(bar);
+
+ Window.SetSoftInputMode(SoftInput.AdjustPan);
+
+ _layout = new ARelativeLayout(BaseContext);
+ SetContentView(_layout);
+
+ Xamarin.Forms.Application.ClearCurrent();
+
+ _previousState = _currentState;
+ _currentState = AndroidApplicationLifecycleState.OnCreate;
+
+ OnStateChanged();
+
+ _statusBarUnderlay = new global::Android.Views.View(this);
+ var layoutParameters = new ARelativeLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, GetStatusBarHeight()) { AlignWithParent = true };
+ layoutParameters.AddRule(LayoutRules.AlignTop);
+ _statusBarUnderlay.LayoutParameters = layoutParameters;
+ _layout.AddView(_statusBarUnderlay);
+
+ if (Forms.IsLollipopOrNewer)
+ {
+ Window.DecorView.SystemUiVisibility = (StatusBarVisibility)(SystemUiFlags.LayoutFullscreen | SystemUiFlags.LayoutStable);
+ Window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
+ Window.SetStatusBarColor(AColor.Transparent);
+
+ int primaryColorDark = GetColorPrimaryDark();
+
+ if (primaryColorDark != 0)
+ {
+ int r = AColor.GetRedComponent(primaryColorDark);
+ int g = AColor.GetGreenComponent(primaryColorDark);
+ int b = AColor.GetBlueComponent(primaryColorDark);
+ int a = AColor.GetAlphaComponent(primaryColorDark);
+ SetStatusBarColor(AColor.Argb(a, r, g, b));
+ }
+ }
+ }
+
+ protected override void OnDestroy()
+ {
+ // may never be called
+ base.OnDestroy();
+
+ MessagingCenter.Unsubscribe<Page, AlertArguments>(this, Page.AlertSignalName);
+ MessagingCenter.Unsubscribe<Page, bool>(this, Page.BusySetSignalName);
+ MessagingCenter.Unsubscribe<Page, ActionSheetArguments>(this, Page.ActionSheetSignalName);
+
+ if (_platform != null)
+ _platform.Dispose();
+ }
+
+ protected override void OnNewIntent(Intent intent)
+ {
+ base.OnNewIntent(intent);
+ }
+
+ protected override void OnPause()
+ {
+ _layout.HideKeyboard(true);
+
+ // Stop animations or other ongoing actions that could consume CPU
+ // Commit unsaved changes, build only if users expect such changes to be permanently saved when thy leave such as a draft email
+ // Release system resources, such as broadcast receivers, handles to sensors (like GPS), or any resources that may affect battery life when your activity is paused.
+ // Avoid writing to permanent storage and CPU intensive tasks
+ base.OnPause();
+
+ _previousState = _currentState;
+ _currentState = AndroidApplicationLifecycleState.OnPause;
+
+ OnStateChanged();
+ }
+
+ protected override void OnRestart()
+ {
+ base.OnRestart();
+
+ _previousState = _currentState;
+ _currentState = AndroidApplicationLifecycleState.OnRestart;
+
+ OnStateChanged();
+ }
+
+ protected override void OnResume()
+ {
+ // counterpart to OnPause
+ base.OnResume();
+
+ _previousState = _currentState;
+ _currentState = AndroidApplicationLifecycleState.OnResume;
+
+ OnStateChanged();
+ }
+
+ protected override void OnStart()
+ {
+ base.OnStart();
+
+ _previousState = _currentState;
+ _currentState = AndroidApplicationLifecycleState.OnStart;
+
+ OnStateChanged();
+ }
+
+ // Scenarios that stop and restart your app
+ // -- Switches from your app to another app, activity restarts when clicking on the app again.
+ // -- Action in your app that starts a new Activity, the current activity is stopped and the second is created, pressing back restarts the activity
+ // -- The user receives a phone call while using your app on his or her phone
+ protected override void OnStop()
+ {
+ // writing to storage happens here!
+ // full UI obstruction
+ // users focus in another activity
+ // perform heavy load shutdown operations
+ // clean up resources
+ // clean up everything that may leak memory
+ base.OnStop();
+
+ _previousState = _currentState;
+ _currentState = AndroidApplicationLifecycleState.OnStop;
+
+ OnStateChanged();
+ }
+
+ internal int GetStatusBarHeight()
+ {
+ if (_statusBarHeight >= 0)
+ return _statusBarHeight;
+
+ var result = 0;
+ int resourceId = Resources.GetIdentifier("status_bar_height", "dimen", "android");
+ if (resourceId > 0)
+ result = Resources.GetDimensionPixelSize(resourceId);
+ return _statusBarHeight = result;
+ }
+
+ void AppOnPropertyChanged(object sender, PropertyChangedEventArgs args)
+ {
+ if (args.PropertyName == "MainPage")
+ InternalSetPage(_application.MainPage);
+ }
+
+ int GetColorPrimaryDark()
+ {
+ FormsAppCompatActivity context = this;
+ int id = global::Android.Resource.Attribute.ColorPrimaryDark;
+ using(var value = new TypedValue())
+ {
+ try
+ {
+ Resources.Theme theme = context.Theme;
+ if (theme != null && theme.ResolveAttribute(id, value, true))
+ {
+ if (value.Type >= DataType.FirstInt && value.Type <= DataType.LastInt)
+ return value.Data;
+ if (value.Type == DataType.String)
+ return context.Resources.GetColor(value.ResourceId);
+ }
+ }
+ catch (Exception ex)
+ {
+ }
+
+ return -1;
+ }
+ }
+
+ void InternalSetPage(Page page)
+ {
+ if (!Forms.IsInitialized)
+ throw new InvalidOperationException("Call Forms.Init (Activity, Bundle) before this");
+
+ if (_platform != null)
+ {
+ _platform.SetPage(page);
+ return;
+ }
+
+ _busyCount = 0;
+ MessagingCenter.Subscribe<Page, bool>(this, Page.BusySetSignalName, OnPageBusy);
+ MessagingCenter.Subscribe<Page, AlertArguments>(this, Page.AlertSignalName, OnAlertRequested);
+ MessagingCenter.Subscribe<Page, ActionSheetArguments>(this, Page.ActionSheetSignalName, OnActionSheetRequested);
+
+ _platform = new AppCompat.Platform(this);
+ if (_application != null)
+ _application.Platform = _platform;
+ _platform.SetPage(page);
+ _layout.AddView(_platform);
+ _layout.BringToFront();
+ }
+
+ void OnActionSheetRequested(Page sender, ActionSheetArguments arguments)
+ {
+ var builder = new AlertDialog.Builder(this);
+ builder.SetTitle(arguments.Title);
+ string[] items = arguments.Buttons.ToArray();
+ builder.SetItems(items, (o, args) => arguments.Result.TrySetResult(items[args.Which]));
+
+ if (arguments.Cancel != null)
+ builder.SetPositiveButton(arguments.Cancel, (o, args) => arguments.Result.TrySetResult(arguments.Cancel));
+
+ if (arguments.Destruction != null)
+ builder.SetNegativeButton(arguments.Destruction, (o, args) => arguments.Result.TrySetResult(arguments.Destruction));
+
+ AlertDialog dialog = builder.Create();
+ builder.Dispose();
+ //to match current functionality of renderer we set cancelable on outside
+ //and return null
+ dialog.SetCanceledOnTouchOutside(true);
+ dialog.CancelEvent += (o, e) => arguments.SetResult(null);
+ dialog.Show();
+ }
+
+ void OnAlertRequested(Page sender, AlertArguments arguments)
+ {
+ AlertDialog alert = new AlertDialog.Builder(this).Create();
+ alert.SetTitle(arguments.Title);
+ alert.SetMessage(arguments.Message);
+ if (arguments.Accept != null)
+ alert.SetButton((int)DialogButtonType.Positive, arguments.Accept, (o, args) => arguments.SetResult(true));
+ alert.SetButton((int)DialogButtonType.Negative, arguments.Cancel, (o, args) => arguments.SetResult(false));
+ alert.CancelEvent += (o, args) => { arguments.SetResult(false); };
+ alert.Show();
+ }
+
+ void OnPageBusy(Page sender, bool enabled)
+ {
+ _busyCount = Math.Max(0, enabled ? _busyCount + 1 : _busyCount - 1);
+
+ if (!Forms.SupportsProgress)
+ return;
+
+ SetProgressBarIndeterminate(true);
+ UpdateProgressBarVisibility(_busyCount > 0);
+ }
+
+ async void OnStateChanged()
+ {
+ if (_application == null)
+ return;
+
+ if (_previousState == AndroidApplicationLifecycleState.OnCreate && _currentState == AndroidApplicationLifecycleState.OnStart)
+ _application.SendStart();
+ else if (_previousState == AndroidApplicationLifecycleState.OnStop && _currentState == AndroidApplicationLifecycleState.OnRestart)
+ _application.SendResume();
+ else if (_previousState == AndroidApplicationLifecycleState.OnPause && _currentState == AndroidApplicationLifecycleState.OnStop)
+ await _application.SendSleepAsync();
+ }
+
+ void RegisterHandlerForDefaultRenderer(Type target, Type handler, Type filter)
+ {
+ Type current = Registrar.Registered.GetHandlerType(filter);
+ if (current == target)
+ return;
+
+ Registrar.Registered.Register(target, handler);
+ }
+
+ void SetMainPage()
+ {
+ InternalSetPage(_application.MainPage);
+ }
+
+ void UpdateProgressBarVisibility(bool isBusy)
+ {
+ if (!Forms.SupportsProgress)
+ return;
+
+ SetProgressBarIndeterminateVisibility(isBusy);
+ }
+
+ internal class DefaultApplication : Application
+ {
+ }
+
+ #region Statics
+
+ public static event BackButtonPressedEventHandler BackPressed;
+
+ public static int TabLayoutResource { get; set; }
+
+ public static int ToolbarResource { get; set; }
+
+ internal static int GetUniqueId()
+ {
+ // getting unique Id's is an art, and I consider myself the Jackson Pollock of the field
+ if ((int)Build.VERSION.SdkInt >= 17)
+ return global::Android.Views.View.GenerateViewId();
+
+ // Numbers higher than this range reserved for xml
+ // If we roll over, it can be exceptionally problematic for the user if they are still retaining things, android's internal implementation is
+ // basically identical to this except they do a lot of locking we don't have to because we know we only do this
+ // from the UI thread
+ if (s_id >= 0x00ffffff)
+ s_id = 0x00000400;
+ return s_id++;
+ }
+
+ static int s_id = 0x00000400;
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/FormsFragmentPagerAdapter.cs b/Xamarin.Forms.Platform.Android/AppCompat/FormsFragmentPagerAdapter.cs
new file mode 100644
index 00000000..99fbb396
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/FormsFragmentPagerAdapter.cs
@@ -0,0 +1,59 @@
+using Android.OS;
+using Android.Support.V4.App;
+using Java.Lang;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ internal class FormsFragmentPagerAdapter<T> : FragmentPagerAdapter where T : Page
+ {
+ MultiPage<T> _page;
+
+ public FormsFragmentPagerAdapter(MultiPage<T> page, FragmentManager fragmentManager) : base(fragmentManager)
+ {
+ _page = page;
+ }
+
+ public override int Count => CountOverride;
+
+ public int CountOverride { get; set; }
+
+ public override Fragment GetItem(int position)
+ {
+ return FragmentContainer.CreateInstance(_page.Children[position]);
+ }
+
+ public override long GetItemId(int position)
+ {
+ return _page.Children[position].GetHashCode();
+ }
+
+ public override int GetItemPosition(Object objectValue)
+ {
+ var fragContainer = objectValue as FragmentContainer;
+ if (fragContainer != null && fragContainer.Page != null)
+ {
+ int index = _page.Children.IndexOf(fragContainer.Page);
+ if (index >= 0)
+ return index;
+ }
+ return PositionNone;
+ }
+
+ public override ICharSequence GetPageTitleFormatted(int position)
+ {
+ return new String(_page.Children[position].Title);
+ }
+
+ // http://stackoverflow.com/questions/18642890/fragmentstatepageradapter-with-childfragmentmanager-fragmentmanagerimpl-getfra/19099987#19099987
+ public override void RestoreState(IParcelable state, ClassLoader loader)
+ {
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ _page = null;
+ base.Dispose(disposing);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/FormsViewPager.cs b/Xamarin.Forms.Platform.Android/AppCompat/FormsViewPager.cs
new file mode 100644
index 00000000..2327bb4e
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/FormsViewPager.cs
@@ -0,0 +1,34 @@
+using System;
+using Android.Content;
+using Android.Runtime;
+using Android.Support.V4.View;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ internal class FormsViewPager : ViewPager
+ {
+ public FormsViewPager(Context context) : base(context)
+ {
+ }
+
+ protected FormsViewPager(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
+ {
+ }
+
+ public bool EnableGesture { get; set; } = true;
+
+ public override bool OnInterceptTouchEvent(MotionEvent ev)
+ {
+ // Same as:
+ // if (!EnableGesture) return false;
+ // However this is, at least in theory a tidge faster which in this particular area is good
+ return EnableGesture && base.OnInterceptTouchEvent(ev);
+ }
+
+ public override bool OnTouchEvent(MotionEvent e)
+ {
+ return EnableGesture && base.OnTouchEvent(e);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/FragmentContainer.cs b/Xamarin.Forms.Platform.Android/AppCompat/FragmentContainer.cs
new file mode 100644
index 00000000..39219188
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/FragmentContainer.cs
@@ -0,0 +1,111 @@
+using System;
+using Android.OS;
+using Android.Runtime;
+using Android.Support.V4.App;
+using Android.Views;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ internal class FragmentContainer : Fragment
+ {
+ readonly WeakReference _pageReference;
+
+ bool? _isVisible;
+ PageContainer _pageContainer;
+ IVisualElementRenderer _visualElementRenderer;
+
+ public FragmentContainer()
+ {
+ }
+
+ public FragmentContainer(Page page) : this()
+ {
+ _pageReference = new WeakReference(page);
+ }
+
+ protected FragmentContainer(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
+ {
+ }
+
+ public Page Page => (Page)_pageReference?.Target;
+
+ public override bool UserVisibleHint
+ {
+ get { return base.UserVisibleHint; }
+ set
+ {
+ base.UserVisibleHint = value;
+ if (_isVisible == value)
+ return;
+ _isVisible = value;
+ if (_isVisible.Value)
+ Page?.SendAppearing();
+ else
+ Page?.SendDisappearing();
+ }
+ }
+
+ public static Fragment CreateInstance(Page page)
+ {
+ return new FragmentContainer(page) { Arguments = new Bundle() };
+ }
+
+ public override AView OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
+ {
+ if (Page != null)
+ {
+ _visualElementRenderer = Android.Platform.CreateRenderer(Page, ChildFragmentManager);
+ Android.Platform.SetRenderer(Page, _visualElementRenderer);
+
+ _pageContainer = new PageContainer(Forms.Context, _visualElementRenderer, true);
+ return _pageContainer;
+ }
+
+ return null;
+ }
+
+ public override void OnDestroyView()
+ {
+ if (Page != null)
+ {
+ IVisualElementRenderer renderer = _visualElementRenderer;
+ PageContainer container = _pageContainer;
+
+ if (container.Handle != IntPtr.Zero && renderer.ViewGroup.Handle != IntPtr.Zero)
+ {
+ container.RemoveFromParent();
+ renderer.ViewGroup.RemoveFromParent();
+ Page.ClearValue(Android.Platform.RendererProperty);
+
+ container.Dispose();
+ renderer.Dispose();
+ }
+ }
+
+ _visualElementRenderer = null;
+ _pageContainer = null;
+
+ base.OnDestroyView();
+ }
+
+ public override void OnHiddenChanged(bool hidden)
+ {
+ base.OnHiddenChanged(hidden);
+
+ if (Page == null)
+ return;
+
+ if (hidden)
+ Page.SendDisappearing();
+ else
+ Page.SendAppearing();
+ }
+
+ public override void OnPause()
+ {
+ Page?.SendDisappearing();
+ base.OnPause();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/FrameRenderer.cs b/Xamarin.Forms.Platform.Android/AppCompat/FrameRenderer.cs
new file mode 100644
index 00000000..7b544b25
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/FrameRenderer.cs
@@ -0,0 +1,215 @@
+using System;
+using System.ComponentModel;
+using Android.Content;
+using Android.Support.V4.View;
+using Android.Support.V7.Widget;
+using Android.Views;
+using AColor = Android.Graphics.Color;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ public class FrameRenderer : CardView, IVisualElementRenderer, AView.IOnClickListener, AView.IOnTouchListener
+ {
+ readonly Lazy<GestureDetector> _gestureDetector;
+ readonly PanGestureHandler _panGestureHandler;
+ readonly PinchGestureHandler _pinchGestureHandler;
+ readonly Lazy<ScaleGestureDetector> _scaleDetector;
+ readonly TapGestureHandler _tapGestureHandler;
+
+ float _defaultElevation = -1f;
+
+ bool _disposed;
+ Frame _element;
+ InnerGestureListener _gestureListener;
+ VisualElementPackager _visualElementPackager;
+ VisualElementTracker _visualElementTracker;
+
+ public FrameRenderer() : base(Forms.Context)
+ {
+ _tapGestureHandler = new TapGestureHandler(() => Element);
+ _panGestureHandler = new PanGestureHandler(() => Element, Context.FromPixels);
+ _pinchGestureHandler = new PinchGestureHandler(() => Element);
+
+ _gestureDetector =
+ new Lazy<GestureDetector>(
+ () =>
+ new GestureDetector(
+ _gestureListener =
+ new InnerGestureListener(_tapGestureHandler.OnTap, _tapGestureHandler.TapGestureRecognizers, _panGestureHandler.OnPan, _panGestureHandler.OnPanStarted, _panGestureHandler.OnPanComplete)));
+
+ _scaleDetector =
+ new Lazy<ScaleGestureDetector>(
+ () => new ScaleGestureDetector(Context, new InnerScaleListener(_pinchGestureHandler.OnPinch, _pinchGestureHandler.OnPinchStarted, _pinchGestureHandler.OnPinchEnded), Handler));
+ }
+
+ protected CardView Control => this;
+
+ protected Frame Element
+ {
+ get { return _element; }
+ set
+ {
+ if (_element == value)
+ return;
+
+ Frame oldElement = _element;
+ _element = value;
+
+ OnElementChanged(new ElementChangedEventArgs<Frame>(oldElement, _element));
+
+ if (_element != null)
+ _element.SendViewInitialized(Control);
+ }
+ }
+
+ void IOnClickListener.OnClick(AView v)
+ {
+ _tapGestureHandler.OnSingleClick();
+ }
+
+ bool IOnTouchListener.OnTouch(AView v, MotionEvent e)
+ {
+ var handled = false;
+ if (_pinchGestureHandler.IsPinchSupported)
+ {
+ if (!_scaleDetector.IsValueCreated)
+ ScaleGestureDetectorCompat.SetQuickScaleEnabled(_scaleDetector.Value, true);
+ handled = _scaleDetector.Value.OnTouchEvent(e);
+ }
+ return _gestureDetector.Value.OnTouchEvent(e) || handled;
+ }
+
+ VisualElement IVisualElementRenderer.Element => Element;
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ SizeRequest IVisualElementRenderer.GetDesiredSize(int widthConstraint, int heightConstraint)
+ {
+ Context context = Context;
+ return new SizeRequest(new Size(context.ToPixels(20), context.ToPixels(20)));
+ }
+
+ void IVisualElementRenderer.SetElement(VisualElement element)
+ {
+ var frame = element as Frame;
+ if (frame == null)
+ throw new ArgumentException("Element must be of type Frame");
+ Element = frame;
+
+ if (!string.IsNullOrEmpty(Element.AutomationId))
+ ContentDescription = Element.AutomationId;
+ }
+
+ VisualElementTracker IVisualElementRenderer.Tracker => _visualElementTracker;
+
+ void IVisualElementRenderer.UpdateLayout()
+ {
+ VisualElementTracker tracker = _visualElementTracker;
+ tracker?.UpdateLayout();
+ }
+
+ ViewGroup IVisualElementRenderer.ViewGroup => this;
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ _disposed = true;
+
+ if (_gestureListener != null)
+ {
+ _gestureListener.Dispose();
+ _gestureListener = null;
+ }
+
+ if (_visualElementTracker != null)
+ {
+ _visualElementTracker.Dispose();
+ _visualElementTracker = null;
+ }
+
+ if (_visualElementPackager != null)
+ {
+ _visualElementPackager.Dispose();
+ _visualElementPackager = null;
+ }
+
+ if (Element != null)
+ Element.PropertyChanged -= OnElementPropertyChanged;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected virtual void OnElementChanged(ElementChangedEventArgs<Frame> e)
+ {
+ ElementChanged?.Invoke(this, new VisualElementChangedEventArgs(e.OldElement, e.NewElement));
+
+ if (e.OldElement != null)
+ e.OldElement.PropertyChanged -= OnElementPropertyChanged;
+ else
+ {
+ SetOnClickListener(this);
+ SetOnTouchListener(this);
+ }
+
+ if (e.NewElement != null)
+ {
+ if (_visualElementTracker == null)
+ {
+ _visualElementTracker = new VisualElementTracker(this);
+ _visualElementPackager = new VisualElementPackager(this);
+ _visualElementPackager.Load();
+ }
+
+ e.NewElement.PropertyChanged += OnElementPropertyChanged;
+ UpdateShadow();
+ UpdateBackgroundColor();
+ }
+ }
+
+ protected override void OnLayout(bool changed, int left, int top, int right, int bottom)
+ {
+ if (Element == null)
+ return;
+
+ var children = Element.LogicalChildren;
+ for (var i = 0; i < children.Count; i++)
+ {
+ var visualElement = children[i] as VisualElement;
+ if (visualElement == null)
+ continue;
+ IVisualElementRenderer renderer = Android.Platform.GetRenderer(visualElement);
+ renderer?.UpdateLayout();
+ }
+ }
+
+ void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Frame.HasShadowProperty.PropertyName)
+ UpdateShadow();
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackgroundColor();
+ }
+
+ void UpdateBackgroundColor()
+ {
+ Color bgColor = Element.BackgroundColor;
+ SetCardBackgroundColor(bgColor.IsDefault ? AColor.White : bgColor.ToAndroid());
+ }
+
+ void UpdateShadow()
+ {
+ float elevation = _defaultElevation;
+
+ if (elevation == -1f)
+ _defaultElevation = elevation = CardElevation;
+
+ if (Element.HasShadow)
+ CardElevation = elevation;
+ else
+ CardElevation = 0f;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/IManageFragments.cs b/Xamarin.Forms.Platform.Android/AppCompat/IManageFragments.cs
new file mode 100644
index 00000000..5b6c4cb7
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/IManageFragments.cs
@@ -0,0 +1,13 @@
+using Android.Support.V4.App;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ /// <summary>
+ /// Allows the platform to inject child fragment managers for renderers
+ /// which do their own fragment management
+ /// </summary>
+ internal interface IManageFragments
+ {
+ void SetFragmentManager(FragmentManager fragmentManager);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/MasterDetailPageRenderer.cs b/Xamarin.Forms.Platform.Android/AppCompat/MasterDetailPageRenderer.cs
new file mode 100644
index 00000000..ec6b4395
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/MasterDetailPageRenderer.cs
@@ -0,0 +1,355 @@
+using System;
+using System.ComponentModel;
+using System.Threading.Tasks;
+using Android.Support.V4.Widget;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ public class MasterDetailPageRenderer : DrawerLayout, IVisualElementRenderer, DrawerLayout.IDrawerListener
+ {
+ #region Statics
+
+ //from Android source code
+ const uint DefaultScrimColor = 0x99000000;
+
+ #endregion
+
+ int _currentLockMode = -1;
+ MasterDetailContainer _detailLayout;
+
+ bool _disposed;
+ bool _isPresentingFromCore;
+ MasterDetailContainer _masterLayout;
+ bool _presented;
+ VisualElementTracker _tracker;
+
+ public MasterDetailPageRenderer() : base(Forms.Context)
+ {
+ }
+
+ MasterDetailPage Element { get; set; }
+
+ bool Presented
+ {
+ get { return _presented; }
+ set
+ {
+ if (value == _presented)
+ return;
+ UpdateSplitViewLayout();
+ _presented = value;
+ if (Element.MasterBehavior == MasterBehavior.Default && Element.ShouldShowSplitMode)
+ return;
+ if (_presented)
+ OpenDrawer(_masterLayout);
+ else
+ CloseDrawer(_masterLayout);
+ }
+ }
+
+ void IDrawerListener.OnDrawerClosed(global::Android.Views.View drawerView)
+ {
+ }
+
+ void IDrawerListener.OnDrawerOpened(global::Android.Views.View drawerView)
+ {
+ }
+
+ void IDrawerListener.OnDrawerSlide(global::Android.Views.View drawerView, float slideOffset)
+ {
+ }
+
+ void IDrawerListener.OnDrawerStateChanged(int newState)
+ {
+ _presented = IsDrawerVisible(_masterLayout);
+ UpdateIsPresented();
+ }
+
+ VisualElement IVisualElementRenderer.Element => Element;
+
+ event EventHandler<VisualElementChangedEventArgs> IVisualElementRenderer.ElementChanged
+ {
+ add { ElementChanged += value; }
+ remove { ElementChanged -= value; }
+ }
+
+ SizeRequest IVisualElementRenderer.GetDesiredSize(int widthConstraint, int heightConstraint)
+ {
+ Measure(widthConstraint, heightConstraint);
+ return new SizeRequest(new Size(MeasuredWidth, MeasuredHeight));
+ }
+
+ void IVisualElementRenderer.SetElement(VisualElement element)
+ {
+ MasterDetailPage oldElement = Element;
+ MasterDetailPage newElement = Element = element as MasterDetailPage;
+
+ if (oldElement != null)
+ {
+ oldElement.BackButtonPressed -= OnBackButtonPressed;
+ oldElement.PropertyChanged -= HandlePropertyChanged;
+ oldElement.Appearing -= MasterDetailPageAppearing;
+ oldElement.Disappearing -= MasterDetailPageDisappearing;
+ }
+
+ var statusBarHeight = 0;
+ if (Forms.IsLollipopOrNewer)
+ statusBarHeight = ((FormsAppCompatActivity)Context).GetStatusBarHeight();
+
+ if (newElement != null)
+ {
+ if (_detailLayout == null)
+ {
+ _detailLayout = new MasterDetailContainer(newElement, false, Context)
+ {
+ TopPadding = statusBarHeight,
+ LayoutParameters = new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent)
+ };
+
+ _masterLayout = new MasterDetailContainer(newElement, true, Context)
+ {
+ LayoutParameters = new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent) { Gravity = (int)GravityFlags.Start }
+ };
+
+ AddView(_detailLayout);
+ AddView(_masterLayout);
+
+ Device.Info.PropertyChanged += DeviceInfoPropertyChanged;
+
+ SetDrawerListener(this);
+ }
+
+ UpdateBackgroundColor(newElement);
+ UpdateBackgroundImage(newElement);
+
+ UpdateMaster();
+ UpdateDetail();
+
+ newElement.BackButtonPressed += OnBackButtonPressed;
+ newElement.PropertyChanged += HandlePropertyChanged;
+ newElement.Appearing += MasterDetailPageAppearing;
+ newElement.Disappearing += MasterDetailPageDisappearing;
+
+ SetGestureState();
+
+ Presented = newElement.IsPresented;
+
+ newElement.SendViewInitialized(this);
+ }
+
+ OnElementChanged(oldElement, newElement);
+
+ // Make sure to initialize this AFTER event is fired
+ if (_tracker == null)
+ _tracker = new VisualElementTracker(this);
+ }
+
+ VisualElementTracker IVisualElementRenderer.Tracker => _tracker;
+
+ void IVisualElementRenderer.UpdateLayout()
+ {
+ _tracker?.UpdateLayout();
+ }
+
+ ViewGroup IVisualElementRenderer.ViewGroup => this;
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ _disposed = true;
+
+ if (_tracker != null)
+ {
+ _tracker.Dispose();
+ _tracker = null;
+ }
+
+ if (_detailLayout != null)
+ {
+ _detailLayout.Dispose();
+ _detailLayout = null;
+ }
+
+ if (_masterLayout != null)
+ {
+ _masterLayout.Dispose();
+ _masterLayout = null;
+ }
+
+ Device.Info.PropertyChanged -= DeviceInfoPropertyChanged;
+
+ if (Element != null)
+ {
+ Element.BackButtonPressed -= OnBackButtonPressed;
+ Element.PropertyChanged -= HandlePropertyChanged;
+ Element.Appearing -= MasterDetailPageAppearing;
+ Element.Disappearing -= MasterDetailPageDisappearing;
+ Element.ClearValue(Android.Platform.RendererProperty);
+ Element = null;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnAttachedToWindow()
+ {
+ base.OnAttachedToWindow();
+ Element.SendAppearing();
+ }
+
+ protected override void OnDetachedFromWindow()
+ {
+ base.OnDetachedFromWindow();
+ Element.SendDisappearing();
+ }
+
+ protected virtual void OnElementChanged(VisualElement oldElement, VisualElement newElement)
+ {
+ ElementChanged?.Invoke(this, new VisualElementChangedEventArgs(oldElement, newElement));
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ base.OnLayout(changed, l, t, r, b);
+ //hack to make the split layout handle touches the full width
+ if (Element.ShouldShowSplitMode && _masterLayout != null)
+ _masterLayout.Right = r;
+ }
+
+ async void DeviceInfoPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (nameof(Device.Info.CurrentOrientation) == e.PropertyName)
+ {
+ if (!Element.ShouldShowSplitMode && Presented)
+ {
+ Element.CanChangeIsPresented = true;
+ //hack : when the orientation changes and we try to close the Master on Android
+ //sometimes Android picks the width of the screen previous to the rotation
+ //this leaves a little of the master visible, the hack is to delay for 50ms closing the drawer
+ await Task.Delay(100);
+ CloseDrawer(_masterLayout);
+ }
+ UpdateSplitViewLayout();
+ }
+ }
+
+ event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ void HandleMasterPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ }
+
+ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "Master")
+ UpdateMaster();
+ else if (e.PropertyName == "Detail")
+ UpdateDetail();
+ else if (e.PropertyName == "IsGestureEnabled")
+ SetGestureState();
+ else if (e.PropertyName == MasterDetailPage.IsPresentedProperty.PropertyName)
+ {
+ _isPresentingFromCore = true;
+ Presented = Element.IsPresented;
+ _isPresentingFromCore = false;
+ }
+ else if (e.PropertyName == Page.BackgroundImageProperty.PropertyName)
+ UpdateBackgroundImage(Element);
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackgroundColor(Element);
+ }
+
+ void MasterDetailPageAppearing(object sender, EventArgs e)
+ {
+ Element.Master?.SendAppearing();
+ Element.Detail?.SendAppearing();
+ }
+
+ void MasterDetailPageDisappearing(object sender, EventArgs e)
+ {
+ Element.Master?.SendDisappearing();
+ Element.Detail?.SendDisappearing();
+ }
+
+ void OnBackButtonPressed(object sender, BackButtonPressedEventArgs backButtonPressedEventArgs)
+ {
+ if (!IsDrawerOpen((int)GravityFlags.Start) || _currentLockMode == LockModeLockedOpen)
+ return;
+
+ CloseDrawer((int)GravityFlags.Start);
+ backButtonPressedEventArgs.Handled = true;
+ }
+
+ void SetGestureState()
+ {
+ SetDrawerLockMode(Element.IsGestureEnabled ? LockModeUnlocked : LockModeLockedClosed);
+ }
+
+ void SetLockMode(int lockMode)
+ {
+ if (_currentLockMode != lockMode)
+ {
+ SetDrawerLockMode(lockMode);
+ _currentLockMode = lockMode;
+ }
+ }
+
+ void UpdateBackgroundColor(Page view)
+ {
+ Color backgroundColor = view.BackgroundColor;
+ if (backgroundColor.IsDefault)
+ SetBackgroundColor(backgroundColor.ToAndroid());
+ }
+
+ void UpdateBackgroundImage(Page view)
+ {
+ string backgroundImage = view.BackgroundImage;
+ if (!string.IsNullOrEmpty(backgroundImage))
+ this.SetBackground(Context.Resources.GetDrawable(backgroundImage));
+ }
+
+ void UpdateDetail()
+ {
+ Context.HideKeyboard(this);
+ _detailLayout.ChildView = Element.Detail;
+ }
+
+ void UpdateIsPresented()
+ {
+ if (_isPresentingFromCore)
+ return;
+ if (Presented != Element.IsPresented)
+ ((IElementController)Element).SetValueFromRenderer(MasterDetailPage.IsPresentedProperty, Presented);
+ }
+
+ void UpdateMaster()
+ {
+ MasterDetailContainer masterContainer = _masterLayout;
+ if (masterContainer == null)
+ return;
+
+ if (masterContainer.ChildView != null)
+ masterContainer.ChildView.PropertyChanged -= HandleMasterPropertyChanged;
+
+ masterContainer.ChildView = Element.Master;
+ if (Element.Master != null)
+ Element.Master.PropertyChanged += HandleMasterPropertyChanged;
+ }
+
+ void UpdateSplitViewLayout()
+ {
+ if (Device.Idiom == TargetIdiom.Tablet)
+ {
+ bool isShowingSplit = Element.ShouldShowSplitMode || (Element.ShouldShowSplitMode && Element.MasterBehavior != MasterBehavior.Default && Element.IsPresented);
+ SetLockMode(isShowingSplit ? LockModeLockedOpen : LockModeUnlocked);
+ unchecked
+ {
+ SetScrimColor(isShowingSplit ? Color.Transparent.ToAndroid() : (int)DefaultScrimColor);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs b/Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs
new file mode 100644
index 00000000..fd4cb72b
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs
@@ -0,0 +1,789 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading.Tasks;
+using Android.Animation;
+using Android.App;
+using Android.Content;
+using Android.Content.Res;
+using Android.Graphics;
+using Android.Graphics.Drawables;
+using Android.OS;
+using Android.Runtime;
+using Android.Support.V4.Widget;
+using Android.Support.V7.Graphics.Drawable;
+using Android.Util;
+using Android.Views;
+using ActionBarDrawerToggle = Android.Support.V7.App.ActionBarDrawerToggle;
+using AView = Android.Views.View;
+using AToolbar = Android.Support.V7.Widget.Toolbar;
+using Fragment = Android.Support.V4.App.Fragment;
+using FragmentManager = Android.Support.V4.App.FragmentManager;
+using FragmentTransaction = Android.Support.V4.App.FragmentTransaction;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ public class NavigationPageRenderer : VisualElementRenderer<NavigationPage>, IManageFragments
+ {
+ #region Statics
+
+ // All statics need to be made non-static/bound to platform
+
+ static ViewPropertyAnimator s_currentAnimation;
+
+ #endregion
+
+ readonly List<Fragment> _fragmentStack = new List<Fragment>();
+
+ Drawable _backgroundDrawable;
+ Page _current;
+
+ bool _disposed;
+ ActionBarDrawerToggle _drawerToggle;
+ FragmentManager _fragmentManager;
+ int _lastActionBarHeight = -1;
+ AToolbar _toolbar;
+ ToolbarTracker _toolbarTracker;
+ bool _toolbarVisible;
+
+ public NavigationPageRenderer()
+ {
+ AutoPackage = false;
+ Id = FormsAppCompatActivity.GetUniqueId();
+ Device.Info.PropertyChanged += DeviceInfoPropertyChanged;
+ }
+
+ internal int ContainerPadding { get; set; }
+
+ Page Current
+ {
+ get { return _current; }
+ set
+ {
+ if (_current == value)
+ return;
+
+ if (_current != null)
+ _current.PropertyChanged -= CurrentOnPropertyChanged;
+
+ _current = value;
+
+ if (_current != null)
+ {
+ _current.PropertyChanged += CurrentOnPropertyChanged;
+ ToolbarVisible = NavigationPage.GetHasNavigationBar(_current);
+ }
+ }
+ }
+
+ FragmentManager FragmentManager => _fragmentManager ?? (_fragmentManager = ((FormsAppCompatActivity)Context).SupportFragmentManager);
+
+ bool ToolbarVisible
+ {
+ get { return _toolbarVisible; }
+ set
+ {
+ if (_toolbarVisible == value)
+ return;
+ _toolbarVisible = value;
+ RequestLayout();
+ }
+ }
+
+ public void SetFragmentManager(FragmentManager childFragmentManager)
+ {
+ if (_fragmentManager == null)
+ _fragmentManager = childFragmentManager;
+ }
+
+ public Task<bool> PopToRootAsync(Page page, bool animated = true)
+ {
+ return OnPopToRootAsync(page, animated);
+ }
+
+ public Task<bool> PopViewAsync(Page page, bool animated = true)
+ {
+ return OnPopViewAsync(page, animated);
+ }
+
+ public Task<bool> PushViewAsync(Page page, bool animated = true)
+ {
+ return OnPushAsync(page, animated);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ _disposed = true;
+
+ var activity = (FormsAppCompatActivity)Context;
+
+ // API only exists on newer android YAY
+ if ((int)Build.VERSION.SdkInt >= 17)
+ {
+ if (!activity.IsDestroyed)
+ {
+ FragmentManager fm = FragmentManager;
+ FragmentTransaction trans = fm.BeginTransaction();
+ foreach (Fragment fragment in _fragmentStack)
+ trans.Remove(fragment);
+ trans.CommitAllowingStateLoss();
+ fm.ExecutePendingTransactions();
+ }
+ }
+
+ if (Element != null)
+ {
+ for (var i = 0; i < Element.InternalChildren.Count; i++)
+ {
+ var child = Element.InternalChildren[i] as VisualElement;
+ if (child == null)
+ continue;
+ IVisualElementRenderer renderer = Android.Platform.GetRenderer(child);
+ renderer?.Dispose();
+ }
+ Element.PushRequested -= OnPushed;
+ Element.PopRequested -= OnPopped;
+ Element.PopToRootRequested -= OnPoppedToRoot;
+ Element.InsertPageBeforeRequested -= OnInsertPageBeforeRequested;
+ Element.RemovePageRequested -= OnRemovePageRequested;
+ Element.SendDisappearing();
+ }
+
+ if (_toolbarTracker != null)
+ {
+ _toolbarTracker.CollectionChanged -= ToolbarTrackerOnCollectionChanged;
+ _toolbarTracker.Target = null;
+ _toolbarTracker = null;
+ }
+
+ if (_toolbar != null)
+ {
+ _toolbar.NavigationClick -= BarOnNavigationClick;
+ _toolbar.Dispose();
+ _toolbar = null;
+ }
+
+ Current = null;
+
+ Device.Info.PropertyChanged -= DeviceInfoPropertyChanged;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnAttachedToWindow()
+ {
+ base.OnAttachedToWindow();
+ Element.SendAppearing();
+ _fragmentStack.Last().UserVisibleHint = true;
+ RegisterToolbar();
+ UpdateToolbar();
+ }
+
+ protected override void OnDetachedFromWindow()
+ {
+ base.OnDetachedFromWindow();
+ Element.SendDisappearing();
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<NavigationPage> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ {
+ e.OldElement.PushRequested -= OnPushed;
+ e.OldElement.PopRequested -= OnPopped;
+ e.OldElement.PopToRootRequested -= OnPoppedToRoot;
+ e.OldElement.InsertPageBeforeRequested -= OnInsertPageBeforeRequested;
+ e.OldElement.RemovePageRequested -= OnRemovePageRequested;
+
+ RemoveAllViews();
+ if (_toolbar != null)
+ AddView(_toolbar);
+ }
+
+ if (e.NewElement != null)
+ {
+ if (_toolbarTracker == null)
+ {
+ SetupToolbar();
+ _toolbarTracker = new ToolbarTracker();
+ _toolbarTracker.CollectionChanged += ToolbarTrackerOnCollectionChanged;
+ }
+
+ var parents = new List<Page>();
+ Page root = Element;
+ while (!Application.IsApplicationOrNull(root.RealParent))
+ {
+ root = (Page)root.RealParent;
+ parents.Add(root);
+ }
+
+ _toolbarTracker.Target = e.NewElement;
+ _toolbarTracker.AdditionalTargets = parents;
+ UpdateMenu();
+
+ e.NewElement.PushRequested += OnPushed;
+ e.NewElement.PopRequested += OnPopped;
+ e.NewElement.PopToRootRequested += OnPoppedToRoot;
+ e.NewElement.InsertPageBeforeRequested += OnInsertPageBeforeRequested;
+ e.NewElement.RemovePageRequested += OnRemovePageRequested;
+
+ // If there is already stuff on the stack we need to push it
+ e.NewElement.StackCopy.Reverse().ForEach(p => PushViewAsync(p, false));
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == NavigationPage.BarBackgroundColorProperty.PropertyName)
+ UpdateToolbar();
+ else if (e.PropertyName == NavigationPage.BarTextColorProperty.PropertyName)
+ UpdateToolbar();
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ AToolbar bar = _toolbar;
+ // make sure bar stays on top of everything
+ bar.BringToFront();
+
+ base.OnLayout(changed, l, t, r, b);
+
+ int barHeight = ActionBarHeight();
+
+ if (barHeight != _lastActionBarHeight && _lastActionBarHeight > 0)
+ {
+ ResetToolbar();
+ bar = _toolbar;
+ }
+ _lastActionBarHeight = barHeight;
+
+ bar.Measure(MeasureSpecFactory.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(barHeight, MeasureSpecMode.Exactly));
+
+ int internalHeight = b - t - barHeight;
+ int containerHeight = ToolbarVisible ? internalHeight : b - t;
+ containerHeight -= ContainerPadding;
+
+ Element.ContainerArea = new Rectangle(0, 0, Context.FromPixels(r - l), Context.FromPixels(containerHeight));
+ // Potential for optimization here, the exact conditions by which you don't need to do this are complex
+ // and the cost of doing when it's not needed is moderate to low since the layout will short circuit pretty fast
+ Element.ForceLayout();
+
+ for (var i = 0; i < ChildCount; i++)
+ {
+ AView child = GetChildAt(i);
+ bool isBar = JNIEnv.IsSameObject(child.Handle, bar.Handle);
+
+ if (ToolbarVisible)
+ {
+ if (isBar)
+ bar.Layout(0, 0, r - l, barHeight);
+ else
+ child.Layout(0, barHeight + ContainerPadding, r, b);
+ }
+ else
+ {
+ if (isBar)
+ bar.Layout(0, -1000, r, barHeight - 1000);
+ else
+ child.Layout(0, ContainerPadding, r, b);
+ }
+ }
+ }
+
+ protected virtual void SetupPageTransition(FragmentTransaction transaction, bool isPush)
+ {
+ if (isPush)
+ transaction.SetTransition((int)FragmentTransit.FragmentOpen);
+ else
+ transaction.SetTransition((int)FragmentTransit.FragmentClose);
+ }
+
+ internal int GetNavBarHeight()
+ {
+ if (!ToolbarVisible)
+ return 0;
+
+ return ActionBarHeight();
+ }
+
+ int ActionBarHeight()
+ {
+ int attr = Resource.Attribute.actionBarSize;
+
+ int actionBarHeight;
+ using(var tv = new TypedValue())
+ {
+ actionBarHeight = 0;
+ if (Context.Theme.ResolveAttribute(attr, tv, true))
+ actionBarHeight = TypedValue.ComplexToDimensionPixelSize(tv.Data, Resources.DisplayMetrics);
+ }
+
+ if (actionBarHeight <= 0)
+ return Device.Info.CurrentOrientation.IsPortrait() ? (int)Context.ToPixels(56) : (int)Context.ToPixels(48);
+
+ return actionBarHeight;
+ }
+
+ void AnimateArrowIn()
+ {
+ var icon = _toolbar.NavigationIcon as DrawerArrowDrawable;
+ if (icon == null)
+ return;
+
+ ValueAnimator valueAnim = ValueAnimator.OfFloat(0, 1);
+ valueAnim.SetDuration(200);
+ valueAnim.Update += (s, a) => icon.Progress = (float)a.Animation.AnimatedValue;
+ valueAnim.Start();
+ }
+
+ void AnimateArrowOut()
+ {
+ var icon = _toolbar.NavigationIcon as DrawerArrowDrawable;
+ if (icon == null)
+ return;
+
+ ValueAnimator valueAnim = ValueAnimator.OfFloat(1, 0);
+ valueAnim.SetDuration(200);
+ valueAnim.Update += (s, a) => icon.Progress = (float)a.Animation.AnimatedValue;
+ valueAnim.Start();
+ }
+
+ void BarOnNavigationClick(object sender, AToolbar.NavigationClickEventArgs navigationClickEventArgs)
+ {
+ Element?.PopAsync();
+ }
+
+ void CurrentOnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == NavigationPage.HasNavigationBarProperty.PropertyName)
+ ToolbarVisible = NavigationPage.GetHasNavigationBar(Current);
+ else if (e.PropertyName == Page.TitleProperty.PropertyName)
+ UpdateToolbar();
+ }
+
+ async void DeviceInfoPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (nameof(Device.Info.CurrentOrientation) == e.PropertyName)
+ ResetToolbar();
+ }
+
+ void FilterPageFragment(Page page)
+ {
+ _fragmentStack.RemoveAll(f => ((FragmentContainer)f).Page == page);
+ }
+
+ void HandleToolbarItemPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == MenuItem.IsEnabledProperty.PropertyName || e.PropertyName == MenuItem.TextProperty.PropertyName || e.PropertyName == MenuItem.IconProperty.PropertyName)
+ UpdateMenu();
+ }
+
+ void InsertPageBefore(Page page, Page before)
+ {
+ UpdateToolbar();
+
+ int index = Element.InternalChildren.IndexOf(before);
+ if (index == -1)
+ throw new InvalidOperationException("This should never happen, please file a bug");
+
+ Fragment fragment = FragmentContainer.CreateInstance(page);
+ _fragmentStack.Insert(index, fragment);
+ }
+
+ void OnInsertPageBeforeRequested(object sender, NavigationRequestedEventArgs e)
+ {
+ InsertPageBefore(e.Page, e.BeforePage);
+ }
+
+ void OnPopped(object sender, NavigationRequestedEventArgs e)
+ {
+ e.Task = PopViewAsync(e.Page, e.Animated);
+ }
+
+ void OnPoppedToRoot(object sender, NavigationRequestedEventArgs e)
+ {
+ e.Task = PopToRootAsync(e.Page, e.Animated);
+ }
+
+ Task<bool> OnPopToRootAsync(Page page, bool animated)
+ {
+ return SwitchContentAsync(page, animated, true, true);
+ }
+
+ Task<bool> OnPopViewAsync(Page page, bool animated)
+ {
+ Page pageToShow = Element.StackCopy.Skip(1).FirstOrDefault();
+ if (pageToShow == null)
+ return Task.FromResult(false);
+
+ return SwitchContentAsync(pageToShow, animated, true);
+ }
+
+ Task<bool> OnPushAsync(Page view, bool animated)
+ {
+ return SwitchContentAsync(view, animated);
+ }
+
+ void OnPushed(object sender, NavigationRequestedEventArgs e)
+ {
+ e.Task = PushViewAsync(e.Page, e.Animated);
+ }
+
+ void OnRemovePageRequested(object sender, NavigationRequestedEventArgs e)
+ {
+ RemovePage(e.Page);
+ }
+
+ void RegisterToolbar()
+ {
+ Context context = Context;
+ AToolbar bar = _toolbar;
+ Element page = Element.RealParent;
+
+ MasterDetailPage masterDetailPage = null;
+ while (page != null)
+ {
+ if (page is MasterDetailPage)
+ {
+ masterDetailPage = page as MasterDetailPage;
+ break;
+ }
+ page = page.RealParent;
+ }
+
+ if (masterDetailPage == null)
+ {
+ masterDetailPage = Element.InternalChildren[0] as MasterDetailPage;
+ if (masterDetailPage == null)
+ return;
+ }
+
+ if (masterDetailPage.ShouldShowSplitMode)
+ return;
+
+ var renderer = Android.Platform.GetRenderer(masterDetailPage) as MasterDetailPageRenderer;
+ if (renderer == null)
+ return;
+
+ var drawerLayout = (DrawerLayout)renderer;
+ _drawerToggle = new ActionBarDrawerToggle((Activity)context, drawerLayout, bar, global::Android.Resource.String.Ok, global::Android.Resource.String.Ok)
+ {
+ ToolbarNavigationClickListener = new ClickListener(Element)
+ };
+
+ drawerLayout.SetDrawerListener(new DrawerMultiplexedListener { Listeners = { _drawerToggle, renderer } });
+ _drawerToggle.DrawerIndicatorEnabled = true;
+ }
+
+ void RemovePage(Page page)
+ {
+ IVisualElementRenderer rendererToRemove = Android.Platform.GetRenderer(page);
+ var containerToRemove = (PageContainer)rendererToRemove?.ViewGroup.Parent;
+
+ // Also remove this page from the fragmentStack
+ FilterPageFragment(page);
+
+ containerToRemove.RemoveFromParent();
+ if (rendererToRemove != null)
+ {
+ rendererToRemove.ViewGroup.RemoveFromParent();
+ rendererToRemove.Dispose();
+ }
+ containerToRemove?.Dispose();
+
+ Device.StartTimer(TimeSpan.FromMilliseconds(10), () =>
+ {
+ UpdateToolbar();
+ return false;
+ });
+ }
+
+ void ResetToolbar()
+ {
+ _toolbar.RemoveFromParent();
+ _toolbar.NavigationClick -= BarOnNavigationClick;
+ _toolbar = null;
+
+ SetupToolbar();
+ RegisterToolbar();
+ UpdateToolbar();
+ UpdateMenu();
+ }
+
+ void SetupToolbar()
+ {
+ Context context = Context;
+ var activity = (FormsAppCompatActivity)context;
+
+ AToolbar bar;
+ if (FormsAppCompatActivity.ToolbarResource != 0)
+ bar = activity.LayoutInflater.Inflate(FormsAppCompatActivity.ToolbarResource, null).JavaCast<AToolbar>();
+ else
+ bar = new AToolbar(context);
+
+ bar.NavigationClick += BarOnNavigationClick;
+
+ AddView(bar);
+ _toolbar = bar;
+ }
+
+ Task<bool> SwitchContentAsync(Page view, bool animated, bool removed = false, bool popToRoot = false)
+ {
+ var activity = (FormsAppCompatActivity)Context;
+ var tcs = new TaskCompletionSource<bool>();
+ Fragment fragment = FragmentContainer.CreateInstance(view);
+ FragmentManager fm = FragmentManager;
+ List<Fragment> fragments = _fragmentStack;
+
+ Current = view;
+
+ FragmentTransaction transaction = fm.BeginTransaction();
+
+ if (animated)
+ SetupPageTransition(transaction, !removed);
+
+ transaction.DisallowAddToBackStack();
+
+ if (fragments.Count == 0)
+ {
+ transaction.Add(Id, fragment);
+ fragments.Add(fragment);
+ }
+ else
+ {
+ if (removed)
+ {
+ // pop only one page, or pop everything to the root
+ var popPage = true;
+ while (fragments.Count > 1 && popPage)
+ {
+ Fragment currentToRemove = fragments.Last();
+ fragments.RemoveAt(fragments.Count - 1);
+ transaction.Remove(currentToRemove);
+ popPage = popToRoot;
+ }
+
+ Fragment toShow = fragments.Last();
+ // Execute pending transactions so that we can be sure the fragment list is accurate.
+ fm.ExecutePendingTransactions();
+ if (fm.Fragments.Contains(toShow))
+ transaction.Show(toShow);
+ else
+ transaction.Add(Id, toShow);
+ }
+ else
+ {
+ // push
+ Fragment currentToHide = fragments.Last();
+ transaction.Hide(currentToHide);
+ transaction.Add(Id, fragment);
+ fragments.Add(fragment);
+ }
+ }
+ transaction.Commit();
+
+ // The fragment transitions don't really SUPPORT telling you when they end
+ // There are some hacks you can do, but they actually are worse than just doing this:
+
+ if (animated)
+ {
+ if (!removed)
+ {
+ UpdateToolbar();
+ if (_drawerToggle != null && Element.StackDepth == 2)
+ AnimateArrowIn();
+ }
+ else if (_drawerToggle != null && Element.StackDepth == 2)
+ AnimateArrowOut();
+
+ Device.StartTimer(TimeSpan.FromMilliseconds(200), () =>
+ {
+ tcs.TrySetResult(true);
+ fragment.UserVisibleHint = true;
+ if (removed)
+ UpdateToolbar();
+ return false;
+ });
+ }
+ else
+ {
+ Device.StartTimer(TimeSpan.FromMilliseconds(1), () =>
+ {
+ tcs.TrySetResult(true);
+ fragment.UserVisibleHint = true;
+ UpdateToolbar();
+ return false;
+ });
+ }
+
+ // 200ms is how long the animations are, and they are "reversible" in the sense that starting another one slightly before it's done is fine
+
+ return tcs.Task;
+ }
+
+ void ToolbarTrackerOnCollectionChanged(object sender, EventArgs eventArgs)
+ {
+ UpdateMenu();
+ }
+
+ void UpdateMenu()
+ {
+ AToolbar bar = _toolbar;
+ Context context = Context;
+ IMenu menu = bar.Menu;
+
+ foreach (ToolbarItem item in _toolbarTracker.ToolbarItems)
+ item.PropertyChanged -= HandleToolbarItemPropertyChanged;
+ menu.Clear();
+
+ foreach (ToolbarItem item in _toolbarTracker.ToolbarItems)
+ {
+ item.PropertyChanged += HandleToolbarItemPropertyChanged;
+ if (item.Order == ToolbarItemOrder.Secondary)
+ {
+ IMenuItem menuItem = menu.Add(item.Text);
+ menuItem.SetEnabled(item.IsEnabled);
+ menuItem.SetOnMenuItemClickListener(new GenericMenuClickListener(item.Activate));
+ }
+ else
+ {
+ IMenuItem menuItem = menu.Add(item.Text);
+ FileImageSource icon = item.Icon;
+ if (!string.IsNullOrEmpty(icon))
+ {
+ Drawable iconBitmap = context.Resources.GetDrawable(icon);
+ if (iconBitmap != null)
+ menuItem.SetIcon(iconBitmap);
+ }
+ menuItem.SetEnabled(item.IsEnabled);
+ menuItem.SetShowAsAction(ShowAsAction.Always);
+ menuItem.SetOnMenuItemClickListener(new GenericMenuClickListener(item.Activate));
+ }
+ }
+ }
+
+ void UpdateToolbar()
+ {
+ if (_disposed)
+ return;
+
+ Context context = Context;
+ var activity = (FormsAppCompatActivity)context;
+ AToolbar bar = _toolbar;
+ ActionBarDrawerToggle toggle = _drawerToggle;
+
+ if (bar == null)
+ return;
+
+ bool isNavigated = Element.StackDepth > 1;
+ bar.NavigationIcon = null;
+
+ if (isNavigated)
+ {
+ if (toggle != null)
+ {
+ toggle.DrawerIndicatorEnabled = false;
+ toggle.SyncState();
+ }
+
+ if (NavigationPage.GetHasBackButton(Element.CurrentPage))
+ {
+ var icon = new DrawerArrowDrawable(activity.SupportActionBar.ThemedContext);
+ icon.Progress = 1;
+ bar.NavigationIcon = icon;
+ }
+ }
+ else
+ {
+ if (toggle != null)
+ {
+ toggle.DrawerIndicatorEnabled = true;
+ toggle.SyncState();
+ }
+ }
+
+ Color tintColor = Element.BarBackgroundColor;
+
+ if (Forms.IsLollipopOrNewer)
+ {
+ if (tintColor.IsDefault)
+ bar.BackgroundTintMode = null;
+ else
+ {
+ bar.BackgroundTintMode = PorterDuff.Mode.Src;
+ bar.BackgroundTintList = ColorStateList.ValueOf(tintColor.ToAndroid());
+ }
+ }
+ else
+ {
+ if (tintColor.IsDefault && _backgroundDrawable != null)
+ bar.SetBackground(_backgroundDrawable);
+ else if (!tintColor.IsDefault)
+ {
+ if (_backgroundDrawable == null)
+ _backgroundDrawable = bar.Background;
+ bar.SetBackgroundColor(tintColor.ToAndroid());
+ }
+ }
+
+ Color textColor = Element.BarTextColor;
+ if (!textColor.IsDefault)
+ bar.SetTitleTextColor(textColor.ToAndroid().ToArgb());
+
+ bar.Title = Element.CurrentPage.Title ?? "";
+ }
+
+ class ClickListener : Object, IOnClickListener
+ {
+ readonly NavigationPage _element;
+
+ public ClickListener(NavigationPage element)
+ {
+ _element = element;
+ }
+
+ public void OnClick(AView v)
+ {
+ _element?.PopAsync();
+ }
+ }
+
+ class DrawerMultiplexedListener : Object, DrawerLayout.IDrawerListener
+ {
+ public List<DrawerLayout.IDrawerListener> Listeners { get; } = new List<DrawerLayout.IDrawerListener>(2);
+
+ public void OnDrawerClosed(AView drawerView)
+ {
+ foreach (DrawerLayout.IDrawerListener listener in Listeners)
+ listener.OnDrawerClosed(drawerView);
+ }
+
+ public void OnDrawerOpened(AView drawerView)
+ {
+ foreach (DrawerLayout.IDrawerListener listener in Listeners)
+ listener.OnDrawerOpened(drawerView);
+ }
+
+ public void OnDrawerSlide(AView drawerView, float slideOffset)
+ {
+ foreach (DrawerLayout.IDrawerListener listener in Listeners)
+ listener.OnDrawerSlide(drawerView, slideOffset);
+ }
+
+ public void OnDrawerStateChanged(int newState)
+ {
+ foreach (DrawerLayout.IDrawerListener listener in Listeners)
+ listener.OnDrawerStateChanged(newState);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/PickerRenderer.cs b/Xamarin.Forms.Platform.Android/AppCompat/PickerRenderer.cs
new file mode 100644
index 00000000..d59d9f6e
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/PickerRenderer.cs
@@ -0,0 +1,141 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using Android.App;
+using Android.Text;
+using Android.Widget;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ public class PickerRenderer : ViewRenderer<Picker, EditText>
+ {
+ AlertDialog _dialog;
+ bool _disposed;
+
+ public PickerRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected override EditText CreateNativeControl()
+ {
+ return new EditText(Context);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ _disposed = true;
+
+ ((ObservableList<string>)Element.Items).CollectionChanged -= RowsCollectionChanged;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
+ {
+ if (e.OldElement != null)
+ ((ObservableList<string>)e.OldElement.Items).CollectionChanged -= RowsCollectionChanged;
+
+ if (e.NewElement != null)
+ {
+ ((ObservableList<string>)e.NewElement.Items).CollectionChanged += RowsCollectionChanged;
+ if (Control == null)
+ {
+ EditText textField = CreateNativeControl();
+ textField.Focusable = false;
+ textField.Clickable = true;
+ textField.Tag = this;
+ textField.InputType = InputTypes.Null;
+ textField.SetOnClickListener(PickerListener.Instance);
+ SetNativeControl(textField);
+ }
+ UpdatePicker();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Picker.TitleProperty.PropertyName)
+ UpdatePicker();
+ if (e.PropertyName == Picker.SelectedIndexProperty.PropertyName)
+ UpdatePicker();
+ }
+
+ internal override void OnFocusChangeRequested(object sender, VisualElement.FocusRequestArgs e)
+ {
+ base.OnFocusChangeRequested(sender, e);
+
+ if (e.Focus)
+ OnClick();
+ else if (_dialog != null)
+ {
+ _dialog.Hide();
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ Control.ClearFocus();
+ _dialog = null;
+ }
+ }
+
+ void OnClick()
+ {
+ Picker model = Element;
+ using(var builder = new AlertDialog.Builder(Context))
+ {
+ builder.SetTitle(model.Title ?? "");
+ string[] items = model.Items.ToArray();
+ builder.SetItems(items, (s, e) => ((IElementController)model).SetValueFromRenderer(Picker.SelectedIndexProperty, e.Which));
+
+ builder.SetNegativeButton(global::Android.Resource.String.Cancel, (o, args) => { });
+
+ _dialog = builder.Create();
+ }
+
+ _dialog.SetCanceledOnTouchOutside(true);
+ _dialog.DismissEvent += (sender, args) =>
+ {
+ _dialog.Dispose();
+ _dialog = null;
+ };
+
+ _dialog.Show();
+ }
+
+ void RowsCollectionChanged(object sender, EventArgs e)
+ {
+ UpdatePicker();
+ }
+
+ void UpdatePicker()
+ {
+ Control.Hint = Element.Title;
+
+ if (Element.SelectedIndex == -1 || Element.Items == null)
+ Control.Text = null;
+ else
+ Control.Text = Element.Items[Element.SelectedIndex];
+ }
+
+ class PickerListener : Object, IOnClickListener
+ {
+ #region Statics
+
+ public static readonly PickerListener Instance = new PickerListener();
+
+ #endregion
+
+ public void OnClick(global::Android.Views.View v)
+ {
+ var renderer = v.Tag as PickerRenderer;
+ renderer?.OnClick();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/Platform.cs b/Xamarin.Forms.Platform.Android/AppCompat/Platform.cs
new file mode 100644
index 00000000..12c6a02a
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/Platform.cs
@@ -0,0 +1,394 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Android.Content;
+using Android.Views;
+using Android.Views.Animations;
+using ARelativeLayout = Android.Widget.RelativeLayout;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ internal class Platform : BindableObject, IPlatform, IPlatformLayout, INavigation, IDisposable
+ {
+ readonly Context _context;
+ readonly PlatformRenderer _renderer;
+ bool _disposed;
+ bool _navAnimationInProgress;
+ NavigationModel _navModel = new NavigationModel();
+
+ public Platform(Context context)
+ {
+ _context = context;
+
+ _renderer = new PlatformRenderer(context, this);
+
+ FormsAppCompatActivity.BackPressed += HandleBackPressed;
+ }
+
+ internal bool NavAnimationInProgress
+ {
+ get { return _navAnimationInProgress; }
+ set
+ {
+ if (_navAnimationInProgress == value)
+ return;
+ _navAnimationInProgress = value;
+ if (value)
+ MessagingCenter.Send(this, CloseContextActionsSignalName);
+ }
+ }
+
+ Page Page { get; set; }
+
+ public void Dispose()
+ {
+ if (_disposed)
+ return;
+ _disposed = true;
+
+ SetPage(null);
+
+ FormsAppCompatActivity.BackPressed -= HandleBackPressed;
+ }
+
+ void INavigation.InsertPageBefore(Page page, Page before)
+ {
+ throw new InvalidOperationException("InsertPageBefore is not supported globally on Android, please use a NavigationPage.");
+ }
+
+ IReadOnlyList<Page> INavigation.ModalStack => _navModel.Modals.ToList();
+
+ IReadOnlyList<Page> INavigation.NavigationStack => new List<Page>();
+
+ Task<Page> INavigation.PopAsync()
+ {
+ return ((INavigation)this).PopAsync(true);
+ }
+
+ Task<Page> INavigation.PopAsync(bool animated)
+ {
+ throw new InvalidOperationException("PopAsync is not supported globally on Android, please use a NavigationPage.");
+ }
+
+ Task<Page> INavigation.PopModalAsync()
+ {
+ return ((INavigation)this).PopModalAsync(true);
+ }
+
+ Task<Page> INavigation.PopModalAsync(bool animated)
+ {
+ Page modal = _navModel.PopModal();
+ modal.SendDisappearing();
+ var source = new TaskCompletionSource<Page>();
+
+ IVisualElementRenderer modalRenderer = Android.Platform.GetRenderer(modal);
+ if (modalRenderer != null)
+ {
+ var modalContainer = modalRenderer.ViewGroup.Parent as ModalContainer;
+ if (animated)
+ {
+ modalContainer.Animate().TranslationY(_renderer.Height).SetInterpolator(new AccelerateInterpolator(1)).SetDuration(300).SetListener(new GenericAnimatorListener
+ {
+ OnEnd = a =>
+ {
+ modalContainer.RemoveFromParent();
+ modalContainer.Dispose();
+ source.TrySetResult(modal);
+ _navModel.CurrentPage?.SendAppearing();
+ modalContainer = null;
+ }
+ });
+ }
+ else
+ {
+ modalContainer.RemoveFromParent();
+ modalContainer.Dispose();
+ source.TrySetResult(modal);
+ _navModel.CurrentPage?.SendAppearing();
+ }
+ }
+
+ return source.Task;
+ }
+
+ Task INavigation.PopToRootAsync()
+ {
+ return ((INavigation)this).PopToRootAsync(true);
+ }
+
+ Task INavigation.PopToRootAsync(bool animated)
+ {
+ throw new InvalidOperationException("PopToRootAsync is not supported globally on Android, please use a NavigationPage.");
+ }
+
+ Task INavigation.PushAsync(Page root)
+ {
+ return ((INavigation)this).PushAsync(root, true);
+ }
+
+ Task INavigation.PushAsync(Page root, bool animated)
+ {
+ throw new InvalidOperationException("PushAsync is not supported globally on Android, please use a NavigationPage.");
+ }
+
+ Task INavigation.PushModalAsync(Page modal)
+ {
+ return ((INavigation)this).PushModalAsync(modal, true);
+ }
+
+ async Task INavigation.PushModalAsync(Page modal, bool animated)
+ {
+ _navModel.CurrentPage?.SendDisappearing();
+
+ _navModel.PushModal(modal);
+
+ modal.Platform = this;
+
+ Task presentModal = PresentModal(modal, animated);
+
+ await presentModal;
+
+ // Verify that the modal is still on the stack
+ if (_navModel.CurrentPage == modal)
+ modal.SendAppearing();
+ }
+
+ void INavigation.RemovePage(Page page)
+ {
+ throw new InvalidOperationException("RemovePage is not supported globally on Android, please use a NavigationPage.");
+ }
+
+ SizeRequest IPlatform.GetNativeSize(VisualElement view, double widthConstraint, double heightConstraint)
+ {
+ Performance.Start();
+
+ // FIXME: potential crash
+ IVisualElementRenderer viewRenderer = Android.Platform.GetRenderer(view);
+
+ // negative numbers have special meanings to android they don't to us
+ widthConstraint = widthConstraint <= -1 ? double.PositiveInfinity : _context.ToPixels(widthConstraint);
+ heightConstraint = heightConstraint <= -1 ? double.PositiveInfinity : _context.ToPixels(heightConstraint);
+
+ int width = !double.IsPositiveInfinity(widthConstraint)
+ ? MeasureSpecFactory.MakeMeasureSpec((int)widthConstraint, MeasureSpecMode.AtMost)
+ : MeasureSpecFactory.MakeMeasureSpec(0, MeasureSpecMode.Unspecified);
+
+ int height = !double.IsPositiveInfinity(heightConstraint)
+ ? MeasureSpecFactory.MakeMeasureSpec((int)heightConstraint, MeasureSpecMode.AtMost)
+ : MeasureSpecFactory.MakeMeasureSpec(0, MeasureSpecMode.Unspecified);
+
+ SizeRequest rawResult = viewRenderer.GetDesiredSize(width, height);
+ if (rawResult.Minimum == Size.Zero)
+ rawResult.Minimum = rawResult.Request;
+ var result = new SizeRequest(new Size(_context.FromPixels(rawResult.Request.Width), _context.FromPixels(rawResult.Request.Height)),
+ new Size(_context.FromPixels(rawResult.Minimum.Width), _context.FromPixels(rawResult.Minimum.Height)));
+
+ Performance.Stop();
+ return result;
+ }
+
+ void IPlatformLayout.OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ if (changed)
+ LayoutRootPage(Page, r - l, b - t);
+
+ Android.Platform.GetRenderer(Page).UpdateLayout();
+
+ for (var i = 0; i < _renderer.ChildCount; i++)
+ {
+ global::Android.Views.View child = _renderer.GetChildAt(i);
+ if (child is ModalContainer)
+ {
+ child.Measure(MeasureSpecFactory.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(t - b, MeasureSpecMode.Exactly));
+ child.Layout(l, t, r, b);
+ }
+ }
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ SetInheritedBindingContext(Page, BindingContext);
+
+ base.OnBindingContextChanged();
+ }
+
+ internal void SetPage(Page newRoot)
+ {
+ var layout = false;
+ if (Page != null)
+ {
+ _renderer.RemoveAllViews();
+
+ foreach (IVisualElementRenderer rootRenderer in _navModel.Roots.Select(Android.Platform.GetRenderer))
+ rootRenderer.Dispose();
+ _navModel = new NavigationModel();
+
+ layout = true;
+ }
+
+ if (newRoot == null)
+ return;
+
+ _navModel.Push(newRoot, null);
+
+ Page = newRoot;
+ Page.Platform = this;
+ AddChild(Page, layout);
+
+ ((Application)Page.RealParent).NavigationProxy.Inner = this;
+ }
+
+ void AddChild(Page page, bool layout = false)
+ {
+ if (Android.Platform.GetRenderer(page) != null)
+ return;
+
+ Android.Platform.SetPageContext(page, _context);
+ IVisualElementRenderer renderView = RendererFactory.GetRenderer(page);
+ Android.Platform.SetRenderer(page, renderView);
+
+ if (layout)
+ LayoutRootPage(page, _renderer.Width, _renderer.Height);
+
+ _renderer.AddView(renderView.ViewGroup);
+ }
+
+ bool HandleBackPressed(object sender, EventArgs e)
+ {
+ if (NavAnimationInProgress)
+ return true;
+
+ Page root = _navModel.Roots.Last();
+ bool handled = root.SendBackButtonPressed();
+
+ return handled;
+ }
+
+ void LayoutRootPage(Page page, int width, int height)
+ {
+ var activity = (FormsAppCompatActivity)_context;
+ int statusBarHeight = Forms.IsLollipopOrNewer ? activity.GetStatusBarHeight() : 0;
+
+ if (page is MasterDetailPage)
+ page.Layout(new Rectangle(0, 0, _context.FromPixels(width), _context.FromPixels(height)));
+ else
+ {
+ page.Layout(new Rectangle(0, _context.FromPixels(statusBarHeight), _context.FromPixels(width), _context.FromPixels(height - statusBarHeight)));
+ }
+ }
+
+ Task PresentModal(Page modal, bool animated)
+ {
+ var modalContainer = new ModalContainer(_context, modal);
+
+ _renderer.AddView(modalContainer);
+
+ var source = new TaskCompletionSource<bool>();
+ NavAnimationInProgress = true;
+ if (animated)
+ {
+ modalContainer.TranslationY = _renderer.Height;
+ modalContainer.Animate().TranslationY(0).SetInterpolator(new DecelerateInterpolator(1)).SetDuration(300).SetListener(new GenericAnimatorListener
+ {
+ OnEnd = a =>
+ {
+ source.TrySetResult(false);
+ NavAnimationInProgress = false;
+ modalContainer = null;
+ },
+ OnCancel = a =>
+ {
+ source.TrySetResult(true);
+ NavAnimationInProgress = false;
+ modalContainer = null;
+ }
+ });
+ }
+ else
+ {
+ NavAnimationInProgress = false;
+ source.TrySetResult(true);
+ }
+
+ return source.Task;
+ }
+
+ sealed class ModalContainer : ViewGroup
+ {
+ global::Android.Views.View _backgroundView;
+ bool _disposed;
+ Page _modal;
+ IVisualElementRenderer _renderer;
+
+ public ModalContainer(Context context, Page modal) : base(context)
+ {
+ _modal = modal;
+
+ _backgroundView = new global::Android.Views.View(context);
+ _backgroundView.SetWindowBackground();
+ AddView(_backgroundView);
+
+ Android.Platform.SetPageContext(modal, context);
+ _renderer = RendererFactory.GetRenderer(modal);
+ Android.Platform.SetRenderer(modal, _renderer);
+
+ AddView(_renderer.ViewGroup);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ _disposed = true;
+ RemoveAllViews();
+ if (_renderer != null)
+ {
+ _renderer.Dispose();
+ _renderer = null;
+ _modal.ClearValue(Android.Platform.RendererProperty);
+ _modal = null;
+ }
+
+ if (_backgroundView != null)
+ {
+ _backgroundView.Dispose();
+ _backgroundView = null;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ var activity = (FormsAppCompatActivity)Context;
+ int statusBarHeight = Forms.IsLollipopOrNewer ? activity.GetStatusBarHeight() : 0;
+ if (changed)
+ {
+ if (_modal is MasterDetailPage)
+ _modal.Layout(new Rectangle(0, 0, activity.FromPixels(r - l), activity.FromPixels(b - t)));
+ else
+ {
+ _modal.Layout(new Rectangle(0, activity.FromPixels(statusBarHeight), activity.FromPixels(r - l), activity.FromPixels(b - t - statusBarHeight)));
+ }
+
+ _backgroundView.Layout(0, statusBarHeight, r - l, b - t);
+ }
+
+ _renderer.UpdateLayout();
+ }
+ }
+
+ #region Statics
+
+ public static implicit operator ViewGroup(Platform canvas)
+ {
+ return canvas._renderer;
+ }
+
+ internal const string CloseContextActionsSignalName = "Xamarin.CloseContextActions";
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/Resource.cs b/Xamarin.Forms.Platform.Android/AppCompat/Resource.cs
new file mode 100644
index 00000000..08d3c5e4
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/Resource.cs
@@ -0,0 +1,31 @@
+using Android.Runtime;
+
+[assembly: ResourceDesigner("Xamarin.Forms.Platform.Android.Resource", IsApplication = false)]
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class Resource
+ {
+ static Resource()
+ {
+ ResourceIdManager.UpdateIdValues();
+ }
+
+ public class Attribute
+ {
+ // aapt resource value: 0x7f0100a5
+ // ReSharper disable once InconsistentNaming
+ // Android is pretty insistent about this casing
+ public static int actionBarSize = 2130772133;
+
+ static Attribute()
+ {
+ ResourceIdManager.UpdateIdValues();
+ }
+
+ Attribute()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/SwitchRenderer.cs b/Xamarin.Forms.Platform.Android/AppCompat/SwitchRenderer.cs
new file mode 100644
index 00000000..f243c634
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/SwitchRenderer.cs
@@ -0,0 +1,92 @@
+using System;
+using Android.Support.V7.Widget;
+using Android.Widget;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ public class SwitchRenderer : ViewRenderer<Switch, SwitchCompat>, CompoundButton.IOnCheckedChangeListener
+ {
+ bool _disposed;
+
+ public SwitchRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ void CompoundButton.IOnCheckedChangeListener.OnCheckedChanged(CompoundButton buttonView, bool isChecked)
+ {
+ ((IViewController)Element).SetValueFromRenderer(Switch.IsToggledProperty, isChecked);
+ }
+
+ public override SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)
+ {
+ SizeRequest sizeConstraint = base.GetDesiredSize(widthConstraint, heightConstraint);
+
+ if (sizeConstraint.Request.Width == 0)
+ {
+ int width = widthConstraint;
+ if (widthConstraint <= 0)
+ width = (int)Context.GetThemeAttributeDp(global::Android.Resource.Attribute.SwitchMinWidth);
+ else if (widthConstraint <= 0)
+ width = 100;
+
+ sizeConstraint = new SizeRequest(new Size(width, sizeConstraint.Request.Height), new Size(width, sizeConstraint.Minimum.Height));
+ }
+
+ return sizeConstraint;
+ }
+
+ protected override SwitchCompat CreateNativeControl()
+ {
+ return new SwitchCompat(Context);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ _disposed = true;
+
+ if (Element != null)
+ Element.Toggled -= HandleToggled;
+
+ Control.SetOnCheckedChangeListener(null);
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Switch> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ e.OldElement.Toggled -= HandleToggled;
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SwitchCompat aswitch = CreateNativeControl();
+ aswitch.SetOnCheckedChangeListener(this);
+ SetNativeControl(aswitch);
+ }
+ else
+ UpdateEnabled(); // Normally set by SetNativeControl, but not when the Control is reused.
+
+ e.NewElement.Toggled += HandleToggled;
+ Control.Checked = e.NewElement.IsToggled;
+ }
+ }
+
+ void HandleToggled(object sender, EventArgs e)
+ {
+ Control.Checked = Element.IsToggled;
+ }
+
+ void UpdateEnabled()
+ {
+ Control.Enabled = Element.IsEnabled;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/TabbedPageRenderer.cs b/Xamarin.Forms.Platform.Android/AppCompat/TabbedPageRenderer.cs
new file mode 100644
index 00000000..f978028b
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/TabbedPageRenderer.cs
@@ -0,0 +1,322 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using Android.Content;
+using Android.OS;
+using Android.Runtime;
+using Android.Support.Design.Widget;
+using Android.Support.V4.App;
+using Android.Support.V4.View;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ public class TabbedPageRenderer : VisualElementRenderer<TabbedPage>, TabLayout.IOnTabSelectedListener, ViewPager.IOnPageChangeListener, IManageFragments
+ {
+ bool _disposed;
+ FragmentManager _fragmentManager;
+ TabLayout _tabLayout;
+ bool _useAnimations = true;
+ FormsViewPager _viewPager;
+
+ public TabbedPageRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ public FragmentManager FragmentManager => _fragmentManager ?? (_fragmentManager = ((FormsAppCompatActivity)Context).SupportFragmentManager);
+
+ internal bool UseAnimations
+ {
+ get { return _useAnimations; }
+ set
+ {
+ FormsViewPager pager = _viewPager;
+
+ _useAnimations = value;
+ if (pager != null)
+ pager.EnableGesture = value;
+ }
+ }
+
+ public void SetFragmentManager(FragmentManager childFragmentManager)
+ {
+ if (_fragmentManager == null)
+ _fragmentManager = childFragmentManager;
+ }
+
+ void ViewPager.IOnPageChangeListener.OnPageScrolled(int position, float positionOffset, int positionOffsetPixels)
+ {
+ UpdateTabBarTranslation(position, positionOffset);
+ }
+
+ void ViewPager.IOnPageChangeListener.OnPageScrollStateChanged(int state)
+ {
+ }
+
+ void ViewPager.IOnPageChangeListener.OnPageSelected(int position)
+ {
+ Element.CurrentPage = Element.Children[position];
+ }
+
+ void TabLayout.IOnTabSelectedListener.OnTabReselected(TabLayout.Tab tab)
+ {
+ }
+
+ void TabLayout.IOnTabSelectedListener.OnTabSelected(TabLayout.Tab tab)
+ {
+ if (Element == null)
+ return;
+
+ int selectedIndex = tab.Position;
+ if (Element.Children.Count > selectedIndex && selectedIndex >= 0)
+ Element.CurrentPage = Element.Children[selectedIndex];
+ }
+
+ void TabLayout.IOnTabSelectedListener.OnTabUnselected(TabLayout.Tab tab)
+ {
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ _disposed = true;
+ RemoveAllViews();
+ foreach (Page pageToRemove in Element.Children)
+ {
+ IVisualElementRenderer pageRenderer = Android.Platform.GetRenderer(pageToRemove);
+ if (pageRenderer != null)
+ {
+ pageRenderer.ViewGroup.RemoveFromParent();
+ pageRenderer.Dispose();
+ }
+ pageToRemove.ClearValue(Android.Platform.RendererProperty);
+ }
+
+ if (_viewPager != null)
+ {
+ _viewPager.Adapter.Dispose();
+ _viewPager.Dispose();
+ _viewPager = null;
+ }
+
+ if (_tabLayout != null)
+ {
+ _tabLayout.SetOnTabSelectedListener(null);
+ _tabLayout.Dispose();
+ _tabLayout = null;
+ }
+
+ if (Element != null)
+ Element.InternalChildren.CollectionChanged -= OnChildrenCollectionChanged;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnAttachedToWindow()
+ {
+ base.OnAttachedToWindow();
+ Element.SendAppearing();
+ }
+
+ protected override void OnDetachedFromWindow()
+ {
+ base.OnDetachedFromWindow();
+ Element.SendDisappearing();
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
+ {
+ base.OnElementChanged(e);
+
+ var activity = (FormsAppCompatActivity)Context;
+
+ if (e.OldElement != null)
+ e.OldElement.InternalChildren.CollectionChanged -= OnChildrenCollectionChanged;
+
+ if (e.NewElement != null)
+ {
+ if (_tabLayout == null)
+ {
+ TabLayout tabs;
+ if (FormsAppCompatActivity.TabLayoutResource > 0)
+ {
+ tabs = _tabLayout = activity.LayoutInflater.Inflate(FormsAppCompatActivity.TabLayoutResource, null).JavaCast<TabLayout>();
+ }
+ else
+ tabs = _tabLayout = new TabLayout(activity) { TabMode = TabLayout.ModeFixed, TabGravity = TabLayout.GravityFill };
+ FormsViewPager pager =
+ _viewPager =
+ new FormsViewPager(activity)
+ {
+ OverScrollMode = OverScrollMode.Never,
+ EnableGesture = UseAnimations,
+ LayoutParameters = new LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent),
+ Adapter = new FormsFragmentPagerAdapter<Page>(e.NewElement, FragmentManager) { CountOverride = e.NewElement.Children.Count }
+ };
+ pager.Id = FormsAppCompatActivity.GetUniqueId();
+ pager.AddOnPageChangeListener(this);
+
+ tabs.SetupWithViewPager(pager);
+ UpdateTabIcons();
+ tabs.SetOnTabSelectedListener(this);
+
+ AddView(pager);
+ AddView(tabs);
+ }
+
+ TabbedPage tabbedPage = e.NewElement;
+ if (tabbedPage.CurrentPage != null)
+ ScrollToCurrentPage();
+
+ UpdateIgnoreContainerAreas();
+ tabbedPage.InternalChildren.CollectionChanged += OnChildrenCollectionChanged;
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == "CurrentPage")
+ ScrollToCurrentPage();
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ TabLayout tabs = _tabLayout;
+ FormsViewPager pager = _viewPager;
+ Context context = Context;
+ int width = r - l;
+ int height = b - t;
+
+ tabs.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost));
+ var tabsHeight = 0;
+
+ //MinimumHeight is only available on API 16+
+ if ((int)Build.VERSION.SdkInt >= 16)
+ tabsHeight = Math.Min(height, Math.Max(tabs.MeasuredHeight, tabs.MinimumHeight));
+ else
+ tabsHeight = Math.Min(height, tabs.MeasuredHeight);
+
+ pager.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.AtMost), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost));
+
+ if (width > 0 && height > 0)
+ {
+ Element.ContainerArea = new Rectangle(0, context.FromPixels(tabsHeight), context.FromPixels(width), context.FromPixels(height - tabsHeight));
+
+ for (var i = 0; i < Element.InternalChildren.Count; i++)
+ {
+ var child = Element.InternalChildren[i] as VisualElement;
+ if (child == null)
+ continue;
+ IVisualElementRenderer renderer = Android.Platform.GetRenderer(child);
+ var navigationRenderer = renderer as NavigationPageRenderer;
+ if (navigationRenderer != null)
+ navigationRenderer.ContainerPadding = tabsHeight;
+ }
+
+ pager.Layout(0, 0, width, b);
+ // We need to measure again to ensure that the tabs show up
+ tabs.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(tabsHeight, MeasureSpecMode.Exactly));
+ tabs.Layout(0, 0, width, tabsHeight);
+
+ UpdateTabBarTranslation(pager.CurrentItem, 0);
+ }
+
+ base.OnLayout(changed, l, t, r, b);
+ }
+
+ void OnChildrenCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ FormsViewPager pager = _viewPager;
+ TabLayout tabs = _tabLayout;
+
+ ((FormsFragmentPagerAdapter<Page>)pager.Adapter).CountOverride = Element.Children.Count;
+ pager.Adapter.NotifyDataSetChanged();
+
+ if (Element.Children.Count == 0)
+ tabs.RemoveAllTabs();
+ else
+ {
+ tabs.SetupWithViewPager(pager);
+ UpdateTabIcons();
+ tabs.SetOnTabSelectedListener(this);
+ }
+
+ UpdateIgnoreContainerAreas();
+ }
+
+ void ScrollToCurrentPage()
+ {
+ _viewPager.SetCurrentItem(Element.Children.IndexOf(Element.CurrentPage), UseAnimations);
+ }
+
+ void UpdateIgnoreContainerAreas()
+ {
+ foreach (Page child in Element.Children)
+ child.IgnoresContainerArea = child is NavigationPage;
+ }
+
+ void UpdateTabBarTranslation(int position, float offset)
+ {
+ TabLayout tabs = _tabLayout;
+
+ if (position >= Element.InternalChildren.Count)
+ return;
+
+ var leftPage = (Page)Element.InternalChildren[position];
+ IVisualElementRenderer leftRenderer = Android.Platform.GetRenderer(leftPage);
+
+ if (leftRenderer == null)
+ return;
+
+ if (offset <= 0 || position >= Element.InternalChildren.Count - 1)
+ {
+ var leftNavRenderer = leftRenderer as NavigationPageRenderer;
+ if (leftNavRenderer != null)
+ tabs.TranslationY = leftNavRenderer.GetNavBarHeight();
+ else
+ tabs.TranslationY = 0;
+ }
+ else
+ {
+ var rightPage = (Page)Element.InternalChildren[position + 1];
+ IVisualElementRenderer rightRenderer = Android.Platform.GetRenderer(rightPage);
+
+ var leftHeight = 0;
+ var leftNavRenderer = leftRenderer as NavigationPageRenderer;
+ if (leftNavRenderer != null)
+ leftHeight = leftNavRenderer.GetNavBarHeight();
+
+ var rightHeight = 0;
+ var rightNavRenderer = rightRenderer as NavigationPageRenderer;
+ if (rightNavRenderer != null)
+ rightHeight = rightNavRenderer.GetNavBarHeight();
+
+ tabs.TranslationY = leftHeight + (rightHeight - leftHeight) * offset;
+ }
+ }
+
+ void UpdateTabIcons()
+ {
+ TabLayout tabs = _tabLayout;
+
+ if (tabs.TabCount != Element.Children.Count)
+ return;
+
+ for (var i = 0; i < Element.Children.Count; i++)
+ {
+ Page child = Element.Children[i];
+ FileImageSource icon = child.Icon;
+ if (string.IsNullOrEmpty(icon))
+ continue;
+
+ TabLayout.Tab tab = tabs.GetTabAt(i);
+ tab.SetIcon(ResourceManager.IdFromTitle(icon, ResourceManager.DrawableClass));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/ViewRenderer.cs b/Xamarin.Forms.Platform.Android/AppCompat/ViewRenderer.cs
new file mode 100644
index 00000000..3c869216
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/ViewRenderer.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ public abstract class ViewRenderer<TView, TControl> : Android.ViewRenderer<TView, TControl> where TView : View where TControl : global::Android.Views.View
+ {
+ protected abstract TControl CreateNativeControl();
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/CellAdapter.cs b/Xamarin.Forms.Platform.Android/CellAdapter.cs
new file mode 100644
index 00000000..9f439157
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/CellAdapter.cs
@@ -0,0 +1,327 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using Android.App;
+using Android.Content;
+using Android.Util;
+using Android.Views;
+using Android.Widget;
+using AView = Android.Views.View;
+using AListView = Android.Widget.ListView;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public abstract class CellAdapter : BaseAdapter<object>, AdapterView.IOnItemLongClickListener, ActionMode.ICallback, AdapterView.IOnItemClickListener,
+ global::Android.Support.V7.View.ActionMode.ICallback
+ {
+ readonly Context _context;
+ ActionMode _actionMode;
+ Cell _actionModeContext;
+
+ bool _actionModeNeedsUpdates;
+ AView _contextView;
+ global::Android.Support.V7.View.ActionMode _supportActionMode;
+
+ protected CellAdapter(Context context)
+ {
+ if (context == null)
+ throw new ArgumentNullException("context");
+
+ _context = context;
+ }
+
+ internal Cell ActionModeContext
+ {
+ get { return _actionModeContext; }
+ set
+ {
+ if (_actionModeContext == value)
+ return;
+
+ if (_actionModeContext != null)
+ ((INotifyCollectionChanged)_actionModeContext.ContextActions).CollectionChanged -= OnContextItemsChanged;
+
+ ActionModeObject = null;
+ _actionModeContext = value;
+
+ if (_actionModeContext != null)
+ {
+ ((INotifyCollectionChanged)_actionModeContext.ContextActions).CollectionChanged += OnContextItemsChanged;
+ ActionModeObject = _actionModeContext.BindingContext;
+ }
+ }
+ }
+
+ internal object ActionModeObject { get; set; }
+
+ internal AView ContextView
+ {
+ get { return _contextView; }
+ set
+ {
+ if (_contextView == value)
+ return;
+
+ if (_contextView != null)
+ {
+ var isSelected = (bool)ActionModeContext.GetValue(ListViewAdapter.IsSelectedProperty);
+ if (isSelected)
+ SetSelectedBackground(_contextView);
+ else
+ UnsetSelectedBackground(_contextView);
+ }
+
+ _contextView = value;
+
+ if (_contextView != null)
+ SetSelectedBackground(_contextView, true);
+ }
+ }
+
+ public bool OnActionItemClicked(ActionMode mode, IMenuItem item)
+ {
+ OnActionItemClickedImpl(item);
+ if (mode != null && mode.Handle != IntPtr.Zero)
+ mode.Finish();
+ return true;
+ }
+
+ bool global::Android.Support.V7.View.ActionMode.ICallback.OnActionItemClicked(global::Android.Support.V7.View.ActionMode mode, IMenuItem item)
+ {
+ OnActionItemClickedImpl(item);
+ mode.Finish();
+ return true;
+ }
+
+ public bool OnCreateActionMode(ActionMode mode, IMenu menu)
+ {
+ CreateContextMenu(menu);
+ return true;
+ }
+
+ bool global::Android.Support.V7.View.ActionMode.ICallback.OnCreateActionMode(global::Android.Support.V7.View.ActionMode mode, IMenu menu)
+ {
+ CreateContextMenu(menu);
+ return true;
+ }
+
+ public void OnDestroyActionMode(ActionMode mode)
+ {
+ OnDestroyActionModeImpl();
+ _actionMode.Dispose();
+ _actionMode = null;
+ }
+
+ void global::Android.Support.V7.View.ActionMode.ICallback.OnDestroyActionMode(global::Android.Support.V7.View.ActionMode mode)
+ {
+ OnDestroyActionModeImpl();
+ _supportActionMode.Dispose();
+ _supportActionMode = null;
+ }
+
+ public bool OnPrepareActionMode(ActionMode mode, IMenu menu)
+ {
+ return OnPrepareActionModeImpl(menu);
+ }
+
+ bool global::Android.Support.V7.View.ActionMode.ICallback.OnPrepareActionMode(global::Android.Support.V7.View.ActionMode mode, IMenu menu)
+ {
+ return OnPrepareActionModeImpl(menu);
+ }
+
+ public void OnItemClick(AdapterView parent, AView view, int position, long id)
+ {
+ if (_actionMode != null || _supportActionMode != null)
+ {
+ var listView = parent as AListView;
+ if (listView != null)
+ position -= listView.HeaderViewsCount;
+ HandleContextMode(view, position);
+ }
+ else
+ HandleItemClick(parent, view, position, id);
+ }
+
+ public bool OnItemLongClick(AdapterView parent, AView view, int position, long id)
+ {
+ var listView = parent as AListView;
+ if (listView != null)
+ position -= listView.HeaderViewsCount;
+ return HandleContextMode(view, position);
+ }
+
+ protected abstract Cell GetCellForPosition(int position);
+
+ protected virtual void HandleItemClick(AdapterView parent, AView view, int position, long id)
+ {
+ }
+
+ protected void SetSelectedBackground(AView view, bool isContextTarget = false)
+ {
+ int attribute = isContextTarget ? global::Android.Resource.Attribute.ColorLongPressedHighlight : global::Android.Resource.Attribute.ColorActivatedHighlight;
+ using(var value = new TypedValue())
+ {
+ if (_context.Theme.ResolveAttribute(attribute, value, true))
+ view.SetBackgroundResource(value.ResourceId);
+ else
+ view.SetBackgroundResource(global::Android.Resource.Color.HoloBlueDark);
+ }
+ }
+
+ protected void UnsetSelectedBackground(AView view)
+ {
+ view.SetBackgroundResource(0);
+ }
+
+ internal void CloseContextAction()
+ {
+ if (_actionMode != null)
+ _actionMode.Finish();
+ if (_supportActionMode != null)
+ _supportActionMode.Finish();
+ }
+
+ void CreateContextMenu(IMenu menu)
+ {
+ var changed = new PropertyChangedEventHandler(OnContextActionPropertyChanged);
+ var changing = new PropertyChangingEventHandler(OnContextActionPropertyChanging);
+ var commandChanged = new EventHandler(OnContextActionCommandCanExecuteChanged);
+
+ for (var i = 0; i < ActionModeContext.ContextActions.Count; i++)
+ {
+ MenuItem action = ActionModeContext.ContextActions[i];
+
+ IMenuItem item = menu.Add(Menu.None, i, Menu.None, action.Text);
+
+ if (action.Icon != null)
+ item.SetIcon(_context.Resources.GetDrawable(action.Icon));
+
+ action.PropertyChanged += changed;
+ action.PropertyChanging += changing;
+
+ if (action.Command != null)
+ action.Command.CanExecuteChanged += commandChanged;
+
+ if (!action.IsEnabled)
+ item.SetEnabled(false);
+ }
+ }
+
+ bool HandleContextMode(AView view, int position)
+ {
+ Cell cell = GetCellForPosition(position);
+
+ if (_actionMode != null || _supportActionMode != null)
+ {
+ if (!cell.HasContextActions)
+ {
+ _actionMode?.Finish();
+ _supportActionMode?.Finish();
+ return false;
+ }
+
+ ActionModeContext = cell;
+
+ _actionMode?.Invalidate();
+ _supportActionMode?.Invalidate();
+ }
+ else
+ {
+ if (!cell.HasContextActions)
+ return false;
+
+ ActionModeContext = cell;
+
+ var appCompatActivity = Forms.Context as FormsAppCompatActivity;
+ if (appCompatActivity == null)
+ _actionMode = ((Activity)Forms.Context).StartActionMode(this);
+ else
+ _supportActionMode = appCompatActivity.StartSupportActionMode(this);
+ }
+
+ ContextView = view;
+
+ return true;
+ }
+
+ void OnActionItemClickedImpl(IMenuItem item)
+ {
+ int index = item.ItemId;
+ MenuItem action = ActionModeContext.ContextActions[index];
+
+ action.Activate();
+ }
+
+ void OnContextActionCommandCanExecuteChanged(object sender, EventArgs eventArgs)
+ {
+ _actionModeNeedsUpdates = true;
+ _actionMode.Invalidate();
+ }
+
+ void OnContextActionPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ var action = (MenuItem)sender;
+
+ if (e.PropertyName == MenuItem.CommandProperty.PropertyName)
+ {
+ if (action.Command != null)
+ action.Command.CanExecuteChanged += OnContextActionCommandCanExecuteChanged;
+ }
+ else
+ _actionModeNeedsUpdates = true;
+ }
+
+ void OnContextActionPropertyChanging(object sender, PropertyChangingEventArgs e)
+ {
+ var action = (MenuItem)sender;
+
+ if (e.PropertyName == MenuItem.CommandProperty.PropertyName)
+ {
+ if (action.Command != null)
+ action.Command.CanExecuteChanged -= OnContextActionCommandCanExecuteChanged;
+ }
+ }
+
+ void OnContextItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ _actionModeNeedsUpdates = true;
+ _actionMode.Invalidate();
+ }
+
+ void OnDestroyActionModeImpl()
+ {
+ var changed = new PropertyChangedEventHandler(OnContextActionPropertyChanged);
+ var changing = new PropertyChangingEventHandler(OnContextActionPropertyChanging);
+ var commandChanged = new EventHandler(OnContextActionCommandCanExecuteChanged);
+
+ ((INotifyCollectionChanged)ActionModeContext.ContextActions).CollectionChanged -= OnContextItemsChanged;
+
+ for (var i = 0; i < ActionModeContext.ContextActions.Count; i++)
+ {
+ MenuItem action = ActionModeContext.ContextActions[i];
+ action.PropertyChanged -= changed;
+ action.PropertyChanging -= changing;
+
+ if (action.Command != null)
+ action.Command.CanExecuteChanged -= commandChanged;
+ }
+ ContextView = null;
+
+ ActionModeContext = null;
+ _actionModeNeedsUpdates = false;
+ }
+
+ bool OnPrepareActionModeImpl(IMenu menu)
+ {
+ if (_actionModeNeedsUpdates)
+ {
+ _actionModeNeedsUpdates = false;
+
+ menu.Clear();
+ CreateContextMenu(menu);
+ }
+
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Cells/BaseCellView.cs b/Xamarin.Forms.Platform.Android/Cells/BaseCellView.cs
new file mode 100644
index 00000000..7855b01e
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Cells/BaseCellView.cs
@@ -0,0 +1,208 @@
+using System.IO;
+using System.Threading.Tasks;
+using Android.Content;
+using Android.Graphics;
+using Android.Text;
+using Android.Views;
+using Android.Widget;
+using AView = Android.Views.View;
+using AColor = Android.Graphics.Color;
+using AColorDraw = Android.Graphics.Drawables.ColorDrawable;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class BaseCellView : LinearLayout, INativeElementView
+ {
+ public const double DefaultMinHeight = 44;
+
+ readonly Color _androidDefaultTextColor;
+ readonly Cell _cell;
+ readonly TextView _detailText;
+ readonly ImageView _imageView;
+ readonly TextView _mainText;
+ Color _defaultDetailColor;
+ Color _defaultMainTextColor;
+ Color _detailTextColor;
+ string _detailTextText;
+ ImageSource _imageSource;
+ Color _mainTextColor;
+ string _mainTextText;
+
+ public BaseCellView(Context context, Cell cell) : base(context)
+ {
+ _cell = cell;
+ SetMinimumWidth((int)context.ToPixels(25));
+ SetMinimumHeight((int)context.ToPixels(25));
+ Orientation = Orientation.Horizontal;
+
+ var padding = (int)context.FromPixels(8);
+ SetPadding(padding, padding, padding, padding);
+
+ _imageView = new ImageView(context);
+ var imageParams = new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.FillParent)
+ {
+ Width = (int)context.ToPixels(60),
+ Height = (int)context.ToPixels(60),
+ RightMargin = 0,
+ Gravity = GravityFlags.Center
+ };
+ using(imageParams)
+ AddView(_imageView, imageParams);
+
+ var textLayout = new LinearLayout(context) { Orientation = Orientation.Vertical };
+
+ _mainText = new TextView(context);
+ _mainText.SetSingleLine(true);
+ _mainText.Ellipsize = TextUtils.TruncateAt.End;
+ _mainText.SetPadding((int)context.ToPixels(15), padding, padding, padding);
+ _mainText.SetTextAppearance(context, global::Android.Resource.Attribute.TextAppearanceListItem);
+ using(var lp = new LayoutParams(ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent))
+ textLayout.AddView(_mainText, lp);
+
+ _detailText = new TextView(context);
+ _detailText.SetSingleLine(true);
+ _detailText.Ellipsize = TextUtils.TruncateAt.End;
+ _detailText.SetPadding((int)context.ToPixels(15), padding, padding, padding);
+ _detailText.Visibility = ViewStates.Gone;
+ _detailText.SetTextAppearance(context, global::Android.Resource.Attribute.TextAppearanceListItemSmall);
+ using(var lp = new LayoutParams(ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent))
+ textLayout.AddView(_detailText, lp);
+
+ var layoutParams = new LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent) { Width = 0, Weight = 1, Gravity = GravityFlags.Center };
+
+ using(layoutParams)
+ AddView(textLayout, layoutParams);
+
+ SetMinimumHeight((int)context.ToPixels(DefaultMinHeight));
+ _androidDefaultTextColor = Color.FromUint((uint)_mainText.CurrentTextColor);
+ }
+
+ public AView AccessoryView { get; private set; }
+
+ public string DetailText
+ {
+ get { return _detailTextText; }
+ set
+ {
+ if (_detailTextText == value)
+ return;
+
+ _detailTextText = value;
+ _detailText.Text = value;
+ _detailText.Visibility = string.IsNullOrEmpty(value) ? ViewStates.Gone : ViewStates.Visible;
+ }
+ }
+
+ public string MainText
+ {
+ get { return _mainTextText; }
+ set
+ {
+ if (_mainTextText == value)
+ return;
+
+ _mainTextText = value;
+ _mainText.Text = value;
+ }
+ }
+
+ Element INativeElementView.Element
+ {
+ get { return _cell; }
+ }
+
+ public void SetAccessoryView(AView view)
+ {
+ if (AccessoryView != null)
+ RemoveView(AccessoryView);
+
+ if (view != null)
+ {
+ using(var layout = new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.FillParent))
+ AddView(view, layout);
+
+ AccessoryView = view;
+ }
+ }
+
+ public void SetDefaultMainTextColor(Color defaultColor)
+ {
+ _defaultMainTextColor = defaultColor;
+ if (_mainTextColor == Color.Default)
+ _mainText.SetTextColor(defaultColor.ToAndroid());
+ }
+
+ public void SetDetailTextColor(Color color)
+ {
+ if (_detailTextColor == color)
+ return;
+
+ if (_defaultDetailColor == Color.Default)
+ _defaultDetailColor = Color.FromUint((uint)_detailText.CurrentTextColor);
+
+ _detailTextColor = color;
+ _detailText.SetTextColor(color.ToAndroid(_defaultDetailColor));
+ }
+
+ public void SetImageSource(ImageSource source)
+ {
+ UpdateBitmap(source, _imageSource);
+ _imageSource = source;
+ }
+
+ public void SetImageVisible(bool visible)
+ {
+ _imageView.Visibility = visible ? ViewStates.Visible : ViewStates.Gone;
+ }
+
+ public void SetIsEnabled(bool isEnable)
+ {
+ _mainText.Enabled = isEnable;
+ _detailText.Enabled = isEnable;
+ }
+
+ public void SetMainTextColor(Color color)
+ {
+ Color defaultColorToSet = _defaultMainTextColor == Color.Default ? _androidDefaultTextColor : _defaultMainTextColor;
+
+ _mainTextColor = color;
+ _mainText.SetTextColor(color.ToAndroid(defaultColorToSet));
+ }
+
+ public void SetRenderHeight(double height)
+ {
+ height = Context.ToPixels(height);
+ LayoutParameters = new LayoutParams(ViewGroup.LayoutParams.MatchParent, (int)(height == -1 ? ViewGroup.LayoutParams.WrapContent : height));
+ }
+
+ async void UpdateBitmap(ImageSource source, ImageSource previousSource = null)
+ {
+ if (Equals(source, previousSource))
+ return;
+
+ _imageView.SetImageResource(global::Android.Resource.Color.Transparent);
+
+ Bitmap bitmap = null;
+
+ IImageSourceHandler handler;
+
+ if (source != null && (handler = Registrar.Registered.GetHandler<IImageSourceHandler>(source.GetType())) != null)
+ {
+ try
+ {
+ bitmap = await handler.LoadImageAsync(source, Context);
+ }
+ catch (TaskCanceledException)
+ {
+ }
+ catch (IOException e)
+ {
+ }
+ }
+
+ _imageView.SetImageBitmap(bitmap);
+ if (bitmap != null)
+ bitmap.Dispose();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Cells/CellFactory.cs b/Xamarin.Forms.Platform.Android/Cells/CellFactory.cs
new file mode 100644
index 00000000..589236c3
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Cells/CellFactory.cs
@@ -0,0 +1,41 @@
+using Android.Content;
+using Android.Views;
+using AView = Android.Views.View;
+using AListView = Android.Widget.ListView;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public static class CellFactory
+ {
+ public static AView GetCell(Cell item, AView convertView, ViewGroup parent, Context context, View view)
+ {
+ CellRenderer renderer = CellRenderer.GetRenderer(item);
+ if (renderer == null)
+ {
+ renderer = Registrar.Registered.GetHandler<CellRenderer>(item.GetType());
+ renderer.ParentView = view;
+ }
+
+ AView result = renderer.GetCell(item, convertView, parent, context);
+
+ if (view is TableView)
+ UpdateMinimumHeightFromParent(context, result, (TableView)view);
+ else if (view is ListView)
+ UpdateMinimumHeightFromParent(context, result, (ListView)view);
+
+ return result;
+ }
+
+ static void UpdateMinimumHeightFromParent(Context context, AView view, TableView table)
+ {
+ if (!table.HasUnevenRows && table.RowHeight > 0)
+ view.SetMinimumHeight((int)context.ToPixels(table.RowHeight));
+ }
+
+ static void UpdateMinimumHeightFromParent(Context context, AView view, ListView listView)
+ {
+ if (!listView.HasUnevenRows && listView.RowHeight > 0)
+ view.SetMinimumHeight((int)context.ToPixels(listView.RowHeight));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Cells/CellRenderer.cs b/Xamarin.Forms.Platform.Android/Cells/CellRenderer.cs
new file mode 100644
index 00000000..d9d4eee5
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Cells/CellRenderer.cs
@@ -0,0 +1,131 @@
+using System;
+using System.ComponentModel;
+using Android.Content;
+using Android.Views;
+using Android.Widget;
+using AView = Android.Views.View;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class CellRenderer : IRegisterable
+ {
+ static readonly PropertyChangedEventHandler PropertyChangedHandler = OnGlobalCellPropertyChanged;
+
+ static readonly BindableProperty RendererProperty = BindableProperty.CreateAttached("Renderer", typeof(CellRenderer), typeof(Cell), null);
+
+ EventHandler _onForceUpdateSizeRequested;
+
+ public View ParentView { get; set; }
+
+ protected Cell Cell { get; set; }
+
+ public AView GetCell(Cell item, AView convertView, ViewGroup parent, Context context)
+ {
+ Performance.Start();
+
+ Cell = item;
+ Cell.PropertyChanged -= PropertyChangedHandler;
+
+ SetRenderer(Cell, this);
+
+ if (convertView != null)
+ {
+ Object tag = convertView.Tag;
+ var renderHolder = tag as RendererHolder;
+ if (renderHolder != null)
+ {
+ Cell oldCell = renderHolder.Renderer.Cell;
+ oldCell.SendDisappearing();
+
+ if (Cell != oldCell)
+ SetRenderer(oldCell, null);
+ }
+ }
+
+ AView view = GetCellCore(item, convertView, parent, context);
+
+ WireUpForceUpdateSizeRequested(item, view);
+
+ var holder = view.Tag as RendererHolder;
+ if (holder == null)
+ view.Tag = new RendererHolder { Renderer = this };
+ else
+ holder.Renderer = this;
+
+ Cell.PropertyChanged += PropertyChangedHandler;
+ Cell.SendAppearing();
+
+ Performance.Stop();
+
+ return view;
+ }
+
+ protected virtual AView GetCellCore(Cell item, AView convertView, ViewGroup parent, Context context)
+ {
+ Performance.Start();
+
+ LayoutInflater inflater = LayoutInflater.FromContext(context);
+ const int type = global::Android.Resource.Layout.SimpleListItem1;
+ AView view = inflater.Inflate(type, null);
+
+ var textView = view.FindViewById<TextView>(global::Android.Resource.Id.Text1);
+ textView.Text = item.ToString();
+ textView.SetBackgroundColor(global::Android.Graphics.Color.Transparent);
+ view.SetBackgroundColor(global::Android.Graphics.Color.Black);
+
+ Performance.Stop();
+
+ return view;
+ }
+
+ protected virtual void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ }
+
+ protected void WireUpForceUpdateSizeRequested(Cell cell, AView nativeCell)
+ {
+ cell.ForceUpdateSizeRequested -= _onForceUpdateSizeRequested;
+
+ _onForceUpdateSizeRequested = delegate
+ {
+ // RenderHeight may not be changed, but that's okay, since we
+ // don't actually use the height argument in the OnMeasure override.
+ nativeCell.Measure(nativeCell.Width, (int)cell.RenderHeight);
+ nativeCell.SetMinimumHeight(nativeCell.MeasuredHeight);
+ nativeCell.SetMinimumWidth(nativeCell.MeasuredWidth);
+ };
+
+ cell.ForceUpdateSizeRequested += _onForceUpdateSizeRequested;
+ }
+
+ internal static CellRenderer GetRenderer(BindableObject cell)
+ {
+ return (CellRenderer)cell.GetValue(RendererProperty);
+ }
+
+ internal static void SetRenderer(BindableObject cell, CellRenderer renderer)
+ {
+ cell.SetValue(RendererProperty, renderer);
+ }
+
+ static void OnGlobalCellPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ var cell = (Cell)sender;
+ CellRenderer renderer = GetRenderer(cell);
+ if (renderer == null)
+ {
+ cell.PropertyChanged -= PropertyChangedHandler;
+ return;
+ }
+
+ renderer.OnCellPropertyChanged(sender, e);
+ ;
+ }
+
+ class RendererHolder : Object
+ {
+ public CellRenderer Renderer;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Cells/EntryCellEditText.cs b/Xamarin.Forms.Platform.Android/Cells/EntryCellEditText.cs
new file mode 100644
index 00000000..287804ba
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Cells/EntryCellEditText.cs
@@ -0,0 +1,45 @@
+using System;
+using Android.App;
+using Android.Content;
+using Android.Graphics;
+using Android.Views;
+using Android.Widget;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public sealed class EntryCellEditText : EditText
+ {
+ SoftInput _startingMode;
+
+ public EntryCellEditText(Context context) : base(context)
+ {
+ }
+
+ public override bool OnKeyPreIme(Keycode keyCode, KeyEvent e)
+ {
+ if (keyCode == Keycode.Back && e.Action == KeyEventActions.Down)
+ {
+ EventHandler handler = BackButtonPressed;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+ return base.OnKeyPreIme(keyCode, e);
+ }
+
+ protected override void OnFocusChanged(bool gainFocus, FocusSearchDirection direction, Rect previouslyFocusedRect)
+ {
+ Window window = ((Activity)Context).Window;
+ if (gainFocus)
+ {
+ _startingMode = window.Attributes.SoftInputMode;
+ window.SetSoftInputMode(SoftInput.AdjustPan);
+ }
+ else
+ window.SetSoftInputMode(_startingMode);
+
+ base.OnFocusChanged(gainFocus, direction, previouslyFocusedRect);
+ }
+
+ internal event EventHandler BackButtonPressed;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Cells/EntryCellRenderer.cs b/Xamarin.Forms.Platform.Android/Cells/EntryCellRenderer.cs
new file mode 100644
index 00000000..00330928
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Cells/EntryCellRenderer.cs
@@ -0,0 +1,119 @@
+using System.ComponentModel;
+using Android.Content;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class EntryCellRenderer : CellRenderer
+ {
+ EntryCellView _view;
+
+ protected override global::Android.Views.View GetCellCore(Cell item, global::Android.Views.View convertView, ViewGroup parent, Context context)
+ {
+ if ((_view = convertView as EntryCellView) == null)
+ _view = new EntryCellView(context, item);
+ else
+ {
+ _view.TextChanged = null;
+ _view.FocusChanged = null;
+ _view.EditingCompleted = null;
+ }
+
+ UpdateLabel();
+ UpdateLabelColor();
+ UpdatePlaceholder();
+ UpdateKeyboard();
+ UpdateHorizontalTextAlignment();
+ UpdateText();
+ UpdateIsEnabled();
+ UpdateHeight();
+
+ _view.TextChanged = OnTextChanged;
+ _view.EditingCompleted = OnEditingCompleted;
+
+ return _view;
+ }
+
+ protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnCellPropertyChanged(sender, e);
+
+ if (e.PropertyName == EntryCell.LabelProperty.PropertyName)
+ UpdateLabel();
+ else if (e.PropertyName == EntryCell.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == EntryCell.PlaceholderProperty.PropertyName)
+ UpdatePlaceholder();
+ else if (e.PropertyName == EntryCell.KeyboardProperty.PropertyName)
+ UpdateKeyboard();
+ else if (e.PropertyName == EntryCell.LabelColorProperty.PropertyName)
+ UpdateLabelColor();
+ else if (e.PropertyName == EntryCell.HorizontalTextAlignmentProperty.PropertyName)
+ UpdateHorizontalTextAlignment();
+ else if (e.PropertyName == Cell.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled();
+ else if (e.PropertyName == "RenderHeight")
+ UpdateHeight();
+ }
+
+ void OnEditingCompleted()
+ {
+ var entryCell = (EntryCell)Cell;
+ entryCell.SendCompleted();
+ }
+
+ void OnTextChanged(string text)
+ {
+ var entryCell = (EntryCell)Cell;
+ entryCell.Text = text;
+ }
+
+ void UpdateHeight()
+ {
+ _view.SetRenderHeight(Cell.RenderHeight);
+ }
+
+ void UpdateHorizontalTextAlignment()
+ {
+ var entryCell = (EntryCell)Cell;
+ _view.EditText.Gravity = entryCell.HorizontalTextAlignment.ToHorizontalGravityFlags();
+ }
+
+ void UpdateIsEnabled()
+ {
+ var entryCell = (EntryCell)Cell;
+ _view.EditText.Enabled = entryCell.IsEnabled;
+ }
+
+ void UpdateKeyboard()
+ {
+ var entryCell = (EntryCell)Cell;
+ _view.EditText.InputType = entryCell.Keyboard.ToInputType();
+ }
+
+ void UpdateLabel()
+ {
+ _view.LabelText = ((EntryCell)Cell).Label;
+ }
+
+ void UpdateLabelColor()
+ {
+ _view.SetLabelTextColor(((EntryCell)Cell).LabelColor, global::Android.Resource.Color.PrimaryTextDark);
+ }
+
+ void UpdatePlaceholder()
+ {
+ var entryCell = (EntryCell)Cell;
+ _view.EditText.Hint = entryCell.Placeholder;
+ }
+
+ void UpdateText()
+ {
+ var entryCell = (EntryCell)Cell;
+ if (_view.EditText.Text == entryCell.Text)
+ return;
+
+ _view.EditText.Text = entryCell.Text;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Cells/EntryCellView.cs b/Xamarin.Forms.Platform.Android/Cells/EntryCellView.cs
new file mode 100644
index 00000000..c0206f1e
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Cells/EntryCellView.cs
@@ -0,0 +1,145 @@
+using System;
+using Android.Content;
+using Android.Text;
+using Android.Views;
+using Android.Views.InputMethods;
+using Android.Widget;
+using Java.Lang;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public sealed class EntryCellView : LinearLayout, ITextWatcher, global::Android.Views.View.IOnFocusChangeListener, TextView.IOnEditorActionListener, INativeElementView
+ {
+ public const double DefaultMinHeight = 55;
+
+ readonly Cell _cell;
+ readonly TextView _label;
+
+ Color _labelTextColor;
+ string _labelTextText;
+
+ public EntryCellView(Context context, Cell cell) : base(context)
+ {
+ _cell = cell;
+ SetMinimumWidth((int)context.ToPixels(50));
+ SetMinimumHeight((int)context.ToPixels(85));
+ Orientation = Orientation.Horizontal;
+
+ var padding = (int)context.ToPixels(8);
+ SetPadding((int)context.ToPixels(15), padding, padding, padding);
+
+ _label = new TextView(context);
+ _label.SetTextAppearance(context, global::Android.Resource.Attribute.TextAppearanceListItem);
+
+ var layoutParams = new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent) { Gravity = GravityFlags.CenterVertical };
+ using(layoutParams)
+ AddView(_label, layoutParams);
+
+ EditText = new EntryCellEditText(context);
+ EditText.AddTextChangedListener(this);
+ EditText.OnFocusChangeListener = this;
+ EditText.SetOnEditorActionListener(this);
+ EditText.ImeOptions = ImeAction.Done;
+ EditText.BackButtonPressed += OnBackButtonPressed;
+ //editText.SetBackgroundDrawable (null);
+ layoutParams = new LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent) { Width = 0, Weight = 1, Gravity = GravityFlags.FillHorizontal | GravityFlags.Center };
+ using(layoutParams)
+ AddView(EditText, layoutParams);
+ }
+
+ public Action EditingCompleted { get; set; }
+
+ public EntryCellEditText EditText { get; }
+
+ public Action<bool> FocusChanged { get; set; }
+
+ public string LabelText
+ {
+ get { return _labelTextText; }
+ set
+ {
+ if (_labelTextText == value)
+ return;
+
+ _labelTextText = value;
+ _label.Text = value;
+ }
+ }
+
+ public Action<string> TextChanged { get; set; }
+
+ public Element Element
+ {
+ get { return _cell; }
+ }
+
+ bool TextView.IOnEditorActionListener.OnEditorAction(TextView v, ImeAction actionId, KeyEvent e)
+ {
+ if (actionId == ImeAction.Done)
+ {
+ OnKeyboardDoneButtonPressed(EditText, EventArgs.Empty);
+ EditText.ClearFocus();
+ v.HideKeyboard();
+ }
+
+ // Fire Completed and dismiss keyboard for hardware / physical keyboards
+ if (actionId == ImeAction.ImeNull && e.KeyCode == Keycode.Enter)
+ {
+ OnKeyboardDoneButtonPressed(EditText, EventArgs.Empty);
+ EditText.ClearFocus();
+ v.HideKeyboard();
+ }
+
+ return true;
+ }
+
+ void IOnFocusChangeListener.OnFocusChange(global::Android.Views.View view, bool hasFocus)
+ {
+ Action<bool> focusChanged = FocusChanged;
+ if (focusChanged != null)
+ focusChanged(hasFocus);
+ }
+
+ void ITextWatcher.AfterTextChanged(IEditable s)
+ {
+ }
+
+ void ITextWatcher.BeforeTextChanged(ICharSequence s, int start, int count, int after)
+ {
+ }
+
+ void ITextWatcher.OnTextChanged(ICharSequence s, int start, int before, int count)
+ {
+ Action<string> changed = TextChanged;
+ if (changed != null)
+ changed(s != null ? s.ToString() : null);
+ }
+
+ public void SetLabelTextColor(Color color, int defaultColorResourceId)
+ {
+ if (_labelTextColor == color)
+ return;
+
+ _labelTextColor = color;
+ _label.SetTextColor(color.ToAndroid(defaultColorResourceId));
+ }
+
+ public void SetRenderHeight(double height)
+ {
+ SetMinimumHeight((int)Context.ToPixels(height == -1 ? DefaultMinHeight : height));
+ }
+
+ void OnBackButtonPressed(object sender, EventArgs e)
+ {
+ // TODO Clear focus
+ }
+
+ void OnKeyboardDoneButtonPressed(object sender, EventArgs e)
+ {
+ // TODO Clear focus
+ Action editingCompleted = EditingCompleted;
+ if (editingCompleted != null)
+ editingCompleted();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Cells/ImageCellRenderer.cs b/Xamarin.Forms.Platform.Android/Cells/ImageCellRenderer.cs
new file mode 100644
index 00000000..62815ed6
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Cells/ImageCellRenderer.cs
@@ -0,0 +1,37 @@
+using System.ComponentModel;
+using Android.Content;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class ImageCellRenderer : TextCellRenderer
+ {
+ protected override global::Android.Views.View GetCellCore(Cell item, global::Android.Views.View convertView, ViewGroup parent, Context context)
+ {
+ var result = (BaseCellView)base.GetCellCore(item, convertView, parent, context);
+
+ UpdateImage();
+
+ return result;
+ }
+
+ protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args)
+ {
+ base.OnCellPropertyChanged(sender, args);
+ if (args.PropertyName == ImageCell.ImageSourceProperty.PropertyName)
+ UpdateImage();
+ }
+
+ void UpdateImage()
+ {
+ var cell = (ImageCell)Cell;
+ if (cell.ImageSource != null)
+ {
+ View.SetImageVisible(true);
+ View.SetImageSource(cell.ImageSource);
+ }
+ else
+ View.SetImageVisible(false);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Cells/SwitchCellRenderer.cs b/Xamarin.Forms.Platform.Android/Cells/SwitchCellRenderer.cs
new file mode 100644
index 00000000..bba9d260
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Cells/SwitchCellRenderer.cs
@@ -0,0 +1,55 @@
+using System.ComponentModel;
+using Android.Content;
+using Android.Views;
+using AView = Android.Views.View;
+using ASwitch = Android.Widget.Switch;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class SwitchCellRenderer : CellRenderer
+ {
+ const double DefaultHeight = 30;
+ SwitchCellView _view;
+
+ protected override AView GetCellCore(Cell item, AView convertView, ViewGroup parent, Context context)
+ {
+ var cell = (SwitchCell)Cell;
+
+ if ((_view = convertView as SwitchCellView) == null)
+ _view = new SwitchCellView(context, item);
+
+ _view.Cell = cell;
+
+ UpdateText();
+ UpdateChecked();
+ UpdateHeight();
+
+ return _view;
+ }
+
+ protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args)
+ {
+ if (args.PropertyName == SwitchCell.TextProperty.PropertyName)
+ UpdateText();
+ else if (args.PropertyName == SwitchCell.OnProperty.PropertyName)
+ UpdateChecked();
+ else if (args.PropertyName == "RenderHeight")
+ UpdateHeight();
+ }
+
+ void UpdateChecked()
+ {
+ ((ASwitch)_view.AccessoryView).Checked = ((SwitchCell)Cell).On;
+ }
+
+ void UpdateHeight()
+ {
+ _view.SetRenderHeight(Cell.RenderHeight);
+ }
+
+ void UpdateText()
+ {
+ _view.MainText = ((SwitchCell)Cell).Text;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Cells/SwitchCellView.cs b/Xamarin.Forms.Platform.Android/Cells/SwitchCellView.cs
new file mode 100644
index 00000000..f15c41b0
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Cells/SwitchCellView.cs
@@ -0,0 +1,25 @@
+using Android.Content;
+using Android.Widget;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class SwitchCellView : BaseCellView, CompoundButton.IOnCheckedChangeListener
+ {
+ public SwitchCellView(Context context, Cell cell) : base(context, cell)
+ {
+ var sw = new global::Android.Widget.Switch(context);
+ sw.SetOnCheckedChangeListener(this);
+
+ SetAccessoryView(sw);
+
+ SetImageVisible(false);
+ }
+
+ public SwitchCell Cell { get; set; }
+
+ public void OnCheckedChanged(CompoundButton buttonView, bool isChecked)
+ {
+ Cell.On = isChecked;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Cells/TextCellRenderer.cs b/Xamarin.Forms.Platform.Android/Cells/TextCellRenderer.cs
new file mode 100644
index 00000000..cbaaa2b7
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Cells/TextCellRenderer.cs
@@ -0,0 +1,78 @@
+using System.ComponentModel;
+using Android.Content;
+using Android.Views;
+using AView = Android.Views.View;
+using AColor = Android.Graphics.Color;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class TextCellRenderer : CellRenderer
+ {
+ internal TextCellView View { get; private set; }
+
+ protected override AView GetCellCore(Cell item, AView convertView, ViewGroup parent, Context context)
+ {
+ if ((View = convertView as TextCellView) == null)
+ View = new TextCellView(context, item);
+
+ UpdateMainText();
+ UpdateDetailText();
+ UpdateHeight();
+ UpdateIsEnabled();
+ View.SetImageVisible(false);
+
+ return View;
+ }
+
+ protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args)
+ {
+ if (args.PropertyName == TextCell.TextProperty.PropertyName || args.PropertyName == TextCell.TextColorProperty.PropertyName)
+ UpdateMainText();
+ else if (args.PropertyName == TextCell.DetailProperty.PropertyName || args.PropertyName == TextCell.DetailColorProperty.PropertyName)
+ UpdateDetailText();
+ else if (args.PropertyName == Cell.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled();
+ else if (args.PropertyName == "RenderHeight")
+ UpdateHeight();
+ }
+
+ void UpdateDetailText()
+ {
+ var cell = (TextCell)Cell;
+ View.DetailText = cell.Detail;
+ View.SetDetailTextColor(cell.DetailColor);
+ }
+
+ void UpdateHeight()
+ {
+ View.SetRenderHeight(Cell.RenderHeight);
+ }
+
+ void UpdateIsEnabled()
+ {
+ var cell = (TextCell)Cell;
+ View.SetIsEnabled(cell.IsEnabled);
+ }
+
+ void UpdateMainText()
+ {
+ var cell = (TextCell)Cell;
+ View.MainText = cell.Text;
+
+ if (!TemplatedItemsList<ItemsView<Cell>, Cell>.GetIsGroupHeader(cell))
+ View.SetDefaultMainTextColor(Color.Accent);
+ else
+ View.SetDefaultMainTextColor(Color.Default);
+
+ View.SetMainTextColor(cell.TextColor);
+ }
+
+ // ensure we don't get other people's BaseCellView's
+ internal class TextCellView : BaseCellView
+ {
+ public TextCellView(Context context, Cell cell) : base(context, cell)
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs b/Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs
new file mode 100644
index 00000000..4bf83395
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Cells/ViewCellRenderer.cs
@@ -0,0 +1,178 @@
+using Android.Content;
+using Android.Views;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class ViewCellRenderer : CellRenderer
+ {
+ protected override AView GetCellCore(Cell item, AView convertView, ViewGroup parent, Context context)
+ {
+ Performance.Start();
+ var cell = (ViewCell)item;
+
+ var container = convertView as ViewCellContainer;
+ if (container != null)
+ {
+ container.Update(cell);
+ Performance.Stop();
+ return container;
+ }
+
+ BindableProperty unevenRows = null, rowHeight = null;
+ if (ParentView is TableView)
+ {
+ unevenRows = TableView.HasUnevenRowsProperty;
+ rowHeight = TableView.RowHeightProperty;
+ }
+ else if (ParentView is ListView)
+ {
+ unevenRows = ListView.HasUnevenRowsProperty;
+ rowHeight = ListView.RowHeightProperty;
+ }
+
+ IVisualElementRenderer view = Platform.CreateRenderer(cell.View);
+ Platform.SetRenderer(cell.View, view);
+ cell.View.IsPlatformEnabled = true;
+ var c = new ViewCellContainer(context, view, cell, ParentView, unevenRows, rowHeight);
+
+ Performance.Stop();
+
+ return c;
+ }
+
+ internal class ViewCellContainer : ViewGroup, INativeElementView
+ {
+ readonly View _parent;
+ readonly BindableProperty _rowHeight;
+ readonly BindableProperty _unevenRows;
+ IVisualElementRenderer _view;
+ ViewCell _viewCell;
+
+ public ViewCellContainer(Context context, IVisualElementRenderer view, ViewCell viewCell, View parent, BindableProperty unevenRows, BindableProperty rowHeight) : base(context)
+ {
+ _view = view;
+ _parent = parent;
+ _unevenRows = unevenRows;
+ _rowHeight = rowHeight;
+ _viewCell = viewCell;
+ AddView(view.ViewGroup);
+ UpdateIsEnabled();
+ }
+
+ protected bool ParentHasUnevenRows
+ {
+ get { return (bool)_parent.GetValue(_unevenRows); }
+ }
+
+ protected int ParentRowHeight
+ {
+ get { return (int)_parent.GetValue(_rowHeight); }
+ }
+
+ public Element Element
+ {
+ get { return _viewCell; }
+ }
+
+ public override bool OnInterceptTouchEvent(MotionEvent ev)
+ {
+ if (!Enabled)
+ return true;
+ return base.OnInterceptTouchEvent(ev);
+ }
+
+ public void Update(ViewCell cell)
+ {
+ Performance.Start();
+
+ var renderer = GetChildAt(0) as IVisualElementRenderer;
+ var viewHandlerType = Registrar.Registered.GetHandlerType(cell.View.GetType()) ?? typeof(Platform.DefaultRenderer);
+ if (renderer != null && renderer.GetType() == viewHandlerType)
+ {
+ Performance.Start("Reuse");
+ _viewCell = cell;
+
+ cell.View.DisableLayout = true;
+ foreach (VisualElement c in cell.View.Descendants())
+ c.DisableLayout = true;
+
+ Performance.Start("Reuse.SetElement");
+ renderer.SetElement(cell.View);
+ Performance.Stop("Reuse.SetElement");
+
+ Platform.SetRenderer(cell.View, _view);
+
+ cell.View.DisableLayout = false;
+ foreach (VisualElement c in cell.View.Descendants())
+ c.DisableLayout = false;
+
+ var viewAsLayout = cell.View as Layout;
+ if (viewAsLayout != null)
+ viewAsLayout.ForceLayout();
+
+ Invalidate();
+
+ Performance.Stop("Reuse");
+ Performance.Stop();
+ return;
+ }
+
+ RemoveView(_view.ViewGroup);
+ Platform.SetRenderer(_viewCell.View, null);
+ _viewCell.View.IsPlatformEnabled = false;
+ _view.ViewGroup.Dispose();
+
+ _viewCell = cell;
+ _view = Platform.CreateRenderer(_viewCell.View);
+
+ Platform.SetRenderer(_viewCell.View, _view);
+ AddView(_view.ViewGroup);
+
+ UpdateIsEnabled();
+
+ Performance.Stop();
+ }
+
+ public void UpdateIsEnabled()
+ {
+ Enabled = _viewCell.IsEnabled;
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ Performance.Start();
+
+ double width = Context.FromPixels(r - l);
+ double height = Context.FromPixels(b - t);
+
+ Performance.Start("Element.Layout");
+ Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion(_view.Element, new Rectangle(0, 0, width, height));
+ Performance.Stop("Element.Layout");
+
+ _view.UpdateLayout();
+ Performance.Stop();
+ }
+
+ protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
+ {
+ Performance.Start();
+
+ int width = MeasureSpec.GetSize(widthMeasureSpec);
+ int height;
+
+ if (ParentHasUnevenRows)
+ {
+ SizeRequest measure = _view.Element.Measure(Context.FromPixels(width), double.PositiveInfinity, MeasureFlags.IncludeMargins);
+ height = (int)Context.ToPixels(_viewCell.Height > 0 ? _viewCell.Height : measure.Request.Height);
+ }
+ else
+ height = (int)Context.ToPixels(ParentRowHeight == -1 ? BaseCellView.DefaultMinHeight : ParentRowHeight);
+
+ SetMeasuredDimension(width, height);
+
+ Performance.Stop();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/ColorExtensions.cs b/Xamarin.Forms.Platform.Android/ColorExtensions.cs
new file mode 100644
index 00000000..afe7286d
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/ColorExtensions.cs
@@ -0,0 +1,40 @@
+using Android.Content.Res;
+using AColor = Android.Graphics.Color;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public static class ColorExtensions
+ {
+ static readonly int[][] ColorStates = { new[] { global::Android.Resource.Attribute.StateEnabled }, new[] { -global::Android.Resource.Attribute.StateEnabled } };
+
+ public static AColor ToAndroid(this Color self)
+ {
+ return new AColor((byte)(byte.MaxValue * self.R), (byte)(byte.MaxValue * self.G), (byte)(byte.MaxValue * self.B), (byte)(byte.MaxValue * self.A));
+ }
+
+ public static AColor ToAndroid(this Color self, int defaultColorResourceId)
+ {
+ if (self == Color.Default)
+ {
+ using(Resources resources = Resources.System)
+ return resources.GetColor(defaultColorResourceId);
+ }
+
+ return ToAndroid(self);
+ }
+
+ public static AColor ToAndroid(this Color self, Color defaultColor)
+ {
+ if (self == Color.Default)
+ return defaultColor.ToAndroid();
+
+ return ToAndroid(self);
+ }
+
+ public static ColorStateList ToAndroidPreserveDisabled(this Color color, ColorStateList defaults)
+ {
+ int disabled = defaults.GetColorForState(ColorStates[1], color.ToAndroid());
+ return new ColorStateList(ColorStates, new[] { color.ToAndroid().ToArgb(), disabled });
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/ContextExtensions.cs b/Xamarin.Forms.Platform.Android/ContextExtensions.cs
new file mode 100644
index 00000000..9a22c570
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/ContextExtensions.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Runtime.CompilerServices;
+using Android.Content;
+using Android.Util;
+using Android.Views.InputMethods;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public static class ContextExtensions
+ {
+ static float s_displayDensity = float.MinValue;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double FromPixels(this Context self, double pixels)
+ {
+ SetupMetrics(self);
+
+ return pixels / s_displayDensity;
+ }
+
+ public static void HideKeyboard(this Context self, global::Android.Views.View view)
+ {
+ var service = (InputMethodManager)self.GetSystemService(Context.InputMethodService);
+ service.HideSoftInputFromWindow(view.WindowToken, 0);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float ToPixels(this Context self, double dp)
+ {
+ SetupMetrics(self);
+
+ return (float)Math.Round(dp * s_displayDensity);
+ }
+
+ internal static double GetThemeAttributeDp(this Context self, int resource)
+ {
+ using(var value = new TypedValue())
+ {
+ if (!self.Theme.ResolveAttribute(resource, value, true))
+ return -1;
+
+ var pixels = (double)TypedValue.ComplexToDimension(value.Data, self.Resources.DisplayMetrics);
+
+ return self.FromPixels(pixels);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static void SetupMetrics(Context context)
+ {
+ if (s_displayDensity != float.MinValue)
+ return;
+
+ using(DisplayMetrics metrics = context.Resources.DisplayMetrics)
+ s_displayDensity = metrics.Density;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Deserializer.cs b/Xamarin.Forms.Platform.Android/Deserializer.cs
new file mode 100644
index 00000000..4c62ad1a
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Deserializer.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO.IsolatedStorage;
+using System.Runtime.Serialization;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class Deserializer : IDeserializer
+ {
+ const string PropertyStoreFile = "PropertyStore.forms";
+
+ public Task<IDictionary<string, object>> DeserializePropertiesAsync()
+ {
+ // Deserialize property dictionary to local storage
+ // Make sure to use Internal
+ return Task.Run(() =>
+ {
+ using(IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
+ using(IsolatedStorageFileStream stream = store.OpenFile(PropertyStoreFile, System.IO.FileMode.OpenOrCreate))
+ using(XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max))
+ {
+ if (stream.Length == 0)
+ return null;
+
+ try
+ {
+ var dcs = new DataContractSerializer(typeof(Dictionary<string, object>));
+ return (IDictionary<string, object>)dcs.ReadObject(reader);
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine("Could not deserialize properties: " + e.Message);
+ Log.Warning("Xamarin.Forms PropertyStore", $"Exception while reading Application properties: {e}");
+ }
+ }
+
+ return null;
+ });
+ }
+
+ public Task SerializePropertiesAsync(IDictionary<string, object> properties)
+ {
+ properties = new Dictionary<string, object>(properties);
+ // Serialize property dictionary to local storage
+ // Make sure to use Internal
+ return Task.Run(() =>
+ {
+ var success = false;
+ using(IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
+ using(IsolatedStorageFileStream stream = store.OpenFile(PropertyStoreFile + ".tmp", System.IO.FileMode.OpenOrCreate))
+ using(XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(stream))
+ {
+ try
+ {
+ var dcs = new DataContractSerializer(typeof(Dictionary<string, object>));
+ dcs.WriteObject(writer, properties);
+ writer.Flush();
+ success = true;
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine("Could not serialize properties: " + e.Message);
+ Log.Warning("Xamarin.Forms PropertyStore", $"Exception while writing Application properties: {e}");
+ }
+ }
+
+ if (!success)
+ return;
+ using(IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
+ {
+ try
+ {
+ if (store.FileExists(PropertyStoreFile))
+ store.DeleteFile(PropertyStoreFile);
+ store.MoveFile(PropertyStoreFile + ".tmp", PropertyStoreFile);
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine("Could not move new serialized property file over old: " + e.Message);
+ Log.Warning("Xamarin.Forms PropertyStore", $"Exception while writing Application properties: {e}");
+ }
+ }
+ });
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/ElementChangedEventArgs.cs b/Xamarin.Forms.Platform.Android/ElementChangedEventArgs.cs
new file mode 100644
index 00000000..cb529bd9
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/ElementChangedEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class ElementChangedEventArgs<TElement> : EventArgs where TElement : Element
+ {
+ public ElementChangedEventArgs(TElement oldElement, TElement newElement)
+ {
+ OldElement = oldElement;
+ NewElement = newElement;
+ }
+
+ public TElement NewElement { get; private set; }
+
+ public TElement OldElement { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/ExportCellAttribute.cs b/Xamarin.Forms.Platform.Android/ExportCellAttribute.cs
new file mode 100644
index 00000000..96aec6cb
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/ExportCellAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class ExportCellAttribute : HandlerAttribute
+ {
+ public ExportCellAttribute(Type handler, Type target) : base(handler, target)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/ExportImageSourceHandlerAttribute.cs b/Xamarin.Forms.Platform.Android/ExportImageSourceHandlerAttribute.cs
new file mode 100644
index 00000000..4c5c01fb
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/ExportImageSourceHandlerAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class ExportImageSourceHandlerAttribute : HandlerAttribute
+ {
+ public ExportImageSourceHandlerAttribute(Type handler, Type target) : base(handler, target)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/ExportRendererAttribute.cs b/Xamarin.Forms.Platform.Android/ExportRendererAttribute.cs
new file mode 100644
index 00000000..bf18653b
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/ExportRendererAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class ExportRendererAttribute : HandlerAttribute
+ {
+ public ExportRendererAttribute(Type handler, Type target) : base(handler, target)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Extensions.cs b/Xamarin.Forms.Platform.Android/Extensions.cs
new file mode 100644
index 00000000..c326555a
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Extensions.cs
@@ -0,0 +1,40 @@
+using Android.Content.Res;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public static class Extensions
+ {
+ internal static IMenuItem FindMenuItemByNameOrIcon(this IMenu menu, string menuName, string iconName)
+ {
+ if (menu.Size() == 1)
+ return menu.GetItem(0);
+
+ for (var i = 0; i < menu.Size(); i++)
+ {
+ IMenuItem menuItem = menu.GetItem(i);
+ if (menuItem.TitleFormatted != null && menuName == menuItem.TitleFormatted.ToString())
+ return menuItem;
+
+ if (!string.IsNullOrEmpty(iconName))
+ {
+ // TODO : search by iconName
+ }
+ }
+ return null;
+ }
+
+ internal static DeviceOrientation ToDeviceOrientation(this Orientation orientation)
+ {
+ switch (orientation)
+ {
+ case Orientation.Landscape:
+ return DeviceOrientation.Landscape;
+ case Orientation.Portrait:
+ return DeviceOrientation.Portrait;
+ default:
+ return DeviceOrientation.Other;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Forms.cs b/Xamarin.Forms.Platform.Android/Forms.cs
new file mode 100644
index 00000000..8eb50380
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Forms.cs
@@ -0,0 +1,514 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.IsolatedStorage;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Net.Http;
+using System.Reflection;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Android.App;
+using Android.Content;
+using Android.Content.Res;
+using Android.OS;
+using Android.Util;
+using Xamarin.Forms.Platform.Android;
+using Resource = Android.Resource;
+using Trace = System.Diagnostics.Trace;
+
+namespace Xamarin.Forms
+{
+ public static class Forms
+ {
+ const int TabletCrossover = 600;
+
+ static bool? s_supportsProgress;
+
+ static bool? s_isLollipopOrNewer;
+
+ public static Context Context { get; internal set; }
+
+ public static bool IsInitialized { get; private set; }
+
+ internal static bool IsLollipopOrNewer
+ {
+ get
+ {
+ if (!s_isLollipopOrNewer.HasValue)
+ s_isLollipopOrNewer = (int)Build.VERSION.SdkInt >= 21;
+ return s_isLollipopOrNewer.Value;
+ }
+ }
+
+ internal static bool SupportsProgress
+ {
+ get
+ {
+ var activity = Context as Activity;
+ if (!s_supportsProgress.HasValue)
+ {
+ int progressCircularId = Context.Resources.GetIdentifier("progress_circular", "id", "android");
+ if (progressCircularId > 0 && activity != null)
+ s_supportsProgress = activity.FindViewById(progressCircularId) != null;
+ else
+ s_supportsProgress = true;
+ }
+ return s_supportsProgress.Value;
+ }
+ }
+
+ internal static AndroidTitleBarVisibility TitleBarVisibility { get; private set; }
+
+ // Provide backwards compat for Forms.Init and AndroidActivity
+ // Why is bundle a param if never used?
+ public static void Init(Context activity, Bundle bundle)
+ {
+ Assembly resourceAssembly = Assembly.GetCallingAssembly();
+ SetupInit(activity, resourceAssembly);
+ }
+
+ public static void Init(Context activity, Bundle bundle, Assembly resourceAssembly)
+ {
+ SetupInit(activity, resourceAssembly);
+ }
+
+ public static void SetTitleBarVisibility(AndroidTitleBarVisibility visibility)
+ {
+ TitleBarVisibility = visibility;
+ }
+
+ public static event EventHandler<ViewInitializedEventArgs> ViewInitialized;
+
+ internal static void SendViewInitialized(this VisualElement self, global::Android.Views.View nativeView)
+ {
+ EventHandler<ViewInitializedEventArgs> viewInitialized = ViewInitialized;
+ if (viewInitialized != null)
+ viewInitialized(self, new ViewInitializedEventArgs { View = self, NativeView = nativeView });
+ }
+
+ static void SetupInit(Context activity, Assembly resourceAssembly)
+ {
+ Context = activity;
+
+ ResourceManager.Init(resourceAssembly);
+
+ // Detect if legacy device and use appropriate accent color
+ // Hardcoded because could not get color from the theme drawable
+ var sdkVersion = (int)Build.VERSION.SdkInt;
+ if (sdkVersion <= 10)
+ {
+ // legacy theme button pressed color
+ Color.Accent = Color.FromHex("#fffeaa0c");
+ }
+ else
+ {
+ // Holo dark light blue
+ Color.Accent = Color.FromHex("#ff33b5e5");
+ }
+
+ if (!IsInitialized)
+ Log.Listeners.Add(new DelegateLogListener((c, m) => Trace.WriteLine(m, c)));
+
+ Device.OS = TargetPlatform.Android;
+ Device.PlatformServices = new AndroidPlatformServices();
+
+ // use field and not property to avoid exception in getter
+ if (Device.info != null)
+ {
+ ((AndroidDeviceInfo)Device.info).Dispose();
+ Device.info = null;
+ }
+
+ // probably could be done in a better way
+ var deviceInfoProvider = activity as IDeviceInfoProvider;
+ if (deviceInfoProvider != null)
+ Device.Info = new AndroidDeviceInfo(deviceInfoProvider);
+
+ var ticker = Ticker.Default as AndroidTicker;
+ if (ticker != null)
+ ticker.Dispose();
+ Ticker.Default = new AndroidTicker();
+
+ if (!IsInitialized)
+ {
+ Registrar.RegisterAll(new[] { typeof(ExportRendererAttribute), typeof(ExportCellAttribute), typeof(ExportImageSourceHandlerAttribute) });
+ }
+
+ int minWidthDp = Context.Resources.Configuration.SmallestScreenWidthDp;
+
+ Device.Idiom = minWidthDp >= TabletCrossover ? TargetIdiom.Tablet : TargetIdiom.Phone;
+
+ if (ExpressionSearch.Default == null)
+ ExpressionSearch.Default = new AndroidExpressionSearch();
+
+ IsInitialized = true;
+ }
+
+ class AndroidDeviceInfo : DeviceInfo
+ {
+ readonly IDeviceInfoProvider _formsActivity;
+ readonly Size _pixelScreenSize;
+ readonly double _scalingFactor;
+
+ Orientation _previousOrientation = Orientation.Undefined;
+
+ public AndroidDeviceInfo(IDeviceInfoProvider formsActivity)
+ {
+ _formsActivity = formsActivity;
+ CheckOrientationChanged(_formsActivity.Resources.Configuration.Orientation);
+ formsActivity.ConfigurationChanged += ConfigurationChanged;
+
+ using(DisplayMetrics display = formsActivity.Resources.DisplayMetrics)
+ {
+ _scalingFactor = display.Density;
+ _pixelScreenSize = new Size(display.WidthPixels, display.HeightPixels);
+ ScaledScreenSize = new Size(_pixelScreenSize.Width / _scalingFactor, _pixelScreenSize.Width / _scalingFactor);
+ }
+ }
+
+ public override Size PixelScreenSize
+ {
+ get { return _pixelScreenSize; }
+ }
+
+ public override Size ScaledScreenSize { get; }
+
+ public override double ScalingFactor
+ {
+ get { return _scalingFactor; }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ _formsActivity.ConfigurationChanged -= ConfigurationChanged;
+ base.Dispose(disposing);
+ }
+
+ void CheckOrientationChanged(Orientation orientation)
+ {
+ if (!_previousOrientation.Equals(orientation))
+ CurrentOrientation = orientation.ToDeviceOrientation();
+
+ _previousOrientation = orientation;
+ }
+
+ void ConfigurationChanged(object sender, EventArgs e)
+ {
+ CheckOrientationChanged(_formsActivity.Resources.Configuration.Orientation);
+ }
+ }
+
+ class AndroidExpressionSearch : ExpressionVisitor, IExpressionSearch
+ {
+ List<object> _results;
+ Type _targetType;
+
+ public List<T> FindObjects<T>(Expression expression) where T : class
+ {
+ _results = new List<object>();
+ _targetType = typeof(T);
+ Visit(expression);
+ return _results.Select(o => o as T).ToList();
+ }
+
+ protected override Expression VisitMember(MemberExpression node)
+ {
+ if (node.Expression is ConstantExpression && node.Member is FieldInfo)
+ {
+ object container = ((ConstantExpression)node.Expression).Value;
+ object value = ((FieldInfo)node.Member).GetValue(container);
+
+ if (_targetType.IsInstanceOfType(value))
+ _results.Add(value);
+ }
+ return base.VisitMember(node);
+ }
+ }
+
+ class AndroidPlatformServices : IPlatformServices
+ {
+ static readonly MD5CryptoServiceProvider Checksum = new MD5CryptoServiceProvider();
+ double _buttonDefaultSize;
+ double _editTextDefaultSize;
+ double _labelDefaultSize;
+ double _largeSize;
+ double _mediumSize;
+
+ double _microSize;
+ double _smallSize;
+
+ public void BeginInvokeOnMainThread(Action action)
+ {
+ var activity = Context as Activity;
+ if (activity != null)
+ activity.RunOnUiThread(action);
+ }
+
+ public ITimer CreateTimer(Action<object> callback)
+ {
+ return new _Timer(new Timer(o => callback(o)));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, int dueTime, int period)
+ {
+ return new _Timer(new Timer(o => callback(o), state, dueTime, period));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, long dueTime, long period)
+ {
+ return new _Timer(new Timer(o => callback(o), state, dueTime, period));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, TimeSpan dueTime, TimeSpan period)
+ {
+ return new _Timer(new Timer(o => callback(o), state, dueTime, period));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, uint dueTime, uint period)
+ {
+ return new _Timer(new Timer(o => callback(o), state, dueTime, period));
+ }
+
+ public Assembly[] GetAssemblies()
+ {
+ return AppDomain.CurrentDomain.GetAssemblies();
+ }
+
+ public string GetMD5Hash(string input)
+ {
+ byte[] bytes = Checksum.ComputeHash(Encoding.UTF8.GetBytes(input));
+ var ret = new char[32];
+ for (var i = 0; i < 16; i++)
+ {
+ ret[i * 2] = (char)Hex(bytes[i] >> 4);
+ ret[i * 2 + 1] = (char)Hex(bytes[i] & 0xf);
+ }
+ return new string(ret);
+ }
+
+ public double GetNamedSize(NamedSize size, Type targetElementType, bool useOldSizes)
+ {
+ if (_smallSize == 0)
+ {
+ _smallSize = ConvertTextAppearanceToSize(Resource.Attribute.TextAppearanceSmall, Resource.Style.TextAppearanceDeviceDefaultSmall, 12);
+ _mediumSize = ConvertTextAppearanceToSize(Resource.Attribute.TextAppearanceMedium, Resource.Style.TextAppearanceDeviceDefaultMedium, 14);
+ _largeSize = ConvertTextAppearanceToSize(Resource.Attribute.TextAppearanceLarge, Resource.Style.TextAppearanceDeviceDefaultLarge, 18);
+ _buttonDefaultSize = ConvertTextAppearanceToSize(Resource.Attribute.TextAppearanceButton, Resource.Style.TextAppearanceDeviceDefaultWidgetButton, 14);
+ _editTextDefaultSize = ConvertTextAppearanceToSize(Resource.Style.TextAppearanceWidgetEditText, Resource.Style.TextAppearanceDeviceDefaultWidgetEditText, 18);
+ _labelDefaultSize = _smallSize;
+ // as decreed by the android docs, ALL HAIL THE ANDROID DOCS, ALL GLORY TO THE DOCS, PRAISE HYPNOTOAD
+ _microSize = Math.Max(1, _smallSize - (_mediumSize - _smallSize));
+ }
+
+ if (useOldSizes)
+ {
+ switch (size)
+ {
+ case NamedSize.Default:
+ if (typeof(Button).IsAssignableFrom(targetElementType))
+ return _buttonDefaultSize;
+ if (typeof(Label).IsAssignableFrom(targetElementType))
+ return _labelDefaultSize;
+ if (typeof(Editor).IsAssignableFrom(targetElementType) || typeof(Entry).IsAssignableFrom(targetElementType) || typeof(SearchBar).IsAssignableFrom(targetElementType))
+ return _editTextDefaultSize;
+ return 14;
+ case NamedSize.Micro:
+ return 10;
+ case NamedSize.Small:
+ return 12;
+ case NamedSize.Medium:
+ return 14;
+ case NamedSize.Large:
+ return 18;
+ default:
+ throw new ArgumentOutOfRangeException("size");
+ }
+ }
+ switch (size)
+ {
+ case NamedSize.Default:
+ if (typeof(Button).IsAssignableFrom(targetElementType))
+ return _buttonDefaultSize;
+ if (typeof(Label).IsAssignableFrom(targetElementType))
+ return _labelDefaultSize;
+ if (typeof(Editor).IsAssignableFrom(targetElementType) || typeof(Entry).IsAssignableFrom(targetElementType))
+ return _editTextDefaultSize;
+ return _mediumSize;
+ case NamedSize.Micro:
+ return _microSize;
+ case NamedSize.Small:
+ return _smallSize;
+ case NamedSize.Medium:
+ return _mediumSize;
+ case NamedSize.Large:
+ return _largeSize;
+ default:
+ throw new ArgumentOutOfRangeException("size");
+ }
+ }
+
+ public async Task<Stream> GetStreamAsync(Uri uri, CancellationToken cancellationToken)
+ {
+ using(var client = new HttpClient())
+ using(HttpResponseMessage response = await client.GetAsync(uri, cancellationToken))
+ return await response.Content.ReadAsStreamAsync();
+ }
+
+ public IIsolatedStorageFile GetUserStoreForApplication()
+ {
+ return new _IsolatedStorageFile(IsolatedStorageFile.GetUserStoreForApplication());
+ }
+
+ public bool IsInvokeRequired
+ {
+ get
+ {
+ using(Looper my = Looper.MyLooper())
+ using(Looper main = Looper.MainLooper)
+ return my != main;
+ }
+ }
+
+ public void OpenUriAction(Uri uri)
+ {
+ global::Android.Net.Uri aUri = global::Android.Net.Uri.Parse(uri.ToString());
+ var intent = new Intent(Intent.ActionView, aUri);
+ Context.StartActivity(intent);
+ }
+
+ public void StartTimer(TimeSpan interval, Func<bool> callback)
+ {
+ Timer timer = null;
+ TimerCallback onTimeout = o => BeginInvokeOnMainThread(() =>
+ {
+ if (callback())
+ return;
+
+ timer.Dispose();
+ });
+ timer = new Timer(onTimeout, null, interval, interval);
+ }
+
+ double ConvertTextAppearanceToSize(int themeDefault, int deviceDefault, double defaultValue)
+ {
+ double myValue;
+
+ if (TryGetTextAppearance(themeDefault, out myValue))
+ return myValue;
+ if (TryGetTextAppearance(deviceDefault, out myValue))
+ return myValue;
+ return defaultValue;
+ }
+
+ static int Hex(int v)
+ {
+ if (v < 10)
+ return '0' + v;
+ return 'a' + v - 10;
+ }
+
+ static bool TryGetTextAppearance(int appearance, out double val)
+ {
+ val = 0;
+ try
+ {
+ using(var value = new TypedValue())
+ {
+ if (Context.Theme.ResolveAttribute(appearance, value, true))
+ {
+ var textSizeAttr = new[] { Resource.Attribute.TextSize };
+ const int indexOfAttrTextSize = 0;
+ using(TypedArray array = Context.ObtainStyledAttributes(value.Data, textSizeAttr))
+ {
+ val = Context.FromPixels(array.GetDimensionPixelSize(indexOfAttrTextSize, -1));
+ return true;
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ // Before you ask, yes, Exception. I know. But thats what android throws, new Exception... YAY BINDINGS
+ // log exception using insights if possible
+ }
+ return false;
+ }
+
+ public class _Timer : ITimer
+ {
+ readonly Timer _timer;
+
+ public _Timer(Timer timer)
+ {
+ _timer = timer;
+ }
+
+ public void Change(int dueTime, int period)
+ {
+ _timer.Change(dueTime, period);
+ }
+
+ public void Change(long dueTime, long period)
+ {
+ _timer.Change(dueTime, period);
+ }
+
+ public void Change(TimeSpan dueTime, TimeSpan period)
+ {
+ _timer.Change(dueTime, period);
+ }
+
+ public void Change(uint dueTime, uint period)
+ {
+ _timer.Change(dueTime, period);
+ }
+ }
+
+ public class _IsolatedStorageFile : IIsolatedStorageFile
+ {
+ readonly IsolatedStorageFile _isolatedStorageFile;
+
+ public _IsolatedStorageFile(IsolatedStorageFile isolatedStorageFile)
+ {
+ _isolatedStorageFile = isolatedStorageFile;
+ }
+
+ public Task CreateDirectoryAsync(string path)
+ {
+ _isolatedStorageFile.CreateDirectory(path);
+ return Task.FromResult(true);
+ }
+
+ public Task<bool> GetDirectoryExistsAsync(string path)
+ {
+ return Task.FromResult(_isolatedStorageFile.DirectoryExists(path));
+ }
+
+ public Task<bool> GetFileExistsAsync(string path)
+ {
+ return Task.FromResult(_isolatedStorageFile.FileExists(path));
+ }
+
+ public Task<DateTimeOffset> GetLastWriteTimeAsync(string path)
+ {
+ return Task.FromResult(_isolatedStorageFile.GetLastWriteTime(path));
+ }
+
+ public Task<Stream> OpenFileAsync(string path, FileMode mode, FileAccess access)
+ {
+ Stream stream = _isolatedStorageFile.OpenFile(path, (System.IO.FileMode)mode, (System.IO.FileAccess)access);
+ return Task.FromResult(stream);
+ }
+
+ public Task<Stream> OpenFileAsync(string path, FileMode mode, FileAccess access, FileShare share)
+ {
+ Stream stream = _isolatedStorageFile.OpenFile(path, (System.IO.FileMode)mode, (System.IO.FileAccess)access, (System.IO.FileShare)share);
+ return Task.FromResult(stream);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/FormsApplicationActivity.cs b/Xamarin.Forms.Platform.Android/FormsApplicationActivity.cs
new file mode 100644
index 00000000..c05c79f6
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/FormsApplicationActivity.cs
@@ -0,0 +1,319 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using Android.App;
+using Android.Content;
+using Android.Content.Res;
+using Android.OS;
+using Android.Views;
+using Android.Widget;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class FormsApplicationActivity : Activity, IDeviceInfoProvider, IStartActivityForResult
+ {
+ public delegate bool BackButtonPressedEventHandler(object sender, EventArgs e);
+
+ readonly ConcurrentDictionary<int, Action<Result, Intent>> _activityResultCallbacks = new ConcurrentDictionary<int, Action<Result, Intent>>();
+
+ Application _application;
+ Platform _canvas;
+ AndroidApplicationLifecycleState _currentState;
+ LinearLayout _layout;
+
+ int _nextActivityResultCallbackKey;
+
+ AndroidApplicationLifecycleState _previousState;
+
+ protected FormsApplicationActivity()
+ {
+ _previousState = AndroidApplicationLifecycleState.Uninitialized;
+ _currentState = AndroidApplicationLifecycleState.Uninitialized;
+ }
+
+ public event EventHandler ConfigurationChanged;
+
+ int IStartActivityForResult.RegisterActivityResultCallback(Action<Result, Intent> callback)
+ {
+ int requestCode = _nextActivityResultCallbackKey;
+
+ while (!_activityResultCallbacks.TryAdd(requestCode, callback))
+ {
+ _nextActivityResultCallbackKey += 1;
+ requestCode = _nextActivityResultCallbackKey;
+ }
+
+ _nextActivityResultCallbackKey += 1;
+
+ return requestCode;
+ }
+
+ void IStartActivityForResult.UnregisterActivityResultCallback(int requestCode)
+ {
+ Action<Result, Intent> callback;
+ _activityResultCallbacks.TryRemove(requestCode, out callback);
+ }
+
+ public static event BackButtonPressedEventHandler BackPressed;
+
+ public override void OnBackPressed()
+ {
+ if (BackPressed != null && BackPressed(this, EventArgs.Empty))
+ return;
+ base.OnBackPressed();
+ }
+
+ public override void OnConfigurationChanged(Configuration newConfig)
+ {
+ base.OnConfigurationChanged(newConfig);
+ EventHandler handler = ConfigurationChanged;
+ if (handler != null)
+ handler(this, new EventArgs());
+ }
+
+ // FIXME: THIS SHOULD NOT BE MANDATORY
+ // or
+ // This should be specified in an interface and formalized, perhaps even provide a stock AndroidActivity users
+ // can derive from to avoid having to do any work.
+ public override bool OnOptionsItemSelected(IMenuItem item)
+ {
+ if (item.ItemId == global::Android.Resource.Id.Home)
+ _canvas.SendHomeClicked();
+ return base.OnOptionsItemSelected(item);
+ }
+
+ public override bool OnPrepareOptionsMenu(IMenu menu)
+ {
+ _canvas.PrepareMenu(menu);
+ return base.OnPrepareOptionsMenu(menu);
+ }
+
+ [Obsolete("Please use protected LoadApplication (Application app) instead")]
+ public void SetPage(Page page)
+ {
+ var application = new DefaultApplication { MainPage = page };
+ LoadApplication(application);
+ }
+
+ protected void LoadApplication(Application application)
+ {
+ if (application == null)
+ throw new ArgumentNullException("application");
+
+ _application = application;
+ Xamarin.Forms.Application.Current = application;
+
+ application.PropertyChanged += AppOnPropertyChanged;
+
+ SetMainPage();
+ }
+
+ protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
+ {
+ base.OnActivityResult(requestCode, resultCode, data);
+
+ Action<Result, Intent> callback;
+
+ if (_activityResultCallbacks.TryGetValue(requestCode, out callback))
+ callback(resultCode, data);
+ }
+
+ protected override void OnCreate(Bundle savedInstanceState)
+ {
+ Window.RequestFeature(WindowFeatures.IndeterminateProgress);
+
+ base.OnCreate(savedInstanceState);
+
+ _layout = new LinearLayout(BaseContext);
+ SetContentView(_layout);
+
+ Xamarin.Forms.Application.ClearCurrent();
+
+ _previousState = _currentState;
+ _currentState = AndroidApplicationLifecycleState.OnCreate;
+
+ OnStateChanged();
+ }
+
+ protected override void OnDestroy()
+ {
+ // may never be called
+ base.OnDestroy();
+
+ MessagingCenter.Unsubscribe<Page, AlertArguments>(this, Page.AlertSignalName);
+ MessagingCenter.Unsubscribe<Page, bool>(this, Page.BusySetSignalName);
+ MessagingCenter.Unsubscribe<Page, ActionSheetArguments>(this, Page.ActionSheetSignalName);
+
+ if (_canvas != null)
+ ((IDisposable)_canvas).Dispose();
+ }
+
+ protected override void OnPause()
+ {
+ _layout.HideKeyboard(true);
+
+ // Stop animations or other ongoing actions that could consume CPU
+ // Commit unsaved changes, build only if users expect such changes to be permanently saved when thy leave such as a draft email
+ // Release system resources, such as broadcast receivers, handles to sensors (like GPS), or any resources that may affect battery life when your activity is paused.
+ // Avoid writing to permanent storage and CPU intensive tasks
+ base.OnPause();
+
+ _previousState = _currentState;
+ _currentState = AndroidApplicationLifecycleState.OnPause;
+
+ OnStateChanged();
+ }
+
+ protected override void OnRestart()
+ {
+ base.OnRestart();
+
+ _previousState = _currentState;
+ _currentState = AndroidApplicationLifecycleState.OnRestart;
+
+ OnStateChanged();
+ }
+
+ protected override void OnResume()
+ {
+ // counterpart to OnPause
+ base.OnResume();
+
+ _previousState = _currentState;
+ _currentState = AndroidApplicationLifecycleState.OnResume;
+
+ OnStateChanged();
+ }
+
+ protected override void OnStart()
+ {
+ base.OnStart();
+
+ _previousState = _currentState;
+ _currentState = AndroidApplicationLifecycleState.OnStart;
+
+ OnStateChanged();
+ }
+
+ // Scenarios that stop and restart you app
+ // -- Switches from your app to another app, activity restarts when clicking on the app again.
+ // -- Action in your app that starts a new Activity, the current activity is stopped and the second is created, pressing back restarts the activity
+ // -- The user recieves a phone call while using your app on his or her phone
+ protected override void OnStop()
+ {
+ // writing to storage happens here!
+ // full UI obstruction
+ // users focus in another activity
+ // perform heavy load shutdown operations
+ // clean up resources
+ // clean up everything that may leak memory
+ base.OnStop();
+
+ _previousState = _currentState;
+ _currentState = AndroidApplicationLifecycleState.OnStop;
+
+ OnStateChanged();
+ }
+
+ void AppOnPropertyChanged(object sender, PropertyChangedEventArgs args)
+ {
+ if (args.PropertyName == "MainPage")
+ InternalSetPage(_application.MainPage);
+ }
+
+ void InternalSetPage(Page page)
+ {
+ if (!Forms.IsInitialized)
+ throw new InvalidOperationException("Call Forms.Init (Activity, Bundle) before this");
+
+ if (_canvas != null)
+ {
+ _canvas.SetPage(page);
+ return;
+ }
+
+ var busyCount = 0;
+ MessagingCenter.Subscribe(this, Page.BusySetSignalName, (Page sender, bool enabled) =>
+ {
+ busyCount = Math.Max(0, enabled ? busyCount + 1 : busyCount - 1);
+
+ if (!Forms.SupportsProgress)
+ return;
+
+ SetProgressBarIndeterminate(true);
+ UpdateProgressBarVisibility(busyCount > 0);
+ });
+
+ UpdateProgressBarVisibility(busyCount > 0);
+
+ MessagingCenter.Subscribe(this, Page.AlertSignalName, (Page sender, AlertArguments arguments) =>
+ {
+ AlertDialog alert = new AlertDialog.Builder(this).Create();
+ alert.SetTitle(arguments.Title);
+ alert.SetMessage(arguments.Message);
+ if (arguments.Accept != null)
+ alert.SetButton((int)DialogButtonType.Positive, arguments.Accept, (o, args) => arguments.SetResult(true));
+ alert.SetButton((int)DialogButtonType.Negative, arguments.Cancel, (o, args) => arguments.SetResult(false));
+ alert.CancelEvent += (o, args) => { arguments.SetResult(false); };
+ alert.Show();
+ });
+
+ MessagingCenter.Subscribe(this, Page.ActionSheetSignalName, (Page sender, ActionSheetArguments arguments) =>
+ {
+ var builder = new AlertDialog.Builder(this);
+ builder.SetTitle(arguments.Title);
+ string[] items = arguments.Buttons.ToArray();
+ builder.SetItems(items, (sender2, args) => { arguments.Result.TrySetResult(items[args.Which]); });
+
+ if (arguments.Cancel != null)
+ builder.SetPositiveButton(arguments.Cancel, delegate { arguments.Result.TrySetResult(arguments.Cancel); });
+
+ if (arguments.Destruction != null)
+ builder.SetNegativeButton(arguments.Destruction, delegate { arguments.Result.TrySetResult(arguments.Destruction); });
+
+ AlertDialog dialog = builder.Create();
+ builder.Dispose();
+ //to match current functionality of renderer we set cancelable on outside
+ //and return null
+ dialog.SetCanceledOnTouchOutside(true);
+ dialog.CancelEvent += (sender3, e) => { arguments.SetResult(null); };
+ dialog.Show();
+ });
+
+ _canvas = new Platform(this);
+ if (_application != null)
+ _application.Platform = _canvas;
+ _canvas.SetPage(page);
+ _layout.AddView(_canvas.GetViewGroup());
+ }
+
+ void OnStateChanged()
+ {
+ if (_application == null)
+ return;
+
+ if (_previousState == AndroidApplicationLifecycleState.OnCreate && _currentState == AndroidApplicationLifecycleState.OnStart)
+ _application.SendStart();
+ else if (_previousState == AndroidApplicationLifecycleState.OnStop && _currentState == AndroidApplicationLifecycleState.OnRestart)
+ _application.SendResume();
+ else if (_previousState == AndroidApplicationLifecycleState.OnPause && _currentState == AndroidApplicationLifecycleState.OnStop)
+ _application.SendSleepAsync().Wait();
+ }
+
+ void SetMainPage()
+ {
+ InternalSetPage(_application.MainPage);
+ }
+
+ void UpdateProgressBarVisibility(bool isBusy)
+ {
+ if (!Forms.SupportsProgress)
+ return;
+ SetProgressBarIndeterminateVisibility(isBusy);
+ }
+
+ internal class DefaultApplication : Application
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/GenericMenuClickListener.cs b/Xamarin.Forms.Platform.Android/GenericMenuClickListener.cs
new file mode 100644
index 00000000..8a6dd3b8
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/GenericMenuClickListener.cs
@@ -0,0 +1,22 @@
+using System;
+using Android.Views;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class GenericMenuClickListener : Object, IMenuItemOnMenuItemClickListener
+ {
+ readonly Action _callback;
+
+ public GenericMenuClickListener(Action callback)
+ {
+ _callback = callback;
+ }
+
+ public bool OnMenuItemClick(IMenuItem item)
+ {
+ _callback();
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/GetDesiredSizeDelegate.cs b/Xamarin.Forms.Platform.Android/GetDesiredSizeDelegate.cs
new file mode 100644
index 00000000..11f77ebf
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/GetDesiredSizeDelegate.cs
@@ -0,0 +1,4 @@
+namespace Xamarin.Forms.Platform.Android
+{
+ public delegate SizeRequest? GetDesiredSizeDelegate(NativeViewWrapperRenderer renderer, int widthConstraint, int heightConstraint);
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/IDeviceInfoProvider.cs b/Xamarin.Forms.Platform.Android/IDeviceInfoProvider.cs
new file mode 100644
index 00000000..c9810b16
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/IDeviceInfoProvider.cs
@@ -0,0 +1,12 @@
+using System;
+using Android.Content.Res;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public interface IDeviceInfoProvider
+ {
+ Resources Resources { get; }
+
+ event EventHandler ConfigurationChanged;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/IPlatformLayout.cs b/Xamarin.Forms.Platform.Android/IPlatformLayout.cs
new file mode 100644
index 00000000..af30fc92
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/IPlatformLayout.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms.Platform.Android
+{
+ internal interface IPlatformLayout
+ {
+ void OnLayout(bool changed, int l, int t, int r, int b);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/IStartActivityForResult.cs b/Xamarin.Forms.Platform.Android/IStartActivityForResult.cs
new file mode 100644
index 00000000..71de9793
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/IStartActivityForResult.cs
@@ -0,0 +1,14 @@
+using System;
+using Android.App;
+using Android.Content;
+using Android.OS;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal interface IStartActivityForResult
+ {
+ int RegisterActivityResultCallback(Action<Result, Intent> callback);
+ void StartActivityForResult(Intent intent, int requestCode, Bundle options = null);
+ void UnregisterActivityResultCallback(int requestCode);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/IVisualElementRenderer.cs b/Xamarin.Forms.Platform.Android/IVisualElementRenderer.cs
new file mode 100644
index 00000000..99393516
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/IVisualElementRenderer.cs
@@ -0,0 +1,22 @@
+using System;
+using Android.Views;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public interface IVisualElementRenderer : IRegisterable, IDisposable
+ {
+ VisualElement Element { get; }
+
+ VisualElementTracker Tracker { get; }
+
+ ViewGroup ViewGroup { get; }
+
+ event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint);
+
+ void SetElement(VisualElement element);
+ void UpdateLayout();
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/InnerGestureListener.cs b/Xamarin.Forms.Platform.Android/InnerGestureListener.cs
new file mode 100644
index 00000000..f83a1ac7
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/InnerGestureListener.cs
@@ -0,0 +1,146 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Android.Runtime;
+using Android.Views;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class InnerGestureListener : Object, GestureDetector.IOnGestureListener, GestureDetector.IOnDoubleTapListener
+ {
+ bool _isScrolling;
+ Func<bool> _scrollCompleteDelegate;
+ Func<float, float, int, bool> _scrollDelegate;
+ Func<int, bool> _scrollStartedDelegate;
+ Func<int, bool> _tapDelegate;
+ Func<int, IEnumerable<TapGestureRecognizer>> _tapGestureRecognizers;
+
+ public InnerGestureListener(Func<int, bool> tapDelegate, Func<int, IEnumerable<TapGestureRecognizer>> tapGestureRecognizers, Func<float, float, int, bool> scrollDelegate,
+ Func<int, bool> scrollStartedDelegate, Func<bool> scrollCompleteDelegate)
+ {
+ if (tapDelegate == null)
+ throw new ArgumentNullException("tapDelegate");
+ if (tapGestureRecognizers == null)
+ throw new ArgumentNullException("tapGestureRecognizers");
+ if (scrollDelegate == null)
+ throw new ArgumentNullException("scrollDelegate");
+ if (scrollStartedDelegate == null)
+ throw new ArgumentNullException("scrollStartedDelegate");
+ if (scrollCompleteDelegate == null)
+ throw new ArgumentNullException("scrollCompleteDelegate");
+
+ _tapDelegate = tapDelegate;
+ _tapGestureRecognizers = tapGestureRecognizers;
+ _scrollDelegate = scrollDelegate;
+ _scrollStartedDelegate = scrollStartedDelegate;
+ _scrollCompleteDelegate = scrollCompleteDelegate;
+ }
+
+ // This is needed because GestureRecognizer callbacks can be delayed several hundred milliseconds
+ // which can result in the need to resurect this object if it has already been disposed. We dispose
+ // eagerly to allow easier garbage collection of the renderer
+ internal InnerGestureListener(IntPtr handle, JniHandleOwnership ownership) : base(handle, ownership)
+ {
+ }
+
+ bool GestureDetector.IOnDoubleTapListener.OnDoubleTap(MotionEvent e)
+ {
+ if (_tapDelegate == null || _tapGestureRecognizers == null)
+ return false;
+ return _tapDelegate(2);
+ }
+
+ bool GestureDetector.IOnDoubleTapListener.OnDoubleTapEvent(MotionEvent e)
+ {
+ return false;
+ }
+
+ bool GestureDetector.IOnDoubleTapListener.OnSingleTapConfirmed(MotionEvent e)
+ {
+ if (_tapDelegate == null || _tapGestureRecognizers == null)
+ return false;
+
+ // optimization: only wait for a second tap if there is a double tap handler
+ if (!HasDoubleTapHandler())
+ return false;
+
+ return _tapDelegate(1);
+ }
+
+ bool GestureDetector.IOnGestureListener.OnDown(MotionEvent e)
+ {
+ return false;
+ }
+
+ bool GestureDetector.IOnGestureListener.OnFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
+ {
+ EndScrolling();
+
+ return false;
+ }
+
+ void GestureDetector.IOnGestureListener.OnLongPress(MotionEvent e)
+ {
+ }
+
+ bool GestureDetector.IOnGestureListener.OnScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
+ {
+ if (_scrollDelegate == null || e1 == null || e2 == null)
+ return false;
+
+ if (!_isScrolling && _scrollStartedDelegate != null)
+ _scrollStartedDelegate(e2.PointerCount);
+
+ _isScrolling = true;
+
+ float totalX = e2.GetX() - e1.GetX();
+ float totalY = e2.GetY() - e1.GetY();
+
+ return _scrollDelegate(totalX, totalY, e2.PointerCount);
+ }
+
+ void GestureDetector.IOnGestureListener.OnShowPress(MotionEvent e)
+ {
+ }
+
+ bool GestureDetector.IOnGestureListener.OnSingleTapUp(MotionEvent e)
+ {
+ if (_tapDelegate == null || _tapGestureRecognizers == null)
+ return false;
+
+ // optimization: do not wait for a second tap if there is no double tap handler
+ if (HasDoubleTapHandler())
+ return false;
+
+ return _tapDelegate(1);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _tapDelegate = null;
+ _tapGestureRecognizers = null;
+ _scrollDelegate = null;
+ _scrollStartedDelegate = null;
+ _scrollCompleteDelegate = null;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ void EndScrolling()
+ {
+ if (_isScrolling && _scrollCompleteDelegate != null)
+ _scrollCompleteDelegate();
+
+ _isScrolling = false;
+ }
+
+ bool HasDoubleTapHandler()
+ {
+ return _tapGestureRecognizers(2).Any();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/InnerScaleListener.cs b/Xamarin.Forms.Platform.Android/InnerScaleListener.cs
new file mode 100644
index 00000000..4a6c6581
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/InnerScaleListener.cs
@@ -0,0 +1,68 @@
+using System;
+using Android.Runtime;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class InnerScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener
+ {
+ Func<float, Point, bool> _pinchDelegate;
+ Action _pinchEndedDelegate;
+ Func<Point, bool> _pinchStartedDelegate;
+
+ public InnerScaleListener(Func<float, Point, bool> pinchDelegate, Func<Point, bool> pinchStarted, Action pinchEnded)
+ {
+ if (pinchDelegate == null)
+ throw new ArgumentNullException("pinchDelegate");
+
+ if (pinchStarted == null)
+ throw new ArgumentNullException("pinchStarted");
+
+ if (pinchEnded == null)
+ throw new ArgumentNullException("pinchEnded");
+
+ _pinchDelegate = pinchDelegate;
+ _pinchStartedDelegate = pinchStarted;
+ _pinchEndedDelegate = pinchEnded;
+ }
+
+ // This is needed because GestureRecognizer callbacks can be delayed several hundred milliseconds
+ // which can result in the need to resurect this object if it has already been disposed. We dispose
+ // eagerly to allow easier garbage collection of the renderer
+ internal InnerScaleListener(IntPtr handle, JniHandleOwnership ownership) : base(handle, ownership)
+ {
+ }
+
+ public override bool OnScale(ScaleGestureDetector detector)
+ {
+ float cur = detector.CurrentSpan;
+ float last = detector.PreviousSpan;
+
+ if (Math.Abs(cur - last) < 10)
+ return false;
+
+ return _pinchDelegate(detector.ScaleFactor, new Point(Forms.Context.FromPixels(detector.FocusX), Forms.Context.FromPixels(detector.FocusY)));
+ }
+
+ public override bool OnScaleBegin(ScaleGestureDetector detector)
+ {
+ return _pinchStartedDelegate(new Point(Forms.Context.FromPixels(detector.FocusX), Forms.Context.FromPixels(detector.FocusY)));
+ }
+
+ public override void OnScaleEnd(ScaleGestureDetector detector)
+ {
+ _pinchEndedDelegate();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _pinchDelegate = null;
+ _pinchStartedDelegate = null;
+ _pinchEndedDelegate = null;
+ }
+ base.Dispose(disposing);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/KeyboardManager.cs b/Xamarin.Forms.Platform.Android/KeyboardManager.cs
new file mode 100644
index 00000000..649c99bd
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/KeyboardManager.cs
@@ -0,0 +1,41 @@
+using System;
+using Android.Content;
+using Android.OS;
+using Android.Views.InputMethods;
+using Android.Widget;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal static class KeyboardManager
+ {
+ internal static void HideKeyboard(this AView inputView, bool overrideValidation = false)
+ {
+ using(var inputMethodManager = (InputMethodManager)Forms.Context.GetSystemService(Context.InputMethodService))
+ {
+ IBinder windowToken = null;
+
+ if (!overrideValidation && !(inputView is EditText || inputView is TextView || inputView is SearchView))
+ throw new ArgumentException("inputView should be of type EditText, SearchView, or TextView");
+
+ windowToken = inputView.WindowToken;
+ if (windowToken != null)
+ inputMethodManager.HideSoftInputFromWindow(windowToken, HideSoftInputFlags.None);
+ }
+ }
+
+ internal static void ShowKeyboard(this AView inputView)
+ {
+ using(var inputMethodManager = (InputMethodManager)Forms.Context.GetSystemService(Context.InputMethodService))
+ {
+ if (inputView is EditText || inputView is TextView || inputView is SearchView)
+ {
+ inputMethodManager.ShowSoftInput(inputView, ShowFlags.Forced);
+ inputMethodManager.ToggleSoftInput(ShowFlags.Forced, HideSoftInputFlags.ImplicitOnly);
+ }
+ else
+ throw new ArgumentException("inputView should be of type EditText, SearchView, or TextView");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/LayoutExtensions.cs b/Xamarin.Forms.Platform.Android/LayoutExtensions.cs
new file mode 100644
index 00000000..90427b61
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/LayoutExtensions.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public static class LayoutExtensions
+ {
+ public static void Add(this IList<View> children, AView view, GetDesiredSizeDelegate getDesiredSizeDelegate = null, OnLayoutDelegate onLayoutDelegate = null,
+ OnMeasureDelegate onMeasureDelegate = null)
+ {
+ children.Add(view.ToView(getDesiredSizeDelegate, onLayoutDelegate, onMeasureDelegate));
+ }
+
+ public static View ToView(this AView view, GetDesiredSizeDelegate getDesiredSizeDelegate = null, OnLayoutDelegate onLayoutDelegate = null, OnMeasureDelegate onMeasureDelegate = null)
+ {
+ return new NativeViewWrapper(view, getDesiredSizeDelegate, onLayoutDelegate, onMeasureDelegate);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/MeasureSpecFactory.cs b/Xamarin.Forms.Platform.Android/MeasureSpecFactory.cs
new file mode 100644
index 00000000..9ab854c5
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/MeasureSpecFactory.cs
@@ -0,0 +1,20 @@
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal static class MeasureSpecFactory
+ {
+ public static int GetSize(int measureSpec)
+ {
+ const int modeMask = 0x3 << 30;
+ return measureSpec & ~modeMask;
+ }
+
+ // Literally does the same thing as the android code, 1000x faster because no bridge cross
+ // benchmarked by calling 1,000,000 times in a loop on actual device
+ public static int MakeMeasureSpec(int size, MeasureSpecMode mode)
+ {
+ return size + (int)mode;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/NativeViewWrapper.cs b/Xamarin.Forms.Platform.Android/NativeViewWrapper.cs
new file mode 100644
index 00000000..eecef9bc
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/NativeViewWrapper.cs
@@ -0,0 +1,22 @@
+namespace Xamarin.Forms.Platform.Android
+{
+ public class NativeViewWrapper : View
+ {
+ public NativeViewWrapper(global::Android.Views.View nativeView, GetDesiredSizeDelegate getDesiredSizeDelegate = null, OnLayoutDelegate onLayoutDelegate = null,
+ OnMeasureDelegate onMeasureDelegate = null)
+ {
+ GetDesiredSizeDelegate = getDesiredSizeDelegate;
+ NativeView = nativeView;
+ OnLayoutDelegate = onLayoutDelegate;
+ OnMeasureDelegate = onMeasureDelegate;
+ }
+
+ public GetDesiredSizeDelegate GetDesiredSizeDelegate { get; }
+
+ public global::Android.Views.View NativeView { get; }
+
+ public OnLayoutDelegate OnLayoutDelegate { get; }
+
+ public OnMeasureDelegate OnMeasureDelegate { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/NativeViewWrapperRenderer.cs b/Xamarin.Forms.Platform.Android/NativeViewWrapperRenderer.cs
new file mode 100644
index 00000000..933f436f
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/NativeViewWrapperRenderer.cs
@@ -0,0 +1,61 @@
+namespace Xamarin.Forms.Platform.Android
+{
+ public class NativeViewWrapperRenderer : ViewRenderer<NativeViewWrapper, global::Android.Views.View>
+ {
+ public override SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)
+ {
+ if (Element?.GetDesiredSizeDelegate == null)
+ return base.GetDesiredSize(widthConstraint, heightConstraint);
+
+ // The user has specified a different implementation of GetDesiredSizeDelegate
+ SizeRequest? result = Element.GetDesiredSizeDelegate(this, widthConstraint, heightConstraint);
+
+ // If the delegate returns a SizeRequest, we use it; if it returns null,
+ // fall back to the default implementation
+ return result ?? base.GetDesiredSize(widthConstraint, heightConstraint);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<NativeViewWrapper> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement == null)
+ {
+ SetNativeControl(Element.NativeView);
+ Control.LayoutChange += (sender, args) => Element?.InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ if (Element?.OnLayoutDelegate == null)
+ {
+ base.OnLayout(changed, l, t, r, b);
+ return;
+ }
+
+ // The user has specified a different implementation of OnLayout
+ bool handled = Element.OnLayoutDelegate(this, changed, l, t, r, b);
+
+ // If the delegate wasn't able to handle the request, fall back to the default implementation
+ if (!handled)
+ base.OnLayout(changed, l, t, r, b);
+ }
+
+ protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
+ {
+ if (Element?.OnMeasureDelegate == null)
+ {
+ base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
+ return;
+ }
+
+ // The user has specified a different implementation of OnMeasure
+ bool handled = Element.OnMeasureDelegate(this, widthMeasureSpec, heightMeasureSpec);
+
+ // If the delegate wasn't able to handle the request, fall back to the default implementation
+ if (!handled)
+ base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/OnLayoutDelegate.cs b/Xamarin.Forms.Platform.Android/OnLayoutDelegate.cs
new file mode 100644
index 00000000..bf5170d4
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/OnLayoutDelegate.cs
@@ -0,0 +1,4 @@
+namespace Xamarin.Forms.Platform.Android
+{
+ public delegate bool OnLayoutDelegate(NativeViewWrapperRenderer renderer, bool changed, int l, int t, int r, int b);
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/OnMeasureDelegate.cs b/Xamarin.Forms.Platform.Android/OnMeasureDelegate.cs
new file mode 100644
index 00000000..48502d23
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/OnMeasureDelegate.cs
@@ -0,0 +1,4 @@
+namespace Xamarin.Forms.Platform.Android
+{
+ public delegate bool OnMeasureDelegate(NativeViewWrapperRenderer renderer, int widthMeasureSpec, int heightMeasureSpec);
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/PanGestureHandler.cs b/Xamarin.Forms.Platform.Android/PanGestureHandler.cs
new file mode 100644
index 00000000..a552964c
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/PanGestureHandler.cs
@@ -0,0 +1,69 @@
+using System;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class PanGestureHandler
+ {
+ readonly Func<double, double> _pixelTranslation;
+
+ public PanGestureHandler(Func<View> getView, Func<double, double> pixelTranslation)
+ {
+ _pixelTranslation = pixelTranslation;
+ GetView = getView;
+ }
+
+ Func<View> GetView { get; }
+
+ public bool OnPan(float x, float y, int pointerCount)
+ {
+ View view = GetView();
+
+ if (view == null)
+ return false;
+
+ var result = false;
+ foreach (PanGestureRecognizer panGesture in
+ view.GestureRecognizers.GetGesturesFor<PanGestureRecognizer>(g => g.TouchPoints == pointerCount))
+ {
+ ((IPanGestureController)panGesture).SendPan(view, _pixelTranslation(x), _pixelTranslation(y), Application.Current.PanGestureId);
+ result = true;
+ }
+
+ return result;
+ }
+
+ public bool OnPanComplete()
+ {
+ View view = GetView();
+
+ if (view == null)
+ return false;
+
+ var result = false;
+ foreach (PanGestureRecognizer panGesture in view.GestureRecognizers.GetGesturesFor<PanGestureRecognizer>())
+ {
+ ((IPanGestureController)panGesture).SendPanCompleted(view, Application.Current.PanGestureId);
+ result = true;
+ }
+ Application.Current.PanGestureId++;
+ return result;
+ }
+
+ public bool OnPanStarted(int pointerCount)
+ {
+ View view = GetView();
+
+ if (view == null)
+ return false;
+
+ var result = false;
+ foreach (PanGestureRecognizer panGesture in
+ view.GestureRecognizers.GetGesturesFor<PanGestureRecognizer>(g => g.TouchPoints == pointerCount))
+ {
+ ((IPanGestureController)panGesture).SendPanStarted(view, Application.Current.PanGestureId);
+ result = true;
+ }
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/PinchGestureHandler.cs b/Xamarin.Forms.Platform.Android/PinchGestureHandler.cs
new file mode 100644
index 00000000..bc06531c
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/PinchGestureHandler.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Linq;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class PinchGestureHandler
+ {
+ double _pinchStartingScale = 1;
+
+ public PinchGestureHandler(Func<View> getView)
+ {
+ GetView = getView;
+ }
+
+ public bool IsPinchSupported
+ {
+ get
+ {
+ View view = GetView();
+ return view != null && view.GestureRecognizers.GetGesturesFor<PinchGestureRecognizer>().Any();
+ }
+ }
+
+ Func<View> GetView { get; }
+
+ // A View can have at most one pinch gesture, so we just need to look for one (or none)
+ PinchGestureRecognizer PinchGesture => GetView()?.GestureRecognizers.GetGesturesFor<PinchGestureRecognizer>().FirstOrDefault();
+
+ public bool OnPinch(float scale, Point scalePoint)
+ {
+ View view = GetView();
+
+ if (view == null)
+ return false;
+
+ PinchGestureRecognizer pinchGesture = PinchGesture;
+ if (pinchGesture == null)
+ return true;
+
+ var scalePointTransformed = new Point(scalePoint.X / view.Width, scalePoint.Y / view.Height);
+ ((IPinchGestureController)pinchGesture).SendPinch(view, 1 + (scale - 1) * _pinchStartingScale, scalePointTransformed);
+
+ return true;
+ }
+
+ public void OnPinchEnded()
+ {
+ View view = GetView();
+
+ if (view == null)
+ return;
+
+ PinchGestureRecognizer pinchGesture = PinchGesture;
+ ((IPinchGestureController)pinchGesture)?.SendPinchEnded(view);
+ }
+
+ public bool OnPinchStarted(Point scalePoint)
+ {
+ View view = GetView();
+
+ if (view == null)
+ return false;
+
+ PinchGestureRecognizer pinchGesture = PinchGesture;
+ if (pinchGesture == null)
+ return false;
+
+ _pinchStartingScale = view.Scale;
+
+ var scalePointTransformed = new Point(scalePoint.X / view.Width, scalePoint.Y / view.Height);
+
+ ((IPinchGestureController)pinchGesture).SendPinchStarted(view, scalePointTransformed);
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Platform.cs b/Xamarin.Forms.Platform.Android/Platform.cs
new file mode 100644
index 00000000..1de13b41
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Platform.cs
@@ -0,0 +1,1056 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading.Tasks;
+using Android.App;
+using Android.Content;
+using Android.Content.Res;
+using Android.Graphics;
+using Android.Graphics.Drawables;
+using Android.Support.V4.App;
+using Android.Util;
+using Android.Views;
+using Android.Widget;
+using Xamarin.Forms.Platform.Android.AppCompat;
+using FragmentManager = Android.Support.V4.App.FragmentManager;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class Platform : BindableObject, IPlatform, INavigation, IDisposable, IPlatformLayout
+ {
+ internal const string CloseContextActionsSignalName = "Xamarin.CloseContextActions";
+
+ internal static readonly BindableProperty RendererProperty = BindableProperty.CreateAttached("Renderer", typeof(IVisualElementRenderer), typeof(Platform), default(IVisualElementRenderer),
+ propertyChanged: (bindable, oldvalue, newvalue) =>
+ {
+ var view = bindable as VisualElement;
+ if (view != null)
+ view.IsPlatformEnabled = newvalue != null;
+ });
+
+ internal static readonly BindableProperty PageContextProperty = BindableProperty.CreateAttached("PageContext", typeof(Context), typeof(Platform), null);
+
+ readonly Context _context;
+
+ readonly PlatformRenderer _renderer;
+ readonly ToolbarTracker _toolbarTracker = new ToolbarTracker();
+
+ NavigationPage _currentNavigationPage;
+
+ TabbedPage _currentTabbedPage;
+
+ Color _defaultActionBarTitleTextColor;
+
+ bool _disposed;
+
+ bool _ignoreAndroidSelection;
+
+ Page _navigationPageCurrentPage;
+ NavigationModel _navModel = new NavigationModel();
+
+ internal Platform(Context context)
+ {
+ _context = context;
+
+ _defaultActionBarTitleTextColor = SetDefaultActionBarTitleTextColor();
+
+ _renderer = new PlatformRenderer(context, this);
+
+ FormsApplicationActivity.BackPressed += HandleBackPressed;
+
+ _toolbarTracker.CollectionChanged += ToolbarTrackerOnCollectionChanged;
+ }
+
+ #region IPlatform implementation
+
+ internal Page Page { get; private set; }
+
+ #endregion
+
+ ActionBar ActionBar
+ {
+ get { return ((Activity)_context).ActionBar; }
+ }
+
+ MasterDetailPage CurrentMasterDetailPage { get; set; }
+
+ NavigationPage CurrentNavigationPage
+ {
+ get { return _currentNavigationPage; }
+ set
+ {
+ if (_currentNavigationPage == value)
+ return;
+
+ if (_currentNavigationPage != null)
+ {
+ _currentNavigationPage.Pushed -= CurrentNavigationPageOnPushed;
+ _currentNavigationPage.Popped -= CurrentNavigationPageOnPopped;
+ _currentNavigationPage.PoppedToRoot -= CurrentNavigationPageOnPoppedToRoot;
+ _currentNavigationPage.PropertyChanged -= CurrentNavigationPageOnPropertyChanged;
+ }
+
+ RegisterNavPageCurrent(null);
+
+ _currentNavigationPage = value;
+
+ if (_currentNavigationPage != null)
+ {
+ _currentNavigationPage.Pushed += CurrentNavigationPageOnPushed;
+ _currentNavigationPage.Popped += CurrentNavigationPageOnPopped;
+ _currentNavigationPage.PoppedToRoot += CurrentNavigationPageOnPoppedToRoot;
+ _currentNavigationPage.PropertyChanged += CurrentNavigationPageOnPropertyChanged;
+ RegisterNavPageCurrent(_currentNavigationPage.CurrentPage);
+ }
+
+ UpdateActionBarBackgroundColor();
+ UpdateActionBarTextColor();
+ UpdateActionBarUpImageColor();
+ UpdateActionBarTitle();
+ }
+ }
+
+ TabbedPage CurrentTabbedPage
+ {
+ get { return _currentTabbedPage; }
+ set
+ {
+ if (_currentTabbedPage == value)
+ return;
+
+ if (_currentTabbedPage != null)
+ {
+ _currentTabbedPage.PagesChanged -= CurrentTabbedPageChildrenChanged;
+ _currentTabbedPage.PropertyChanged -= CurrentTabbedPageOnPropertyChanged;
+
+ if (value == null)
+ ActionBar.RemoveAllTabs();
+ }
+
+ _currentTabbedPage = value;
+
+ if (_currentTabbedPage != null)
+ {
+ _currentTabbedPage.PagesChanged += CurrentTabbedPageChildrenChanged;
+ _currentTabbedPage.PropertyChanged += CurrentTabbedPageOnPropertyChanged;
+ }
+
+ UpdateActionBarTitle();
+
+ ActionBar.NavigationMode = value == null ? ActionBarNavigationMode.Standard : ActionBarNavigationMode.Tabs;
+ CurrentTabbedPageChildrenChanged(null, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ }
+ }
+
+ ActionBarDrawerToggle MasterDetailPageToggle { get; set; }
+
+ void IDisposable.Dispose()
+ {
+ if (_disposed)
+ return;
+ _disposed = true;
+
+ SetPage(null);
+
+ FormsApplicationActivity.BackPressed -= HandleBackPressed;
+ _toolbarTracker.CollectionChanged -= ToolbarTrackerOnCollectionChanged;
+ _toolbarTracker.Target = null;
+
+ CurrentNavigationPage = null;
+ CurrentMasterDetailPage = null;
+ CurrentTabbedPage = null;
+ }
+
+ void INavigation.InsertPageBefore(Page page, Page before)
+ {
+ throw new InvalidOperationException("InsertPageBefore is not supported globally on Android, please use a NavigationPage.");
+ }
+
+ IReadOnlyList<Page> INavigation.ModalStack => _navModel.Modals.ToList();
+
+ IReadOnlyList<Page> INavigation.NavigationStack => new List<Page>();
+
+ Task<Page> INavigation.PopAsync()
+ {
+ return ((INavigation)this).PopAsync(true);
+ }
+
+ Task<Page> INavigation.PopAsync(bool animated)
+ {
+ throw new InvalidOperationException("PopAsync is not supported globally on Android, please use a NavigationPage.");
+ }
+
+ Task<Page> INavigation.PopModalAsync()
+ {
+ return ((INavigation)this).PopModalAsync(true);
+ }
+
+ Task<Page> INavigation.PopModalAsync(bool animated)
+ {
+ Page modal = _navModel.PopModal();
+
+ modal.SendDisappearing();
+ var source = new TaskCompletionSource<Page>();
+
+ IVisualElementRenderer modalRenderer = GetRenderer(modal);
+ if (modalRenderer != null)
+ {
+ if (animated)
+ {
+ modalRenderer.ViewGroup.Animate().Alpha(0).ScaleX(0.8f).ScaleY(0.8f).SetDuration(250).SetListener(new GenericAnimatorListener
+ {
+ OnEnd = a =>
+ {
+ modalRenderer.ViewGroup.RemoveFromParent();
+ modalRenderer.Dispose();
+ source.TrySetResult(modal);
+ _navModel.CurrentPage?.SendAppearing();
+ }
+ });
+ }
+ else
+ {
+ modalRenderer.ViewGroup.RemoveFromParent();
+ modalRenderer.Dispose();
+ source.TrySetResult(modal);
+ _navModel.CurrentPage?.SendAppearing();
+ }
+ }
+
+ _toolbarTracker.Target = _navModel.Roots.Last();
+ UpdateActionBar();
+
+ return source.Task;
+ }
+
+ Task INavigation.PopToRootAsync()
+ {
+ return ((INavigation)this).PopToRootAsync(true);
+ }
+
+ Task INavigation.PopToRootAsync(bool animated)
+ {
+ throw new InvalidOperationException("PopToRootAsync is not supported globally on Android, please use a NavigationPage.");
+ }
+
+ Task INavigation.PushAsync(Page root)
+ {
+ return ((INavigation)this).PushAsync(root, true);
+ }
+
+ Task INavigation.PushAsync(Page root, bool animated)
+ {
+ throw new InvalidOperationException("PushAsync is not supported globally on Android, please use a NavigationPage.");
+ }
+
+ Task INavigation.PushModalAsync(Page modal)
+ {
+ return ((INavigation)this).PushModalAsync(modal, true);
+ }
+
+ async Task INavigation.PushModalAsync(Page modal, bool animated)
+ {
+ _navModel.CurrentPage?.SendDisappearing();
+
+ _navModel.PushModal(modal);
+
+ modal.Platform = this;
+
+ await PresentModal(modal, animated);
+
+ // Verify that the modal is still on the stack
+ if (_navModel.CurrentPage == modal)
+ modal.SendAppearing();
+
+ _toolbarTracker.Target = _navModel.Roots.Last();
+
+ UpdateActionBar();
+ }
+
+ void INavigation.RemovePage(Page page)
+ {
+ throw new InvalidOperationException("RemovePage is not supported globally on Android, please use a NavigationPage.");
+ }
+
+ public static IVisualElementRenderer CreateRenderer(VisualElement element)
+ {
+ UpdateGlobalContext(element);
+
+ IVisualElementRenderer renderer = Registrar.Registered.GetHandler<IVisualElementRenderer>(element.GetType()) ?? new DefaultRenderer();
+ renderer.SetElement(element);
+
+ return renderer;
+ }
+
+ public static IVisualElementRenderer GetRenderer(VisualElement bindable)
+ {
+ return (IVisualElementRenderer)bindable.GetValue(RendererProperty);
+ }
+
+ public static void SetRenderer(VisualElement bindable, IVisualElementRenderer value)
+ {
+ bindable.SetValue(RendererProperty, value);
+ }
+
+ public void UpdateActionBarTextColor()
+ {
+ SetActionBarTextColor();
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ SetInheritedBindingContext(Page, BindingContext);
+
+ base.OnBindingContextChanged();
+ }
+
+ internal static IVisualElementRenderer CreateRenderer(VisualElement element, FragmentManager fragmentManager)
+ {
+ UpdateGlobalContext(element);
+
+ IVisualElementRenderer renderer = Registrar.Registered.GetHandler<IVisualElementRenderer>(element.GetType()) ?? new DefaultRenderer();
+
+ var managesFragments = renderer as IManageFragments;
+ managesFragments?.SetFragmentManager(fragmentManager);
+
+ renderer.SetElement(element);
+
+ return renderer;
+ }
+
+ internal static Context GetPageContext(BindableObject bindable)
+ {
+ return (Context)bindable.GetValue(PageContextProperty);
+ }
+
+ internal ViewGroup GetViewGroup()
+ {
+ return _renderer;
+ }
+
+ internal void PrepareMenu(IMenu menu)
+ {
+ foreach (ToolbarItem item in _toolbarTracker.ToolbarItems)
+ item.PropertyChanged -= HandleToolbarItemPropertyChanged;
+ menu.Clear();
+
+ if (!ShouldShowActionBarTitleArea())
+ return;
+
+ foreach (ToolbarItem item in _toolbarTracker.ToolbarItems)
+ {
+ item.PropertyChanged += HandleToolbarItemPropertyChanged;
+ if (item.Order == ToolbarItemOrder.Secondary)
+ {
+ IMenuItem menuItem = menu.Add(item.Text);
+ menuItem.SetEnabled(item.IsEnabled);
+ menuItem.SetOnMenuItemClickListener(new GenericMenuClickListener(item.Activate));
+ }
+ else
+ {
+ IMenuItem menuItem = menu.Add(item.Text);
+ if (!string.IsNullOrEmpty(item.Icon))
+ {
+ Drawable iconBitmap = _context.Resources.GetDrawable(item.Icon);
+ if (iconBitmap != null)
+ menuItem.SetIcon(iconBitmap);
+ }
+ menuItem.SetEnabled(item.IsEnabled);
+ menuItem.SetShowAsAction(ShowAsAction.Always);
+ menuItem.SetOnMenuItemClickListener(new GenericMenuClickListener(item.Activate));
+ }
+ }
+ }
+
+ internal async void SendHomeClicked()
+ {
+ if (UpButtonShouldNavigate())
+ {
+ if (NavAnimationInProgress)
+ return;
+ NavAnimationInProgress = true;
+ await CurrentNavigationPage.PopAsync();
+ NavAnimationInProgress = false;
+ }
+ else if (CurrentMasterDetailPage != null)
+ {
+ if (CurrentMasterDetailPage.ShouldShowSplitMode && CurrentMasterDetailPage.IsPresented)
+ return;
+ CurrentMasterDetailPage.IsPresented = !CurrentMasterDetailPage.IsPresented;
+ }
+ }
+
+ internal void SetPage(Page newRoot)
+ {
+ var layout = false;
+ if (Page != null)
+ {
+ _renderer.RemoveAllViews();
+
+ foreach (IVisualElementRenderer rootRenderer in _navModel.Roots.Select(GetRenderer))
+ rootRenderer.Dispose();
+ _navModel = new NavigationModel();
+
+ layout = true;
+ }
+
+ if (newRoot == null)
+ return;
+
+ _navModel.Push(newRoot, null);
+
+ Page = newRoot;
+ Page.Platform = this;
+ AddChild(Page, layout);
+
+ ((Application)Page.RealParent).NavigationProxy.Inner = this;
+
+ _toolbarTracker.Target = newRoot;
+
+ UpdateActionBar();
+ }
+
+ internal static void SetPageContext(BindableObject bindable, Context context)
+ {
+ bindable.SetValue(PageContextProperty, context);
+ }
+
+ internal void UpdateActionBar()
+ {
+ List<Page> relevantAncestors = AncestorPagesOfPage(_navModel.CurrentPage);
+
+ IEnumerable<NavigationPage> navPages = relevantAncestors.OfType<NavigationPage>();
+ if (navPages.Count() > 1)
+ throw new Exception("Android only allows one navigation page on screen at a time");
+ NavigationPage navPage = navPages.FirstOrDefault();
+
+ IEnumerable<TabbedPage> tabbedPages = relevantAncestors.OfType<TabbedPage>();
+ if (tabbedPages.Count() > 1)
+ throw new Exception("Android only allows one tabbed page on screen at a time");
+ TabbedPage tabbedPage = tabbedPages.FirstOrDefault();
+
+ CurrentMasterDetailPage = relevantAncestors.OfType<MasterDetailPage>().FirstOrDefault();
+ CurrentNavigationPage = navPage;
+ CurrentTabbedPage = tabbedPage;
+
+ if (navPage != null && navPage.CurrentPage == null)
+ {
+ throw new InvalidOperationException("NavigationPage must have a root Page before being used. Either call PushAsync with a valid Page, or pass a Page to the constructor before usage.");
+ }
+
+ UpdateActionBarTitle();
+
+ if (ShouldShowActionBarTitleArea() || tabbedPage != null)
+ ShowActionBar();
+ else
+ HideActionBar();
+ UpdateMasterDetailToggle();
+ }
+
+ internal void UpdateActionBarBackgroundColor()
+ {
+ if (!((Activity)_context).ActionBar.IsShowing)
+ return;
+ Color colorToUse = Color.Default;
+ if (CurrentNavigationPage != null)
+ {
+#pragma warning disable 618
+ if (CurrentNavigationPage.Tint != Color.Default)
+ colorToUse = CurrentNavigationPage.Tint;
+#pragma warning restore 618
+ else if (CurrentNavigationPage.BarBackgroundColor != Color.Default)
+ colorToUse = CurrentNavigationPage.BarBackgroundColor;
+ }
+ using(Drawable drawable = colorToUse == Color.Default ? GetActionBarBackgroundDrawable() : new ColorDrawable(colorToUse.ToAndroid()))
+ ((Activity)_context).ActionBar.SetBackgroundDrawable(drawable);
+ }
+
+ internal void UpdateMasterDetailToggle(bool update = false)
+ {
+ if (CurrentMasterDetailPage == null)
+ {
+ if (MasterDetailPageToggle == null)
+ return;
+ // clear out the icon
+ ClearMasterDetailToggle();
+ return;
+ }
+ if (!CurrentMasterDetailPage.ShouldShowToolbarButton() || string.IsNullOrEmpty(CurrentMasterDetailPage.Master.Icon) ||
+ (CurrentMasterDetailPage.ShouldShowSplitMode && CurrentMasterDetailPage.IsPresented))
+ {
+ //clear out existing icon;
+ ClearMasterDetailToggle();
+ return;
+ }
+
+ if (MasterDetailPageToggle == null || update)
+ {
+ ClearMasterDetailToggle();
+ GetNewMasterDetailToggle();
+ }
+
+ bool state;
+ if (CurrentNavigationPage == null)
+ state = true;
+ else
+ state = !UpButtonShouldNavigate();
+ if (state == MasterDetailPageToggle.DrawerIndicatorEnabled)
+ return;
+ MasterDetailPageToggle.DrawerIndicatorEnabled = state;
+ MasterDetailPageToggle.SyncState();
+ }
+
+ internal void UpdateNavigationTitleBar()
+ {
+ UpdateActionBarTitle();
+ UpdateActionBar();
+ UpdateActionBarUpImageColor();
+ }
+
+ void AddChild(VisualElement view, bool layout = false)
+ {
+ if (GetRenderer(view) != null)
+ return;
+
+ SetPageContext(view, _context);
+ IVisualElementRenderer renderView = CreateRenderer(view);
+ SetRenderer(view, renderView);
+
+ if (layout)
+ view.Layout(new Rectangle(0, 0, _context.FromPixels(_renderer.Width), _context.FromPixels(_renderer.Height)));
+
+ _renderer.AddView(renderView.ViewGroup);
+ }
+
+ ActionBar.Tab AddTab(Page page, int index)
+ {
+ ActionBar actionBar = ((Activity)_context).ActionBar;
+ TabbedPage currentTabs = CurrentTabbedPage;
+
+ ActionBar.Tab atab = actionBar.NewTab();
+ atab.SetText(page.Title);
+ atab.TabSelected += (sender, e) =>
+ {
+ if (!_ignoreAndroidSelection)
+ currentTabs.CurrentPage = page;
+ };
+ actionBar.AddTab(atab, index);
+
+ page.PropertyChanged += PagePropertyChanged;
+ return atab;
+ }
+
+ List<Page> AncestorPagesOfPage(Page root)
+ {
+ var result = new List<Page>();
+ if (root == null)
+ return result;
+
+ if (root is IPageContainer<Page>)
+ {
+ var navPage = (IPageContainer<Page>)root;
+ result.AddRange(AncestorPagesOfPage(navPage.CurrentPage));
+ }
+ else if (root is MasterDetailPage)
+ result.AddRange(AncestorPagesOfPage(((MasterDetailPage)root).Detail));
+ else
+ {
+ foreach (Page page in root.InternalChildren.OfType<Page>())
+ result.AddRange(AncestorPagesOfPage(page));
+ }
+
+ result.Add(root);
+ return result;
+ }
+
+ void ClearMasterDetailToggle()
+ {
+ if (MasterDetailPageToggle == null)
+ return;
+
+ MasterDetailPageToggle.DrawerIndicatorEnabled = false;
+ MasterDetailPageToggle.SyncState();
+ MasterDetailPageToggle.Dispose();
+ MasterDetailPageToggle = null;
+ }
+
+ void CurrentNavigationPageOnPopped(object sender, NavigationEventArgs eventArg)
+ {
+ UpdateNavigationTitleBar();
+ }
+
+ void CurrentNavigationPageOnPoppedToRoot(object sender, EventArgs eventArgs)
+ {
+ UpdateNavigationTitleBar();
+ }
+
+ void CurrentNavigationPageOnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == NavigationPage.TintProperty.PropertyName)
+ UpdateActionBarBackgroundColor();
+ else if (e.PropertyName == NavigationPage.BarBackgroundColorProperty.PropertyName)
+ UpdateActionBarBackgroundColor();
+ else if (e.PropertyName == NavigationPage.BarTextColorProperty.PropertyName)
+ {
+ UpdateActionBarTextColor();
+ UpdateActionBarUpImageColor();
+ }
+ else if (e.PropertyName == NavigationPage.CurrentPageProperty.PropertyName)
+ RegisterNavPageCurrent(CurrentNavigationPage.CurrentPage);
+ }
+
+ void CurrentNavigationPageOnPushed(object sender, NavigationEventArgs eventArg)
+ {
+ UpdateNavigationTitleBar();
+ }
+
+ void CurrentTabbedPageChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ if (CurrentTabbedPage == null)
+ return;
+
+ _ignoreAndroidSelection = true;
+
+ e.Apply((o, index, create) => AddTab((Page)o, index), (o, index) => RemoveTab((Page)o, index), Reset);
+
+ if (CurrentTabbedPage.CurrentPage != null)
+ {
+ Page page = CurrentTabbedPage.CurrentPage;
+ int index = TabbedPage.GetIndex(page);
+ if (index >= 0 && index < CurrentTabbedPage.Children.Count)
+ ActionBar.GetTabAt(index).Select();
+ }
+
+ _ignoreAndroidSelection = false;
+ }
+
+ void CurrentTabbedPageOnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName != "CurrentPage")
+ return;
+
+ UpdateActionBar();
+
+ // If we switch tabs while pushing a new page, UpdateActionBar() can set currentTabbedPage to null
+ if (_currentTabbedPage == null)
+ return;
+
+ NavAnimationInProgress = true;
+
+ Page page = _currentTabbedPage.CurrentPage;
+ if (page == null)
+ {
+ ActionBar.SelectTab(null);
+ NavAnimationInProgress = false;
+ return;
+ }
+
+ int index = TabbedPage.GetIndex(page);
+ if (ActionBar.SelectedNavigationIndex == index || index >= ActionBar.NavigationItemCount)
+ {
+ NavAnimationInProgress = false;
+ return;
+ }
+
+ ActionBar.SelectTab(ActionBar.GetTabAt(index));
+
+ NavAnimationInProgress = false;
+ }
+
+ Drawable GetActionBarBackgroundDrawable()
+ {
+ int[] backgroundDataArray = { global::Android.Resource.Attribute.Background };
+
+ using(var outVal = new TypedValue())
+ {
+ _context.Theme.ResolveAttribute(global::Android.Resource.Attribute.ActionBarStyle, outVal, true);
+ TypedArray actionBarStyle = _context.Theme.ObtainStyledAttributes(outVal.ResourceId, backgroundDataArray);
+
+ Drawable result = actionBarStyle.GetDrawable(0);
+ actionBarStyle.Recycle();
+ return result;
+ }
+ }
+
+ void GetNewMasterDetailToggle()
+ {
+ int icon = ResourceManager.GetDrawableByName(CurrentMasterDetailPage.Master.Icon);
+ var drawer = GetRenderer(CurrentMasterDetailPage) as MasterDetailRenderer;
+ if (drawer == null)
+ return;
+ MasterDetailPageToggle = new ActionBarDrawerToggle(_context as Activity, drawer, icon, 0, 0);
+ MasterDetailPageToggle.SyncState();
+ }
+
+ bool HandleBackPressed(object sender, EventArgs e)
+ {
+ if (NavAnimationInProgress)
+ return true;
+
+ Page root = _navModel.Roots.Last();
+ bool handled = root.SendBackButtonPressed();
+
+ return handled;
+ }
+
+ void HandleToolbarItemPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == MenuItem.IsEnabledProperty.PropertyName)
+ (_context as Activity).InvalidateOptionsMenu();
+ else if (e.PropertyName == MenuItem.TextProperty.PropertyName)
+ (_context as Activity).InvalidateOptionsMenu();
+ else if (e.PropertyName == MenuItem.IconProperty.PropertyName)
+ (_context as Activity).InvalidateOptionsMenu();
+ }
+
+ void HideActionBar()
+ {
+ ReloadToolbarItems();
+ UpdateActionBarHomeAsUp(ActionBar);
+ ActionBar.Hide();
+ }
+
+ void NavigationPageCurrentPageOnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == NavigationPage.HasNavigationBarProperty.PropertyName)
+ UpdateActionBar();
+ else if (e.PropertyName == Page.TitleProperty.PropertyName)
+ UpdateActionBarTitle();
+ }
+
+ void PagePropertyChanged(object sender, PropertyChangedEventArgs args)
+ {
+ if (args.PropertyName == Page.TitleProperty.PropertyName)
+ {
+ ActionBar actionBar = ((Activity)_context).ActionBar;
+ TabbedPage currentTabs = CurrentTabbedPage;
+
+ if (currentTabs == null || actionBar.TabCount == 0)
+ return;
+
+ var page = sender as Page;
+ ActionBar.Tab atab = actionBar.GetTabAt(currentTabs.Children.IndexOf(page));
+ atab.SetText(page.Title);
+ }
+ }
+
+ Task PresentModal(Page modal, bool animated)
+ {
+ IVisualElementRenderer modalRenderer = GetRenderer(modal);
+ if (modalRenderer == null)
+ {
+ SetPageContext(modal, _context);
+ modalRenderer = CreateRenderer(modal);
+ SetRenderer(modal, modalRenderer);
+
+ if (modal.BackgroundColor == Color.Default && modal.BackgroundImage == null)
+ modalRenderer.ViewGroup.SetWindowBackground();
+ }
+ modalRenderer.Element.Layout(new Rectangle(0, 0, _context.FromPixels(_renderer.Width), _context.FromPixels(_renderer.Height)));
+ _renderer.AddView(modalRenderer.ViewGroup);
+
+ var source = new TaskCompletionSource<bool>();
+ NavAnimationInProgress = true;
+ if (animated)
+ {
+ modalRenderer.ViewGroup.Alpha = 0;
+ modalRenderer.ViewGroup.ScaleX = 0.8f;
+ modalRenderer.ViewGroup.ScaleY = 0.8f;
+ modalRenderer.ViewGroup.Animate().Alpha(1).ScaleX(1).ScaleY(1).SetDuration(250).SetListener(new GenericAnimatorListener
+ {
+ OnEnd = a =>
+ {
+ source.TrySetResult(false);
+ NavAnimationInProgress = false;
+ },
+ OnCancel = a =>
+ {
+ source.TrySetResult(true);
+ NavAnimationInProgress = false;
+ }
+ });
+ }
+ else
+ {
+ NavAnimationInProgress = false;
+ source.TrySetResult(true);
+ }
+
+ return source.Task;
+ }
+
+ void RegisterNavPageCurrent(Page page)
+ {
+ if (_navigationPageCurrentPage != null)
+ _navigationPageCurrentPage.PropertyChanged -= NavigationPageCurrentPageOnPropertyChanged;
+
+ _navigationPageCurrentPage = page;
+
+ if (_navigationPageCurrentPage != null)
+ _navigationPageCurrentPage.PropertyChanged += NavigationPageCurrentPageOnPropertyChanged;
+ }
+
+ void ReloadToolbarItems()
+ {
+ var activity = (Activity)_context;
+ activity.InvalidateOptionsMenu();
+ }
+
+ void RemoveTab(Page page, int index)
+ {
+ ActionBar actionBar = ((Activity)_context).ActionBar;
+ page.PropertyChanged -= PagePropertyChanged;
+ actionBar.RemoveTabAt(index);
+ }
+
+ void Reset()
+ {
+ ActionBar.RemoveAllTabs();
+
+ if (CurrentTabbedPage == null)
+ return;
+
+ var i = 0;
+ foreach (Page tab in CurrentTabbedPage.Children.OfType<Page>())
+ {
+ ActionBar.Tab realTab = AddTab(tab, i++);
+ if (tab == CurrentTabbedPage.CurrentPage)
+ realTab.Select();
+ }
+ }
+
+ void SetActionBarTextColor()
+ {
+ Color navigationBarTextColor = CurrentNavigationPage == null ? Color.Default : CurrentNavigationPage.BarTextColor;
+ TextView actionBarTitleTextView = null;
+
+ int actionBarTitleId = _context.Resources.GetIdentifier("action_bar_title", "id", "android");
+ if (actionBarTitleId > 0)
+ actionBarTitleTextView = ((Activity)_context).FindViewById<TextView>(actionBarTitleId);
+
+ if (actionBarTitleTextView != null && navigationBarTextColor != Color.Default)
+ actionBarTitleTextView.SetTextColor(navigationBarTextColor.ToAndroid());
+ else if (actionBarTitleTextView != null && navigationBarTextColor == Color.Default)
+ actionBarTitleTextView.SetTextColor(_defaultActionBarTitleTextColor.ToAndroid());
+ }
+
+ Color SetDefaultActionBarTitleTextColor()
+ {
+ var defaultTitleTextColor = new Color();
+
+ TextView actionBarTitleTextView = null;
+
+ int actionBarTitleId = _context.Resources.GetIdentifier("action_bar_title", "id", "android");
+ if (actionBarTitleId > 0)
+ actionBarTitleTextView = ((Activity)_context).FindViewById<TextView>(actionBarTitleId);
+
+ if (actionBarTitleTextView != null)
+ {
+ ColorStateList defaultTitleColorList = actionBarTitleTextView.TextColors;
+ string defaultColorHex = defaultTitleColorList.DefaultColor.ToString("X");
+ defaultTitleTextColor = Color.FromHex(defaultColorHex);
+ }
+
+ return defaultTitleTextColor;
+ }
+
+ bool ShouldShowActionBarTitleArea()
+ {
+ if (Forms.TitleBarVisibility == AndroidTitleBarVisibility.Never)
+ return false;
+
+ bool hasMasterDetailPage = CurrentMasterDetailPage != null;
+ bool navigated = CurrentNavigationPage != null && CurrentNavigationPage.StackDepth > 1;
+ bool navigationPageHasNavigationBar = CurrentNavigationPage != null && NavigationPage.GetHasNavigationBar(CurrentNavigationPage.CurrentPage);
+ return navigationPageHasNavigationBar || (hasMasterDetailPage && !navigated);
+ }
+
+ bool ShouldUpdateActionBarUpColor()
+ {
+ bool hasMasterDetailPage = CurrentMasterDetailPage != null;
+ bool navigated = CurrentNavigationPage != null && CurrentNavigationPage.StackDepth > 1;
+ return (hasMasterDetailPage && navigated) || !hasMasterDetailPage;
+ }
+
+ void ShowActionBar()
+ {
+ ReloadToolbarItems();
+ UpdateActionBarHomeAsUp(ActionBar);
+ ActionBar.Show();
+ UpdateActionBarBackgroundColor();
+ UpdateActionBarTextColor();
+ }
+
+ void ToolbarTrackerOnCollectionChanged(object sender, EventArgs eventArgs)
+ {
+ ReloadToolbarItems();
+ }
+
+ bool UpButtonShouldNavigate()
+ {
+ if (CurrentNavigationPage == null)
+ return false;
+
+ bool pagePushed = CurrentNavigationPage.StackDepth > 1;
+ bool pushedPageHasBackButton = NavigationPage.GetHasBackButton(CurrentNavigationPage.CurrentPage);
+
+ return pagePushed && pushedPageHasBackButton;
+ }
+
+ void UpdateActionBarHomeAsUp(ActionBar actionBar)
+ {
+ bool showHomeAsUp = ShouldShowActionBarTitleArea() && (CurrentMasterDetailPage != null || UpButtonShouldNavigate());
+ actionBar.SetDisplayHomeAsUpEnabled(showHomeAsUp);
+ }
+
+ void UpdateActionBarTitle()
+ {
+ Page view = null;
+ if (CurrentNavigationPage != null)
+ view = CurrentNavigationPage.CurrentPage;
+ else if (CurrentTabbedPage != null)
+ view = CurrentTabbedPage.CurrentPage;
+
+ if (view == null)
+ return;
+
+ ActionBar actionBar = ((Activity)_context).ActionBar;
+
+ var useLogo = false;
+ var showHome = false;
+ var showTitle = false;
+
+ if (ShouldShowActionBarTitleArea())
+ {
+ actionBar.Title = view.Title;
+ FileImageSource titleIcon = NavigationPage.GetTitleIcon(view);
+ if (!string.IsNullOrWhiteSpace(titleIcon))
+ {
+ actionBar.SetLogo(_context.Resources.GetDrawable(titleIcon));
+ useLogo = true;
+ showHome = true;
+ showTitle = true;
+ }
+ else
+ {
+ showHome = true;
+ showTitle = true;
+ }
+ }
+
+ ActionBarDisplayOptions options = 0;
+ if (useLogo)
+ options = options | ActionBarDisplayOptions.UseLogo;
+ if (showHome)
+ options = options | ActionBarDisplayOptions.ShowHome;
+ if (showTitle)
+ options = options | ActionBarDisplayOptions.ShowTitle;
+ actionBar.SetDisplayOptions(options, ActionBarDisplayOptions.UseLogo | ActionBarDisplayOptions.ShowTitle | ActionBarDisplayOptions.ShowHome);
+
+ UpdateActionBarHomeAsUp(actionBar);
+ }
+
+ void UpdateActionBarUpImageColor()
+ {
+ Color navigationBarTextColor = CurrentNavigationPage == null ? Color.Default : CurrentNavigationPage.BarTextColor;
+ ImageView actionBarUpImageView = null;
+
+ int actionBarUpId = _context.Resources.GetIdentifier("up", "id", "android");
+ if (actionBarUpId > 0)
+ actionBarUpImageView = ((Activity)_context).FindViewById<ImageView>(actionBarUpId);
+
+ if (actionBarUpImageView != null && navigationBarTextColor != Color.Default)
+ {
+ if (ShouldUpdateActionBarUpColor())
+ actionBarUpImageView.SetColorFilter(navigationBarTextColor.ToAndroid(), PorterDuff.Mode.SrcIn);
+ else
+ actionBarUpImageView.SetColorFilter(null);
+ }
+ else if (actionBarUpImageView != null && navigationBarTextColor == Color.Default)
+ actionBarUpImageView.SetColorFilter(null);
+ }
+
+ static void UpdateGlobalContext(VisualElement view)
+ {
+ Element parent = view;
+ while (!Application.IsApplicationOrNull(parent.RealParent))
+ parent = parent.RealParent;
+
+ var rootPage = parent as Page;
+ if (rootPage != null)
+ {
+ Context context = GetPageContext(rootPage);
+ if (context != null)
+ Forms.Context = context;
+ }
+ }
+
+ internal class DefaultRenderer : VisualElementRenderer<View>
+ {
+ }
+
+ #region IPlatformEngine implementation
+
+ void IPlatformLayout.OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ if (changed)
+ {
+ // ActionBar title text color resets on rotation, make sure to update
+ UpdateActionBarTextColor();
+ foreach (Page modal in _navModel.Roots.ToList())
+ modal.Layout(new Rectangle(0, 0, _context.FromPixels(r - l), _context.FromPixels(b - t)));
+ }
+
+ foreach (IVisualElementRenderer view in _navModel.Roots.Select(GetRenderer))
+ view.UpdateLayout();
+ }
+
+ SizeRequest IPlatform.GetNativeSize(VisualElement view, double widthConstraint, double heightConstraint)
+ {
+ Performance.Start();
+
+ // FIXME: potential crash
+ IVisualElementRenderer viewRenderer = GetRenderer(view);
+
+ // negative numbers have special meanings to android they don't to us
+ widthConstraint = widthConstraint <= -1 ? double.PositiveInfinity : _context.ToPixels(widthConstraint);
+ heightConstraint = heightConstraint <= -1 ? double.PositiveInfinity : _context.ToPixels(heightConstraint);
+
+ int width = !double.IsPositiveInfinity(widthConstraint)
+ ? MeasureSpecFactory.MakeMeasureSpec((int)widthConstraint, MeasureSpecMode.AtMost)
+ : MeasureSpecFactory.MakeMeasureSpec(0, MeasureSpecMode.Unspecified);
+
+ int height = !double.IsPositiveInfinity(heightConstraint)
+ ? MeasureSpecFactory.MakeMeasureSpec((int)heightConstraint, MeasureSpecMode.AtMost)
+ : MeasureSpecFactory.MakeMeasureSpec(0, MeasureSpecMode.Unspecified);
+
+ SizeRequest rawResult = viewRenderer.GetDesiredSize(width, height);
+ if (rawResult.Minimum == Size.Zero)
+ rawResult.Minimum = rawResult.Request;
+ var result = new SizeRequest(new Size(_context.FromPixels(rawResult.Request.Width), _context.FromPixels(rawResult.Request.Height)),
+ new Size(_context.FromPixels(rawResult.Minimum.Width), _context.FromPixels(rawResult.Minimum.Height)));
+
+ Performance.Stop();
+ return result;
+ }
+
+ bool _navAnimationInProgress;
+
+ internal bool NavAnimationInProgress
+ {
+ get { return _navAnimationInProgress; }
+ set
+ {
+ if (_navAnimationInProgress == value)
+ return;
+ _navAnimationInProgress = value;
+ if (value)
+ MessagingCenter.Send(this, CloseContextActionsSignalName);
+ }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/PlatformEffect.cs b/Xamarin.Forms.Platform.Android/PlatformEffect.cs
new file mode 100644
index 00000000..6830b722
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/PlatformEffect.cs
@@ -0,0 +1,9 @@
+using Android.Views;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public abstract class PlatformEffect : PlatformEffect<ViewGroup, AView>
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/PlatformRenderer.cs b/Xamarin.Forms.Platform.Android/PlatformRenderer.cs
new file mode 100644
index 00000000..4fbc0293
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/PlatformRenderer.cs
@@ -0,0 +1,81 @@
+using System;
+using Android.App;
+using Android.Content;
+using Android.Views;
+using Android.Widget;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class PlatformRenderer : ViewGroup
+ {
+ readonly IPlatformLayout _canvas;
+ Point _downPosition;
+
+ DateTime _downTime;
+
+ public PlatformRenderer(Context context, IPlatformLayout canvas) : base(context)
+ {
+ _canvas = canvas;
+ Focusable = true;
+ FocusableInTouchMode = true;
+ }
+
+ public override bool DispatchTouchEvent(MotionEvent e)
+ {
+ if (e.Action == MotionEventActions.Down)
+ {
+ _downTime = DateTime.UtcNow;
+ _downPosition = new Point(e.RawX, e.RawY);
+ }
+
+ if (e.Action != MotionEventActions.Up)
+ return base.DispatchTouchEvent(e);
+
+ global::Android.Views.View currentView = ((Activity)Context).CurrentFocus;
+ bool result = base.DispatchTouchEvent(e);
+
+ do
+ {
+ if (!(currentView is EditText))
+ break;
+
+ global::Android.Views.View newCurrentView = ((Activity)Context).CurrentFocus;
+
+ if (currentView != newCurrentView)
+ break;
+
+ double distance = _downPosition.Distance(new Point(e.RawX, e.RawY));
+
+ if (distance > Context.ToPixels(20) || DateTime.UtcNow - _downTime > TimeSpan.FromMilliseconds(200))
+ break;
+
+ var location = new int[2];
+ currentView.GetLocationOnScreen(location);
+
+ float x = e.RawX + currentView.Left - location[0];
+ float y = e.RawY + currentView.Top - location[1];
+
+ var rect = new Rectangle(currentView.Left, currentView.Top, currentView.Width, currentView.Height);
+
+ if (rect.Contains(x, y))
+ break;
+
+ Context.HideKeyboard(currentView);
+ RequestFocus();
+ } while (false);
+
+ return result;
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ SetMeasuredDimension(r - l, b - t);
+ _canvas?.OnLayout(changed, l, t, r, b);
+ }
+
+ protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
+ {
+ SetMeasuredDimension(MeasureSpec.GetSize(widthMeasureSpec), MeasureSpec.GetSize(heightMeasureSpec));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Properties/AssemblyInfo.cs b/Xamarin.Forms.Platform.Android/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..03f4fa6a
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Properties/AssemblyInfo.cs
@@ -0,0 +1,65 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.Android;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("Xamarin.Forms.Platform.Android")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCulture("")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Platform")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
+#if ROOT_RENDERERS
+[assembly: ExportRenderer (typeof (BoxView), typeof (BoxRenderer))]
+[assembly: ExportRenderer (typeof (Entry), typeof (EntryRenderer))]
+[assembly: ExportRenderer (typeof (Editor), typeof (EditorRenderer))]
+[assembly: ExportRenderer (typeof (Label), typeof (LabelRenderer))]
+[assembly: ExportRenderer (typeof (Image), typeof (ImageRenderer))]
+[assembly: ExportRenderer (typeof (Button), typeof (ButtonRenderer))]
+[assembly: ExportRenderer (typeof (TableView), typeof (TableViewRenderer))]
+[assembly: ExportRenderer (typeof (ListView), typeof (ListViewRenderer))]
+[assembly: ExportRenderer (typeof (Slider), typeof (SliderRenderer))]
+[assembly: ExportRenderer (typeof (WebView), typeof (WebViewRenderer))]
+[assembly: ExportRenderer (typeof (SearchBar), typeof (SearchBarRenderer))]
+[assembly: ExportRenderer (typeof (Switch), typeof (SwitchRenderer))]
+[assembly: ExportRenderer (typeof (DatePicker), typeof (DatePickerRenderer))]
+[assembly: ExportRenderer (typeof (TimePicker), typeof (TimePickerRenderer))]
+[assembly: ExportRenderer (typeof (Picker), typeof (PickerRenderer))]
+[assembly: ExportRenderer (typeof (Stepper), typeof (StepperRenderer))]
+[assembly: ExportRenderer (typeof (ProgressBar), typeof (ProgressBarRenderer))]
+[assembly: ExportRenderer (typeof (ScrollView), typeof (ScrollViewRenderer))]
+[assembly: ExportRenderer (typeof (Toolbar), typeof (ToolbarRenderer))]
+[assembly: ExportRenderer (typeof (ActivityIndicator), typeof (ActivityIndicatorRenderer))]
+[assembly: ExportRenderer (typeof (Frame), typeof (FrameRenderer))]
+[assembly: ExportRenderer (typeof (NavigationMenu), typeof (NavigationMenuRenderer))]
+[assembly: ExportRenderer (typeof (OpenGLView), typeof (OpenGLViewRenderer))]
+
+[assembly: ExportRenderer (typeof (TabbedPage), typeof (TabbedRenderer))]
+[assembly: ExportRenderer (typeof (NavigationPage), typeof (NavigationRenderer))]
+[assembly: ExportRenderer (typeof (CarouselPage), typeof (CarouselPageRenderer))]
+[assembly: ExportRenderer (typeof (Page), typeof (PageRenderer))]
+[assembly: ExportRenderer (typeof (MasterDetailPage), typeof (MasterDetailRenderer))]
+#endif
+
+[assembly: ExportRenderer(typeof(NativeViewWrapper), typeof(NativeViewWrapperRenderer))]
+[assembly: ExportCell(typeof(Cell), typeof(CellRenderer))]
+[assembly: ExportCell(typeof(EntryCell), typeof(EntryCellRenderer))]
+[assembly: ExportCell(typeof(SwitchCell), typeof(SwitchCellRenderer))]
+[assembly: ExportCell(typeof(TextCell), typeof(TextCellRenderer))]
+[assembly: ExportCell(typeof(ImageCell), typeof(ImageCellRenderer))]
+[assembly: ExportCell(typeof(ViewCell), typeof(ViewCellRenderer))]
+[assembly: ExportImageSourceHandler(typeof(FileImageSource), typeof(FileImageSourceHandler))]
+[assembly: ExportImageSourceHandler(typeof(StreamImageSource), typeof(StreamImagesourceHandler))]
+[assembly: ExportImageSourceHandler(typeof(UriImageSource), typeof(ImageLoaderSourceHandler))]
+[assembly: Xamarin.Forms.Dependency(typeof(Deserializer))]
+[assembly: Xamarin.Forms.Dependency(typeof(ResourcesProvider))]
+[assembly: Preserve] \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/RendererFactory.cs b/Xamarin.Forms.Platform.Android/RendererFactory.cs
new file mode 100644
index 00000000..7d0b03b3
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/RendererFactory.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public static class RendererFactory
+ {
+ [Obsolete("Use Platform.CreateRenderer")]
+ public static IVisualElementRenderer GetRenderer(VisualElement view)
+ {
+ return Platform.CreateRenderer(view);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/RendererPool.cs b/Xamarin.Forms.Platform.Android/RendererPool.cs
new file mode 100644
index 00000000..95a28778
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/RendererPool.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public sealed class RendererPool
+ {
+ readonly Dictionary<Type, Stack<IVisualElementRenderer>> _freeRenderers = new Dictionary<Type, Stack<IVisualElementRenderer>>();
+
+ readonly VisualElement _oldElement;
+
+ readonly IVisualElementRenderer _parent;
+
+ public RendererPool(IVisualElementRenderer renderer, VisualElement oldElement)
+ {
+ if (renderer == null)
+ throw new ArgumentNullException("renderer");
+
+ if (oldElement == null)
+ throw new ArgumentNullException("oldElement");
+
+ _oldElement = oldElement;
+ _parent = renderer;
+ }
+
+ public void ClearChildrenRenderers()
+ {
+ if (_parent.Element.LogicalChildren.Count == 0)
+ return;
+ ClearChildrenRenderers(_oldElement);
+ }
+
+ public IVisualElementRenderer GetFreeRenderer(VisualElement view)
+ {
+ if (view == null)
+ throw new ArgumentNullException("view");
+
+ Type rendererType = Registrar.Registered.GetHandlerType(view.GetType()) ?? typeof(ViewRenderer);
+
+ Stack<IVisualElementRenderer> renderers;
+ if (!_freeRenderers.TryGetValue(rendererType, out renderers) || renderers.Count == 0)
+ return null;
+
+ IVisualElementRenderer renderer = renderers.Pop();
+ renderer.SetElement(view);
+ return renderer;
+ }
+
+ void ClearChildrenRenderers(VisualElement view)
+ {
+ if (view == null)
+ return;
+
+ foreach (Element logicalChild in view.LogicalChildren)
+ {
+ var child = logicalChild as VisualElement;
+ if (child != null)
+ {
+ IVisualElementRenderer renderer = Platform.GetRenderer(child);
+ if (renderer == null)
+ continue;
+
+ if (renderer.ViewGroup.Parent != _parent.ViewGroup)
+ continue;
+
+ renderer.ViewGroup.RemoveFromParent();
+
+ Platform.SetRenderer(child, null);
+ PushRenderer(renderer);
+ }
+ }
+
+ if (_parent.ViewGroup.ChildCount != 0)
+ _parent.ViewGroup.RemoveAllViews();
+ }
+
+ void PushRenderer(IVisualElementRenderer renderer)
+ {
+ Type rendererType = renderer.GetType();
+
+ Stack<IVisualElementRenderer> renderers;
+ if (!_freeRenderers.TryGetValue(rendererType, out renderers))
+ _freeRenderers[rendererType] = renderers = new Stack<IVisualElementRenderer>();
+
+ renderers.Push(renderer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/AHorizontalScrollView.cs b/Xamarin.Forms.Platform.Android/Renderers/AHorizontalScrollView.cs
new file mode 100644
index 00000000..6a64a35b
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/AHorizontalScrollView.cs
@@ -0,0 +1,62 @@
+using Android.Content;
+using Android.Views;
+using Android.Widget;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class AHorizontalScrollView : HorizontalScrollView
+ {
+ readonly ScrollViewRenderer _renderer;
+
+ public AHorizontalScrollView(Context context, ScrollViewRenderer renderer) : base(context)
+ {
+ _renderer = renderer;
+ }
+
+ internal bool IsBidirectional { get; set; }
+
+ public override bool OnInterceptTouchEvent(MotionEvent ev)
+ {
+ // set the start point for the bidirectional scroll;
+ // Down is swallowed by other controls, so we'll just sneak this in here without actually preventing
+ // other controls from getting the event.
+ if (IsBidirectional && ev.Action == MotionEventActions.Down)
+ {
+ _renderer.LastY = ev.RawY;
+ _renderer.LastX = ev.RawX;
+ }
+
+ return base.OnInterceptTouchEvent(ev);
+ }
+
+ public override bool OnTouchEvent(MotionEvent ev)
+ {
+ // The nested ScrollViews will allow us to scroll EITHER vertically OR horizontally in a single gesture.
+ // This will allow us to also scroll diagonally.
+ // We'll fall through to the base event so we still get the fling from the ScrollViews.
+ // We have to do this in both ScrollViews, since a single gesture will be owned by one or the other, depending
+ // on the initial direction of movement (i.e., horizontal/vertical).
+ if (IsBidirectional)
+ {
+ float dX = _renderer.LastX - ev.RawX;
+ float dY = _renderer.LastY - ev.RawY;
+ _renderer.LastY = ev.RawY;
+ _renderer.LastX = ev.RawX;
+ if (ev.Action == MotionEventActions.Move)
+ {
+ var parent = (global::Android.Widget.ScrollView)Parent;
+ parent.ScrollBy(0, (int)dY);
+ ScrollBy((int)dX, 0);
+ }
+ }
+ return base.OnTouchEvent(ev);
+ }
+
+ protected override void OnScrollChanged(int l, int t, int oldl, int oldt)
+ {
+ base.OnScrollChanged(l, t, oldl, oldt);
+
+ _renderer.UpdateScrollPosition(Forms.Context.FromPixels(l), Forms.Context.FromPixels(t));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ActionSheetRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/ActionSheetRenderer.cs
new file mode 100644
index 00000000..ca51a709
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ActionSheetRenderer.cs
@@ -0,0 +1,83 @@
+using System;
+using Android.App;
+using Android.Graphics;
+using Android.OS;
+using Android.Views;
+using Android.Widget;
+using AButton = Android.Widget.Button;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ [Obsolete("ActionSheet now uses default implementation.")]
+ public class ActionSheetRenderer : Dialog, AView.IOnClickListener
+ {
+ readonly ActionSheetArguments _arguments;
+ readonly LinearLayout _layout;
+
+ internal ActionSheetRenderer(ActionSheetArguments actionSheetArguments) : base(Forms.Context)
+ {
+ _arguments = actionSheetArguments;
+ _layout = new LinearLayout(Context);
+ }
+
+ void AView.IOnClickListener.OnClick(AView v)
+ {
+ var button = (AButton)v;
+ _arguments.SetResult(button.Text);
+ Hide();
+ }
+
+ public override void Cancel()
+ {
+ base.Cancel();
+ _arguments.SetResult(null);
+ }
+
+ public override void OnAttachedToWindow()
+ {
+ base.OnAttachedToWindow();
+ Window.SetGravity(GravityFlags.CenterVertical);
+ Window.SetLayout(-1, -2);
+ }
+
+ protected override void OnCreate(Bundle savedInstanceState)
+ {
+ base.OnCreate(savedInstanceState);
+
+ SetCanceledOnTouchOutside(true);
+
+ _layout.Orientation = Orientation.Vertical;
+
+ using(var layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.FillParent))
+ SetContentView(_layout, layoutParams);
+
+ if (_arguments.Destruction != null)
+ {
+ AButton destruct = AddButton(_arguments.Destruction);
+ destruct.Background.SetColorFilter(new Color(1, 0, 0, 1).ToAndroid(), PorterDuff.Mode.Multiply);
+ }
+
+ foreach (string button in _arguments.Buttons)
+ AddButton(button);
+
+ if (_arguments.Cancel != null)
+ {
+ AButton cancel = AddButton(_arguments.Cancel);
+ cancel.Background.SetColorFilter(new Color(0.5, 0.5, 0.5, 1).ToAndroid(), PorterDuff.Mode.Multiply);
+ }
+
+ SetTitle(_arguments.Title);
+ }
+
+ AButton AddButton(string name)
+ {
+ var button = new AButton(Context) { Text = name };
+ button.SetOnClickListener(this);
+
+ _layout.AddView(button);
+
+ return button;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ActivityIndicatorRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/ActivityIndicatorRenderer.cs
new file mode 100644
index 00000000..e2314c61
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ActivityIndicatorRenderer.cs
@@ -0,0 +1,59 @@
+using System.ComponentModel;
+using Android.Graphics;
+using Android.OS;
+using Android.Views;
+using AProgressBar = Android.Widget.ProgressBar;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class ActivityIndicatorRenderer : ViewRenderer<ActivityIndicator, AProgressBar>
+ {
+ public ActivityIndicatorRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<ActivityIndicator> e)
+ {
+ base.OnElementChanged(e);
+
+ AProgressBar progressBar = Control;
+ if (progressBar == null)
+ {
+ progressBar = new AProgressBar(Context) { Indeterminate = true };
+ SetNativeControl(progressBar);
+ }
+
+ UpdateColor();
+ UpdateVisibility();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == ActivityIndicator.IsRunningProperty.PropertyName)
+ UpdateVisibility();
+ else if (e.PropertyName == ActivityIndicator.ColorProperty.PropertyName)
+ UpdateColor();
+ }
+
+ void UpdateColor()
+ {
+ if (Build.VERSION.SdkInt < BuildVersionCodes.Lollipop)
+ return;
+
+ Color color = Element.Color;
+
+ if (!color.IsDefault)
+ Control.IndeterminateDrawable.SetColorFilter(color.ToAndroid(), PorterDuff.Mode.SrcIn);
+ else
+ Control.IndeterminateDrawable.ClearColorFilter();
+ }
+
+ void UpdateVisibility()
+ {
+ Control.Visibility = Element.IsRunning ? ViewStates.Visible : ViewStates.Invisible;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/AlignmentExtensions.cs b/Xamarin.Forms.Platform.Android/Renderers/AlignmentExtensions.cs
new file mode 100644
index 00000000..dd05f166
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/AlignmentExtensions.cs
@@ -0,0 +1,33 @@
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal static class AlignmentExtensions
+ {
+ internal static GravityFlags ToHorizontalGravityFlags(this TextAlignment alignment)
+ {
+ switch (alignment)
+ {
+ case TextAlignment.Center:
+ return GravityFlags.CenterHorizontal;
+ case TextAlignment.End:
+ return GravityFlags.Right;
+ default:
+ return GravityFlags.Left;
+ }
+ }
+
+ internal static GravityFlags ToVerticalGravityFlags(this TextAlignment alignment)
+ {
+ switch (alignment)
+ {
+ case TextAlignment.Start:
+ return GravityFlags.Top;
+ case TextAlignment.End:
+ return GravityFlags.Bottom;
+ default:
+ return GravityFlags.CenterVertical;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/BoxRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/BoxRenderer.cs
new file mode 100644
index 00000000..725829f4
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/BoxRenderer.cs
@@ -0,0 +1,43 @@
+using System.ComponentModel;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class BoxRenderer : VisualElementRenderer<BoxView>
+ {
+ public BoxRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ public override bool OnTouchEvent(MotionEvent e)
+ {
+ base.OnTouchEvent(e);
+ return !Element.InputTransparent;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e)
+ {
+ base.OnElementChanged(e);
+ UpdateBackgroundColor();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == BoxView.ColorProperty.PropertyName || e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackgroundColor();
+ }
+
+ void UpdateBackgroundColor()
+ {
+ Color colorToSet = Element.Color;
+
+ if (colorToSet == Color.Default)
+ colorToSet = Element.BackgroundColor;
+
+ SetBackgroundColor(colorToSet.ToAndroid(Color.Transparent));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ButtonDrawable.cs b/Xamarin.Forms.Platform.Android/Renderers/ButtonDrawable.cs
new file mode 100644
index 00000000..f25f9301
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ButtonDrawable.cs
@@ -0,0 +1,150 @@
+using System.Linq;
+using Android.Graphics;
+using Android.Graphics.Drawables;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class ButtonDrawable : Drawable
+ {
+ bool _isDisposed;
+ Bitmap _normalBitmap;
+ bool _pressed;
+ Bitmap _pressedBitmap;
+
+ public ButtonDrawable()
+ {
+ _pressed = false;
+ }
+
+ public Button Button { get; set; }
+
+ public override bool IsStateful
+ {
+ get { return true; }
+ }
+
+ public override int Opacity
+ {
+ get { return 0; }
+ }
+
+ public override void Draw(Canvas canvas)
+ {
+ int width = Bounds.Width();
+ int height = Bounds.Height();
+
+ if (width <= 0 || height <= 0)
+ return;
+
+ if (_normalBitmap == null || _normalBitmap.Height != height || _normalBitmap.Width != width)
+ {
+ Reset();
+
+ _normalBitmap = CreateBitmap(false, width, height);
+ _pressedBitmap = CreateBitmap(true, width, height);
+ }
+
+ Bitmap bitmap = GetState().Contains(global::Android.Resource.Attribute.StatePressed) ? _pressedBitmap : _normalBitmap;
+ canvas.DrawBitmap(bitmap, 0, 0, new Paint());
+ }
+
+ public void Reset()
+ {
+ if (_normalBitmap != null)
+ {
+ _normalBitmap.Recycle();
+ _normalBitmap.Dispose();
+ _normalBitmap = null;
+ }
+
+ if (_pressedBitmap != null)
+ {
+ _pressedBitmap.Recycle();
+ _pressedBitmap.Dispose();
+ _pressedBitmap = null;
+ }
+ }
+
+ public override void SetAlpha(int alpha)
+ {
+ }
+
+ public override void SetColorFilter(ColorFilter cf)
+ {
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (_isDisposed)
+ return;
+
+ _isDisposed = true;
+
+ if (disposing)
+ Reset();
+
+ base.Dispose(disposing);
+ }
+
+ protected override bool OnStateChange(int[] state)
+ {
+ bool old = _pressed;
+ _pressed = state.Contains(global::Android.Resource.Attribute.StatePressed);
+ if (_pressed != old)
+ {
+ InvalidateSelf();
+ return true;
+ }
+ return false;
+ }
+
+ Bitmap CreateBitmap(bool pressed, int width, int height)
+ {
+ Bitmap bitmap = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888);
+ using(var canvas = new Canvas(bitmap))
+ {
+ DrawBackground(canvas, width, height, pressed);
+ DrawOutline(canvas, width, height);
+ }
+
+ return bitmap;
+ }
+
+ void DrawBackground(Canvas canvas, int width, int height, bool pressed)
+ {
+ var paint = new Paint { AntiAlias = true };
+ var path = new Path();
+
+ float borderRadius = Forms.Context.ToPixels(Button.BorderRadius);
+
+ path.AddRoundRect(new RectF(0, 0, width, height), borderRadius, borderRadius, Path.Direction.Cw);
+
+ paint.Color = pressed ? Button.BackgroundColor.AddLuminosity(-0.1).ToAndroid() : Button.BackgroundColor.ToAndroid();
+ paint.SetStyle(Paint.Style.Fill);
+ canvas.DrawPath(path, paint);
+ }
+
+ void DrawOutline(Canvas canvas, int width, int height)
+ {
+ if (Button.BorderWidth <= 0)
+ return;
+
+ using(var paint = new Paint { AntiAlias = true })
+ using(var path = new Path())
+ {
+ float borderWidth = Forms.Context.ToPixels(Button.BorderWidth);
+ float inset = borderWidth / 2;
+
+ // adjust border radius so outer edge of stroke is same radius as border radius of background
+ float borderRadius = Forms.Context.ToPixels(Button.BorderRadius) - inset;
+
+ path.AddRoundRect(new RectF(inset, inset, width - inset, height - inset), borderRadius, borderRadius, Path.Direction.Cw);
+ paint.StrokeWidth = borderWidth;
+ paint.SetStyle(Paint.Style.Stroke);
+ paint.Color = Button.BorderColor.ToAndroid();
+
+ canvas.DrawPath(path, paint);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ButtonRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/ButtonRenderer.cs
new file mode 100644
index 00000000..eb9b884f
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ButtonRenderer.cs
@@ -0,0 +1,252 @@
+using System;
+using System.ComponentModel;
+using Android.Content.Res;
+using Android.Graphics;
+using Android.Graphics.Drawables;
+using Android.Util;
+using AButton = Android.Widget.Button;
+using AView = Android.Views.View;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class ButtonRenderer : ViewRenderer<Button, AButton>, AView.IOnAttachStateChangeListener
+ {
+ ButtonDrawable _backgroundDrawable;
+ ColorStateList _buttonDefaulTextColors;
+ Drawable _defaultDrawable;
+ float _defaultFontSize;
+ Typeface _defaultTypeface;
+ bool _drawableEnabled;
+
+ bool _isDisposed;
+
+ public ButtonRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ AButton NativeButton
+ {
+ get { return Control; }
+ }
+
+ public void OnViewAttachedToWindow(AView attachedView)
+ {
+ UpdateText();
+ }
+
+ public void OnViewDetachedFromWindow(AView detachedView)
+ {
+ }
+
+ public override SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)
+ {
+ UpdateText();
+ return base.GetDesiredSize(widthConstraint, heightConstraint);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (_isDisposed)
+ return;
+
+ _isDisposed = true;
+
+ if (disposing)
+ {
+ if (_backgroundDrawable != null)
+ {
+ _backgroundDrawable.Dispose();
+ _backgroundDrawable = null;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement == null)
+ {
+ AButton button = Control;
+ if (button == null)
+ {
+ button = new AButton(Context);
+ button.SetOnClickListener(ButtonClickListener.Instance.Value);
+ button.Tag = this;
+ SetNativeControl(button);
+
+ button.AddOnAttachStateChangeListener(this);
+ }
+ }
+ else
+ {
+ if (_drawableEnabled)
+ {
+ _drawableEnabled = false;
+ _backgroundDrawable.Reset();
+ _backgroundDrawable = null;
+ }
+ }
+
+ UpdateAll();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Button.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Button.TextColorProperty.PropertyName)
+ UpdateTextColor();
+ else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ UpdateEnabled();
+ else if (e.PropertyName == Button.FontProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateDrawable();
+ else if (e.PropertyName == Button.ImageProperty.PropertyName)
+ UpdateBitmap();
+ else if (e.PropertyName == VisualElement.IsVisibleProperty.PropertyName)
+ UpdateText();
+
+ if (_drawableEnabled &&
+ (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName || e.PropertyName == Button.BorderColorProperty.PropertyName || e.PropertyName == Button.BorderRadiusProperty.PropertyName ||
+ e.PropertyName == Button.BorderWidthProperty.PropertyName))
+ {
+ _backgroundDrawable.Reset();
+ Control.Invalidate();
+ }
+
+ base.OnElementPropertyChanged(sender, e);
+ }
+
+ protected override void UpdateBackgroundColor()
+ {
+ // Do nothing, the drawable handles this now
+ }
+
+ void UpdateAll()
+ {
+ UpdateFont();
+ UpdateText();
+ UpdateBitmap();
+ UpdateTextColor();
+ UpdateEnabled();
+ UpdateDrawable();
+ }
+
+ async void UpdateBitmap()
+ {
+ if (Element.Image != null && !string.IsNullOrEmpty(Element.Image.File))
+ {
+ Drawable image = Context.Resources.GetDrawable(Element.Image.File);
+ Control.SetCompoundDrawablesWithIntrinsicBounds(image, null, null, null);
+ if (image != null)
+ image.Dispose();
+ }
+ else
+ Control.SetCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
+ }
+
+ void UpdateDrawable()
+ {
+ if (Element.BackgroundColor == Color.Default)
+ {
+ if (!_drawableEnabled)
+ return;
+
+ if (_defaultDrawable != null)
+ Control.SetBackgroundDrawable(_defaultDrawable);
+
+ _drawableEnabled = false;
+ }
+ else
+ {
+ if (_backgroundDrawable == null)
+ _backgroundDrawable = new ButtonDrawable();
+
+ _backgroundDrawable.Button = Element;
+
+ if (_drawableEnabled)
+ return;
+
+ if (_defaultDrawable == null)
+ _defaultDrawable = Control.Background;
+
+ Control.SetBackgroundDrawable(_backgroundDrawable);
+ _drawableEnabled = true;
+ }
+
+ Control.Invalidate();
+ }
+
+ void UpdateEnabled()
+ {
+ Control.Enabled = Element.IsEnabled;
+ }
+
+ void UpdateFont()
+ {
+ Button button = Element;
+ if (button.Font == Font.Default && _defaultFontSize == 0f)
+ return;
+
+ if (_defaultFontSize == 0f)
+ {
+ _defaultTypeface = NativeButton.Typeface;
+ _defaultFontSize = NativeButton.TextSize;
+ }
+
+ if (button.Font == Font.Default)
+ {
+ NativeButton.Typeface = _defaultTypeface;
+ NativeButton.SetTextSize(ComplexUnitType.Px, _defaultFontSize);
+ }
+ else
+ {
+ NativeButton.Typeface = button.Font.ToTypeface();
+ NativeButton.SetTextSize(ComplexUnitType.Sp, button.Font.ToScaledPixel());
+ }
+ }
+
+ void UpdateText()
+ {
+ NativeButton.Text = Element.Text;
+ }
+
+ void UpdateTextColor()
+ {
+ Color color = Element.TextColor;
+
+ if (color.IsDefault)
+ {
+ if (_buttonDefaulTextColors == null)
+ return;
+
+ NativeButton.SetTextColor(_buttonDefaulTextColors);
+ }
+ else
+ {
+ _buttonDefaulTextColors = _buttonDefaulTextColors ?? Control.TextColors;
+
+ // Set the new enabled state color, preserving the default disabled state color
+ NativeButton.SetTextColor(color.ToAndroidPreserveDisabled(_buttonDefaulTextColors));
+ }
+ }
+
+ class ButtonClickListener : Object, IOnClickListener
+ {
+ public static readonly Lazy<ButtonClickListener> Instance = new Lazy<ButtonClickListener>(() => new ButtonClickListener());
+
+ public void OnClick(AView v)
+ {
+ var renderer = v.Tag as ButtonRenderer;
+ if (renderer != null)
+ ((IButtonController)renderer.Element).SendClicked();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/CarouselPageAdapter.cs b/Xamarin.Forms.Platform.Android/Renderers/CarouselPageAdapter.cs
new file mode 100644
index 00000000..345501d5
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/CarouselPageAdapter.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Collections.Specialized;
+using System.Linq;
+using Android.Content;
+using Android.Support.V4.View;
+using Android.Views;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class CarouselPageAdapter : PagerAdapter, ViewPager.IOnPageChangeListener
+ {
+ readonly Context _context;
+ readonly ViewPager _pager;
+ bool _ignoreAndroidSelection;
+ CarouselPage _page;
+
+ public CarouselPageAdapter(ViewPager pager, CarouselPage page, Context context)
+ {
+ _pager = pager;
+ _page = page;
+ _context = context;
+
+ page.PagesChanged += OnPagesChanged;
+ }
+
+ public override int Count
+ {
+ get { return _page.Children.Count(); }
+ }
+
+ public void OnPageScrolled(int position, float positionOffset, int positionOffsetPixels)
+ {
+ }
+
+ public void OnPageScrollStateChanged(int state)
+ {
+ }
+
+ public void OnPageSelected(int position)
+ {
+ if (_ignoreAndroidSelection)
+ return;
+
+ int currentItem = _pager.CurrentItem;
+ _page.CurrentPage = currentItem >= 0 && currentItem < _page.LogicalChildren.Count ? _page.LogicalChildren[currentItem] as ContentPage : null;
+ }
+
+ public override void DestroyItem(ViewGroup p0, int p1, Object p2)
+ {
+ var holder = (ObjectJavaBox<Tuple<ViewGroup, Page, int>>)p2;
+ Page destroyedPage = holder.Instance.Item2;
+
+ IVisualElementRenderer renderer = Platform.GetRenderer(destroyedPage);
+ renderer.ViewGroup.RemoveFromParent();
+ holder.Instance.Item1.RemoveFromParent();
+ }
+
+ public override int GetItemPosition(Object item)
+ {
+ // The int is the current index.
+ var holder = (ObjectJavaBox<Tuple<ViewGroup, Page, int>>)item;
+ Element parent = holder.Instance.Item2.RealParent;
+ if (parent == null)
+ return PositionNone;
+
+ // Unfortunately we can't just call CarouselPage.GetIndex, because we need to know
+ // if the item has been removed. We could update MultiPage<T> to set removed items' index
+ // to -1 to support this if it ever becomes an issue.
+ int index = ((CarouselPage)parent).Children.IndexOf(holder.Instance.Item2);
+ if (index == -1)
+ return PositionNone;
+
+ if (index != holder.Instance.Item3)
+ {
+ holder.Instance = new Tuple<ViewGroup, Page, int>(holder.Instance.Item1, holder.Instance.Item2, index);
+ return index;
+ }
+
+ return PositionUnchanged;
+ }
+
+ public override Object InstantiateItem(ViewGroup container, int position)
+ {
+ ContentPage child = _page.Children.ElementAt(position);
+ if (Platform.GetRenderer(child) == null)
+ Platform.SetRenderer(child, Platform.CreateRenderer(child));
+
+ IVisualElementRenderer renderer = Platform.GetRenderer(child);
+ renderer.ViewGroup.RemoveFromParent();
+
+ ViewGroup frame = new PageContainer(_context, renderer);
+
+ container.AddView(frame);
+
+ return new ObjectJavaBox<Tuple<ViewGroup, Page, int>>(new Tuple<ViewGroup, Page, int>(frame, child, position));
+ }
+
+ public override bool IsViewFromObject(global::Android.Views.View p0, Object p1)
+ {
+ var holder = (ObjectJavaBox<Tuple<ViewGroup, Page, int>>)p1;
+ ViewGroup frame = holder.Instance.Item1;
+ return p0 == frame;
+ }
+
+ public void UpdateCurrentItem()
+ {
+ if (_page.CurrentPage == null)
+ throw new InvalidOperationException("CarouselPage has no children.");
+
+ int index = CarouselPage.GetIndex(_page.CurrentPage);
+ if (index >= 0 && index < _page.Children.Count)
+ _pager.CurrentItem = index;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && _page != null)
+ {
+ foreach (Element element in _page.LogicalChildren)
+ {
+ var childPage = element as VisualElement;
+
+ if (childPage == null)
+ continue;
+
+ IVisualElementRenderer childPageRenderer = Platform.GetRenderer(childPage);
+ if (childPageRenderer != null)
+ {
+ childPageRenderer.ViewGroup.RemoveFromParent();
+ childPageRenderer.Dispose();
+ Platform.SetRenderer(childPage, null);
+ }
+ }
+ _page.PagesChanged -= OnPagesChanged;
+ _page = null;
+ }
+ base.Dispose(disposing);
+ }
+
+ void OnPagesChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ _ignoreAndroidSelection = true;
+
+ NotifyDataSetChanged();
+
+ _ignoreAndroidSelection = false;
+
+ if (_page.CurrentPage == null)
+ return;
+
+ UpdateCurrentItem();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/CarouselPageRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/CarouselPageRenderer.cs
new file mode 100644
index 00000000..1533005a
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/CarouselPageRenderer.cs
@@ -0,0 +1,100 @@
+using System.ComponentModel;
+using Android.Support.V4.View;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class CarouselPageRenderer : VisualElementRenderer<CarouselPage>
+ {
+ ViewPager _viewPager;
+
+ public CarouselPageRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && _viewPager != null)
+ {
+ if (_viewPager.Adapter != null)
+ _viewPager.Adapter.Dispose();
+ _viewPager.Dispose();
+ _viewPager = null;
+ }
+ base.Dispose(disposing);
+ }
+
+ protected override void OnAttachedToWindow()
+ {
+ base.OnAttachedToWindow();
+ var adapter = new CarouselPageAdapter(_viewPager, Element, Context);
+ _viewPager.Adapter = adapter;
+ _viewPager.SetOnPageChangeListener(adapter);
+
+ adapter.UpdateCurrentItem();
+
+ Element.SendAppearing();
+ }
+
+ protected override void OnDetachedFromWindow()
+ {
+ base.OnDetachedFromWindow();
+ Element.SendDisappearing();
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<CarouselPage> e)
+ {
+ base.OnElementChanged(e);
+
+ if (_viewPager != null)
+ {
+ RemoveView(_viewPager);
+ _viewPager.SetOnPageChangeListener(null);
+ _viewPager.Dispose();
+ }
+
+ _viewPager = new ViewPager(Context);
+
+ AddView(_viewPager);
+
+ _viewPager.OffscreenPageLimit = int.MaxValue;
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == "CurrentPage" && Element.CurrentPage != null)
+ {
+ if (!Element.Batched)
+ UpdateCurrentItem();
+ }
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ base.OnLayout(changed, l, t, r, b);
+ if (_viewPager != null)
+ {
+ _viewPager.Measure(MeasureSpecFactory.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly));
+ _viewPager.Layout(0, 0, r - l, b - t);
+ }
+ }
+
+ protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
+ {
+ _viewPager.Measure(widthMeasureSpec, heightMeasureSpec);
+ SetMeasuredDimension(_viewPager.MeasuredWidth, _viewPager.MeasuredHeight);
+ }
+
+ void UpdateCurrentItem()
+ {
+ int index = CarouselPage.GetIndex(Element.CurrentPage);
+ if (index < 0 || index >= Element.LogicalChildren.Count)
+ return;
+
+ _viewPager.CurrentItem = index;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/CarouselViewExtensions.cs b/Xamarin.Forms.Platform.Android/Renderers/CarouselViewExtensions.cs
new file mode 100644
index 00000000..6349b2b7
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/CarouselViewExtensions.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using Android.Content;
+using Android.Graphics;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal static class CarouselViewExtensions
+ {
+ internal static int Area(this System.Drawing.Rectangle rectangle)
+ {
+ return rectangle.Width * rectangle.Height;
+ }
+
+ internal static IntVector BoundTranslation(this System.Drawing.Rectangle viewport, IntVector delta, System.Drawing.Rectangle bound)
+ {
+ // TODO: generalize the math
+ Debug.Assert(delta.X == 0 || delta.Y == 0);
+
+ IntVector start = viewport.LeadingCorner(delta);
+ IntVector end = start + delta;
+ IntVector clampedEnd = end.Clamp(bound);
+ IntVector clampedDelta = clampedEnd - start;
+ return clampedDelta;
+ }
+
+ internal static IntVector Center(this System.Drawing.Rectangle rectangle)
+ {
+ return (IntVector)rectangle.Location + (IntVector)rectangle.Size / 2;
+ }
+
+ internal static IntVector Clamp(this IntVector position, System.Drawing.Rectangle bound)
+ {
+ return new IntVector(position.X.Clamp(bound.Left, bound.Right), position.Y.Clamp(bound.Top, bound.Bottom));
+ }
+
+ internal static IntVector LeadingCorner(this System.Drawing.Rectangle rectangle, IntVector delta)
+ {
+ return new IntVector(delta.X < 0 ? rectangle.Left : rectangle.Right, delta.Y < 0 ? rectangle.Top : rectangle.Bottom);
+ }
+
+ internal static bool LexicographicallyLess(this System.Drawing.Point source, System.Drawing.Point target)
+ {
+ if (source.X < target.X)
+ return true;
+
+ if (source.X > target.X)
+ return false;
+
+ return source.Y < target.Y;
+ }
+
+ internal static Rect ToAndroidRectangle(this System.Drawing.Rectangle rectangle)
+ {
+ return new Rect(rectangle.Left, right: rectangle.Right, top: rectangle.Top, bottom: rectangle.Bottom);
+ }
+
+ internal static Rectangle ToFormsRectangle(this System.Drawing.Rectangle rectangle, Context context)
+ {
+ return new Rectangle(context.FromPixels(rectangle.Left), context.FromPixels(rectangle.Top), context.FromPixels(rectangle.Width), context.FromPixels(rectangle.Height));
+ }
+
+ internal static int[] ToRange(this Tuple<int, int> startAndCount)
+ {
+ return Enumerable.Range(startAndCount.Item1, startAndCount.Item2).ToArray();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/CarouselViewRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/CarouselViewRenderer.cs
new file mode 100644
index 00000000..f63b6fd9
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/CarouselViewRenderer.cs
@@ -0,0 +1,353 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using Android.Support.V7.Widget;
+using AndroidListView = Android.Widget.ListView;
+using static System.Diagnostics.Debug;
+using Observer = Android.Support.V7.Widget.RecyclerView.AdapterDataObserver;
+using BclDebug = System.Diagnostics.Debug;
+using IntRectangle = System.Drawing.Rectangle;
+using IntSize = System.Drawing.Size;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class CarouselViewRenderer : ViewRenderer<CarouselView, RecyclerView>
+ {
+ PhysicalLayoutManager _physicalLayout;
+ int _position;
+
+ public CarouselViewRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ ItemViewAdapter Adapter
+ {
+ get { return (ItemViewAdapter)Control.GetAdapter(); }
+ }
+
+ new RecyclerView Control
+ {
+ get
+ {
+ Initialize();
+ return base.Control;
+ }
+ }
+
+ ICarouselViewController Controller => Element;
+
+ PhysicalLayoutManager LayoutManager
+ {
+ get { return (PhysicalLayoutManager)Control.GetLayoutManager(); }
+ }
+
+ protected override Size MinimumSize()
+ {
+ return new Size(40, 40);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<CarouselView> e)
+ {
+ CarouselView oldElement = e.OldElement;
+ if (oldElement != null)
+ e.OldElement.CollectionChanged -= OnCollectionChanged;
+
+ base.OnElementChanged(e);
+ Initialize();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "Position" && _position != Element.Position)
+ _physicalLayout.ScrollToPosition(Element.Position);
+
+ base.OnElementPropertyChanged(sender, e);
+ }
+
+ protected override void OnLayout(bool changed, int left, int top, int right, int bottom)
+ {
+ int width = right - left;
+ int height = bottom - top;
+
+ LayoutManager.Layout(width, height);
+
+ base.OnLayout(changed, left, top, right, bottom);
+
+ Control.Measure(new MeasureSpecification(width, MeasureSpecificationType.Exactly), new MeasureSpecification(height, MeasureSpecificationType.Exactly));
+
+ Control.Layout(0, 0, width, height);
+ }
+
+ void Initialize()
+ {
+ // cache hit? Check if the view page is already created
+ RecyclerView recyclerView = base.Control;
+ if (recyclerView != null)
+ return;
+
+ // cache miss
+ recyclerView = new RecyclerView(Context);
+ SetNativeControl(recyclerView);
+
+ // layoutManager
+ recyclerView.SetLayoutManager(_physicalLayout = new PhysicalLayoutManager(Context, new VirtualLayoutManager(), Element.Position));
+
+ // swiping
+ var dragging = false;
+ recyclerView.AddOnScrollListener(new OnScrollListener(onDragStart: () => dragging = true, onDragEnd: () =>
+ {
+ dragging = false;
+ IntVector velocity = _physicalLayout.Velocity;
+
+ int target = velocity.X > 0 ? _physicalLayout.VisiblePositions().Max() : _physicalLayout.VisiblePositions().Min();
+ _physicalLayout.ScrollToPosition(target);
+ }));
+
+ // scrolling
+ var scrolling = false;
+ _physicalLayout.OnBeginScroll += position => scrolling = true;
+ _physicalLayout.OnEndScroll += position => scrolling = false;
+
+ // appearing
+ _physicalLayout.OnAppearing += appearingPosition => { Controller.SendPositionAppearing(appearingPosition); };
+
+ // disappearing
+ _physicalLayout.OnDisappearing += disappearingPosition =>
+ {
+ Controller.SendPositionDisappearing(disappearingPosition);
+
+ // animation completed
+ if (!scrolling && !dragging)
+ {
+ _position = _physicalLayout.VisiblePositions().Single();
+
+ OnPositionChanged();
+ OnItemChanged();
+ }
+ };
+
+ // adapter
+ var adapter = new ItemViewAdapter(this);
+ adapter.RegisterAdapterDataObserver(new PositionUpdater(this));
+ recyclerView.SetAdapter(adapter);
+
+ // initialize properties
+ Element.Position = 0;
+
+ // initialize events
+ Element.CollectionChanged += OnCollectionChanged;
+ }
+
+ void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ Adapter.NotifyItemRangeInserted(e.NewStartingIndex, e.NewItems.Count);
+ break;
+
+ case NotifyCollectionChangedAction.Move:
+ for (var i = 0; i < e.NewItems.Count; i++)
+ Adapter.NotifyItemMoved(e.OldStartingIndex + i, e.NewStartingIndex + i);
+ break;
+
+ case NotifyCollectionChangedAction.Remove:
+ if (Element.Count == 0)
+ throw new InvalidOperationException("CarouselView must retain a least one item.");
+
+ Adapter.NotifyItemRangeRemoved(e.OldStartingIndex, e.OldItems.Count);
+ break;
+
+ case NotifyCollectionChangedAction.Replace:
+ Adapter.NotifyItemRangeChanged(e.OldStartingIndex, e.OldItems.Count);
+ break;
+
+ case NotifyCollectionChangedAction.Reset:
+ Adapter.NotifyDataSetChanged();
+ break;
+
+ default:
+ throw new Exception($"Enum value '{(int)e.Action}' is not a member of NotifyCollectionChangedAction enumeration.");
+ }
+ }
+
+ void OnItemChanged()
+ {
+ object item = ((IItemViewController)Element).GetItem(_position);
+ Controller.SendSelectedItemChanged(item);
+ }
+
+ void OnPositionChanged()
+ {
+ Element.Position = _position;
+ Controller.SendSelectedPositionChanged(_position);
+ }
+
+ // http://developer.android.com/reference/android/support/v7/widget/RecyclerView.html
+ // http://developer.android.com/training/material/lists-cards.html
+ // http://wiresareobsolete.com/2014/09/building-a-recyclerview-layoutmanager-part-1/
+
+ class OnScrollListener : RecyclerView.OnScrollListener
+ {
+ readonly Action _onDragEnd;
+ readonly Action _onDragStart;
+ ScrollState _lastScrollState;
+
+ internal OnScrollListener(Action onDragEnd, Action onDragStart)
+ {
+ _onDragEnd = onDragEnd;
+ _onDragStart = onDragStart;
+ }
+
+ public override void OnScrollStateChanged(RecyclerView recyclerView, int newState)
+ {
+ var state = (ScrollState)newState;
+ if (_lastScrollState != ScrollState.Dragging && state == ScrollState.Dragging)
+ _onDragStart();
+
+ if (_lastScrollState == ScrollState.Dragging && state != ScrollState.Dragging)
+ _onDragEnd();
+
+ _lastScrollState = state;
+ base.OnScrollStateChanged(recyclerView, newState);
+ }
+
+ enum ScrollState
+ {
+ Idle,
+ Dragging,
+ Settling
+ }
+ }
+
+ class PositionUpdater : Observer
+ {
+ readonly CarouselViewRenderer _carouselView;
+
+ internal PositionUpdater(CarouselViewRenderer carouselView)
+ {
+ _carouselView = carouselView;
+ }
+
+ public override void OnItemRangeInserted(int positionStart, int itemCount)
+ {
+ // removal after the current position won't change current position
+ if (positionStart > _carouselView._position)
+ ;
+
+ // raise position changed
+ else
+ {
+ _carouselView._position += itemCount;
+ _carouselView.OnPositionChanged();
+ }
+
+ base.OnItemRangeInserted(positionStart, itemCount);
+ }
+
+ public override void OnItemRangeMoved(int fromPosition, int toPosition, int itemCount)
+ {
+ base.OnItemRangeMoved(fromPosition, toPosition, itemCount);
+ }
+
+ public override void OnItemRangeRemoved(int positionStart, int itemCount)
+ {
+ Assert(itemCount == 1);
+
+ // removal after the current position won't change current position
+ if (positionStart > _carouselView._position)
+ ;
+
+ // raise item changed
+ else if (positionStart == _carouselView._position && positionStart != _carouselView.Adapter.ItemCount)
+ {
+ _carouselView.OnItemChanged();
+ return;
+ }
+
+ // raise position changed
+ else
+ {
+ _carouselView._position -= itemCount;
+ _carouselView.OnPositionChanged();
+ }
+
+ base.OnItemRangeRemoved(positionStart, itemCount);
+ }
+ }
+
+ internal class VirtualLayoutManager : PhysicalLayoutManager.VirtualLayoutManager
+ {
+ const int Columns = 1;
+
+ IntSize _itemSize;
+
+ internal override bool CanScrollHorizontally => true;
+
+ internal override bool CanScrollVertically => false;
+
+ public override string ToString()
+ {
+ return $"itemSize={_itemSize}";
+ }
+
+ internal override IntRectangle GetBounds(int originPosition, RecyclerView.State state)
+ => new IntRectangle(LayoutItem(originPosition, 0).Location, new IntSize(_itemSize.Width * state.ItemCount, _itemSize.Height));
+
+ internal override Tuple<int, int> GetPositions(int positionOrigin, int itemCount, IntRectangle viewport, bool includeBuffer)
+ {
+ // returns one item off-screen in either direction.
+ int buffer = includeBuffer ? 1 : 0;
+ int left = GetPosition(itemCount, positionOrigin - buffer, viewport.Left);
+ int right = GetPosition(itemCount, positionOrigin + buffer, viewport.Right, true);
+
+ int start = left;
+ int count = right - left + 1;
+ return new Tuple<int, int>(start, count);
+ }
+
+ internal override void Layout(int positionOffset, IntSize viewportSize, ref IntVector offset)
+ {
+ int width = viewportSize.Width / Columns;
+ int height = viewportSize.Height;
+
+ if (_itemSize.Width != 0)
+ offset *= (double)width / _itemSize.Width;
+
+ _itemSize = new IntSize(width, height);
+ }
+
+ internal override IntRectangle LayoutItem(int positionOffset, int position)
+ {
+ // measure
+ IntSize size = _itemSize;
+
+ // layout
+ var location = new IntVector((position - positionOffset) * size.Width, 0);
+
+ // allocate
+ return new IntRectangle(location, size);
+ }
+
+ int GetPosition(int itemCount, int positionOrigin, int x, bool exclusive = false)
+ {
+ int position = x / _itemSize.Width + positionOrigin;
+ bool hasRemainder = x % _itemSize.Width != 0;
+
+ if (hasRemainder && x < 0)
+ position--;
+
+ if (!hasRemainder && exclusive)
+ position--;
+
+ position = position.Clamp(0, itemCount - 1);
+ return position;
+ }
+ }
+ }
+
+ // RecyclerView virtualizes indexes (adapter position <-> viewGroup child index)
+ // PhysicalLayoutManager virtualizes location (regular layout <-> screen)
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ConditionalFocusLayout.cs b/Xamarin.Forms.Platform.Android/Renderers/ConditionalFocusLayout.cs
new file mode 100644
index 00000000..6368d023
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ConditionalFocusLayout.cs
@@ -0,0 +1,48 @@
+using Android.Content;
+using Android.Views;
+using Android.Widget;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class ConditionalFocusLayout : LinearLayout, global::Android.Views.View.IOnTouchListener
+ {
+ public ConditionalFocusLayout(Context context) : base(context)
+ {
+ SetOnTouchListener(this);
+ }
+
+ public bool OnTouch(global::Android.Views.View v, MotionEvent e)
+ {
+ bool allowFocus = v is EditText;
+ DescendantFocusability = allowFocus ? DescendantFocusability.AfterDescendants : DescendantFocusability.BlockDescendants;
+ return false;
+ }
+
+ internal void ApplyTouchListenersToSpecialCells(Cell item)
+ {
+ DescendantFocusability = DescendantFocusability.BlockDescendants;
+
+ global::Android.Views.View aView = GetChildAt(0);
+ (aView as EntryCellView)?.EditText.SetOnTouchListener(this);
+
+ var viewCell = item as ViewCell;
+ if (viewCell == null || viewCell?.View == null)
+ return;
+
+ IVisualElementRenderer renderer = Platform.GetRenderer(viewCell.View);
+ if (renderer?.ViewGroup?.ChildCount != 0)
+ (renderer.ViewGroup.GetChildAt(0) as EditText)?.SetOnTouchListener(this);
+
+ foreach (Element descendant in viewCell.View.Descendants())
+ {
+ var element = descendant as VisualElement;
+ if (element == null)
+ continue;
+ renderer = Platform.GetRenderer(element);
+ if (renderer?.ViewGroup?.ChildCount == 0)
+ continue;
+ (renderer.ViewGroup.GetChildAt(0) as EditText)?.SetOnTouchListener(this);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/DatePickerRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/DatePickerRenderer.cs
new file mode 100644
index 00000000..11d9a0d0
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/DatePickerRenderer.cs
@@ -0,0 +1,154 @@
+using System;
+using System.ComponentModel;
+using Android.App;
+using Android.Widget;
+using AView = Android.Views.View;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class DatePickerRenderer : ViewRenderer<DatePicker, EditText>
+ {
+ DatePickerDialog _dialog;
+ bool _disposed;
+
+ public DatePickerRenderer()
+ {
+ AutoPackage = false;
+ if (Forms.IsLollipopOrNewer)
+ Device.Info.PropertyChanged += DeviceInfoPropertyChanged;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ if (Forms.IsLollipopOrNewer)
+ Device.Info.PropertyChanged -= DeviceInfoPropertyChanged;
+
+ _disposed = true;
+ if (_dialog != null)
+ {
+ _dialog.Hide();
+ _dialog.Dispose();
+ _dialog = null;
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement == null)
+ {
+ var textField = new EditText(Context) { Focusable = false, Clickable = true, Tag = this };
+
+ textField.SetOnClickListener(TextFieldClickHandler.Instance);
+ SetNativeControl(textField);
+ }
+
+ SetDate(Element.Date);
+
+ UpdateMinimumDate();
+ UpdateMaximumDate();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == "Date" || e.PropertyName == DatePicker.FormatProperty.PropertyName)
+ SetDate(Element.Date);
+ else if (e.PropertyName == "MinimumDate")
+ UpdateMinimumDate();
+ else if (e.PropertyName == "MaximumDate")
+ UpdateMaximumDate();
+ }
+
+ internal override void OnFocusChangeRequested(object sender, VisualElement.FocusRequestArgs e)
+ {
+ base.OnFocusChangeRequested(sender, e);
+
+ if (e.Focus)
+ OnTextFieldClicked();
+ else if (_dialog != null)
+ {
+ _dialog.Hide();
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ Control.ClearFocus();
+ _dialog = null;
+ }
+ }
+
+ void CreateDatePickerDialog(int year, int month, int day)
+ {
+ DatePicker view = Element;
+ _dialog = new DatePickerDialog(Context, (o, e) =>
+ {
+ view.Date = e.Date;
+ ((IElementController)view).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ Control.ClearFocus();
+ _dialog = null;
+ }, year, month, day);
+ }
+
+ void DeviceInfoPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "CurrentOrientation")
+ {
+ DatePickerDialog currentDialog = _dialog;
+ if (currentDialog != null && currentDialog.IsShowing)
+ {
+ currentDialog.Dismiss();
+ CreateDatePickerDialog(currentDialog.DatePicker.Year, currentDialog.DatePicker.Month, currentDialog.DatePicker.DayOfMonth);
+ _dialog.Show();
+ }
+ }
+ }
+
+ void OnTextFieldClicked()
+ {
+ DatePicker view = Element;
+ ((IElementController)view).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
+
+ CreateDatePickerDialog(view.Date.Year, view.Date.Month - 1, view.Date.Day);
+
+ UpdateMinimumDate();
+ UpdateMaximumDate();
+ _dialog.Show();
+ }
+
+ void SetDate(DateTime date)
+ {
+ Control.Text = date.ToString(Element.Format);
+ }
+
+ void UpdateMaximumDate()
+ {
+ if (_dialog != null)
+ {
+ _dialog.DatePicker.MaxDate = (long)Element.MaximumDate.ToUniversalTime().Subtract(DateTime.MinValue.AddYears(1969)).TotalMilliseconds;
+ }
+ }
+
+ void UpdateMinimumDate()
+ {
+ if (_dialog != null)
+ {
+ _dialog.DatePicker.MinDate = (long)Element.MinimumDate.ToUniversalTime().Subtract(DateTime.MinValue.AddYears(1969)).TotalMilliseconds;
+ }
+ }
+
+ class TextFieldClickHandler : Object, IOnClickListener
+ {
+ public static readonly TextFieldClickHandler Instance = new TextFieldClickHandler();
+
+ public void OnClick(AView v)
+ {
+ ((DatePickerRenderer)v.Tag).OnTextFieldClicked();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/DescendantFocusToggler.cs b/Xamarin.Forms.Platform.Android/Renderers/DescendantFocusToggler.cs
new file mode 100644
index 00000000..1f54b7c5
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/DescendantFocusToggler.cs
@@ -0,0 +1,42 @@
+using System;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class DescendantFocusToggler : IDescendantFocusToggler
+ {
+ public bool RequestFocus(global::Android.Views.View control, Func<bool> baseRequestFocus)
+ {
+ IViewParent ancestor = control.Parent;
+ var previousFocusability = DescendantFocusability.BlockDescendants;
+ ConditionalFocusLayout cfl = null;
+
+ // Work our way up through the tree until we find a ConditionalFocusLayout
+ while (ancestor is ViewGroup)
+ {
+ cfl = ancestor as ConditionalFocusLayout;
+
+ if (cfl != null)
+ {
+ previousFocusability = cfl.DescendantFocusability;
+ // Toggle DescendantFocusability to allow this control to get focus
+ cfl.DescendantFocusability = DescendantFocusability.AfterDescendants;
+ break;
+ }
+
+ ancestor = ancestor.Parent;
+ }
+
+ // Call the original RequestFocus implementation for the View
+ bool result = baseRequestFocus();
+
+ if (cfl != null)
+ {
+ // Toggle descendantfocusability back to whatever it was
+ cfl.DescendantFocusability = previousFocusability;
+ }
+
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/EditorEditText.cs b/Xamarin.Forms.Platform.Android/Renderers/EditorEditText.cs
new file mode 100644
index 00000000..24273121
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/EditorEditText.cs
@@ -0,0 +1,42 @@
+using System;
+using Android.Content;
+using Android.Graphics;
+using Android.Views;
+using Android.Widget;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class EditorEditText : EditText, IDescendantFocusToggler
+ {
+ DescendantFocusToggler _descendantFocusToggler;
+
+ internal EditorEditText(Context context) : base(context)
+ {
+ }
+
+ bool IDescendantFocusToggler.RequestFocus(global::Android.Views.View control, Func<bool> baseRequestFocus)
+ {
+ _descendantFocusToggler = _descendantFocusToggler ?? new DescendantFocusToggler();
+
+ return _descendantFocusToggler.RequestFocus(control, baseRequestFocus);
+ }
+
+ public override bool OnKeyPreIme(Keycode keyCode, KeyEvent e)
+ {
+ if (keyCode == Keycode.Back && e.Action == KeyEventActions.Down)
+ {
+ EventHandler handler = OnBackKeyboardPressed;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+ return base.OnKeyPreIme(keyCode, e);
+ }
+
+ public override bool RequestFocus(FocusSearchDirection direction, Rect previouslyFocusedRect)
+ {
+ return (this as IDescendantFocusToggler).RequestFocus(this, () => base.RequestFocus(direction, previouslyFocusedRect));
+ }
+
+ internal event EventHandler OnBackKeyboardPressed;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/EditorRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/EditorRenderer.cs
new file mode 100644
index 00000000..14078abc
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/EditorRenderer.cs
@@ -0,0 +1,140 @@
+using System.ComponentModel;
+using Android.Content.Res;
+using Android.Text;
+using Android.Util;
+using Android.Views;
+using Java.Lang;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class EditorRenderer : ViewRenderer<Editor, EditorEditText>, ITextWatcher
+ {
+ ColorStateList _defaultColors;
+
+ public EditorRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ void ITextWatcher.AfterTextChanged(IEditable s)
+ {
+ }
+
+ void ITextWatcher.BeforeTextChanged(ICharSequence s, int start, int count, int after)
+ {
+ }
+
+ void ITextWatcher.OnTextChanged(ICharSequence s, int start, int before, int count)
+ {
+ if (string.IsNullOrEmpty(Element.Text) && s.Length() == 0)
+ return;
+
+ if (Element.Text != s.ToString())
+ ((IElementController)Element).SetValueFromRenderer(Editor.TextProperty, s.ToString());
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
+ {
+ base.OnElementChanged(e);
+
+ HandleKeyboardOnFocus = true;
+
+ EditorEditText edit = Control;
+ if (edit == null)
+ {
+ edit = new EditorEditText(Context);
+
+ SetNativeControl(edit);
+ edit.AddTextChangedListener(this);
+ edit.OnBackKeyboardPressed += (sender, args) =>
+ {
+ Element.SendCompleted();
+ edit.ClearFocus();
+ };
+ }
+
+ edit.SetSingleLine(false);
+ edit.Gravity = GravityFlags.Top;
+ edit.SetHorizontallyScrolling(false);
+
+ UpdateText();
+ UpdateInputType();
+ UpdateTextColor();
+ UpdateFont();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Editor.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == InputView.KeyboardProperty.PropertyName)
+ UpdateInputType();
+ else if (e.PropertyName == Editor.TextColorProperty.PropertyName)
+ UpdateTextColor();
+ else if (e.PropertyName == Editor.FontAttributesProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Editor.FontFamilyProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Editor.FontSizeProperty.PropertyName)
+ UpdateFont();
+
+ base.OnElementPropertyChanged(sender, e);
+ }
+
+ internal override void OnNativeFocusChanged(bool hasFocus)
+ {
+ if (Element.IsFocused && !hasFocus) // Editor has requested an unfocus, fire completed event
+ Element.SendCompleted();
+ }
+
+ void UpdateFont()
+ {
+ Control.Typeface = Element.ToTypeface();
+ Control.SetTextSize(ComplexUnitType.Sp, (float)Element.FontSize);
+ }
+
+ void UpdateInputType()
+ {
+ Editor model = Element;
+ EditorEditText edit = Control;
+ edit.InputType = model.Keyboard.ToInputType() | InputTypes.TextFlagMultiLine;
+ }
+
+ void UpdateText()
+ {
+ string newText = Element.Text ?? "";
+
+ if (Control.Text == newText)
+ return;
+
+ Control.Text = newText;
+ Control.SetSelection(newText.Length);
+ }
+
+ void UpdateTextColor()
+ {
+ if (Element.TextColor.IsDefault)
+ {
+ if (_defaultColors == null)
+ {
+ // This control has always had the default colors; nothing to update
+ return;
+ }
+
+ // This control is being set back to the default colors
+ Control.SetTextColor(_defaultColors);
+ }
+ else
+ {
+ if (_defaultColors == null)
+ {
+ // Keep track of the default colors so we can return to them later
+ // and so we can preserve the default disabled color
+ _defaultColors = Control.TextColors;
+ }
+
+ Control.SetTextColor(Element.TextColor.ToAndroidPreserveDisabled(_defaultColors));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/EntryEditText.cs b/Xamarin.Forms.Platform.Android/Renderers/EntryEditText.cs
new file mode 100644
index 00000000..de03a414
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/EntryEditText.cs
@@ -0,0 +1,42 @@
+using System;
+using Android.Content;
+using Android.Graphics;
+using Android.Views;
+using Android.Widget;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class EntryEditText : EditText, IDescendantFocusToggler
+ {
+ DescendantFocusToggler _descendantFocusToggler;
+
+ internal EntryEditText(Context context) : base(context)
+ {
+ }
+
+ bool IDescendantFocusToggler.RequestFocus(global::Android.Views.View control, Func<bool> baseRequestFocus)
+ {
+ _descendantFocusToggler = _descendantFocusToggler ?? new DescendantFocusToggler();
+
+ return _descendantFocusToggler.RequestFocus(control, baseRequestFocus);
+ }
+
+ public override bool OnKeyPreIme(Keycode keyCode, KeyEvent e)
+ {
+ if (keyCode == Keycode.Back && e.Action == KeyEventActions.Down)
+ {
+ EventHandler handler = OnKeyboardBackPressed;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+ return base.OnKeyPreIme(keyCode, e);
+ }
+
+ public override bool RequestFocus(FocusSearchDirection direction, Rect previouslyFocusedRect)
+ {
+ return (this as IDescendantFocusToggler).RequestFocus(this, () => base.RequestFocus(direction, previouslyFocusedRect));
+ }
+
+ internal event EventHandler OnKeyboardBackPressed;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/EntryRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/EntryRenderer.cs
new file mode 100644
index 00000000..24824536
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/EntryRenderer.cs
@@ -0,0 +1,189 @@
+using System.ComponentModel;
+using Android.Content.Res;
+using Android.Text;
+using Android.Util;
+using Android.Views;
+using Android.Views.InputMethods;
+using Android.Widget;
+using Java.Lang;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class EntryRenderer : ViewRenderer<Entry, EntryEditText>, ITextWatcher, TextView.IOnEditorActionListener
+ {
+ ColorStateList _hintTextColorDefault;
+ ColorStateList _textColorDefault;
+ EntryEditText _textView;
+
+ public EntryRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ bool TextView.IOnEditorActionListener.OnEditorAction(TextView v, ImeAction actionId, KeyEvent e)
+ {
+ // Fire Completed and dismiss keyboard for hardware / physical keyboards
+ if (actionId == ImeAction.Done || (actionId == ImeAction.ImeNull && e.KeyCode == Keycode.Enter))
+ {
+ Control.ClearFocus();
+ v.HideKeyboard();
+ Element.SendCompleted();
+ }
+
+ return true;
+ }
+
+ void ITextWatcher.AfterTextChanged(IEditable s)
+ {
+ }
+
+ void ITextWatcher.BeforeTextChanged(ICharSequence s, int start, int count, int after)
+ {
+ }
+
+ void ITextWatcher.OnTextChanged(ICharSequence s, int start, int before, int count)
+ {
+ if (string.IsNullOrEmpty(Element.Text) && s.Length() == 0)
+ return;
+
+ ((IElementController)Element).SetValueFromRenderer(Entry.TextProperty, s.ToString());
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
+ {
+ base.OnElementChanged(e);
+
+ HandleKeyboardOnFocus = true;
+
+ if (e.OldElement == null)
+ {
+ _textView = new EntryEditText(Context);
+ _textView.ImeOptions = ImeAction.Done;
+ _textView.AddTextChangedListener(this);
+ _textView.SetOnEditorActionListener(this);
+ _textView.OnKeyboardBackPressed += (sender, args) => _textView.ClearFocus();
+ SetNativeControl(_textView);
+ }
+
+ _textView.Hint = Element.Placeholder;
+ _textView.Text = Element.Text;
+ UpdateInputType();
+
+ UpdateColor();
+ UpdateAlignment();
+ UpdateFont();
+ UpdatePlaceholderColor();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Entry.PlaceholderProperty.PropertyName)
+ Control.Hint = Element.Placeholder;
+ else if (e.PropertyName == Entry.IsPasswordProperty.PropertyName)
+ UpdateInputType();
+ else if (e.PropertyName == Entry.TextProperty.PropertyName)
+ {
+ if (Control.Text != Element.Text)
+ {
+ Control.Text = Element.Text;
+ if (Control.IsFocused)
+ {
+ Control.SetSelection(Control.Text.Length);
+ Control.ShowKeyboard();
+ }
+ }
+ }
+ else if (e.PropertyName == Entry.TextColorProperty.PropertyName)
+ UpdateColor();
+ else if (e.PropertyName == InputView.KeyboardProperty.PropertyName)
+ UpdateInputType();
+ else if (e.PropertyName == Entry.HorizontalTextAlignmentProperty.PropertyName)
+ UpdateAlignment();
+ else if (e.PropertyName == Entry.FontAttributesProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Entry.FontFamilyProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Entry.FontSizeProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Entry.PlaceholderColorProperty.PropertyName)
+ UpdatePlaceholderColor();
+
+ base.OnElementPropertyChanged(sender, e);
+ }
+
+ void UpdateAlignment()
+ {
+ Control.Gravity = Element.HorizontalTextAlignment.ToHorizontalGravityFlags();
+ }
+
+ void UpdateColor()
+ {
+ if (Element.TextColor.IsDefault)
+ {
+ if (_textColorDefault == null)
+ {
+ // This control has always had the default colors; nothing to update
+ return;
+ }
+
+ // This control is being set back to the default colors
+ Control.SetTextColor(_textColorDefault);
+ }
+ else
+ {
+ if (_textColorDefault == null)
+ {
+ // Keep track of the default colors so we can return to them later
+ // and so we can preserve the default disabled color
+ _textColorDefault = Control.TextColors;
+ }
+
+ Control.SetTextColor(Element.TextColor.ToAndroidPreserveDisabled(_textColorDefault));
+ }
+ }
+
+ void UpdateFont()
+ {
+ Control.Typeface = Element.ToTypeface();
+ Control.SetTextSize(ComplexUnitType.Sp, (float)Element.FontSize);
+ }
+
+ void UpdateInputType()
+ {
+ Entry model = Element;
+ _textView.InputType = model.Keyboard.ToInputType();
+ if (model.IsPassword && ((_textView.InputType & InputTypes.ClassText) == InputTypes.ClassText))
+ _textView.InputType = _textView.InputType | InputTypes.TextVariationPassword;
+ if (model.IsPassword && ((_textView.InputType & InputTypes.ClassNumber) == InputTypes.ClassNumber))
+ _textView.InputType = _textView.InputType | InputTypes.NumberVariationPassword;
+ }
+
+ void UpdatePlaceholderColor()
+ {
+ Color placeholderColor = Element.PlaceholderColor;
+
+ if (placeholderColor.IsDefault)
+ {
+ if (_hintTextColorDefault == null)
+ {
+ // This control has always had the default colors; nothing to update
+ return;
+ }
+
+ // This control is being set back to the default colors
+ Control.SetHintTextColor(_hintTextColorDefault);
+ }
+ else
+ {
+ if (_hintTextColorDefault == null)
+ {
+ // Keep track of the default colors so we can return to them later
+ // and so we can preserve the default disabled color
+ _hintTextColorDefault = Control.HintTextColors;
+ }
+
+ Control.SetHintTextColor(placeholderColor.ToAndroidPreserveDisabled(_hintTextColorDefault));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/FileImageSourceHandler.cs b/Xamarin.Forms.Platform.Android/Renderers/FileImageSourceHandler.cs
new file mode 100644
index 00000000..edf7dc37
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/FileImageSourceHandler.cs
@@ -0,0 +1,17 @@
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Android.Content;
+using Android.Graphics;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public sealed class FileImageSourceHandler : IImageSourceHandler
+ {
+ public async Task<Bitmap> LoadImageAsync(ImageSource imagesource, Context context, CancellationToken cancelationToken = default(CancellationToken))
+ {
+ string file = ((FileImageSource)imagesource).File;
+ return await (File.Exists(file) ? BitmapFactory.DecodeFileAsync(file) : context.Resources.GetBitmapAsync(file)).ConfigureAwait(false);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/FontExtensions.cs b/Xamarin.Forms.Platform.Android/Renderers/FontExtensions.cs
new file mode 100644
index 00000000..da458642
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/FontExtensions.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using Android.Graphics;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public static class FontExtensions
+ {
+ static readonly Dictionary<Tuple<string, FontAttributes>, Typeface> Typefaces = new Dictionary<Tuple<string, FontAttributes>, Typeface>();
+
+ static Typeface s_defaultTypeface;
+
+ public static float ToScaledPixel(this Font self)
+ {
+ if (self.IsDefault)
+ return 14;
+
+ if (self.UseNamedSize)
+ {
+ switch (self.NamedSize)
+ {
+ case NamedSize.Micro:
+ return 10;
+ case NamedSize.Small:
+ return 12;
+ case NamedSize.Default:
+ case NamedSize.Medium:
+ return 14;
+ case NamedSize.Large:
+ return 18;
+ }
+ }
+
+ return (float)self.FontSize;
+ }
+
+ public static Typeface ToTypeface(this Font self)
+ {
+ if (self.IsDefault)
+ return s_defaultTypeface ?? (s_defaultTypeface = Typeface.Default);
+
+ var key = new Tuple<string, FontAttributes>(self.FontFamily, self.FontAttributes);
+ Typeface result;
+ if (Typefaces.TryGetValue(key, out result))
+ return result;
+
+ var style = TypefaceStyle.Normal;
+ if ((self.FontAttributes & (FontAttributes.Bold | FontAttributes.Italic)) == (FontAttributes.Bold | FontAttributes.Italic))
+ style = TypefaceStyle.BoldItalic;
+ else if ((self.FontAttributes & FontAttributes.Bold) != 0)
+ style = TypefaceStyle.Bold;
+ else if ((self.FontAttributes & FontAttributes.Italic) != 0)
+ style = TypefaceStyle.Italic;
+
+ if (self.FontFamily != null)
+ result = Typeface.Create(self.FontFamily, style);
+ else
+ result = Typeface.Create(Typeface.Default, style);
+
+ Typefaces[key] = result;
+ return result;
+ }
+
+ internal static bool IsDefault(this IFontElement self)
+ {
+ return self.FontFamily == null && self.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(Label), true) && self.FontAttributes == FontAttributes.None;
+ }
+
+ internal static Typeface ToTypeface(this IFontElement self)
+ {
+ var key = new Tuple<string, FontAttributes>(self.FontFamily, self.FontAttributes);
+ Typeface result;
+ if (Typefaces.TryGetValue(key, out result))
+ return result;
+
+ var style = TypefaceStyle.Normal;
+ if ((self.FontAttributes & (FontAttributes.Bold | FontAttributes.Italic)) == (FontAttributes.Bold | FontAttributes.Italic))
+ style = TypefaceStyle.BoldItalic;
+ else if ((self.FontAttributes & FontAttributes.Bold) != 0)
+ style = TypefaceStyle.Bold;
+ else if ((self.FontAttributes & FontAttributes.Italic) != 0)
+ style = TypefaceStyle.Italic;
+
+ if (self.FontFamily != null)
+ result = Typeface.Create(self.FontFamily, style);
+ else
+ result = Typeface.Create(Typeface.Default, style);
+
+ Typefaces[key] = result;
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/FormattedStringExtensions.cs b/Xamarin.Forms.Platform.Android/Renderers/FormattedStringExtensions.cs
new file mode 100644
index 00000000..2a65c98f
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/FormattedStringExtensions.cs
@@ -0,0 +1,90 @@
+using System.Text;
+using Android.Graphics;
+using Android.Text;
+using Android.Text.Style;
+using Android.Util;
+using Android.Widget;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public static class FormattedStringExtensions
+ {
+ public static SpannableString ToAttributed(this FormattedString formattedString, Font defaultFont, Color defaultForegroundColor, TextView view)
+ {
+ if (formattedString == null)
+ return null;
+
+ var builder = new StringBuilder();
+ foreach (Span span in formattedString.Spans)
+ {
+ if (span.Text == null)
+ continue;
+
+ builder.Append(span.Text);
+ }
+
+ var spannable = new SpannableString(builder.ToString());
+
+ var c = 0;
+ foreach (Span span in formattedString.Spans)
+ {
+ if (span.Text == null)
+ continue;
+
+ int start = c;
+ int end = start + span.Text.Length;
+ c = end;
+
+ if (span.ForegroundColor != Color.Default)
+ {
+ spannable.SetSpan(new ForegroundColorSpan(span.ForegroundColor.ToAndroid()), start, end, SpanTypes.InclusiveExclusive);
+ }
+ else if (defaultForegroundColor != Color.Default)
+ {
+ spannable.SetSpan(new ForegroundColorSpan(defaultForegroundColor.ToAndroid()), start, end, SpanTypes.InclusiveExclusive);
+ }
+
+ if (span.BackgroundColor != Color.Default)
+ {
+ spannable.SetSpan(new BackgroundColorSpan(span.BackgroundColor.ToAndroid()), start, end, SpanTypes.InclusiveExclusive);
+ }
+
+ if (!span.IsDefault())
+ spannable.SetSpan(new FontSpan(span.Font, view), start, end, SpanTypes.InclusiveInclusive);
+ else if (defaultFont != Font.Default)
+ spannable.SetSpan(new FontSpan(defaultFont, view), start, end, SpanTypes.InclusiveInclusive);
+ }
+ return spannable;
+ }
+
+ class FontSpan : MetricAffectingSpan
+ {
+ public FontSpan(Font font, TextView view)
+ {
+ Font = font;
+ TextView = view;
+ }
+
+ public Font Font { get; }
+
+ public TextView TextView { get; }
+
+ public override void UpdateDrawState(TextPaint tp)
+ {
+ Apply(tp);
+ }
+
+ public override void UpdateMeasureState(TextPaint p)
+ {
+ Apply(p);
+ }
+
+ void Apply(Paint paint)
+ {
+ paint.SetTypeface(Font.ToTypeface());
+ float value = Font.ToScaledPixel();
+ paint.TextSize = TypedValue.ApplyDimension(ComplexUnitType.Sp, value, TextView.Resources.DisplayMetrics);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/FormsImageView.cs b/Xamarin.Forms.Platform.Android/Renderers/FormsImageView.cs
new file mode 100644
index 00000000..ae32e16c
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/FormsImageView.cs
@@ -0,0 +1,36 @@
+using System;
+using Android.Content;
+using Android.Runtime;
+using Android.Widget;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class FormsImageView : ImageView
+ {
+ bool _skipInvalidate;
+
+ public FormsImageView(Context context) : base(context)
+ {
+ }
+
+ protected FormsImageView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
+ {
+ }
+
+ public override void Invalidate()
+ {
+ if (_skipInvalidate)
+ {
+ _skipInvalidate = false;
+ return;
+ }
+
+ base.Invalidate();
+ }
+
+ public void SkipInvalidate()
+ {
+ _skipInvalidate = true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/FormsTextView.cs b/Xamarin.Forms.Platform.Android/Renderers/FormsTextView.cs
new file mode 100644
index 00000000..1dc25ea9
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/FormsTextView.cs
@@ -0,0 +1,41 @@
+using System;
+using Android.Content;
+using Android.Runtime;
+using Android.Util;
+using Android.Widget;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class FormsTextView : TextView
+ {
+ bool _skip;
+
+ public FormsTextView(Context context) : base(context)
+ {
+ }
+
+ public FormsTextView(Context context, IAttributeSet attrs) : base(context, attrs)
+ {
+ }
+
+ public FormsTextView(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
+ {
+ }
+
+ protected FormsTextView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
+ {
+ }
+
+ public override void Invalidate()
+ {
+ if (!_skip)
+ base.Invalidate();
+ _skip = false;
+ }
+
+ public void SkipNextInvalidate()
+ {
+ _skip = true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/FormsWebChromeClient.cs b/Xamarin.Forms.Platform.Android/Renderers/FormsWebChromeClient.cs
new file mode 100644
index 00000000..5d885774
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/FormsWebChromeClient.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using Android.App;
+using Android.Content;
+using Android.Webkit;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class FormsWebChromeClient : WebChromeClient
+ {
+ IStartActivityForResult _context;
+ List<int> _requestCodes;
+
+ public override bool OnShowFileChooser(global::Android.Webkit.WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
+ {
+ base.OnShowFileChooser(webView, filePathCallback, fileChooserParams);
+ return ChooseFile(filePathCallback, fileChooserParams.CreateIntent(), fileChooserParams.Title);
+ }
+
+ public void UnregisterCallbacks()
+ {
+ if (_requestCodes == null || _requestCodes.Count == 0 || _context == null)
+ return;
+
+ foreach (int requestCode in _requestCodes)
+ _context.UnregisterActivityResultCallback(requestCode);
+
+ _requestCodes = null;
+ }
+
+ protected bool ChooseFile(IValueCallback filePathCallback, Intent intent, string title)
+ {
+ Action<Result, Intent> callback = (resultCode, intentData) =>
+ {
+ if (filePathCallback == null)
+ return;
+
+ Object result = ParseResult(resultCode, intentData);
+ filePathCallback.OnReceiveValue(result);
+ };
+
+ _requestCodes = _requestCodes ?? new List<int>();
+
+ int newRequestCode = _context.RegisterActivityResultCallback(callback);
+
+ _requestCodes.Add(newRequestCode);
+
+ _context.StartActivityForResult(Intent.CreateChooser(intent, title), newRequestCode);
+
+ return true;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ UnregisterCallbacks();
+ base.Dispose(disposing);
+ }
+
+ protected virtual Object ParseResult(Result resultCode, Intent data)
+ {
+ return FileChooserParams.ParseResult((int)resultCode, data);
+ }
+
+ internal void SetContext(IStartActivityForResult startActivityForResult)
+ {
+ if (startActivityForResult == null)
+ throw new ArgumentNullException(nameof(startActivityForResult));
+
+ _context = startActivityForResult;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/FrameRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/FrameRenderer.cs
new file mode 100644
index 00000000..63fb5da4
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/FrameRenderer.cs
@@ -0,0 +1,195 @@
+using System.ComponentModel;
+using Android.Graphics;
+using Android.Graphics.Drawables;
+using AButton = Android.Widget.Button;
+using ACanvas = Android.Graphics.Canvas;
+using GlobalResource = Android.Resource;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class FrameRenderer : VisualElementRenderer<Frame>
+ {
+ bool _disposed;
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (disposing && !_disposed)
+ {
+ Background.Dispose();
+ _disposed = true;
+ }
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null && e.OldElement == null)
+ UpdateBackground();
+ }
+
+ void UpdateBackground()
+ {
+ SetBackgroundDrawable(new FrameDrawable(Element));
+ }
+
+ class FrameDrawable : Drawable
+ {
+ readonly Frame _frame;
+
+ bool _isDisposed;
+ Bitmap _normalBitmap;
+
+ public FrameDrawable(Frame frame)
+ {
+ _frame = frame;
+ frame.PropertyChanged += FrameOnPropertyChanged;
+ }
+
+ public override bool IsStateful
+ {
+ get { return false; }
+ }
+
+ public override int Opacity
+ {
+ get { return 0; }
+ }
+
+ public override void Draw(ACanvas canvas)
+ {
+ int width = Bounds.Width();
+ int height = Bounds.Height();
+
+ if (width <= 0 || height <= 0)
+ {
+ if (_normalBitmap != null)
+ {
+ _normalBitmap.Dispose();
+ _normalBitmap = null;
+ }
+ return;
+ }
+
+ if (_normalBitmap == null || _normalBitmap.Height != height || _normalBitmap.Width != width)
+ {
+ // If the user changes the orientation of the screen, make sure to detroy reference before
+ // reassigning a new bitmap reference.
+ if (_normalBitmap != null)
+ {
+ _normalBitmap.Dispose();
+ _normalBitmap = null;
+ }
+
+ _normalBitmap = CreateBitmap(false, width, height);
+ }
+ Bitmap bitmap = _normalBitmap;
+ using(var paint = new Paint())
+ canvas.DrawBitmap(bitmap, 0, 0, paint);
+ }
+
+ public override void SetAlpha(int alpha)
+ {
+ }
+
+ public override void SetColorFilter(ColorFilter cf)
+ {
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_isDisposed)
+ {
+ if (_normalBitmap != null)
+ {
+ _normalBitmap.Dispose();
+ _normalBitmap = null;
+ }
+
+ _isDisposed = true;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override bool OnStateChange(int[] state)
+ {
+ return false;
+ }
+
+ Bitmap CreateBitmap(bool pressed, int width, int height)
+ {
+ Bitmap bitmap;
+ using(Bitmap.Config config = Bitmap.Config.Argb8888)
+ bitmap = Bitmap.CreateBitmap(width, height, config);
+
+ using(var canvas = new ACanvas(bitmap))
+ {
+ DrawBackground(canvas, width, height, pressed);
+ DrawOutline(canvas, width, height);
+ }
+
+ return bitmap;
+ }
+
+ void DrawBackground(ACanvas canvas, int width, int height, bool pressed)
+ {
+ using(var paint = new Paint { AntiAlias = true })
+ using(var path = new Path())
+ using(Path.Direction direction = Path.Direction.Cw)
+ using(Paint.Style style = Paint.Style.Fill)
+ using(var rect = new RectF(0, 0, width, height))
+ {
+ float rx = Forms.Context.ToPixels(5);
+ float ry = Forms.Context.ToPixels(5);
+ path.AddRoundRect(rect, rx, ry, direction);
+
+ global::Android.Graphics.Color color = _frame.BackgroundColor.ToAndroid();
+
+ paint.SetStyle(style);
+ paint.Color = color;
+
+ canvas.DrawPath(path, paint);
+ }
+ }
+
+ void DrawOutline(ACanvas canvas, int width, int height)
+ {
+ using(var paint = new Paint { AntiAlias = true })
+ using(var path = new Path())
+ using(Path.Direction direction = Path.Direction.Cw)
+ using(Paint.Style style = Paint.Style.Stroke)
+ using(var rect = new RectF(0, 0, width, height))
+ {
+ float rx = Forms.Context.ToPixels(5);
+ float ry = Forms.Context.ToPixels(5);
+ path.AddRoundRect(rect, rx, ry, direction);
+
+ paint.StrokeWidth = 1;
+ paint.SetStyle(style);
+ paint.Color = _frame.OutlineColor.ToAndroid();
+
+ canvas.DrawPath(path, paint);
+ }
+ }
+
+ void FrameOnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName || e.PropertyName == Frame.OutlineColorProperty.PropertyName)
+ {
+ using(var canvas = new ACanvas(_normalBitmap))
+ {
+ int width = Bounds.Width();
+ int height = Bounds.Height();
+ canvas.DrawColor(global::Android.Graphics.Color.Black, PorterDuff.Mode.Clear);
+ DrawBackground(canvas, width, height, false);
+ DrawOutline(canvas, width, height);
+ }
+ InvalidateSelf();
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/GenericAnimatorListener.cs b/Xamarin.Forms.Platform.Android/Renderers/GenericAnimatorListener.cs
new file mode 100644
index 00000000..c89f007c
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/GenericAnimatorListener.cs
@@ -0,0 +1,41 @@
+using System;
+using Android.Animation;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class GenericAnimatorListener : AnimatorListenerAdapter
+ {
+ public Action<Animator> OnCancel { get; set; }
+
+ public Action<Animator> OnEnd { get; set; }
+
+ public Action<Animator> OnRepeat { get; set; }
+
+ public override void OnAnimationCancel(Animator animation)
+ {
+ if (OnCancel != null)
+ OnCancel(animation);
+ base.OnAnimationCancel(animation);
+ }
+
+ public override void OnAnimationEnd(Animator animation)
+ {
+ if (OnEnd != null)
+ OnEnd(animation);
+ base.OnAnimationEnd(animation);
+ }
+
+ public override void OnAnimationRepeat(Animator animation)
+ {
+ if (OnRepeat != null)
+ OnRepeat(animation);
+ base.OnAnimationRepeat(animation);
+ }
+
+ protected override void JavaFinalize()
+ {
+ OnCancel = OnRepeat = OnEnd = null;
+ base.JavaFinalize();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/IDescendantFocusToggler.cs b/Xamarin.Forms.Platform.Android/Renderers/IDescendantFocusToggler.cs
new file mode 100644
index 00000000..b908e9ad
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/IDescendantFocusToggler.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal interface IDescendantFocusToggler
+ {
+ bool RequestFocus(global::Android.Views.View control, Func<bool> baseRequestFocus);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/IImageSourceHandler.cs b/Xamarin.Forms.Platform.Android/Renderers/IImageSourceHandler.cs
new file mode 100644
index 00000000..a072e4dc
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/IImageSourceHandler.cs
@@ -0,0 +1,12 @@
+using System.Threading;
+using System.Threading.Tasks;
+using Android.Content;
+using Android.Graphics;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public interface IImageSourceHandler : IRegisterable
+ {
+ Task<Bitmap> LoadImageAsync(ImageSource imagesource, Context context, CancellationToken cancelationToken = default(CancellationToken));
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/IToolbarButton.cs b/Xamarin.Forms.Platform.Android/Renderers/IToolbarButton.cs
new file mode 100644
index 00000000..a409c41c
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/IToolbarButton.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms.Platform.Android
+{
+ internal interface IToolbarButton
+ {
+ ToolbarItem Item { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ImageExtensions.cs b/Xamarin.Forms.Platform.Android/Renderers/ImageExtensions.cs
new file mode 100644
index 00000000..e48682c3
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ImageExtensions.cs
@@ -0,0 +1,26 @@
+using Android.Widget;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal static class ImageExtensions
+ {
+ static ImageView.ScaleType s_fill;
+ static ImageView.ScaleType s_aspectFill;
+ static ImageView.ScaleType s_aspectFit;
+
+ public static ImageView.ScaleType ToScaleType(this Aspect aspect)
+ {
+ switch (aspect)
+ {
+ case Aspect.Fill:
+ return s_fill ?? (s_fill = ImageView.ScaleType.FitXy);
+ case Aspect.AspectFill:
+ return s_aspectFill ?? (s_aspectFill = ImageView.ScaleType.CenterCrop);
+ default:
+ case Aspect.AspectFit:
+ return s_aspectFit ?? (s_aspectFit = ImageView.ScaleType.FitCenter);
+ ;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ImageLoaderSourceHandler.cs b/Xamarin.Forms.Platform.Android/Renderers/ImageLoaderSourceHandler.cs
new file mode 100644
index 00000000..541dbeaf
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ImageLoaderSourceHandler.cs
@@ -0,0 +1,22 @@
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Android.Content;
+using Android.Graphics;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public sealed class ImageLoaderSourceHandler : IImageSourceHandler
+ {
+ public async Task<Bitmap> LoadImageAsync(ImageSource imagesource, Context context, CancellationToken cancelationToken = default(CancellationToken))
+ {
+ var imageLoader = imagesource as UriImageSource;
+ if (imageLoader != null && imageLoader.Uri != null)
+ {
+ using(Stream imageStream = await imageLoader.GetStreamAsync(cancelationToken).ConfigureAwait(false))
+ return await BitmapFactory.DecodeStreamAsync(imageStream).ConfigureAwait(false);
+ }
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs
new file mode 100644
index 00000000..a080e58b
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs
@@ -0,0 +1,108 @@
+using System;
+using System.ComponentModel;
+using System.IO;
+using System.Threading.Tasks;
+using Android.Graphics;
+using AImageView = Android.Widget.ImageView;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class ImageRenderer : ViewRenderer<Image, AImageView>
+ {
+ bool _isDisposed;
+
+ public ImageRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (_isDisposed)
+ return;
+
+ _isDisposed = true;
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement == null)
+ {
+ var view = new FormsImageView(Context);
+ SetNativeControl(view);
+ }
+
+ UpdateBitmap(e.OldElement);
+ UpdateAspect();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Image.SourceProperty.PropertyName)
+ UpdateBitmap();
+ else if (e.PropertyName == Image.AspectProperty.PropertyName)
+ UpdateAspect();
+ }
+
+ void UpdateAspect()
+ {
+ AImageView.ScaleType type = Element.Aspect.ToScaleType();
+ Control.SetScaleType(type);
+ }
+
+ async void UpdateBitmap(Image previous = null)
+ {
+ if (Device.IsInvokeRequired)
+ throw new InvalidOperationException("Image Bitmap must not be updated from background thread");
+
+ Bitmap bitmap = null;
+
+ ImageSource source = Element.Source;
+ IImageSourceHandler handler;
+
+ if (previous != null && Equals(previous.Source, Element.Source))
+ return;
+
+ ((IElementController)Element).SetValueFromRenderer(Image.IsLoadingPropertyKey, true);
+
+ var formsImageView = Control as FormsImageView;
+ if (formsImageView != null)
+ formsImageView.SkipInvalidate();
+
+ Control.SetImageResource(global::Android.Resource.Color.Transparent);
+
+ if (source != null && (handler = Registrar.Registered.GetHandler<IImageSourceHandler>(source.GetType())) != null)
+ {
+ try
+ {
+ bitmap = await handler.LoadImageAsync(source, Context);
+ }
+ catch (TaskCanceledException)
+ {
+ }
+ catch (IOException e)
+ {
+ }
+ }
+
+ if (Element == null || !Equals(Element.Source, source))
+ return;
+
+ if (!_isDisposed)
+ {
+ Control.SetImageBitmap(bitmap);
+ if (bitmap != null)
+ bitmap.Dispose();
+
+ ((IElementController)Element).SetValueFromRenderer(Image.IsLoadingPropertyKey, false);
+ ((IVisualElementController)Element).NativeSizeChanged();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/IntVector.cs b/Xamarin.Forms.Platform.Android/Renderers/IntVector.cs
new file mode 100644
index 00000000..e5e0986c
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/IntVector.cs
@@ -0,0 +1,86 @@
+namespace Xamarin.Forms.Platform.Android
+{
+ internal struct IntVector
+ {
+ public static explicit operator IntVector(System.Drawing.Size size)
+ {
+ return new IntVector(size.Width, size.Height);
+ }
+
+ public static explicit operator IntVector(System.Drawing.Point point)
+ {
+ return new IntVector(point.X, point.Y);
+ }
+
+ public static implicit operator System.Drawing.Point(IntVector vector)
+ {
+ return new System.Drawing.Point(vector.X, vector.Y);
+ }
+
+ public static implicit operator System.Drawing.Size(IntVector vector)
+ {
+ return new System.Drawing.Size(vector.X, vector.Y);
+ }
+
+ public static bool operator ==(IntVector lhs, IntVector rhs)
+ {
+ return lhs.X == rhs.X && lhs.Y == rhs.Y;
+ }
+
+ public static bool operator !=(IntVector lhs, IntVector rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+ public static System.Drawing.Rectangle operator -(System.Drawing.Rectangle source, IntVector vector) => source + -vector;
+
+ public static System.Drawing.Rectangle operator +(System.Drawing.Rectangle source, IntVector vector) => new System.Drawing.Rectangle(source.Location + vector, source.Size);
+
+ public static System.Drawing.Point operator -(System.Drawing.Point point, IntVector delta) => point + -delta;
+
+ public static System.Drawing.Point operator +(System.Drawing.Point point, IntVector delta) => new System.Drawing.Point(point.X + delta.X, point.Y + delta.Y);
+
+ public static IntVector operator -(IntVector vector, IntVector other) => vector + -other;
+
+ public static IntVector operator +(IntVector vector, IntVector other) => new IntVector(vector.X + other.X, vector.Y + other.Y);
+
+ public static IntVector operator -(IntVector vector) => vector * -1;
+
+ public static IntVector operator *(IntVector vector, int scaler) => new IntVector(vector.X * scaler, vector.Y * scaler);
+
+ public static IntVector operator /(IntVector vector, int scaler) => new IntVector(vector.X / scaler, vector.Y / scaler);
+
+ public static IntVector operator *(IntVector vector, double scaler) => new IntVector((int)(vector.X * scaler), (int)(vector.Y * scaler));
+
+ public static IntVector operator /(IntVector vector, double scaler) => vector * (1 / scaler);
+
+ internal static IntVector Origin = new IntVector(0, 0);
+ internal static IntVector XUnit = new IntVector(1, 0);
+ internal static IntVector YUnit = new IntVector(0, 1);
+
+ internal IntVector(int x, int y)
+ {
+ X = x;
+ Y = y;
+ }
+
+ internal int X { get; }
+
+ internal int Y { get; }
+
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return $"{X},{Y}";
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ItemViewAdapter.cs b/Xamarin.Forms.Platform.Android/Renderers/ItemViewAdapter.cs
new file mode 100644
index 00000000..84dfa171
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ItemViewAdapter.cs
@@ -0,0 +1,89 @@
+using System.Collections.Generic;
+using Android.Support.V7.Widget;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class ItemViewAdapter : RecyclerView.Adapter
+ {
+ readonly IVisualElementRenderer _renderer;
+ readonly Dictionary<int, object> _typeByTypeId;
+ readonly Dictionary<object, int> _typeIdByType;
+ int _nextItemTypeId;
+
+ public ItemViewAdapter(IVisualElementRenderer carouselRenderer)
+ {
+ _renderer = carouselRenderer;
+ _typeByTypeId = new Dictionary<int, object>();
+ _typeIdByType = new Dictionary<object, int>();
+ _nextItemTypeId = 0;
+ }
+
+ public override int ItemCount
+ {
+ get { return Element.Count; }
+ }
+
+ IItemViewController Controller
+ {
+ get { return Element; }
+ }
+
+ ItemsView Element
+ {
+ get { return (ItemsView)_renderer.Element; }
+ }
+
+ public override int GetItemViewType(int position)
+ {
+ // get item and type from ItemSource and ItemTemplate
+ object item = Controller.GetItem(position);
+ object type = Controller.GetItemType(item);
+
+ // map type as DataTemplate to type as Id
+ int id = default(int);
+ if (!_typeIdByType.TryGetValue(type, out id))
+ {
+ id = _nextItemTypeId++;
+ _typeByTypeId[id] = type;
+ _typeIdByType[type] = id;
+ }
+ return id;
+ }
+
+ public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
+ {
+ var carouselHolder = (CarouselViewHolder)holder;
+
+ object item = Controller.GetItem(position);
+ Controller.BindView(carouselHolder.View, item);
+ }
+
+ public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
+ {
+ // create view from type
+ object type = _typeByTypeId[viewType];
+ View view = Controller.CreateView(type);
+
+ // create renderer for view
+ IVisualElementRenderer renderer = Platform.CreateRenderer(view);
+ Platform.SetRenderer(view, renderer);
+
+ // package renderer + view
+ return new CarouselViewHolder(view, renderer);
+ }
+
+ class CarouselViewHolder : RecyclerView.ViewHolder
+ {
+ public CarouselViewHolder(View view, IVisualElementRenderer renderer) : base(renderer.ViewGroup)
+ {
+ VisualElementRenderer = renderer;
+ View = view;
+ }
+
+ public View View { get; }
+
+ public IVisualElementRenderer VisualElementRenderer { get; }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/KeyboardExtensions.cs b/Xamarin.Forms.Platform.Android/Renderers/KeyboardExtensions.cs
new file mode 100644
index 00000000..ab168b6d
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/KeyboardExtensions.cs
@@ -0,0 +1,77 @@
+using Android.Text;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal static class KeyboardExtensions
+ {
+ public static InputTypes ToInputType(this Keyboard self)
+ {
+ var result = new InputTypes();
+
+ // ClassText: !autocaps, spellcheck, suggestions
+ // TextFlagNoSuggestions: !autocaps, !spellcheck, !suggestions
+ // InputTypes.ClassText | InputTypes.TextFlagCapSentences autocaps, spellcheck, suggestions
+ // InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagNoSuggestions; autocaps, !spellcheck, !suggestions
+
+ if (self == Keyboard.Default)
+ result = InputTypes.ClassText | InputTypes.TextVariationNormal;
+ else if (self == Keyboard.Chat)
+ result = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagNoSuggestions;
+ else if (self == Keyboard.Email)
+ result = InputTypes.ClassText | InputTypes.TextVariationEmailAddress;
+ else if (self == Keyboard.Numeric)
+ result = InputTypes.ClassNumber | InputTypes.NumberFlagDecimal;
+ else if (self == Keyboard.Telephone)
+ result = InputTypes.ClassPhone;
+ else if (self == Keyboard.Text)
+ result = InputTypes.ClassText | InputTypes.TextFlagCapSentences;
+ else if (self == Keyboard.Url)
+ result = InputTypes.ClassText | InputTypes.TextVariationUri;
+ else if (self is CustomKeyboard)
+ {
+ var custom = (CustomKeyboard)self;
+ bool capitalizedSentenceEnabled = (custom.Flags & KeyboardFlags.CapitalizeSentence) == KeyboardFlags.CapitalizeSentence;
+ bool spellcheckEnabled = (custom.Flags & KeyboardFlags.Spellcheck) == KeyboardFlags.Spellcheck;
+ bool suggestionsEnabled = (custom.Flags & KeyboardFlags.Suggestions) == KeyboardFlags.Suggestions;
+
+ if (!capitalizedSentenceEnabled && !spellcheckEnabled && !suggestionsEnabled)
+ result = InputTypes.ClassText | InputTypes.TextFlagNoSuggestions;
+
+ if (!capitalizedSentenceEnabled && !spellcheckEnabled && suggestionsEnabled)
+ {
+ // Due to the nature of android, TextFlagAutoCorrect includes Spellcheck
+ Log.Warning(null, "On Android, KeyboardFlags.Suggestions enables KeyboardFlags.Spellcheck as well due to a platform limitation.");
+ result = InputTypes.ClassText | InputTypes.TextFlagAutoCorrect;
+ }
+
+ if (!capitalizedSentenceEnabled && spellcheckEnabled && !suggestionsEnabled)
+ result = InputTypes.ClassText | InputTypes.TextFlagAutoComplete;
+
+ if (!capitalizedSentenceEnabled && spellcheckEnabled && suggestionsEnabled)
+ result = InputTypes.ClassText | InputTypes.TextFlagAutoCorrect;
+
+ if (capitalizedSentenceEnabled && !spellcheckEnabled && !suggestionsEnabled)
+ result = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagNoSuggestions;
+
+ if (capitalizedSentenceEnabled && !spellcheckEnabled && suggestionsEnabled)
+ {
+ // Due to the nature of android, TextFlagAutoCorrect includes Spellcheck
+ Log.Warning(null, "On Android, KeyboardFlags.Suggestions enables KeyboardFlags.Spellcheck as well due to a platform limitation.");
+ result = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagAutoCorrect;
+ }
+
+ if (capitalizedSentenceEnabled && spellcheckEnabled && !suggestionsEnabled)
+ result = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagAutoComplete;
+
+ if (capitalizedSentenceEnabled && spellcheckEnabled && suggestionsEnabled)
+ result = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagAutoCorrect;
+ }
+ else
+ {
+ // Should never happens
+ result = InputTypes.TextVariationNormal;
+ }
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/LabelRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/LabelRenderer.cs
new file mode 100644
index 00000000..45068838
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/LabelRenderer.cs
@@ -0,0 +1,213 @@
+using System;
+using System.ComponentModel;
+using Android.Content.Res;
+using Android.Graphics;
+using Android.Text;
+using Android.Util;
+using Android.Widget;
+using AColor = Android.Graphics.Color;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class LabelRenderer : ViewRenderer<Label, TextView>
+ {
+ ColorStateList _labelTextColorDefault;
+ int _lastConstraintHeight;
+ int _lastConstraintWidth;
+
+ SizeRequest? _lastSizeRequest;
+ float _lastTextSize = -1f;
+ Typeface _lastTypeface;
+
+ Color _lastUpdateColor = Color.Default;
+ FormsTextView _view;
+ bool _wasFormatted;
+
+ public LabelRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ public override SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)
+ {
+ if (_lastSizeRequest.HasValue)
+ {
+ // if we are measuring the same thing, no need to waste the time
+ bool canRecycleLast = widthConstraint == _lastConstraintWidth && heightConstraint == _lastConstraintHeight;
+
+ if (!canRecycleLast)
+ {
+ // if the last time we measured the returned size was all around smaller than the passed constraint
+ // and the constraint is bigger than the last size request, we can assume the newly measured size request
+ // will not change either.
+ int lastConstraintWidthSize = MeasureSpecFactory.GetSize(_lastConstraintWidth);
+ int lastConstraintHeightSize = MeasureSpecFactory.GetSize(_lastConstraintHeight);
+
+ int currentConstraintWidthSize = MeasureSpecFactory.GetSize(widthConstraint);
+ int currentConstraintHeightSize = MeasureSpecFactory.GetSize(heightConstraint);
+
+ bool lastWasSmallerThanConstraints = _lastSizeRequest.Value.Request.Width < lastConstraintWidthSize && _lastSizeRequest.Value.Request.Height < lastConstraintHeightSize;
+
+ bool currentConstraintsBiggerThanLastRequest = currentConstraintWidthSize >= _lastSizeRequest.Value.Request.Width && currentConstraintHeightSize >= _lastSizeRequest.Value.Request.Height;
+
+ canRecycleLast = lastWasSmallerThanConstraints && currentConstraintsBiggerThanLastRequest;
+ }
+
+ if (canRecycleLast)
+ return _lastSizeRequest.Value;
+ }
+
+ SizeRequest result = base.GetDesiredSize(widthConstraint, heightConstraint);
+ result.Minimum = new Size(Math.Min(Context.ToPixels(10), result.Request.Width), result.Request.Height);
+
+ _lastConstraintWidth = widthConstraint;
+ _lastConstraintHeight = heightConstraint;
+ _lastSizeRequest = result;
+
+ return result;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
+ {
+ base.OnElementChanged(e);
+ if (_view == null)
+ {
+ _view = new FormsTextView(Context);
+ _labelTextColorDefault = _view.TextColors;
+ SetNativeControl(_view);
+ }
+
+ if (e.OldElement == null)
+ {
+ UpdateText();
+ UpdateLineBreakMode();
+ UpdateGravity();
+ }
+ else
+ {
+ _view.SkipNextInvalidate();
+ UpdateText();
+ if (e.OldElement.LineBreakMode != e.NewElement.LineBreakMode)
+ UpdateLineBreakMode();
+ if (e.OldElement.HorizontalTextAlignment != e.NewElement.HorizontalTextAlignment || e.OldElement.VerticalTextAlignment != e.NewElement.VerticalTextAlignment)
+ UpdateGravity();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Label.HorizontalTextAlignmentProperty.PropertyName || e.PropertyName == Label.VerticalTextAlignmentProperty.PropertyName)
+ UpdateGravity();
+ else if (e.PropertyName == Label.TextColorProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Label.FontProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Label.LineBreakModeProperty.PropertyName)
+ UpdateLineBreakMode();
+ else if (e.PropertyName == Label.TextProperty.PropertyName || e.PropertyName == Label.FormattedTextProperty.PropertyName)
+ UpdateText();
+ }
+
+ void UpdateColor()
+ {
+ Color c = Element.TextColor;
+ if (c == _lastUpdateColor)
+ return;
+ _lastUpdateColor = c;
+
+ if (c.IsDefault)
+ _view.SetTextColor(_labelTextColorDefault);
+ else
+ _view.SetTextColor(c.ToAndroid());
+ }
+
+ void UpdateFont()
+ {
+ Font f = Element.Font;
+
+ Typeface newTypeface = f.ToTypeface();
+ if (newTypeface != _lastTypeface)
+ {
+ _view.Typeface = newTypeface;
+ _lastTypeface = newTypeface;
+ }
+
+ float newTextSize = f.ToScaledPixel();
+ if (newTextSize != _lastTextSize)
+ {
+ _view.SetTextSize(ComplexUnitType.Sp, newTextSize);
+ _lastTextSize = newTextSize;
+ }
+ }
+
+ void UpdateGravity()
+ {
+ Label label = Element;
+
+ _view.Gravity = label.HorizontalTextAlignment.ToHorizontalGravityFlags() | label.VerticalTextAlignment.ToVerticalGravityFlags();
+
+ _lastSizeRequest = null;
+ }
+
+ void UpdateLineBreakMode()
+ {
+ switch (Element.LineBreakMode)
+ {
+ case LineBreakMode.NoWrap:
+ _view.SetSingleLine(true);
+ _view.Ellipsize = null;
+ break;
+ case LineBreakMode.WordWrap:
+ _view.SetSingleLine(false);
+ _view.Ellipsize = null;
+ _view.SetMaxLines(100);
+ break;
+ case LineBreakMode.CharacterWrap:
+ _view.SetSingleLine(false);
+ _view.Ellipsize = null;
+ _view.SetMaxLines(100);
+ break;
+ case LineBreakMode.HeadTruncation:
+ _view.SetSingleLine(true);
+ _view.Ellipsize = TextUtils.TruncateAt.Start;
+ break;
+ case LineBreakMode.TailTruncation:
+ _view.SetSingleLine(true);
+ _view.Ellipsize = TextUtils.TruncateAt.End;
+ break;
+ case LineBreakMode.MiddleTruncation:
+ _view.SetSingleLine(true);
+ _view.Ellipsize = TextUtils.TruncateAt.Middle;
+ break;
+ }
+ _lastSizeRequest = null;
+ }
+
+ void UpdateText()
+ {
+ if (Element.FormattedText != null)
+ {
+ FormattedString formattedText = Element.FormattedText ?? Element.Text;
+ _view.TextFormatted = formattedText.ToAttributed(Element.Font, Element.TextColor, _view);
+ _wasFormatted = true;
+ }
+ else
+ {
+ if (_wasFormatted)
+ {
+ _view.SetTextColor(_labelTextColorDefault);
+ _lastUpdateColor = Color.Default;
+ }
+ _view.Text = Element.Text;
+ UpdateColor();
+ UpdateFont();
+
+ _wasFormatted = false;
+ }
+
+ _lastSizeRequest = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs b/Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs
new file mode 100644
index 00000000..28f1696e
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs
@@ -0,0 +1,531 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Linq;
+using Android.Content;
+using Android.Util;
+using Android.Views;
+using Android.Widget;
+using AView = Android.Views.View;
+using AListView = Android.Widget.ListView;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal sealed class ListViewAdapter : CellAdapter
+ {
+ const int DefaultGroupHeaderTemplateId = 0;
+ const int DefaultItemTemplateId = 1;
+
+ static int s_dividerHorizontalDarkId = int.MinValue;
+
+ internal static readonly BindableProperty IsSelectedProperty = BindableProperty.CreateAttached("IsSelected", typeof(bool), typeof(Cell), false);
+
+ readonly Context _context;
+ readonly ListView _listView;
+ readonly AListView _realListView;
+ readonly Dictionary<DataTemplate, int> _templateToId = new Dictionary<DataTemplate, int>();
+ int _dataTemplateIncrementer = 2; // lets start at not 0 because
+ Cell _enabledCheckCell;
+
+ bool _fromNative;
+ AView _lastSelected;
+ WeakReference<Cell> _selectedCell;
+
+ public ListViewAdapter(Context context, AListView realListView, ListView listView) : base(context)
+ {
+ _context = context;
+ _realListView = realListView;
+ _listView = listView;
+
+ if (listView.SelectedItem != null)
+ SelectItem(listView.SelectedItem);
+
+ listView.TemplatedItems.CollectionChanged += OnCollectionChanged;
+ listView.TemplatedItems.GroupedCollectionChanged += OnGroupedCollectionChanged;
+ listView.ItemSelected += OnItemSelected;
+
+ realListView.OnItemClickListener = this;
+ realListView.OnItemLongClickListener = this;
+
+ MessagingCenter.Subscribe<Platform>(this, Platform.CloseContextActionsSignalName, p => CloseContextAction());
+ }
+
+ public override int Count
+ {
+ get
+ {
+ int count = _listView.TemplatedItems.Count;
+
+ if (_listView.IsGroupingEnabled)
+ {
+ for (var i = 0; i < _listView.TemplatedItems.Count; i++)
+ count += _listView.TemplatedItems.GetGroup(i).Count;
+ }
+
+ return count;
+ }
+ }
+
+ public AView FooterView { get; set; }
+
+ public override bool HasStableIds
+ {
+ get { return false; }
+ }
+
+ public AView HeaderView { get; set; }
+
+ public bool IsAttachedToWindow { get; set; }
+
+ public override object this[int index]
+ {
+ get
+ {
+ if (_listView.IsGroupingEnabled)
+ {
+ Cell cell = GetCellForPosition(index);
+ return cell.BindingContext;
+ }
+
+ return _listView.ListProxy[index];
+ }
+ }
+
+ public override int ViewTypeCount
+ {
+ get { return 20; }
+ }
+
+ public override bool AreAllItemsEnabled()
+ {
+ return false;
+ }
+
+ public override long GetItemId(int position)
+ {
+ return position;
+ }
+
+ public override int GetItemViewType(int position)
+ {
+ var group = 0;
+ var row = 0;
+ DataTemplate itemTemplate;
+ if (!_listView.IsGroupingEnabled)
+ itemTemplate = _listView.ItemTemplate;
+ else
+ {
+ group = _listView.TemplatedItems.GetGroupIndexFromGlobal(position, out row);
+
+ if (row == 0)
+ {
+ itemTemplate = _listView.GroupHeaderTemplate;
+ if (itemTemplate == null)
+ return DefaultGroupHeaderTemplateId;
+ }
+ else
+ {
+ itemTemplate = _listView.ItemTemplate;
+ row--;
+ }
+ }
+
+ if (itemTemplate == null)
+ return DefaultItemTemplateId;
+
+ var selector = itemTemplate as DataTemplateSelector;
+ if (selector != null)
+ {
+ object item = null;
+ if (_listView.IsGroupingEnabled)
+ item = _listView.TemplatedItems.GetGroup(group).ListProxy[row];
+ else
+ item = _listView.TemplatedItems.ListProxy[position];
+ itemTemplate = selector.SelectTemplate(item, _listView);
+ }
+ int key;
+ if (!_templateToId.TryGetValue(itemTemplate, out key))
+ {
+ _dataTemplateIncrementer++;
+ key = _dataTemplateIncrementer;
+ _templateToId[itemTemplate] = key;
+ }
+ return key;
+ }
+
+ public override AView GetView(int position, AView convertView, ViewGroup parent)
+ {
+ Cell cell = null;
+
+ Performance.Start();
+
+ ListViewCachingStrategy cachingStrategy = _listView.CachingStrategy;
+ var nextCellIsHeader = false;
+ if (cachingStrategy == ListViewCachingStrategy.RetainElement || convertView == null)
+ {
+ if (_listView.IsGroupingEnabled)
+ {
+ List<Cell> cells = GetCellsFromPosition(position, 2);
+ if (cells.Count > 0)
+ cell = cells[0];
+
+ if (cells.Count == 2)
+ nextCellIsHeader = TemplatedItemsList<ItemsView<Cell>, Cell>.GetIsGroupHeader(cells[1]);
+ }
+
+ if (cell == null)
+ {
+ cell = GetCellForPosition(position);
+ if (cell == null)
+ return new AView(_context);
+ }
+ }
+
+ var makeBline = true;
+ var layout = convertView as ConditionalFocusLayout;
+ if (layout != null)
+ {
+ makeBline = false;
+ convertView = layout.GetChildAt(0);
+ }
+ else
+ layout = new ConditionalFocusLayout(_context) { Orientation = Orientation.Vertical };
+
+ if (cachingStrategy == ListViewCachingStrategy.RecycleElement && convertView != null)
+ {
+ var boxedCell = (INativeElementView)convertView;
+ if (boxedCell == null)
+ {
+ throw new InvalidOperationException($"View for cell must implement {nameof(INativeElementView)} to enable recycling.");
+ }
+ cell = (Cell)boxedCell.Element;
+
+ if (ActionModeContext == cell)
+ {
+ // This appears to never happen, the theory is android keeps all views alive that are currently selected for long-press (preventing them from being recycled).
+ // This is convenient since we wont have to worry about the user scrolling the cell offscreen and us losing our context actions.
+ ActionModeContext = null;
+ ContextView = null;
+ }
+ // We are going to re-set the Platform here because in some cases (headers mostly) its possible this is unset and
+ // when the binding context gets updated the measure passes will all fail. By applying this hear the Update call
+ // further down will result in correct layouts.
+ cell.Platform = _listView.Platform;
+
+ cell.SendDisappearing();
+
+ int row = position;
+ var group = 0;
+ if (_listView.IsGroupingEnabled)
+ group = _listView.TemplatedItems.GetGroupIndexFromGlobal(position, out row);
+
+ TemplatedItemsList<ItemsView<Cell>, Cell> templatedList = _listView.TemplatedItems.GetGroup(group);
+
+ if (_listView.IsGroupingEnabled)
+ {
+ if (row == 0)
+ templatedList.UpdateHeader(cell, group);
+ else
+ templatedList.UpdateContent(cell, row - 1);
+ }
+ else
+ templatedList.UpdateContent(cell, row);
+
+ cell.SendAppearing();
+
+ if (cell.BindingContext == ActionModeObject)
+ {
+ ActionModeContext = cell;
+ ContextView = layout;
+ }
+
+ if (ReferenceEquals(_listView.SelectedItem, cell.BindingContext))
+ Select(_listView.IsGroupingEnabled ? row - 1 : row, layout);
+ else if (cell.BindingContext == ActionModeObject)
+ SetSelectedBackground(layout, true);
+ else
+ UnsetSelectedBackground(layout);
+
+ Performance.Stop();
+ return layout;
+ }
+
+ AView view = CellFactory.GetCell(cell, convertView, parent, _context, _listView);
+
+ Performance.Start("AddView");
+
+ if (!makeBline)
+ {
+ if (convertView != view)
+ {
+ layout.RemoveViewAt(0);
+ layout.AddView(view, 0);
+ }
+ }
+ else
+ layout.AddView(view, 0);
+
+ Performance.Stop("AddView");
+
+ AView bline;
+ if (makeBline)
+ {
+ bline = new AView(_context) { LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FillParent, 1) };
+
+ layout.AddView(bline);
+ }
+ else
+ bline = layout.GetChildAt(1);
+
+ bool isHeader = TemplatedItemsList<ItemsView<Cell>, Cell>.GetIsGroupHeader(cell);
+
+ Color separatorColor = _listView.SeparatorColor;
+
+ if (nextCellIsHeader || _listView.SeparatorVisibility == SeparatorVisibility.None)
+ bline.SetBackgroundColor(global::Android.Graphics.Color.Transparent);
+ else if (isHeader || !separatorColor.IsDefault)
+ bline.SetBackgroundColor(separatorColor.ToAndroid(Color.Accent));
+ else
+ {
+ if (s_dividerHorizontalDarkId == int.MinValue)
+ {
+ using(var value = new TypedValue())
+ {
+ int id = global::Android.Resource.Drawable.DividerHorizontalDark;
+ if (_context.Theme.ResolveAttribute(global::Android.Resource.Attribute.ListDivider, value, true))
+ id = value.ResourceId;
+ else if (_context.Theme.ResolveAttribute(global::Android.Resource.Attribute.Divider, value, true))
+ id = value.ResourceId;
+
+ s_dividerHorizontalDarkId = id;
+ }
+ }
+
+ bline.SetBackgroundResource(s_dividerHorizontalDarkId);
+ }
+
+ if ((bool)cell.GetValue(IsSelectedProperty))
+ Select(position, layout);
+ else
+ UnsetSelectedBackground(layout);
+
+ layout.ApplyTouchListenersToSpecialCells(cell);
+
+ Performance.Stop();
+
+ return layout;
+ }
+
+ public override bool IsEnabled(int position)
+ {
+ ListView list = _listView;
+
+ if (list.IsGroupingEnabled)
+ {
+ int leftOver;
+ list.TemplatedItems.GetGroupIndexFromGlobal(position, out leftOver);
+ return leftOver > 0;
+ }
+
+ if (list.CachingStrategy == ListViewCachingStrategy.RecycleElement)
+ {
+ if (_enabledCheckCell == null)
+ _enabledCheckCell = GetCellForPosition(position);
+ else
+ list.TemplatedItems.UpdateContent(_enabledCheckCell, position);
+ return _enabledCheckCell.IsEnabled;
+ }
+
+ Cell item = GetCellForPosition(position);
+ return item.IsEnabled;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ CloseContextAction();
+ MessagingCenter.Unsubscribe<Platform>(this, Platform.CloseContextActionsSignalName);
+ _realListView.OnItemClickListener = null;
+ _realListView.OnItemLongClickListener = null;
+
+ _listView.TemplatedItems.CollectionChanged -= OnCollectionChanged;
+ _listView.TemplatedItems.GroupedCollectionChanged -= OnGroupedCollectionChanged;
+ _listView.ItemSelected -= OnItemSelected;
+
+ if (_lastSelected != null)
+ {
+ _lastSelected.Dispose();
+ _lastSelected = null;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override Cell GetCellForPosition(int position)
+ {
+ return GetCellsFromPosition(position, 1).FirstOrDefault();
+ }
+
+ protected override void HandleItemClick(AdapterView parent, AView view, int position, long id)
+ {
+ Cell cell = null;
+
+ if (_listView.CachingStrategy == ListViewCachingStrategy.RecycleElement)
+ {
+ AView cellOwner = view;
+ var layout = cellOwner as ConditionalFocusLayout;
+ if (layout != null)
+ cellOwner = layout.GetChildAt(0);
+ cell = (Cell)((INativeElementView)cellOwner).Element;
+ }
+
+ // All our ListView's have called AddHeaderView. This effectively becomes index 0, so our index 0 is index 1 to the listView.
+ position--;
+
+ if (position < 0 || position >= Count)
+ return;
+
+ Select(position, view);
+ _fromNative = true;
+ _listView.NotifyRowTapped(position, cell);
+ }
+
+ // TODO: We can optimize this by storing the last position, group index and global index
+ // and increment/decrement from that starting place.
+ List<Cell> GetCellsFromPosition(int position, int take)
+ {
+ var cells = new List<Cell>(take);
+ if (position < 0)
+ return cells;
+
+ if (!_listView.IsGroupingEnabled)
+ {
+ for (var x = 0; x < take; x++)
+ {
+ if (position + x >= _listView.TemplatedItems.Count)
+ return cells;
+
+ cells.Add(_listView.TemplatedItems[x + position]);
+ }
+
+ return cells;
+ }
+
+ var i = 0;
+ var global = 0;
+ for (; i < _listView.TemplatedItems.Count; i++)
+ {
+ TemplatedItemsList<ItemsView<Cell>, Cell> group = _listView.TemplatedItems.GetGroup(i);
+
+ if (global == position || cells.Count > 0)
+ {
+ cells.Add(group.HeaderContent);
+ if (cells.Count == take)
+ return cells;
+ }
+
+ global++;
+
+ if (global + group.Count < position)
+ {
+ global += group.Count;
+ continue;
+ }
+
+ for (var g = 0; g < group.Count; g++)
+ {
+ if (global == position || cells.Count > 0)
+ {
+ cells.Add(group[g]);
+ if (cells.Count == take)
+ return cells;
+ }
+
+ global++;
+ }
+ }
+
+ return cells;
+ }
+
+ void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ OnDataChanged();
+ }
+
+ void OnDataChanged()
+ {
+ if (IsAttachedToWindow)
+ NotifyDataSetChanged();
+ else
+ {
+ // In a TabbedPage page with two pages, Page A and Page B with ListView, if A changes B's ListView,
+ // we need to reset the ListView's adapter to reflect the changes on page B
+ // If there header and footer are present at the reset time of the adapter
+ // they will be DOUBLE added to the ViewGround (the ListView) causing indexes to be off by one.
+ _realListView.RemoveHeaderView(HeaderView);
+ _realListView.RemoveFooterView(FooterView);
+ _realListView.Adapter = _realListView.Adapter;
+ _realListView.AddHeaderView(HeaderView);
+ _realListView.AddFooterView(FooterView);
+ }
+ }
+
+ void OnGroupedCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ OnDataChanged();
+ }
+
+ void OnItemSelected(object sender, SelectedItemChangedEventArgs eventArg)
+ {
+ if (_fromNative)
+ {
+ _fromNative = false;
+ return;
+ }
+
+ SelectItem(eventArg.SelectedItem);
+ }
+
+ void Select(int index, AView view)
+ {
+ if (_lastSelected != null)
+ {
+ UnsetSelectedBackground(_lastSelected);
+ Cell previousCell;
+ if (_selectedCell.TryGetTarget(out previousCell))
+ previousCell.SetValue(IsSelectedProperty, false);
+ }
+
+ _lastSelected = view;
+
+ if (index == -1)
+ return;
+
+ Cell cell = GetCellForPosition(index);
+ cell.SetValue(IsSelectedProperty, true);
+ _selectedCell = new WeakReference<Cell>(cell);
+
+ if (view != null)
+ SetSelectedBackground(view);
+ }
+
+ void SelectItem(object item)
+ {
+ int position = _listView.TemplatedItems.GetGlobalIndexOfItem(item);
+ AView view = null;
+ if (position != -1)
+ view = _realListView.GetChildAt(position + 1 - _realListView.FirstVisiblePosition);
+
+ Select(position, view);
+ }
+
+ enum CellType
+ {
+ Row,
+ Header
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs
new file mode 100644
index 00000000..06a9554c
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs
@@ -0,0 +1,355 @@
+using System.ComponentModel;
+using Android.App;
+using Android.Content;
+using Android.Support.V4.Widget;
+using Android.Views;
+using AListView = Android.Widget.ListView;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class ListViewRenderer : ViewRenderer<ListView, AListView>, SwipeRefreshLayout.IOnRefreshListener
+ {
+ ListViewAdapter _adapter;
+ IVisualElementRenderer _headerRenderer;
+ IVisualElementRenderer _footerRenderer;
+ Container _headerView;
+ Container _footerView;
+ bool _isAttached;
+ ScrollToRequestedEventArgs _pendingScrollTo;
+
+ SwipeRefreshLayout _refresh;
+
+ public ListViewRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ void SwipeRefreshLayout.IOnRefreshListener.OnRefresh()
+ {
+ IListViewController controller = Element;
+ controller.SendRefreshing();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (_headerView == null)
+ return;
+
+ if (_headerRenderer != null)
+ {
+ _headerRenderer.ViewGroup.RemoveAllViews();
+ _headerRenderer.Dispose();
+ _headerRenderer = null;
+ }
+
+ if (_footerRenderer != null)
+ {
+ _footerRenderer.ViewGroup.RemoveAllViews();
+ _footerRenderer.Dispose();
+ _footerRenderer = null;
+ }
+
+ _headerView.Dispose();
+ _headerView = null;
+
+ _footerView.Dispose();
+ _footerView = null;
+
+ if (_adapter != null)
+ {
+ _adapter.Dispose();
+ _adapter = null;
+ }
+
+ Element.ScrollToRequested -= OnScrollToRequested;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override Size MinimumSize()
+ {
+ return new Size(40, 40);
+ }
+
+ protected override void OnAttachedToWindow()
+ {
+ base.OnAttachedToWindow();
+
+ _isAttached = true;
+ _adapter.IsAttachedToWindow = _isAttached;
+ }
+
+ protected override void OnDetachedFromWindow()
+ {
+ base.OnDetachedFromWindow();
+
+ _isAttached = false;
+ _adapter.IsAttachedToWindow = _isAttached;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ {
+ e.OldElement.ScrollToRequested -= OnScrollToRequested;
+
+ if (_adapter != null)
+ {
+ _adapter.Dispose();
+ _adapter = null;
+ }
+ }
+
+ if (e.NewElement != null)
+ {
+ AListView nativeListView = Control;
+ if (nativeListView == null)
+ {
+ var ctx = (Activity)Context;
+ nativeListView = new AListView(ctx);
+ _refresh = new SwipeRefreshLayout(ctx);
+ _refresh.SetOnRefreshListener(this);
+ _refresh.AddView(nativeListView, LayoutParams.MatchParent);
+ SetNativeControl(nativeListView, _refresh);
+
+ _headerView = new Container(ctx);
+ nativeListView.AddHeaderView(_headerView, null, false);
+ _footerView = new Container(ctx);
+ nativeListView.AddFooterView(_footerView, null, false);
+ }
+
+ e.NewElement.ScrollToRequested += OnScrollToRequested;
+
+ nativeListView.DividerHeight = 0;
+ nativeListView.Focusable = false;
+ nativeListView.DescendantFocusability = DescendantFocusability.AfterDescendants;
+ nativeListView.OnFocusChangeListener = this;
+ nativeListView.Adapter = _adapter = new ListViewAdapter(Context, nativeListView, e.NewElement);
+ _adapter.HeaderView = _headerView;
+ _adapter.FooterView = _footerView;
+ _adapter.IsAttachedToWindow = _isAttached;
+
+ UpdateHeader();
+ UpdateFooter();
+ UpdateIsSwipeToRefreshEnabled();
+ UpdateIsRefreshing();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == "HeaderElement")
+ UpdateHeader();
+ else if (e.PropertyName == "FooterElement")
+ UpdateFooter();
+ else if (e.PropertyName == "RefreshAllowed")
+ UpdateIsSwipeToRefreshEnabled();
+ else if (e.PropertyName == ListView.IsPullToRefreshEnabledProperty.PropertyName)
+ UpdateIsSwipeToRefreshEnabled();
+ else if (e.PropertyName == ListView.IsRefreshingProperty.PropertyName)
+ UpdateIsRefreshing();
+ else if (e.PropertyName == ListView.SeparatorColorProperty.PropertyName || e.PropertyName == ListView.SeparatorVisibilityProperty.PropertyName)
+ _adapter.NotifyDataSetChanged();
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ base.OnLayout(changed, l, t, r, b);
+
+ if (_pendingScrollTo != null)
+ {
+ OnScrollToRequested(this, _pendingScrollTo);
+ _pendingScrollTo = null;
+ }
+ }
+
+ void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
+ {
+ if (!_isAttached)
+ {
+ _pendingScrollTo = e;
+ return;
+ }
+
+ Cell cell;
+ int position;
+
+ if (Element.IsGroupingEnabled)
+ {
+ var results = Element.TemplatedItems.GetGroupAndIndexOfItem(e.Group, e.Item);
+ if (results.Item1 == -1 || results.Item2 == -1)
+ return;
+
+ TemplatedItemsList<ItemsView<Cell>, Cell> group = Element.TemplatedItems.GetGroup(results.Item1);
+ cell = group[results.Item2];
+
+ position = Element.TemplatedItems.GetGlobalIndexForGroup(group) + results.Item2 + 1;
+ }
+ else
+ {
+ position = Element.TemplatedItems.GetGlobalIndexOfItem(e.Item);
+ cell = Element.TemplatedItems[position];
+ }
+
+ //Android offsets position of cells when using header
+ int realPositionWithHeader = position + 1;
+
+ if (e.Position == ScrollToPosition.MakeVisible)
+ {
+ if (e.ShouldAnimate)
+ Control.SmoothScrollToPosition(realPositionWithHeader);
+ else
+ Control.SetSelection(realPositionWithHeader);
+ return;
+ }
+
+ int height = Control.Height;
+ var cellHeight = (int)cell.RenderHeight;
+ if (cellHeight == -1)
+ {
+ int first = Control.FirstVisiblePosition;
+ if (first <= position && position <= Control.LastVisiblePosition)
+ cellHeight = Control.GetChildAt(position - first).Height;
+ else
+ {
+ AView view = _adapter.GetView(position, null, null);
+ view.Measure(MeasureSpecFactory.MakeMeasureSpec(Control.Width, MeasureSpecMode.AtMost), MeasureSpecFactory.MakeMeasureSpec(0, MeasureSpecMode.Unspecified));
+ cellHeight = view.MeasuredHeight;
+ }
+ }
+
+ var y = 0;
+
+ if (e.Position == ScrollToPosition.Center)
+ y = height / 2 - cellHeight / 2;
+ else if (e.Position == ScrollToPosition.End)
+ y = height - cellHeight;
+
+ if (e.ShouldAnimate)
+ Control.SmoothScrollToPositionFromTop(realPositionWithHeader, y);
+ else
+ Control.SetSelectionFromTop(realPositionWithHeader, y);
+ }
+
+ void UpdateFooter()
+ {
+ var footer = (VisualElement)((IListViewController)Element).FooterElement;
+ if (_footerRenderer != null && (footer == null || Registrar.Registered.GetHandlerType(footer.GetType()) != _footerRenderer.GetType()))
+ {
+ _footerView.Child = null;
+ _footerRenderer.Dispose();
+ _footerRenderer = null;
+ }
+
+ if (footer == null)
+ return;
+
+ if (_footerRenderer != null)
+ _footerRenderer.SetElement(footer);
+ else
+ {
+ _footerRenderer = Platform.CreateRenderer(footer);
+ _footerView.Child = _footerRenderer;
+ }
+
+ Platform.SetRenderer(footer, _footerRenderer);
+ }
+
+ void UpdateHeader()
+ {
+ var header = (VisualElement)((IListViewController)Element).HeaderElement;
+ if (_headerRenderer != null && (header == null || Registrar.Registered.GetHandlerType(header.GetType()) != _headerRenderer.GetType()))
+ {
+ _headerView.Child = null;
+ _headerRenderer.Dispose();
+ _headerRenderer = null;
+ }
+
+ if (header == null)
+ return;
+
+ if (_headerRenderer != null)
+ _headerRenderer.SetElement(header);
+ else
+ {
+ _headerRenderer = Platform.CreateRenderer(header);
+ _headerView.Child = _headerRenderer;
+ }
+
+ Platform.SetRenderer(header, _headerRenderer);
+ }
+
+ void UpdateIsRefreshing()
+ {
+ _refresh.Refreshing = Element.IsRefreshing;
+ }
+
+ void UpdateIsSwipeToRefreshEnabled()
+ {
+ _refresh.Enabled = Element.IsPullToRefreshEnabled && (Element as IListViewController).RefreshAllowed;
+ }
+
+ internal class Container : ViewGroup
+ {
+ IVisualElementRenderer _child;
+
+ public Container(Context context) : base(context)
+ {
+ }
+
+ public IVisualElementRenderer Child
+ {
+ set
+ {
+ if (_child != null)
+ RemoveView(_child.ViewGroup);
+
+ _child = value;
+
+ if (value != null)
+ AddView(value.ViewGroup);
+ }
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ if (_child == null)
+ return;
+
+ _child.UpdateLayout();
+ }
+
+ protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
+ {
+ if (_child == null)
+ {
+ SetMeasuredDimension(0, 0);
+ return;
+ }
+
+ VisualElement element = _child.Element;
+
+ Context ctx = Context;
+
+ var width = (int)ctx.FromPixels(MeasureSpecFactory.GetSize(widthMeasureSpec));
+
+ SizeRequest request = _child.Element.Measure(width, double.PositiveInfinity, MeasureFlags.IncludeMargins);
+ Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion(_child.Element, new Rectangle(0, 0, width, request.Request.Height));
+
+ int widthSpec = MeasureSpecFactory.MakeMeasureSpec((int)ctx.ToPixels(width), MeasureSpecMode.Exactly);
+ int heightSpec = MeasureSpecFactory.MakeMeasureSpec((int)ctx.ToPixels(request.Request.Height), MeasureSpecMode.Exactly);
+
+ _child.ViewGroup.Measure(widthMeasureSpec, heightMeasureSpec);
+ SetMeasuredDimension(widthSpec, heightSpec);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/MasterDetailContainer.cs b/Xamarin.Forms.Platform.Android/Renderers/MasterDetailContainer.cs
new file mode 100644
index 00000000..6f92d90f
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/MasterDetailContainer.cs
@@ -0,0 +1,138 @@
+using Android.Content;
+using Android.Content.Res;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class MasterDetailContainer : ViewGroup
+ {
+ const int DefaultMasterSize = 320;
+ const int DefaultSmallMasterSize = 240;
+ readonly bool _isMaster;
+ readonly MasterDetailPage _parent;
+ VisualElement _childView;
+
+ public MasterDetailContainer(MasterDetailPage parent, bool isMaster, Context context) : base(context)
+ {
+ _parent = parent;
+ _isMaster = isMaster;
+ }
+
+ public VisualElement ChildView
+ {
+ get { return _childView; }
+ set
+ {
+ if (_childView == value)
+ return;
+
+ RemoveAllViews();
+ if (_childView != null)
+ DisposeChildRenderers();
+
+ _childView = value;
+
+ if (_childView == null)
+ return;
+
+ IVisualElementRenderer renderer = Platform.GetRenderer(_childView);
+ if (renderer == null)
+ Platform.SetRenderer(_childView, renderer = Platform.CreateRenderer(_childView));
+
+ if (renderer.ViewGroup.Parent != this)
+ {
+ if (renderer.ViewGroup.Parent != null)
+ renderer.ViewGroup.RemoveFromParent();
+ SetDefaultBackgroundColor(renderer);
+ AddView(renderer.ViewGroup);
+ renderer.UpdateLayout();
+ }
+ }
+ }
+
+ public int TopPadding { get; set; }
+
+ double DefaultWidthMaster
+ {
+ get
+ {
+ double w = Context.FromPixels(Resources.DisplayMetrics.WidthPixels);
+ return w < DefaultSmallMasterSize ? w : (w < DefaultMasterSize ? DefaultSmallMasterSize : DefaultMasterSize);
+ }
+ }
+
+ public override bool OnInterceptTouchEvent(MotionEvent ev)
+ {
+ bool isShowingPopover = _parent.IsPresented && !_parent.ShouldShowSplitMode;
+ if (!_isMaster && isShowingPopover)
+ return true;
+ return base.OnInterceptTouchEvent(ev);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ RemoveAllViews();
+ DisposeChildRenderers();
+ }
+ base.Dispose(disposing);
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ if (_childView == null)
+ return;
+
+ Rectangle bounds = GetBounds(_isMaster, l, t, r, b);
+ if (_isMaster)
+ _parent.MasterBounds = bounds;
+ else
+ _parent.DetailBounds = bounds;
+
+ IVisualElementRenderer renderer = Platform.GetRenderer(_childView);
+ renderer.UpdateLayout();
+ }
+
+ void DisposeChildRenderers()
+ {
+ IVisualElementRenderer childRenderer = Platform.GetRenderer(_childView);
+ if (childRenderer != null)
+ childRenderer.Dispose();
+ _childView.ClearValue(Platform.RendererProperty);
+ }
+
+ Rectangle GetBounds(bool isMasterPage, int left, int top, int right, int bottom)
+ {
+ double width = Context.FromPixels(right - left);
+ double height = Context.FromPixels(bottom - top);
+ double xPos = 0;
+
+ //splitview
+ if (_parent.ShouldShowSplitMode)
+ {
+ //to keep some behavior we have on iPad where you can toggle and it won't do anything
+ bool isDefaultNoToggle = _parent.MasterBehavior == MasterBehavior.Default;
+ xPos = isMasterPage ? 0 : (_parent.IsPresented || isDefaultNoToggle ? DefaultWidthMaster : 0);
+ width = isMasterPage ? DefaultWidthMaster : _parent.IsPresented || isDefaultNoToggle ? width - DefaultWidthMaster : width;
+ }
+ else
+ {
+ //popover make the master smaller
+ width = isMasterPage && (Device.Info.CurrentOrientation.IsLandscape() || Device.Idiom == TargetIdiom.Tablet) ? DefaultWidthMaster : width;
+ }
+
+ double padding = Context.FromPixels(TopPadding);
+ return new Rectangle(xPos, padding, width, height - padding);
+ }
+
+ void SetDefaultBackgroundColor(IVisualElementRenderer renderer)
+ {
+ if (ChildView.BackgroundColor == Color.Default)
+ {
+ TypedArray colors = Context.Theme.ObtainStyledAttributes(new[] { global::Android.Resource.Attribute.ColorBackground });
+ renderer.ViewGroup.SetBackgroundColor(new global::Android.Graphics.Color(colors.GetColor(0, 0)));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/MasterDetailRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/MasterDetailRenderer.cs
new file mode 100644
index 00000000..ce3fb267
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/MasterDetailRenderer.cs
@@ -0,0 +1,348 @@
+using System;
+using System.ComponentModel;
+using System.Threading.Tasks;
+using Android.App;
+using Android.Support.V4.Widget;
+using Android.Views;
+using AView = Android.Views.View;
+using AColor = Android.Graphics.Drawables.ColorDrawable;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class MasterDetailRenderer : DrawerLayout, IVisualElementRenderer, DrawerLayout.IDrawerListener
+ {
+ //from Android source code
+ const uint DefaultScrimColor = 0x99000000;
+ int _currentLockMode = -1;
+ MasterDetailContainer _detailLayout;
+ bool _isPresentingFromCore;
+ MasterDetailContainer _masterLayout;
+ MasterDetailPage _page;
+ bool _presented;
+
+ public MasterDetailRenderer() : base(Forms.Context)
+ {
+ }
+
+ public bool Presented
+ {
+ get { return _presented; }
+ set
+ {
+ if (value == _presented)
+ return;
+ UpdateSplitViewLayout();
+ _presented = value;
+ if (_page.MasterBehavior == MasterBehavior.Default && _page.ShouldShowSplitMode)
+ return;
+ if (_presented)
+ OpenDrawer(_masterLayout);
+ else
+ CloseDrawer(_masterLayout);
+ }
+ }
+
+ public void OnDrawerClosed(AView drawerView)
+ {
+ }
+
+ public void OnDrawerOpened(AView drawerView)
+ {
+ }
+
+ public void OnDrawerSlide(AView drawerView, float slideOffset)
+ {
+ }
+
+ public void OnDrawerStateChanged(int newState)
+ {
+ _presented = IsDrawerVisible(_masterLayout);
+ UpdateIsPresented();
+ }
+
+ public VisualElement Element
+ {
+ get { return _page; }
+ }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)
+ {
+ Measure(widthConstraint, heightConstraint);
+ return new SizeRequest(new Size(MeasuredWidth, MeasuredHeight));
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ MasterDetailPage oldElement = _page;
+ _page = element as MasterDetailPage;
+
+ _detailLayout = new MasterDetailContainer(_page, false, Context) { LayoutParameters = new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent) };
+
+ _masterLayout = new MasterDetailContainer(_page, true, Context)
+ {
+ LayoutParameters = new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent) { Gravity = (int)GravityFlags.Start }
+ };
+
+ AddView(_detailLayout);
+
+ AddView(_masterLayout);
+
+ var activity = Context as Activity;
+ activity.ActionBar.SetDisplayShowHomeEnabled(true);
+ activity.ActionBar.SetHomeButtonEnabled(true);
+
+ UpdateBackgroundColor(_page);
+ UpdateBackgroundImage(_page);
+
+ OnElementChanged(oldElement, element);
+
+ if (oldElement != null)
+ oldElement.BackButtonPressed -= OnBackButtonPressed;
+
+ if (_page != null)
+ _page.BackButtonPressed += OnBackButtonPressed;
+
+ if (Tracker == null)
+ Tracker = new VisualElementTracker(this);
+
+ _page.PropertyChanged += HandlePropertyChanged;
+ _page.Appearing += MasterDetailPageAppearing;
+ _page.Disappearing += MasterDetailPageDisappearing;
+
+ UpdateMaster();
+ UpdateDetail();
+
+ Device.Info.PropertyChanged += DeviceInfoPropertyChanged;
+ SetGestureState();
+
+ Presented = _page.IsPresented;
+
+ SetDrawerListener(this);
+
+ if (element != null)
+ element.SendViewInitialized(this);
+
+ if (element != null && !string.IsNullOrEmpty(element.AutomationId))
+ ContentDescription = element.AutomationId;
+ }
+
+ public VisualElementTracker Tracker { get; private set; }
+
+ public void UpdateLayout()
+ {
+ if (Tracker != null)
+ Tracker.UpdateLayout();
+ }
+
+ public ViewGroup ViewGroup
+ {
+ get { return this; }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (Tracker != null)
+ {
+ Tracker.Dispose();
+ Tracker = null;
+ }
+
+ if (_detailLayout != null)
+ {
+ _detailLayout.Dispose();
+ _detailLayout = null;
+ }
+
+ if (_masterLayout != null)
+ {
+ _masterLayout.Dispose();
+ _masterLayout = null;
+ }
+
+ Device.Info.PropertyChanged -= DeviceInfoPropertyChanged;
+
+ if (_page != null)
+ {
+ _page.BackButtonPressed -= OnBackButtonPressed;
+ _page.PropertyChanged -= HandlePropertyChanged;
+ _page.Appearing -= MasterDetailPageAppearing;
+ _page.Disappearing -= MasterDetailPageDisappearing;
+ _page.ClearValue(Platform.RendererProperty);
+ _page = null;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnAttachedToWindow()
+ {
+ base.OnAttachedToWindow();
+ ((Page)Element).SendAppearing();
+ }
+
+ protected override void OnDetachedFromWindow()
+ {
+ base.OnDetachedFromWindow();
+ ((Page)Element).SendDisappearing();
+ }
+
+ protected virtual void OnElementChanged(VisualElement oldElement, VisualElement newElement)
+ {
+ EventHandler<VisualElementChangedEventArgs> changed = ElementChanged;
+ if (changed != null)
+ changed(this, new VisualElementChangedEventArgs(oldElement, newElement));
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ base.OnLayout(changed, l, t, r, b);
+ //hack to make the split layout handle touches the full width
+ if (_page.ShouldShowSplitMode && _masterLayout != null)
+ _masterLayout.Right = r;
+ }
+
+ async void DeviceInfoPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "CurrentOrientation")
+ {
+ if (!_page.ShouldShowSplitMode && Presented)
+ {
+ _page.CanChangeIsPresented = true;
+ //hack : when the orientation changes and we try to close the Master on Android
+ //sometimes Android picks the width of the screen previous to the rotation
+ //this leaves a little of the master visible, the hack is to delay for 50ms closing the drawer
+ await Task.Delay(50);
+ CloseDrawer(_masterLayout);
+ }
+ UpdateSplitViewLayout();
+ }
+ }
+
+ void HandleMasterPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Page.TitleProperty.PropertyName || e.PropertyName == Page.IconProperty.PropertyName)
+ ((Platform)_page.Platform).UpdateMasterDetailToggle(true);
+ }
+
+ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "Master")
+ UpdateMaster();
+ else if (e.PropertyName == "Detail")
+ {
+ UpdateDetail();
+ ((Platform)_page.Platform).UpdateActionBar();
+ }
+ else if (e.PropertyName == MasterDetailPage.IsPresentedProperty.PropertyName)
+ {
+ _isPresentingFromCore = true;
+ Presented = _page.IsPresented;
+ _isPresentingFromCore = false;
+ }
+ else if (e.PropertyName == "IsGestureEnabled")
+ SetGestureState();
+ else if (e.PropertyName == Page.BackgroundImageProperty.PropertyName)
+ UpdateBackgroundImage(_page);
+ if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackgroundColor(_page);
+ }
+
+ void MasterDetailPageAppearing(object sender, EventArgs e)
+ {
+ if (_page.Master != null)
+ _page.Master.SendAppearing();
+
+ if (_page.Detail != null)
+ _page.Detail.SendAppearing();
+ }
+
+ void MasterDetailPageDisappearing(object sender, EventArgs e)
+ {
+ if (_page.Master != null)
+ _page.Master.SendDisappearing();
+
+ if (_page.Detail != null)
+ _page.Detail.SendDisappearing();
+ }
+
+ void OnBackButtonPressed(object sender, BackButtonPressedEventArgs backButtonPressedEventArgs)
+ {
+ if (IsDrawerOpen((int)GravityFlags.Start))
+ {
+ if (_currentLockMode != LockModeLockedOpen)
+ {
+ CloseDrawer((int)GravityFlags.Start);
+ backButtonPressedEventArgs.Handled = true;
+ }
+ }
+ }
+
+ void SetGestureState()
+ {
+ SetDrawerLockMode(_page.IsGestureEnabled ? LockModeUnlocked : LockModeLockedClosed);
+ }
+
+ void SetLockMode(int lockMode)
+ {
+ if (_currentLockMode != lockMode)
+ {
+ SetDrawerLockMode(lockMode);
+ _currentLockMode = lockMode;
+ }
+ }
+
+ void UpdateBackgroundColor(Page view)
+ {
+ if (view.BackgroundColor != Color.Default)
+ SetBackgroundColor(view.BackgroundColor.ToAndroid());
+ }
+
+ void UpdateBackgroundImage(Page view)
+ {
+ if (!string.IsNullOrEmpty(view.BackgroundImage))
+ SetBackgroundDrawable(Context.Resources.GetDrawable(view.BackgroundImage));
+ }
+
+ void UpdateDetail()
+ {
+ Context.HideKeyboard(this);
+ _detailLayout.ChildView = _page.Detail;
+ }
+
+ void UpdateIsPresented()
+ {
+ if (_isPresentingFromCore)
+ return;
+ if (Presented != _page.IsPresented)
+ ((IElementController)_page).SetValueFromRenderer(MasterDetailPage.IsPresentedProperty, Presented);
+ }
+
+ void UpdateMaster()
+ {
+ if (_masterLayout != null && _masterLayout.ChildView != null)
+ _masterLayout.ChildView.PropertyChanged -= HandleMasterPropertyChanged;
+ _masterLayout.ChildView = _page.Master;
+ if (_page.Master != null)
+ _page.Master.PropertyChanged += HandleMasterPropertyChanged;
+ }
+
+ void UpdateSplitViewLayout()
+ {
+ if (Device.Idiom == TargetIdiom.Tablet)
+ {
+ bool isShowingSplit = _page.ShouldShowSplitMode || (_page.ShouldShowSplitMode && _page.MasterBehavior != MasterBehavior.Default && _page.IsPresented);
+ SetLockMode(isShowingSplit ? LockModeLockedOpen : LockModeUnlocked);
+ unchecked
+ {
+ SetScrimColor(isShowingSplit ? Color.Transparent.ToAndroid() : (int)DefaultScrimColor);
+ }
+ ((Platform)_page.Platform).UpdateMasterDetailToggle();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/MeasureSpecification.cs b/Xamarin.Forms.Platform.Android/Renderers/MeasureSpecification.cs
new file mode 100644
index 00000000..fe38a560
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/MeasureSpecification.cs
@@ -0,0 +1,41 @@
+namespace Xamarin.Forms.Platform.Android
+{
+ internal struct MeasureSpecification
+ {
+ public static explicit operator MeasureSpecification(int measureSpecification)
+ {
+ return new MeasureSpecification(measureSpecification);
+ }
+
+ public static implicit operator int(MeasureSpecification measureSpecification)
+ {
+ return measureSpecification.Encode();
+ }
+
+ internal MeasureSpecification(int measureSpecification)
+ {
+ Value = measureSpecification & (int)~MeasureSpecificationType.Mask;
+ Type = (MeasureSpecificationType)(measureSpecification & (int)MeasureSpecificationType.Mask);
+ }
+
+ internal MeasureSpecification(int value, MeasureSpecificationType measureSpecification)
+ {
+ Value = value;
+ Type = measureSpecification;
+ }
+
+ internal int Value { get; }
+
+ internal MeasureSpecificationType Type { get; }
+
+ internal int Encode()
+ {
+ return Value | (int)Type;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{0} {1}", Value, Type);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/MeasureSpecificationType.cs b/Xamarin.Forms.Platform.Android/Renderers/MeasureSpecificationType.cs
new file mode 100644
index 00000000..bb61d841
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/MeasureSpecificationType.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ [Flags]
+ internal enum MeasureSpecificationType
+ {
+ Unspecified = 0,
+ Exactly = 0x1 << 31,
+ AtMost = 0x1 << 32,
+ Mask = Exactly | AtMost
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/NavigationMenuRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/NavigationMenuRenderer.cs
new file mode 100644
index 00000000..9678b9ca
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/NavigationMenuRenderer.cs
@@ -0,0 +1,152 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using Android.Content;
+using Android.Graphics;
+using Android.Views;
+using Android.Widget;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public sealed class NavigationMenuRenderer : ViewRenderer
+ {
+ public NavigationMenuRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ GridView GridView
+ {
+ get { return Control as GridView; }
+ }
+
+ NavigationMenu NavigationMenu
+ {
+ get { return Element as NavigationMenu; }
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<View> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement == null)
+ {
+ var grid = new GridView(Context);
+ grid.SetVerticalSpacing(20);
+
+ SetNativeControl(grid);
+ }
+
+ UpdateTargets();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ switch (e.PropertyName)
+ {
+ case "Targets":
+ UpdateTargets();
+ break;
+ }
+ }
+
+ protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
+ {
+ GridView.NumColumns = w > h ? 3 : 2;
+ base.OnSizeChanged(w, h, oldw, oldh);
+ }
+
+ void UpdateTargets()
+ {
+ GridView.Adapter = new MenuAdapter(NavigationMenu);
+ }
+
+ class MenuElementView : LinearLayout
+ {
+ readonly ImageButton _image;
+ readonly TextView _label;
+ string _icon;
+
+ public MenuElementView(Context context) : base(context)
+ {
+ Orientation = Orientation.Vertical;
+ _image = new ImageButton(context);
+ _image.SetScaleType(ImageView.ScaleType.FitCenter);
+ _image.Click += (object sender, EventArgs e) =>
+ {
+ if (Selected != null)
+ Selected();
+ };
+ AddView(_image, new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent) { Gravity = GravityFlags.Center });
+
+ _label = new TextView(context) { TextAlignment = global::Android.Views.TextAlignment.Center, Gravity = GravityFlags.Center };
+ AddView(_label, new LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent));
+ }
+
+ public string Icon
+ {
+ get { return _icon; }
+ set
+ {
+ _icon = value;
+ Bitmap bitmap = Context.Resources.GetBitmap(_icon);
+ _image.SetImageBitmap(bitmap);
+ }
+ }
+
+ public string Name
+ {
+ get { return _label.Text; }
+ set { _label.Text = value; }
+ }
+
+ public Action Selected { get; set; }
+ }
+
+ class MenuAdapter : BaseAdapter<Page>
+ {
+ readonly NavigationMenu _menu;
+
+ public MenuAdapter(NavigationMenu menu)
+ {
+ _menu = menu;
+ }
+
+ #region implemented abstract members of BaseAdapter
+
+ public override Page this[int index]
+ {
+ get { return _menu.Targets.ElementAtOrDefault(index); }
+ }
+
+ #endregion
+
+ public override AView GetView(int position, AView convertView, ViewGroup parent)
+ {
+ MenuElementView menuItem = convertView as MenuElementView ?? new MenuElementView(parent.Context);
+ Page item = this[position];
+ menuItem.Icon = item.Icon;
+ menuItem.Name = item.Title;
+ menuItem.Selected = () => _menu.SendTargetSelected(item);
+ return menuItem;
+ }
+
+ #region implemented abstract members of BaseAdapter
+
+ public override long GetItemId(int position)
+ {
+ return 0;
+ }
+
+ public override int Count
+ {
+ get { return _menu.Targets.Count(); }
+ }
+
+ #endregion
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/NavigationRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/NavigationRenderer.cs
new file mode 100644
index 00000000..f0e6dc73
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/NavigationRenderer.cs
@@ -0,0 +1,302 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Android.Views;
+using AButton = Android.Widget.Button;
+using AView = Android.Views.View;
+using AndroidAnimation = Android.Animation;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class NavigationRenderer : VisualElementRenderer<NavigationPage>
+ {
+ static ViewPropertyAnimator s_currentAnimation;
+
+ Page _current;
+ Page _exitingPage;
+
+ public NavigationRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ public Task<bool> PopToRootAsync(Page page, bool animated = true)
+ {
+ return OnPopToRootAsync(page, animated);
+ }
+
+ public Task<bool> PopViewAsync(Page page, bool animated = true)
+ {
+ return OnPopViewAsync(page, animated);
+ }
+
+ public Task<bool> PushViewAsync(Page page, bool animated = true)
+ {
+ return OnPushAsync(page, animated);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ foreach (VisualElement child in Element.InternalChildren)
+ {
+ IVisualElementRenderer renderer = Platform.GetRenderer(child);
+ if (renderer != null)
+ renderer.Dispose();
+ }
+
+ if (Element != null)
+ {
+ Element.PushRequested -= OnPushed;
+ Element.PopRequested -= OnPopped;
+ Element.PopToRootRequested -= OnPoppedToRoot;
+ Element.InsertPageBeforeRequested -= OnInsertPageBeforeRequested;
+ Element.RemovePageRequested -= OnRemovePageRequested;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnAttachedToWindow()
+ {
+ base.OnAttachedToWindow();
+ Element.SendAppearing();
+ }
+
+ protected override void OnDetachedFromWindow()
+ {
+ base.OnDetachedFromWindow();
+ Element.SendDisappearing();
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<NavigationPage> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ {
+ NavigationPage oldNav = e.OldElement;
+ oldNav.PushRequested -= OnPushed;
+ oldNav.PopRequested -= OnPopped;
+ oldNav.PopToRootRequested -= OnPoppedToRoot;
+ oldNav.InsertPageBeforeRequested -= OnInsertPageBeforeRequested;
+ oldNav.RemovePageRequested -= OnRemovePageRequested;
+
+ RemoveAllViews();
+ }
+
+ NavigationPage nav = e.NewElement;
+ nav.PushRequested += OnPushed;
+ nav.PopRequested += OnPopped;
+ nav.PopToRootRequested += OnPoppedToRoot;
+ nav.InsertPageBeforeRequested += OnInsertPageBeforeRequested;
+ nav.RemovePageRequested += OnRemovePageRequested;
+
+ // If there is already stuff on the stack we need to push it
+ nav.StackCopy.Reverse().ForEach(p => PushViewAsync(p, false));
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ base.OnLayout(changed, l, t, r, b);
+
+ for (var i = 0; i < ChildCount; i++)
+ GetChildAt(i).Layout(0, 0, r - l, b - t);
+ }
+
+ protected virtual Task<bool> OnPopToRootAsync(Page page, bool animated)
+ {
+ return SwitchContentAsync(page, animated, true);
+ }
+
+ protected virtual Task<bool> OnPopViewAsync(Page page, bool animated)
+ {
+ Page pageToShow = Element.StackCopy.Skip(1).FirstOrDefault();
+ if (pageToShow == null)
+ return Task.FromResult(false);
+
+ return SwitchContentAsync(pageToShow, animated, true);
+ }
+
+ protected virtual Task<bool> OnPushAsync(Page view, bool animated)
+ {
+ return SwitchContentAsync(view, animated);
+ }
+
+ void InsertPageBefore(Page page, Page before)
+ {
+ }
+
+ void OnInsertPageBeforeRequested(object sender, NavigationRequestedEventArgs e)
+ {
+ InsertPageBefore(e.Page, e.BeforePage);
+ }
+
+ void OnPopped(object sender, NavigationRequestedEventArgs e)
+ {
+ e.Task = PopViewAsync(e.Page, e.Animated);
+ }
+
+ void OnPoppedToRoot(object sender, NavigationRequestedEventArgs e)
+ {
+ e.Task = PopToRootAsync(e.Page, e.Animated);
+ }
+
+ void OnPushed(object sender, NavigationRequestedEventArgs e)
+ {
+ e.Task = PushViewAsync(e.Page, e.Animated);
+ }
+
+ void OnRemovePageRequested(object sender, NavigationRequestedEventArgs e)
+ {
+ RemovePage(e.Page);
+ }
+
+ void RemovePage(Page page)
+ {
+ IVisualElementRenderer rendererToRemove = Platform.GetRenderer(page);
+ PageContainer containerToRemove = rendererToRemove == null ? null : (PageContainer)rendererToRemove.ViewGroup.Parent;
+
+ containerToRemove.RemoveFromParent();
+
+ if (rendererToRemove != null)
+ {
+ rendererToRemove.ViewGroup.RemoveFromParent();
+ rendererToRemove.Dispose();
+ }
+
+ containerToRemove?.Dispose();
+
+ Device.StartTimer(TimeSpan.FromMilliseconds(0), () =>
+ {
+ ((Platform)Element.Platform).UpdateNavigationTitleBar();
+ return false;
+ });
+ }
+
+ Task<bool> SwitchContentAsync(Page view, bool animated, bool removed = false)
+ {
+ Context.HideKeyboard(this);
+
+ IVisualElementRenderer rendererToAdd = Platform.GetRenderer(view);
+ bool existing = rendererToAdd != null;
+ if (!existing)
+ Platform.SetRenderer(view, rendererToAdd = Platform.CreateRenderer(view));
+
+ Page pageToRemove = _current;
+ IVisualElementRenderer rendererToRemove = pageToRemove == null ? null : Platform.GetRenderer(pageToRemove);
+ PageContainer containerToRemove = rendererToRemove == null ? null : (PageContainer)rendererToRemove.ViewGroup.Parent;
+ PageContainer containerToAdd = (PageContainer)rendererToAdd.ViewGroup.Parent ?? new PageContainer(Context, rendererToAdd);
+
+ containerToAdd.SetWindowBackground();
+
+ _current = view;
+
+ ((Platform)Element.Platform).NavAnimationInProgress = true;
+
+ var tcs = new TaskCompletionSource<bool>();
+
+ if (animated)
+ {
+ if (s_currentAnimation != null)
+ s_currentAnimation.Cancel();
+
+ if (removed)
+ {
+ // animate out
+ if (containerToAdd.Parent != this)
+ AddView(containerToAdd, Element.LogicalChildren.IndexOf(rendererToAdd.Element));
+ else
+ ((Page)rendererToAdd.Element).SendAppearing();
+ containerToAdd.Visibility = ViewStates.Visible;
+
+ if (containerToRemove != null)
+ {
+ Action<AndroidAnimation.Animator> done = a =>
+ {
+ containerToRemove.Visibility = ViewStates.Gone;
+ containerToRemove.Alpha = 1;
+ containerToRemove.ScaleX = 1;
+ containerToRemove.ScaleY = 1;
+ RemoveView(containerToRemove);
+
+ tcs.TrySetResult(true);
+ ((Platform)Element.Platform).NavAnimationInProgress = false;
+
+ VisualElement removedElement = rendererToRemove.Element;
+ rendererToRemove.Dispose();
+ if (removedElement != null)
+ Platform.SetRenderer(removedElement, null);
+ };
+
+ // should always happen
+ s_currentAnimation = containerToRemove.Animate().Alpha(0).ScaleX(0.8f).ScaleY(0.8f).SetDuration(250).SetListener(new GenericAnimatorListener { OnEnd = a =>
+ {
+ s_currentAnimation = null;
+ done(a);
+ },
+ OnCancel = done });
+ }
+ }
+ else
+ {
+ bool containerAlreadyAdded = containerToAdd.Parent == this;
+ // animate in
+ if (!containerAlreadyAdded)
+ AddView(containerToAdd);
+ else
+ ((Page)rendererToAdd.Element).SendAppearing();
+
+ if (existing)
+ Element.ForceLayout();
+
+ containerToAdd.Alpha = 0;
+ containerToAdd.ScaleX = containerToAdd.ScaleY = 0.8f;
+ containerToAdd.Visibility = ViewStates.Visible;
+ s_currentAnimation = containerToAdd.Animate().Alpha(1).ScaleX(1).ScaleY(1).SetDuration(250).SetListener(new GenericAnimatorListener { OnEnd = a =>
+ {
+ if (containerToRemove != null && containerToRemove.Handle != IntPtr.Zero)
+ {
+ containerToRemove.Visibility = ViewStates.Gone;
+ if (pageToRemove != null)
+ pageToRemove.SendDisappearing();
+ }
+ s_currentAnimation = null;
+ tcs.TrySetResult(true);
+ ((Platform)Element.Platform).NavAnimationInProgress = false;
+ } });
+ }
+ }
+ else
+ {
+ // just do it fast
+ if (containerToRemove != null)
+ {
+ if (removed)
+ RemoveView(containerToRemove);
+ else
+ containerToRemove.Visibility = ViewStates.Gone;
+ }
+
+ if (containerToAdd.Parent != this)
+ AddView(containerToAdd);
+ else
+ ((Page)rendererToAdd.Element).SendAppearing();
+
+ if (containerToRemove != null && !removed)
+ pageToRemove.SendDisappearing();
+
+ if (existing)
+ Element.ForceLayout();
+
+ containerToAdd.Visibility = ViewStates.Visible;
+ tcs.SetResult(true);
+ ((Platform)Element.Platform).NavAnimationInProgress = false;
+ }
+
+ return tcs.Task;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ObjectJavaBox.cs b/Xamarin.Forms.Platform.Android/Renderers/ObjectJavaBox.cs
new file mode 100644
index 00000000..6addf745
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ObjectJavaBox.cs
@@ -0,0 +1,14 @@
+using Java.Lang;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal sealed class ObjectJavaBox<T> : Object
+ {
+ public ObjectJavaBox(T instance)
+ {
+ Instance = instance;
+ }
+
+ public T Instance { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/OpenGLViewRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/OpenGLViewRenderer.cs
new file mode 100644
index 00000000..5c787b76
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/OpenGLViewRenderer.cs
@@ -0,0 +1,102 @@
+using System;
+using System.ComponentModel;
+using Android.Opengl;
+using Javax.Microedition.Khronos.Opengles;
+using EGLConfig = Javax.Microedition.Khronos.Egl.EGLConfig;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class OpenGLViewRenderer : ViewRenderer<OpenGLView, GLSurfaceView>
+ {
+ bool _disposed;
+
+ public OpenGLViewRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (!_disposed && disposing)
+ {
+ _disposed = true;
+
+ if (Element != null)
+ ((IOpenGlViewController)Element).DisplayRequested -= Display;
+ }
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<OpenGLView> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ ((IOpenGlViewController)Element).DisplayRequested -= Display;
+
+ if (e.NewElement != null)
+ {
+ GLSurfaceView surfaceView = Control;
+ if (surfaceView == null)
+ {
+ surfaceView = new GLSurfaceView(Context);
+ surfaceView.SetEGLContextClientVersion(2);
+ SetNativeControl(surfaceView);
+ }
+
+ ((IOpenGlViewController)Element).DisplayRequested += Display;
+ surfaceView.SetRenderer(new Renderer(Element));
+ SetRenderMode();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == OpenGLView.HasRenderLoopProperty.PropertyName)
+ SetRenderMode();
+ }
+
+ void Display(object sender, EventArgs eventArgs)
+ {
+ if (Element.HasRenderLoop)
+ return;
+ Control.RequestRender();
+ }
+
+ void SetRenderMode()
+ {
+ Control.RenderMode = Element.HasRenderLoop ? Rendermode.Continuously : Rendermode.WhenDirty;
+ }
+
+ class Renderer : Object, GLSurfaceView.IRenderer
+ {
+ readonly OpenGLView _model;
+ Rectangle _rect;
+
+ public Renderer(OpenGLView model)
+ {
+ _model = model;
+ }
+
+ public void OnDrawFrame(IGL10 gl)
+ {
+ Action<Rectangle> onDisplay = _model.OnDisplay;
+ if (onDisplay == null)
+ return;
+ onDisplay(_rect);
+ }
+
+ public void OnSurfaceChanged(IGL10 gl, int width, int height)
+ {
+ _rect = new Rectangle(0.0, 0.0, width, height);
+ }
+
+ public void OnSurfaceCreated(IGL10 gl, EGLConfig config)
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/PageContainer.cs b/Xamarin.Forms.Platform.Android/Renderers/PageContainer.cs
new file mode 100644
index 00000000..06e33e18
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/PageContainer.cs
@@ -0,0 +1,30 @@
+using Android.Content;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class PageContainer : ViewGroup
+ {
+ public PageContainer(Context context, IVisualElementRenderer child, bool inFragment = false) : base(context)
+ {
+ AddView(child.ViewGroup);
+ Child = child;
+ IsInFragment = inFragment;
+ }
+
+ public IVisualElementRenderer Child { get; set; }
+
+ public bool IsInFragment { get; set; }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ Child.UpdateLayout();
+ }
+
+ protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
+ {
+ Child.ViewGroup.Measure(widthMeasureSpec, heightMeasureSpec);
+ SetMeasuredDimension(Child.ViewGroup.MeasuredWidth, Child.ViewGroup.MeasuredHeight);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/PageRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/PageRenderer.cs
new file mode 100644
index 00000000..24d85aa8
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/PageRenderer.cs
@@ -0,0 +1,71 @@
+using System.ComponentModel;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class PageRenderer : VisualElementRenderer<Page>
+ {
+ public override bool OnTouchEvent(MotionEvent e)
+ {
+ base.OnTouchEvent(e);
+
+ return true;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ Element?.SendDisappearing();
+ base.Dispose(disposing);
+ }
+
+ protected override void OnAttachedToWindow()
+ {
+ base.OnAttachedToWindow();
+ var pageContainer = Parent as PageContainer;
+ if (pageContainer != null && pageContainer.IsInFragment)
+ return;
+ Element.SendAppearing();
+ }
+
+ protected override void OnDetachedFromWindow()
+ {
+ base.OnDetachedFromWindow();
+ var pageContainer = Parent as PageContainer;
+ if (pageContainer != null && pageContainer.IsInFragment)
+ return;
+ Element.SendDisappearing();
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
+ {
+ Page view = e.NewElement;
+ base.OnElementChanged(e);
+
+ UpdateBackgroundColor(view);
+ UpdateBackgroundImage(view);
+
+ Clickable = true;
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+ if (e.PropertyName == Page.BackgroundImageProperty.PropertyName)
+ UpdateBackgroundImage(Element);
+ if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackgroundColor(Element);
+ }
+
+ void UpdateBackgroundColor(Page view)
+ {
+ if (view.BackgroundColor != Color.Default)
+ SetBackgroundColor(view.BackgroundColor.ToAndroid());
+ }
+
+ void UpdateBackgroundImage(Page view)
+ {
+ if (!string.IsNullOrEmpty(view.BackgroundImage))
+ this.SetBackground(Context.Resources.GetDrawable(view.BackgroundImage));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/PhysicalLayoutManager.cs b/Xamarin.Forms.Platform.Android/Renderers/PhysicalLayoutManager.cs
new file mode 100644
index 00000000..64e859d7
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/PhysicalLayoutManager.cs
@@ -0,0 +1,531 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Android.Content;
+using Android.Graphics;
+using Android.Support.V7.Widget;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class PhysicalLayoutManager : RecyclerView.LayoutManager
+ {
+ // ObservableCollection is our public entryway to this method and it only supports single item removal
+ internal const int MaxItemsRemoved = 1;
+
+ static readonly int s_samplesCount = 5;
+ static Func<int, int> s_fixPosition = o => o;
+
+ readonly Context _context;
+ readonly Queue<Action<RecyclerView.Recycler, RecyclerView.State>> _deferredLayout;
+ readonly List<IntVector> _samples;
+ readonly SeekAndSnapScroller _scroller;
+ readonly Dictionary<int, global::Android.Views.View> _viewByAdaptorPosition;
+ readonly VirtualLayoutManager _virtualLayout;
+ readonly HashSet<int> _visibleAdapterPosition;
+ AdapterChangeType _adapterChangeType;
+ IntVector _locationOffset; // upper left corner of screen is positionOrigin + locationOffset
+ int _positionOrigin; // coordinates are relative to the upper left corner of this element
+
+ public PhysicalLayoutManager(Context context, VirtualLayoutManager virtualLayout, int positionOrigin)
+ {
+ _positionOrigin = positionOrigin;
+ _context = context;
+ _virtualLayout = virtualLayout;
+ _viewByAdaptorPosition = new Dictionary<int, global::Android.Views.View>();
+ _visibleAdapterPosition = new HashSet<int>();
+ _samples = Enumerable.Repeat(IntVector.Origin, s_samplesCount).ToList();
+ _deferredLayout = new Queue<Action<RecyclerView.Recycler, RecyclerView.State>>();
+ _scroller = new SeekAndSnapScroller(context, adapterPosition =>
+ {
+ IntVector end = virtualLayout.LayoutItem(positionOrigin, adapterPosition).Center();
+ IntVector begin = Viewport.Center();
+ return end - begin;
+ });
+
+ _scroller.OnBeginScroll += adapterPosition => OnBeginScroll?.Invoke(adapterPosition);
+ _scroller.OnEndScroll += adapterPosition => OnEndScroll?.Invoke(adapterPosition);
+ }
+
+ public IntVector Velocity => _samples.Aggregate((o, a) => o + a) / _samples.Count;
+
+ public System.Drawing.Rectangle Viewport => Rectangle + _locationOffset;
+
+ // helpers to deal with locations as IntRectangles and IntVectors
+ System.Drawing.Rectangle Rectangle => new System.Drawing.Rectangle(0, 0, Width, Height);
+
+ public override bool CanScrollHorizontally() => _virtualLayout.CanScrollHorizontally;
+
+ public override bool CanScrollVertically() => _virtualLayout.CanScrollVertically;
+
+ public override global::Android.Views.View FindViewByPosition(int adapterPosition)
+ {
+ // Used by SmoothScrollToPosition to know when the view
+ // for the targeted adapterPosition has been attached.
+
+ global::Android.Views.View view;
+ if (!_viewByAdaptorPosition.TryGetValue(adapterPosition, out view))
+ return null;
+ return view;
+ }
+
+ public override RecyclerView.LayoutParams GenerateDefaultLayoutParams()
+ {
+ return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
+ }
+
+ public void Layout(int width, int height)
+ {
+ // e.g. when rotated the width and height are updated the virtual layout will
+ // need to resize and provide a new viewport offset given the current one.
+ _virtualLayout.Layout(_positionOrigin, new System.Drawing.Size(width, height), ref _locationOffset);
+ }
+
+ public override void OnAdapterChanged(RecyclerView.Adapter oldAdapter, RecyclerView.Adapter newAdapter)
+ {
+ RemoveAllViews();
+ }
+
+ public event Action<int> OnAppearing;
+
+ public event Action<int> OnBeginScroll;
+
+ public event Action<int> OnDisappearing;
+
+ public event Action<int> OnEndScroll;
+
+ public override void OnItemsAdded(RecyclerView recyclerView, int positionStart, int itemCount)
+ {
+ _adapterChangeType = AdapterChangeType.Added;
+
+ _deferredLayout.Enqueue((recycler, state) =>
+ {
+ KeyValuePair<int, global::Android.Views.View>[] viewByAdaptorPositionCopy = _viewByAdaptorPosition.ToArray();
+ _viewByAdaptorPosition.Clear();
+ foreach (KeyValuePair<int, global::Android.Views.View> pair in viewByAdaptorPositionCopy)
+ {
+ global::Android.Views.View view = pair.Value;
+ int position = pair.Key;
+
+ // position unchanged
+ if (position < positionStart)
+ _viewByAdaptorPosition[position] = view;
+
+ // position changed
+ else
+ _viewByAdaptorPosition[position + itemCount] = view;
+ }
+
+ if (_positionOrigin >= positionStart)
+ _positionOrigin += itemCount;
+ });
+ base.OnItemsAdded(recyclerView, positionStart, itemCount);
+ }
+
+ public override void OnItemsChanged(RecyclerView recyclerView)
+ {
+ _adapterChangeType = AdapterChangeType.Changed;
+
+ // low-fidelity change event; assume everything has changed. If adapter reports it has "stable IDs" then
+ // RecyclerView will attempt to synthesize high-fidelity change events: added, removed, moved, updated.
+ base.OnItemsChanged(recyclerView);
+ }
+
+ public override void OnItemsMoved(RecyclerView recyclerView, int from, int toValue, int itemCount)
+ {
+ _adapterChangeType = AdapterChangeType.Moved;
+ base.OnItemsMoved(recyclerView, from, toValue, itemCount);
+ }
+
+ public override void OnItemsRemoved(RecyclerView recyclerView, int positionStart, int itemCount)
+ {
+ Debug.Assert(itemCount == MaxItemsRemoved);
+ _adapterChangeType = AdapterChangeType.Removed;
+
+ int positionEnd = positionStart + itemCount;
+
+ _deferredLayout.Enqueue((recycler, state) =>
+ {
+ if (state.ItemCount == 0)
+ throw new InvalidOperationException("Cannot delete all items.");
+
+ // re-map views to their new positions
+ KeyValuePair<int, global::Android.Views.View>[] viewByAdaptorPositionCopy = _viewByAdaptorPosition.ToArray();
+ _viewByAdaptorPosition.Clear();
+ foreach (KeyValuePair<int, global::Android.Views.View> pair in viewByAdaptorPositionCopy)
+ {
+ global::Android.Views.View view = pair.Value;
+ int position = pair.Key;
+
+ // position unchanged
+ if (position < positionStart)
+ _viewByAdaptorPosition[position] = view;
+
+ // position changed
+ else if (position >= positionEnd)
+ _viewByAdaptorPosition[position - itemCount] = view;
+
+ // removed
+ else
+ {
+ _viewByAdaptorPosition[-1] = view;
+ if (_visibleAdapterPosition.Contains(position))
+ _visibleAdapterPosition.Remove(position);
+ }
+ }
+
+ // if removed origin then shift origin to first removed position
+ if (_positionOrigin >= positionStart && _positionOrigin < positionEnd)
+ {
+ _positionOrigin = positionStart;
+
+ // if no items to right of removed origin then set origin to item prior to removed set
+ if (_positionOrigin >= state.ItemCount)
+ {
+ _positionOrigin = state.ItemCount - 1;
+
+ if (!_viewByAdaptorPosition.ContainsKey(_positionOrigin))
+ throw new InvalidOperationException("VirtualLayoutManager must add items to the left and right of the origin");
+ }
+ }
+
+ // if removed before origin then shift origin left
+ else if (_positionOrigin >= positionEnd)
+ _positionOrigin -= itemCount;
+ });
+
+ base.OnItemsRemoved(recyclerView, positionStart, itemCount);
+ }
+
+ public override void OnItemsUpdated(RecyclerView recyclerView, int positionStart, int itemCount)
+ {
+ _adapterChangeType = AdapterChangeType.Updated;
+
+ // rebind rendered updated elements
+ _deferredLayout.Enqueue((recycler, state) =>
+ {
+ for (var i = 0; i < itemCount; i++)
+ {
+ int position = positionStart + i;
+
+ global::Android.Views.View view;
+ if (!_viewByAdaptorPosition.TryGetValue(position, out view))
+ continue;
+
+ recycler.BindViewToPosition(view, position);
+ }
+ });
+
+ base.OnItemsUpdated(recyclerView, positionStart, itemCount);
+ }
+
+ public override void OnLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state)
+ {
+ AdapterChangeType adapterChangeType = _adapterChangeType;
+ if (state.IsPreLayout)
+ adapterChangeType = default(AdapterChangeType);
+
+ // adapter updates
+ if (!state.IsPreLayout)
+ {
+ while (_deferredLayout.Count > 0)
+ _deferredLayout.Dequeue()(recycler, state);
+ }
+
+ // get visible items
+ int[] positions = _virtualLayout.GetPositions(_positionOrigin, state.ItemCount, Viewport,
+ // IsPreLayout => some type of data update of yet unknown type. Must assume update
+ // could be remove so virtualLayout must +1 off-screen left in case origin is
+ // removed and +n off-screen right to slide onscreen if a big item is removed
+ state.IsPreLayout || adapterChangeType == AdapterChangeType.Removed).ToRange();
+
+ // disappearing
+ List<int> disappearing = _viewByAdaptorPosition.Keys.Except(positions).ToList();
+
+ // defer cleanup of displaced items and lay them out off-screen so they animate off-screen
+ if (adapterChangeType == AdapterChangeType.Added)
+ {
+ positions = positions.Concat(disappearing).OrderBy(o => o).ToArray();
+ disappearing.Clear();
+ }
+
+ // recycle
+ foreach (int position in disappearing)
+ {
+ global::Android.Views.View view = _viewByAdaptorPosition[position];
+
+ // remove
+ _viewByAdaptorPosition.Remove(position);
+ OnAppearingOrDisappearing(position, false);
+
+ // scrap
+ new DecoratedView(this, view).DetachAndScrap(recycler);
+ }
+
+ // TODO: Generalize
+ if (adapterChangeType == AdapterChangeType.Removed && _positionOrigin == state.ItemCount - 1)
+ {
+ System.Drawing.Rectangle vlayout = _virtualLayout.LayoutItem(_positionOrigin, _positionOrigin);
+ _locationOffset = new IntVector(vlayout.Width - Width, _locationOffset.Y);
+ }
+
+ var nextLocationOffset = new System.Drawing.Point(int.MaxValue, int.MaxValue);
+ int nextPositionOrigin = int.MaxValue;
+ foreach (int position in positions)
+ {
+ // attach
+ global::Android.Views.View view;
+ if (!_viewByAdaptorPosition.TryGetValue(position, out view))
+ AddView(_viewByAdaptorPosition[position] = view = recycler.GetViewForPosition(position));
+
+ // layout
+ var decoratedView = new DecoratedView(this, view);
+ System.Drawing.Rectangle layout = _virtualLayout.LayoutItem(_positionOrigin, position);
+ System.Drawing.Rectangle physicalLayout = layout - _locationOffset;
+ decoratedView.Layout(physicalLayout);
+
+ bool isVisible = Viewport.IntersectsWith(layout);
+ if (isVisible)
+ OnAppearingOrDisappearing(position, true);
+
+ // update offsets
+ if (isVisible && position < nextPositionOrigin)
+ {
+ nextLocationOffset = layout.Location;
+ nextPositionOrigin = position;
+ }
+ }
+
+ // update origin
+ if (nextPositionOrigin != int.MaxValue)
+ {
+ _positionOrigin = nextPositionOrigin;
+ _locationOffset -= (IntVector)nextLocationOffset;
+ }
+
+ // scrapped views not re-attached must be recycled (why isn't this done by Android, I dunno)
+ foreach (RecyclerView.ViewHolder viewHolder in recycler.ScrapList.ToArray())
+ recycler.RecycleView(viewHolder.ItemView);
+ }
+
+ public override int ScrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state)
+ {
+ var delta = new IntVector(dx, 0);
+ ScrollBy(ref delta, recycler, state);
+ return delta.X;
+ }
+
+ public override void ScrollToPosition(int adapterPosition)
+ {
+ if (adapterPosition < 0 || adapterPosition >= ItemCount)
+ throw new ArgumentException(nameof(adapterPosition));
+
+ _scroller.TargetPosition = adapterPosition;
+ StartSmoothScroll(_scroller);
+ }
+
+ public override int ScrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state)
+ {
+ var delta = new IntVector(0, dy);
+ ScrollBy(ref delta, recycler, state);
+ return delta.Y;
+ }
+
+ public override void SmoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int adapterPosition)
+ {
+ ScrollToPosition(adapterPosition);
+ }
+
+ // entry points
+ public override bool SupportsPredictiveItemAnimations() => true;
+
+ public override string ToString()
+ {
+ return $"offset={_locationOffset}";
+ }
+
+ public IEnumerable<global::Android.Views.View> Views()
+ {
+ return _viewByAdaptorPosition.Values;
+ }
+
+ public IEnumerable<int> VisiblePositions()
+ {
+ return _visibleAdapterPosition;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ }
+
+ void OffsetChildren(IntVector delta)
+ {
+ OffsetChildrenHorizontal(-delta.X);
+ OffsetChildrenVertical(-delta.Y);
+ }
+
+ void OnAppearingOrDisappearing(int position, bool isAppearing)
+ {
+ if (isAppearing)
+ {
+ if (!_visibleAdapterPosition.Contains(position))
+ {
+ _visibleAdapterPosition.Add(position);
+ OnAppearing?.Invoke(position);
+ }
+ }
+ else
+ {
+ if (_visibleAdapterPosition.Contains(position))
+ {
+ _visibleAdapterPosition.Remove(position);
+ OnDisappearing?.Invoke(position);
+ }
+ }
+ }
+
+ void ScrollBy(ref IntVector delta, RecyclerView.Recycler recycler, RecyclerView.State state)
+ {
+ _adapterChangeType = default(AdapterChangeType);
+
+ delta = Viewport.BoundTranslation(delta, _virtualLayout.GetBounds(_positionOrigin, state));
+
+ _locationOffset += delta;
+ _samples.Insert(0, delta);
+ _samples.RemoveAt(_samples.Count - 1);
+
+ OffsetChildren(delta);
+ OnLayoutChildren(recycler, state);
+ }
+
+ enum AdapterChangeType
+ {
+ Removed = 1,
+ Added,
+ Moved,
+ Updated,
+ Changed
+ }
+
+ internal struct DecoratedView
+ {
+ public static implicit operator global::Android.Views.View(DecoratedView view)
+ {
+ return view._view;
+ }
+
+ readonly PhysicalLayoutManager _layout;
+ readonly global::Android.Views.View _view;
+
+ internal DecoratedView(PhysicalLayoutManager layout, global::Android.Views.View view)
+ {
+ _layout = layout;
+ _view = view;
+ }
+
+ internal int Left => _layout.GetDecoratedLeft(_view);
+
+ internal int Top => _layout.GetDecoratedTop(_view);
+
+ internal int Bottom => _layout.GetDecoratedBottom(_view);
+
+ internal int Right => _layout.GetDecoratedRight(_view);
+
+ internal int Width => Right - Left;
+
+ internal int Height => Bottom - Top;
+
+ internal System.Drawing.Rectangle Rectangle => new System.Drawing.Rectangle(Left, Top, Width, Height);
+
+ internal void Measure(int widthUsed, int heightUsed)
+ {
+ _layout.MeasureChild(_view, widthUsed, heightUsed);
+ }
+
+ internal void MeasureWithMargins(int widthUsed, int heightUsed)
+ {
+ _layout.MeasureChildWithMargins(_view, widthUsed, heightUsed);
+ }
+
+ internal void Layout(System.Drawing.Rectangle position)
+ {
+ var renderer = _view as IVisualElementRenderer;
+ renderer.Element.Layout(position.ToFormsRectangle(_layout._context));
+
+ _layout.LayoutDecorated(_view, position.Left, position.Top, position.Right, position.Bottom);
+ }
+
+ internal void Add()
+ {
+ _layout.AddView(_view);
+ }
+
+ internal void DetachAndScrap(RecyclerView.Recycler recycler)
+ {
+ _layout.DetachAndScrapView(_view, recycler);
+ }
+ }
+
+ internal abstract class VirtualLayoutManager
+ {
+ internal abstract bool CanScrollHorizontally { get; }
+
+ internal abstract bool CanScrollVertically { get; }
+
+ internal abstract System.Drawing.Rectangle GetBounds(int positionOrigin, RecyclerView.State state);
+
+ internal abstract Tuple<int, int> GetPositions(int positionOrigin, int itemCount, System.Drawing.Rectangle viewport, bool isPreLayout);
+
+ internal abstract void Layout(int positionOrigin, System.Drawing.Size viewportSize, ref IntVector offset);
+
+ internal abstract System.Drawing.Rectangle LayoutItem(int positionOrigin, int position);
+ }
+
+ enum SnapPreference
+ {
+ None = 0,
+ Begin = 1,
+ End = -1
+ }
+
+ sealed class SeekAndSnapScroller : LinearSmoothScroller
+ {
+ readonly SnapPreference _snapPreference;
+ readonly Func<int, IntVector> _vectorToPosition;
+
+ internal SeekAndSnapScroller(Context context, Func<int, IntVector> vectorToPosition, SnapPreference snapPreference = SnapPreference.None) : base(context)
+ {
+ _vectorToPosition = vectorToPosition;
+ _snapPreference = snapPreference;
+ }
+
+ protected override int HorizontalSnapPreference => (int)_snapPreference;
+
+ public override PointF ComputeScrollVectorForPosition(int targetPosition)
+ {
+ IntVector vector = _vectorToPosition(targetPosition);
+ return new PointF(vector.X, vector.Y);
+ }
+
+ public event Action<int> OnBeginScroll;
+
+ public event Action<int> OnEndScroll;
+
+ protected override void OnStart()
+ {
+ OnBeginScroll?.Invoke(TargetPosition);
+ base.OnStart();
+ }
+
+ protected override void OnStop()
+ {
+ // expected this to be triggered with the animation stops but it
+ // actually seems to be triggered when the target is found
+ OnEndScroll?.Invoke(TargetPosition);
+ base.OnStop();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/PickerRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/PickerRenderer.cs
new file mode 100644
index 00000000..b9114d22
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/PickerRenderer.cs
@@ -0,0 +1,165 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using Android.App;
+using Android.Views;
+using Android.Widget;
+using ADatePicker = Android.Widget.DatePicker;
+using ATimePicker = Android.Widget.TimePicker;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class PickerRenderer : ViewRenderer<Picker, EditText>
+ {
+ AlertDialog _dialog;
+
+ bool _isDisposed;
+
+ public PickerRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_isDisposed)
+ {
+ _isDisposed = true;
+ ((ObservableList<string>)Element.Items).CollectionChanged -= RowsCollectionChanged;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
+ {
+ if (e.OldElement != null)
+ ((ObservableList<string>)e.OldElement.Items).CollectionChanged -= RowsCollectionChanged;
+
+ if (e.NewElement != null)
+ {
+ ((ObservableList<string>)e.NewElement.Items).CollectionChanged += RowsCollectionChanged;
+ if (Control == null)
+ {
+ var textField = new EditText(Context) { Focusable = false, Clickable = true, Tag = this };
+ textField.SetOnClickListener(PickerListener.Instance);
+ SetNativeControl(textField);
+ }
+ UpdatePicker();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Picker.TitleProperty.PropertyName)
+ UpdatePicker();
+ if (e.PropertyName == Picker.SelectedIndexProperty.PropertyName)
+ UpdatePicker();
+ }
+
+ internal override void OnFocusChangeRequested(object sender, VisualElement.FocusRequestArgs e)
+ {
+ base.OnFocusChangeRequested(sender, e);
+
+ if (e.Focus)
+ OnClick();
+ else if (_dialog != null)
+ {
+ _dialog.Hide();
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ Control.ClearFocus();
+ _dialog = null;
+ }
+ }
+
+ void OnClick()
+ {
+ Picker model = Element;
+
+ var picker = new NumberPicker(Context);
+ if (model.Items != null && model.Items.Any())
+ {
+ picker.MaxValue = model.Items.Count - 1;
+ picker.MinValue = 0;
+ picker.SetDisplayedValues(model.Items.ToArray());
+ picker.WrapSelectorWheel = false;
+ picker.DescendantFocusability = DescendantFocusability.BlockDescendants;
+ picker.Value = model.SelectedIndex;
+ }
+
+ var layout = new LinearLayout(Context) { Orientation = Orientation.Vertical };
+ layout.AddView(picker);
+
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
+
+ var builder = new AlertDialog.Builder(Context);
+ builder.SetView(layout);
+ builder.SetTitle(model.Title ?? "");
+ builder.SetNegativeButton(global::Android.Resource.String.Cancel, (s, a) =>
+ {
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ // It is possible for the Content of the Page to be changed when Focus is changed.
+ // In this case, we'll lose our Control.
+ Control?.ClearFocus();
+ _dialog = null;
+ });
+ builder.SetPositiveButton(global::Android.Resource.String.Ok, (s, a) =>
+ {
+ ((IElementController)Element).SetValueFromRenderer(Picker.SelectedIndexProperty, picker.Value);
+ // It is possible for the Content of the Page to be changed on SelectedIndexChanged.
+ // In this case, the Element & Control will no longer exist.
+ if (Element != null)
+ {
+ if (model.Items.Count > 0 && Element.SelectedIndex >= 0)
+ Control.Text = model.Items[Element.SelectedIndex];
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ // It is also possible for the Content of the Page to be changed when Focus is changed.
+ // In this case, we'll lose our Control.
+ Control?.ClearFocus();
+ }
+ _dialog = null;
+ });
+
+ (_dialog = builder.Create()).Show();
+ }
+
+ void RowsCollectionChanged(object sender, EventArgs e)
+ {
+ UpdatePicker();
+ }
+
+ void UpdatePicker()
+ {
+ Control.Hint = Element.Title;
+
+ string oldText = Control.Text;
+
+ if (Element.SelectedIndex == -1 || Element.Items == null)
+ Control.Text = null;
+ else
+ Control.Text = Element.Items[Element.SelectedIndex];
+
+ if (oldText != Control.Text)
+ ((IVisualElementController)Element).NativeSizeChanged();
+ }
+
+ class PickerListener : Object, IOnClickListener
+ {
+ public static readonly PickerListener Instance = new PickerListener();
+
+ public void OnClick(global::Android.Views.View v)
+ {
+ var renderer = v.Tag as PickerRenderer;
+ if (renderer == null)
+ return;
+
+ renderer.OnClick();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ProgressBarRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/ProgressBarRenderer.cs
new file mode 100644
index 00000000..865732f7
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ProgressBarRenderer.cs
@@ -0,0 +1,40 @@
+using System.ComponentModel;
+using AProgressBar = Android.Widget.ProgressBar;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class ProgressBarRenderer : ViewRenderer<ProgressBar, AProgressBar>
+ {
+ public ProgressBarRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<ProgressBar> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement == null)
+ {
+ var progressBar = new AProgressBar(Context, null, global::Android.Resource.Attribute.ProgressBarStyleHorizontal) { Indeterminate = false, Max = 10000 };
+
+ SetNativeControl(progressBar);
+ }
+
+ UpdateProgress();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == ProgressBar.ProgressProperty.PropertyName)
+ UpdateProgress();
+ }
+
+ void UpdateProgress()
+ {
+ Control.Progress = (int)(Element.Progress * 10000);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ScrollViewContainer.cs b/Xamarin.Forms.Platform.Android/Renderers/ScrollViewContainer.cs
new file mode 100644
index 00000000..c79e6137
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ScrollViewContainer.cs
@@ -0,0 +1,75 @@
+using Android.Content;
+using Android.Views;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class ScrollViewContainer : ViewGroup
+ {
+ readonly ScrollView _parent;
+ View _childView;
+
+ public ScrollViewContainer(ScrollView parent, Context context) : base(context)
+ {
+ _parent = parent;
+ }
+
+ public View ChildView
+ {
+ get { return _childView; }
+ set
+ {
+ if (_childView == value)
+ return;
+
+ RemoveAllViews();
+
+ _childView = value;
+
+ if (_childView == null)
+ return;
+
+ IVisualElementRenderer renderer;
+ if ((renderer = Platform.GetRenderer(_childView)) == null)
+ Platform.SetRenderer(_childView, renderer = Platform.CreateRenderer(_childView));
+
+ if (renderer.ViewGroup.Parent != null)
+ renderer.ViewGroup.RemoveFromParent();
+
+ AddView(renderer.ViewGroup);
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (disposing)
+ {
+ if (ChildCount > 0)
+ GetChildAt(0).Dispose();
+ RemoveAllViews();
+ _childView = null;
+ }
+ }
+
+ protected override void OnLayout(bool changed, int left, int top, int right, int bottom)
+ {
+ if (_childView == null)
+ return;
+
+ IVisualElementRenderer renderer = Platform.GetRenderer(_childView);
+ renderer.UpdateLayout();
+ }
+
+ protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
+ {
+ // we need to make sure we are big enough to be laid out at 0,0
+ if (_childView != null)
+ {
+ SetMeasuredDimension((int)Context.ToPixels(_childView.Bounds.Right + _parent.Padding.Right), (int)Context.ToPixels(_childView.Bounds.Bottom + _parent.Padding.Bottom));
+ }
+ else
+ SetMeasuredDimension((int)Context.ToPixels(_parent.Padding.Right), (int)Context.ToPixels(_parent.Padding.Bottom));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ScrollViewRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/ScrollViewRenderer.cs
new file mode 100644
index 00000000..15f04278
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ScrollViewRenderer.cs
@@ -0,0 +1,331 @@
+using System;
+using System.ComponentModel;
+using System.Threading.Tasks;
+using Android.Animation;
+using Android.Graphics;
+using Android.Views;
+using Android.Widget;
+using AScrollView = Android.Widget.ScrollView;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class ScrollViewRenderer : AScrollView, IVisualElementRenderer
+ {
+ ScrollViewContainer _container;
+ HorizontalScrollView _hScrollView;
+ bool _isAttached;
+
+ bool _isBidirectional;
+ ScrollToRequestedEventArgs _pendingScrollTo;
+ ScrollView _view;
+
+ public ScrollViewRenderer() : base(Forms.Context)
+ {
+ }
+
+ protected IScrollViewController Controller
+ {
+ get { return (IScrollViewController)Element; }
+ }
+
+ internal float LastX { get; set; }
+
+ internal float LastY { get; set; }
+
+ public VisualElement Element
+ {
+ get { return _view; }
+ }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)
+ {
+ Measure(widthConstraint, heightConstraint);
+ return new SizeRequest(new Size(MeasuredWidth, MeasuredHeight), new Size(40, 40));
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ ScrollView oldElement = _view;
+ _view = (ScrollView)element;
+
+ if (oldElement != null)
+ {
+ oldElement.PropertyChanged -= HandlePropertyChanged;
+ ((IScrollViewController)oldElement).ScrollToRequested -= OnScrollToRequested;
+ }
+ if (element != null)
+ {
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+
+ if (_container == null)
+ {
+ Tracker = new VisualElementTracker(this);
+ _container = new ScrollViewContainer(_view, Forms.Context);
+ }
+
+ _view.PropertyChanged += HandlePropertyChanged;
+ Controller.ScrollToRequested += OnScrollToRequested;
+
+ LoadContent();
+ UpdateBackgroundColor();
+
+ UpdateOrientation();
+
+ element.SendViewInitialized(this);
+
+ if (!string.IsNullOrEmpty(element.AutomationId))
+ ContentDescription = element.AutomationId;
+ }
+ }
+
+ public VisualElementTracker Tracker { get; private set; }
+
+ public void UpdateLayout()
+ {
+ if (Tracker != null)
+ Tracker.UpdateLayout();
+ }
+
+ public ViewGroup ViewGroup
+ {
+ get { return this; }
+ }
+
+ public override void Draw(Canvas canvas)
+ {
+ canvas.ClipRect(canvas.ClipBounds);
+
+ base.Draw(canvas);
+ }
+
+ public override bool OnInterceptTouchEvent(MotionEvent ev)
+ {
+ if (Element.InputTransparent)
+ return false;
+
+ // set the start point for the bidirectional scroll;
+ // Down is swallowed by other controls, so we'll just sneak this in here without actually preventing
+ // other controls from getting the event.
+ if (_isBidirectional && ev.Action == MotionEventActions.Down)
+ {
+ LastY = ev.RawY;
+ LastX = ev.RawX;
+ }
+
+ return base.OnInterceptTouchEvent(ev);
+ }
+
+ public override bool OnTouchEvent(MotionEvent ev)
+ {
+ // The nested ScrollViews will allow us to scroll EITHER vertically OR horizontally in a single gesture.
+ // This will allow us to also scroll diagonally.
+ // We'll fall through to the base event so we still get the fling from the ScrollViews.
+ // We have to do this in both ScrollViews, since a single gesture will be owned by one or the other, depending
+ // on the initial direction of movement (i.e., horizontal/vertical).
+ if (_isBidirectional && !Element.InputTransparent)
+ {
+ float dX = LastX - ev.RawX;
+ float dY = LastY - ev.RawY;
+ LastY = ev.RawY;
+ LastX = ev.RawX;
+ if (ev.Action == MotionEventActions.Move)
+ {
+ ScrollBy(0, (int)dY);
+ foreach (AHorizontalScrollView child in this.GetChildrenOfType<AHorizontalScrollView>())
+ {
+ child.ScrollBy((int)dX, 0);
+ break;
+ }
+ }
+ }
+ return base.OnTouchEvent(ev);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ SetElement(null);
+
+ if (disposing)
+ {
+ Tracker.Dispose();
+ Tracker = null;
+ RemoveAllViews();
+ _container.Dispose();
+ _container = null;
+ }
+ }
+
+ protected override void OnAttachedToWindow()
+ {
+ base.OnAttachedToWindow();
+
+ _isAttached = true;
+ }
+
+ protected override void OnDetachedFromWindow()
+ {
+ base.OnDetachedFromWindow();
+
+ _isAttached = false;
+ }
+
+ protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ EventHandler<VisualElementChangedEventArgs> changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ protected override void OnLayout(bool changed, int left, int top, int right, int bottom)
+ {
+ base.OnLayout(changed, left, top, right, bottom);
+ if (_view.Content != null && _hScrollView != null)
+ _hScrollView.Layout(0, 0, right - left, Math.Max(bottom - top, (int)Context.ToPixels(_view.Content.Height)));
+ }
+
+ protected override void OnScrollChanged(int l, int t, int oldl, int oldt)
+ {
+ base.OnScrollChanged(l, t, oldl, oldt);
+
+ UpdateScrollPosition(Forms.Context.FromPixels(l), Forms.Context.FromPixels(t));
+ }
+
+ internal void UpdateScrollPosition(double x, double y)
+ {
+ if (_view != null)
+ Controller.SetScrolledPosition(x, y);
+ }
+
+ static int GetDistance(double start, double position, double v)
+ {
+ return (int)(start + (position - start) * v);
+ }
+
+ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "Content")
+ LoadContent();
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackgroundColor();
+ else if (e.PropertyName == ScrollView.OrientationProperty.PropertyName)
+ UpdateOrientation();
+ }
+
+ void LoadContent()
+ {
+ _container.ChildView = _view.Content;
+ }
+
+ async void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
+ {
+ if (!_isAttached)
+ {
+ _pendingScrollTo = e;
+ return;
+ }
+
+ // 99.99% of the time simply queuing to the end of the execution queue should handle this case.
+ // However it is possible to end a layout cycle and STILL be layout requested. We want to
+ // back off until all are done, even if they trigger layout storms over and over. So we back off
+ // for 10ms tops then move on.
+ var cycle = 0;
+ while (IsLayoutRequested)
+ {
+ await Task.Delay(TimeSpan.FromMilliseconds(1));
+ cycle++;
+
+ if (cycle >= 10)
+ break;
+ }
+
+ var x = (int)Forms.Context.ToPixels(e.ScrollX);
+ var y = (int)Forms.Context.ToPixels(e.ScrollY);
+ int currentX = _view.Orientation == ScrollOrientation.Horizontal ? _hScrollView.ScrollX : ScrollX;
+ int currentY = _view.Orientation == ScrollOrientation.Horizontal ? _hScrollView.ScrollY : ScrollY;
+ if (e.Mode == ScrollToMode.Element)
+ {
+ Point itemPosition = Controller.GetScrollPositionForElement(e.Element as VisualElement, e.Position);
+
+ x = (int)Forms.Context.ToPixels(itemPosition.X);
+ y = (int)Forms.Context.ToPixels(itemPosition.Y);
+ }
+ if (e.ShouldAnimate)
+ {
+ ValueAnimator animator = ValueAnimator.OfFloat(0f, 1f);
+ animator.SetDuration(1000);
+ animator.Update += (o, animatorUpdateEventArgs) =>
+ {
+ var v = (double)animatorUpdateEventArgs.Animation.AnimatedValue;
+ int distX = GetDistance(currentX, x, v);
+ int distY = GetDistance(currentY, y, v);
+
+ if (_view == null)
+ {
+ // This is probably happening because the page with this Scroll View
+ // was popped off the stack during animation
+ animator.Cancel();
+ return;
+ }
+
+ if (_view.Orientation == ScrollOrientation.Horizontal)
+ _hScrollView.ScrollTo(distX, distY);
+ else
+ ScrollTo(distX, distY);
+ };
+ animator.AnimationEnd += delegate
+ {
+ if (Controller == null)
+ return;
+ Controller.SendScrollFinished();
+ };
+
+ animator.Start();
+ }
+ else
+ {
+ if (_view.Orientation == ScrollOrientation.Horizontal)
+ _hScrollView.ScrollTo(x, y);
+ else
+ ScrollTo(x, y);
+ Controller.SendScrollFinished();
+ }
+ }
+
+ void UpdateBackgroundColor()
+ {
+ SetBackgroundColor(Element.BackgroundColor.ToAndroid(Color.Transparent));
+ }
+
+ void UpdateOrientation()
+ {
+ if (_view.Orientation == ScrollOrientation.Horizontal || _view.Orientation == ScrollOrientation.Both)
+ {
+ if (_hScrollView == null)
+ _hScrollView = new AHorizontalScrollView(Context, this);
+
+ ((AHorizontalScrollView)_hScrollView).IsBidirectional = _isBidirectional = _view.Orientation == ScrollOrientation.Both;
+
+ if (_hScrollView.Parent != this)
+ {
+ _container.RemoveFromParent();
+ _hScrollView.AddView(_container);
+ AddView(_hScrollView);
+ }
+ }
+ else
+ {
+ if (_container.Parent != this)
+ {
+ _container.RemoveFromParent();
+ if (_hScrollView != null)
+ _hScrollView.RemoveFromParent();
+ AddView(_container);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/SearchBarRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/SearchBarRenderer.cs
new file mode 100644
index 00000000..e31b95aa
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/SearchBarRenderer.cs
@@ -0,0 +1,236 @@
+using System.ComponentModel;
+using System.Linq;
+using Android.Content.Res;
+using Android.Graphics;
+using Android.OS;
+using Android.Text;
+using Android.Util;
+using Android.Widget;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class SearchBarRenderer : ViewRenderer<SearchBar, SearchView>, SearchView.IOnQueryTextListener
+ {
+ EditText _editText;
+ ColorStateList _hintTextColorDefault;
+ InputTypes _inputType;
+ ColorStateList _textColorDefault;
+
+ public SearchBarRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ bool SearchView.IOnQueryTextListener.OnQueryTextChange(string newText)
+ {
+ ((IElementController)Element).SetValueFromRenderer(SearchBar.TextProperty, newText);
+
+ return true;
+ }
+
+ bool SearchView.IOnQueryTextListener.OnQueryTextSubmit(string query)
+ {
+ Element.OnSearchButtonPressed();
+ Control.ClearFocus();
+ return true;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
+ {
+ base.OnElementChanged(e);
+
+ HandleKeyboardOnFocus = true;
+
+ SearchView searchView = Control;
+
+ if (searchView == null)
+ {
+ searchView = new SearchView(Context);
+ searchView.SetIconifiedByDefault(false);
+ searchView.Iconified = false;
+ SetNativeControl(searchView);
+ }
+
+ BuildVersionCodes androidVersion = Build.VERSION.SdkInt;
+ if (androidVersion >= BuildVersionCodes.JellyBean)
+ _inputType = searchView.InputType;
+ else
+ {
+ // < API 16, Cannot get the default InputType for a SearchView
+ _inputType = InputTypes.ClassText | InputTypes.TextFlagAutoComplete | InputTypes.TextFlagNoSuggestions;
+ }
+
+ searchView.ClearFocus();
+ UpdatePlaceholder();
+ UpdateText();
+ UpdateEnabled();
+ UpdateCancelButtonColor();
+ UpdateFont();
+ UpdateAlignment();
+ UpdateTextColor();
+ UpdatePlaceholderColor();
+
+ if (e.OldElement == null)
+ {
+ searchView.SetOnQueryTextListener(this);
+ searchView.SetOnQueryTextFocusChangeListener(this);
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == SearchBar.PlaceholderProperty.PropertyName)
+ UpdatePlaceholder();
+ else if (e.PropertyName == SearchBar.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == SearchBar.CancelButtonColorProperty.PropertyName)
+ UpdateCancelButtonColor();
+ else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ UpdateEnabled();
+ else if (e.PropertyName == SearchBar.FontAttributesProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == SearchBar.FontFamilyProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == SearchBar.FontSizeProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == SearchBar.HorizontalTextAlignmentProperty.PropertyName)
+ UpdateAlignment();
+ else if (e.PropertyName == SearchBar.TextColorProperty.PropertyName)
+ UpdateTextColor();
+ else if (e.PropertyName == SearchBar.PlaceholderColorProperty.PropertyName)
+ UpdatePlaceholderColor();
+ }
+
+ internal override void OnNativeFocusChanged(bool hasFocus)
+ {
+ if (hasFocus && !Element.IsEnabled)
+ Control.ClearFocus();
+ }
+
+ void UpdateAlignment()
+ {
+ _editText = _editText ?? Control.GetChildrenOfType<EditText>().FirstOrDefault();
+
+ if (_editText == null)
+ return;
+
+ _editText.Gravity = Element.HorizontalTextAlignment.ToHorizontalGravityFlags() | Xamarin.Forms.TextAlignment.Center.ToVerticalGravityFlags();
+ }
+
+ void UpdateCancelButtonColor()
+ {
+ int searchViewCloseButtonId = Control.Resources.GetIdentifier("android:id/search_close_btn", null, null);
+ if (searchViewCloseButtonId != 0)
+ {
+ var image = FindViewById<ImageView>(searchViewCloseButtonId);
+ if (image != null && image.Drawable != null)
+ {
+ if (Element.CancelButtonColor != Color.Default)
+ image.Drawable.SetColorFilter(Element.CancelButtonColor.ToAndroid(), PorterDuff.Mode.SrcIn);
+ else
+ image.Drawable.ClearColorFilter();
+ }
+ }
+ }
+
+ void UpdateEnabled()
+ {
+ SearchBar model = Element;
+ SearchView control = Control;
+ if (!model.IsEnabled)
+ {
+ control.ClearFocus();
+ // removes cursor in SearchView
+ control.SetInputType(InputTypes.Null);
+ }
+ else
+ control.SetInputType(_inputType);
+ }
+
+ void UpdateFont()
+ {
+ _editText = _editText ?? Control.GetChildrenOfType<EditText>().FirstOrDefault();
+
+ if (_editText == null)
+ return;
+
+ _editText.Typeface = Element.ToTypeface();
+ _editText.SetTextSize(ComplexUnitType.Sp, (float)Element.FontSize);
+ }
+
+ void UpdatePlaceholder()
+ {
+ Control.SetQueryHint(Element.Placeholder);
+ }
+
+ void UpdatePlaceholderColor()
+ {
+ _editText = _editText ?? Control.GetChildrenOfType<EditText>().FirstOrDefault();
+
+ if (_editText == null)
+ return;
+
+ Color placeholderColor = Element.PlaceholderColor;
+
+ if (placeholderColor.IsDefault)
+ {
+ if (_hintTextColorDefault == null)
+ {
+ // This control has always had the default colors; nothing to update
+ return;
+ }
+
+ // This control is being set back to the default colors
+ _editText.SetHintTextColor(_hintTextColorDefault);
+ }
+ else
+ {
+ // Keep track of the default colors so we can return to them later
+ // and so we can preserve the default disabled color
+ _hintTextColorDefault = _hintTextColorDefault ?? _editText.HintTextColors;
+
+ _editText.SetHintTextColor(placeholderColor.ToAndroidPreserveDisabled(_hintTextColorDefault));
+ }
+ }
+
+ void UpdateText()
+ {
+ string query = Control.Query;
+ if (query != Element.Text)
+ Control.SetQuery(Element.Text, false);
+ }
+
+ void UpdateTextColor()
+ {
+ _editText = _editText ?? Control.GetChildrenOfType<EditText>().FirstOrDefault();
+
+ if (_editText == null)
+ return;
+
+ Color textColor = Element.TextColor;
+
+ if (textColor.IsDefault)
+ {
+ if (_textColorDefault == null)
+ {
+ // This control has always had the default colors; nothing to update
+ return;
+ }
+
+ // This control is being set back to the default colors
+ _editText.SetTextColor(_textColorDefault);
+ }
+ else
+ {
+ // Keep track of the default colors so we can return to them later
+ // and so we can preserve the default disabled color
+ _textColorDefault = _textColorDefault ?? _editText.TextColors;
+
+ _editText.SetTextColor(textColor.ToAndroidPreserveDisabled(_textColorDefault));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/SliderRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/SliderRenderer.cs
new file mode 100644
index 00000000..694052ef
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/SliderRenderer.cs
@@ -0,0 +1,98 @@
+using System.ComponentModel;
+using Android.Graphics.Drawables;
+using Android.OS;
+using Android.Widget;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class SliderRenderer : ViewRenderer<Slider, SeekBar>, SeekBar.IOnSeekBarChangeListener
+ {
+ double _max;
+ double _min;
+
+ public SliderRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ double Value
+ {
+ get { return _min + (_max - _min) * (Control.Progress / 1000.0); }
+ set { Control.Progress = (int)((value - _min) / (_max - _min) * 1000.0); }
+ }
+
+ void SeekBar.IOnSeekBarChangeListener.OnProgressChanged(SeekBar seekBar, int progress, bool fromUser)
+ {
+ ((IElementController)Element).SetValueFromRenderer(Slider.ValueProperty, Value);
+ }
+
+ void SeekBar.IOnSeekBarChangeListener.OnStartTrackingTouch(SeekBar seekBar)
+ {
+ }
+
+ void SeekBar.IOnSeekBarChangeListener.OnStopTrackingTouch(SeekBar seekBar)
+ {
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Slider> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement == null)
+ {
+ var seekBar = new SeekBar(Context);
+ SetNativeControl(seekBar);
+
+ seekBar.Max = 1000;
+
+ seekBar.SetOnSeekBarChangeListener(this);
+ }
+
+ Slider slider = e.NewElement;
+ _min = slider.Minimum;
+ _max = slider.Maximum;
+ Value = slider.Value;
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ Slider view = Element;
+ switch (e.PropertyName)
+ {
+ case "Maximum":
+ _max = view.Maximum;
+ break;
+ case "Minimum":
+ _min = view.Minimum;
+ break;
+ case "Value":
+ if (Value != view.Value)
+ Value = view.Value;
+ break;
+ }
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ base.OnLayout(changed, l, t, r, b);
+
+ BuildVersionCodes androidVersion = Build.VERSION.SdkInt;
+ if (androidVersion >= BuildVersionCodes.JellyBean)
+ {
+ // Thumb only supported JellyBean and higher
+
+ if (Control == null)
+ return;
+
+ SeekBar seekbar = Control;
+
+ Drawable thumb = seekbar.Thumb;
+ int thumbTop = seekbar.Height / 2 - thumb.IntrinsicHeight / 2;
+
+ thumb.SetBounds(thumb.Bounds.Left, thumbTop, thumb.Bounds.Left + thumb.IntrinsicWidth, thumbTop + thumb.IntrinsicHeight);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/StepperRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/StepperRenderer.cs
new file mode 100644
index 00000000..70eed60b
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/StepperRenderer.cs
@@ -0,0 +1,94 @@
+using System.ComponentModel;
+using Android.Views;
+using Android.Widget;
+using Java.Lang;
+using AButton = Android.Widget.Button;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class StepperRenderer : ViewRenderer<Stepper, LinearLayout>
+ {
+ AButton _downButton;
+ AButton _upButton;
+
+ public StepperRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement == null)
+ {
+ _downButton = new AButton(Context) { Text = "-", Gravity = GravityFlags.Center, Tag = this };
+
+ _downButton.SetOnClickListener(StepperListener.Instance);
+
+ _upButton = new AButton(Context) { Text = "+", Tag = this };
+
+ _upButton.SetOnClickListener(StepperListener.Instance);
+ _upButton.SetHeight((int)Context.ToPixels(10.0));
+
+ var layout = new LinearLayout(Context) { Orientation = Orientation.Horizontal };
+
+ layout.AddView(_downButton);
+ layout.AddView(_upButton);
+
+ SetNativeControl(layout);
+ }
+
+ UpdateButtonEnabled();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ switch (e.PropertyName)
+ {
+ case "Minimum":
+ UpdateButtonEnabled();
+ break;
+ case "Maximum":
+ UpdateButtonEnabled();
+ break;
+ case "Value":
+ UpdateButtonEnabled();
+ break;
+ case "IsEnabled":
+ UpdateButtonEnabled();
+ break;
+ }
+ }
+
+ void UpdateButtonEnabled()
+ {
+ Stepper view = Element;
+ _upButton.Enabled = view.IsEnabled ? view.Value < view.Maximum : view.IsEnabled;
+ _downButton.Enabled = view.IsEnabled ? view.Value > view.Minimum : view.IsEnabled;
+ }
+
+ class StepperListener : Object, IOnClickListener
+ {
+ public static readonly StepperListener Instance = new StepperListener();
+
+ public void OnClick(global::Android.Views.View v)
+ {
+ var renderer = v.Tag as StepperRenderer;
+ if (renderer == null)
+ return;
+
+ Stepper stepper = renderer.Element;
+ if (stepper == null)
+ return;
+
+ if (v == renderer._upButton)
+ ((IElementController)stepper).SetValueFromRenderer(Stepper.ValueProperty, stepper.Value + stepper.Increment);
+ else if (v == renderer._downButton)
+ ((IElementController)stepper).SetValueFromRenderer(Stepper.ValueProperty, stepper.Value - stepper.Increment);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/StreamImagesourceHandler.cs b/Xamarin.Forms.Platform.Android/Renderers/StreamImagesourceHandler.cs
new file mode 100644
index 00000000..708ed665
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/StreamImagesourceHandler.cs
@@ -0,0 +1,22 @@
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Android.Content;
+using Android.Graphics;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public sealed class StreamImagesourceHandler : IImageSourceHandler
+ {
+ public async Task<Bitmap> LoadImageAsync(ImageSource imagesource, Context context, CancellationToken cancelationToken = default(CancellationToken))
+ {
+ var streamsource = imagesource as StreamImageSource;
+ if (streamsource != null && streamsource.Stream != null)
+ {
+ using(Stream stream = await streamsource.GetStreamAsync(cancelationToken).ConfigureAwait(false))
+ return await BitmapFactory.DecodeStreamAsync(stream).ConfigureAwait(false);
+ }
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/SwitchRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/SwitchRenderer.cs
new file mode 100644
index 00000000..39916b58
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/SwitchRenderer.cs
@@ -0,0 +1,83 @@
+using System;
+using Android.Widget;
+using ASwitch = Android.Widget.Switch;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class SwitchRenderer : ViewRenderer<Switch, ASwitch>, CompoundButton.IOnCheckedChangeListener
+ {
+ public SwitchRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ void CompoundButton.IOnCheckedChangeListener.OnCheckedChanged(CompoundButton buttonView, bool isChecked)
+ {
+ ((IViewController)Element).SetValueFromRenderer(Switch.IsToggledProperty, isChecked);
+ }
+
+ public override SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)
+ {
+ SizeRequest sizeConstraint = base.GetDesiredSize(widthConstraint, heightConstraint);
+
+ if (sizeConstraint.Request.Width == 0)
+ {
+ int width = widthConstraint;
+ if (widthConstraint <= 0)
+ width = (int)Context.GetThemeAttributeDp(global::Android.Resource.Attribute.SwitchMinWidth);
+ else if (widthConstraint <= 0)
+ width = 100;
+
+ sizeConstraint = new SizeRequest(new Size(width, sizeConstraint.Request.Height), new Size(width, sizeConstraint.Minimum.Height));
+ }
+
+ return sizeConstraint;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && Control != null)
+ {
+ if (Element != null)
+ Element.Toggled -= HandleToggled;
+
+ Control.SetOnCheckedChangeListener(null);
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Switch> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ e.OldElement.Toggled -= HandleToggled;
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var aswitch = new ASwitch(Context);
+ aswitch.SetOnCheckedChangeListener(this);
+ SetNativeControl(aswitch);
+ }
+ else
+ UpdateEnabled(); // Normally set by SetNativeControl, but not when the Control is reused.
+
+ e.NewElement.Toggled += HandleToggled;
+ Control.Checked = e.NewElement.IsToggled;
+ }
+ }
+
+ void HandleToggled(object sender, EventArgs e)
+ {
+ Control.Checked = Element.IsToggled;
+ }
+
+ void UpdateEnabled()
+ {
+ Control.Enabled = Element.IsEnabled;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/TabbedRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/TabbedRenderer.cs
new file mode 100644
index 00000000..35404a64
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/TabbedRenderer.cs
@@ -0,0 +1,75 @@
+using System.ComponentModel;
+using AButton = Android.Widget.Button;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class TabbedRenderer : VisualElementRenderer<TabbedPage>
+ {
+ public TabbedRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && Element != null && Element.Children.Count > 0)
+ {
+ RemoveAllViews();
+ foreach (Page pageToRemove in Element.Children)
+ {
+ IVisualElementRenderer pageRenderer = Platform.GetRenderer(pageToRemove);
+ if (pageRenderer != null)
+ pageRenderer.Dispose();
+ pageToRemove.ClearValue(Platform.RendererProperty);
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnAttachedToWindow()
+ {
+ base.OnAttachedToWindow();
+ Element.SendAppearing();
+ }
+
+ protected override void OnDetachedFromWindow()
+ {
+ base.OnDetachedFromWindow();
+ Element.SendDisappearing();
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
+ {
+ base.OnElementChanged(e);
+
+ TabbedPage tabs = e.NewElement;
+ if (tabs.CurrentPage != null)
+ SwitchContent(tabs.CurrentPage);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == "CurrentPage")
+ SwitchContent(Element.CurrentPage);
+ }
+
+ protected virtual void SwitchContent(Page view)
+ {
+ Context.HideKeyboard(this);
+
+ RemoveAllViews();
+
+ if (view == null)
+ return;
+
+ if (Platform.GetRenderer(view) == null)
+ Platform.SetRenderer(view, Platform.CreateRenderer(view));
+
+ AddView(Platform.GetRenderer(view).ViewGroup);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/TableViewModelRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/TableViewModelRenderer.cs
new file mode 100644
index 00000000..a7659ed8
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/TableViewModelRenderer.cs
@@ -0,0 +1,228 @@
+using Android.Content;
+using Android.Util;
+using Android.Views;
+using Android.Widget;
+using AView = Android.Views.View;
+using AListView = Android.Widget.ListView;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class TableViewModelRenderer : CellAdapter
+ {
+ readonly TableView _view;
+ protected readonly Context Context;
+ Cell _restoreFocus;
+
+ public TableViewModelRenderer(Context context, AListView listView, TableView view) : base(context)
+ {
+ _view = view;
+ Context = context;
+
+ view.ModelChanged += (sender, args) => NotifyDataSetChanged();
+
+ listView.OnItemClickListener = this;
+ listView.OnItemLongClickListener = this;
+ }
+
+ public override int Count
+ {
+ get
+ {
+ var count = 0;
+
+ //Get each adapter's count + 1 for the header
+ int section = _view.Model.GetSectionCount();
+ for (var i = 0; i < section; i++)
+ count += _view.Model.GetRowCount(i) + 1;
+
+ return count;
+ }
+ }
+
+ public override object this[int position]
+ {
+ get
+ {
+ bool isHeader, nextIsHeader;
+ Cell cell = GetCellForPosition(position, out isHeader, out nextIsHeader);
+ return cell;
+ }
+ }
+
+ public override int ViewTypeCount
+ {
+ get
+ {
+ //The headers count as a view type too
+ var viewTypeCount = 1;
+
+ //Get each adapter's ViewTypeCount
+ int section = _view.Model.GetSectionCount();
+ for (var i = 0; i < section; i++)
+ viewTypeCount += _view.Model.GetRowCount(i);
+
+ return viewTypeCount;
+ }
+ }
+
+ public override bool AreAllItemsEnabled()
+ {
+ return false;
+ }
+
+ public override long GetItemId(int position)
+ {
+ return position;
+ }
+
+ public override AView GetView(int position, AView convertView, ViewGroup parent)
+ {
+ object obj = this[position];
+ if (obj == null)
+ return new AView(Context);
+
+ bool isHeader, nextIsHeader;
+ Cell item = GetCellForPosition(position, out isHeader, out nextIsHeader);
+
+ var makeBline = true;
+ var layout = convertView as ConditionalFocusLayout;
+ if (layout != null)
+ {
+ makeBline = false;
+ convertView = layout.GetChildAt(0);
+ }
+ else
+ layout = new ConditionalFocusLayout(Context) { Orientation = Orientation.Vertical };
+
+ AView aview = CellFactory.GetCell(item, convertView, parent, Context, _view);
+
+ if (!makeBline)
+ {
+ if (convertView != aview)
+ {
+ layout.RemoveViewAt(0);
+ layout.AddView(aview, 0);
+ }
+ }
+ else
+ layout.AddView(aview, 0);
+
+ AView bline;
+ if (makeBline)
+ {
+ bline = new AView(Context) { LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FillParent, 1) };
+
+ layout.AddView(bline);
+ }
+ else
+ bline = layout.GetChildAt(1);
+
+ if (isHeader)
+ bline.SetBackgroundColor(Color.Accent.ToAndroid());
+ else if (nextIsHeader)
+ bline.SetBackgroundColor(global::Android.Graphics.Color.Transparent);
+ else
+ {
+ using(var value = new TypedValue())
+ {
+ int id = global::Android.Resource.Drawable.DividerHorizontalDark;
+ if (Context.Theme.ResolveAttribute(global::Android.Resource.Attribute.ListDivider, value, true))
+ id = value.ResourceId;
+ else if (Context.Theme.ResolveAttribute(global::Android.Resource.Attribute.Divider, value, true))
+ id = value.ResourceId;
+
+ bline.SetBackgroundResource(id);
+ }
+ }
+
+ layout.ApplyTouchListenersToSpecialCells(item);
+
+ if (_restoreFocus == item)
+ {
+ if (!aview.HasFocus)
+ aview.RequestFocus();
+
+ _restoreFocus = null;
+ }
+ else if (aview.HasFocus)
+ aview.ClearFocus();
+
+ return layout;
+ }
+
+ public override bool IsEnabled(int position)
+ {
+ bool isHeader, nextIsHeader;
+ Cell item = GetCellForPosition(position, out isHeader, out nextIsHeader);
+ return !isHeader && item.IsEnabled;
+ }
+
+ protected override Cell GetCellForPosition(int position)
+ {
+ bool isHeader, nextIsHeader;
+ return GetCellForPosition(position, out isHeader, out nextIsHeader);
+ }
+
+ protected override void HandleItemClick(AdapterView parent, AView nview, int position, long id)
+ {
+ int sectionCount = _view.Model.GetSectionCount();
+ for (var sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++)
+ {
+ if (position == 0)
+ return;
+
+ int size = _view.Model.GetRowCount(sectionIndex) + 1;
+
+ if (position < size)
+ {
+ _view.Model.RowSelected(sectionIndex, position - 1);
+ return;
+ }
+
+ position -= size;
+ }
+ }
+
+ Cell GetCellForPosition(int position, out bool isHeader, out bool nextIsHeader)
+ {
+ isHeader = false;
+ nextIsHeader = false;
+
+ int sectionCount = _view.Model.GetSectionCount();
+
+ for (var sectionIndex = 0; sectionIndex < sectionCount; sectionIndex ++)
+ {
+ int size = _view.Model.GetRowCount(sectionIndex) + 1;
+
+ if (position == 0)
+ {
+ isHeader = true;
+ nextIsHeader = size == 0 && sectionIndex < sectionCount - 1;
+
+ Cell header = _view.Model.GetHeaderCell(sectionIndex);
+
+ Cell resultCell = null;
+ if (header != null)
+ resultCell = header;
+
+ if (resultCell == null)
+ resultCell = new TextCell { Text = _view.Model.GetSectionTitle(sectionIndex) };
+
+ resultCell.Parent = _view;
+
+ return resultCell;
+ }
+
+ if (position < size)
+ {
+ nextIsHeader = position == size - 1;
+ return (Cell)_view.Model.GetItem(sectionIndex, position - 1);
+ }
+
+ position -= size;
+ }
+
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/TableViewRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/TableViewRenderer.cs
new file mode 100644
index 00000000..e4017a7e
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/TableViewRenderer.cs
@@ -0,0 +1,44 @@
+using Android.Views;
+using AView = Android.Views.View;
+using AListView = Android.Widget.ListView;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class TableViewRenderer : ViewRenderer<TableView, AListView>
+ {
+ public TableViewRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected virtual TableViewModelRenderer GetModelRenderer(AListView listView, TableView view)
+ {
+ return new TableViewModelRenderer(Context, listView, view);
+ }
+
+ protected override Size MinimumSize()
+ {
+ return new Size(40, 40);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<TableView> e)
+ {
+ base.OnElementChanged(e);
+
+ AListView listView = Control;
+ if (listView == null)
+ {
+ listView = new AListView(Context);
+ SetNativeControl(listView);
+ }
+
+ listView.Focusable = false;
+ listView.DescendantFocusability = DescendantFocusability.AfterDescendants;
+
+ TableView view = e.NewElement;
+
+ TableViewModelRenderer source = GetModelRenderer(listView, view);
+ listView.Adapter = source;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/TimePickerRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/TimePickerRenderer.cs
new file mode 100644
index 00000000..cfa676d0
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/TimePickerRenderer.cs
@@ -0,0 +1,95 @@
+using System;
+using System.ComponentModel;
+using Android.App;
+using Android.Widget;
+using ADatePicker = Android.Widget.DatePicker;
+using ATimePicker = Android.Widget.TimePicker;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class TimePickerRenderer : ViewRenderer<TimePicker, EditText>, TimePickerDialog.IOnTimeSetListener
+ {
+ AlertDialog _dialog;
+
+ public TimePickerRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ void TimePickerDialog.IOnTimeSetListener.OnTimeSet(ATimePicker view, int hourOfDay, int minute)
+ {
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+
+ ((IElementController)Element).SetValueFromRenderer(TimePicker.TimeProperty, new TimeSpan(hourOfDay, minute, 0));
+ Control.ClearFocus();
+ _dialog = null;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement == null)
+ {
+ var textField = new EditText(Context) { Focusable = false, Clickable = true, Tag = this };
+
+ textField.SetOnClickListener(TimePickerListener.Instance);
+ SetNativeControl(textField);
+ }
+
+ SetTime(e.NewElement.Time);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == TimePicker.TimeProperty.PropertyName || e.PropertyName == TimePicker.FormatProperty.PropertyName)
+ SetTime(Element.Time);
+ }
+
+ internal override void OnFocusChangeRequested(object sender, VisualElement.FocusRequestArgs e)
+ {
+ base.OnFocusChangeRequested(sender, e);
+
+ if (e.Focus)
+ OnClick();
+ else if (_dialog != null)
+ {
+ _dialog.Hide();
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ Control.ClearFocus();
+ _dialog = null;
+ }
+ }
+
+ void OnClick()
+ {
+ TimePicker view = Element;
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
+
+ _dialog = new TimePickerDialog(Context, this, view.Time.Hours, view.Time.Minutes, false);
+ _dialog.Show();
+ }
+
+ void SetTime(TimeSpan time)
+ {
+ Control.Text = DateTime.Today.Add(time).ToString(Element.Format);
+ }
+
+ class TimePickerListener : Object, IOnClickListener
+ {
+ public static readonly TimePickerListener Instance = new TimePickerListener();
+
+ public void OnClick(global::Android.Views.View v)
+ {
+ var renderer = v.Tag as TimePickerRenderer;
+ if (renderer == null)
+ return;
+
+ renderer.OnClick();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ToolbarButton.cs b/Xamarin.Forms.Platform.Android/Renderers/ToolbarButton.cs
new file mode 100644
index 00000000..74ff08b8
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ToolbarButton.cs
@@ -0,0 +1,36 @@
+using System;
+using System.ComponentModel;
+using Android.Content;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal sealed class ToolbarButton : global::Android.Widget.Button, IToolbarButton
+ {
+ public ToolbarButton(Context context, ToolbarItem item) : base(context)
+ {
+ if (item == null)
+ throw new ArgumentNullException("item", "you should specify a ToolbarItem");
+ Item = item;
+ Enabled = Item.IsEnabled;
+ Text = Item.Text;
+ SetBackgroundColor(new Color(0, 0, 0, 0).ToAndroid());
+ Click += (sender, e) => Item.Activate();
+ Item.PropertyChanged += HandlePropertyChanged;
+ }
+
+ public ToolbarItem Item { get; set; }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ Item.PropertyChanged -= HandlePropertyChanged;
+ base.Dispose(disposing);
+ }
+
+ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == MenuItem.IsEnabledProperty.PropertyName)
+ Enabled = Item.IsEnabled;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ToolbarImageButton.cs b/Xamarin.Forms.Platform.Android/Renderers/ToolbarImageButton.cs
new file mode 100644
index 00000000..6d18db54
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ToolbarImageButton.cs
@@ -0,0 +1,41 @@
+using System;
+using System.ComponentModel;
+using Android.Content;
+using Android.Graphics;
+using Android.Widget;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal sealed class ToolbarImageButton : ImageButton, IToolbarButton
+ {
+ public ToolbarImageButton(Context context, ToolbarItem item) : base(context)
+ {
+ if (item == null)
+ throw new ArgumentNullException("item", "you should specify a ToolbarItem");
+ Item = item;
+ Enabled = item.IsEnabled;
+ Bitmap bitmap;
+ bitmap = Context.Resources.GetBitmap(Item.Icon);
+ SetImageBitmap(bitmap);
+ SetBackgroundColor(new Color(0, 0, 0, 0).ToAndroid());
+ Click += (sender, e) => item.Activate();
+ bitmap.Dispose();
+ Item.PropertyChanged += HandlePropertyChanged;
+ }
+
+ public ToolbarItem Item { get; set; }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ Item.PropertyChanged -= HandlePropertyChanged;
+ base.Dispose(disposing);
+ }
+
+ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == MenuItem.IsEnabledProperty.PropertyName)
+ Enabled = Item.IsEnabled;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ToolbarRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/ToolbarRenderer.cs
new file mode 100644
index 00000000..f40b75f3
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ToolbarRenderer.cs
@@ -0,0 +1,65 @@
+using Android.Widget;
+using AScrollView = Android.Widget.ScrollView;
+using AButton = Android.Widget.Button;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class ToolbarRenderer : ViewRenderer
+ {
+ public ToolbarRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<View> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement == null)
+ {
+ var layout = new LinearLayout(Context);
+ layout.SetBackgroundColor(new Color(0.2, 0.2, 0.2, 0.5).ToAndroid());
+
+ layout.Orientation = Orientation.Horizontal;
+
+ SetNativeControl(layout);
+ }
+ else
+ {
+ var oldToolbar = (Toolbar)e.OldElement;
+ oldToolbar.ItemAdded -= OnToolbarItemsChanged;
+ oldToolbar.ItemRemoved -= OnToolbarItemsChanged;
+ }
+
+ UpdateChildren();
+
+ var toolbar = (Toolbar)e.NewElement;
+ toolbar.ItemAdded += OnToolbarItemsChanged;
+ toolbar.ItemRemoved += OnToolbarItemsChanged;
+ }
+
+ void OnToolbarItemsChanged(object sender, ToolbarItemEventArgs e)
+ {
+ UpdateChildren();
+ }
+
+ void UpdateChildren()
+ {
+ RemoveAllViews();
+
+ foreach (ToolbarItem child in ((Toolbar)Element).Items)
+ {
+ AView view = null;
+
+ if (!string.IsNullOrEmpty(child.Icon))
+ view = new ToolbarImageButton(Context, child);
+ else
+ view = new AButton(Context);
+
+ using(var param = new LinearLayout.LayoutParams(LayoutParams.WrapContent, (int)Context.ToPixels(48), 1))
+ ((LinearLayout)Control).AddView(view, param);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ViewGroupExtensions.cs b/Xamarin.Forms.Platform.Android/Renderers/ViewGroupExtensions.cs
new file mode 100644
index 00000000..dfcb9ca2
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/ViewGroupExtensions.cs
@@ -0,0 +1,27 @@
+using System.Collections.Generic;
+using AView = Android.Views.View;
+using AViewGroup = Android.Views.ViewGroup;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal static class ViewGroupExtensions
+ {
+ internal static IEnumerable<T> GetChildrenOfType<T>(this AViewGroup self) where T : AView
+ {
+ for (var i = 0; i < self.ChildCount; i++)
+ {
+ AView child = self.GetChildAt(i);
+ var typedChild = child as T;
+ if (typedChild != null)
+ yield return typedChild;
+
+ if (child is AViewGroup)
+ {
+ IEnumerable<T> myChildren = (child as AViewGroup).GetChildrenOfType<T>();
+ foreach (T nextChild in myChildren)
+ yield return nextChild;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Renderers/WebViewRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/WebViewRenderer.cs
new file mode 100644
index 00000000..d2c0f0d6
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/WebViewRenderer.cs
@@ -0,0 +1,206 @@
+using System;
+using System.ComponentModel;
+using Android.Webkit;
+using AWebView = Android.Webkit.WebView;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class WebViewRenderer : ViewRenderer<WebView, AWebView>, IWebViewRenderer
+ {
+ bool _ignoreSourceChanges;
+ FormsWebChromeClient _webChromeClient;
+
+ public WebViewRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ public void LoadHtml(string html, string baseUrl)
+ {
+ Control.LoadDataWithBaseURL(baseUrl == null ? "file:///android_asset/" : baseUrl, html, "text/html", "UTF-8", null);
+ }
+
+ public void LoadUrl(string url)
+ {
+ Control.LoadUrl(url);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (Element != null)
+ {
+ if (Control != null)
+ Control.StopLoading();
+ Element.EvalRequested -= OnEvalRequested;
+ Element.GoBackRequested -= OnGoBackRequested;
+ Element.GoForwardRequested -= OnGoForwardRequested;
+
+ _webChromeClient?.Dispose();
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected virtual FormsWebChromeClient GetFormsWebChromeClient()
+ {
+ return new FormsWebChromeClient();
+ }
+
+ protected override Size MinimumSize()
+ {
+ return new Size(Context.ToPixels(40), Context.ToPixels(40));
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
+ {
+ base.OnElementChanged(e);
+
+ if (Control == null)
+ {
+ var webView = new AWebView(Context);
+ webView.LayoutParameters = new global::Android.Widget.AbsoluteLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent, 0, 0);
+ webView.SetWebViewClient(new WebClient(this));
+
+ _webChromeClient = GetFormsWebChromeClient();
+ _webChromeClient.SetContext(Context as IStartActivityForResult);
+ webView.SetWebChromeClient(_webChromeClient);
+
+ webView.Settings.JavaScriptEnabled = true;
+ webView.Settings.DomStorageEnabled = true;
+ SetNativeControl(webView);
+ }
+
+ if (e.OldElement != null)
+ {
+ e.OldElement.EvalRequested -= OnEvalRequested;
+ e.OldElement.GoBackRequested -= OnGoBackRequested;
+ e.OldElement.GoForwardRequested -= OnGoForwardRequested;
+ }
+
+ if (e.NewElement != null)
+ {
+ e.NewElement.EvalRequested += OnEvalRequested;
+ e.NewElement.GoBackRequested += OnGoBackRequested;
+ e.NewElement.GoForwardRequested += OnGoForwardRequested;
+ }
+
+ Load();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ switch (e.PropertyName)
+ {
+ case "Source":
+ Load();
+ break;
+ }
+ }
+
+ void Load()
+ {
+ if (_ignoreSourceChanges)
+ return;
+
+ if (Element.Source != null)
+ Element.Source.Load(this);
+
+ UpdateCanGoBackForward();
+ }
+
+ void OnEvalRequested(object sender, EventArg<string> eventArg)
+ {
+ LoadUrl("javascript:" + eventArg.Data);
+ }
+
+ void OnGoBackRequested(object sender, EventArgs eventArgs)
+ {
+ if (Control.CanGoBack())
+ Control.GoBack();
+
+ UpdateCanGoBackForward();
+ }
+
+ void OnGoForwardRequested(object sender, EventArgs eventArgs)
+ {
+ if (Control.CanGoForward())
+ Control.GoForward();
+
+ UpdateCanGoBackForward();
+ }
+
+ void UpdateCanGoBackForward()
+ {
+ if (Element == null || Control == null)
+ return;
+ Element.CanGoBack = Control.CanGoBack();
+ Element.CanGoForward = Control.CanGoForward();
+ }
+
+ class WebClient : WebViewClient
+ {
+ WebNavigationResult _navigationResult = WebNavigationResult.Success;
+ WebViewRenderer _renderer;
+
+ public WebClient(WebViewRenderer renderer)
+ {
+ if (renderer == null)
+ throw new ArgumentNullException("renderer");
+ _renderer = renderer;
+ }
+
+ public override void OnPageFinished(AWebView view, string url)
+ {
+ if (_renderer.Element == null || url == "file:///android_asset/")
+ return;
+
+ var source = new UrlWebViewSource { Url = url };
+ _renderer._ignoreSourceChanges = true;
+ ((IElementController)_renderer.Element).SetValueFromRenderer(WebView.SourceProperty, source);
+ _renderer._ignoreSourceChanges = false;
+
+ var args = new WebNavigatedEventArgs(WebNavigationEvent.NewPage, source, url, _navigationResult);
+
+ _renderer.Element.SendNavigated(args);
+
+ _renderer.UpdateCanGoBackForward();
+
+ base.OnPageFinished(view, url);
+ }
+
+ public override void OnReceivedError(AWebView view, ClientError errorCode, string description, string failingUrl)
+ {
+ _navigationResult = WebNavigationResult.Failure;
+ if (errorCode == ClientError.Timeout)
+ _navigationResult = WebNavigationResult.Timeout;
+ base.OnReceivedError(view, errorCode, description, failingUrl);
+ }
+
+ public override bool ShouldOverrideUrlLoading(AWebView view, string url)
+ {
+ if (_renderer.Element == null)
+ return true;
+
+ var args = new WebNavigatingEventArgs(WebNavigationEvent.NewPage, new UrlWebViewSource { Url = url }, url);
+
+ _renderer.Element.SendNavigating(args);
+ _navigationResult = WebNavigationResult.Success;
+
+ _renderer.UpdateCanGoBackForward();
+ return args.Cancel;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ if (disposing)
+ _renderer = null;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/ResourceManager.cs b/Xamarin.Forms.Platform.Android/ResourceManager.cs
new file mode 100644
index 00000000..4c150a05
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/ResourceManager.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using System.Threading.Tasks;
+using Android.Content.Res;
+using Android.Graphics;
+using Android.Graphics.Drawables;
+using Path = System.IO.Path;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public static class ResourceManager
+ {
+ public static Type DrawableClass { get; set; }
+
+ public static Type ResourceClass { get; set; }
+
+ public static Bitmap GetBitmap(this Resources resource, string name)
+ {
+ return BitmapFactory.DecodeResource(resource, IdFromTitle(name, DrawableClass));
+ }
+
+ public static Task<Bitmap> GetBitmapAsync(this Resources resource, string name)
+ {
+ return BitmapFactory.DecodeResourceAsync(resource, IdFromTitle(name, DrawableClass));
+ }
+
+ public static Drawable GetDrawable(this Resources resource, string name)
+ {
+ int id = IdFromTitle(name, DrawableClass);
+ if (id == 0)
+ {
+ Log.Warning("Could not load image named: {0}", name);
+ return null;
+ }
+ return resource.GetDrawable(id);
+ }
+
+ public static int GetDrawableByName(string name)
+ {
+ return IdFromTitle(name, DrawableClass);
+ }
+
+ public static int GetResourceByName(string name)
+ {
+ return IdFromTitle(name, ResourceClass);
+ }
+
+ public static void Init(Assembly masterAssembly)
+ {
+ DrawableClass = masterAssembly.GetTypes().FirstOrDefault(x => x.Name == "Drawable");
+ ResourceClass = masterAssembly.GetTypes().FirstOrDefault(x => x.Name == "Id");
+ }
+
+ internal static int IdFromTitle(string title, Type type)
+ {
+ string name = Path.GetFileNameWithoutExtension(title);
+ int id = GetId(type, name);
+ return id; // Resources.System.GetDrawable (Resource.Drawable.dashboard);
+ }
+
+ static int GetId(Type type, string propertyName)
+ {
+ FieldInfo[] props = type.GetFields();
+ FieldInfo prop = props.Select(p => p).FirstOrDefault(p => p.Name == propertyName);
+ if (prop != null)
+ return (int)prop.GetValue(type);
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/ResourcesProvider.cs b/Xamarin.Forms.Platform.Android/ResourcesProvider.cs
new file mode 100644
index 00000000..334ef56a
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/ResourcesProvider.cs
@@ -0,0 +1,68 @@
+using Android.Content;
+using Android.Content.Res;
+using Android.Util;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class ResourcesProvider : ISystemResourcesProvider
+ {
+ ResourceDictionary _dictionary;
+
+ public IResourceDictionary GetSystemResources()
+ {
+ _dictionary = new ResourceDictionary();
+
+ UpdateStyles();
+
+ return _dictionary;
+ }
+
+ public Style GetStyle(int style)
+ {
+ var result = new Style(typeof(Label));
+
+ double fontSize = 0;
+ string fontFamily = null;
+ global::Android.Graphics.Color defaultColor = global::Android.Graphics.Color.Argb(0, 0, 0, 0);
+ global::Android.Graphics.Color androidColor = defaultColor;
+
+ Context context = Forms.Context;
+ using(var value = new TypedValue())
+ {
+ if (context.Theme.ResolveAttribute(style, value, true))
+ {
+ var styleattrs = new[] { global::Android.Resource.Attribute.TextSize, global::Android.Resource.Attribute.FontFamily, global::Android.Resource.Attribute.TextColor };
+ using(TypedArray array = context.ObtainStyledAttributes(value.ResourceId, styleattrs))
+ {
+ fontSize = context.FromPixels(array.GetDimensionPixelSize(0, -1));
+ fontFamily = array.GetString(1);
+ androidColor = array.GetColor(2, defaultColor);
+ }
+ }
+ }
+
+ if (fontSize > 0)
+ result.Setters.Add(new Setter { Property = Label.FontSizeProperty, Value = fontSize });
+
+ if (!string.IsNullOrEmpty(fontFamily))
+ result.Setters.Add(new Setter { Property = Label.FontFamilyProperty, Value = fontFamily });
+
+ if (androidColor != defaultColor)
+ {
+ result.Setters.Add(new Setter { Property = Label.TextColorProperty, Value = Color.FromRgba(androidColor.R, androidColor.G, androidColor.B, androidColor.A) });
+ }
+
+ return result;
+ }
+
+ void UpdateStyles()
+ {
+ _dictionary[Device.Styles.BodyStyleKey] = new Style(typeof(Label)); // do nothing, its fine
+ _dictionary[Device.Styles.TitleStyleKey] = GetStyle(global::Android.Resource.Attribute.TextAppearanceLarge);
+ _dictionary[Device.Styles.SubtitleStyleKey] = GetStyle(global::Android.Resource.Attribute.TextAppearanceMedium);
+ _dictionary[Device.Styles.CaptionStyleKey] = GetStyle(global::Android.Resource.Attribute.TextAppearanceSmall);
+ _dictionary[Device.Styles.ListItemTextStyleKey] = GetStyle(global::Android.Resource.Attribute.TextAppearanceListItem);
+ _dictionary[Device.Styles.ListItemDetailTextStyleKey] = GetStyle(global::Android.Resource.Attribute.TextAppearanceListItemSmall);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/TapGestureHandler.cs b/Xamarin.Forms.Platform.Android/TapGestureHandler.cs
new file mode 100644
index 00000000..dcd8d6f7
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/TapGestureHandler.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class TapGestureHandler
+ {
+ public TapGestureHandler(Func<View> getView)
+ {
+ GetView = getView;
+ }
+
+ Func<View> GetView { get; }
+
+ public void OnSingleClick()
+ {
+ // only handle click if we don't have double tap registered
+ if (TapGestureRecognizers(2).Any())
+ return;
+
+ OnTap(1);
+ }
+
+ public bool OnTap(int count)
+ {
+ View view = GetView();
+
+ if (view == null)
+ return false;
+
+ IEnumerable<TapGestureRecognizer> gestureRecognizers = TapGestureRecognizers(count);
+ var result = false;
+ foreach (TapGestureRecognizer gestureRecognizer in gestureRecognizers)
+ {
+ gestureRecognizer.SendTapped(view);
+ result = true;
+ }
+
+ return result;
+ }
+
+ public IEnumerable<TapGestureRecognizer> TapGestureRecognizers(int count)
+ {
+ View view = GetView();
+ if (view == null)
+ return Enumerable.Empty<TapGestureRecognizer>();
+
+ return view.GestureRecognizers.GetGesturesFor<TapGestureRecognizer>(recognizer => recognizer.NumberOfTapsRequired == count);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/ViewExtensions.cs b/Xamarin.Forms.Platform.Android/ViewExtensions.cs
new file mode 100644
index 00000000..04a80ef2
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/ViewExtensions.cs
@@ -0,0 +1,61 @@
+using Android.Content;
+using Android.Graphics.Drawables;
+using Android.OS;
+using Android.Util;
+using Android.Views;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public static class ViewExtensions
+ {
+ static int s_apiLevel;
+
+ public static void RemoveFromParent(this AView view)
+ {
+ if (view == null)
+ return;
+ if (view.Parent == null)
+ return;
+ ((ViewGroup)view.Parent).RemoveView(view);
+ }
+
+ public static void SetBackground(this AView view, Drawable drawable)
+ {
+ if (s_apiLevel == 0)
+ s_apiLevel = (int)Build.VERSION.SdkInt;
+
+ if (s_apiLevel < 16)
+ {
+#pragma warning disable 618
+ view.SetBackgroundDrawable(drawable);
+#pragma warning restore 618
+ }
+ else
+ view.Background = drawable;
+ }
+
+ public static void SetWindowBackground(this AView view)
+ {
+ Context context = view.Context;
+ using(var background = new TypedValue())
+ {
+ if (context.Theme.ResolveAttribute(global::Android.Resource.Attribute.WindowBackground, background, true))
+ {
+ string type = context.Resources.GetResourceTypeName(background.ResourceId).ToLower();
+ switch (type)
+ {
+ case "color":
+ global::Android.Graphics.Color color = context.Resources.GetColor(background.ResourceId);
+ view.SetBackgroundColor(color);
+ break;
+ case "drawable":
+ using(Drawable drawable = context.Resources.GetDrawable(background.ResourceId))
+ view.SetBackgroundDrawable(drawable);
+ break;
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/ViewInitializedEventArgs.cs b/Xamarin.Forms.Platform.Android/ViewInitializedEventArgs.cs
new file mode 100644
index 00000000..e6dc6a1d
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/ViewInitializedEventArgs.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ public class ViewInitializedEventArgs : EventArgs
+ {
+ public global::Android.Views.View NativeView { get; internal set; }
+
+ public VisualElement View { get; internal set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/ViewPool.cs b/Xamarin.Forms.Platform.Android/ViewPool.cs
new file mode 100644
index 00000000..b5c1ddc7
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/ViewPool.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using Android.Views;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class ViewPool : IDisposable
+ {
+ readonly Dictionary<Type, Stack<AView>> _freeViews = new Dictionary<Type, Stack<AView>>();
+ readonly ViewGroup _viewGroup;
+
+ bool _disposed;
+
+ public ViewPool(ViewGroup viewGroup)
+ {
+ _viewGroup = viewGroup;
+ }
+
+ public void Dispose()
+ {
+ if (_disposed)
+ return;
+
+ foreach (Stack<AView> views in _freeViews.Values)
+ {
+ foreach (AView view in views)
+ view.Dispose();
+ }
+
+ _disposed = true;
+ }
+
+ public void ClearChildren()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(null);
+
+ ClearChildren(_viewGroup);
+ }
+
+ public TView GetFreeView<TView>() where TView : AView
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(null);
+
+ Stack<AView> views;
+ if (_freeViews.TryGetValue(typeof(TView), out views) && views.Count > 0)
+ return (TView)views.Pop();
+
+ return null;
+ }
+
+ void ClearChildren(ViewGroup group)
+ {
+ if (group == null)
+ return;
+
+ int count = group.ChildCount;
+ for (var i = 0; i < count; i++)
+ {
+ AView child = group.GetChildAt(i);
+
+ var g = child as ViewGroup;
+ if (g != null)
+ ClearChildren(g);
+
+ Type childType = child.GetType();
+ Stack<AView> stack;
+ if (!_freeViews.TryGetValue(childType, out stack))
+ _freeViews[childType] = stack = new Stack<AView>();
+
+ stack.Push(child);
+ }
+
+ group.RemoveAllViews();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/ViewRenderer.cs b/Xamarin.Forms.Platform.Android/ViewRenderer.cs
new file mode 100644
index 00000000..f5c094ba
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/ViewRenderer.cs
@@ -0,0 +1,205 @@
+using System;
+using System.ComponentModel;
+using Android.App;
+using Android.Views;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public abstract class ViewRenderer : ViewRenderer<View, AView>
+ {
+ }
+
+ public abstract class ViewRenderer<TView, TNativeView> : VisualElementRenderer<TView>, AView.IOnFocusChangeListener where TView : View where TNativeView : AView
+ {
+ ViewGroup _container;
+
+ bool _disposed;
+ EventHandler<VisualElement.FocusRequestArgs> _focusChangeHandler;
+
+ SoftInput _startingInputMode;
+
+ internal bool HandleKeyboardOnFocus;
+
+ public TNativeView Control { get; private set; }
+
+ void IOnFocusChangeListener.OnFocusChange(AView v, bool hasFocus)
+ {
+ if (Element is Entry || Element is SearchBar || Element is Editor)
+ {
+ var isInViewCell = false;
+ Element parent = Element.RealParent;
+ while (!(parent is Page) && parent != null)
+ {
+ if (parent is Cell)
+ {
+ isInViewCell = true;
+ break;
+ }
+ parent = parent.RealParent;
+ }
+
+ if (isInViewCell)
+ {
+ Window window = ((Activity)Context).Window;
+ if (hasFocus)
+ {
+ _startingInputMode = window.Attributes.SoftInputMode;
+ window.SetSoftInputMode(SoftInput.AdjustPan);
+ }
+ else
+ window.SetSoftInputMode(_startingInputMode);
+ }
+ }
+ OnNativeFocusChanged(hasFocus);
+
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, hasFocus);
+ }
+
+ public override SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)
+ {
+ AView view = _container == this ? (AView)Control : _container;
+ view.Measure(widthConstraint, heightConstraint);
+
+ return new SizeRequest(new Size(Control.MeasuredWidth, Control.MeasuredHeight), MinimumSize());
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ if (Control != null)
+ {
+ Control.RemoveFromParent();
+ Control.Dispose();
+ Control = null;
+ }
+
+ if (_container != null && _container != this)
+ {
+ _container.RemoveFromParent();
+ _container.Dispose();
+ _container = null;
+ }
+
+ _disposed = true;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<TView> e)
+ {
+ base.OnElementChanged(e);
+
+ if (_focusChangeHandler == null)
+ _focusChangeHandler = OnFocusChangeRequested;
+
+ if (e.OldElement != null)
+ e.OldElement.FocusChangeRequested -= _focusChangeHandler;
+
+ if (e.NewElement != null)
+ e.NewElement.FocusChangeRequested += _focusChangeHandler;
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled();
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ base.OnLayout(changed, l, t, r, b);
+ if (Control == null)
+ return;
+
+ AView view = _container == this ? (AView)Control : _container;
+
+ view.Measure(MeasureSpecFactory.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly));
+ view.Layout(0, 0, r - l, b - t);
+ }
+
+ protected override void OnRegisterEffect(PlatformEffect effect)
+ {
+ base.OnRegisterEffect(effect);
+ effect.Control = Control;
+ }
+
+ protected override void SetAutomationId(string id)
+ {
+ if (Control == null)
+ base.SetAutomationId(id);
+ else
+ {
+ ContentDescription = id + "_Container";
+ Control.ContentDescription = id;
+ }
+ }
+
+ protected void SetNativeControl(TNativeView control)
+ {
+ SetNativeControl(control, this);
+ }
+
+ internal virtual void OnFocusChangeRequested(object sender, VisualElement.FocusRequestArgs e)
+ {
+ if (Control == null)
+ return;
+
+ if (e.Focus)
+ e.Result = Control.RequestFocus();
+ else
+ {
+ e.Result = true;
+ Control.ClearFocus();
+ }
+
+ //handles keyboard on focus for Editor, Entry and SearchBar
+ if (HandleKeyboardOnFocus)
+ {
+ if (e.Focus)
+ Control.ShowKeyboard();
+ else
+ Control.HideKeyboard();
+ }
+ }
+
+ internal virtual void OnNativeFocusChanged(bool hasFocus)
+ {
+ }
+
+ internal override void SendVisualElementInitialized(VisualElement element, AView nativeView)
+ {
+ base.SendVisualElementInitialized(element, Control);
+ }
+
+ internal void SetNativeControl(TNativeView control, ViewGroup container)
+ {
+ if (Control != null)
+ {
+ Control.OnFocusChangeListener = null;
+ RemoveView(Control);
+ }
+
+ _container = container;
+
+ Control = control;
+
+ AView toAdd = container == this ? control : (AView)container;
+ AddView(toAdd, LayoutParams.MatchParent);
+
+ Control.OnFocusChangeListener = this;
+
+ UpdateIsEnabled();
+ }
+
+ void UpdateIsEnabled()
+ {
+ if (Control != null)
+ Control.Enabled = Element.IsEnabled;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/VisualElementChangedEventArgs.cs b/Xamarin.Forms.Platform.Android/VisualElementChangedEventArgs.cs
new file mode 100644
index 00000000..de7c7e5d
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/VisualElementChangedEventArgs.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.Forms.Platform.Android
+{
+ public class VisualElementChangedEventArgs : ElementChangedEventArgs<VisualElement>
+ {
+ public VisualElementChangedEventArgs(VisualElement oldElement, VisualElement newElement) : base(oldElement, newElement)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/VisualElementExtensions.cs b/Xamarin.Forms.Platform.Android/VisualElementExtensions.cs
new file mode 100644
index 00000000..13f2fffa
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/VisualElementExtensions.cs
@@ -0,0 +1,42 @@
+namespace Xamarin.Forms.Platform.Android
+{
+ public static class VisualElementExtensions
+ {
+ public static bool ShouldBeMadeClickable(this View view)
+ {
+ var shouldBeClickable = false;
+ for (var i = 0; i < view.GestureRecognizers.Count; i++)
+ {
+ IGestureRecognizer gesture = view.GestureRecognizers[i];
+ if (gesture is TapGestureRecognizer || gesture is PinchGestureRecognizer || gesture is PanGestureRecognizer)
+ {
+ shouldBeClickable = true;
+ break;
+ }
+ }
+
+ // do some evil
+ // This is required so that a layout only absorbs click events if it is not fully transparent
+ // However this is not desirable behavior in a ViewCell because it prevents the ViewCell from activating
+ if (view is Layout && view.BackgroundColor != Color.Transparent && view.BackgroundColor != Color.Default)
+ {
+ Element parent = view.RealParent;
+ var skip = false;
+ while (parent != null)
+ {
+ if (parent is ViewCell)
+ {
+ skip = true;
+ break;
+ }
+ parent = parent.RealParent;
+ }
+
+ if (!skip)
+ shouldBeClickable = true;
+ }
+
+ return shouldBeClickable;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/VisualElementPackager.cs b/Xamarin.Forms.Platform.Android/VisualElementPackager.cs
new file mode 100644
index 00000000..e7e6ab6f
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/VisualElementPackager.cs
@@ -0,0 +1,217 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class VisualElementPackager : IDisposable
+ {
+ readonly EventHandler<ElementEventArgs> _childAddedHandler;
+ readonly EventHandler<ElementEventArgs> _childRemovedHandler;
+ readonly EventHandler _childReorderedHandler;
+ List<IVisualElementRenderer> _childViews;
+
+ bool _disposed;
+
+ IVisualElementRenderer _renderer;
+
+ public VisualElementPackager(IVisualElementRenderer renderer)
+ {
+ if (renderer == null)
+ throw new ArgumentNullException("renderer");
+
+ _childAddedHandler = OnChildAdded;
+ _childRemovedHandler = OnChildRemoved;
+ _childReorderedHandler = OnChildrenReordered;
+
+ _renderer = renderer;
+ _renderer.ElementChanged += (sender, args) => SetElement(args.OldElement, args.NewElement);
+ }
+
+ public void Dispose()
+ {
+ if (_disposed)
+ return;
+ _disposed = true;
+
+ if (_renderer != null)
+ {
+ if (_childViews != null)
+ {
+ _childViews.Clear();
+ _childViews = null;
+ }
+
+ _renderer.Element.ChildAdded -= _childAddedHandler;
+ _renderer.Element.ChildRemoved -= _childRemovedHandler;
+
+ _renderer.Element.ChildrenReordered -= _childReorderedHandler;
+ _renderer = null;
+ }
+ }
+
+ public void Load()
+ {
+ SetElement(null, _renderer.Element);
+ }
+
+ void AddChild(VisualElement view, IVisualElementRenderer oldRenderer = null, RendererPool pool = null, bool sameChildren = false)
+ {
+ Performance.Start();
+
+ if (_childViews == null)
+ _childViews = new List<IVisualElementRenderer>();
+
+ IVisualElementRenderer renderer = oldRenderer;
+ if (pool != null)
+ renderer = pool.GetFreeRenderer(view);
+ if (renderer == null)
+ {
+ Performance.Start("New renderer");
+ renderer = Platform.CreateRenderer(view);
+ Performance.Stop("New renderer");
+ }
+
+ if (renderer == oldRenderer)
+ {
+ Platform.SetRenderer(renderer.Element, null);
+ renderer.SetElement(view);
+ }
+
+ Performance.Start("Set renderer");
+ Platform.SetRenderer(view, renderer);
+ Performance.Stop("Set renderer");
+
+ Performance.Start("Add view");
+ if (!sameChildren)
+ {
+ _renderer.ViewGroup.AddView(renderer.ViewGroup);
+ _childViews.Add(renderer);
+ }
+ Performance.Stop("Add view");
+
+ Performance.Stop();
+ }
+
+ void EnsureChildOrder()
+ {
+ for (var i = 0; i < _renderer.Element.LogicalChildren.Count; i++)
+ {
+ Element child = _renderer.Element.LogicalChildren[i];
+ var element = (VisualElement)child;
+ if (element != null)
+ {
+ IVisualElementRenderer r = Platform.GetRenderer(element);
+ _renderer.ViewGroup.BringChildToFront(r.ViewGroup);
+ }
+ }
+ }
+
+ void OnChildAdded(object sender, ElementEventArgs e)
+ {
+ var view = e.Element as VisualElement;
+ if (view != null)
+ AddChild(view);
+ if (_renderer.Element.LogicalChildren[_renderer.Element.LogicalChildren.Count - 1] != view)
+ EnsureChildOrder();
+ }
+
+ void OnChildRemoved(object sender, ElementEventArgs e)
+ {
+ Performance.Start();
+ var view = e.Element as VisualElement;
+ if (view != null)
+ RemoveChild(view);
+
+ Performance.Stop();
+ }
+
+ void OnChildrenReordered(object sender, EventArgs e)
+ {
+ EnsureChildOrder();
+ }
+
+ void RemoveChild(VisualElement view)
+ {
+ IVisualElementRenderer renderer = Platform.GetRenderer(view);
+ _childViews.Remove(renderer);
+ renderer.ViewGroup.RemoveFromParent();
+ renderer.Dispose();
+ }
+
+ void SetElement(VisualElement oldElement, VisualElement newElement)
+ {
+ Performance.Start();
+
+ var sameChildrenTypes = false;
+
+ ReadOnlyCollection<Element> newChildren = null, oldChildren = null;
+
+ RendererPool pool = null;
+ if (oldElement != null)
+ {
+ if (newElement != null)
+ {
+ sameChildrenTypes = true;
+
+ oldChildren = oldElement.LogicalChildren;
+ newChildren = newElement.LogicalChildren;
+ if (oldChildren.Count == newChildren.Count)
+ {
+ for (var i = 0; i < oldChildren.Count; i++)
+ {
+ if (oldChildren[i].GetType() != newChildren[i].GetType())
+ {
+ sameChildrenTypes = false;
+ break;
+ }
+ }
+ }
+ else
+ sameChildrenTypes = false;
+ }
+
+ oldElement.ChildAdded -= _childAddedHandler;
+ oldElement.ChildRemoved -= _childRemovedHandler;
+
+ oldElement.ChildrenReordered -= _childReorderedHandler;
+
+ if (!sameChildrenTypes)
+ {
+ _childViews = new List<IVisualElementRenderer>();
+ pool = new RendererPool(_renderer, oldElement);
+ pool.ClearChildrenRenderers();
+ }
+ }
+
+ if (newElement != null)
+ {
+ Performance.Start("Setup");
+ newElement.ChildAdded += _childAddedHandler;
+ newElement.ChildRemoved += _childRemovedHandler;
+
+ newElement.ChildrenReordered += _childReorderedHandler;
+
+ newChildren = newChildren ?? newElement.LogicalChildren;
+
+ for (var i = 0; i < newChildren.Count; i++)
+ {
+ IVisualElementRenderer oldRenderer = null;
+ if (oldChildren != null && sameChildrenTypes)
+ oldRenderer = _childViews[i];
+
+ AddChild((VisualElement)newChildren[i], oldRenderer, pool, sameChildrenTypes);
+ }
+
+#if DEBUG
+ //if (renderer.Element.LogicalChildren.Any() && renderer.ViewGroup.ChildCount != renderer.Element.LogicalChildren.Count)
+ // throw new InvalidOperationException ("SetElement did not create the correct number of children");
+#endif
+ Performance.Stop("Setup");
+ }
+
+ Performance.Stop();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/VisualElementRenderer.cs b/Xamarin.Forms.Platform.Android/VisualElementRenderer.cs
new file mode 100644
index 00000000..41c97b18
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/VisualElementRenderer.cs
@@ -0,0 +1,392 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using Android.Support.V4.View;
+using Android.Views;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public abstract class VisualElementRenderer<TElement> : FormsViewGroup, IVisualElementRenderer, AView.IOnTouchListener, AView.IOnClickListener, IEffectControlProvider where TElement : VisualElement
+ {
+ readonly List<EventHandler<VisualElementChangedEventArgs>> _elementChangedHandlers = new List<EventHandler<VisualElementChangedEventArgs>>();
+
+ readonly Lazy<GestureDetector> _gestureDetector;
+ readonly PanGestureHandler _panGestureHandler;
+ readonly PinchGestureHandler _pinchGestureHandler;
+
+ readonly TapGestureHandler _tapGestureHandler;
+
+ bool _clickable;
+ NotifyCollectionChangedEventHandler _collectionChangeHandler;
+
+ VisualElementRendererFlags _flags = VisualElementRendererFlags.AutoPackage | VisualElementRendererFlags.AutoTrack;
+
+ InnerGestureListener _gestureListener;
+ VisualElementPackager _packager;
+ PropertyChangedEventHandler _propertyChangeHandler;
+ Lazy<ScaleGestureDetector> _scaleDetector;
+ VelocityTracker _velocity;
+
+ protected VisualElementRenderer() : base(Forms.Context)
+ {
+ _tapGestureHandler = new TapGestureHandler(() => View);
+ _panGestureHandler = new PanGestureHandler(() => View, Context.FromPixels);
+ _pinchGestureHandler = new PinchGestureHandler(() => View);
+
+ _gestureDetector =
+ new Lazy<GestureDetector>(
+ () =>
+ new GestureDetector(
+ _gestureListener =
+ new InnerGestureListener(_tapGestureHandler.OnTap, _tapGestureHandler.TapGestureRecognizers, _panGestureHandler.OnPan, _panGestureHandler.OnPanStarted, _panGestureHandler.OnPanComplete)));
+
+ _scaleDetector =
+ new Lazy<ScaleGestureDetector>(
+ () => new ScaleGestureDetector(Context, new InnerScaleListener(_pinchGestureHandler.OnPinch, _pinchGestureHandler.OnPinchStarted, _pinchGestureHandler.OnPinchEnded), Handler));
+ }
+
+ public TElement Element { get; private set; }
+
+ protected bool AutoPackage
+ {
+ get { return (_flags & VisualElementRendererFlags.AutoPackage) != 0; }
+ set
+ {
+ if (value)
+ _flags |= VisualElementRendererFlags.AutoPackage;
+ else
+ _flags &= ~VisualElementRendererFlags.AutoPackage;
+ }
+ }
+
+ protected bool AutoTrack
+ {
+ get { return (_flags & VisualElementRendererFlags.AutoTrack) != 0; }
+ set
+ {
+ if (value)
+ _flags |= VisualElementRendererFlags.AutoTrack;
+ else
+ _flags &= ~VisualElementRendererFlags.AutoTrack;
+ }
+ }
+
+ View View
+ {
+ get { return Element as View; }
+ }
+
+ void IEffectControlProvider.RegisterEffect(Effect effect)
+ {
+ var platformEffect = effect as PlatformEffect;
+ if (platformEffect != null)
+ OnRegisterEffect(platformEffect);
+ }
+
+ void IOnClickListener.OnClick(AView v)
+ {
+ _tapGestureHandler.OnSingleClick();
+ }
+
+ bool IOnTouchListener.OnTouch(AView v, MotionEvent e)
+ {
+ var handled = false;
+ if (_pinchGestureHandler.IsPinchSupported)
+ {
+ if (!_scaleDetector.IsValueCreated)
+ ScaleGestureDetectorCompat.SetQuickScaleEnabled(_scaleDetector.Value, true);
+ handled = _scaleDetector.Value.OnTouchEvent(e);
+ }
+ return _gestureDetector.Value.OnTouchEvent(e) || handled;
+ }
+
+ VisualElement IVisualElementRenderer.Element
+ {
+ get { return Element; }
+ }
+
+ event EventHandler<VisualElementChangedEventArgs> IVisualElementRenderer.ElementChanged
+ {
+ add { _elementChangedHandlers.Add(value); }
+ remove { _elementChangedHandlers.Remove(value); }
+ }
+
+ public virtual SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)
+ {
+ Measure(widthConstraint, heightConstraint);
+ return new SizeRequest(new Size(MeasuredWidth, MeasuredHeight), MinimumSize());
+ }
+
+ void IVisualElementRenderer.SetElement(VisualElement element)
+ {
+ if (!(element is TElement))
+ throw new ArgumentException("element is not of type " + typeof(TElement), "element");
+
+ SetElement((TElement)element);
+ }
+
+ public VisualElementTracker Tracker { get; private set; }
+
+ public void UpdateLayout()
+ {
+ Performance.Start();
+ if (Tracker != null)
+ Tracker.UpdateLayout();
+
+ Performance.Stop();
+ }
+
+ public ViewGroup ViewGroup
+ {
+ get { return this; }
+ }
+
+ public event EventHandler<ElementChangedEventArgs<TElement>> ElementChanged;
+
+ public void SetElement(TElement element)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ TElement oldElement = Element;
+ Element = element;
+
+ Performance.Start();
+
+ if (oldElement != null)
+ {
+ oldElement.PropertyChanged -= _propertyChangeHandler;
+ UnsubscribeGestureRecognizers(oldElement);
+ }
+
+ // element may be allowed to be passed as null in the future
+ if (element != null)
+ {
+ Color currentColor = oldElement != null ? oldElement.BackgroundColor : Color.Default;
+ if (element.BackgroundColor != currentColor)
+ UpdateBackgroundColor();
+ }
+
+ if (_propertyChangeHandler == null)
+ _propertyChangeHandler = OnElementPropertyChanged;
+
+ element.PropertyChanged += _propertyChangeHandler;
+ SubscribeGestureRecognizers(element);
+
+ if (oldElement == null)
+ {
+ SetOnClickListener(this);
+ SetOnTouchListener(this);
+ SoundEffectsEnabled = false;
+ }
+
+ InputTransparent = Element.InputTransparent;
+
+ // must be updated AFTER SetOnClickListener is called
+ // SetOnClickListener implicitly calls Clickable = true
+ UpdateGestureRecognizers(true);
+
+ OnElementChanged(new ElementChangedEventArgs<TElement>(oldElement, element));
+
+ if (AutoPackage && _packager == null)
+ SetPackager(new VisualElementPackager(this));
+
+ if (AutoTrack && Tracker == null)
+ SetTracker(new VisualElementTracker(this));
+
+ if (element != null)
+ SendVisualElementInitialized(element, this);
+
+ var controller = (IElementController)oldElement;
+ if (controller != null && controller.EffectControlProvider == this)
+ controller.EffectControlProvider = null;
+
+ controller = element;
+ if (controller != null)
+ controller.EffectControlProvider = this;
+
+ if (element != null && !string.IsNullOrEmpty(element.AutomationId))
+ SetAutomationId(element.AutomationId);
+
+ Performance.Stop();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if ((_flags & VisualElementRendererFlags.Disposed) != 0)
+ return;
+ _flags |= VisualElementRendererFlags.Disposed;
+
+ if (disposing)
+ {
+ if (Tracker != null)
+ {
+ Tracker.Dispose();
+ Tracker = null;
+ }
+
+ if (_packager != null)
+ {
+ _packager.Dispose();
+ _packager = null;
+ }
+
+ if (_scaleDetector != null && _scaleDetector.IsValueCreated)
+ {
+ _scaleDetector.Value.Dispose();
+ _scaleDetector = null;
+ }
+
+ if (_gestureListener != null)
+ {
+ _gestureListener.Dispose();
+ _gestureListener = null;
+ }
+
+ int count = ChildCount;
+ for (var i = 0; i < count; i++)
+ {
+ AView child = GetChildAt(i);
+ child.Dispose();
+ }
+
+ RemoveAllViews();
+
+ if (Element != null)
+ {
+ Element.PropertyChanged -= _propertyChangeHandler;
+ UnsubscribeGestureRecognizers(Element);
+
+ if (Platform.GetRenderer(Element) == this)
+ Platform.SetRenderer(Element, null);
+
+ Element = null;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected virtual Size MinimumSize()
+ {
+ return new Size();
+ }
+
+ protected virtual void OnElementChanged(ElementChangedEventArgs<TElement> e)
+ {
+ var args = new VisualElementChangedEventArgs(e.OldElement, e.NewElement);
+ for (var i = 0; i < _elementChangedHandlers.Count; i++)
+ _elementChangedHandlers[i](this, args);
+
+ EventHandler<ElementChangedEventArgs<TElement>> changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackgroundColor();
+ else if (e.PropertyName == VisualElement.InputTransparentProperty.PropertyName)
+ InputTransparent = Element.InputTransparent;
+ }
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ if (Element == null)
+ return;
+
+ ReadOnlyCollection<Element> children = Element.LogicalChildren;
+ for (var i = 0; i < children.Count; i++)
+ {
+ var visualElement = children[i] as VisualElement;
+ if (visualElement == null)
+ continue;
+
+ IVisualElementRenderer renderer = Platform.GetRenderer(visualElement);
+ renderer?.UpdateLayout();
+ }
+ }
+
+ protected virtual void OnRegisterEffect(PlatformEffect effect)
+ {
+ effect.Container = this;
+ }
+
+ protected virtual void SetAutomationId(string id)
+ {
+ ContentDescription = id;
+ }
+
+ protected void SetPackager(VisualElementPackager packager)
+ {
+ _packager = packager;
+ packager.Load();
+ }
+
+ protected void SetTracker(VisualElementTracker tracker)
+ {
+ Tracker = tracker;
+ }
+
+ protected virtual void UpdateBackgroundColor()
+ {
+ SetBackgroundColor(Element.BackgroundColor.ToAndroid());
+ }
+
+ internal virtual void SendVisualElementInitialized(VisualElement element, AView nativeView)
+ {
+ element.SendViewInitialized(nativeView);
+ }
+
+ void HandleGestureRecognizerCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
+ {
+ UpdateGestureRecognizers();
+ }
+
+ void SubscribeGestureRecognizers(VisualElement element)
+ {
+ var view = element as View;
+ if (view == null)
+ return;
+
+ if (_collectionChangeHandler == null)
+ _collectionChangeHandler = HandleGestureRecognizerCollectionChanged;
+
+ var observableCollection = (ObservableCollection<IGestureRecognizer>)view.GestureRecognizers;
+ observableCollection.CollectionChanged += _collectionChangeHandler;
+ }
+
+ void UnsubscribeGestureRecognizers(VisualElement element)
+ {
+ var view = element as View;
+ if (view == null || _collectionChangeHandler == null)
+ return;
+
+ var observableCollection = (ObservableCollection<IGestureRecognizer>)view.GestureRecognizers;
+ observableCollection.CollectionChanged -= _collectionChangeHandler;
+ }
+
+ void UpdateClickable(bool force = false)
+ {
+ var view = Element as View;
+ if (view == null)
+ return;
+
+ bool newValue = view.ShouldBeMadeClickable();
+ if (force || _clickable != newValue)
+ Clickable = newValue;
+ }
+
+ void UpdateGestureRecognizers(bool forceClick = false)
+ {
+ if (View == null)
+ return;
+
+ UpdateClickable(forceClick);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/VisualElementRendererFlags.cs b/Xamarin.Forms.Platform.Android/VisualElementRendererFlags.cs
new file mode 100644
index 00000000..cfabfe77
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/VisualElementRendererFlags.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ [Flags]
+ public enum VisualElementRendererFlags
+ {
+ Disposed = 1 << 0,
+ AutoTrack = 1 << 1,
+ AutoPackage = 1 << 2
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/VisualElementTracker.cs b/Xamarin.Forms.Platform.Android/VisualElementTracker.cs
new file mode 100644
index 00000000..2b9815d3
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/VisualElementTracker.cs
@@ -0,0 +1,396 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using Android.Content;
+using Android.OS;
+using Android.Views;
+using AView = Android.Views.View;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ public class VisualElementTracker : IDisposable
+ {
+ readonly EventHandler<EventArg<VisualElement>> _batchCommittedHandler;
+ readonly IList<string> _batchedProperties = new List<string>();
+ readonly PropertyChangedEventHandler _propertyChangedHandler;
+ Context _context;
+
+ bool _disposed;
+
+ VisualElement _element;
+ bool _initialUpdateNeeded = true;
+ bool _layoutNeeded;
+ IVisualElementRenderer _renderer;
+
+ public VisualElementTracker(IVisualElementRenderer renderer)
+ {
+ if (renderer == null)
+ throw new ArgumentNullException("renderer");
+
+ _batchCommittedHandler = HandleRedrawNeeded;
+ _propertyChangedHandler = HandlePropertyChanged;
+
+ _renderer = renderer;
+ _context = renderer.ViewGroup.Context;
+ _renderer.ElementChanged += RendererOnElementChanged;
+
+ VisualElement view = renderer.Element;
+ SetElement(null, view);
+
+ renderer.ViewGroup.SetCameraDistance(3600);
+
+ renderer.ViewGroup.AddOnAttachStateChangeListener(AttachTracker.Instance);
+ }
+
+ public void Dispose()
+ {
+ if (_disposed)
+ return;
+ _disposed = true;
+
+ SetElement(_element, null);
+
+ if (_renderer != null)
+ {
+ _renderer.ElementChanged -= RendererOnElementChanged;
+ _renderer.ViewGroup.RemoveOnAttachStateChangeListener(AttachTracker.Instance);
+ _renderer = null;
+ _context = null;
+ }
+ }
+
+ public void UpdateLayout()
+ {
+ Performance.Start();
+
+ VisualElement view = _renderer.Element;
+ AView aview = _renderer.ViewGroup;
+
+ var x = (int)_context.ToPixels(view.X);
+ var y = (int)_context.ToPixels(view.Y);
+ var width = (int)_context.ToPixels(view.Width);
+ var height = (int)_context.ToPixels(view.Height);
+
+ var formsViewGroup = aview as FormsViewGroup;
+ if (formsViewGroup == null)
+ {
+ Performance.Start("Measure");
+ aview.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.Exactly));
+ Performance.Stop("Measure");
+
+ Performance.Start("Layout");
+ aview.Layout(x, y, x + width, y + height);
+ Performance.Stop("Layout");
+ }
+ else
+ {
+ Performance.Start("MeasureAndLayout");
+ formsViewGroup.MeasureAndLayout(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.Exactly), x, y, x + width, y + height);
+ Performance.Stop("MeasureAndLayout");
+ }
+
+ Performance.Stop();
+
+ //On Width or Height changes, the anchors needs to be updated
+ UpdateAnchorX();
+ UpdateAnchorY();
+ }
+
+ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Layout.IsClippedToBoundsProperty.PropertyName)
+ {
+ UpdateClipToBounds();
+ return;
+ }
+
+ if (_renderer.Element.Batched)
+ {
+ if (e.PropertyName == VisualElement.XProperty.PropertyName || e.PropertyName == VisualElement.YProperty.PropertyName || e.PropertyName == VisualElement.WidthProperty.PropertyName ||
+ e.PropertyName == VisualElement.HeightProperty.PropertyName)
+ _layoutNeeded = true;
+ else if (e.PropertyName == VisualElement.AnchorXProperty.PropertyName || e.PropertyName == VisualElement.AnchorYProperty.PropertyName || e.PropertyName == VisualElement.ScaleProperty.PropertyName ||
+ e.PropertyName == VisualElement.RotationProperty.PropertyName || e.PropertyName == VisualElement.RotationXProperty.PropertyName || e.PropertyName == VisualElement.RotationYProperty.PropertyName ||
+ e.PropertyName == VisualElement.IsVisibleProperty.PropertyName || e.PropertyName == VisualElement.OpacityProperty.PropertyName ||
+ e.PropertyName == VisualElement.TranslationXProperty.PropertyName || e.PropertyName == VisualElement.TranslationYProperty.PropertyName)
+ {
+ if (!_batchedProperties.Contains(e.PropertyName))
+ _batchedProperties.Add(e.PropertyName);
+ }
+ return;
+ }
+
+ if (e.PropertyName == VisualElement.XProperty.PropertyName || e.PropertyName == VisualElement.YProperty.PropertyName || e.PropertyName == VisualElement.WidthProperty.PropertyName ||
+ e.PropertyName == VisualElement.HeightProperty.PropertyName)
+ MaybeRequestLayout();
+ else if (e.PropertyName == VisualElement.AnchorXProperty.PropertyName)
+ UpdateAnchorX();
+ else if (e.PropertyName == VisualElement.AnchorYProperty.PropertyName)
+ UpdateAnchorY();
+ else if (e.PropertyName == VisualElement.ScaleProperty.PropertyName)
+ UpdateScale();
+ else if (e.PropertyName == VisualElement.RotationProperty.PropertyName)
+ UpdateRotation();
+ else if (e.PropertyName == VisualElement.RotationXProperty.PropertyName)
+ UpdateRotationX();
+ else if (e.PropertyName == VisualElement.RotationYProperty.PropertyName)
+ UpdateRotationY();
+ else if (e.PropertyName == VisualElement.IsVisibleProperty.PropertyName)
+ UpdateIsVisible();
+ else if (e.PropertyName == VisualElement.OpacityProperty.PropertyName)
+ UpdateOpacity();
+ else if (e.PropertyName == VisualElement.TranslationXProperty.PropertyName)
+ UpdateTranslationX();
+ else if (e.PropertyName == VisualElement.TranslationYProperty.PropertyName)
+ UpdateTranslationY();
+ }
+
+ void HandleRedrawNeeded(object sender, EventArg<VisualElement> e)
+ {
+ foreach (string propertyName in _batchedProperties)
+ HandlePropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+ _batchedProperties.Clear();
+
+ if (_layoutNeeded)
+ MaybeRequestLayout();
+ _layoutNeeded = false;
+ }
+
+ void HandleViewAttachedToWindow()
+ {
+ if (_initialUpdateNeeded)
+ {
+ UpdateNativeView(this, EventArgs.Empty);
+ _initialUpdateNeeded = false;
+ }
+
+ UpdateClipToBounds();
+ }
+
+ void MaybeRequestLayout()
+ {
+ var isInLayout = false;
+ if ((int)Build.VERSION.SdkInt >= 18)
+ isInLayout = _renderer.ViewGroup.IsInLayout;
+
+ if (!isInLayout && !_renderer.ViewGroup.IsLayoutRequested)
+ _renderer.ViewGroup.RequestLayout();
+ }
+
+ void RendererOnElementChanged(object sender, VisualElementChangedEventArgs args)
+ {
+ SetElement(args.OldElement, args.NewElement);
+ }
+
+ void SetElement(VisualElement oldElement, VisualElement newElement)
+ {
+ if (oldElement != null)
+ {
+ oldElement.BatchCommitted -= _batchCommittedHandler;
+ oldElement.PropertyChanged -= _propertyChangedHandler;
+ _context = null;
+ }
+
+ _element = newElement;
+ if (newElement != null)
+ {
+ newElement.BatchCommitted += _batchCommittedHandler;
+ newElement.PropertyChanged += _propertyChangedHandler;
+ _context = _renderer.ViewGroup.Context;
+
+ if (oldElement != null)
+ {
+ AView view = _renderer.ViewGroup;
+
+ // ReSharper disable CompareOfFloatsByEqualityOperator
+ if (oldElement.AnchorX != newElement.AnchorX)
+ UpdateAnchorX();
+ if (oldElement.AnchorY != newElement.AnchorY)
+ UpdateAnchorY();
+ if (oldElement.IsVisible != newElement.IsVisible)
+ UpdateIsVisible();
+ if (oldElement.IsEnabled != newElement.IsEnabled)
+ view.Enabled = newElement.IsEnabled;
+ if (oldElement.Opacity != newElement.Opacity)
+ UpdateOpacity();
+ if (oldElement.Rotation != newElement.Rotation)
+ UpdateRotation();
+ if (oldElement.RotationX != newElement.RotationX)
+ UpdateRotationX();
+ if (oldElement.RotationY != newElement.RotationY)
+ UpdateRotationY();
+ if (oldElement.Scale != newElement.Scale)
+ UpdateScale();
+ // ReSharper restore CompareOfFloatsByEqualityOperator
+
+ _initialUpdateNeeded = false;
+ }
+ }
+ }
+
+ void UpdateAnchorX()
+ {
+ VisualElement view = _renderer.Element;
+ AView aview = _renderer.ViewGroup;
+
+ float currentPivot = aview.PivotX;
+ var target = (float)(view.AnchorX * _context.ToPixels(view.Width));
+ if (currentPivot != target)
+ aview.PivotX = target;
+ }
+
+ void UpdateAnchorY()
+ {
+ VisualElement view = _renderer.Element;
+ AView aview = _renderer.ViewGroup;
+
+ float currentPivot = aview.PivotY;
+ var target = (float)(view.AnchorY * _context.ToPixels(view.Height));
+ if (currentPivot != target)
+ aview.PivotY = target;
+ }
+
+ void UpdateClipToBounds()
+ {
+ var layout = _renderer.Element as Layout;
+ var parent = _renderer.ViewGroup.Parent as ViewGroup;
+
+ if (parent == null || layout == null)
+ return;
+
+ bool shouldClip = layout.IsClippedToBounds;
+
+ if ((int)Build.VERSION.SdkInt >= 18 && parent.ClipChildren == shouldClip)
+ return;
+
+ parent.SetClipChildren(shouldClip);
+ parent.Invalidate();
+ }
+
+ void UpdateIsVisible()
+ {
+ VisualElement view = _renderer.Element;
+ AView aview = _renderer.ViewGroup;
+
+ if (view.IsVisible && aview.Visibility != ViewStates.Visible)
+ aview.Visibility = ViewStates.Visible;
+ if (!view.IsVisible && aview.Visibility != ViewStates.Gone)
+ aview.Visibility = ViewStates.Gone;
+ }
+
+ void UpdateNativeView(object sender, EventArgs e)
+ {
+ Performance.Start();
+
+ VisualElement view = _renderer.Element;
+ AView aview = _renderer.ViewGroup;
+
+ if (aview is FormsViewGroup)
+ {
+ var formsViewGroup = (FormsViewGroup)aview;
+ formsViewGroup.SendBatchUpdate((float)(view.AnchorX * _context.ToPixels(view.Width)), (float)(view.AnchorY * _context.ToPixels(view.Height)),
+ (int)(view.IsVisible ? ViewStates.Visible : ViewStates.Invisible), view.IsEnabled, (float)view.Opacity, (float)view.Rotation, (float)view.RotationX, (float)view.RotationY, (float)view.Scale,
+ _context.ToPixels(view.TranslationX), _context.ToPixels(view.TranslationY));
+ }
+ else
+ {
+ UpdateAnchorX();
+ UpdateAnchorY();
+ UpdateIsVisible();
+
+ if (view.IsEnabled != aview.Enabled)
+ aview.Enabled = view.IsEnabled;
+
+ UpdateOpacity();
+ UpdateRotation();
+ UpdateRotationX();
+ UpdateRotationY();
+ UpdateScale();
+ UpdateTranslationX();
+ UpdateTranslationY();
+ }
+
+ Performance.Stop();
+ }
+
+ void UpdateOpacity()
+ {
+ Performance.Start();
+
+ VisualElement view = _renderer.Element;
+ AView aview = _renderer.ViewGroup;
+
+ aview.Alpha = (float)view.Opacity;
+
+ Performance.Stop();
+ }
+
+ void UpdateRotation()
+ {
+ VisualElement view = _renderer.Element;
+ AView aview = _renderer.ViewGroup;
+
+ aview.Rotation = (float)view.Rotation;
+ }
+
+ void UpdateRotationX()
+ {
+ VisualElement view = _renderer.Element;
+ AView aview = _renderer.ViewGroup;
+
+ aview.RotationX = (float)view.RotationX;
+ }
+
+ void UpdateRotationY()
+ {
+ VisualElement view = _renderer.Element;
+ AView aview = _renderer.ViewGroup;
+
+ aview.RotationY = (float)view.RotationY;
+ }
+
+ void UpdateScale()
+ {
+ VisualElement view = _renderer.Element;
+ AView aview = _renderer.ViewGroup;
+
+ aview.ScaleX = (float)view.Scale;
+ aview.ScaleY = (float)view.Scale;
+ }
+
+ void UpdateTranslationX()
+ {
+ VisualElement view = _renderer.Element;
+ AView aview = _renderer.ViewGroup;
+
+ aview.TranslationX = _context.ToPixels(view.TranslationX);
+ }
+
+ void UpdateTranslationY()
+ {
+ VisualElement view = _renderer.Element;
+ AView aview = _renderer.ViewGroup;
+
+ aview.TranslationY = _context.ToPixels(view.TranslationY);
+ }
+
+ class AttachTracker : Object, AView.IOnAttachStateChangeListener
+ {
+ public static readonly AttachTracker Instance = new AttachTracker();
+
+ public void OnViewAttachedToWindow(AView attachedView)
+ {
+ var renderer = attachedView as IVisualElementRenderer;
+ if (renderer == null || renderer.Tracker == null)
+ return;
+
+ renderer.Tracker.HandleViewAttachedToWindow();
+ }
+
+ public void OnViewDetachedFromWindow(AView detachedView)
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj b/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj
new file mode 100644
index 00000000..05fee22d
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj
@@ -0,0 +1,259 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}</ProjectGuid>
+ <ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Platform.Android</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Platform.Android</AssemblyName>
+ <FileAlignment>512</FileAlignment>
+ <AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+ <TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
+ <AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Mono.Android" />
+ <Reference Include="mscorlib" />
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Runtime.Serialization" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="Xamarin.Android.Support.v7.CardView">
+ <HintPath>..\packages\Xamarin.Android.Support.v7.CardView.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.v7.CardView.dll</HintPath>
+ </Reference>
+ <Reference Include="Xamarin.Android.Support.v4">
+ <HintPath>..\packages\Xamarin.Android.Support.v4.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll</HintPath>
+ </Reference>
+ <Reference Include="Xamarin.Android.Support.v7.AppCompat">
+ <HintPath>..\packages\Xamarin.Android.Support.v7.AppCompat.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.v7.AppCompat.dll</HintPath>
+ </Reference>
+ <Reference Include="Xamarin.Android.Support.Design">
+ <HintPath>..\packages\Xamarin.Android.Support.Design.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.Design.dll</HintPath>
+ </Reference>
+ <Reference Include="Xamarin.GooglePlayServices.AppIndexing, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.GooglePlayServices.AppIndexing.29.0.0.1\lib\MonoAndroid41\Xamarin.GooglePlayServices.AppIndexing.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.GooglePlayServices.Base, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.GooglePlayServices.Base.29.0.0.1\lib\MonoAndroid41\Xamarin.GooglePlayServices.Base.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.GooglePlayServices.Basement, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.GooglePlayServices.Basement.29.0.0.1\lib\MonoAndroid41\Xamarin.GooglePlayServices.Basement.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Xamarin.Android.Support.v7.RecyclerView, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.Android.Support.v7.RecyclerView.23.1.1.1\lib\MonoAndroid403\Xamarin.Android.Support.v7.RecyclerView.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="AndroidApplicationLifecycleState.cs" />
+ <Compile Include="AndroidTitleBarVisibility.cs" />
+ <Compile Include="AppCompat\FormsViewPager.cs" />
+ <Compile Include="AppCompat\FragmentContainer.cs" />
+ <Compile Include="AppCompat\FrameRenderer.cs" />
+ <Compile Include="AppCompat\IManageFragments.cs" />
+ <Compile Include="AppCompat\Platform.cs" />
+ <Compile Include="AppCompat\Resource.cs" />
+ <Compile Include="CellAdapter.cs" />
+ <Compile Include="Cells\EntryCellEditText.cs" />
+ <Compile Include="Cells\EntryCellView.cs" />
+ <Compile Include="Cells\ImageCellRenderer.cs" />
+ <Compile Include="Cells\SwitchCellView.cs" />
+ <Compile Include="Deserializer.cs" />
+ <Compile Include="AppCompat\FormsAppCompatActivity.cs" />
+ <Compile Include="ElementChangedEventArgs.cs" />
+ <Compile Include="ExportCellAttribute.cs" />
+ <Compile Include="ExportImageSourceHandlerAttribute.cs" />
+ <Compile Include="ExportRendererAttribute.cs" />
+ <Compile Include="FormsApplicationActivity.cs" />
+ <Compile Include="AndroidActivity.cs" />
+ <Compile Include="AndroidTicker.cs" />
+ <Compile Include="Cells\BaseCellView.cs" />
+ <Compile Include="Cells\CellFactory.cs" />
+ <Compile Include="Cells\CellRenderer.cs" />
+ <Compile Include="Cells\EntryCellRenderer.cs" />
+ <Compile Include="Cells\SwitchCellRenderer.cs" />
+ <Compile Include="Cells\TextCellRenderer.cs" />
+ <Compile Include="Cells\ViewCellRenderer.cs" />
+ <Compile Include="ColorExtensions.cs" />
+ <Compile Include="ContextExtensions.cs" />
+ <Compile Include="GetDesiredSizeDelegate.cs" />
+ <Compile Include="IDeviceInfoProvider.cs" />
+ <Compile Include="InnerGestureListener.cs" />
+ <Compile Include="InnerScaleListener.cs" />
+ <Compile Include="IPlatformLayout.cs" />
+ <Compile Include="AppCompat\ButtonRenderer.cs" />
+ <Compile Include="AppCompat\MasterDetailPageRenderer.cs" />
+ <Compile Include="AppCompat\NavigationPageRenderer.cs" />
+ <Compile Include="AppCompat\SwitchRenderer.cs" />
+ <Compile Include="AppCompat\TabbedPageRenderer.cs" />
+ <Compile Include="MeasureSpecFactory.cs" />
+ <Compile Include="NativeViewWrapper.cs" />
+ <Compile Include="NativeViewWrapperRenderer.cs" />
+ <Compile Include="OnLayoutDelegate.cs" />
+ <Compile Include="OnMeasureDelegate.cs" />
+ <Compile Include="PanGestureHandler.cs" />
+ <Compile Include="PinchGestureHandler.cs" />
+ <Compile Include="PlatformEffect.cs" />
+ <Compile Include="LayoutExtensions.cs" />
+ <Compile Include="Renderers\AHorizontalScrollView.cs" />
+ <Compile Include="Renderers\ButtonDrawable.cs" />
+ <Compile Include="Renderers\CarouselViewExtensions.cs" />
+ <Compile Include="Renderers\CarouselViewRenderer.cs" />
+ <Compile Include="Renderers\AlignmentExtensions.cs" />
+ <Compile Include="IStartActivityForResult.cs" />
+ <Compile Include="Renderers\ConditionalFocusLayout.cs" />
+ <Compile Include="Renderers\DescendantFocusToggler.cs" />
+ <Compile Include="Renderers\EditorEditText.cs" />
+ <Compile Include="Renderers\EntryEditText.cs" />
+ <Compile Include="Renderers\FileImageSourceHandler.cs" />
+ <Compile Include="Renderers\FormattedStringExtensions.cs" />
+ <Compile Include="Renderers\FormsImageView.cs" />
+ <Compile Include="Renderers\FormsTextView.cs" />
+ <Compile Include="Renderers\FormsWebChromeClient.cs" />
+ <Compile Include="Renderers\GenericAnimatorListener.cs" />
+ <Compile Include="Renderers\IDescendantFocusToggler.cs" />
+ <Compile Include="Renderers\IImageSourceHandler.cs" />
+ <Compile Include="Renderers\ImageExtensions.cs" />
+ <Compile Include="Renderers\ImageLoaderSourceHandler.cs" />
+ <Compile Include="Renderers\IntVector.cs" />
+ <Compile Include="Renderers\ItemViewAdapter.cs" />
+ <Compile Include="Renderers\IToolbarButton.cs" />
+ <Compile Include="Renderers\KeyboardExtensions.cs" />
+ <Compile Include="AppCompat\PickerRenderer.cs" />
+ <Compile Include="AppCompat\ViewRenderer.cs" />
+ <Compile Include="Renderers\MasterDetailContainer.cs" />
+ <Compile Include="Renderers\MeasureSpecification.cs" />
+ <Compile Include="Renderers\MeasureSpecificationType.cs" />
+ <Compile Include="Renderers\PageContainer.cs" />
+ <Compile Include="Renderers\PhysicalLayoutManager.cs" />
+ <Compile Include="Renderers\ScrollViewContainer.cs" />
+ <Compile Include="Renderers\StreamImagesourceHandler.cs" />
+ <Compile Include="Renderers\ToolbarButton.cs" />
+ <Compile Include="Renderers\ToolbarImageButton.cs" />
+ <Compile Include="Renderers\ViewGroupExtensions.cs" />
+ <Compile Include="TapGestureHandler.cs" />
+ <Compile Include="ViewInitializedEventArgs.cs" />
+ <Compile Include="VisualElementChangedEventArgs.cs" />
+ <Compile Include="RendererPool.cs" />
+ <Compile Include="ViewPool.cs" />
+ <Compile Include="GenericMenuClickListener.cs" />
+ <Compile Include="IVisualElementRenderer.cs" />
+ <Compile Include="ViewRenderer.cs" />
+ <Compile Include="Platform.cs" />
+ <Compile Include="PlatformRenderer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Forms.cs" />
+ <Compile Include="RendererFactory.cs" />
+ <Compile Include="Renderers\ActionSheetRenderer.cs" />
+ <Compile Include="Renderers\ActivityIndicatorRenderer.cs" />
+ <Compile Include="Renderers\BoxRenderer.cs" />
+ <Compile Include="Renderers\ButtonRenderer.cs" />
+ <Compile Include="Renderers\CarouselPageRenderer.cs" />
+ <Compile Include="Renderers\DatePickerRenderer.cs" />
+ <Compile Include="Renderers\EditorRenderer.cs" />
+ <Compile Include="Renderers\EntryRenderer.cs" />
+ <Compile Include="Renderers\FontExtensions.cs" />
+ <Compile Include="Renderers\FrameRenderer.cs" />
+ <Compile Include="Renderers\ImageRenderer.cs" />
+ <Compile Include="Renderers\LabelRenderer.cs" />
+ <Compile Include="Renderers\ListViewAdapter.cs" />
+ <Compile Include="Renderers\ListViewRenderer.cs" />
+ <Compile Include="Renderers\MasterDetailRenderer.cs" />
+ <Compile Include="Renderers\NavigationMenuRenderer.cs" />
+ <Compile Include="Renderers\NavigationRenderer.cs" />
+ <Compile Include="Renderers\ObjectJavaBox.cs" />
+ <Compile Include="Renderers\CarouselPageAdapter.cs" />
+ <Compile Include="Renderers\PageRenderer.cs" />
+ <Compile Include="Renderers\ProgressBarRenderer.cs" />
+ <Compile Include="Renderers\ScrollViewRenderer.cs" />
+ <Compile Include="Renderers\SearchBarRenderer.cs" />
+ <Compile Include="Renderers\SliderRenderer.cs" />
+ <Compile Include="Renderers\StepperRenderer.cs" />
+ <Compile Include="Renderers\SwitchRenderer.cs" />
+ <Compile Include="Renderers\TabbedRenderer.cs" />
+ <Compile Include="Renderers\TableViewModelRenderer.cs" />
+ <Compile Include="Renderers\TableViewRenderer.cs" />
+ <Compile Include="Renderers\TimePickerRenderer.cs" />
+ <Compile Include="Renderers\ToolbarRenderer.cs" />
+ <Compile Include="Renderers\WebViewRenderer.cs" />
+ <Compile Include="ResourceManager.cs" />
+ <Compile Include="ViewExtensions.cs" />
+ <Compile Include="VisualElementExtensions.cs" />
+ <Compile Include="VisualElementPackager.cs" />
+ <Compile Include="VisualElementRenderer.cs" />
+ <Compile Include="VisualElementRendererFlags.cs" />
+ <Compile Include="VisualElementTracker.cs" />
+ <Compile Include="Renderers\PickerRenderer.cs" />
+ <Compile Include="KeyboardManager.cs" />
+ <Compile Include="ResourcesProvider.cs" />
+ <Compile Include="Extensions.cs" />
+ <Compile Include="Renderers\OpenGLViewRenderer.cs" />
+ <Compile Include="AppCompat\CarouselPageRenderer.cs" />
+ <Compile Include="AppCompat\FormsFragmentPagerAdapter.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.Android.FormsViewGroup\Xamarin.Forms.Platform.Android.FormsViewGroup.csproj">
+ <Project>{3b72465b-acae-43ae-9327-10f372fe5f80}</Project>
+ <Name>Xamarin.Forms.Platform.Android.FormsViewGroup</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.nuspec b/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.nuspec
new file mode 100644
index 00000000..1e5676e3
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.nuspec
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<package >
+ <metadata>
+ <id>Xamarin.Forms.Platform.Android</id>
+ <version>$version$</version>
+ <title>Xamarin.Forms Android Platform Renderers</title>
+ <authors>Xamarin Inc.</authors>
+ <owners>Xamarin Inc.</owners>
+ <requireLicenseAcceptance>false</requireLicenseAcceptance>
+ <description>Xamarin.Forms platform abstruction library for mobile applications.</description>
+ <releaseNotes></releaseNotes>
+ <copyright>Copyright 2013</copyright>
+ </metadata>
+ <files>
+ <file src="..\GooglePlayServices\*.dll" target="lib\MonoAndroid40" />
+ </files>
+</package>
diff --git a/Xamarin.Forms.Platform.Android/packages.config b/Xamarin.Forms.Platform.Android/packages.config
new file mode 100644
index 00000000..d7a54544
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/packages.config
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Xamarin.Android.Support.Design" version="23.1.1.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.Android.Support.v4" version="23.1.1.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.Android.Support.v7.AppCompat" version="23.1.1.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.Android.Support.v7.CardView" version="23.1.1.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.Android.Support.v7.RecyclerView" version="23.1.1.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.GooglePlayServices.AppIndexing" version="29.0.0.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.GooglePlayServices.Base" version="29.0.0.1" targetFramework="monoandroid60" />
+ <package id="Xamarin.GooglePlayServices.Basement" version="29.0.0.1" targetFramework="monoandroid60" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.UAP/FormsCommandBar.cs b/Xamarin.Forms.Platform.UAP/FormsCommandBar.cs
new file mode 100644
index 00000000..2ca665af
--- /dev/null
+++ b/Xamarin.Forms.Platform.UAP/FormsCommandBar.cs
@@ -0,0 +1,37 @@
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+namespace Xamarin.Forms.Platform.UWP
+{
+ public class FormsCommandBar : CommandBar
+ {
+ Windows.UI.Xaml.Controls.Button _moreButton;
+
+ public FormsCommandBar()
+ {
+ PrimaryCommands.VectorChanged += OnCommandsChanged;
+ SecondaryCommands.VectorChanged += OnCommandsChanged;
+ }
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+ _moreButton = GetTemplateChild("MoreButton") as Windows.UI.Xaml.Controls.Button;
+ UpdateMore();
+ }
+
+ void OnCommandsChanged(IObservableVector<ICommandBarElement> sender, IVectorChangedEventArgs args)
+ {
+ UpdateMore();
+ }
+
+ void UpdateMore()
+ {
+ if (_moreButton == null)
+ return;
+
+ _moreButton.Visibility = PrimaryCommands.Count > 0 || SecondaryCommands.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.UAP/FormsTextBoxStyle.xaml b/Xamarin.Forms.Platform.UAP/FormsTextBoxStyle.xaml
new file mode 100644
index 00000000..c573552a
--- /dev/null
+++ b/Xamarin.Forms.Platform.UAP/FormsTextBoxStyle.xaml
@@ -0,0 +1,199 @@
+<ResourceDictionary
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:uwp="using:Xamarin.Forms.Platform.UWP">
+
+ <uwp:TextAlignmentToHorizontalAlignmentConverter x:Key="AlignmentConverter" />
+ <Style x:Key="FormsTextBoxStyle" TargetType="uwp:FormsTextBox">
+ <Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
+ <Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
+ <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
+ <Setter Property="Background" Value="{ThemeResource SystemControlBackgroundAltHighBrush}" />
+ <Setter Property="BackgroundFocusBrush" Value="{ThemeResource SystemControlBackgroundChromeWhiteBrush}" />
+ <Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundChromeDisabledLowBrush}" />
+ <Setter Property="SelectionHighlightColor" Value="{ThemeResource SystemControlHighlightAccentBrush}" />
+ <Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
+ <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
+ <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
+ <Setter Property="PlaceholderForegroundBrush" Value="{ThemeResource SystemControlPageTextBaseMediumBrush}" />
+ <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
+ <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
+ <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
+ <Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="uwp:FormsTextBox">
+ <Grid>
+ <Grid.Resources>
+ <Style x:Name="DeleteButtonStyle" TargetType="Button">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="Button">
+ <Grid x:Name="ButtonLayoutGrid" BorderBrush="{ThemeResource TextBoxButtonBorderThemeBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}"
+ Background="{ThemeResource TextBoxButtonBackgroundThemeBrush}">
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal" />
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
+ Storyboard.TargetName="GlyphElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background"
+ Storyboard.TargetName="ButtonLayoutGrid">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
+ Storyboard.TargetName="GlyphElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltChromeWhiteBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity"
+ Storyboard.TargetName="ButtonLayoutGrid" />
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <TextBlock x:Name="GlyphElement" AutomationProperties.AccessibilityView="Raw"
+ Foreground="{ThemeResource SystemControlForegroundChromeBlackMediumBrush}" FontStyle="Normal"
+ FontSize="12" FontFamily="{ThemeResource SymbolThemeFontFamily}" HorizontalAlignment="Center"
+ Text="&#xE10A;" VerticalAlignment="Center" />
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ </Grid.Resources>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="Auto" />
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
+ Storyboard.TargetName="HeaderContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background"
+ Storyboard.TargetName="BackgroundElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledTransparentBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BorderElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="BorderElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledChromeDisabledLowBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
+ Storyboard.TargetName="PlaceholderTextContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledChromeDisabledLowBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Normal" />
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="BorderElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightChromeAltLowBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundHoverOpacity}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Focused">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"
+ Storyboard.TargetName="PlaceholderTextContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlPageTextChromeBlackMediumLowBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background"
+ Storyboard.TargetName="BackgroundElement">
+ <DiscreteObjectKeyFrame KeyTime="0"
+ Value="{Binding BackgroundFocusBrush, RelativeSource={RelativeSource TemplatedParent}}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundFocusedOpacity}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="BorderElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlForegroundChromeBlackHighBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="RequestedTheme"
+ Storyboard.TargetName="ContentElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Light" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="ButtonStates">
+ <VisualState x:Name="ButtonVisible">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DeleteButton">
+ <DiscreteObjectKeyFrame KeyTime="0">
+ <DiscreteObjectKeyFrame.Value>
+ <Visibility>Visible</Visibility>
+ </DiscreteObjectKeyFrame.Value>
+ </DiscreteObjectKeyFrame>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="ButtonCollapsed" />
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Border x:Name="BackgroundElement" Background="{TemplateBinding Background}" Grid.ColumnSpan="2"
+ Margin="{TemplateBinding BorderThickness}" Opacity="{ThemeResource TextControlBackgroundRestOpacity}"
+ Grid.Row="1" Grid.RowSpan="1" />
+ <Border x:Name="BorderElement" BorderBrush="{TemplateBinding BorderBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}" Grid.ColumnSpan="2" Grid.Row="1" Grid.RowSpan="1" />
+ <ContentPresenter x:Name="HeaderContentPresenter" Grid.ColumnSpan="2"
+ ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}"
+ Foreground="{ThemeResource SystemControlForegroundBaseHighBrush}" FontWeight="Normal"
+ Margin="0,0,0,8" Grid.Row="0" Visibility="Collapsed" x:DeferLoadStrategy="Lazy" />
+ <ScrollViewer x:Name="ContentElement" AutomationProperties.AccessibilityView="Raw"
+ HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
+ HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
+ IsTabStop="False" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
+ IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
+ IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
+ Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Grid.Row="1"
+ VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
+ VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" ZoomMode="Disabled" />
+ <ContentControl x:Name="PlaceholderTextContentPresenter" Grid.ColumnSpan="2"
+ Content="{TemplateBinding PlaceholderText}"
+ Foreground="{TemplateBinding PlaceholderForegroundBrush}" IsHitTestVisible="False"
+ IsTabStop="False" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"
+ Grid.Row="1"
+ HorizontalAlignment="{Binding TextAlignment,
+ RelativeSource={RelativeSource Mode=TemplatedParent},
+ Converter={StaticResource AlignmentConverter}}" />
+ <Button x:Name="DeleteButton" BorderThickness="{TemplateBinding BorderThickness}" Grid.Column="1"
+ FontSize="{TemplateBinding FontSize}" IsTabStop="False" Margin="{ThemeResource HelperButtonThemePadding}"
+ MinWidth="34" Grid.Row="1" Style="{StaticResource DeleteButtonStyle}" Visibility="Collapsed"
+ VerticalAlignment="Stretch" />
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+</ResourceDictionary> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.UAP/IToolBarForegroundBinder.cs b/Xamarin.Forms.Platform.UAP/IToolBarForegroundBinder.cs
new file mode 100644
index 00000000..21562bda
--- /dev/null
+++ b/Xamarin.Forms.Platform.UAP/IToolBarForegroundBinder.cs
@@ -0,0 +1,10 @@
+using Windows.UI.Xaml.Controls;
+
+namespace Xamarin.Forms.Platform.UWP
+{
+ internal interface IToolBarForegroundBinder
+ {
+ void BindForegroundColor(AppBar appBar);
+ void BindForegroundColor(AppBarButton button);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.UAP/MasterDetailControl.cs b/Xamarin.Forms.Platform.UAP/MasterDetailControl.cs
new file mode 100644
index 00000000..9ec03f8d
--- /dev/null
+++ b/Xamarin.Forms.Platform.UAP/MasterDetailControl.cs
@@ -0,0 +1,222 @@
+using System.Threading.Tasks;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+
+namespace Xamarin.Forms.Platform.UWP
+{
+ public class MasterDetailControl : Control, IToolbarProvider
+ {
+ public static readonly DependencyProperty MasterProperty = DependencyProperty.Register("Master", typeof(FrameworkElement), typeof(MasterDetailControl),
+ new PropertyMetadata(default(FrameworkElement)));
+
+ public static readonly DependencyProperty MasterTitleProperty = DependencyProperty.Register("MasterTitle", typeof(string), typeof(MasterDetailControl), new PropertyMetadata(default(string)));
+
+ public static readonly DependencyProperty DetailProperty = DependencyProperty.Register("Detail", typeof(FrameworkElement), typeof(MasterDetailControl),
+ new PropertyMetadata(default(FrameworkElement)));
+
+ public static readonly DependencyProperty IsPaneOpenProperty = DependencyProperty.Register("IsPaneOpen", typeof(bool), typeof(MasterDetailControl), new PropertyMetadata(default(bool)));
+
+ public static readonly DependencyProperty ShouldShowSplitModeProperty = DependencyProperty.Register("ShouldShowSplitMode", typeof(bool), typeof(MasterDetailControl),
+ new PropertyMetadata(default(bool), OnShouldShowSplitModeChanged));
+
+ public static readonly DependencyProperty DetailTitleProperty = DependencyProperty.Register("DetailTitle", typeof(string), typeof(MasterDetailControl), new PropertyMetadata(default(string)));
+
+ public static readonly DependencyProperty ToolbarForegroundProperty = DependencyProperty.Register("ToolbarForeground", typeof(Brush), typeof(MasterDetailControl),
+ new PropertyMetadata(default(Brush)));
+
+ public static readonly DependencyProperty ToolbarBackgroundProperty = DependencyProperty.Register("ToolbarBackground", typeof(Brush), typeof(MasterDetailControl),
+ new PropertyMetadata(default(Brush)));
+
+ public static readonly DependencyProperty MasterTitleVisibilityProperty = DependencyProperty.Register("MasterTitleVisibility", typeof(Visibility), typeof(MasterDetailControl),
+ new PropertyMetadata(default(Visibility)));
+
+ public static readonly DependencyProperty DetailTitleVisibilityProperty = DependencyProperty.Register("DetailTitleVisibility", typeof(Visibility), typeof(MasterDetailControl),
+ new PropertyMetadata(default(Visibility)));
+
+ public static readonly DependencyProperty MasterToolbarVisibilityProperty = DependencyProperty.Register("MasterToolbarVisibility", typeof(Visibility), typeof(MasterDetailControl),
+ new PropertyMetadata(default(Visibility)));
+
+ CommandBar _commandBar;
+
+ TaskCompletionSource<CommandBar> _commandBarTcs;
+ FrameworkElement _masterPresenter;
+ FrameworkElement _detailPresenter;
+ SplitView _split;
+
+ public MasterDetailControl()
+ {
+ DefaultStyleKey = typeof(MasterDetailControl);
+ MasterTitleVisibility = Visibility.Collapsed;
+ DetailTitleVisibility = Visibility.Collapsed;
+ if (Device.Idiom != TargetIdiom.Phone)
+ MasterToolbarVisibility = Visibility.Collapsed;
+ }
+
+ public FrameworkElement Detail
+ {
+ get { return (FrameworkElement)GetValue(DetailProperty); }
+ set { SetValue(DetailProperty, value); }
+ }
+
+ public Windows.Foundation.Size DetailSize
+ {
+ get
+ {
+ double height = ActualHeight;
+ double width = ActualWidth;
+
+ if (_commandBar != null)
+ height -= _commandBar.ActualHeight;
+
+ if (ShouldShowSplitMode && IsPaneOpen)
+ {
+ if (_split != null)
+ width -= _split.OpenPaneLength;
+ else if (_detailPresenter != null)
+ width -= _masterPresenter.ActualWidth;
+ }
+
+ return new Windows.Foundation.Size(width, height);
+ }
+ }
+
+ public string DetailTitle
+ {
+ get { return (string)GetValue(DetailTitleProperty); }
+ set { SetValue(DetailTitleProperty, value); }
+ }
+
+ public Visibility DetailTitleVisibility
+ {
+ get { return (Visibility)GetValue(DetailTitleVisibilityProperty); }
+ set { SetValue(DetailTitleVisibilityProperty, value); }
+ }
+
+ public bool IsPaneOpen
+ {
+ get { return (bool)GetValue(IsPaneOpenProperty); }
+ set { SetValue(IsPaneOpenProperty, value); }
+ }
+
+ public FrameworkElement Master
+ {
+ get { return (FrameworkElement)GetValue(MasterProperty); }
+ set { SetValue(MasterProperty, value); }
+ }
+
+ public Windows.Foundation.Size MasterSize
+ {
+ get
+ {
+ double height = ActualHeight;
+ double width = 0;
+
+ if (_commandBar != null)
+ height -= _commandBar.ActualHeight;
+
+ if (_split != null)
+ width = _split.OpenPaneLength;
+ else if (_masterPresenter != null)
+ width = _masterPresenter.ActualWidth;
+
+ return new Windows.Foundation.Size(width, height);
+ }
+ }
+
+ public string MasterTitle
+ {
+ get { return (string)GetValue(MasterTitleProperty); }
+ set { SetValue(MasterTitleProperty, value); }
+ }
+
+ public Visibility MasterTitleVisibility
+ {
+ get { return (Visibility)GetValue(MasterTitleVisibilityProperty); }
+ set { SetValue(MasterTitleVisibilityProperty, value); }
+ }
+
+ public Visibility MasterToolbarVisibility
+ {
+ get { return (Visibility)GetValue(MasterToolbarVisibilityProperty); }
+ set { SetValue(MasterToolbarVisibilityProperty, value); }
+ }
+
+ public bool ShouldShowSplitMode
+ {
+ get { return (bool)GetValue(ShouldShowSplitModeProperty); }
+ set { SetValue(ShouldShowSplitModeProperty, value); }
+ }
+
+ public Brush ToolbarBackground
+ {
+ get { return (Brush)GetValue(ToolbarBackgroundProperty); }
+ set { SetValue(ToolbarBackgroundProperty, value); }
+ }
+
+ public Brush ToolbarForeground
+ {
+ get { return (Brush)GetValue(ToolbarForegroundProperty); }
+ set { SetValue(ToolbarForegroundProperty, value); }
+ }
+
+ Task<CommandBar> IToolbarProvider.GetCommandBarAsync()
+ {
+ if (_commandBar != null)
+ return Task.FromResult(_commandBar);
+
+ _commandBarTcs = new TaskCompletionSource<CommandBar>();
+ ApplyTemplate();
+ return _commandBarTcs.Task;
+ }
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ _split = GetTemplateChild("SplitView") as SplitView;
+ if (_split == null)
+ return;
+
+ var paneToggle = GetTemplateChild("PaneTogglePane") as Windows.UI.Xaml.Controls.Button;
+ if (paneToggle != null)
+ paneToggle.Click += OnToggleClicked;
+
+ var contentToggle = GetTemplateChild("ContentTogglePane") as Windows.UI.Xaml.Controls.Button;
+ if (contentToggle != null)
+ contentToggle.Click += OnToggleClicked;
+
+ _masterPresenter = GetTemplateChild("MasterPresenter") as FrameworkElement;
+ _detailPresenter = GetTemplateChild("DetailPresenter") as FrameworkElement;
+
+ _commandBar = GetTemplateChild("CommandBar") as CommandBar;
+
+ UpdateMode();
+
+ TaskCompletionSource<CommandBar> tcs = _commandBarTcs;
+ if (tcs != null)
+ {
+ _commandBarTcs = null;
+ tcs.SetResult(_commandBar);
+ }
+ }
+
+ static void OnShouldShowSplitModeChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
+ {
+ ((MasterDetailControl)dependencyObject).UpdateMode();
+ }
+
+ void OnToggleClicked(object sender, RoutedEventArgs args)
+ {
+ IsPaneOpen = !IsPaneOpen;
+ }
+
+ void UpdateMode()
+ {
+ if (_split == null)
+ return;
+
+ _split.DisplayMode = ShouldShowSplitMode ? SplitViewDisplayMode.Inline : SplitViewDisplayMode.Overlay;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.UAP/MasterDetailPageRenderer.cs b/Xamarin.Forms.Platform.UAP/MasterDetailPageRenderer.cs
new file mode 100644
index 00000000..c8c09789
--- /dev/null
+++ b/Xamarin.Forms.Platform.UAP/MasterDetailPageRenderer.cs
@@ -0,0 +1,312 @@
+using System;
+using System.ComponentModel;
+using System.Threading.Tasks;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Automation;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Media;
+
+namespace Xamarin.Forms.Platform.UWP
+{
+ public class MasterDetailPageRenderer : IVisualElementRenderer, IToolbarProvider, ITitleProvider, IToolBarForegroundBinder
+ {
+ Page _master;
+ Page _detail;
+ bool _showTitle;
+
+ VisualElementTracker<Page, FrameworkElement> _tracker;
+
+ public MasterDetailControl Control { get; private set; }
+
+ public MasterDetailPage Element { get; private set; }
+
+ protected VisualElementTracker<Page, FrameworkElement> Tracker
+ {
+ get { return _tracker; }
+ set
+ {
+ if (_tracker == value)
+ return;
+
+ if (_tracker != null)
+ _tracker.Dispose();
+
+ _tracker = value;
+ }
+ }
+
+ public void Dispose()
+ {
+ ClearMaster();
+ ClearDetail();
+
+ Tracker = null;
+ if (Element != null)
+ SetElement(null);
+ }
+
+ Brush ITitleProvider.BarBackgroundBrush
+ {
+ set { Control.ToolbarBackground = value; }
+ }
+
+ Brush ITitleProvider.BarForegroundBrush
+ {
+ set { Control.ToolbarForeground = value; }
+ }
+
+ bool ITitleProvider.ShowTitle
+ {
+ get { return _showTitle; }
+
+ set
+ {
+ if (_showTitle == value)
+ return;
+ _showTitle = value;
+ if (_showTitle)
+ Control.DetailTitleVisibility = Visibility.Visible;
+ else
+ Control.DetailTitleVisibility = Visibility.Collapsed;
+ }
+ }
+
+ string ITitleProvider.Title
+ {
+ get { return Element?.Title; }
+
+ set
+ {
+ if (Control != null)
+ Control.DetailTitle = value;
+ }
+ }
+
+ Task<CommandBar> IToolbarProvider.GetCommandBarAsync()
+ {
+ return ((IToolbarProvider)Control)?.GetCommandBarAsync();
+ }
+
+ FrameworkElement IVisualElementRenderer.ContainerElement
+ {
+ get { return Control; }
+ }
+
+ VisualElement IVisualElementRenderer.Element
+ {
+ get { return Element; }
+ }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ Size size = Device.Info.ScaledScreenSize;
+ return new SizeRequest(new Size(size.Width, size.Height));
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ MasterDetailPage old = Element;
+ Element = (MasterDetailPage)element;
+
+ if (element != old)
+ OnElementChanged(new ElementChangedEventArgs<MasterDetailPage>(old, Element));
+ }
+
+ protected virtual void OnElementChanged(ElementChangedEventArgs<MasterDetailPage> e)
+ {
+ if (e.OldElement != null)
+ e.OldElement.PropertyChanged -= OnElementPropertyChanged;
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ Control = new MasterDetailControl();
+ Control.Loaded += OnControlLoaded;
+ Control.Unloaded += OnControlUnlaoded;
+ Control.SizeChanged += OnNativeSizeChanged;
+
+ Control.RegisterPropertyChangedCallback(MasterDetailControl.IsPaneOpenProperty, OnIsPaneOpenChanged);
+
+ Tracker = new VisualElementTracker<Page, FrameworkElement> { Container = Control, Element = Element };
+ }
+
+ e.NewElement.PropertyChanged += OnElementPropertyChanged;
+ UpdateDetail();
+ UpdateMaster();
+ UpdateMode();
+ UpdateIsPresented();
+
+ if (!string.IsNullOrEmpty(e.NewElement.AutomationId))
+ Control.SetValue(AutomationProperties.AutomationIdProperty, e.NewElement.AutomationId);
+ }
+ }
+
+ protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == MasterDetailPage.IsPresentedProperty.PropertyName)
+ UpdateIsPresented();
+ else if (e.PropertyName == "Master")
+ UpdateMaster();
+ else if (e.PropertyName == "Detail")
+ UpdateDetail();
+ else if (e.PropertyName == "ShouldShowSplitMode")
+ UpdateMode();
+ }
+
+ void ClearDetail()
+ {
+ ((ITitleProvider)this).ShowTitle = false;
+
+ if (_detail == null)
+ return;
+
+ _detail.PropertyChanged -= OnDetailPropertyChanged;
+
+ IVisualElementRenderer renderer = Platform.GetRenderer(_detail);
+ renderer?.Dispose();
+
+ _detail.ClearValue(Platform.RendererProperty);
+ _detail = null;
+ }
+
+ void ClearMaster()
+ {
+ if (_master == null)
+ return;
+
+ _master.PropertyChanged -= OnMasterPropertyChanged;
+
+ IVisualElementRenderer renderer = Platform.GetRenderer(_master);
+ renderer?.Dispose();
+
+ _master.ClearValue(Platform.RendererProperty);
+ _master = null;
+ }
+
+ void OnControlLoaded(object sender, RoutedEventArgs routedEventArgs)
+ {
+ if (Element == null)
+ return;
+
+ Element.SendAppearing();
+ UpdateBounds();
+ }
+
+ void OnControlUnlaoded(object sender, RoutedEventArgs routedEventArgs)
+ {
+ if (Element == null)
+ return;
+
+ Element.SendDisappearing();
+ }
+
+ void OnDetailPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Page.TitleProperty.PropertyName || e.PropertyName == NavigationPage.CurrentPageProperty.PropertyName)
+ UpdateDetailTitle();
+ }
+
+ void OnIsPaneOpenChanged(DependencyObject sender, DependencyProperty dp)
+ {
+ ((IElementController)Element).SetValueFromRenderer(MasterDetailPage.IsPresentedProperty, Control.IsPaneOpen);
+ UpdateBounds();
+ }
+
+ void OnMasterPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Page.TitleProperty.PropertyName)
+ Control.MasterTitle = _master?.Title;
+ }
+
+ void OnNativeSizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ UpdateBounds();
+ }
+
+ void UpdateBounds()
+ {
+ Windows.Foundation.Size masterSize = Control.MasterSize;
+ Windows.Foundation.Size detailSize = Control.DetailSize;
+
+ Element.MasterBounds = new Rectangle(0, 0, masterSize.Width, masterSize.Height);
+ Element.DetailBounds = new Rectangle(0, 0, detailSize.Width, detailSize.Height);
+ }
+
+ void UpdateDetail()
+ {
+ ClearDetail();
+
+ FrameworkElement element = null;
+
+ _detail = Element.Detail;
+ if (_detail != null)
+ {
+ _detail.PropertyChanged += OnDetailPropertyChanged;
+
+ IVisualElementRenderer renderer = _detail.GetOrCreateRenderer();
+ element = renderer.ContainerElement;
+ }
+
+ Control.Detail = element;
+ UpdateDetailTitle();
+ }
+
+ void UpdateDetailTitle()
+ {
+ if (_detail == null)
+ return;
+
+ Control.DetailTitle = (_detail as NavigationPage)?.CurrentPage?.Title ?? _detail.Title ?? Element?.Title;
+ }
+
+ void UpdateIsPresented()
+ {
+ Control.IsPaneOpen = Element.IsPresented;
+ }
+
+ void UpdateMaster()
+ {
+ ClearMaster();
+
+ FrameworkElement element = null;
+ _master = Element.Master;
+ if (_master != null)
+ {
+ _master.PropertyChanged += OnMasterPropertyChanged;
+
+ IVisualElementRenderer renderer = _master.GetOrCreateRenderer();
+ element = renderer.ContainerElement;
+ }
+
+ Control.Master = element;
+ Control.MasterTitle = _master?.Title;
+ }
+
+ void UpdateMode()
+ {
+ Control.ShouldShowSplitMode = Element.ShouldShowSplitMode;
+ }
+
+#if WINDOWS_UWP
+ public void BindForegroundColor(AppBar appBar)
+ {
+ SetAppBarForegroundBinding(appBar);
+ }
+
+ public void BindForegroundColor(AppBarButton button)
+ {
+ SetAppBarForegroundBinding(button);
+ }
+
+ void SetAppBarForegroundBinding(FrameworkElement element)
+ {
+ element.SetBinding(Windows.UI.Xaml.Controls.Control.ForegroundProperty,
+ new Windows.UI.Xaml.Data.Binding { Path = new PropertyPath("Control.ToolbarForeground"), Source = this, RelativeSource = new RelativeSource { Mode = RelativeSourceMode.TemplatedParent } });
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.UAP/PageControl.xaml b/Xamarin.Forms.Platform.UAP/PageControl.xaml
new file mode 100644
index 00000000..5732b86d
--- /dev/null
+++ b/Xamarin.Forms.Platform.UAP/PageControl.xaml
@@ -0,0 +1,10 @@
+<ContentControl
+ x:Class="Xamarin.Forms.Platform.UWP.PageControl"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ mc:Ignorable="d" d:DesignWidth="1024"
+ HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
+
+</ContentControl>
diff --git a/Xamarin.Forms.Platform.UAP/Properties/AssemblyInfo.cs b/Xamarin.Forms.Platform.UAP/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..01702c9d
--- /dev/null
+++ b/Xamarin.Forms.Platform.UAP/Properties/AssemblyInfo.cs
@@ -0,0 +1,60 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.UWP;
+
+[assembly: AssemblyTitle("Xamarin.Forms.Platform.UAP")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Dependency(typeof(WindowsSerializer))]
+
+// Views
+
+[assembly: ExportRenderer(typeof(Layout), typeof(LayoutRenderer))]
+[assembly: ExportRenderer(typeof(BoxView), typeof(BoxViewRenderer))]
+[assembly: ExportRenderer(typeof(Image), typeof(ImageRenderer))]
+[assembly: ExportRenderer(typeof(Label), typeof(LabelRenderer))]
+[assembly: ExportRenderer(typeof(Button), typeof(ButtonRenderer))]
+[assembly: ExportRenderer(typeof(ListView), typeof(ListViewRenderer))]
+[assembly: ExportRenderer(typeof(CarouselView), typeof(CarouselViewRenderer))]
+[assembly: ExportRenderer(typeof(ScrollView), typeof(ScrollViewRenderer))]
+[assembly: ExportRenderer(typeof(ProgressBar), typeof(ProgressBarRenderer))]
+[assembly: ExportRenderer(typeof(Slider), typeof(SliderRenderer))]
+[assembly: ExportRenderer(typeof(Switch), typeof(SwitchRenderer))]
+[assembly: ExportRenderer(typeof(WebView), typeof(WebViewRenderer))]
+[assembly: ExportRenderer(typeof(Frame), typeof(FrameRenderer))]
+[assembly: ExportRenderer(typeof(ActivityIndicator), typeof(ActivityIndicatorRenderer))]
+[assembly: ExportRenderer(typeof(Editor), typeof(EditorRenderer))]
+[assembly: ExportRenderer(typeof(Picker), typeof(PickerRenderer))]
+[assembly: ExportRenderer(typeof(TimePicker), typeof(TimePickerRenderer))]
+[assembly: ExportRenderer(typeof(DatePicker), typeof(DatePickerRenderer))]
+[assembly: ExportRenderer(typeof(Stepper), typeof(StepperRenderer))]
+[assembly: ExportRenderer(typeof(Entry), typeof(EntryRenderer))]
+[assembly: ExportRenderer(typeof(TableView), typeof(TableViewRenderer))]
+[assembly: ExportRenderer(typeof(NativeViewWrapper), typeof(NativeViewWrapperRenderer))]
+
+//ImageSources
+
+[assembly: ExportImageSourceHandler(typeof(FileImageSource), typeof(FileImageSourceHandler))]
+[assembly: ExportImageSourceHandler(typeof(StreamImageSource), typeof(StreamImagesourceHandler))]
+[assembly: ExportImageSourceHandler(typeof(UriImageSource), typeof(ImageLoaderSourceHandler))]
+
+// Pages
+
+[assembly: ExportRenderer(typeof(Page), typeof(PageRenderer))]
+[assembly: ExportRenderer(typeof(NavigationPage), typeof(NavigationPageRenderer))]
+[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(MasterDetailPageRenderer))]
+[assembly: ExportRenderer(typeof(CarouselPage), typeof(CarouselPageRenderer))]
+
+// Cells
+
+[assembly: ExportCell(typeof(Cell), typeof(TextCellRenderer))]
+[assembly: ExportCell(typeof(ImageCell), typeof(ImageCellRenderer))]
+[assembly: ExportCell(typeof(EntryCell), typeof(EntryCellRenderer))]
+[assembly: ExportCell(typeof(SwitchCell), typeof(SwitchCellRenderer))]
+[assembly: ExportCell(typeof(ViewCell), typeof(ViewCellRenderer))]
+[assembly: Dependency(typeof(WindowsResourcesProvider))]
+[assembly: ExportRenderer(typeof(SearchBar), typeof(SearchBarRenderer))]
+[assembly: ExportRenderer(typeof(TabbedPage), typeof(TabbedPageRenderer))] \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.UAP/Properties/Xamarin.Forms.Platform.UAP.rd.xml b/Xamarin.Forms.Platform.UAP/Properties/Xamarin.Forms.Platform.UAP.rd.xml
new file mode 100644
index 00000000..13a5a5ad
--- /dev/null
+++ b/Xamarin.Forms.Platform.UAP/Properties/Xamarin.Forms.Platform.UAP.rd.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ This file contains Runtime Directives, specifications about types your application accesses
+ through reflection and other dynamic code patterns. Runtime Directives are used to control the
+ .NET Native optimizer and ensure that it does not remove code accessed by your library. If your
+ library does not do any reflection, then you generally do not need to edit this file. However,
+ if your library reflects over types, especially types passed to it or derived from its types,
+ then you should write Runtime Directives.
+
+ The most common use of reflection in libraries is to discover information about types passed
+ to the library. Runtime Directives have three ways to express requirements on types passed to
+ your library.
+
+ 1. Parameter, GenericParameter, TypeParameter, TypeEnumerableParameter
+ Use these directives to reflect over types passed as a parameter.
+
+ 2. SubTypes
+ Use a SubTypes directive to reflect over types derived from another type.
+
+ 3. AttributeImplies
+ Use an AttributeImplies directive to indicate that your library needs to reflect over
+ types or methods decorated with an attribute.
+
+ For more information on writing Runtime Directives for libraries, please visit
+ http://go.microsoft.com/fwlink/?LinkId=613100
+-->
+<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
+ <Library Name="Xamarin.Forms.Platform.UAP">
+
+ <!-- add directives for your library here -->
+
+ </Library>
+</Directives>
diff --git a/Xamarin.Forms.Platform.UAP/Resources.xaml b/Xamarin.Forms.Platform.UAP/Resources.xaml
new file mode 100644
index 00000000..e26eb392
--- /dev/null
+++ b/Xamarin.Forms.Platform.UAP/Resources.xaml
@@ -0,0 +1,1091 @@
+<ResourceDictionary
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:uwp="using:Xamarin.Forms.Platform.UWP"
+ x:Class="Xamarin.Forms.Platform.UWP.Resources">
+
+ <ResourceDictionary.MergedDictionaries>
+ <ResourceDictionary Source="FormsTextBoxStyle.xaml" />
+ </ResourceDictionary.MergedDictionaries>
+
+ <uwp:CaseConverter x:Key="LowerConverter" ConvertToUpper="False" />
+ <uwp:CaseConverter x:Key="UpperConverter" ConvertToUpper="True" />
+ <uwp:HeightConverter x:Key="HeightConverter" />
+ <uwp:CollapseWhenEmptyConverter x:Key="CollapseWhenEmpty" />
+ <uwp:BoolToVisibilityConverter x:Key="BoolVisibilityConverter" />
+ <uwp:BoolToVisibilityConverter x:Key="InvertedBoolVisibilityConverter" FalseIsVisible="True" />
+ <uwp:PageToRenderedElementConverter x:Key="PageToRenderer" />
+ <uwp:ImageConverter x:Key="ImageConverter" />
+ <uwp:ViewToRendererConverter x:Key="ViewToRenderer" />
+ <uwp:ColorConverter x:Key="ColorConverter" />
+ <uwp:HorizontalTextAlignmentConverter x:Key="HorizontalTextAlignmentConverter" />
+ <uwp:TextAlignmentToHorizontalAlignmentConverter x:Key="AlignmentConverter" />
+ <uwp:KeyboardConverter x:Key="KeyboardConverter" />
+ <uwp:MasterBackgroundConverter x:Key="MasterBackgroundConverter" />
+ <x:Double x:Key="TitleBarHeight">48</x:Double>
+
+ <DataTemplate x:Key="PushPinTemplate">
+ <Path Data="M 50.7361,983.661 C 44.1895,983.661 38.8369,988.97 38.8369,995.517 39.8649,1003.3 45.246,1008.1 49.8547,1014.12 50.2838,1014.66 51.2336,1014.66 51.6619,1014.12 52.1384,1013.48 52.7575,1012.73 53.4248,1011.91 55.0322,1012.07 56.4727,1012.32 57.5676,1012.71 58.407,1013 59.06,1013.33 59.4192,1013.63 59.7784,1013.93 59.7716,1014.11 59.7716,1014.16 59.7716,1014.21 59.7716,1014.39 59.4192,1014.69 59.06,1014.99 58.407,1015.32 57.5676,1015.61 55.8888,1016.2 53.4519,1016.63 50.7361,1016.63 48.0204,1016.63 45.5399,1016.2 43.8611,1015.61 43.0218,1015.32 42.3695,1014.99 42.0103,1014.69 41.6504,1014.39 41.6135,1014.21 41.6135,1014.16 41.6135,1014.11 41.6511,1013.93 42.0103,1013.63 42.3695,1013.33 43.0218,1013 43.8611,1012.71 44.3158,1012.55 44.8455,1012.35 45.4039,1012.22 L 43.8611,1010.33 C 43.6124,1010.4 43.3441,1010.46 43.1119,1010.55 42.1005,1010.9 41.2318,1011.31 40.5555,1011.87 39.8799,1012.43 39.3216,1013.22 39.3216,1014.16 39.3216,1015.1 39.8799,1015.85 40.5555,1016.41 41.2318,1016.97 42.1005,1017.42 43.1119,1017.77 45.1356,1018.48 47.8025,1018.92 50.7362,1018.92 54.437,1018.81 57.9892,1018.36 60.8733,1016.41 62.5084,1014.79 62.0756,1013.4 60.8733,1011.87 60.1969,1011.31 59.3726,1010.9 58.3612,1010.55 57.4331,1010.22 56.3503,1009.94 55.1878,1009.75 56.1992,1008.51 57.2362,1007.18 58.2289,1005.79 60.5599,1002.51 62.5918,998.968 62.5918,995.517 62.5918,988.97 57.2836,983.661 50.7362,983.661 Z M 50.7361,989.655 C 47.571,989.655 44.9627,992.219 44.9627,995.385 44.9627,998.55 47.571,1001.16 50.7361,1001.16 53.902,1001.16 56.4659,998.55 56.4659,995.385 56.4659,992.219 53.902,989.655 50.7361,989.655 Z M 50.7361,991.947 C 52.6591,991.947 54.174,993.462 54.174,995.385 54.174,997.307 52.6591,998.866 50.7361,998.866 48.8139,998.866 47.2546,997.307 47.2546,995.385 47.2546,993.462 48.8139,991.947 50.7361,991.947 Z" Fill="#000000" Height="74" Stretch="Fill" Margin="0" Width="50"/>
+ </DataTemplate>
+
+ <Style x:Key="PageTitleStyle" TargetType="TextBlock">
+ <Setter Property="FontWeight" Value="Bold" />
+ </Style>
+
+ <Style x:Key="RootContainerStyle" TargetType="Canvas">
+ <Setter Property="Background" Value="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
+ </Style>
+
+ <Style x:Key="ActionSheetStyle" TargetType="ContentDialog" />
+ <Style x:Key="ActionSheetList" TargetType="ListView">
+ <Setter Property="SelectionMode" Value="None" />
+ <Setter Property="ItemContainerStyle">
+ <Setter.Value>
+ <Style TargetType="ListViewItem">
+ <Setter Property="Margin" Value="0" />
+ <Setter Property="HorizontalContentAlignment" Value="Stretch" />
+ </Style>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="ItemTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <TextBlock Text="{Binding}" HorizontalAlignment="Stretch" VerticalAlignment="Center" Style="{ThemeResource SubtitleTextBlockStyle}" />
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <ControlTemplate TargetType="ContentDialog" x:Key="MyContentDialogControlTemplate">
+ <Border x:Name="Container">
+ <Grid x:Name="LayoutRoot">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ </Grid.ColumnDefinitions>
+ <Border x:Name="BackgroundElement"
+ Background="{TemplateBinding Background}"
+ FlowDirection="{TemplateBinding FlowDirection}"
+ BorderThickness="{ThemeResource ContentDialogBorderWidth}"
+ BorderBrush="{ThemeResource SystemControlForegroundAccentBrush}"
+ MaxWidth="{TemplateBinding MaxWidth}"
+ MaxHeight="{TemplateBinding MaxHeight}"
+ MinWidth="{TemplateBinding MinWidth}"
+ MinHeight="{TemplateBinding MinHeight}" >
+ <Grid x:Name="DialogSpace" VerticalAlignment="Stretch">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ <RowDefinition Height="Auto" />
+ </Grid.RowDefinitions>
+ <ScrollViewer x:Name="ContentScrollViewer"
+ HorizontalScrollBarVisibility="Disabled"
+ VerticalScrollBarVisibility="Disabled"
+ ZoomMode="Disabled"
+ Margin="{ThemeResource ContentDialogContentScrollViewerMargin}"
+ IsTabStop="False">
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <!--CHANGED HERE. Used to be Auto as well-->
+ <RowDefinition />
+ </Grid.RowDefinitions>
+ <ContentControl x:Name="Title"
+ Margin="{ThemeResource ContentDialogTitleMargin}"
+ Content="{TemplateBinding Title}"
+ ContentTemplate="{TemplateBinding TitleTemplate}"
+ FontSize="20"
+ FontFamily="Segoe UI"
+ FontWeight="Normal"
+ Foreground="{TemplateBinding Foreground}"
+ HorizontalAlignment="Left"
+ VerticalAlignment="Top"
+ IsTabStop="False"
+ MaxHeight="{ThemeResource ContentDialogTitleMaxHeight}" >
+ <ContentControl.Template>
+ <ControlTemplate TargetType="ContentControl">
+ <ContentPresenter
+ Content="{TemplateBinding Content}"
+ MaxLines="2"
+ TextWrapping="Wrap"
+ ContentTemplate="{TemplateBinding ContentTemplate}"
+ Margin="{TemplateBinding Padding}"
+ ContentTransitions="{TemplateBinding ContentTransitions}"
+ HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
+ VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
+ </ControlTemplate>
+ </ContentControl.Template>
+ </ContentControl>
+ <ContentPresenter x:Name="Content"
+ ContentTemplate="{TemplateBinding ContentTemplate}"
+ Content="{TemplateBinding Content}"
+ FontSize="{ThemeResource ControlContentThemeFontSize}"
+ FontFamily="{ThemeResource ContentControlThemeFontFamily}"
+ Margin="{ThemeResource ContentDialogContentMargin}"
+ Foreground="{TemplateBinding Foreground}"
+ Grid.Row="1"
+ TextWrapping="Wrap" />
+ </Grid>
+ </ScrollViewer>
+ <Grid x:Name="CommandSpace" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Bottom">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition/>
+ <ColumnDefinition/>
+ </Grid.ColumnDefinitions>
+ <Border x:Name="Button1Host"
+ Margin="{ThemeResource ContentDialogButton1HostMargin}"
+ MinWidth="{ThemeResource ContentDialogButtonMinWidth}"
+ MaxWidth="{ThemeResource ContentDialogButtonMaxWidth}"
+ Height="{ThemeResource ContentDialogButtonHeight}"
+ HorizontalAlignment="Stretch" />
+ <Border x:Name="Button2Host"
+ Margin="{ThemeResource ContentDialogButton2HostMargin}"
+ MinWidth="{ThemeResource ContentDialogButtonMinWidth}"
+ MaxWidth="{ThemeResource ContentDialogButtonMaxWidth}"
+ Height="{ThemeResource ContentDialogButtonHeight}"
+ Grid.Column="1"
+ HorizontalAlignment="Stretch" />
+ </Grid>
+ </Grid>
+ </Border>
+ </Grid>
+ </Border>
+ </ControlTemplate>
+
+ <Style x:Key="JumpListGrid" TargetType="GridView">
+ <Setter Property="ItemTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <Border Background="{ThemeResource SystemColorControlAccentBrush}" Padding="5" Margin="3" MinHeight="80" MinWidth="80">
+ <TextBlock Text="{Binding}" Style="{ThemeResource SubheaderTextBlockStyle}" VerticalAlignment="Bottom" />
+ </Border>
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style TargetType="Button" x:Key="PaneButton">
+ <Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}" />
+ <Setter Property="FontSize" Value="20" />
+ <Setter Property="Height" Value="48" />
+ <Setter Property="Width" Value="48" />
+ <Setter Property="Content" Value="" />
+ </Style>
+
+ <DataTemplate x:Key="CellTemplate">
+ <uwp:CellControl HorizontalContentAlignment="Stretch" />
+ </DataTemplate>
+
+ <DataTemplate x:Key="TableRoot">
+ <TextBlock Margin="0,20,0,0" Text="{Binding Title,Converter={StaticResource LowerConverter}}" Style="{ThemeResource TitleTextBlockStyle}" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=Self},Converter={StaticResource CollapseWhenEmpty}}" />
+ </DataTemplate>
+
+ <DataTemplate x:Key="TableSection">
+ <TextBlock Margin="0,20,0,0" Text="{Binding Title,Converter={StaticResource LowerConverter}}" Style="{ThemeResource SubtitleTextBlockStyle}" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=Self},Converter={StaticResource CollapseWhenEmpty}}" />
+ </DataTemplate>
+
+ <uwp:ListViewGroupStyleSelector x:Key="ListViewGroupSelector" />
+
+ <DataTemplate x:Key="ListViewGroupTemplate">
+ <TextBlock Text="{Binding}" Style="{ThemeResource BaseTextBlockStyle}" />
+ </DataTemplate>
+
+ <GroupStyle x:Key="ListViewGroup" HidesIfEmpty="False">
+ <GroupStyle.HeaderContainerStyle>
+ <Style TargetType="ListViewHeaderItem">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <uwp:ListGroupHeaderPresenter />
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ </GroupStyle.HeaderContainerStyle>
+ <GroupStyle.HeaderTemplate>
+ <DataTemplate>
+ <uwp:CellControl IsGroupHeader="true" HorizontalContentAlignment="Stretch" />
+ </DataTemplate>
+ </GroupStyle.HeaderTemplate>
+ </GroupStyle>
+
+ <DataTemplate x:Key="ViewCell">
+ <ContentControl DataContext="{Binding Cell}">
+ <ContentPresenter Height="{Binding RenderHeight, Converter={StaticResource HeightConverter}}" Content="{Binding View, Converter={StaticResource ViewToRenderer}}" />
+ </ContentControl>
+ </DataTemplate>
+
+ <DataTemplate x:Key="ContainedPageTemplate">
+ <ContentPresenter Content="{Binding Converter={StaticResource PageToRenderer}}">
+ <ContentPresenter.Resources>
+ <Style TargetType="uwp:PageControl">
+ <Setter Property="Background" Value="Transparent" />
+ </Style>
+ </ContentPresenter.Resources>
+ </ContentPresenter>
+ </DataTemplate>
+
+ <DataTemplate x:Key="View">
+ <ContentPresenter Content="{Binding Converter={StaticResource ViewToRenderer}}" />
+ </DataTemplate>
+
+ <SolidColorBrush x:Key="TabButtonPointerOverBackgroundBrush" Color="#44888888" />
+ <SolidColorBrush x:Key="TabButtonBackgroundBrush" Color="#29888888" />
+
+ <Style x:Key="TitleToolbar" TargetType="uwp:FormsCommandBar">
+ <Setter Property="ContentTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <TextBlock Text="{Binding}" Margin="10,0,0,0" VerticalAlignment="Center" Style="{ThemeResource TitleTextBlockStyle}" />
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style TargetType="uwp:MasterDetailControl">
+ <Setter Property="ToolbarForeground" Value="{ThemeResource DefaultTextForegroundThemeBrush}" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="uwp:MasterDetailControl">
+ <SplitView x:Name="SplitView" IsPaneOpen="{Binding IsPaneOpen,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}" DisplayMode="Overlay">
+ <SplitView.Pane>
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+ <StackPanel Grid.Row="0" Orientation="Horizontal" Visibility="{TemplateBinding MasterToolbarVisibility}" Background="{TemplateBinding ToolbarBackground}">
+ <Button Name="PaneTogglePane" Style="{ThemeResource PaneButton}" Foreground="{TemplateBinding ToolbarForeground}" />
+ <TextBlock Style="{ThemeResource TitleTextBlockStyle}" VerticalAlignment="Center" Text="{TemplateBinding MasterTitle}" Visibility="{TemplateBinding MasterTitleVisibility}" Foreground="{TemplateBinding ToolbarForeground}"/>
+ </StackPanel>
+
+ <ContentPresenter x:Name="MasterPresenter" Grid.Row="1" Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Master}" />
+ </Grid>
+ </SplitView.Pane>
+ <SplitView.Content>
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+
+ <uwp:FormsCommandBar x:Name="CommandBar" Grid.Row="0" Foreground="{TemplateBinding ToolbarForeground}" Background="{TemplateBinding ToolbarBackground}" Visibility="{TemplateBinding DetailTitleVisibility}" VerticalContentAlignment="Top">
+ <uwp:FormsCommandBar.Content>
+ <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
+ <Button Name="ContentTogglePane" Style="{ThemeResource PaneButton}" Foreground="{TemplateBinding ToolbarForeground}" Visibility="{Binding ElementName=SplitView,Path=IsPaneOpen,Converter={StaticResource InvertedBoolVisibilityConverter}}" />
+ <ContentControl VerticalAlignment="Top" VerticalContentAlignment="Center" Height="{StaticResource TitleBarHeight}">
+ <TextBlock Text="{TemplateBinding DetailTitle}" Margin="10,0,0,0" Foreground="{TemplateBinding ToolbarForeground}" Style="{ThemeResource TitleTextBlockStyle}" />
+ </ContentControl>
+ </StackPanel>
+ </uwp:FormsCommandBar.Content>
+ </uwp:FormsCommandBar>
+
+ <ContentPresenter x:Name="DetailPresenter" Grid.Row="1" Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Detail}" />
+ </Grid>
+ </SplitView.Content>
+ </SplitView>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="FormsListViewItem" TargetType="ListViewItem">
+ <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
+ <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
+ <Setter Property="Background" Value="Transparent" />
+ <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
+ <Setter Property="TabNavigation" Value="Local" />
+ <Setter Property="IsHoldingEnabled" Value="True" />
+ <Setter Property="Padding" Value="0" />
+ <Setter Property="HorizontalContentAlignment" Value="Stretch" />
+ <Setter Property="VerticalContentAlignment" Value="Center" />
+ <Setter Property="MinWidth" Value="{ThemeResource ListViewItemMinWidth}" />
+ <Setter Property="MinHeight" Value="0" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="ListViewItem">
+ <ListViewItemPresenter
+ CheckBrush="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
+ ContentMargin="{TemplateBinding Padding}"
+ CheckMode="Inline"
+ ContentTransitions="{TemplateBinding ContentTransitions}"
+ CheckBoxBrush="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
+ DragForeground="{ThemeResource ListViewItemDragForegroundThemeBrush}"
+ DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}"
+ DragBackground="{ThemeResource ListViewItemDragBackgroundThemeBrush}"
+ DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}"
+ FocusBorderBrush="{ThemeResource SystemControlForegroundAltHighBrush}"
+ FocusSecondaryBorderBrush="{ThemeResource SystemControlForegroundBaseHighBrush}"
+ HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
+ PointerOverForeground="{ThemeResource SystemControlHighlightAltBaseHighBrush}"
+ PressedBackground="{ThemeResource SystemControlHighlightListMediumBrush}"
+ PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}"
+ PointerOverBackground="{ThemeResource SystemControlHighlightListLowBrush}"
+ ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
+ SelectedPressedBackground="{ThemeResource SystemControlHighlightListAccentHighBrush}"
+ SelectionCheckMarkVisualEnabled="True"
+ SelectedForeground="{ThemeResource SystemControlHighlightAltBaseHighBrush}"
+ SelectedPointerOverBackground="{ThemeResource SystemControlHighlightListAccentMediumBrush}"
+ SelectedBackground="{ThemeResource SystemControlHighlightListAccentLowBrush}"
+ VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ <Style x:Key="FormsCarouselViewItem" TargetType="FlipViewItem">
+ <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
+ <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
+ <Setter Property="Background" Value="Transparent" />
+ <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
+ <Setter Property="TabNavigation" Value="Local" />
+ <Setter Property="IsHoldingEnabled" Value="True" />
+ <Setter Property="Padding" Value="0" />
+ <Setter Property="HorizontalContentAlignment" Value="Stretch" />
+ <Setter Property="VerticalContentAlignment" Value="Center" />
+ <Setter Property="MinWidth" Value="{ThemeResource ListViewItemMinWidth}" />
+ <Setter Property="MinHeight" Value="0" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="ListViewItem">
+ <ListViewItemPresenter
+ CheckBrush="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
+ ContentMargin="{TemplateBinding Padding}"
+ CheckMode="Inline"
+ ContentTransitions="{TemplateBinding ContentTransitions}"
+ CheckBoxBrush="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
+ DragForeground="{ThemeResource ListViewItemDragForegroundThemeBrush}"
+ DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}"
+ DragBackground="{ThemeResource ListViewItemDragBackgroundThemeBrush}"
+ DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}"
+ FocusBorderBrush="{ThemeResource SystemControlForegroundAltHighBrush}"
+ FocusSecondaryBorderBrush="{ThemeResource SystemControlForegroundBaseHighBrush}"
+ HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
+ PointerOverForeground="{ThemeResource SystemControlHighlightAltBaseHighBrush}"
+ PressedBackground="{ThemeResource SystemControlHighlightListMediumBrush}"
+ PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}"
+ PointerOverBackground="{ThemeResource SystemControlHighlightListLowBrush}"
+ ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
+ SelectedPressedBackground="{ThemeResource SystemControlHighlightListAccentHighBrush}"
+ SelectionCheckMarkVisualEnabled="True"
+ SelectedForeground="{ThemeResource SystemControlHighlightAltBaseHighBrush}"
+ SelectedPointerOverBackground="{ThemeResource SystemControlHighlightListAccentMediumBrush}"
+ SelectedBackground="{ThemeResource SystemControlHighlightListAccentLowBrush}"
+ VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <DataTemplate x:Key="TextCell">
+ <StackPanel>
+ <TextBlock
+ Text="{Binding Text}"
+ Style="{ThemeResource BaseTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding TextColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}" />
+
+ <TextBlock
+ Text="{Binding Detail}"
+ Style="{ThemeResource BodyTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding DetailColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}"
+ x:Name="detail"/>
+ </StackPanel>
+ </DataTemplate>
+
+ <DataTemplate x:Key="ListViewHeaderTextCell">
+ <StackPanel>
+ <TextBlock
+ Text="{Binding Text}"
+ Style="{ThemeResource SubheaderTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding TextColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}" />
+
+ <TextBlock
+ Text="{Binding Detail}"
+ Style="{ThemeResource BodyTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding DetailColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}"
+ x:Name="detail" />
+ </StackPanel>
+ </DataTemplate>
+
+ <DataTemplate x:Key="ImageCell">
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition />
+ </Grid.ColumnDefinitions>
+
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ </Grid.RowDefinitions>
+
+ <Image Grid.Column="0" Grid.RowSpan="2"
+ DataContext="{Binding ImageSource, Converter={StaticResource ImageConverter}}"
+ Source="{Binding Value}"
+ VerticalAlignment="Center" />
+
+ <TextBlock Grid.Column="1" Grid.Row="0"
+ Text="{Binding Text}"
+ Style="{ThemeResource BaseTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding TextColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}" />
+
+ <TextBlock Grid.Column="1" Grid.Row="1"
+ Text="{Binding Detail}"
+ Style="{ThemeResource BodyTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding DetailColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}"
+ x:Name="detail" />
+ </Grid>
+ </DataTemplate>
+
+ <DataTemplate x:Key="SwitchCell">
+ <Grid HorizontalAlignment="Stretch">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="Auto" />
+ </Grid.ColumnDefinitions>
+
+ <TextBlock Grid.Column="0" Text="{Binding Text}" VerticalAlignment="Center" Style="{ThemeResource BaseTextBlockStyle}" />
+
+ <ToggleSwitch Grid.Column="1" IsOn="{Binding On, Mode=TwoWay}" OnContent="" OffContent="" VerticalAlignment="Center" />
+ </Grid>
+ </DataTemplate>
+
+ <DataTemplate x:Key="EntryCell">
+ <uwp:EntryCellTextBox IsEnabled="{Binding IsEnabled}" Header="{Binding}" Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" TextAlignment="{Binding HorizontalTextAlignment,Converter={StaticResource HorizontalTextAlignmentConverter}}" PlaceholderText="{Binding Placeholder}" InputScope="{Binding Keyboard,Converter={StaticResource KeyboardConverter}}" HorizontalAlignment="Stretch">
+ <uwp:EntryCellTextBox.HeaderTemplate>
+ <DataTemplate>
+ <TextBlock Text="{Binding Label}" Style="{ThemeResource BaseTextBlockStyle}" Foreground="{Binding LabelColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}" />
+ </DataTemplate>
+ </uwp:EntryCellTextBox.HeaderTemplate>
+ </uwp:EntryCellTextBox>
+ </DataTemplate>
+
+ <Style x:Key="TabbedPageStyle" TargetType="uwp:FormsPivot">
+ <Setter Property="HeaderTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <TextBlock Text="{Binding Title}" Style="{ThemeResource BodyTextBlockStyle}" />
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+
+ <Setter Property="ItemTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <uwp:TabbedPagePresenter Content="{Binding}" ContentTemplate="{ThemeResource ContainedPageTemplate}" />
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="uwp:FormsPivot">
+ <Grid x:Name="RootElement" Background="{TemplateBinding Background}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="NavigationButtonsVisibility">
+ <VisualState x:Name="NavigationButtonsHidden"/>
+ <VisualState x:Name="NavigationButtonsVisible">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="NextButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsEnabled" Storyboard.TargetName="NextButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="True"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PreviousButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsEnabled" Storyboard.TargetName="PreviousButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="True"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="HeaderStates">
+ <VisualState x:Name="HeaderDynamic"/>
+ <VisualState x:Name="HeaderStatic">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="Header">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="StaticHeader">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <uwp:FormsCommandBar x:Name="CommandBar" Grid.Row="0" VerticalContentAlignment="Top" Background="{TemplateBinding ToolbarBackground}" Visibility="{TemplateBinding ToolbarVisibility}" >
+ <uwp:FormsCommandBar.Content>
+ <ContentControl VerticalAlignment="Top" VerticalContentAlignment="Center" Height="{ThemeResource TitleBarHeight}" >
+ <TextBlock Text="{TemplateBinding Title}" VerticalAlignment="Center" Padding="10,0,0,0" Foreground="{TemplateBinding ToolbarForeground}" Style="{ThemeResource TitleTextBlockStyle}" />
+ </ContentControl>
+ </uwp:FormsCommandBar.Content>
+ </uwp:FormsCommandBar>
+ <Grid Grid.Row="1">
+ <Grid.Resources>
+ <ControlTemplate x:Key="NextTemplate" TargetType="Button">
+ <Border x:Name="Root" BorderBrush="{ThemeResource SystemControlForegroundTransparentBrush}" BorderThickness="{ThemeResource PivotNavButtonBorderThemeThickness}" Background="{ThemeResource SystemControlBackgroundBaseMediumLowBrush}">
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal"/>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Root">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="Arrow">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltAltMediumHighBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Root">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumHighBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="Arrow">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltAltMediumHighBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <FontIcon x:Name="Arrow" Foreground="{ThemeResource SystemControlForegroundAltMediumHighBrush}" FontSize="12" FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="&#xE0E3;" HorizontalAlignment="Center" MirroredWhenRightToLeft="True" UseLayoutRounding="False" VerticalAlignment="Center"/>
+ </Border>
+ </ControlTemplate>
+ <ControlTemplate x:Key="PreviousTemplate" TargetType="Button">
+ <Border x:Name="Root" BorderBrush="{ThemeResource SystemControlForegroundTransparentBrush}" BorderThickness="{ThemeResource PivotNavButtonBorderThemeThickness}" Background="{ThemeResource SystemControlBackgroundBaseMediumLowBrush}">
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal"/>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Root">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="Arrow">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltAltMediumHighBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Root">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumHighBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="Arrow">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltAltMediumHighBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <FontIcon x:Name="Arrow" Foreground="{ThemeResource SystemControlForegroundAltMediumHighBrush}" FontSize="12" FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="&#xE0E2;" HorizontalAlignment="Center" MirroredWhenRightToLeft="True" UseLayoutRounding="False" VerticalAlignment="Center"/>
+ </Border>
+ </ControlTemplate>
+ </Grid.Resources>
+ <ScrollViewer x:Name="ScrollViewer" BringIntoViewOnFocusChange="False" HorizontalSnapPointsAlignment="Center" HorizontalSnapPointsType="MandatorySingle" HorizontalScrollBarVisibility="Hidden" Margin="{TemplateBinding Padding}" Template="{StaticResource ScrollViewerScrollBarlessTemplate}" VerticalSnapPointsType="None" VerticalScrollBarVisibility="Disabled" VerticalScrollMode="Disabled" VerticalContentAlignment="Stretch" ZoomMode="Disabled">
+ <PivotPanel x:Name="Panel" VerticalAlignment="Stretch">
+ <Grid x:Name="PivotLayoutElement">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ <ColumnDefinition Width="Auto"/>
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+ <Grid.RenderTransform>
+ <CompositeTransform x:Name="PivotLayoutElementTranslateTransform"/>
+ </Grid.RenderTransform>
+ <ContentPresenter x:Name="LeftHeaderPresenter" ContentTemplate="{TemplateBinding LeftHeaderTemplate}" Content="{TemplateBinding LeftHeader}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
+ <ContentControl x:Name="HeaderClipper" Grid.Column="1" HorizontalContentAlignment="Stretch" UseSystemFocusVisuals="True">
+ <ContentControl.Clip>
+ <RectangleGeometry x:Name="HeaderClipperGeometry"/>
+ </ContentControl.Clip>
+ <Grid Background="Transparent">
+ <PivotHeaderPanel x:Name="StaticHeader" Visibility="Collapsed"/>
+ <PivotHeaderPanel x:Name="Header">
+ <PivotHeaderPanel.RenderTransform>
+ <TransformGroup>
+ <CompositeTransform x:Name="HeaderTranslateTransform"/>
+ <CompositeTransform x:Name="HeaderOffsetTranslateTransform"/>
+ </TransformGroup>
+ </PivotHeaderPanel.RenderTransform>
+ </PivotHeaderPanel>
+ </Grid>
+ </ContentControl>
+ <Button x:Name="PreviousButton" Background="Transparent" Grid.Column="1" HorizontalAlignment="Left" Height="36" IsTabStop="False" IsEnabled="False" Margin="{ThemeResource PivotNavButtonMargin}" Opacity="0" Template="{StaticResource PreviousTemplate}" UseSystemFocusVisuals="False" VerticalAlignment="Top" Width="20"/>
+ <Button x:Name="NextButton" Background="Transparent" Grid.Column="1" HorizontalAlignment="Right" Height="36" IsTabStop="False" IsEnabled="False" Margin="{ThemeResource PivotNavButtonMargin}" Opacity="0" Template="{StaticResource NextTemplate}" UseSystemFocusVisuals="False" VerticalAlignment="Top" Width="20"/>
+ <ContentPresenter x:Name="RightHeaderPresenter" ContentTemplate="{TemplateBinding RightHeaderTemplate}" Content="{TemplateBinding RightHeader}" Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
+ <ItemsPresenter x:Name="PivotItemPresenter" Grid.ColumnSpan="3" Grid.Row="1">
+ <ItemsPresenter.RenderTransform>
+ <TransformGroup>
+ <TranslateTransform x:Name="ItemsPresenterTranslateTransform"/>
+ <CompositeTransform x:Name="ItemsPresenterCompositeTransform"/>
+ </TransformGroup>
+ </ItemsPresenter.RenderTransform>
+ </ItemsPresenter>
+ </Grid>
+ </PivotPanel>
+ </ScrollViewer>
+ </Grid>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="PageControlDefaultStyle" TargetType="uwp:PageControl">
+ <Setter Property="ContentMargin" Value="0" />
+ <Setter Property="TitleBrush" Value="{ThemeResource DefaultTextForegroundThemeBrush}" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="uwp:PageControl">
+ <Grid Background="{TemplateBinding Background}">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+
+ <uwp:FormsCommandBar x:Name="CommandBar" Grid.Row="0" VerticalContentAlignment="Top" Background="{TemplateBinding NavigationBarBackground}" Visibility="{Binding ShowNavigationBar,RelativeSource={RelativeSource Mode=TemplatedParent},Converter={StaticResource BoolVisibilityConverter}}">
+ <uwp:FormsCommandBar.Content>
+ <ContentControl VerticalAlignment="Top" VerticalContentAlignment="Center" Height="{ThemeResource TitleBarHeight}">
+ <TextBlock Text="{Binding Title}" VerticalAlignment="Center" Padding="10,0,0,0" Foreground="{TemplateBinding TitleBrush}" Style="{ThemeResource TitleTextBlockStyle}" />
+ </ContentControl>
+ </uwp:FormsCommandBar.Content>
+ </uwp:FormsCommandBar>
+
+ <ContentPresenter Margin="{TemplateBinding ContentMargin}" ContentTransitions="{TemplateBinding ContentTransitions}" x:Name="presenter" Grid.Row="1" />
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style TargetType="uwp:StepperControl">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Grid HorizontalAlignment="Left">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+
+ <Button Name="Minus" Grid.Column="0" Content="-" />
+ <Button Name="Plus" Grid.Column="1" Content="+" />
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style TargetType="uwp:PageControl" BasedOn="{StaticResource PageControlDefaultStyle}" />
+
+ <Style TargetType="TextBox">
+ <Setter Property="Margin" Value="0" />
+ </Style>
+
+ <Style TargetType="ToggleSwitch">
+ <Setter Property="MinWidth" Value="0"/>
+ </Style>
+
+ <SolidColorBrush x:Key="FormsCancelForegroundBrush" />
+ <SolidColorBrush x:Key="FormsCancelBackgroundBrush" />
+
+ <!-- Default Style for AutoSuggestBox -->
+ <Style TargetType="AutoSuggestBox">
+ <Setter Property="VerticalAlignment" Value="Top" />
+ <Setter Property="IsTabStop" Value="False" />
+ <Setter Property="TextBoxStyle" Value="{StaticResource AutoSuggestBoxTextBoxStyle}" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="AutoSuggestBox">
+ <Grid>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="Orientation">
+ <VisualState x:Name="Landscape"/>
+ <VisualState x:Name="Portrait"/>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <uwp:FormsTextBox x:Name="TextBox"
+ Style="{TemplateBinding TextBoxStyle}"
+ FontFamily="{TemplateBinding FontFamily}"
+ FontSize="{TemplateBinding FontSize}"
+ FontStyle="{TemplateBinding FontStyle}"
+ PlaceholderText="{TemplateBinding PlaceholderText}"
+ Header="{TemplateBinding Header}"
+ Width="{TemplateBinding Width}"
+ ScrollViewer.BringIntoViewOnFocusChange="False"
+ Canvas.ZIndex="0"
+ Margin="0"
+ DesiredCandidateWindowAlignment="BottomEdge"/>
+ <Popup x:Name="SuggestionsPopup">
+ <Border x:Name="SuggestionsContainer">
+ <Border.RenderTransform>
+ <TranslateTransform x:Name="UpwardTransform"/>
+ </Border.RenderTransform>
+ <ListView x:Name="SuggestionsList"
+ Background="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}"
+ BorderThickness="{ThemeResource AutoSuggestListBorderThemeThickness}"
+ BorderBrush="{ThemeResource SystemControlForegroundBaseMediumLowBrush}"
+ DisplayMemberPath="{TemplateBinding DisplayMemberPath}"
+ IsItemClickEnabled="True"
+ ItemTemplate="{TemplateBinding ItemTemplate}"
+ ItemTemplateSelector="{TemplateBinding ItemTemplateSelector}"
+ ItemContainerStyle="{TemplateBinding ItemContainerStyle}"
+ MaxHeight="{ThemeResource AutoSuggestListMaxHeight}"
+ Margin="{ThemeResource AutoSuggestListMargin}">
+ <ListView.ItemContainerTransitions>
+ <TransitionCollection />
+ </ListView.ItemContainerTransitions>
+ </ListView>
+ </Border>
+ </Popup>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style TargetType="uwp:FormsTextBox" x:Key="AutoSuggestBoxTextBoxStyle">
+ <Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
+ <Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
+ <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
+ <Setter Property="ForegroundFocusBrush" Value="{ThemeResource SystemControlForegroundChromeBlackHighBrush}" />
+ <Setter Property="PlaceholderForegroundBrush" Value="{ThemeResource SystemControlPageTextBaseMediumBrush}" />
+ <Setter Property="PlaceholderForegroundFocusBrush" Value="{ThemeResource SystemControlPageTextChromeBlackMediumLowBrush}" />
+ <Setter Property="Background" Value="{ThemeResource SystemControlBackgroundAltHighBrush}" />
+ <Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundChromeDisabledLowBrush}" />
+ <Setter Property="SelectionHighlightColor" Value="{ThemeResource SystemControlHighlightAccentBrush}" />
+ <Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
+ <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
+ <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
+ <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
+ <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
+ <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
+ <Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="uwp:FormsTextBox">
+ <Grid>
+ <Grid.Resources>
+ <Style x:Name="DeleteButtonStyle" TargetType="Button">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="Button">
+ <Grid>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal" />
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
+ Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource FormsCancelBackgroundBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
+ Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltChromeWhiteBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <DoubleAnimation Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="Opacity"
+ To="0"
+ Duration="0" />
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Border x:Name="BorderElement"
+ BorderBrush="{ThemeResource TextBoxButtonBorderThemeBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}"
+ Background="{ThemeResource FormsCancelBackgroundBrush}">
+ <TextBlock x:Name="GlyphElement"
+ Foreground="{ThemeResource FormsCancelForegroundBrush}"
+ VerticalAlignment="Center"
+ HorizontalAlignment="Center"
+ FontStyle="Normal"
+ FontSize="12"
+ Text="&#xE10A;"
+ FontFamily="{ThemeResource SymbolThemeFontFamily}"
+ AutomationProperties.AccessibilityView="Raw"/>
+ </Border>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ <Style x:Name="QueryButtonStyle" TargetType="Button">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="Button">
+ <Grid>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal" />
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
+ Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltAccentBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
+ Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltChromeWhiteBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <DoubleAnimation Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="Opacity"
+ To="0"
+ Duration="0" />
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Border x:Name="BorderElement"
+ BorderBrush="{ThemeResource TextBoxButtonBorderThemeBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}"
+ Background="{ThemeResource TextBoxButtonBackgroundThemeBrush}">
+ <ContentPresenter x:Name="ContentPresenter"
+ Content="{TemplateBinding Content}"
+ ContentTransitions="{TemplateBinding ContentTransitions}"
+ ContentTemplate="{TemplateBinding ContentTemplate}"
+ Margin="{TemplateBinding Padding}"
+ HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
+ VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
+ AutomationProperties.AccessibilityView="Raw"/>
+ </Border>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ </Grid.Resources>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter"
+ Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
+ Storyboard.TargetProperty="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledTransparentBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="BorderBrush">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement"
+ Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledChromeDisabledLowBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter"
+ Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledChromeDisabledLowBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Normal" />
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="BorderBrush">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightChromeAltLowBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
+ Storyboard.TargetProperty="Opacity">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundHoverOpacity}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Focused">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter"
+ Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding PlaceholderForegroundFocusBrush, RelativeSource={RelativeSource TemplatedParent}}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
+ Storyboard.TargetProperty="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundChromeWhiteBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
+ Storyboard.TargetProperty="Opacity">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundFocusedOpacity}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="BorderBrush">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement"
+ Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding ForegroundFocusBrush, RelativeSource={RelativeSource TemplatedParent}}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement"
+ Storyboard.TargetProperty="RequestedTheme">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Light" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="QueryButton"
+ Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundChromeBlackMediumBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="ButtonStates">
+ <VisualState x:Name="ButtonVisible">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="DeleteButton"
+ Storyboard.TargetProperty="Visibility">
+ <DiscreteObjectKeyFrame KeyTime="0">
+ <DiscreteObjectKeyFrame.Value>
+ <Visibility>Visible</Visibility>
+ </DiscreteObjectKeyFrame.Value>
+ </DiscreteObjectKeyFrame>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="ButtonCollapsed" />
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="Auto" />
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+ <Border x:Name="BackgroundElement"
+ Grid.Row="1"
+ Background="{TemplateBinding Background}"
+ Margin="{TemplateBinding BorderThickness}"
+ Opacity="{ThemeResource TextControlBackgroundRestOpacity}"
+ Grid.ColumnSpan="3"
+ Grid.RowSpan="1"/>
+ <Border x:Name="BorderElement"
+ Grid.Row="1"
+ BorderBrush="{TemplateBinding BorderBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}"
+ Grid.ColumnSpan="3"
+ Grid.RowSpan="1"/>
+ <ContentPresenter x:Name="HeaderContentPresenter"
+ x:DeferLoadStrategy="Lazy"
+ Visibility="Collapsed"
+ Grid.Row="0"
+ Foreground="{Binding PlaceholderForegroundBrush, RelativeSource={RelativeSource TemplatedParent}}"
+ Margin="0,0,0,8"
+ Grid.ColumnSpan="3"
+ Content="{TemplateBinding Header}"
+ ContentTemplate="{TemplateBinding HeaderTemplate}"
+ FontWeight="Normal"
+ TextWrapping="Wrap" />
+ <ScrollViewer x:Name="ContentElement"
+ Grid.Row="1"
+ HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
+ HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
+ VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
+ VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
+ IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
+ IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
+ IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
+ Margin="{TemplateBinding BorderThickness}"
+ Padding="{TemplateBinding Padding}"
+ IsTabStop="False"
+ AutomationProperties.AccessibilityView="Raw"
+ ZoomMode="Disabled" />
+ <!-- Converting the TextAlignment set for the control's input text to a HorizontalAlignment
+ so the PlaceholderText's alignment will match the input text -->
+ <ContentControl x:Name="PlaceholderTextContentPresenter"
+ Grid.Row="1"
+ Foreground="{Binding PlaceholderForegroundBrush, RelativeSource={RelativeSource TemplatedParent}}"
+ Margin="{TemplateBinding BorderThickness}"
+ Padding="{TemplateBinding Padding}"
+ IsTabStop="False"
+ Grid.ColumnSpan="3"
+ Content="{TemplateBinding PlaceholderText}"
+ FontFamily="{TemplateBinding FontFamily}"
+ FontSize="{TemplateBinding FontSize}"
+ FontStyle="{TemplateBinding FontStyle}"
+ IsHitTestVisible="False"
+ HorizontalAlignment="{Binding TextAlignment,
+ RelativeSource={RelativeSource Mode=TemplatedParent},
+ Converter={StaticResource AlignmentConverter}}" />
+ <Button x:Name="DeleteButton"
+ Grid.Row="1"
+ Style="{StaticResource DeleteButtonStyle}"
+ BorderThickness="{TemplateBinding BorderThickness}"
+ Margin="{ThemeResource HelperButtonThemePadding}"
+ IsTabStop="False"
+ Grid.Column="1"
+ Visibility="Collapsed"
+ FontSize="{TemplateBinding FontSize}"
+ MinWidth="34"
+ VerticalAlignment="Stretch"/>
+ <Button x:Name="QueryButton"
+ Grid.Row="1"
+ Style="{StaticResource QueryButtonStyle}"
+ BorderThickness="{TemplateBinding BorderThickness}"
+ Margin="{ThemeResource HelperButtonThemePadding}"
+ IsTabStop="False"
+ Grid.Column="2"
+ FontSize="{TemplateBinding FontSize}"
+ MinWidth="34"
+ VerticalAlignment="Stretch"/>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+</ResourceDictionary> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.UAP/SearchBarRenderer.cs b/Xamarin.Forms.Platform.UAP/SearchBarRenderer.cs
new file mode 100644
index 00000000..6ec13e1b
--- /dev/null
+++ b/Xamarin.Forms.Platform.UAP/SearchBarRenderer.cs
@@ -0,0 +1,208 @@
+using System.ComponentModel;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+
+namespace Xamarin.Forms.Platform.UWP
+{
+ public class SearchBarRenderer : ViewRenderer<SearchBar, AutoSuggestBox>
+ {
+ Brush _defaultPlaceholderColorBrush;
+ Brush _defaultPlaceholderColorFocusBrush;
+ Brush _defaultTextColorBrush;
+ Brush _defaultTextColorFocusBrush;
+
+ bool _fontApplied;
+
+ FormsTextBox _queryTextBox;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
+ {
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new AutoSuggestBox { QueryIcon = new SymbolIcon(Symbol.Find) });
+ Control.QuerySubmitted += OnQuerySubmitted;
+ Control.TextChanged += OnTextChanged;
+ Control.Loaded += OnControlLoaded;
+ }
+
+ UpdateText();
+ UpdatePlaceholder();
+ UpdateCancelButtonColor();
+ UpdateAlignment();
+ UpdateFont();
+ UpdateTextColor();
+ UpdatePlaceholderColor();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == SearchBar.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == SearchBar.PlaceholderProperty.PropertyName)
+ UpdatePlaceholder();
+ else if (e.PropertyName == SearchBar.CancelButtonColorProperty.PropertyName)
+ UpdateCancelButtonColor();
+ else if (e.PropertyName == SearchBar.HorizontalTextAlignmentProperty.PropertyName)
+ UpdateAlignment();
+ else if (e.PropertyName == SearchBar.FontAttributesProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == SearchBar.FontFamilyProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == SearchBar.FontSizeProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == SearchBar.TextColorProperty.PropertyName)
+ UpdateTextColor();
+ else if (e.PropertyName == SearchBar.PlaceholderColorProperty.PropertyName)
+ UpdatePlaceholderColor();
+ }
+
+ void OnControlLoaded(object sender, RoutedEventArgs routedEventArgs)
+ {
+ _queryTextBox = Control.GetFirstDescendant<FormsTextBox>();
+
+ UpdateAlignment();
+ UpdateTextColor();
+ UpdatePlaceholderColor();
+ }
+
+ void OnQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs e)
+ {
+ Element.OnSearchButtonPressed();
+ }
+
+ void OnTextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs e)
+ {
+ if (e.Reason == AutoSuggestionBoxTextChangeReason.ProgrammaticChange)
+ return;
+
+ ((IElementController)Element).SetValueFromRenderer(SearchBar.TextProperty, sender.Text);
+ }
+
+ void UpdateAlignment()
+ {
+ if (_queryTextBox == null)
+ return;
+
+ _queryTextBox.TextAlignment = Element.HorizontalTextAlignment.ToNativeTextAlignment();
+ }
+
+ void UpdateCancelButtonColor()
+ {
+ var foregroundBrush = Windows.UI.Xaml.Application.Current.Resources["FormsCancelForegroundBrush"] as SolidColorBrush;
+ var backgroundBrush = Windows.UI.Xaml.Application.Current.Resources["FormsCancelBackgroundBrush"] as SolidColorBrush;
+
+ Color cancelColor = Element.CancelButtonColor;
+
+ if (cancelColor.IsDefault)
+ {
+ backgroundBrush.Color = (Windows.UI.Xaml.Application.Current.Resources["TextBoxButtonBackgroundThemeBrush"] as SolidColorBrush).Color;
+ foregroundBrush.Color = (Windows.UI.Xaml.Application.Current.Resources["SystemControlBackgroundChromeBlackMediumBrush"] as SolidColorBrush).Color;
+ }
+ else
+ {
+ Windows.UI.Color newColor = cancelColor.ToWindowsColor();
+ backgroundBrush.Color = newColor;
+ foregroundBrush.Color = newColor.GetIdealForegroundForBackgroundColor();
+ }
+ }
+
+ void UpdateFont()
+ {
+ if (Control == null)
+ return;
+
+ SearchBar searchBar = Element;
+
+ if (searchBar == null)
+ return;
+
+ bool searchBarIsDefault = searchBar.FontFamily == null && searchBar.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(SearchBar), true) && searchBar.FontAttributes == FontAttributes.None;
+
+ if (searchBarIsDefault && !_fontApplied)
+ return;
+
+ if (searchBarIsDefault)
+ {
+ Control.ClearValue(Windows.UI.Xaml.Controls.Control.FontStyleProperty);
+ Control.ClearValue(Windows.UI.Xaml.Controls.Control.FontSizeProperty);
+ Control.ClearValue(Windows.UI.Xaml.Controls.Control.FontFamilyProperty);
+ Control.ClearValue(Windows.UI.Xaml.Controls.Control.FontWeightProperty);
+ Control.ClearValue(Windows.UI.Xaml.Controls.Control.FontStretchProperty);
+ }
+ else
+ Control.ApplyFont(searchBar);
+
+ _fontApplied = true;
+ }
+
+ void UpdatePlaceholder()
+ {
+ Control.PlaceholderText = Element.Placeholder ?? string.Empty;
+ }
+
+ void UpdatePlaceholderColor()
+ {
+ if (_queryTextBox == null)
+ return;
+
+ Color placeholderColor = Element.PlaceholderColor;
+
+ if (placeholderColor.IsDefault)
+ {
+ if (_defaultPlaceholderColorBrush == null)
+ return;
+
+ _queryTextBox.PlaceholderForegroundBrush = _defaultPlaceholderColorBrush;
+ _queryTextBox.PlaceholderForegroundBrush = _defaultPlaceholderColorFocusBrush;
+ }
+
+ if (_defaultPlaceholderColorBrush == null)
+ {
+ _defaultPlaceholderColorBrush = _queryTextBox.PlaceholderForegroundBrush;
+ _defaultPlaceholderColorFocusBrush = _queryTextBox.PlaceholderForegroundFocusBrush;
+ }
+
+ _queryTextBox.PlaceholderForegroundBrush = placeholderColor.ToBrush();
+ _queryTextBox.PlaceholderForegroundFocusBrush = placeholderColor.ToBrush();
+ }
+
+ void UpdateText()
+ {
+ Control.Text = Element.Text ?? string.Empty;
+ }
+
+ void UpdateTextColor()
+ {
+ if (_queryTextBox == null)
+ return;
+
+ Color textColor = Element.TextColor;
+
+ if (textColor.IsDefault)
+ {
+ if (_defaultTextColorBrush == null)
+ return;
+
+ _queryTextBox.Foreground = _defaultTextColorBrush;
+ _queryTextBox.ForegroundFocusBrush = _defaultTextColorFocusBrush;
+ }
+
+ if (_defaultTextColorBrush == null)
+ {
+ _defaultTextColorBrush = _queryTextBox.Foreground;
+ _defaultTextColorFocusBrush = _queryTextBox.ForegroundFocusBrush;
+ }
+
+ _queryTextBox.Foreground = textColor.ToBrush();
+ _queryTextBox.ForegroundFocusBrush = textColor.ToBrush();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.UAP/StepperControl.cs b/Xamarin.Forms.Platform.UAP/StepperControl.cs
new file mode 100644
index 00000000..0de09318
--- /dev/null
+++ b/Xamarin.Forms.Platform.UAP/StepperControl.cs
@@ -0,0 +1,227 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+
+namespace Xamarin.Forms.Platform.UWP
+{
+ public sealed class StepperControl : Control
+ {
+ public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(StepperControl), new PropertyMetadata(default(double), OnValueChanged));
+
+ public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(double), typeof(StepperControl), new PropertyMetadata(default(double), OnMaxMinChanged));
+
+ public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum", typeof(double), typeof(StepperControl), new PropertyMetadata(default(double), OnMaxMinChanged));
+
+ public static readonly DependencyProperty IncrementProperty = DependencyProperty.Register("Increment", typeof(double), typeof(StepperControl),
+ new PropertyMetadata(default(double), OnIncrementChanged));
+
+ Windows.UI.Xaml.Controls.Button _plus;
+ Windows.UI.Xaml.Controls.Button _minus;
+ VisualStateCache _plusStateCache;
+ VisualStateCache _minusStateCache;
+
+ public StepperControl()
+ {
+ DefaultStyleKey = typeof(StepperControl);
+ }
+
+ public double Increment
+ {
+ get { return (double)GetValue(IncrementProperty); }
+ set { SetValue(IncrementProperty, value); }
+ }
+
+ public double Maximum
+ {
+ get { return (double)GetValue(MaximumProperty); }
+ set { SetValue(MaximumProperty, value); }
+ }
+
+ public double Minimum
+ {
+ get { return (double)GetValue(MinimumProperty); }
+ set { SetValue(MinimumProperty, value); }
+ }
+
+ public double Value
+ {
+ get { return (double)GetValue(ValueProperty); }
+ set { SetValue(ValueProperty, value); }
+ }
+
+ public event EventHandler ValueChanged;
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ _plus = GetTemplateChild("Plus") as Windows.UI.Xaml.Controls.Button;
+ if (_plus != null)
+ _plus.Click += OnPlusClicked;
+
+ _minus = GetTemplateChild("Minus") as Windows.UI.Xaml.Controls.Button;
+ if (_minus != null)
+ _minus.Click += OnMinusClicked;
+
+ UpdateEnabled(Value);
+ }
+
+ static void OnIncrementChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var stepper = (StepperControl)d;
+ stepper.UpdateEnabled(stepper.Value);
+ }
+
+ static void OnMaxMinChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var stepper = (StepperControl)d;
+ stepper.UpdateEnabled(stepper.Value);
+ }
+
+ void OnMinusClicked(object sender, RoutedEventArgs e)
+ {
+ UpdateValue(-Increment);
+ }
+
+ void OnPlusClicked(object sender, RoutedEventArgs e)
+ {
+ UpdateValue(+Increment);
+ }
+
+ static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var stepper = (StepperControl)d;
+ stepper.UpdateEnabled((double)e.NewValue);
+
+ EventHandler changed = stepper.ValueChanged;
+ if (changed != null)
+ changed(d, EventArgs.Empty);
+ }
+
+ VisualStateCache PseudoDisable(Control control)
+ {
+ if (VisualTreeHelper.GetChildrenCount(control) == 0)
+ control.ApplyTemplate();
+
+ VisualStateManager.GoToState(control, "Disabled", true);
+
+ var rootElement = (FrameworkElement)VisualTreeHelper.GetChild(control, 0);
+
+ var cache = new VisualStateCache();
+ IList<VisualStateGroup> groups = VisualStateManager.GetVisualStateGroups(rootElement);
+
+ VisualStateGroup common = null;
+ foreach (var group in groups)
+ {
+ if (group.Name == "CommonStates")
+ common = group;
+ else if (group.Name == "FocusStates")
+ cache.FocusStates = group;
+ else if (cache.FocusStates != null && common != null)
+ break;
+ }
+
+ if (cache.FocusStates != null)
+ groups.Remove(cache.FocusStates);
+
+ if (common != null)
+ {
+ foreach (VisualState state in common.States)
+ {
+ if (state.Name == "Normal")
+ cache.Normal = state;
+ else if (state.Name == "Pressed")
+ cache.Pressed = state;
+ else if (state.Name == "PointerOver")
+ cache.PointerOver = state;
+ }
+
+ if (cache.Normal != null)
+ common.States.Remove(cache.Normal);
+ if (cache.Pressed != null)
+ common.States.Remove(cache.Pressed);
+ if (cache.PointerOver != null)
+ common.States.Remove(cache.PointerOver);
+ }
+
+ return cache;
+ }
+
+ /*
+ The below serves as a way to disable the button visually, rather than using IsEnabled. It's a hack
+ but should remain stable as long as the user doesn't change the WinRT Button template too much.
+
+ The reason we're not using IsEnabled is that the buttons have a click radius that overlap about 40%
+ of the next button. This doesn't cause a problem until one button becomes disabled, then if you think
+ you're still hitting + (haven't noticed its disabled), you will actually hit -. This hack doesn't
+ completely solve the problem, but it drops the overlap to something like 20%. I haven't found the root
+ cause, so this will have to suffice for now.
+ */
+
+ void PsuedoEnable(Control control, ref VisualStateCache cache)
+ {
+ if (cache == null || VisualTreeHelper.GetChildrenCount(control) == 0)
+ return;
+
+ var rootElement = (FrameworkElement)VisualTreeHelper.GetChild(control, 0);
+
+ IList<VisualStateGroup> groups = VisualStateManager.GetVisualStateGroups(rootElement);
+
+ if (cache.FocusStates != null)
+ groups.Add(cache.FocusStates);
+
+ var commonStates = groups.FirstOrDefault(g => g.Name == "CommonStates");
+ if (commonStates == null)
+ return;
+
+ if (cache.Normal != null)
+ commonStates.States.Insert(0, cache.Normal); // defensive
+ if (cache.Pressed != null)
+ commonStates.States.Add(cache.Pressed);
+ if (cache.PointerOver != null)
+ commonStates.States.Add(cache.PointerOver);
+
+ VisualStateManager.GoToState(control, "Normal", true);
+
+ cache = null;
+ }
+
+ void UpdateEnabled(double value)
+ {
+ double increment = Increment;
+ if (_plus != null)
+ {
+ if (value + increment > Maximum)
+ _plusStateCache = PseudoDisable(_plus);
+ else
+ PsuedoEnable(_plus, ref _plusStateCache);
+ }
+
+ if (_minus != null)
+ {
+ if (value - increment < Minimum)
+ _minusStateCache = PseudoDisable(_minus);
+ else
+ PsuedoEnable(_minus, ref _minusStateCache);
+ }
+ }
+
+ void UpdateValue(double delta)
+ {
+ double newValue = Value + delta;
+ if (newValue > Maximum || newValue < Minimum)
+ return;
+
+ Value = newValue;
+ }
+
+ class VisualStateCache
+ {
+ public VisualStateGroup FocusStates;
+ public VisualState Normal, PointerOver, Pressed;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.UAP/TabbedPageRenderer.cs b/Xamarin.Forms.Platform.UAP/TabbedPageRenderer.cs
new file mode 100644
index 00000000..6dfc1a47
--- /dev/null
+++ b/Xamarin.Forms.Platform.UAP/TabbedPageRenderer.cs
@@ -0,0 +1,264 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Threading.Tasks;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Automation;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+
+namespace Xamarin.Forms.Platform.UWP
+{
+ internal class TabbedPagePresenter : Windows.UI.Xaml.Controls.ContentPresenter
+ {
+ public TabbedPagePresenter()
+ {
+ Loaded += TabbedPagePresenter_Loaded;
+ Unloaded += TabbedPagePresenter_Unloaded;
+ SizeChanged += (s, e) =>
+ {
+ if (ActualWidth > 0 && ActualHeight > 0)
+ {
+ var tab = (Page)DataContext;
+ ((TabbedPage)tab.RealParent).ContainerArea = new Rectangle(0, 0, ActualWidth, ActualHeight);
+ }
+ };
+ }
+
+ void TabbedPagePresenter_Loaded(object sender, RoutedEventArgs e)
+ {
+ var tab = (Page)DataContext;
+ tab.SendAppearing();
+ }
+
+ void TabbedPagePresenter_Unloaded(object sender, RoutedEventArgs e)
+ {
+ var tab = (Page)DataContext;
+ tab.SendDisappearing();
+ }
+ }
+
+ public class TabbedPageRenderer : IVisualElementRenderer, ITitleProvider, IToolbarProvider
+ {
+ bool _disposed;
+ bool _showTitle;
+ VisualElementTracker<Page, Pivot> _tracker;
+
+ public Pivot Control { get; private set; }
+
+ public TabbedPage Element { get; private set; }
+
+ protected VisualElementTracker<Page, Pivot> Tracker
+ {
+ get { return _tracker; }
+ set
+ {
+ if (_tracker == value)
+ return;
+
+ if (_tracker != null)
+ _tracker.Dispose();
+
+ _tracker = value;
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ Brush ITitleProvider.BarBackgroundBrush
+ {
+ set { (Control as FormsPivot).ToolbarBackground = value; }
+ }
+
+ Brush ITitleProvider.BarForegroundBrush
+ {
+ set { (Control as FormsPivot).ToolbarForeground = value; }
+ }
+
+ bool ITitleProvider.ShowTitle
+ {
+ get { return _showTitle; }
+
+ set
+ {
+ if (_showTitle == value)
+ return;
+ _showTitle = value;
+
+ UpdateBarVisibility();
+ }
+ }
+
+ string ITitleProvider.Title
+ {
+ get { return (string)Control?.Title; }
+
+ set
+ {
+ if (Control != null && _showTitle)
+ Control.Title = value;
+ }
+ }
+
+ public Task<CommandBar> GetCommandBarAsync()
+ {
+ return (Control as IToolbarProvider)?.GetCommandBarAsync();
+ }
+
+ public FrameworkElement ContainerElement
+ {
+ get { return Control; }
+ }
+
+ VisualElement IVisualElementRenderer.Element
+ {
+ get { return Element; }
+ }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ var constraint = new Windows.Foundation.Size(widthConstraint, heightConstraint);
+
+ double oldWidth = Control.Width;
+ double oldHeight = Control.Height;
+
+ Control.Height = double.NaN;
+ Control.Width = double.NaN;
+
+ Control.Measure(constraint);
+ var result = new Size(Math.Ceiling(Control.DesiredSize.Width), Math.Ceiling(Control.DesiredSize.Height));
+
+ Control.Width = oldWidth;
+ Control.Height = oldHeight;
+
+ return new SizeRequest(result);
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ if (element != null && !(element is TabbedPage))
+ throw new ArgumentException("Element must be a TabbedPage", "element");
+
+ TabbedPage oldElement = Element;
+ Element = (TabbedPage)element;
+
+ if (oldElement != null)
+ {
+ oldElement.PropertyChanged -= OnElementPropertyChanged;
+ ((INotifyCollectionChanged)oldElement.Children).CollectionChanged -= OnPagesChanged;
+ }
+
+ if (element != null)
+ {
+ if (Control == null)
+ {
+ Control = new FormsPivot { Style = (Windows.UI.Xaml.Style)Windows.UI.Xaml.Application.Current.Resources["TabbedPageStyle"] };
+
+ Control.SelectionChanged += OnSelectionChanged;
+
+ Tracker = new BackgroundTracker<Pivot>(Windows.UI.Xaml.Controls.Control.BackgroundProperty) { Element = (Page)element, Control = Control, Container = Control };
+
+ Control.Loaded += OnLoaded;
+ Control.Unloaded += OnUnloaded;
+ }
+
+ Control.DataContext = Element;
+ OnPagesChanged(Element.Children, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ UpdateCurrentPage();
+
+ ((INotifyCollectionChanged)Element.Children).CollectionChanged += OnPagesChanged;
+ element.PropertyChanged += OnElementPropertyChanged;
+
+ if (!string.IsNullOrEmpty(element.AutomationId))
+ Control.SetValue(AutomationProperties.AutomationIdProperty, element.AutomationId);
+ }
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposing || _disposed)
+ return;
+
+ _disposed = true;
+ Element?.SendDisappearing();
+ SetElement(null);
+ Tracker = null;
+ }
+
+ protected void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ EventHandler<VisualElementChangedEventArgs> changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "CurrentPage")
+ UpdateCurrentPage();
+ }
+
+ void OnLoaded(object sender, RoutedEventArgs args)
+ {
+ if (Element == null)
+ return;
+
+ Element.SendAppearing();
+ }
+
+ void OnPagesChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ e.Apply(Element.Children, Control.Items);
+
+ // Potential performance issue, UpdateLayout () is called for every page change
+ Control.UpdateLayout();
+ }
+
+ void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (Element == null)
+ return;
+
+ Page page = e.AddedItems.Count > 0 ? (Page)e.AddedItems[0] : null;
+ Page currentPage = Element.CurrentPage;
+ if (currentPage == page)
+ return;
+ currentPage?.SendDisappearing();
+ Element.CurrentPage = page;
+ page?.SendAppearing();
+ }
+
+ void OnUnloaded(object sender, RoutedEventArgs args)
+ {
+ if (Element == null)
+ return;
+
+ Element.SendDisappearing();
+ }
+
+ void UpdateBarVisibility()
+ {
+ (Control as FormsPivot).ToolbarVisibility = _showTitle ? Visibility.Visible : Visibility.Collapsed;
+ }
+
+ void UpdateCurrentPage()
+ {
+ Page page = Element.CurrentPage;
+
+ var nav = page as NavigationPage;
+ ((ITitleProvider)this).ShowTitle = nav != null;
+
+ if (page == null)
+ return;
+
+ Control.SelectedItem = page;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.UAP/Xamarin.Forms.Platform.UAP.csproj b/Xamarin.Forms.Platform.UAP/Xamarin.Forms.Platform.UAP.csproj
new file mode 100644
index 00000000..4ed5242c
--- /dev/null
+++ b/Xamarin.Forms.Platform.UAP/Xamarin.Forms.Platform.UAP.csproj
@@ -0,0 +1,450 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{00D8D049-FFAA-4759-8FC9-1ECA30777F72}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Platform.UAP</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Platform.UAP</AssemblyName>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
+ <TargetPlatformVersion>10.0.10240.0</TargetPlatformVersion>
+ <TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
+ <MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+ <PlatformTarget>ARM</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\ARM\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+ <PlatformTarget>ARM</PlatformTarget>
+ <OutputPath>bin\ARM\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ <PlatformTarget>x64</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x64\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ <PlatformTarget>x64</PlatformTarget>
+ <OutputPath>bin\x64\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <PlatformTarget>x86</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <PlatformTarget>x86</PlatformTarget>
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
+ <None Include="project.json" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT.Phone\FormsPivot.cs">
+ <Link>FormsPivot.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\AlignmentExtensions.cs">
+ <Link>AlignmentExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\CarouselViewRenderer.cs">
+ <Link>CarouselViewRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\FormsTextBox.cs">
+ <Link>FormsTextBox.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\FormsComboBox.cs">
+ <Link>FormsComboBox.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\FormsDatePicker.cs">
+ <Link>FormsDatePicker.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\FormsTimePicker.cs">
+ <Link>FormsTimePicker.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\HorizontalTextAlignmentConverter.cs">
+ <Link>HorizontalTextAlignmentConverter.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ITitleProvider.cs">
+ <Link>ITitleProvider.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\IToolbarProvider.cs">
+ <Link>IToolbarProvider.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\IWrapperAware.cs">
+ <Link>IWrapperAware.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\NativeViewWrapper.cs">
+ <Link>NativeViewWrapper.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\NativeViewWrapperRenderer.cs">
+ <Link>NativeViewWrapperRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\PlatformEffect.cs">
+ <Link>PlatformEffect.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ViewExtensions.cs">
+ <Link>ViewExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\LayoutExtensions.cs">
+ <Link>LayoutExtensions.cs</Link>
+ </Compile>
+ <Compile Include="IToolBarForegroundBinder.cs" />
+ <Compile Include="SearchBarRenderer.cs" />
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\TextAlignmentToHorizontalAlignmentConverter.cs">
+ <Link>TextAlignmentToHorizontalAlignmentConverter.cs</Link>
+ </Compile>
+ <Compile Include="StepperControl.cs" />
+ <Compile Include="TabbedPageRenderer.cs" />
+ <Content Include="Properties\Xamarin.Forms.Platform.UAP.rd.xml" />
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT.Tablet\Forms.cs">
+ <Link>Forms.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT.Tablet\WindowsPage.cs">
+ <Link>WindowsPage.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT.Tablet\WindowsPlatform.cs">
+ <Link>WindowsPlatform.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT.Tablet\WindowsPlatformServices.cs">
+ <Link>WindowsPlatformServices.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT.Tablet\WindowsResourcesProvider.cs">
+ <Link>WindowsResourcesProvider.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ActivityIndicatorRenderer.cs">
+ <Link>ActivityIndicatorRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\AsyncValue.cs">
+ <Link>AsyncValue.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\BackgroundTracker.cs">
+ <Link>BackgroundTracker.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\BoolToVisibilityConverter.cs">
+ <Link>BoolToVisibilityConverter.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\BoxViewRenderer.cs">
+ <Link>BoxViewRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ButtonRenderer.cs">
+ <Link>ButtonRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\CarouselPageRenderer.cs">
+ <Link>CarouselPageRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\CaseConverter.cs">
+ <Link>CaseConverter.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\CellControl.cs">
+ <Link>CellControl.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\CollapseWhenEmptyConverter.cs">
+ <Link>CollapseWhenEmptyConverter.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ColorConverter.cs">
+ <Link>ColorConverter.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ConvertExtensions.cs">
+ <Link>ConvertExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\DatePickerRenderer.cs">
+ <Link>DatePickerRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\DefaultRenderer.cs">
+ <Link>DefaultRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\EditorRenderer.cs">
+ <Link>EditorRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\EntryCellTextBox.cs">
+ <Link>EntryCellTextBox.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\EntryRenderer.cs">
+ <Link>EntryRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ExportRendererAttribute.cs">
+ <Link>ExportRendererAttribute.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\Extensions.cs">
+ <Link>Extensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\FileImageSourceHandler.cs">
+ <Link>FileImageSourceHandler.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\FileImageSourcePathConverter.cs">
+ <Link>FileImageSourcePathConverter.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\FontExtensions.cs">
+ <Link>FontExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\FormsButton.cs">
+ <Link>FormsButton.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\FrameRenderer.cs">
+ <Link>FrameRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\FrameworkElementExtensions.cs">
+ <Link>FrameworkElementExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\HeightConverter.cs">
+ <Link>HeightConverter.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ICellRenderer.cs">
+ <Link>ICellRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\IImageSourceHandler.cs">
+ <Link>IImageSourceHandler.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ImageConverter.cs">
+ <Link>ImageConverter.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ImageLoaderSourceHandler.cs">
+ <Link>ImageLoaderSourceHandler.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ImageRenderer.cs">
+ <Link>ImageRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\IVisualElementRenderer.cs">
+ <Link>IVisualElementRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\KeyboardConverter.cs">
+ <Link>KeyboardConverter.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\KeyboardExtensions.cs">
+ <Link>KeyboardExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\LabelRenderer.cs">
+ <Link>LabelRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\LayoutRenderer.cs">
+ <Link>LayoutRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ListGroupHeaderPresenter.cs">
+ <Link>ListGroupHeaderPresenter.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ListViewGroupStyleSelector.cs">
+ <Link>ListViewGroupStyleSelector.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ListViewRenderer.cs">
+ <Link>ListViewRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\MasterBackgroundConverter.cs">
+ <Link>MasterBackgroundConverter.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\MenuItemCommand.cs">
+ <Link>MenuItemCommand.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\NavigationPageRenderer.cs">
+ <Link>NavigationPageRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\PageControl.xaml.cs">
+ <Link>PageControl.xaml.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\PageRenderer.cs">
+ <Link>PageRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\PageToRenderedElementConverter.cs">
+ <Link>PageToRenderedElementConverter.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\PickerRenderer.cs">
+ <Link>PickerRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\Platform.cs">
+ <Link>Platform.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ProgressBarRenderer.cs">
+ <Link>ProgressBarRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\RendererFactory.cs">
+ <Link>RendererFactory.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ScrollViewRenderer.cs">
+ <Link>ScrollViewRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\SliderRenderer.cs">
+ <Link>SliderRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\StepperRenderer.cs">
+ <Link>StepperRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\StreamImagesourceHandler.cs">
+ <Link>StreamImagesourceHandler.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\SwitchRenderer.cs">
+ <Link>SwitchRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\TableViewRenderer.cs">
+ <Link>TableViewRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\TaskExtensions.cs">
+ <Link>TaskExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\TextCellRenderer.cs">
+ <Link>TextCellRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\TimePickerRenderer.cs">
+ <Link>TimePickerRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ViewRenderer.cs">
+ <Link>ViewRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\ViewToRendererConverter.cs">
+ <Link>ViewToRendererConverter.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\VisualElementChangedEventArgs.cs">
+ <Link>VisualElementChangedEventArgs.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\VisualElementExtensions.cs">
+ <Link>VisualElementExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\VisualElementPackager.cs">
+ <Link>VisualElementPackager.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\VisualElementRenderer.cs">
+ <Link>VisualElementRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\VisualElementTracker.cs">
+ <Link>VisualElementTracker.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\WebViewRenderer.cs">
+ <Link>WebViewRenderer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\WindowsBasePage.cs">
+ <Link>WindowsBasePage.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\WindowsBasePlatformServices.cs">
+ <Link>WindowsBasePlatformServices.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\WindowsDeviceInfo.cs">
+ <Link>WindowsDeviceInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\WindowsExpressionSearch.cs">
+ <Link>WindowsExpressionSearch.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\WindowsIsolatedStorage.cs">
+ <Link>WindowsIsolatedStorage.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\WindowsSerializer.cs">
+ <Link>WindowsSerializer.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Platform.WinRT\WindowsTicker.cs">
+ <Link>WindowsTicker.cs</Link>
+ </Compile>
+ <Compile Include="FormsCommandBar.cs" />
+ <Compile Include="MasterDetailControl.cs" />
+ <Compile Include="MasterDetailPageRenderer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Page Include="FormsTextBoxStyle.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="PageControl.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Resources.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <SDKReference Include="WindowsMobile, Version=10.0.10240.0">
+ <Name>Windows Mobile Extensions for the UWP</Name>
+ </SDKReference>
+ </ItemGroup>
+ <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
+ <VisualStudioVersion>14.0</VisualStudioVersion>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.UAP/project.json b/Xamarin.Forms.Platform.UAP/project.json
new file mode 100644
index 00000000..c5949392
--- /dev/null
+++ b/Xamarin.Forms.Platform.UAP/project.json
@@ -0,0 +1,16 @@
+{
+ "dependencies": {
+ "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
+ },
+ "frameworks": {
+ "uap10.0": {}
+ },
+ "runtimes": {
+ "win10-arm": {},
+ "win10-arm-aot": {},
+ "win10-x86": {},
+ "win10-x86-aot": {},
+ "win10-x64": {},
+ "win10-x64-aot": {}
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ActivityIndicatorRenderer.cs b/Xamarin.Forms.Platform.WP8/ActivityIndicatorRenderer.cs
new file mode 100644
index 00000000..0e0ceb61
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ActivityIndicatorRenderer.cs
@@ -0,0 +1,36 @@
+using System.ComponentModel;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class ActivityIndicatorRenderer : ViewRenderer<ActivityIndicator, System.Windows.Controls.ProgressBar>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<ActivityIndicator> e)
+ {
+ base.OnElementChanged(e);
+
+ SetNativeControl(new System.Windows.Controls.ProgressBar());
+
+ Control.IsIndeterminate = Element.IsRunning;
+ UpdateColor();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == ActivityIndicator.IsRunningProperty.PropertyName)
+ Control.IsIndeterminate = Element.IsRunning;
+ else if (e.PropertyName == ActivityIndicator.ColorProperty.PropertyName)
+ UpdateColor();
+ }
+
+ void UpdateColor()
+ {
+ Color color = Element.Color;
+ if (color == Color.Default)
+ Control.ClearValue(System.Windows.Controls.Control.ForegroundProperty);
+ else
+ Control.Foreground = color.ToBrush();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/AlignmentExtensions.cs b/Xamarin.Forms.Platform.WP8/AlignmentExtensions.cs
new file mode 100644
index 00000000..7629d3eb
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/AlignmentExtensions.cs
@@ -0,0 +1,33 @@
+using System.Windows;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ internal static class AlignmentExtensions
+ {
+ internal static System.Windows.TextAlignment ToNativeTextAlignment(this TextAlignment alignment)
+ {
+ switch (alignment)
+ {
+ case TextAlignment.Center:
+ return System.Windows.TextAlignment.Center;
+ case TextAlignment.End:
+ return System.Windows.TextAlignment.Right;
+ default:
+ return System.Windows.TextAlignment.Left;
+ }
+ }
+
+ internal static VerticalAlignment ToNativeVerticalAlignment(this TextAlignment alignment)
+ {
+ switch (alignment)
+ {
+ case TextAlignment.Center:
+ return VerticalAlignment.Center;
+ case TextAlignment.End:
+ return VerticalAlignment.Bottom;
+ default:
+ return VerticalAlignment.Top;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/Animatable.cs b/Xamarin.Forms.Platform.WP8/Animatable.cs
new file mode 100644
index 00000000..c8a36dff
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Animatable.cs
@@ -0,0 +1,13 @@
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ internal class Animatable : IAnimatable
+ {
+ public void BatchBegin()
+ {
+ }
+
+ public void BatchCommit()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/AsyncValue.cs b/Xamarin.Forms.Platform.WP8/AsyncValue.cs
new file mode 100644
index 00000000..0b41177d
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/AsyncValue.cs
@@ -0,0 +1,89 @@
+//
+// AsyncValue.cs
+//
+// Author:
+// Eric Maupin <me@ermau.com>
+//
+// Copyright (c) 2013-2014 Xamarin, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ internal sealed class AsyncValue<T> : INotifyPropertyChanged
+ {
+ readonly T _defaultValue;
+ readonly Task<T> _valueTask;
+ bool _isRunning = true;
+
+ public AsyncValue(Task<T> valueTask, T defaultValue)
+ {
+ if (valueTask == null)
+ throw new ArgumentNullException("valueTask");
+
+ _valueTask = valueTask;
+ _defaultValue = defaultValue;
+
+ TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext();
+
+ _valueTask.ContinueWith(t => { IsRunning = false; }, scheduler);
+
+ _valueTask.ContinueWith(t => { OnPropertyChanged("Value"); }, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, scheduler);
+ }
+
+ public bool IsRunning
+ {
+ get { return _isRunning; }
+ set
+ {
+ if (_isRunning == value)
+ return;
+
+ _isRunning = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public T Value
+ {
+ get
+ {
+ if (_valueTask.Status != TaskStatus.RanToCompletion)
+ return _defaultValue;
+
+ return _valueTask.Result;
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/BoxViewRenderer.cs b/Xamarin.Forms.Platform.WP8/BoxViewRenderer.cs
new file mode 100644
index 00000000..84650996
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/BoxViewRenderer.cs
@@ -0,0 +1,17 @@
+using System.Windows.Shapes;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class BoxViewRenderer : ViewRenderer<BoxView, System.Windows.Shapes.Rectangle>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e)
+ {
+ base.OnElementChanged(e);
+
+ var rect = new System.Windows.Shapes.Rectangle();
+ rect.DataContext = Element;
+ rect.SetBinding(Shape.FillProperty, new System.Windows.Data.Binding("Color") { Converter = new ColorConverter() });
+ SetNativeControl(rect);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ButtonRenderer.cs b/Xamarin.Forms.Platform.WP8/ButtonRenderer.cs
new file mode 100644
index 00000000..886a7768
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ButtonRenderer.cs
@@ -0,0 +1,119 @@
+using System;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using WButton = System.Windows.Controls.Button;
+using WImage = System.Windows.Controls.Image;
+using WThickness = System.Windows.Thickness;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class ButtonRenderer : ViewRenderer<Button, WButton>
+ {
+ bool _fontApplied;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
+ {
+ base.OnElementChanged(e);
+
+ var button = new WButton();
+ button.Click += HandleButtonClick;
+ SetNativeControl(button);
+
+ UpdateContent();
+
+ if (Element.BackgroundColor != Color.Default)
+ UpdateBackground();
+
+ if (Element.TextColor != Color.Default)
+ UpdateTextColor();
+
+ if (Element.BorderColor != Color.Default)
+ UpdateBorderColor();
+
+ if (Element.BorderWidth != 0)
+ UpdateBorderWidth();
+
+ UpdateFont();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Button.TextProperty.PropertyName || e.PropertyName == Button.ImageProperty.PropertyName)
+ UpdateContent();
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackground();
+ else if (e.PropertyName == Button.TextColorProperty.PropertyName)
+ UpdateTextColor();
+ else if (e.PropertyName == Button.FontProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Button.BorderColorProperty.PropertyName)
+ UpdateBorderColor();
+ else if (e.PropertyName == Button.BorderWidthProperty.PropertyName)
+ UpdateBorderWidth();
+ }
+
+ void HandleButtonClick(object sender, RoutedEventArgs e)
+ {
+ Button buttonView = Element;
+ if (buttonView != null)
+ ((IButtonController)buttonView).SendClicked();
+ }
+
+ void UpdateBackground()
+ {
+ Control.Background = Element.BackgroundColor != Color.Default ? Element.BackgroundColor.ToBrush() : (Brush)System.Windows.Application.Current.Resources["PhoneBackgroundBrush"];
+ }
+
+ void UpdateBorderColor()
+ {
+ Control.BorderBrush = Element.BorderColor != Color.Default ? Element.BorderColor.ToBrush() : (Brush)System.Windows.Application.Current.Resources["PhoneForegroundBrush"];
+ }
+
+ void UpdateBorderWidth()
+ {
+ Control.BorderThickness = Element.BorderWidth == 0d ? new WThickness(3) : new WThickness(Element.BorderWidth);
+ }
+
+ void UpdateContent()
+ {
+ if (Element.Image != null)
+ {
+ Control.Content = new StackPanel
+ {
+ Orientation = Orientation.Horizontal,
+ Children =
+ {
+ new WImage { Source = new BitmapImage(new Uri("/" + Element.Image.File, UriKind.Relative)), Width = 30, Height = 30, Margin = new WThickness(0, 0, 20, 0) },
+ new TextBlock { Text = Element.Text }
+ }
+ };
+ }
+ else
+ Control.Content = Element.Text;
+ }
+
+ void UpdateFont()
+ {
+ if (Control == null || Element == null)
+ return;
+
+ if (Element.Font == Font.Default && !_fontApplied)
+ return;
+
+ Font fontToApply = Element.Font == Font.Default ? Font.SystemFontOfSize(NamedSize.Medium) : Element.Font;
+
+ Control.ApplyFont(fontToApply);
+ _fontApplied = true;
+ }
+
+ void UpdateTextColor()
+ {
+ Control.Foreground = Element.TextColor != Color.Default ? Element.TextColor.ToBrush() : (Brush)System.Windows.Application.Current.Resources["PhoneForegroundBrush"];
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/CarouselPageRenderer.cs b/Xamarin.Forms.Platform.WP8/CarouselPageRenderer.cs
new file mode 100644
index 00000000..29446c43
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/CarouselPageRenderer.cs
@@ -0,0 +1,219 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using Microsoft.Phone.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ internal class BackgroundTracker<T> : VisualElementTracker<Page, T> where T : FrameworkElement
+ {
+ readonly DependencyProperty _backgroundProperty;
+
+ bool _backgroundNeedsUpdate = true;
+
+ public BackgroundTracker(DependencyProperty backgroundProperty)
+ {
+ if (backgroundProperty == null)
+ throw new ArgumentNullException("backgroundProperty");
+
+ _backgroundProperty = backgroundProperty;
+ }
+
+ protected override void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName || e.PropertyName == Page.BackgroundImageProperty.PropertyName)
+ UpdateBackground();
+
+ base.HandlePropertyChanged(sender, e);
+ }
+
+ protected override void UpdateNativeControl()
+ {
+ base.UpdateNativeControl();
+
+ if (_backgroundNeedsUpdate)
+ UpdateBackground();
+ }
+
+ void UpdateBackground()
+ {
+ if (Model == null || Element == null)
+ return;
+
+ if (Model.BackgroundImage != null)
+ {
+ Element.SetValue(_backgroundProperty, new ImageBrush { ImageSource = new BitmapImage(new Uri(Model.BackgroundImage, UriKind.Relative)) });
+ }
+ else if (Model.BackgroundColor != Color.Default)
+ Element.SetValue(_backgroundProperty, Model.BackgroundColor.ToBrush());
+
+ _backgroundNeedsUpdate = false;
+ }
+ }
+
+ public class CarouselPagePresenter : System.Windows.Controls.ContentPresenter
+ {
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ DependencyObject parent = VisualTreeHelper.GetParent(this);
+ while (parent != null && !(parent is PanoramaItem))
+ parent = VisualTreeHelper.GetParent(parent);
+
+ var panoramaItem = parent as PanoramaItem;
+ if (panoramaItem == null)
+ throw new Exception("No parent PanoramaItem found for carousel page");
+
+ var element = (FrameworkElement)VisualTreeHelper.GetChild(panoramaItem, 0);
+ element.SizeChanged += (s, e) =>
+ {
+ if (element.ActualWidth > 0 && element.ActualHeight > 0)
+ {
+ var carouselItem = (Page)DataContext;
+ ((CarouselPage)carouselItem.RealParent).ContainerArea = new Rectangle(0, 0, element.ActualWidth, element.ActualHeight);
+ }
+ };
+ }
+ }
+
+ public class CarouselPageRenderer : Panorama, IVisualElementRenderer
+ {
+ static readonly System.Windows.DataTemplate PageTemplate;
+
+ static readonly BindableProperty PageContainerProperty = BindableProperty.CreateAttached("PageContainer", typeof(PanoramaItem), typeof(CarouselPageRenderer), null);
+
+ CarouselPage _page;
+ BackgroundTracker<Control> _tracker;
+
+ static CarouselPageRenderer()
+ {
+ PageTemplate = (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["CarouselPage"];
+ }
+
+ public CarouselPageRenderer()
+ {
+ SetBinding(TitleProperty, new System.Windows.Data.Binding("Title"));
+ }
+
+ public UIElement ContainerElement
+ {
+ get { return this; }
+ }
+
+ public VisualElement Element
+ {
+ get { return _page; }
+ }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return new SizeRequest(new Size(widthConstraint, heightConstraint));
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ CarouselPage oldElement = _page;
+ _page = (CarouselPage)element;
+ _tracker = new BackgroundTracker<Control>(BackgroundProperty) { Model = _page, Element = this };
+
+ DataContext = _page;
+
+ SelectionChanged += OnSelectionChanged;
+
+ OnPagesChanged(_page, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+
+ _page.PagesChanged += OnPagesChanged;
+ _page.PropertyChanged += OnPropertyChanged;
+
+ Loaded += (sender, args) => _page.SendAppearing();
+ Unloaded += (sender, args) => _page.SendDisappearing();
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+ }
+
+ protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ EventHandler<VisualElementChangedEventArgs> changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ static PanoramaItem GetPageContainer(BindableObject bindable)
+ {
+ return (PanoramaItem)bindable.GetValue(PageContainerProperty);
+ }
+
+ void InsertItem(object item, int index, bool newItem)
+ {
+ DependencyObject pageContent = PageTemplate.LoadContent();
+
+ var pageItem = (Page)item;
+ PanoramaItem container = GetPageContainer(pageItem);
+ if (container == null)
+ {
+ container = new PanoramaItem { DataContext = item, Content = pageContent };
+
+ SetPageContainer(pageItem, container);
+ }
+
+ Items.Insert(index, container);
+ }
+
+ void OnPagesChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ e.Apply(InsertItem, RemoveItem, Reset);
+ }
+
+ void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "CurrentPage")
+ {
+ ContentPage current = _page.CurrentPage;
+ if (current == null)
+ return;
+
+ SetValue(SelectedItemProperty, GetPageContainer(current));
+ OnItemsChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ }
+ }
+
+ void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ var panoramaItem = (PanoramaItem)SelectedItem;
+ if (panoramaItem == null)
+ _page.CurrentPage = null;
+ else
+ _page.CurrentPage = (ContentPage)panoramaItem.DataContext;
+ }
+
+ void RemoveItem(object item, int index)
+ {
+ Items.RemoveAt(index);
+ }
+
+ void Reset()
+ {
+ Items.Clear();
+
+ var i = 0;
+ foreach (Page pageItem in _page.Children)
+ InsertItem(pageItem, i++, true);
+
+ ContentPage current = _page.CurrentPage;
+ if (current != null)
+ SetValue(SelectedItemProperty, GetPageContainer(current));
+ }
+
+ static void SetPageContainer(BindableObject bindable, PanoramaItem container)
+ {
+ bindable.SetValue(PageContainerProperty, container);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/CarouselViewRenderer.cs b/Xamarin.Forms.Platform.WP8/CarouselViewRenderer.cs
new file mode 100644
index 00000000..6050d07d
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/CarouselViewRenderer.cs
@@ -0,0 +1,13 @@
+using Microsoft.Phone.Controls;
+using SLButton = System.Windows.Controls.Button;
+using SLBinding = System.Windows.Data.Binding;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class CarouselViewRenderer : ViewRenderer<CarouselView, LongListSelector>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<CarouselView> e)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/CellControl.cs b/Xamarin.Forms.Platform.WP8/CellControl.cs
new file mode 100644
index 00000000..743f4ba7
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/CellControl.cs
@@ -0,0 +1,101 @@
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using Microsoft.Phone.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class CellControl : ContentControl
+ {
+ public static readonly DependencyProperty CellProperty = DependencyProperty.Register("Cell", typeof(object), typeof(CellControl),
+ new PropertyMetadata((o, e) => ((CellControl)o).SetSource((Cell)e.OldValue, (Cell)e.NewValue)));
+
+ public static readonly DependencyProperty ShowContextActionsProperty = DependencyProperty.Register("ShowContextActions", typeof(bool), typeof(CellControl), new PropertyMetadata(true));
+
+ readonly PropertyChangedEventHandler _propertyChangedHandler;
+
+ public CellControl()
+ {
+ Unloaded += (sender, args) =>
+ {
+ var cell = DataContext as Cell;
+ if (cell != null)
+ cell.SendDisappearing();
+ };
+
+ _propertyChangedHandler = OnCellPropertyChanged;
+ }
+
+ public Cell Cell
+ {
+ get { return (Cell)GetValue(CellProperty); }
+ set { SetValue(CellProperty, value); }
+ }
+
+ public bool ShowContextActions
+ {
+ get { return (bool)GetValue(ShowContextActionsProperty); }
+ set { SetValue(ShowContextActionsProperty, value); }
+ }
+
+ System.Windows.DataTemplate GetTemplate(Cell cell)
+ {
+ var renderer = Registrar.Registered.GetHandler<ICellRenderer>(cell.GetType());
+ return renderer.GetTemplate(cell);
+ }
+
+ void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "HasContextActions")
+ SetupContextMenu();
+ }
+
+ void SetSource(Cell oldCell, Cell newCell)
+ {
+ if (oldCell != null)
+ {
+ oldCell.PropertyChanged -= _propertyChangedHandler;
+ oldCell.SendDisappearing();
+ }
+
+ DependencyObject content = null;
+ if (newCell != null)
+ {
+ newCell.SendAppearing();
+
+ if (oldCell == null || oldCell.GetType() != newCell.GetType())
+ ContentTemplate = GetTemplate(newCell);
+
+ Content = newCell;
+
+ SetupContextMenu();
+
+ newCell.PropertyChanged += _propertyChangedHandler;
+ }
+ else
+ Content = null;
+ }
+
+ void SetupContextMenu()
+ {
+ if (Content == null || !ShowContextActions)
+ return;
+
+ if (!Cell.HasContextActions)
+ {
+ if (VisualTreeHelper.GetChildrenCount(this) > 0)
+ ContextMenuService.SetContextMenu(VisualTreeHelper.GetChild(this, 0), null);
+
+ return;
+ }
+
+ ApplyTemplate();
+
+ ContextMenu menu = new CustomContextMenu();
+ menu.SetBinding(ItemsControl.ItemsSourceProperty, new System.Windows.Data.Binding("ContextActions"));
+
+ ContextMenuService.SetContextMenu(VisualTreeHelper.GetChild(this, 0), menu);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/CellTemplateSelector.cs b/Xamarin.Forms.Platform.WP8/CellTemplateSelector.cs
new file mode 100644
index 00000000..09d939fd
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/CellTemplateSelector.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Globalization;
+using System.Windows;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class HeightConverter : System.Windows.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var val = (double)value;
+ return val > 0 ? val : double.NaN;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ [Obsolete("Deprecated in favor of CellControl")]
+ public class CellTemplateSelector : DataTemplateSelector
+ {
+ public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(object), typeof(CellTemplateSelector),
+ new PropertyMetadata((o, e) => ((CellTemplateSelector)o).SetSource(e.OldValue, e.NewValue)));
+
+ public CellTemplateSelector()
+ {
+ Loaded += (sender, args) => SetBinding(SourceProperty, new System.Windows.Data.Binding());
+ Unloaded += (sender, args) =>
+ {
+ var cell = DataContext as Cell;
+ if (cell != null)
+ cell.SendDisappearing();
+ };
+ }
+
+ public override System.Windows.DataTemplate SelectTemplate(object item, DependencyObject container)
+ {
+ var cell = item as Cell;
+ if (cell == null)
+ return null;
+
+ var renderer = Registrar.Registered.GetHandler<ICellRenderer>(cell.GetType());
+ return renderer.GetTemplate(cell);
+ }
+
+ void SetSource(object oldSource, object newSource)
+ {
+ var oldCell = oldSource as Cell;
+ var newCell = newSource as Cell;
+
+ if (oldCell != null)
+ oldCell.SendDisappearing();
+
+ if (newCell != null)
+ newCell.SendAppearing();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/CollapseWhenEmptyConverter.cs b/Xamarin.Forms.Platform.WP8/CollapseWhenEmptyConverter.cs
new file mode 100644
index 00000000..d7dc6de6
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/CollapseWhenEmptyConverter.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Globalization;
+using System.Windows;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class CollapseWhenEmptyConverter : System.Windows.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var length = 0;
+
+ var s = value as string;
+ if (s != null)
+ length = s.Length;
+
+ if (value is int)
+ length = (int)value;
+
+ return length > 0 ? Visibility.Visible : Visibility.Collapsed;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ConvertExtensions.cs b/Xamarin.Forms.Platform.WP8/ConvertExtensions.cs
new file mode 100644
index 00000000..ed96ecdf
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ConvertExtensions.cs
@@ -0,0 +1,17 @@
+using System.Windows.Media;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ internal static class ConvertExtensions
+ {
+ public static Brush ToBrush(this Color color)
+ {
+ return new SolidColorBrush(color.ToMediaColor());
+ }
+
+ public static System.Windows.Media.Color ToMediaColor(this Color color)
+ {
+ return System.Windows.Media.Color.FromArgb((byte)(color.A * 255), (byte)(color.R * 255), (byte)(color.G * 255), (byte)(color.B * 255));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/Converters/CaseConverter.cs b/Xamarin.Forms.Platform.WP8/Converters/CaseConverter.cs
new file mode 100644
index 00000000..b972fc57
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Converters/CaseConverter.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Globalization;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class CaseConverter : System.Windows.Data.IValueConverter
+ {
+ public bool ConvertToUpper { get; set; }
+
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value == null)
+ return null;
+
+ var v = (string)value;
+ return ConvertToUpper ? v.ToUpper() : v.ToLower();
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/Converters/ColorConverter.cs b/Xamarin.Forms.Platform.WP8/Converters/ColorConverter.cs
new file mode 100644
index 00000000..1e495ecf
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Converters/ColorConverter.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Globalization;
+using System.Windows.Media;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class ColorConverter : System.Windows.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var color = (Color)value;
+ var defaultColorKey = (string)parameter;
+
+ Brush defaultBrush = defaultColorKey != null ? (Brush)System.Windows.Application.Current.Resources[defaultColorKey] : new SolidColorBrush(Colors.Transparent);
+
+ return color == Color.Default ? defaultBrush : color.ToBrush();
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/Converters/HorizontalTextAlignmentConverter.cs b/Xamarin.Forms.Platform.WP8/Converters/HorizontalTextAlignmentConverter.cs
new file mode 100644
index 00000000..7923b1d3
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Converters/HorizontalTextAlignmentConverter.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Globalization;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class HorizontalTextAlignmentConverter : System.Windows.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var textAlign = (TextAlignment)value;
+
+ return textAlign.ToNativeTextAlignment();
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/Converters/ImageConverter.cs b/Xamarin.Forms.Platform.WP8/Converters/ImageConverter.cs
new file mode 100644
index 00000000..2e8bdef6
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Converters/ImageConverter.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Globalization;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class ImageConverter : System.Windows.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var source = (ImageSource)value;
+ IImageSourceHandler handler;
+
+ if (source != null && (handler = Registrar.Registered.GetHandler<IImageSourceHandler>(source.GetType())) != null)
+ {
+ Task<System.Windows.Media.ImageSource> task = handler.LoadImageAsync(source);
+ return new AsyncValue<System.Windows.Media.ImageSource>(task, null);
+ }
+
+ return null;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/Converters/KeyboardConverter.cs b/Xamarin.Forms.Platform.WP8/Converters/KeyboardConverter.cs
new file mode 100644
index 00000000..cd082b29
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Converters/KeyboardConverter.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Globalization;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class KeyboardConverter : System.Windows.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var keyboard = (Keyboard)value;
+ return keyboard.ToInputScope();
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/CustomContextMenu.cs b/Xamarin.Forms.Platform.WP8/CustomContextMenu.cs
new file mode 100644
index 00000000..4946b2b2
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/CustomContextMenu.cs
@@ -0,0 +1,27 @@
+using System.Windows;
+using System.Windows.Controls;
+using Microsoft.Phone.Controls;
+using WMenuItem = Microsoft.Phone.Controls.MenuItem;
+using WApplication = System.Windows.Application;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public sealed class CustomContextMenu : ContextMenu
+ {
+ protected override DependencyObject GetContainerForItemOverride()
+ {
+ var item = new WMenuItem();
+ item.SetBinding(HeaderedItemsControl.HeaderProperty, new System.Windows.Data.Binding("Text") { Converter = (System.Windows.Data.IValueConverter)WApplication.Current.Resources["LowerConverter"] });
+
+ item.Click += (sender, args) =>
+ {
+ IsOpen = false;
+
+ var menuItem = item.DataContext as MenuItem;
+ if (menuItem != null)
+ menuItem.Activate();
+ };
+ return item;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/DataTemplateSelector.cs b/Xamarin.Forms.Platform.WP8/DataTemplateSelector.cs
new file mode 100644
index 00000000..6a9acca6
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/DataTemplateSelector.cs
@@ -0,0 +1,17 @@
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public abstract class DataTemplateSelector : ContentControl
+ {
+ public abstract System.Windows.DataTemplate SelectTemplate(object item, DependencyObject container);
+
+ protected override void OnContentChanged(object oldContent, object newContent)
+ {
+ base.OnContentChanged(oldContent, newContent);
+
+ ContentTemplate = SelectTemplate(newContent, this);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/DatePickerRenderer.cs b/Xamarin.Forms.Platform.WP8/DatePickerRenderer.cs
new file mode 100644
index 00000000..9553171b
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/DatePickerRenderer.cs
@@ -0,0 +1,59 @@
+using System;
+using System.ComponentModel;
+using System.Reflection;
+using Microsoft.Phone.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class DatePickerRenderer : ViewRenderer<DatePicker, Microsoft.Phone.Controls.DatePicker>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
+ {
+ base.OnElementChanged(e);
+
+ var datePicker = new Microsoft.Phone.Controls.DatePicker { Value = Element.Date };
+ datePicker.ValueChanged += DatePickerOnValueChanged;
+ SetNativeControl(datePicker);
+
+ UpdateFormatString();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "Date")
+ Control.Value = Element.Date;
+ else if (e.PropertyName == DatePicker.FormatProperty.PropertyName)
+ UpdateFormatString();
+ base.OnElementPropertyChanged(sender, e);
+ }
+
+ internal override void OnModelFocusChangeRequested(object sender, VisualElement.FocusRequestArgs args)
+ {
+ Microsoft.Phone.Controls.DatePicker control = Control;
+ if (control == null)
+ return;
+
+ if (args.Focus)
+ {
+ typeof(DateTimePickerBase).InvokeMember("OpenPickerPage", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, Type.DefaultBinder, control, null);
+ args.Result = true;
+ }
+ else
+ {
+ UnfocusControl(control);
+ args.Result = true;
+ }
+ }
+
+ void DatePickerOnValueChanged(object sender, DateTimeValueChangedEventArgs dateTimeValueChangedEventArgs)
+ {
+ if (Control.Value.HasValue)
+ ((IElementController)Element).SetValueFromRenderer(DatePicker.DateProperty, Control.Value.Value);
+ }
+
+ void UpdateFormatString()
+ {
+ Control.ValueStringFormat = "{0:" + Element.Format + "}";
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/Deserializer.cs b/Xamarin.Forms.Platform.WP8/Deserializer.cs
new file mode 100644
index 00000000..a0c2de00
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Deserializer.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO.IsolatedStorage;
+using System.Runtime.Serialization;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ internal class Deserializer : IDeserializer
+ {
+ const string PropertyStoreFile = "PropertyStore.forms";
+
+ public Task<IDictionary<string, object>> DeserializePropertiesAsync()
+ {
+ // Deserialize property dictionary to local storage
+ // Make sure to use Internal
+ return Task.Run(() =>
+ {
+ using(IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
+ using(IsolatedStorageFileStream stream = store.OpenFile(PropertyStoreFile, System.IO.FileMode.OpenOrCreate))
+ using(XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max))
+ {
+ if (stream.Length == 0)
+ return null;
+
+ try
+ {
+ var dcs = new DataContractSerializer(typeof(Dictionary<string, object>));
+ return (IDictionary<string, object>)dcs.ReadObject(reader);
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine("Could not deserialize properties: " + e.Message);
+ }
+ }
+
+ return null;
+ });
+ }
+
+ public Task SerializePropertiesAsync(IDictionary<string, object> properties)
+ {
+ properties = new Dictionary<string, object>(properties);
+ // Serialize property dictionary to local storage
+ // Make sure to use Internal
+ return Task.Run(() =>
+ {
+ var success = false;
+ using(IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
+ using(IsolatedStorageFileStream stream = store.OpenFile(PropertyStoreFile + ".tmp", System.IO.FileMode.OpenOrCreate))
+ using(XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(stream))
+ {
+ try
+ {
+ var dcs = new DataContractSerializer(typeof(Dictionary<string, object>));
+ dcs.WriteObject(writer, properties);
+ writer.Flush();
+ success = true;
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine("Could not serialize properties: " + e.Message);
+ }
+ }
+
+ if (!success)
+ return;
+ using(IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
+ {
+ try
+ {
+ if (store.FileExists(PropertyStoreFile))
+ store.DeleteFile(PropertyStoreFile);
+ store.MoveFile(PropertyStoreFile + ".tmp", PropertyStoreFile);
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine("Could not move new serialized property file over old: " + e.Message);
+ }
+ }
+ });
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/EditorRenderer.cs b/Xamarin.Forms.Platform.WP8/EditorRenderer.cs
new file mode 100644
index 00000000..500bcfae
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/EditorRenderer.cs
@@ -0,0 +1,108 @@
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class EditorRenderer : ViewRenderer<Editor, TextBox>
+ {
+ bool _fontApplied;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
+ {
+ base.OnElementChanged(e);
+
+ var textBox = new TextBox { VerticalScrollBarVisibility = ScrollBarVisibility.Visible, TextWrapping = TextWrapping.Wrap, AcceptsReturn = true };
+
+ SetNativeControl(textBox);
+
+ UpdateText();
+ UpdateInputScope();
+ UpdateTextColor();
+
+ Control.LostFocus += (sender, args) => Element.SendCompleted();
+
+ textBox.TextChanged += TextBoxOnTextChanged;
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Editor.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == InputView.KeyboardProperty.PropertyName)
+ UpdateInputScope();
+ else if (e.PropertyName == Editor.TextColorProperty.PropertyName)
+ UpdateTextColor();
+ else if (e.PropertyName == Editor.FontAttributesProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Editor.FontFamilyProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Editor.FontSizeProperty.PropertyName)
+ UpdateFont();
+ }
+
+ protected override void UpdateBackgroundColor()
+ {
+ Control.Background = Element.BackgroundColor == Color.Default ? (Brush)System.Windows.Application.Current.Resources["PhoneTextBoxBrush"] : Element.BackgroundColor.ToBrush();
+ }
+
+ void TextBoxOnTextChanged(object sender, System.Windows.Controls.TextChangedEventArgs textChangedEventArgs)
+ {
+ ((IElementController)Element).SetValueFromRenderer(Editor.TextProperty, Control.Text);
+ }
+
+ void UpdateFont()
+ {
+ if (Control == null)
+ return;
+
+ Editor editor = Element;
+
+ bool editorIsDefault = editor.FontFamily == null && editor.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(Editor), true) && editor.FontAttributes == FontAttributes.None;
+ if (editor == null || (editorIsDefault && !_fontApplied))
+ return;
+
+ if (editorIsDefault)
+ {
+ Control.ClearValue(System.Windows.Controls.Control.FontStyleProperty);
+ Control.ClearValue(System.Windows.Controls.Control.FontSizeProperty);
+ Control.ClearValue(System.Windows.Controls.Control.FontFamilyProperty);
+ Control.ClearValue(System.Windows.Controls.Control.FontWeightProperty);
+ Control.ClearValue(System.Windows.Controls.Control.FontStretchProperty);
+ }
+ else
+ Control.ApplyFont(editor);
+
+ _fontApplied = true;
+ }
+
+ void UpdateInputScope()
+ {
+ Control.InputScope = Element.Keyboard.ToInputScope();
+ }
+
+ void UpdateText()
+ {
+ string newText = Element.Text ?? "";
+
+ if (Control.Text == newText)
+ return;
+
+ Control.Text = newText;
+ Control.SelectionStart = Control.Text.Length;
+ }
+
+ void UpdateTextColor()
+ {
+ Color textColor = Element.TextColor;
+
+ if (textColor.IsDefault || !Element.IsEnabled)
+ Control.ClearValue(System.Windows.Controls.Control.ForegroundProperty);
+ else
+ Control.Foreground = textColor.ToBrush();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ElementChangedEventArgs.cs b/Xamarin.Forms.Platform.WP8/ElementChangedEventArgs.cs
new file mode 100644
index 00000000..903acb18
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ElementChangedEventArgs.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class VisualElementChangedEventArgs : ElementChangedEventArgs<VisualElement>
+ {
+ public VisualElementChangedEventArgs(VisualElement oldElement, VisualElement newElement) : base(oldElement, newElement)
+ {
+ }
+ }
+
+ public class ElementChangedEventArgs<TElement> : EventArgs where TElement : Element
+ {
+ public ElementChangedEventArgs(TElement oldElement, TElement newElement)
+ {
+ OldElement = oldElement;
+ NewElement = newElement;
+ }
+
+ public TElement NewElement { get; private set; }
+
+ public TElement OldElement { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/EntryRenderer.cs b/Xamarin.Forms.Platform.WP8/EntryRenderer.cs
new file mode 100644
index 00000000..f96ca312
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/EntryRenderer.cs
@@ -0,0 +1,324 @@
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Media;
+using static System.String;
+using WControl = System.Windows.Controls.Control;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ internal static class KeyboardExtensions
+ {
+ public static InputScope ToInputScope(this Keyboard self)
+ {
+ var result = new InputScope();
+ var name = new InputScopeName();
+ if (self == Keyboard.Default)
+ name.NameValue = InputScopeNameValue.Default;
+ else if (self == Keyboard.Chat)
+ name.NameValue = InputScopeNameValue.Chat;
+ else if (self == Keyboard.Email)
+ name.NameValue = InputScopeNameValue.EmailNameOrAddress;
+ else if (self == Keyboard.Numeric)
+ name.NameValue = InputScopeNameValue.Number;
+ else if (self == Keyboard.Telephone)
+ name.NameValue = InputScopeNameValue.TelephoneNumber;
+ else if (self == Keyboard.Text)
+ name.NameValue = InputScopeNameValue.Text;
+ else if (self == Keyboard.Url)
+ name.NameValue = InputScopeNameValue.Url;
+ else if (self is CustomKeyboard)
+ {
+ var custom = (CustomKeyboard)self;
+ bool capitalizedSentenceEnabled = (custom.Flags & KeyboardFlags.CapitalizeSentence) == KeyboardFlags.CapitalizeSentence;
+ bool spellcheckEnabled = (custom.Flags & KeyboardFlags.Spellcheck) == KeyboardFlags.Spellcheck;
+ bool suggestionsEnabled = (custom.Flags & KeyboardFlags.Suggestions) == KeyboardFlags.Suggestions;
+
+ if (!capitalizedSentenceEnabled && !spellcheckEnabled && !suggestionsEnabled)
+ name.NameValue = InputScopeNameValue.Default;
+ if (!capitalizedSentenceEnabled && !spellcheckEnabled && suggestionsEnabled)
+ name.NameValue = InputScopeNameValue.Search;
+ if (!capitalizedSentenceEnabled && spellcheckEnabled && !suggestionsEnabled)
+ {
+ Debug.WriteLine("Keyboard: Suggestions cannot be disabled in Windows Phone if spellcheck is enabled");
+ name.NameValue = InputScopeNameValue.Search;
+ }
+ if (!capitalizedSentenceEnabled && spellcheckEnabled && suggestionsEnabled)
+ name.NameValue = InputScopeNameValue.Search;
+ if (capitalizedSentenceEnabled && !spellcheckEnabled && !suggestionsEnabled)
+ {
+ Debug.WriteLine("Keyboard: Suggestions cannot be disabled in Windows Phone if auto Capitalization is enabled");
+ name.NameValue = InputScopeNameValue.Chat;
+ }
+ if (capitalizedSentenceEnabled && !spellcheckEnabled && suggestionsEnabled)
+ name.NameValue = InputScopeNameValue.Chat;
+ if (capitalizedSentenceEnabled && spellcheckEnabled && !suggestionsEnabled)
+ {
+ Debug.WriteLine("Keyboard: Suggestions cannot be disabled in Windows Phone if spellcheck is enabled");
+ name.NameValue = InputScopeNameValue.Text;
+ }
+ if (capitalizedSentenceEnabled && spellcheckEnabled && suggestionsEnabled)
+ name.NameValue = InputScopeNameValue.Text;
+ }
+ else
+ {
+ // Should never happens
+ name.NameValue = InputScopeNameValue.Default;
+ }
+ result.Names.Add(name);
+ return result;
+ }
+ }
+
+ public class EntryRenderer : ViewRenderer<Entry, FormsPhoneTextBox>
+ {
+ bool _fontApplied;
+ bool _ignoreTextChange;
+ Brush _placeholderDefaultBrush;
+
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ if (Children.Count == 0)
+ return new SizeRequest();
+
+ var constraint = new System.Windows.Size(widthConstraint, heightConstraint);
+
+ FormsPhoneTextBox child = Control;
+
+ double oldWidth = child.Width;
+ double oldHeight = child.Height;
+
+ child.Height = double.NaN;
+ child.Width = double.NaN;
+
+ child.Measure(constraint);
+ var result = new Size(Math.Ceiling(child.DesiredSize.Width), Math.Ceiling(child.DesiredSize.Height));
+
+ child.Width = oldWidth;
+ child.Height = oldHeight;
+
+ return new SizeRequest(result);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
+ {
+ base.OnElementChanged(e);
+
+ var textBox = new FormsPhoneTextBox();
+
+ SetNativeControl(textBox);
+
+ UpdateInputScope();
+ UpdateIsPassword();
+ UpdateText();
+ UpdatePlaceholder();
+ UpdateColor();
+ UpdateFont();
+ UpdateAlignment();
+ UpdatePlaceholderColor();
+ UpdateIsEnabled();
+
+ Control.LostFocus += OnTextBoxUnfocused;
+ Control.TextChanged += TextBoxOnTextChanged;
+ Control.KeyUp += TextBoxOnKeyUp;
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Entry.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Entry.PlaceholderProperty.PropertyName)
+ UpdatePlaceholder();
+ else if (e.PropertyName == Entry.IsPasswordProperty.PropertyName)
+ UpdateIsPassword();
+ else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled();
+ else if (e.PropertyName == Entry.TextColorProperty.PropertyName)
+ UpdateColor();
+ else if (e.PropertyName == InputView.KeyboardProperty.PropertyName)
+ UpdateInputScope();
+ else if (e.PropertyName == Entry.FontAttributesProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Entry.FontFamilyProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Entry.FontSizeProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Entry.HorizontalTextAlignmentProperty.PropertyName)
+ UpdateAlignment();
+ else if (e.PropertyName == Entry.PlaceholderColorProperty.PropertyName)
+ UpdatePlaceholderColor();
+ }
+
+ protected override void UpdateBackgroundColor()
+ {
+ Control.Background = Element.BackgroundColor.IsDefault ? (Brush)System.Windows.Application.Current.Resources["PhoneTextBoxBrush"] : Element.BackgroundColor.ToBrush();
+ }
+
+ internal override void OnModelFocusChangeRequested(object sender, VisualElement.FocusRequestArgs args)
+ {
+ if (args.Focus)
+ args.Result = Control.Focus();
+ else
+ {
+ UnfocusControl(Control);
+ args.Result = true;
+ }
+ }
+
+ void OnTextBoxUnfocused(object sender, RoutedEventArgs e)
+ {
+ if (Element.TextColor.IsDefault)
+ return;
+
+ if (!IsNullOrEmpty(Element.Text))
+ Control.Foreground = Element.TextColor.ToBrush();
+ }
+
+ void TextBoxOnKeyUp(object sender, KeyEventArgs keyEventArgs)
+ {
+ if (keyEventArgs.Key == Key.Enter)
+ Element.SendCompleted();
+ }
+
+ void TextBoxOnTextChanged(object sender, System.Windows.Controls.TextChangedEventArgs textChangedEventArgs)
+ {
+ // Signal to the UpdateText method that the change to TextProperty doesn't need to update the control
+ // This prevents the cursor position from getting lost
+ _ignoreTextChange = true;
+ ((IElementController)Element).SetValueFromRenderer(Entry.TextProperty, Control.Text);
+
+ // If an Entry.TextChanged handler modified the value of the Entry's text, the values could now be
+ // out-of-sync; re-sync them and force the TextBox cursor to the end of the text
+ string entryText = Element.Text;
+ if (Control.Text != entryText)
+ {
+ Control.Text = entryText;
+ Control.SelectionStart = Control.Text.Length;
+ }
+
+ _ignoreTextChange = false;
+ }
+
+ void UpdateAlignment()
+ {
+ if (Control == null)
+ return;
+
+ Control.TextAlignment = Element.HorizontalTextAlignment.ToNativeTextAlignment();
+ }
+
+ void UpdateColor()
+ {
+ if (Control == null)
+ return;
+
+ Entry entry = Element;
+ if (entry != null)
+ {
+ if (!IsNullOrEmpty(entry.Text))
+ {
+ if (!entry.TextColor.IsDefault)
+ Control.Foreground = entry.TextColor.ToBrush();
+ else
+ Control.Foreground = (Brush)WControl.ForegroundProperty.GetMetadata(typeof(FormsPhoneTextBox)).DefaultValue;
+
+ // Force the PhoneTextBox control to do some internal bookkeeping
+ // so the colors change immediately and remain changed when the control gets focus
+ Control.OnApplyTemplate();
+ }
+ }
+ else
+ Control.Foreground = (Brush)WControl.ForegroundProperty.GetMetadata(typeof(FormsPhoneTextBox)).DefaultValue;
+ }
+
+ void UpdateFont()
+ {
+ if (Control == null)
+ return;
+
+ Entry entry = Element;
+
+ if (entry == null)
+ return;
+
+ bool entryIsDefault = entry.FontFamily == null && entry.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(Entry), true) && entry.FontAttributes == FontAttributes.None;
+
+ if (entryIsDefault && !_fontApplied)
+ return;
+
+ if (entryIsDefault)
+ {
+ Control.ClearValue(WControl.FontStyleProperty);
+ Control.ClearValue(WControl.FontSizeProperty);
+ Control.ClearValue(WControl.FontFamilyProperty);
+ Control.ClearValue(WControl.FontWeightProperty);
+ Control.ClearValue(WControl.FontStretchProperty);
+ }
+ else
+ Control.ApplyFont(entry);
+
+ _fontApplied = true;
+ }
+
+ void UpdateInputScope()
+ {
+ Control.InputScope = Element.Keyboard.ToInputScope();
+ }
+
+ void UpdateIsEnabled()
+ {
+ Control.IsEnabled = Element.IsEnabled;
+ }
+
+ void UpdateIsPassword()
+ {
+ Control.IsPassword = Element.IsPassword;
+ }
+
+ void UpdatePlaceholder()
+ {
+ Control.Hint = Element.Placeholder ?? "";
+ }
+
+ void UpdatePlaceholderColor()
+ {
+ Color placeholderColor = Element.PlaceholderColor;
+
+ if (placeholderColor.IsDefault)
+ {
+ if (_placeholderDefaultBrush == null)
+ return;
+
+ // Use the cached default brush
+ Control.PlaceholderForegroundBrush = _placeholderDefaultBrush;
+ return;
+ }
+
+ if (_placeholderDefaultBrush == null)
+ {
+ // Cache the default brush in case we need to set the color back to default
+ _placeholderDefaultBrush = Control.PlaceholderForegroundBrush;
+ }
+
+ Control.PlaceholderForegroundBrush = placeholderColor.ToBrush();
+ }
+
+ void UpdateText()
+ {
+ // If the text property has changed because TextBoxOnTextChanged called SetValueFromRenderer,
+ // we don't want to re-update the text and reset the cursor position
+ if (_ignoreTextChange)
+ return;
+
+ if (Control.Text == Element.Text)
+ return;
+
+ Control.Text = Element.Text ?? "";
+ Control.Select(Control.Text.Length, 0);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ExportCellAttribute.cs b/Xamarin.Forms.Platform.WP8/ExportCellAttribute.cs
new file mode 100644
index 00000000..96aec6cb
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ExportCellAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class ExportCellAttribute : HandlerAttribute
+ {
+ public ExportCellAttribute(Type handler, Type target) : base(handler, target)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ExportImageSourceHandlerAttribute.cs b/Xamarin.Forms.Platform.WP8/ExportImageSourceHandlerAttribute.cs
new file mode 100644
index 00000000..4c5c01fb
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ExportImageSourceHandlerAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class ExportImageSourceHandlerAttribute : HandlerAttribute
+ {
+ public ExportImageSourceHandlerAttribute(Type handler, Type target) : base(handler, target)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ExportRendererAttribute.cs b/Xamarin.Forms.Platform.WP8/ExportRendererAttribute.cs
new file mode 100644
index 00000000..bf18653b
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ExportRendererAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class ExportRendererAttribute : HandlerAttribute
+ {
+ public ExportRendererAttribute(Type handler, Type target) : base(handler, target)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/Extensions.cs b/Xamarin.Forms.Platform.WP8/Extensions.cs
new file mode 100644
index 00000000..844c75ab
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Extensions.cs
@@ -0,0 +1,30 @@
+using Microsoft.Phone.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ internal static class Extensions
+ {
+ public static DeviceOrientation ToDeviceOrientation(this PageOrientation pageOrientation)
+ {
+ switch (pageOrientation)
+ {
+ case PageOrientation.None:
+ return DeviceOrientation.Other;
+ case PageOrientation.Portrait:
+ return DeviceOrientation.Portrait;
+ case PageOrientation.Landscape:
+ return DeviceOrientation.Landscape;
+ case PageOrientation.PortraitUp:
+ return DeviceOrientation.PortraitUp;
+ case PageOrientation.PortraitDown:
+ return DeviceOrientation.PortraitDown;
+ case PageOrientation.LandscapeRight:
+ return DeviceOrientation.LandscapeRight;
+ case PageOrientation.LandscapeLeft:
+ return DeviceOrientation.LandscapeLeft;
+ default:
+ return DeviceOrientation.Other;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/FontExtensions.cs b/Xamarin.Forms.Platform.WP8/FontExtensions.cs
new file mode 100644
index 00000000..186c6719
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/FontExtensions.cs
@@ -0,0 +1,162 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Media;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public static class FontExtensions
+ {
+ public static void ApplyFont(this Control self, Font font)
+ {
+ if (font.UseNamedSize)
+ {
+ switch (font.NamedSize)
+ {
+ case NamedSize.Micro:
+ self.FontSize = (double)System.Windows.Application.Current.Resources["PhoneFontSizeSmall"] - 3;
+ break;
+ case NamedSize.Small:
+ self.FontSize = (double)System.Windows.Application.Current.Resources["PhoneFontSizeSmall"];
+ break;
+ case NamedSize.Medium:
+ self.FontSize = (double)System.Windows.Application.Current.Resources["PhoneFontSizeMedium"];
+ // use medium instead of normal as this is the default for non-labels
+ break;
+ case NamedSize.Large:
+ self.FontSize = (double)System.Windows.Application.Current.Resources["PhoneFontSizeLarge"];
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ else
+ self.FontSize = font.FontSize;
+
+ if (!string.IsNullOrEmpty(font.FontFamily))
+ self.FontFamily = new FontFamily(font.FontFamily);
+ else
+ self.FontFamily = (FontFamily)System.Windows.Application.Current.Resources["PhoneFontFamilySemiBold"];
+
+ if (font.FontAttributes.HasFlag(FontAttributes.Italic))
+ self.FontStyle = FontStyles.Italic;
+ else
+ self.FontStyle = FontStyles.Normal;
+
+ if (font.FontAttributes.HasFlag(FontAttributes.Bold))
+ self.FontWeight = FontWeights.Bold;
+ else
+ self.FontWeight = FontWeights.Normal;
+ }
+
+ public static void ApplyFont(this TextBlock self, Font font)
+ {
+ if (font.UseNamedSize)
+ {
+ switch (font.NamedSize)
+ {
+ case NamedSize.Micro:
+ self.FontSize = (double)System.Windows.Application.Current.Resources["PhoneFontSizeSmall"] - 3;
+ break;
+ case NamedSize.Small:
+ self.FontSize = (double)System.Windows.Application.Current.Resources["PhoneFontSizeSmall"];
+ break;
+ case NamedSize.Medium:
+ self.FontSize = (double)System.Windows.Application.Current.Resources["PhoneFontSizeNormal"];
+ // use normal instead of medium as this is the default
+ break;
+ case NamedSize.Large:
+ self.FontSize = (double)System.Windows.Application.Current.Resources["PhoneFontSizeLarge"];
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ else
+ self.FontSize = font.FontSize;
+
+ if (!string.IsNullOrEmpty(font.FontFamily))
+ self.FontFamily = new FontFamily(font.FontFamily);
+ else
+ self.FontFamily = (FontFamily)System.Windows.Application.Current.Resources["PhoneFontFamilyNormal"];
+
+ if (font.FontAttributes.HasFlag(FontAttributes.Italic))
+ self.FontStyle = FontStyles.Italic;
+ else
+ self.FontStyle = FontStyles.Normal;
+
+ if (font.FontAttributes.HasFlag(FontAttributes.Bold))
+ self.FontWeight = FontWeights.Bold;
+ else
+ self.FontWeight = FontWeights.Normal;
+ }
+
+ public static void ApplyFont(this TextElement self, Font font)
+ {
+ if (font.UseNamedSize)
+ {
+ switch (font.NamedSize)
+ {
+ case NamedSize.Micro:
+ self.FontSize = (double)System.Windows.Application.Current.Resources["PhoneFontSizeSmall"] - 3;
+ break;
+ case NamedSize.Small:
+ self.FontSize = (double)System.Windows.Application.Current.Resources["PhoneFontSizeSmall"];
+ break;
+ case NamedSize.Medium:
+ self.FontSize = (double)System.Windows.Application.Current.Resources["PhoneFontSizeNormal"];
+ // use normal instead of medium as this is the default
+ break;
+ case NamedSize.Large:
+ self.FontSize = (double)System.Windows.Application.Current.Resources["PhoneFontSizeLarge"];
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ else
+ self.FontSize = font.FontSize;
+
+ if (!string.IsNullOrEmpty(font.FontFamily))
+ self.FontFamily = new FontFamily(font.FontFamily);
+ else
+ self.FontFamily = (FontFamily)System.Windows.Application.Current.Resources["PhoneFontFamilyNormal"];
+
+ if (font.FontAttributes.HasFlag(FontAttributes.Italic))
+ self.FontStyle = FontStyles.Italic;
+ else
+ self.FontStyle = FontStyles.Normal;
+
+ if (font.FontAttributes.HasFlag(FontAttributes.Bold))
+ self.FontWeight = FontWeights.Bold;
+ else
+ self.FontWeight = FontWeights.Normal;
+ }
+
+ internal static void ApplyFont(this Control self, IFontElement element)
+ {
+ self.FontSize = element.FontSize;
+
+ if (!string.IsNullOrEmpty(element.FontFamily))
+ self.FontFamily = new FontFamily(element.FontFamily);
+ else
+ self.FontFamily = (FontFamily)System.Windows.Application.Current.Resources["PhoneFontFamilySemiBold"];
+
+ if (element.FontAttributes.HasFlag(FontAttributes.Italic))
+ self.FontStyle = FontStyles.Italic;
+ else
+ self.FontStyle = FontStyles.Normal;
+
+ if (element.FontAttributes.HasFlag(FontAttributes.Bold))
+ self.FontWeight = FontWeights.Bold;
+ else
+ self.FontWeight = FontWeights.Normal;
+ }
+
+ internal static bool IsDefault(this IFontElement self)
+ {
+ return self.FontFamily == null && self.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(Label), true) && self.FontAttributes == FontAttributes.None;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/Forms.cs b/Xamarin.Forms.Platform.WP8/Forms.cs
new file mode 100644
index 00000000..b4435d3a
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Forms.cs
@@ -0,0 +1,254 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Windows;
+using System.Windows.Interop;
+using System.Windows.Media;
+using Microsoft.Phone.Controls;
+using Xamarin.Forms.Platform.WinPhone;
+
+using Expression = System.Linq.Expressions.Expression;
+
+
+namespace Xamarin.Forms
+{
+ public static class Forms
+ {
+ static bool s_isInitialized;
+
+ public static UIElement ConvertPageToUIElement(this Page page, PhoneApplicationPage applicationPage)
+ {
+ var application = new DefaultApplication();
+ application.MainPage = page;
+ var result = new Platform.WinPhone.Platform(applicationPage);
+ result.SetPage(page);
+ return result.GetCanvas();
+ }
+
+ public static void Init()
+ {
+ if (s_isInitialized)
+ return;
+
+ // Needed to prevent stripping of System.Windows.Interactivity
+ // which is current only referenced in the XAML DataTemplates
+ var eventTrigger = new System.Windows.Interactivity.EventTrigger();
+
+ string assemblyName = Assembly.GetExecutingAssembly().GetName().Name;
+
+ System.Windows.Application.Current.Resources.MergedDictionaries.Add(new System.Windows.ResourceDictionary
+ {
+ Source = new Uri(string.Format("/{0};component/WPResources.xaml", assemblyName), UriKind.Relative)
+ });
+
+ var accent = System.Windows.Application.Current.Resources["PhoneAccentBrush"] as SolidColorBrush;
+ System.Windows.Media.Color color = accent.Color;
+ Color.Accent = Color.FromRgba(color.R, color.G, color.B, color.A);
+
+ Log.Listeners.Add(new DelegateLogListener((c, m) => Console.WriteLine("[{0}] {1}", m, c)));
+
+ Device.OS = TargetPlatform.WinPhone;
+ Device.PlatformServices = new WP8PlatformServices();
+ Device.Info = new WP8DeviceInfo();
+
+ Registrar.RegisterAll(new[] { typeof(ExportRendererAttribute), typeof(ExportCellAttribute), typeof(ExportImageSourceHandlerAttribute) });
+
+ Ticker.Default = new WinPhoneTicker();
+
+ Device.Idiom = TargetIdiom.Phone;
+
+ ExpressionSearch.Default = new WinPhoneExpressionSearch();
+
+ s_isInitialized = true;
+ }
+
+ class DefaultApplication : Application
+ {
+ }
+
+ internal class WP8DeviceInfo : DeviceInfo
+ {
+ internal const string BWPorientationChangedName = "Xamarin.WP8.OrientationChanged";
+ readonly double _scalingFactor;
+
+ public WP8DeviceInfo()
+ {
+ MessagingCenter.Subscribe(this, BWPorientationChangedName, (FormsApplicationPage page, DeviceOrientation orientation) => { CurrentOrientation = orientation; });
+
+ Content content = System.Windows.Application.Current.Host.Content;
+
+ // Scaling Factor for Windows Phone 8 is relative to WVGA: https://msdn.microsoft.com/en-us/library/windows/apps/jj206974(v=vs.105).aspx
+ _scalingFactor = content.ScaleFactor / 100d;
+
+ PixelScreenSize = new Size(content.ActualWidth * _scalingFactor, content.ActualHeight * _scalingFactor);
+ ScaledScreenSize = new Size(content.ActualWidth, content.ActualHeight);
+ }
+
+ public override Size PixelScreenSize { get; }
+
+ public override Size ScaledScreenSize { get; }
+
+ public override double ScalingFactor
+ {
+ get { return _scalingFactor; }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ MessagingCenter.Unsubscribe<FormsApplicationPage, DeviceOrientation>(this, BWPorientationChangedName);
+ base.Dispose(disposing);
+ }
+ }
+
+ sealed class WinPhoneExpressionSearch : IExpressionSearch
+ {
+ List<object> _results;
+ Type _targeType;
+
+ public List<T> FindObjects<T>(Expression expression) where T : class
+ {
+ _results = new List<object>();
+ _targeType = typeof(T);
+
+ Visit(expression);
+
+ return _results.Select(o => o as T).ToList();
+ }
+
+ void Visit(Expression expression)
+ {
+ if (expression == null)
+ return;
+
+ switch (expression.NodeType)
+ {
+ case ExpressionType.Negate:
+ case ExpressionType.NegateChecked:
+ case ExpressionType.Not:
+ case ExpressionType.Convert:
+ case ExpressionType.ConvertChecked:
+ case ExpressionType.ArrayLength:
+ case ExpressionType.Quote:
+ case ExpressionType.TypeAs:
+ case ExpressionType.UnaryPlus:
+ Visit(((UnaryExpression)expression).Operand);
+ break;
+ case ExpressionType.Add:
+ case ExpressionType.AddChecked:
+ case ExpressionType.Subtract:
+ case ExpressionType.SubtractChecked:
+ case ExpressionType.Multiply:
+ case ExpressionType.MultiplyChecked:
+ case ExpressionType.Divide:
+ case ExpressionType.Modulo:
+ case ExpressionType.Power:
+ case ExpressionType.And:
+ case ExpressionType.AndAlso:
+ case ExpressionType.Or:
+ case ExpressionType.OrElse:
+ case ExpressionType.LessThan:
+ case ExpressionType.LessThanOrEqual:
+ case ExpressionType.GreaterThan:
+ case ExpressionType.GreaterThanOrEqual:
+ case ExpressionType.Equal:
+ case ExpressionType.NotEqual:
+ case ExpressionType.Coalesce:
+ case ExpressionType.ArrayIndex:
+ case ExpressionType.RightShift:
+ case ExpressionType.LeftShift:
+ case ExpressionType.ExclusiveOr:
+ var binary = (BinaryExpression)expression;
+ Visit(binary.Left);
+ Visit(binary.Right);
+ Visit(binary.Conversion);
+ break;
+ case ExpressionType.TypeIs:
+ Visit(((TypeBinaryExpression)expression).Expression);
+ break;
+ case ExpressionType.Conditional:
+ var conditional = (ConditionalExpression)expression;
+ Visit(conditional.Test);
+ Visit(conditional.IfTrue);
+ Visit(conditional.IfFalse);
+ break;
+ case ExpressionType.MemberAccess:
+ VisitMemberAccess((MemberExpression)expression);
+ break;
+ case ExpressionType.Call:
+ var methodCall = (MethodCallExpression)expression;
+ Visit(methodCall.Object);
+ VisitList(methodCall.Arguments, Visit);
+ break;
+ case ExpressionType.Lambda:
+ Visit(((LambdaExpression)expression).Body);
+ break;
+ case ExpressionType.New:
+ VisitList(((NewExpression)expression).Arguments, Visit);
+ break;
+ case ExpressionType.NewArrayInit:
+ case ExpressionType.NewArrayBounds:
+ VisitList(((NewArrayExpression)expression).Expressions, Visit);
+ break;
+ case ExpressionType.Invoke:
+ var invocation = (InvocationExpression)expression;
+ VisitList(invocation.Arguments, Visit);
+ Visit(invocation.Expression);
+ break;
+ case ExpressionType.MemberInit:
+ var init = (MemberInitExpression)expression;
+ VisitList(init.NewExpression.Arguments, Visit);
+ VisitList(init.Bindings, VisitBinding);
+ break;
+ case ExpressionType.ListInit:
+ var init1 = (ListInitExpression)expression;
+ VisitList(init1.NewExpression.Arguments, Visit);
+ VisitList(init1.Initializers, initializer => VisitList(initializer.Arguments, Visit));
+ break;
+ case ExpressionType.Constant:
+ break;
+ default:
+ throw new ArgumentException(string.Format("Unhandled expression type: '{0}'", expression.NodeType));
+ }
+ }
+
+ void VisitBinding(MemberBinding binding)
+ {
+ switch (binding.BindingType)
+ {
+ case MemberBindingType.Assignment:
+ Visit(((MemberAssignment)binding).Expression);
+ break;
+ case MemberBindingType.MemberBinding:
+ VisitList(((MemberMemberBinding)binding).Bindings, VisitBinding);
+ break;
+ case MemberBindingType.ListBinding:
+ VisitList(((MemberListBinding)binding).Initializers, initializer => VisitList(initializer.Arguments, Visit));
+ break;
+ default:
+ throw new ArgumentException(string.Format("Unhandled binding type '{0}'", binding.BindingType));
+ }
+ }
+
+ static void VisitList<TList>(IEnumerable<TList> list, Action<TList> visitor)
+ {
+ foreach (TList element in list)
+ visitor(element);
+ }
+
+ void VisitMemberAccess(MemberExpression member)
+ {
+ if (member.Expression is ConstantExpression && member.Member is FieldInfo)
+ {
+ object container = ((ConstantExpression)member.Expression).Value;
+ object value = ((FieldInfo)member.Member).GetValue(container);
+
+ if (_targeType.IsInstanceOfType(value))
+ _results.Add(value);
+ }
+ Visit(member.Expression);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/FormsApplicationPage.cs b/Xamarin.Forms.Platform.WP8/FormsApplicationPage.cs
new file mode 100644
index 00000000..ac6decb6
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/FormsApplicationPage.cs
@@ -0,0 +1,86 @@
+using System.ComponentModel;
+using Microsoft.Phone.Controls;
+using Microsoft.Phone.Shell;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class FormsApplicationPage : PhoneApplicationPage
+ {
+ Application _application;
+ Platform _platform;
+
+ protected FormsApplicationPage()
+ {
+ PhoneApplicationService.Current.Launching += OnLaunching;
+ PhoneApplicationService.Current.Activated += OnActivated;
+ PhoneApplicationService.Current.Deactivated += OnDeactivated;
+ PhoneApplicationService.Current.Closing += OnClosing;
+
+ MessagingCenter.Send(this, Forms.WP8DeviceInfo.BWPorientationChangedName, Orientation.ToDeviceOrientation());
+ OrientationChanged += OnOrientationChanged;
+ //DeserializePropertyStore ();
+ }
+
+ protected void LoadApplication(Application application)
+ {
+ Application.Current = application;
+ application.PropertyChanged += ApplicationOnPropertyChanged;
+ _application = application;
+
+ // Hack around the fact that OnLaunching will haev already happened by this point, sad but needed.
+ application.SendStart();
+
+ SetMainPage();
+ }
+
+ void ApplicationOnPropertyChanged(object sender, PropertyChangedEventArgs args)
+ {
+ if (args.PropertyName == "MainPage")
+ SetMainPage();
+ }
+
+ void OnActivated(object sender, ActivatedEventArgs e)
+ {
+ // TODO : figure out consistency of get this to fire
+ // Check whether tombstoned (terminated, but OS retains information about navigation state and state dictionarys) or dormant
+ _application.SendResume();
+ }
+
+ // when app gets tombstoned, user press back past first page
+ void OnClosing(object sender, ClosingEventArgs e)
+ {
+ // populate isolated storage.
+ //SerializePropertyStore ();
+ _application.SendSleepAsync().Wait();
+ }
+
+ void OnDeactivated(object sender, DeactivatedEventArgs e)
+ {
+ // populate state dictionaries, properties
+ //SerializePropertyStore ();
+ _application.SendSleepAsync().Wait();
+ }
+
+ void OnLaunching(object sender, LaunchingEventArgs e)
+ {
+ // TODO : not currently firing, is fired before MainPage ctor is called
+ _application.SendStart();
+ }
+
+ void OnOrientationChanged(object sender, OrientationChangedEventArgs e)
+ {
+ MessagingCenter.Send(this, Forms.WP8DeviceInfo.BWPorientationChangedName, e.Orientation.ToDeviceOrientation());
+ }
+
+ void SetMainPage()
+ {
+ if (_platform == null)
+ _platform = new Platform(this);
+
+ _platform.SetPage(_application.MainPage);
+
+ if (!ReferenceEquals(Content, _platform))
+ Content = _platform.GetCanvas();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/FormsListPicker.cs b/Xamarin.Forms.Platform.WP8/FormsListPicker.cs
new file mode 100644
index 00000000..573f639b
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/FormsListPicker.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Windows;
+using Microsoft.Phone.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class FormsListPicker : ListPicker
+ {
+ internal static readonly DependencyProperty ListPickerModeChangedProperty = DependencyProperty.Register("ListPickerMode", typeof(ListPickerMode), typeof(FormsListPicker),
+ new PropertyMetadata(ModeChanged));
+
+ protected virtual void OnListPickerModeChanged(DependencyPropertyChangedEventArgs args)
+ {
+ ListPickerModeChanged?.Invoke(this, args);
+ }
+
+ internal event EventHandler<DependencyPropertyChangedEventArgs> ListPickerModeChanged;
+
+ static void ModeChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
+ {
+ var listPicker = dependencyObject as FormsListPicker;
+ listPicker?.OnListPickerModeChanged(dependencyPropertyChangedEventArgs);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/FormsPhoneTextBox.cs b/Xamarin.Forms.Platform.WP8/FormsPhoneTextBox.cs
new file mode 100644
index 00000000..342646cd
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/FormsPhoneTextBox.cs
@@ -0,0 +1,236 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Media;
+using Microsoft.Phone.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ /// <summary>
+ /// An intermediate class for injecting bindings for things the default
+ /// textbox doesn't allow us to bind/modify
+ /// </summary>
+ public class FormsPhoneTextBox : PhoneTextBox
+ {
+ const char ObfuscationCharacter = '●';
+
+ public static readonly DependencyProperty PlaceholderForegroundBrushProperty = DependencyProperty.Register("PlaceholderForegroundBrush", typeof(Brush), typeof(FormsPhoneTextBox),
+ new PropertyMetadata(default(Brush)));
+
+ public static readonly DependencyProperty IsPasswordProperty = DependencyProperty.Register("IsPassword", typeof(bool), typeof(FormsPhoneTextBox),
+ new PropertyMetadata(default(bool), OnIsPasswordChanged));
+
+ public new static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(FormsPhoneTextBox), new PropertyMetadata("", TextPropertyChanged));
+
+ protected internal static readonly DependencyProperty DisabledTextProperty = DependencyProperty.Register("DisabledText", typeof(string), typeof(FormsPhoneTextBox), new PropertyMetadata(""));
+
+ static InputScope s_passwordInputScope;
+ InputScope _cachedInputScope;
+ CancellationTokenSource _cts;
+ bool _internalChangeFlag;
+
+ public FormsPhoneTextBox()
+ {
+ TextChanged += OnTextChanged;
+ SelectionChanged += OnSelectionChanged;
+ }
+
+ public bool IsPassword
+ {
+ get { return (bool)GetValue(IsPasswordProperty); }
+ set { SetValue(IsPasswordProperty, value); }
+ }
+
+ public Brush PlaceholderForegroundBrush
+ {
+ get { return (Brush)GetValue(PlaceholderForegroundBrushProperty); }
+ set { SetValue(PlaceholderForegroundBrushProperty, value); }
+ }
+
+ public new string Text
+ {
+ get { return (string)GetValue(TextProperty); }
+ set { SetValue(TextProperty, value); }
+ }
+
+ protected internal string DisabledText
+ {
+ get { return (string)GetValue(DisabledTextProperty); }
+ set { SetValue(DisabledTextProperty, value); }
+ }
+
+ static InputScope PasswordInputScope
+ {
+ get
+ {
+ if (s_passwordInputScope != null)
+ return s_passwordInputScope;
+
+ s_passwordInputScope = new InputScope();
+ var name = new InputScopeName { NameValue = InputScopeNameValue.Default };
+ s_passwordInputScope.Names.Add(name);
+
+ return s_passwordInputScope;
+ }
+ }
+
+ void DelayObfuscation()
+ {
+ int lengthDifference = base.Text.Length - Text.Length;
+
+ string updatedRealText = DetermineTextFromPassword(Text, base.Text);
+
+ if (Text == updatedRealText)
+ {
+ // Nothing to do
+ return;
+ }
+
+ Text = updatedRealText;
+
+ // Cancel any pending delayed obfuscation
+ _cts?.Cancel();
+ _cts = null;
+
+ string newText;
+
+ if (lengthDifference != 1)
+ {
+ // Either More than one character got added in this text change (e.g., a paste operation)
+ // Or characters were removed. Either way, we don't need to do the delayed obfuscation dance
+ newText = Obfuscate();
+ }
+ else
+ {
+ // Only one character was added; we need to leave it visible for a brief time period
+ // Obfuscate all but the last character for now
+ newText = Obfuscate(true);
+
+ // Leave the last character visible until a new character is added
+ // or sufficient time has passed
+ if (_cts == null)
+ _cts = new CancellationTokenSource();
+
+ Task.Run(async () =>
+ {
+ await Task.Delay(TimeSpan.FromSeconds(0.5), _cts.Token);
+ _cts.Token.ThrowIfCancellationRequested();
+ Dispatcher.BeginInvoke(() =>
+ {
+ base.Text = Obfuscate();
+ SelectionStart = base.Text.Length;
+ });
+ }, _cts.Token);
+ }
+
+ if (base.Text == newText)
+ return;
+
+ base.Text = newText;
+ SelectionStart = base.Text.Length;
+ }
+
+ static string DetermineTextFromPassword(string realText, string passwordText)
+ {
+ int firstObfuscationChar = passwordText.IndexOf(ObfuscationCharacter);
+
+ if (firstObfuscationChar > 0)
+ {
+ // The user is typing faster than we can process, and the text is coming in at the beginning
+ // of the textbox instead of the end
+ passwordText = passwordText.Substring(firstObfuscationChar, passwordText.Length - firstObfuscationChar) + passwordText.Substring(0, firstObfuscationChar);
+ }
+
+ if (realText.Length == passwordText.Length)
+ return realText;
+
+ if (passwordText.Length == 0)
+ return "";
+
+ if (passwordText.Length < realText.Length)
+ return realText.Substring(0, passwordText.Length);
+
+ int lengthDifference = passwordText.Length - realText.Length;
+
+ return realText + passwordText.Substring(passwordText.Length - lengthDifference, lengthDifference);
+ }
+
+ string Obfuscate(bool leaveLastVisible = false)
+ {
+ if (leaveLastVisible && Text.Length == 1)
+ return Text;
+
+ if (leaveLastVisible && Text.Length > 1)
+ return new string(ObfuscationCharacter, Text.Length - 1) + Text.Substring(Text.Length - 1, 1);
+
+ return new string(ObfuscationCharacter, Text.Length);
+ }
+
+ static void OnIsPasswordChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
+ {
+ var textBox = (FormsPhoneTextBox)dependencyObject;
+ textBox.UpdateInputScope();
+ textBox.SyncBaseText();
+ }
+
+ void OnSelectionChanged(object sender, RoutedEventArgs routedEventArgs)
+ {
+ if (!IsPassword)
+ return;
+
+ // Prevent the user from selecting any text in the password box by forcing all selection
+ // to zero-length at the end of the text
+ // This simulates the "do not allow clipboard copy" behavior the PasswordBox control has
+ if (SelectionLength > 0 || SelectionStart < Text.Length)
+ {
+ SelectionLength = 0;
+ SelectionStart = Text.Length;
+ }
+ }
+
+ void OnTextChanged(object sender, System.Windows.Controls.TextChangedEventArgs textChangedEventArgs)
+ {
+ if (IsPassword)
+ DelayObfuscation();
+ else if (base.Text != Text)
+ {
+ // Not in password mode, so we just need to make the "real" Text match
+ // what's in the textbox; the internalChange flag keeps the TextProperty
+ // synchronization from happening
+ _internalChangeFlag = true;
+ Text = base.Text;
+ _internalChangeFlag = false;
+ }
+ }
+
+ void SyncBaseText()
+ {
+ if (_internalChangeFlag)
+ return;
+
+ base.Text = IsPassword ? Obfuscate() : Text;
+ DisabledText = base.Text;
+
+ SelectionStart = base.Text.Length;
+ }
+
+ static void TextPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
+ {
+ var textBox = (FormsPhoneTextBox)dependencyObject;
+ textBox.SyncBaseText();
+ }
+
+ void UpdateInputScope()
+ {
+ if (IsPassword)
+ {
+ _cachedInputScope = InputScope;
+ InputScope = PasswordInputScope; // We don't want suggestions turned on if we're in password mode
+ }
+ else
+ InputScope = _cachedInputScope;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/FrameRenderer.cs b/Xamarin.Forms.Platform.WP8/FrameRenderer.cs
new file mode 100644
index 00000000..00472161
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/FrameRenderer.cs
@@ -0,0 +1,57 @@
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class FrameRenderer : ViewRenderer<Frame, Border>
+ {
+ public FrameRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
+ {
+ base.OnElementChanged(e);
+
+ SetNativeControl(new Border());
+
+ PackChild();
+ UpdateBorder();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == "Content")
+ PackChild();
+ else if (e.PropertyName == Frame.OutlineColorProperty.PropertyName || e.PropertyName == Frame.HasShadowProperty.PropertyName)
+ UpdateBorder();
+ }
+
+ void PackChild()
+ {
+ if (Element.Content == null)
+ return;
+
+ Platform.SetRenderer(Element.Content, Platform.CreateRenderer(Element.Content));
+
+ UIElement element = Platform.GetRenderer(Element.Content).ContainerElement;
+ Control.Child = element;
+ }
+
+ void UpdateBorder()
+ {
+ Control.CornerRadius = new CornerRadius(5);
+ if (Element.OutlineColor != Color.Default)
+ {
+ Control.BorderBrush = Element.OutlineColor.ToBrush();
+ Control.BorderThickness = new System.Windows.Thickness(1);
+ }
+ else
+ Control.BorderBrush = new Color(0, 0, 0, 0).ToBrush();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/FrameworkElementExtensions.cs b/Xamarin.Forms.Platform.WP8/FrameworkElementExtensions.cs
new file mode 100644
index 00000000..f8c77cef
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/FrameworkElementExtensions.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ internal static class FrameworkElementExtensions
+ {
+ static readonly Lazy<ConcurrentDictionary<Type, DependencyProperty>> ForegroundProperties =
+ new Lazy<ConcurrentDictionary<Type, DependencyProperty>>(() => new ConcurrentDictionary<Type, DependencyProperty>());
+
+ public static Brush GetForeground(this FrameworkElement element)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ return (Brush)element.GetValue(GetForegroundProperty(element));
+ }
+
+ public static System.Windows.Data.Binding GetForegroundBinding(this FrameworkElement element)
+ {
+ System.Windows.Data.BindingExpression expr = element.GetBindingExpression(GetForegroundProperty(element));
+ if (expr == null)
+ return null;
+
+ return expr.ParentBinding;
+ }
+
+ public static void SetForeground(this FrameworkElement element, Brush foregroundBrush)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ element.SetValue(GetForegroundProperty(element), foregroundBrush);
+ }
+
+ public static void SetForeground(this FrameworkElement element, System.Windows.Data.Binding binding)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ element.SetBinding(GetForegroundProperty(element), binding);
+ }
+
+ static DependencyProperty GetForegroundProperty(FrameworkElement element)
+ {
+ if (element is Control)
+ return Control.ForegroundProperty;
+ if (element is TextBlock)
+ return TextBlock.ForegroundProperty;
+
+ Type type = element.GetType();
+
+ DependencyProperty foregroundProperty;
+ if (!ForegroundProperties.Value.TryGetValue(type, out foregroundProperty))
+ {
+ FieldInfo field = type.GetFields(BindingFlags.Public | BindingFlags.Static).FirstOrDefault(f => f.Name == "ForegroundProperty");
+ if (field == null)
+ throw new ArgumentException("type is not a Foregroundable type");
+
+ var property = (DependencyProperty)field.GetValue(null);
+ ForegroundProperties.Value.TryAdd(type, property);
+
+ return property;
+ }
+
+ return foregroundProperty;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ICellRenderer.cs b/Xamarin.Forms.Platform.WP8/ICellRenderer.cs
new file mode 100644
index 00000000..350b72d6
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ICellRenderer.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public interface ICellRenderer : IRegisterable
+ {
+ System.Windows.DataTemplate GetTemplate(Cell cell);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/IVisualElementRenderer.cs b/Xamarin.Forms.Platform.WP8/IVisualElementRenderer.cs
new file mode 100644
index 00000000..c4e097cb
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/IVisualElementRenderer.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Windows;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public interface IVisualElementRenderer : IRegisterable
+ {
+ UIElement ContainerElement { get; }
+
+ VisualElement Element { get; }
+
+ event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint);
+
+ void SetElement(VisualElement element);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ImageRenderer.cs b/Xamarin.Forms.Platform.WP8/ImageRenderer.cs
new file mode 100644
index 00000000..8be9c15d
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ImageRenderer.cs
@@ -0,0 +1,166 @@
+using System;
+using System.ComponentModel;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ internal static class ImageExtensions
+ {
+ public static Stretch ToStretch(this Aspect aspect)
+ {
+ switch (aspect)
+ {
+ case Aspect.Fill:
+ return Stretch.Fill;
+ case Aspect.AspectFill:
+ return Stretch.UniformToFill;
+ default:
+ case Aspect.AspectFit:
+ return Stretch.Uniform;
+ }
+ }
+ }
+
+ public class ImageRenderer : ViewRenderer<Image, System.Windows.Controls.Image>
+ {
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ // Someone reported a NRE happening in this method which can only be explained by Control being null
+ // which only happens at the very beginning of the view lifecycle. Honest I have no idea how this might
+ // happen because it really shouldn't measure at that point. Add check anyway and live in fear...
+ if (Control?.Source == null)
+ return new SizeRequest();
+
+ var result = new Size { Width = ((BitmapImage)Control.Source).PixelWidth, Height = ((BitmapImage)Control.Source).PixelHeight };
+
+ return new SizeRequest(result);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var image = new System.Windows.Controls.Image();
+ SetNativeControl(image);
+ }
+
+ SetSource(Control);
+ SetAspect(Control);
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Image.SourceProperty.PropertyName)
+ SetSource(Control);
+ else if (e.PropertyName == Image.AspectProperty.PropertyName)
+ SetAspect(Control);
+ }
+
+ void SetAspect(System.Windows.Controls.Image image)
+ {
+ Aspect aspect = Element.Aspect;
+
+ image.Stretch = aspect.ToStretch();
+ }
+
+ async void SetSource(System.Windows.Controls.Image image)
+ {
+ ((IElementController)Element).SetValueFromRenderer(Image.IsLoadingPropertyKey, true);
+
+ ImageSource source = Element.Source;
+ IImageSourceHandler handler;
+ if (source != null && (handler = Registrar.Registered.GetHandler<IImageSourceHandler>(source.GetType())) != null)
+ {
+ System.Windows.Media.ImageSource imagesource;
+ try
+ {
+ imagesource = await handler.LoadImageAsync(source);
+ }
+ catch (TaskCanceledException)
+ {
+ imagesource = null;
+ }
+ image.Source = imagesource;
+ // if you dont at least measure the thing once it wont load the image
+ // then the whole thing falls over.
+ image.Measure(new System.Windows.Size(100, 100));
+ ((IVisualElementController)Element).NativeSizeChanged();
+ }
+ else
+ image.Source = null;
+
+ ((IElementController)Element).SetValueFromRenderer(Image.IsLoadingPropertyKey, false);
+ }
+ }
+
+ public interface IImageSourceHandler : IRegisterable
+ {
+ Task<System.Windows.Media.ImageSource> LoadImageAsync(ImageSource imagesoure, CancellationToken cancelationToken = default(CancellationToken));
+ }
+
+ public sealed class FileImageSourceHandler : IImageSourceHandler
+ {
+ public Task<System.Windows.Media.ImageSource> LoadImageAsync(ImageSource imagesoure, CancellationToken cancelationToken = new CancellationToken())
+ {
+ System.Windows.Media.ImageSource image = null;
+ var filesource = imagesoure as FileImageSource;
+ if (filesource != null)
+ {
+ string file = filesource.File;
+ image = new BitmapImage(new Uri("/" + file, UriKind.Relative));
+ }
+ return Task.FromResult(image);
+ }
+ }
+
+ public sealed class StreamImagesourceHandler : IImageSourceHandler
+ {
+ public async Task<System.Windows.Media.ImageSource> LoadImageAsync(ImageSource imagesource, CancellationToken cancelationToken = new CancellationToken())
+ {
+ BitmapImage bitmapimage = null;
+
+ var streamsource = imagesource as StreamImageSource;
+ if (streamsource != null && streamsource.Stream != null)
+ {
+ using(Stream stream = await streamsource.GetStreamAsync(cancelationToken))
+ {
+ bitmapimage = new BitmapImage();
+ bitmapimage.SetSource(stream);
+ }
+ }
+ return (System.Windows.Media.ImageSource)bitmapimage;
+ }
+ }
+
+ public sealed class ImageLoaderSourceHandler : IImageSourceHandler
+ {
+ public async Task<System.Windows.Media.ImageSource> LoadImageAsync(ImageSource imagesoure, CancellationToken cancelationToken = new CancellationToken())
+ {
+ BitmapImage bitmapimage = null;
+ var imageLoader = imagesoure as UriImageSource;
+ if (imageLoader != null && imageLoader.Uri != null)
+ {
+ using(Stream streamimage = await imageLoader.GetStreamAsync(cancelationToken))
+ {
+ if (streamimage != null && streamimage.CanRead)
+ {
+ bitmapimage = new BitmapImage();
+ bitmapimage.SetSource(streamimage);
+ }
+ }
+ }
+ return bitmapimage;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/LabelRenderer.cs b/Xamarin.Forms.Platform.WP8/LabelRenderer.cs
new file mode 100644
index 00000000..86c68adf
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/LabelRenderer.cs
@@ -0,0 +1,187 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Media;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public static class FormattedStringExtensions
+ {
+ public static IEnumerable<Inline> ToInlines(this FormattedString formattedString)
+ {
+ foreach (Span span in formattedString.Spans)
+ yield return span.ToRun();
+ }
+
+ public static Run ToRun(this Span span)
+ {
+ var run = new Run { Text = span.Text };
+
+ if (span.ForegroundColor != Color.Default)
+ run.Foreground = span.ForegroundColor.ToBrush();
+
+ if (!span.IsDefault())
+ run.ApplyFont(span.Font);
+
+ return run;
+ }
+ }
+
+ public class LabelRenderer : ViewRenderer<Label, TextBlock>
+ {
+ bool _fontApplied;
+
+ protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
+ {
+ if (Element == null)
+ return finalSize;
+ double childHeight = Math.Max(0, Math.Min(Element.Height, Control.DesiredSize.Height));
+ var rect = new Rect();
+
+ switch (Element.VerticalTextAlignment)
+ {
+ case TextAlignment.Start:
+ break;
+ default:
+ case TextAlignment.Center:
+ rect.Y = (int)((finalSize.Height - childHeight) / 2);
+ break;
+ case TextAlignment.End:
+ rect.Y = finalSize.Height - childHeight;
+ break;
+ }
+ rect.Height = childHeight;
+ rect.Width = finalSize.Width;
+ Control.Arrange(rect);
+ return finalSize;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
+ {
+ base.OnElementChanged(e);
+
+ var textBlock = new TextBlock { Foreground = (Brush)System.Windows.Application.Current.Resources["PhoneForegroundBrush"] };
+ UpdateText(textBlock);
+ UpdateColor(textBlock);
+ UpdateAlign(textBlock);
+ UpdateFont(textBlock);
+ UpdateLineBreakMode(textBlock);
+ SetNativeControl(textBlock);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Label.TextProperty.PropertyName || e.PropertyName == Label.FormattedTextProperty.PropertyName)
+ UpdateText(Control);
+ else if (e.PropertyName == Label.TextColorProperty.PropertyName)
+ UpdateColor(Control);
+ else if (e.PropertyName == Label.HorizontalTextAlignmentProperty.PropertyName || e.PropertyName == Label.VerticalTextAlignmentProperty.PropertyName)
+ UpdateAlign(Control);
+ else if (e.PropertyName == Label.FontProperty.PropertyName)
+ UpdateFont(Control);
+ else if (e.PropertyName == Label.LineBreakModeProperty.PropertyName)
+ UpdateLineBreakMode(Control);
+ base.OnElementPropertyChanged(sender, e);
+ }
+
+ void UpdateAlign(TextBlock textBlock)
+ {
+ if (textBlock == null)
+ return;
+
+ Label label = Element;
+ if (label == null)
+ return;
+
+ textBlock.TextAlignment = label.HorizontalTextAlignment.ToNativeTextAlignment();
+ textBlock.VerticalAlignment = label.VerticalTextAlignment.ToNativeVerticalAlignment();
+ }
+
+ void UpdateColor(TextBlock textBlock)
+ {
+ if (textBlock == null)
+ return;
+
+ Label label = Element;
+ if (label != null && label.TextColor != Color.Default)
+ textBlock.Foreground = label.TextColor.ToBrush();
+ else
+ textBlock.Foreground = (Brush)System.Windows.Application.Current.Resources["PhoneForegroundBrush"];
+ }
+
+ void UpdateFont(TextBlock textBlock)
+ {
+ if (textBlock == null)
+ return;
+
+ Label label = Element;
+ if (label == null || (label.IsDefault() && !_fontApplied))
+ return;
+
+ Font fontToApply = label.IsDefault() ? Font.SystemFontOfSize(NamedSize.Medium) : label.Font;
+
+ textBlock.ApplyFont(fontToApply);
+ _fontApplied = true;
+ }
+
+ void UpdateLineBreakMode(TextBlock textBlock)
+ {
+ if (textBlock == null)
+ return;
+
+ switch (Element.LineBreakMode)
+ {
+ case LineBreakMode.NoWrap:
+ textBlock.TextTrimming = TextTrimming.None;
+ textBlock.TextWrapping = TextWrapping.NoWrap;
+ break;
+ case LineBreakMode.WordWrap:
+ textBlock.TextTrimming = TextTrimming.None;
+ textBlock.TextWrapping = TextWrapping.Wrap;
+ break;
+ case LineBreakMode.CharacterWrap:
+ textBlock.TextTrimming = TextTrimming.WordEllipsis;
+ textBlock.TextWrapping = TextWrapping.Wrap;
+ break;
+ case LineBreakMode.HeadTruncation:
+ textBlock.TextTrimming = TextTrimming.WordEllipsis;
+ textBlock.TextWrapping = TextWrapping.NoWrap;
+ break;
+ case LineBreakMode.TailTruncation:
+ textBlock.TextTrimming = TextTrimming.WordEllipsis;
+ textBlock.TextWrapping = TextWrapping.NoWrap;
+ break;
+ case LineBreakMode.MiddleTruncation:
+ textBlock.TextTrimming = TextTrimming.WordEllipsis;
+ textBlock.TextWrapping = TextWrapping.NoWrap;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ void UpdateText(TextBlock textBlock)
+ {
+ if (textBlock == null)
+ return;
+
+ Label label = Element;
+ if (label != null)
+ {
+ if (label.FormattedText == null)
+ textBlock.Text = label.Text;
+ else
+ {
+ FormattedString formattedText = label.FormattedText ?? label.Text;
+
+ textBlock.Inlines.Clear();
+ foreach (Inline inline in formattedText.ToInlines())
+ textBlock.Inlines.Add(inline);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/LayoutExtensions.cs b/Xamarin.Forms.Platform.WP8/LayoutExtensions.cs
new file mode 100644
index 00000000..1fb1f247
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/LayoutExtensions.cs
@@ -0,0 +1,27 @@
+using System.Collections.Generic;
+using System.Windows;
+using WSize = System.Windows.Size;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public delegate SizeRequest? GetDesiredSizeDelegate(NativeViewWrapperRenderer renderer, double widthConstraint, double heightConstraint);
+
+ public delegate WSize? ArrangeOverrideDelegate(NativeViewWrapperRenderer renderer, WSize finalSize);
+
+ public delegate WSize? MeasureOverrideDelegate(NativeViewWrapperRenderer renderer, WSize availableSize);
+
+ public static class LayoutExtensions
+ {
+ public static void Add(this IList<View> children, FrameworkElement view, GetDesiredSizeDelegate getDesiredSizeDelegate = null, ArrangeOverrideDelegate arrangeOverrideDelegate = null,
+ MeasureOverrideDelegate measureOverrideDelegate = null)
+ {
+ children.Add(view.ToView(getDesiredSizeDelegate, arrangeOverrideDelegate, measureOverrideDelegate));
+ }
+
+ public static View ToView(this FrameworkElement view, GetDesiredSizeDelegate getDesiredSizeDelegate = null, ArrangeOverrideDelegate arrangeOverrideDelegate = null,
+ MeasureOverrideDelegate measureOverrideDelegate = null)
+ {
+ return new NativeViewWrapper(view, getDesiredSizeDelegate, arrangeOverrideDelegate, measureOverrideDelegate);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ListViewRenderer.cs b/Xamarin.Forms.Platform.WP8/ListViewRenderer.cs
new file mode 100644
index 00000000..362c993c
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ListViewRenderer.cs
@@ -0,0 +1,717 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Input;
+using System.Windows.Media;
+using Microsoft.Phone.Controls;
+using GestureEventArgs = System.Windows.Input.GestureEventArgs;
+using SLButton = System.Windows.Controls.Button;
+using SLBinding = System.Windows.Data.Binding;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ // Fixes a weird crash, don't ask.
+ internal class FixedLongListSelector : LongListSelector
+ {
+ bool _isInPullToRefresh;
+
+ System.Windows.Point _lastPosition;
+ double _pullToRefreshStatus;
+
+ public FixedLongListSelector()
+ {
+ Loaded += OnLoaded;
+ }
+
+ public bool IsInPullToRefresh
+ {
+ get { return _isInPullToRefresh; }
+ private set
+ {
+ if (_isInPullToRefresh == value)
+ return;
+ _isInPullToRefresh = value;
+
+ if (_isInPullToRefresh)
+ {
+ EventHandler handler = PullToRefreshStarted;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+ else
+ {
+ EventHandler handler = PullToRefreshStatus >= 1 ? PullToRefreshCompleted : PullToRefreshCanceled;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ _pullToRefreshStatus = 0;
+ }
+ }
+ }
+
+ public double PullToRefreshStatus
+ {
+ get { return _pullToRefreshStatus; }
+ set
+ {
+ if (_pullToRefreshStatus == value)
+ return;
+ _pullToRefreshStatus = value;
+ EventHandler handler = PullToRefreshStatusUpdated;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+ }
+
+ public ViewportControl ViewportControl { get; private set; }
+
+ bool ViewportAtTop
+ {
+ get { return ViewportControl.Viewport.Top == 0; }
+ }
+
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ if (ViewportControl != null)
+ {
+ ViewportControl.ViewportChanged -= OnViewportChanged;
+ ViewportControl.ManipulationStateChanged -= OnManipulationStateChanged;
+ }
+
+ ViewportControl = (ViewportControl)VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this, 0), 0), 0);
+ ViewportControl.ViewportChanged += OnViewportChanged;
+ ViewportControl.ManipulationStateChanged += OnManipulationStateChanged;
+ }
+
+ public event EventHandler PullToRefreshCanceled;
+
+ public event EventHandler PullToRefreshCompleted;
+
+ public event EventHandler PullToRefreshStarted;
+
+ public event EventHandler PullToRefreshStatusUpdated;
+
+ protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize)
+ {
+ try
+ {
+ return base.MeasureOverride(availableSize);
+ }
+ catch (ArgumentException)
+ {
+ return base.MeasureOverride(availableSize);
+ }
+ }
+
+ void OnFrameReported(object sender, TouchFrameEventArgs e)
+ {
+ TouchPoint touchPoint;
+ try
+ {
+ touchPoint = e.GetPrimaryTouchPoint(this);
+ }
+ catch (Exception)
+ {
+ return;
+ }
+
+ if (touchPoint == null || touchPoint.Action != TouchAction.Move)
+ return;
+
+ System.Windows.Point position = touchPoint.Position;
+
+ if (IsInPullToRefresh)
+ {
+ double delta = position.Y - _lastPosition.Y;
+ PullToRefreshStatus += delta / 150.0;
+ }
+
+ _lastPosition = position;
+ }
+
+ void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
+ {
+ Loaded -= OnLoaded;
+ Unloaded += OnUnloaded;
+
+ Touch.FrameReported += OnFrameReported;
+ }
+
+ void OnManipulationStateChanged(object o, ManipulationStateChangedEventArgs args)
+ {
+ switch (ViewportControl.ManipulationState)
+ {
+ case ManipulationState.Idle:
+ // thing is rested
+ IsInPullToRefresh = false;
+ break;
+ case ManipulationState.Manipulating:
+ // user interaction
+ IsInPullToRefresh = ViewportAtTop;
+ break;
+ case ManipulationState.Animating:
+ // user let go
+ IsInPullToRefresh = false;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ void OnUnloaded(object sender, RoutedEventArgs routedEventArgs)
+ {
+ Loaded += OnLoaded;
+ Unloaded -= OnUnloaded;
+
+ Touch.FrameReported -= OnFrameReported;
+ }
+
+ void OnViewportChanged(object o, ViewportChangedEventArgs args)
+ {
+ if (ViewportControl.ManipulationState == ManipulationState.Manipulating)
+ IsInPullToRefresh = ViewportAtTop;
+ }
+ }
+
+ public class ListViewRenderer : ViewRenderer<ListView, LongListSelector>
+ {
+ public static readonly DependencyProperty HighlightWhenSelectedProperty = DependencyProperty.RegisterAttached("HighlightWhenSelected", typeof(bool), typeof(ListViewRenderer),
+ new PropertyMetadata(false));
+
+ readonly List<Tuple<FrameworkElement, SLBinding, Brush>> _previousHighlights = new List<Tuple<FrameworkElement, SLBinding, Brush>>();
+
+ Animatable _animatable;
+ object _fromNative;
+ bool _itemNeedsSelecting;
+ FixedLongListSelector _listBox;
+ System.Windows.Controls.ProgressBar _progressBar;
+
+ ViewportControl _viewport;
+
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ SizeRequest result = base.GetDesiredSize(widthConstraint, heightConstraint);
+ result.Minimum = new Size(40, 40);
+ return result;
+ }
+
+ public static bool GetHighlightWhenSelected(DependencyObject dependencyObject)
+ {
+ return (bool)dependencyObject.GetValue(HighlightWhenSelectedProperty);
+ }
+
+ public static void SetHighlightWhenSelected(DependencyObject dependencyObject, bool value)
+ {
+ dependencyObject.SetValue(HighlightWhenSelectedProperty, value);
+ }
+
+ protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
+ {
+ System.Windows.Size result = base.ArrangeOverride(finalSize);
+
+ _progressBar.Measure(finalSize);
+ _progressBar.Arrange(new Rect(0, 0, finalSize.Width, _progressBar.DesiredSize.Height));
+
+ return result;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
+ {
+ base.OnElementChanged(e);
+
+ Element.ScrollToRequested += OnScrollToRequested;
+
+ if (Element.SelectedItem != null)
+ _itemNeedsSelecting = true;
+
+ _listBox = new FixedLongListSelector
+ {
+ DataContext = Element,
+ ItemsSource = Element.TemplatedItems,
+ ItemTemplate = (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["CellTemplate"],
+ GroupHeaderTemplate = (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["ListViewHeader"],
+ ListHeaderTemplate = (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["View"],
+ ListFooterTemplate = (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["View"]
+ };
+ _listBox.SetBinding(LongListSelector.IsGroupingEnabledProperty, new SLBinding("IsGroupingEnabled"));
+
+ _listBox.SelectionChanged += OnNativeSelectionChanged;
+ _listBox.Tap += OnNativeItemTapped;
+ _listBox.ItemRealized += OnItemRealized;
+
+ _listBox.PullToRefreshStarted += OnPullToRefreshStarted;
+ _listBox.PullToRefreshCompleted += OnPullToRefreshCompleted;
+ _listBox.PullToRefreshCanceled += OnPullToRefreshCanceled;
+ _listBox.PullToRefreshStatusUpdated += OnPullToRefreshStatusUpdated;
+
+ SetNativeControl(_listBox);
+
+ _progressBar = new System.Windows.Controls.ProgressBar { Maximum = 1, Visibility = Visibility.Collapsed };
+ Children.Add(_progressBar);
+
+ UpdateHeader();
+ UpdateFooter();
+ UpdateJumpList();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == ListView.SelectedItemProperty.PropertyName)
+ OnItemSelected(Element.SelectedItem);
+ else if (e.PropertyName == "HeaderElement")
+ UpdateHeader();
+ else if (e.PropertyName == "FooterElement")
+ UpdateFooter();
+ else if ((e.PropertyName == ListView.IsRefreshingProperty.PropertyName) || (e.PropertyName == ListView.IsPullToRefreshEnabledProperty.PropertyName) || (e.PropertyName == "CanRefresh"))
+ UpdateIsRefreshing();
+ else if (e.PropertyName == "GroupShortNameBinding")
+ UpdateJumpList();
+ }
+
+ protected override void UpdateNativeWidget()
+ {
+ base.UpdateNativeWidget();
+
+ if (_progressBar != null)
+ _progressBar.Width = Element.Width;
+ }
+
+ Cell FindCell(GestureEventArgs e, out FrameworkElement element)
+ {
+ Cell cell = null;
+ element = e.OriginalSource as FrameworkElement;
+ if (element != null)
+ cell = element.DataContext as Cell;
+
+ if (cell == null)
+ {
+ System.Windows.Point pos = e.GetPosition(_listBox);
+ IEnumerable<UIElement> elements = VisualTreeHelper.FindElementsInHostCoordinates(pos, _listBox);
+ foreach (FrameworkElement frameworkElement in elements.OfType<FrameworkElement>())
+ {
+ if ((cell = frameworkElement.DataContext as Cell) != null)
+ {
+ element = frameworkElement;
+ break;
+ }
+ }
+ }
+
+ return cell;
+ }
+
+ static IEnumerable<T> FindDescendants<T>(DependencyObject dobj) where T : DependencyObject
+ {
+ int count = VisualTreeHelper.GetChildrenCount(dobj);
+ for (var i = 0; i < count; i++)
+ {
+ DependencyObject element = VisualTreeHelper.GetChild(dobj, i);
+ if (element is T)
+ yield return (T)element;
+
+ foreach (T descendant in FindDescendants<T>(element))
+ yield return descendant;
+ }
+ }
+
+ FrameworkElement FindElement(Cell cell)
+ {
+ foreach (CellControl selector in FindDescendants<CellControl>(_listBox))
+ {
+ if (ReferenceEquals(cell, selector.DataContext))
+ return selector;
+ }
+
+ return null;
+ }
+
+ IEnumerable<FrameworkElement> FindHighlight(FrameworkElement element)
+ {
+ FrameworkElement parent = element;
+ while (true)
+ {
+ element = parent;
+ if (element is CellControl)
+ break;
+
+ parent = VisualTreeHelper.GetParent(element) as FrameworkElement;
+ if (parent == null)
+ {
+ parent = element;
+ break;
+ }
+ }
+
+ return FindHighlightCore(parent);
+ }
+
+ IEnumerable<FrameworkElement> FindHighlightCore(DependencyObject element)
+ {
+ int children = VisualTreeHelper.GetChildrenCount(element);
+ for (var i = 0; i < children; i++)
+ {
+ DependencyObject child = VisualTreeHelper.GetChild(element, i);
+
+ var label = child as LabelRenderer;
+ var childElement = child as FrameworkElement;
+ if (childElement != null && (GetHighlightWhenSelected(childElement) || label != null))
+ {
+ if (label != null)
+ yield return label.Control;
+ else
+ yield return childElement;
+ }
+
+ foreach (FrameworkElement recursedElement in FindHighlightCore(childElement))
+ yield return recursedElement;
+ }
+ }
+
+ double GetHeight(Dictionary<System.Windows.DataTemplate, FrameworkElement> reusables, System.Windows.DataTemplate template, object bindingContext)
+ {
+ double width = Control.ActualWidth;
+
+ FrameworkElement content;
+ if (!reusables.TryGetValue(template, out content))
+ {
+ content = (FrameworkElement)template.LoadContent();
+
+ // Windows Phone refuses to properly bind things on a first pass or even a second pass unless it has different content
+ // so we'll force it to cycle here the first time for each template.
+ content.DataContext = bindingContext;
+ content.Measure(new System.Windows.Size(width, double.PositiveInfinity));
+ content.DataContext = null;
+ content.Measure(new System.Windows.Size(width, double.PositiveInfinity));
+
+ var control = content as Control;
+ if (control != null)
+ {
+ // Since we're not adding to the visual tree, we need to inherit the font to measure correctly.
+ control.FontFamily = Control.FontFamily;
+ }
+
+ reusables[template] = content;
+ }
+
+ content.DataContext = bindingContext;
+ content.Measure(new System.Windows.Size(width, double.PositiveInfinity));
+ return content.DesiredSize.Height;
+ }
+
+ void OnItemRealized(object sender, ItemRealizationEventArgs e)
+ {
+ if (!_itemNeedsSelecting)
+ return;
+
+ var cell = e.Container.DataContext as Cell;
+ if (cell == null || !Equals(cell.BindingContext, Element.SelectedItem))
+ return;
+
+ _itemNeedsSelecting = false;
+ OnItemSelected(Element.SelectedItem);
+ }
+
+ void OnItemSelected(object selectedItem)
+ {
+ if (_fromNative != null && Equals(selectedItem, _fromNative))
+ {
+ _fromNative = null;
+ return;
+ }
+
+ RestorePreviousSelectedVisual();
+
+ if (selectedItem == null)
+ {
+ _listBox.SelectedItem = selectedItem;
+ return;
+ }
+
+ IEnumerable<CellControl> items = FindDescendants<CellControl>(_listBox);
+
+ CellControl item = items.FirstOrDefault(i =>
+ {
+ var cell = (Cell)i.DataContext;
+ return Equals(cell.BindingContext, selectedItem);
+ });
+
+ if (item == null)
+ {
+ _itemNeedsSelecting = true;
+ return;
+ }
+
+ SetSelectedVisual(item);
+ }
+
+ void OnNativeItemTapped(object sender, GestureEventArgs e)
+ {
+ var cell = (Cell)Control.SelectedItem;
+ if (cell == null)
+ return;
+
+ Cell parentCell = null;
+
+ if (Element.IsGroupingEnabled)
+ {
+ TemplatedItemsList<ItemsView<Cell>, Cell> til = TemplatedItemsList<ItemsView<Cell>, Cell>.GetGroup(cell);
+ parentCell = til.HeaderContent;
+ }
+
+ _fromNative = cell.BindingContext;
+
+ if (Element.IsGroupingEnabled)
+ {
+ Element.NotifyRowTapped(TemplatedItemsList<ItemsView<Cell>, Cell>.GetIndex(parentCell), TemplatedItemsList<ItemsView<Cell>, Cell>.GetIndex(cell));
+ }
+ else
+ Element.NotifyRowTapped(TemplatedItemsList<ItemsView<Cell>, Cell>.GetIndex(cell));
+ }
+
+ void OnNativeSelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (e.AddedItems.Count == 0)
+ return;
+
+ var cell = (Cell)e.AddedItems[0];
+ Cell parentCell = null;
+
+ if (cell == null)
+ {
+ RestorePreviousSelectedVisual();
+ return;
+ }
+
+ RestorePreviousSelectedVisual();
+ FrameworkElement element = FindElement(cell);
+ if (element != null)
+ SetSelectedVisual(element);
+ }
+
+ void OnPullToRefreshCanceled(object sender, EventArgs args)
+ {
+ if (Element.IsPullToRefreshEnabled && ((IListViewController)Element).RefreshAllowed)
+ _progressBar.Visibility = Visibility.Collapsed;
+ }
+
+ void OnPullToRefreshCompleted(object sender, EventArgs args)
+ {
+ if (Element.IsPullToRefreshEnabled && ((IListViewController)Element).RefreshAllowed)
+ {
+ _progressBar.IsIndeterminate = true;
+ ((IListViewController)Element).SendRefreshing();
+ }
+ }
+
+ void OnPullToRefreshStarted(object sender, EventArgs args)
+ {
+ if (Element.IsPullToRefreshEnabled && ((IListViewController)Element).RefreshAllowed)
+ {
+ _progressBar.Visibility = Visibility.Visible;
+ _progressBar.IsIndeterminate = false;
+ _progressBar.Value = Math.Max(0, Math.Min(1, _listBox.PullToRefreshStatus));
+ }
+ }
+
+ void OnPullToRefreshStatusUpdated(object sender, EventArgs eventArgs)
+ {
+ if (Element.IsPullToRefreshEnabled && ((IListViewController)Element).RefreshAllowed)
+ _progressBar.Value = Math.Max(0, Math.Min(1, _listBox.PullToRefreshStatus));
+ }
+
+ void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
+ {
+ if (_animatable == null && e.ShouldAnimate)
+ _animatable = new Animatable();
+
+ if (_viewport == null)
+ {
+ // Making sure we're actually loaded
+ if (VisualTreeHelper.GetChildrenCount(_listBox) == 0)
+ {
+ RoutedEventHandler handler = null;
+ handler = (o, args) =>
+ {
+ Control.Loaded -= handler;
+ OnScrollToRequested(sender, e);
+ };
+ Control.Loaded += handler;
+
+ return;
+ }
+ _viewport = (ViewportControl)VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(_listBox, 0), 0), 0);
+ if (_viewport.Viewport.Bottom == 0)
+ {
+ EventHandler<ViewportChangedEventArgs> viewportChanged = null;
+ viewportChanged = (o, args) =>
+ {
+ if (_viewport.Viewport.Bottom == 0)
+ return;
+
+ _viewport.ViewportChanged -= viewportChanged;
+ OnScrollToRequested(sender, e);
+ };
+ _viewport.ViewportChanged += viewportChanged;
+ return;
+ }
+ }
+
+ double y = 0;
+ double targetHeight = 0;
+ double targetHeaderHeight = 0;
+
+ var templateReusables = new Dictionary<System.Windows.DataTemplate, FrameworkElement>();
+
+ var found = false;
+
+ if (Element.IsGroupingEnabled)
+ {
+ for (var g = 0; g < Element.TemplatedItems.Count; g++)
+ {
+ if (found)
+ break;
+
+ TemplatedItemsList<ItemsView<Cell>, Cell> til = Element.TemplatedItems.GetGroup(g);
+
+ double headerHeight = GetHeight(templateReusables, Control.GroupHeaderTemplate, til);
+ y += headerHeight;
+
+ for (var i = 0; i < til.Count; i++)
+ {
+ Cell cell = til[i];
+
+ double contentHeight = GetHeight(templateReusables, Control.ItemTemplate, cell);
+
+ if ((ReferenceEquals(til.BindingContext, e.Group) || e.Group == null) && ReferenceEquals(cell.BindingContext, e.Item))
+ {
+ targetHeaderHeight = headerHeight;
+ targetHeight = contentHeight;
+ found = true;
+ break;
+ }
+
+ y += contentHeight;
+ }
+ }
+ }
+ else
+ {
+ for (var i = 0; i < Element.TemplatedItems.Count; i++)
+ {
+ Cell cell = Element.TemplatedItems[i];
+
+ double height = GetHeight(templateReusables, Control.ItemTemplate, cell);
+
+ if (ReferenceEquals(cell.BindingContext, e.Item))
+ {
+ found = true;
+ targetHeight = height;
+ break;
+ }
+
+ y += height;
+ }
+ }
+
+ if (!found)
+ return;
+
+ ScrollToPosition position = e.Position;
+ if (position == ScrollToPosition.MakeVisible)
+ {
+ if (y >= _viewport.Viewport.Top && y <= _viewport.Viewport.Bottom)
+ return;
+ if (y > _viewport.Viewport.Bottom)
+ position = ScrollToPosition.End;
+ else
+ position = ScrollToPosition.Start;
+ }
+
+ if (position == ScrollToPosition.Start && Element.IsGroupingEnabled)
+ y = y - targetHeaderHeight;
+ else if (position == ScrollToPosition.Center)
+ y = y - (_viewport.ActualHeight / 2 + targetHeight / 2);
+ else if (position == ScrollToPosition.End)
+ y = y - _viewport.ActualHeight + targetHeight;
+
+ double startY = _viewport.Viewport.Y;
+ double distance = y - startY;
+
+ if (e.ShouldAnimate)
+ {
+ var animation = new Animation(v => { _viewport.SetViewportOrigin(new System.Windows.Point(0, startY + distance * v)); });
+
+ animation.Commit(_animatable, "ScrollTo", length: 500, easing: Easing.CubicInOut);
+ }
+ else
+ _viewport.SetViewportOrigin(new System.Windows.Point(0, y));
+ }
+
+ void RestorePreviousSelectedVisual()
+ {
+ foreach (Tuple<FrameworkElement, SLBinding, Brush> highlight in _previousHighlights)
+ {
+ if (highlight.Item2 != null)
+ highlight.Item1.SetForeground(highlight.Item2);
+ else
+ highlight.Item1.SetForeground(highlight.Item3);
+ }
+
+ _previousHighlights.Clear();
+ }
+
+ void SetSelectedVisual(FrameworkElement element)
+ {
+ IEnumerable<FrameworkElement> highlightMes = FindHighlight(element);
+ foreach (FrameworkElement toHighlight in highlightMes)
+ {
+ Brush brush = null;
+ SLBinding binding = toHighlight.GetForegroundBinding();
+ if (binding == null)
+ brush = toHighlight.GetForeground();
+
+ _previousHighlights.Add(new Tuple<FrameworkElement, SLBinding, Brush>(toHighlight, binding, brush));
+ toHighlight.SetForeground((Brush)System.Windows.Application.Current.Resources["PhoneAccentBrush"]);
+ }
+ }
+
+ void UpdateFooter()
+ {
+ Control.ListFooter = ((IListViewController)Element).FooterElement;
+ }
+
+ void UpdateHeader()
+ {
+ Control.ListHeader = ((IListViewController)Element).HeaderElement;
+ }
+
+ void UpdateIsRefreshing()
+ {
+ if (Element.IsRefreshing)
+ {
+ _progressBar.Visibility = Visibility.Visible;
+ _progressBar.IsIndeterminate = true;
+ }
+ else
+ {
+ _progressBar.IsIndeterminate = false;
+ _progressBar.Visibility = _listBox.IsInPullToRefresh && Element.IsPullToRefreshEnabled && ((IListViewController)Element).RefreshAllowed ? Visibility.Visible : Visibility.Collapsed;
+ }
+ }
+
+ void UpdateJumpList()
+ {
+ if (_listBox.IsGroupingEnabled && Element.GroupShortNameBinding == null)
+ _listBox.JumpListStyle = null;
+ else
+ _listBox.JumpListStyle = (System.Windows.Style)System.Windows.Application.Current.Resources["HeaderJumpStyle"];
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/MD5.cs b/Xamarin.Forms.Platform.WP8/MD5.cs
new file mode 100644
index 00000000..2c0fc206
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/MD5.cs
@@ -0,0 +1,12 @@
+using System.Security.Cryptography;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ internal abstract class MD5 : HashAlgorithm
+ {
+ public MD5()
+ {
+ HashSizeValue = 128;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/MD5CryptoServiceProvider.cs b/Xamarin.Forms.Platform.WP8/MD5CryptoServiceProvider.cs
new file mode 100644
index 00000000..aa5eba7f
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/MD5CryptoServiceProvider.cs
@@ -0,0 +1,444 @@
+using System;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ internal sealed class MD5CryptoServiceProvider : MD5
+ {
+ const int BlockSizeBytes = 64;
+
+ static readonly uint[] K =
+ {
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122,
+ 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905,
+ 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039,
+ 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82,
+ 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+ };
+
+ uint[] _buff;
+ ulong _count;
+ uint[] _h;
+ byte[] _processingBuffer; // Used to start data when passed less than a block worth.
+ int _processingBufferCount; // Counts how much data we have stored that still needs processed.
+
+ public MD5CryptoServiceProvider()
+ {
+ _h = new uint[4];
+ _buff = new uint[16];
+ _processingBuffer = new byte[BlockSizeBytes];
+
+ Initialize();
+ }
+
+ public override void Initialize()
+ {
+ _count = 0;
+ _processingBufferCount = 0;
+
+ _h[0] = 0x67452301;
+ _h[1] = 0xefcdab89;
+ _h[2] = 0x98badcfe;
+ _h[3] = 0x10325476;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (_processingBuffer != null)
+ {
+ Array.Clear(_processingBuffer, 0, _processingBuffer.Length);
+ _processingBuffer = null;
+ }
+ if (_h != null)
+ {
+ Array.Clear(_h, 0, _h.Length);
+ _h = null;
+ }
+ if (_buff != null)
+ {
+ Array.Clear(_buff, 0, _buff.Length);
+ _buff = null;
+ }
+ }
+
+ protected override void HashCore(byte[] rgb, int ibStart, int cbSize)
+ {
+ int i;
+ State = 1;
+
+ if (_processingBufferCount != 0)
+ {
+ if (cbSize < BlockSizeBytes - _processingBufferCount)
+ {
+ Buffer.BlockCopy(rgb, ibStart, _processingBuffer, _processingBufferCount, cbSize);
+ _processingBufferCount += cbSize;
+ return;
+ }
+ i = BlockSizeBytes - _processingBufferCount;
+ Buffer.BlockCopy(rgb, ibStart, _processingBuffer, _processingBufferCount, i);
+ ProcessBlock(_processingBuffer, 0);
+ _processingBufferCount = 0;
+ ibStart += i;
+ cbSize -= i;
+ }
+
+ for (i = 0; i < cbSize - cbSize % BlockSizeBytes; i += BlockSizeBytes)
+ ProcessBlock(rgb, ibStart + i);
+
+ if (cbSize % BlockSizeBytes != 0)
+ {
+ Buffer.BlockCopy(rgb, cbSize - cbSize % BlockSizeBytes + ibStart, _processingBuffer, 0, cbSize % BlockSizeBytes);
+ _processingBufferCount = cbSize % BlockSizeBytes;
+ }
+ }
+
+ protected override byte[] HashFinal()
+ {
+ var hash = new byte[16];
+ int i, j;
+
+ ProcessFinalBlock(_processingBuffer, 0, _processingBufferCount);
+
+ for (i = 0; i < 4; i++)
+ {
+ for (j = 0; j < 4; j++)
+ hash[i * 4 + j] = (byte)(_h[i] >> j * 8);
+ }
+
+ return hash;
+ }
+
+ internal void AddLength(ulong length, byte[] buffer, int position)
+ {
+ buffer[position++] = (byte)length;
+ buffer[position++] = (byte)(length >> 8);
+ buffer[position++] = (byte)(length >> 16);
+ buffer[position++] = (byte)(length >> 24);
+ buffer[position++] = (byte)(length >> 32);
+ buffer[position++] = (byte)(length >> 40);
+ buffer[position++] = (byte)(length >> 48);
+ buffer[position] = (byte)(length >> 56);
+ }
+
+ void ProcessBlock(byte[] inputBuffer, int inputOffset)
+ {
+ uint a, b, c, d;
+ int i;
+
+ _count += BlockSizeBytes;
+
+ for (i = 0; i < 16; i++)
+ {
+ _buff[i] = inputBuffer[inputOffset + 4 * i] | ((uint)inputBuffer[inputOffset + 4 * i + 1] << 8) | ((uint)inputBuffer[inputOffset + 4 * i + 2] << 16) |
+ ((uint)inputBuffer[inputOffset + 4 * i + 3] << 24);
+ }
+
+ a = _h[0];
+ b = _h[1];
+ c = _h[2];
+ d = _h[3];
+
+ // This function was unrolled because it seems to be doubling our performance with current compiler/VM.
+ // Possibly roll up if this changes.
+
+ // ---- Round 1 --------
+
+ a += (((c ^ d) & b) ^ d) + K[0] + _buff[0];
+ a = (a << 7) | (a >> 25);
+ a += b;
+
+ d += (((b ^ c) & a) ^ c) + K[1] + _buff[1];
+ d = (d << 12) | (d >> 20);
+ d += a;
+
+ c += (((a ^ b) & d) ^ b) + K[2] + _buff[2];
+ c = (c << 17) | (c >> 15);
+ c += d;
+
+ b += (((d ^ a) & c) ^ a) + K[3] + _buff[3];
+ b = (b << 22) | (b >> 10);
+ b += c;
+
+ a += (((c ^ d) & b) ^ d) + K[4] + _buff[4];
+ a = (a << 7) | (a >> 25);
+ a += b;
+
+ d += (((b ^ c) & a) ^ c) + K[5] + _buff[5];
+ d = (d << 12) | (d >> 20);
+ d += a;
+
+ c += (((a ^ b) & d) ^ b) + K[6] + _buff[6];
+ c = (c << 17) | (c >> 15);
+ c += d;
+
+ b += (((d ^ a) & c) ^ a) + K[7] + _buff[7];
+ b = (b << 22) | (b >> 10);
+ b += c;
+
+ a += (((c ^ d) & b) ^ d) + K[8] + _buff[8];
+ a = (a << 7) | (a >> 25);
+ a += b;
+
+ d += (((b ^ c) & a) ^ c) + K[9] + _buff[9];
+ d = (d << 12) | (d >> 20);
+ d += a;
+
+ c += (((a ^ b) & d) ^ b) + K[10] + _buff[10];
+ c = (c << 17) | (c >> 15);
+ c += d;
+
+ b += (((d ^ a) & c) ^ a) + K[11] + _buff[11];
+ b = (b << 22) | (b >> 10);
+ b += c;
+
+ a += (((c ^ d) & b) ^ d) + K[12] + _buff[12];
+ a = (a << 7) | (a >> 25);
+ a += b;
+
+ d += (((b ^ c) & a) ^ c) + K[13] + _buff[13];
+ d = (d << 12) | (d >> 20);
+ d += a;
+
+ c += (((a ^ b) & d) ^ b) + K[14] + _buff[14];
+ c = (c << 17) | (c >> 15);
+ c += d;
+
+ b += (((d ^ a) & c) ^ a) + K[15] + _buff[15];
+ b = (b << 22) | (b >> 10);
+ b += c;
+
+ // ---- Round 2 --------
+
+ a += (((b ^ c) & d) ^ c) + K[16] + _buff[1];
+ a = (a << 5) | (a >> 27);
+ a += b;
+
+ d += (((a ^ b) & c) ^ b) + K[17] + _buff[6];
+ d = (d << 9) | (d >> 23);
+ d += a;
+
+ c += (((d ^ a) & b) ^ a) + K[18] + _buff[11];
+ c = (c << 14) | (c >> 18);
+ c += d;
+
+ b += (((c ^ d) & a) ^ d) + K[19] + _buff[0];
+ b = (b << 20) | (b >> 12);
+ b += c;
+
+ a += (((b ^ c) & d) ^ c) + K[20] + _buff[5];
+ a = (a << 5) | (a >> 27);
+ a += b;
+
+ d += (((a ^ b) & c) ^ b) + K[21] + _buff[10];
+ d = (d << 9) | (d >> 23);
+ d += a;
+
+ c += (((d ^ a) & b) ^ a) + K[22] + _buff[15];
+ c = (c << 14) | (c >> 18);
+ c += d;
+
+ b += (((c ^ d) & a) ^ d) + K[23] + _buff[4];
+ b = (b << 20) | (b >> 12);
+ b += c;
+
+ a += (((b ^ c) & d) ^ c) + K[24] + _buff[9];
+ a = (a << 5) | (a >> 27);
+ a += b;
+
+ d += (((a ^ b) & c) ^ b) + K[25] + _buff[14];
+ d = (d << 9) | (d >> 23);
+ d += a;
+
+ c += (((d ^ a) & b) ^ a) + K[26] + _buff[3];
+ c = (c << 14) | (c >> 18);
+ c += d;
+
+ b += (((c ^ d) & a) ^ d) + K[27] + _buff[8];
+ b = (b << 20) | (b >> 12);
+ b += c;
+
+ a += (((b ^ c) & d) ^ c) + K[28] + _buff[13];
+ a = (a << 5) | (a >> 27);
+ a += b;
+
+ d += (((a ^ b) & c) ^ b) + K[29] + _buff[2];
+ d = (d << 9) | (d >> 23);
+ d += a;
+
+ c += (((d ^ a) & b) ^ a) + K[30] + _buff[7];
+ c = (c << 14) | (c >> 18);
+ c += d;
+
+ b += (((c ^ d) & a) ^ d) + K[31] + _buff[12];
+ b = (b << 20) | (b >> 12);
+ b += c;
+
+ // ---- Round 3 --------
+
+ a += (b ^ c ^ d) + K[32] + _buff[5];
+ a = (a << 4) | (a >> 28);
+ a += b;
+
+ d += (a ^ b ^ c) + K[33] + _buff[8];
+ d = (d << 11) | (d >> 21);
+ d += a;
+
+ c += (d ^ a ^ b) + K[34] + _buff[11];
+ c = (c << 16) | (c >> 16);
+ c += d;
+
+ b += (c ^ d ^ a) + K[35] + _buff[14];
+ b = (b << 23) | (b >> 9);
+ b += c;
+
+ a += (b ^ c ^ d) + K[36] + _buff[1];
+ a = (a << 4) | (a >> 28);
+ a += b;
+
+ d += (a ^ b ^ c) + K[37] + _buff[4];
+ d = (d << 11) | (d >> 21);
+ d += a;
+
+ c += (d ^ a ^ b) + K[38] + _buff[7];
+ c = (c << 16) | (c >> 16);
+ c += d;
+
+ b += (c ^ d ^ a) + K[39] + _buff[10];
+ b = (b << 23) | (b >> 9);
+ b += c;
+
+ a += (b ^ c ^ d) + K[40] + _buff[13];
+ a = (a << 4) | (a >> 28);
+ a += b;
+
+ d += (a ^ b ^ c) + K[41] + _buff[0];
+ d = (d << 11) | (d >> 21);
+ d += a;
+
+ c += (d ^ a ^ b) + K[42] + _buff[3];
+ c = (c << 16) | (c >> 16);
+ c += d;
+
+ b += (c ^ d ^ a) + K[43] + _buff[6];
+ b = (b << 23) | (b >> 9);
+ b += c;
+
+ a += (b ^ c ^ d) + K[44] + _buff[9];
+ a = (a << 4) | (a >> 28);
+ a += b;
+
+ d += (a ^ b ^ c) + K[45] + _buff[12];
+ d = (d << 11) | (d >> 21);
+ d += a;
+
+ c += (d ^ a ^ b) + K[46] + _buff[15];
+ c = (c << 16) | (c >> 16);
+ c += d;
+
+ b += (c ^ d ^ a) + K[47] + _buff[2];
+ b = (b << 23) | (b >> 9);
+ b += c;
+
+ // ---- Round 4 --------
+
+ a += ((~d | b) ^ c) + K[48] + _buff[0];
+ a = (a << 6) | (a >> 26);
+ a += b;
+
+ d += ((~c | a) ^ b) + K[49] + _buff[7];
+ d = (d << 10) | (d >> 22);
+ d += a;
+
+ c += ((~b | d) ^ a) + K[50] + _buff[14];
+ c = (c << 15) | (c >> 17);
+ c += d;
+
+ b += ((~a | c) ^ d) + K[51] + _buff[5];
+ b = (b << 21) | (b >> 11);
+ b += c;
+
+ a += ((~d | b) ^ c) + K[52] + _buff[12];
+ a = (a << 6) | (a >> 26);
+ a += b;
+
+ d += ((~c | a) ^ b) + K[53] + _buff[3];
+ d = (d << 10) | (d >> 22);
+ d += a;
+
+ c += ((~b | d) ^ a) + K[54] + _buff[10];
+ c = (c << 15) | (c >> 17);
+ c += d;
+
+ b += ((~a | c) ^ d) + K[55] + _buff[1];
+ b = (b << 21) | (b >> 11);
+ b += c;
+
+ a += ((~d | b) ^ c) + K[56] + _buff[8];
+ a = (a << 6) | (a >> 26);
+ a += b;
+
+ d += ((~c | a) ^ b) + K[57] + _buff[15];
+ d = (d << 10) | (d >> 22);
+ d += a;
+
+ c += ((~b | d) ^ a) + K[58] + _buff[6];
+ c = (c << 15) | (c >> 17);
+ c += d;
+
+ b += ((~a | c) ^ d) + K[59] + _buff[13];
+ b = (b << 21) | (b >> 11);
+ b += c;
+
+ a += ((~d | b) ^ c) + K[60] + _buff[4];
+ a = (a << 6) | (a >> 26);
+ a += b;
+
+ d += ((~c | a) ^ b) + K[61] + _buff[11];
+ d = (d << 10) | (d >> 22);
+ d += a;
+
+ c += ((~b | d) ^ a) + K[62] + _buff[2];
+ c = (c << 15) | (c >> 17);
+ c += d;
+
+ b += ((~a | c) ^ d) + K[63] + _buff[9];
+ b = (b << 21) | (b >> 11);
+ b += c;
+
+ _h[0] += a;
+ _h[1] += b;
+ _h[2] += c;
+ _h[3] += d;
+ }
+
+ void ProcessFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
+ {
+ ulong total = _count + (ulong)inputCount;
+ var paddingSize = (int)(56 - total % BlockSizeBytes);
+
+ if (paddingSize < 1)
+ paddingSize += BlockSizeBytes;
+
+ var fooBuffer = new byte[inputCount + paddingSize + 8];
+
+ for (var i = 0; i < inputCount; i++)
+ fooBuffer[i] = inputBuffer[i + inputOffset];
+
+ fooBuffer[inputCount] = 0x80;
+ for (int i = inputCount + 1; i < inputCount + paddingSize; i++)
+ fooBuffer[i] = 0x00;
+
+ // I deal in bytes. The algorithm deals in bits.
+ ulong size = total << 3;
+ AddLength(size, fooBuffer, inputCount + paddingSize);
+ ProcessBlock(fooBuffer, 0);
+
+ if (inputCount + paddingSize + 8 == 128)
+ ProcessBlock(fooBuffer, 64);
+ }
+
+ ~MD5CryptoServiceProvider()
+ {
+ Dispose(false);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/MasterDetailRenderer.cs b/Xamarin.Forms.Platform.WP8/MasterDetailRenderer.cs
new file mode 100644
index 00000000..43796d92
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/MasterDetailRenderer.cs
@@ -0,0 +1,183 @@
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using Microsoft.Phone.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class MasterDetailRenderer : VisualElementRenderer<MasterDetailPage, FrameworkElement>
+ {
+ readonly SlideTransition _inTransition = new SlideTransition { Mode = SlideTransitionMode.SlideUpFadeIn };
+ readonly SlideTransition _outTransition = new SlideTransition { Mode = SlideTransitionMode.SlideDownFadeOut };
+ readonly Border _popup = new Border();
+ IVisualElementRenderer _detailRenderer;
+ IVisualElementRenderer _masterRenderer;
+
+ ITransition _toggleTransition;
+
+ public MasterDetailRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ public bool Visible { get; private set; }
+
+ protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
+ {
+ UpdateSizes(finalSize.Width, finalSize.Height);
+ return base.ArrangeOverride(finalSize);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<MasterDetailPage> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ e.OldElement.BackButtonPressed -= HandleBackButtonPressed;
+
+ if (e.NewElement != null)
+ e.NewElement.BackButtonPressed += HandleBackButtonPressed;
+
+ LoadDetail();
+ LoadMaster();
+
+ UpdateSizes(ActualWidth, ActualHeight);
+
+ Loaded += (sender, args) =>
+ {
+ if (Element.IsPresented)
+ Toggle();
+ Element.SendAppearing();
+ };
+ Unloaded += (sender, args) =>
+ {
+ Element.SendDisappearing();
+ if (Visible)
+ {
+ var platform = (Platform)Element.Platform;
+ Canvas container = platform.GetCanvas();
+
+ container.Children.Remove(_popup);
+ }
+ };
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == "Detail")
+ {
+ LoadDetail();
+ UpdateSizes(ActualWidth, ActualHeight);
+ }
+ else if (e.PropertyName == "Master")
+ {
+ LoadMaster();
+ UpdateSizes(ActualWidth, ActualHeight);
+ }
+ else if (e.PropertyName == MasterDetailPage.IsPresentedProperty.PropertyName)
+ {
+ if (Visible == Element.IsPresented)
+ return;
+ Toggle();
+ }
+ }
+
+ internal void Toggle()
+ {
+ var platform = Element.Platform as Platform;
+ Canvas container = platform.GetCanvas();
+
+ if (_toggleTransition != null)
+ return;
+
+ if (Visible)
+ {
+ _toggleTransition = _outTransition.GetTransition(_popup);
+ _toggleTransition.Begin();
+ _toggleTransition.Completed += (sender, args) =>
+ {
+ _toggleTransition.Stop();
+ container.Children.Remove(_popup);
+ _toggleTransition = null;
+ };
+ }
+ else
+ {
+ _popup.Child = _masterRenderer.ContainerElement;
+ container.Children.Add(_popup);
+
+ _toggleTransition = _inTransition.GetTransition(_popup);
+ _toggleTransition.Begin();
+
+ _toggleTransition.Completed += (sender, args) =>
+ {
+ _toggleTransition.Stop();
+ _toggleTransition = null;
+ };
+ }
+
+ Visible = !Visible;
+
+ ((IElementController)Element).SetValueFromRenderer(MasterDetailPage.IsPresentedProperty, Visible);
+ }
+
+ void HandleBackButtonPressed(object sender, BackButtonPressedEventArgs e)
+ {
+ if (Visible)
+ {
+ Toggle();
+ e.Handled = true;
+ }
+ }
+
+ void LoadDetail()
+ {
+ if (_detailRenderer != null)
+ Children.Remove(_detailRenderer.ContainerElement);
+
+ Page detail = Element.Detail;
+ if (Platform.GetRenderer(detail) == null)
+ Platform.SetRenderer(detail, Platform.CreateRenderer(detail));
+
+ _detailRenderer = Platform.GetRenderer(detail);
+
+ Children.Clear();
+ if (_detailRenderer != null)
+ Children.Add(_detailRenderer.ContainerElement);
+ }
+
+ void LoadMaster()
+ {
+ if (_masterRenderer != null && _popup != null)
+ _popup.Child = null;
+
+ Page master = Element.Master;
+ if (Platform.GetRenderer(master) == null)
+ Platform.SetRenderer(master, Platform.CreateRenderer(master));
+
+ _masterRenderer = Platform.GetRenderer(master);
+ var control = _masterRenderer as Panel;
+ if (control != null && master.BackgroundColor == Color.Default)
+ control.Background = Color.Black.ToBrush();
+ }
+
+ void UpdateSizes(double width, double height)
+ {
+ if (width <= 0 || height <= 0)
+ return;
+
+ var platform = Element.Platform as Platform;
+ Size screenSize = platform.Size;
+ Element.MasterBounds = new Rectangle(0, 0, screenSize.Width - 20, screenSize.Height - 20);
+ Element.DetailBounds = new Rectangle(0, 0, width, height);
+
+ _popup.Width = width - 20;
+ _popup.Height = height - 20;
+
+ Canvas.SetLeft(_popup, 10);
+ Canvas.SetTop(_popup, 10);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/NativeViewWrapper.cs b/Xamarin.Forms.Platform.WP8/NativeViewWrapper.cs
new file mode 100644
index 00000000..a28d0c9a
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/NativeViewWrapper.cs
@@ -0,0 +1,24 @@
+using System.Windows;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class NativeViewWrapper : View
+ {
+ public NativeViewWrapper(FrameworkElement nativeElement, GetDesiredSizeDelegate getDesiredSizeDelegate = null, ArrangeOverrideDelegate arrangeOverrideDelegate = null,
+ MeasureOverrideDelegate measureOverrideDelegate = null)
+ {
+ GetDesiredSizeDelegate = getDesiredSizeDelegate;
+ ArrangeOverrideDelegate = arrangeOverrideDelegate;
+ MeasureOverrideDelegate = measureOverrideDelegate;
+ NativeElement = nativeElement;
+ }
+
+ public ArrangeOverrideDelegate ArrangeOverrideDelegate { get; set; }
+
+ public GetDesiredSizeDelegate GetDesiredSizeDelegate { get; }
+
+ public MeasureOverrideDelegate MeasureOverrideDelegate { get; set; }
+
+ public FrameworkElement NativeElement { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/NativeViewWrapperRenderer.cs b/Xamarin.Forms.Platform.WP8/NativeViewWrapperRenderer.cs
new file mode 100644
index 00000000..e28dec94
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/NativeViewWrapperRenderer.cs
@@ -0,0 +1,62 @@
+using System.Windows;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class NativeViewWrapperRenderer : ViewRenderer<NativeViewWrapper, FrameworkElement>
+ {
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ if (Element?.GetDesiredSizeDelegate == null)
+ return base.GetDesiredSize(widthConstraint, heightConstraint);
+
+ // The user has specified a different implementation of GetDesiredSize
+ SizeRequest? result = Element.GetDesiredSizeDelegate(this, widthConstraint, heightConstraint);
+
+ // If the delegate returns a SizeRequest, we use it;
+ // if it returns null, fall back to the default implementation
+ return result ?? base.GetDesiredSize(widthConstraint, heightConstraint);
+ }
+
+ protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
+ {
+ if (Element?.ArrangeOverrideDelegate == null)
+ return base.ArrangeOverride(finalSize);
+
+ // The user has specified a different implementation of ArrangeOverride
+ System.Windows.Size? result = Element.ArrangeOverrideDelegate(this, finalSize);
+
+ // If the delegate returns a Size, we use it;
+ // if it returns null, fall back to the default implementation
+ return result ?? base.ArrangeOverride(finalSize);
+ }
+
+ protected System.Windows.Size MeasureOverride()
+ {
+ return MeasureOverride(new System.Windows.Size());
+ }
+
+ protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize)
+ {
+ if (Element?.MeasureOverrideDelegate == null)
+ return base.MeasureOverride(availableSize);
+
+ // The user has specified a different implementation of MeasureOverride
+ System.Windows.Size? result = Element.MeasureOverrideDelegate(this, availableSize);
+
+ // If the delegate returns a Size, we use it;
+ // if it returns null, fall back to the default implementation
+ return result ?? base.MeasureOverride(availableSize);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<NativeViewWrapper> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement == null)
+ {
+ SetNativeControl(Element.NativeElement);
+ Control.LayoutUpdated += (sender, args) => { Element?.InvalidateMeasure(InvalidationTrigger.MeasureChanged); };
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/NavigationMenuRenderer.cs b/Xamarin.Forms.Platform.WP8/NavigationMenuRenderer.cs
new file mode 100644
index 00000000..c5a983d3
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/NavigationMenuRenderer.cs
@@ -0,0 +1,85 @@
+using System;
+using System.ComponentModel;
+using System.Windows.Media.Imaging;
+using Microsoft.Phone.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ internal class NavigationMenuRenderer : ViewRenderer<NavigationMenu, System.Windows.Controls.Grid>
+ {
+ const int Spacing = 12;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<NavigationMenu> e)
+ {
+ base.OnElementChanged(e);
+
+ var grid = new System.Windows.Controls.Grid();
+ grid.ColumnDefinitions.Add(new System.Windows.Controls.ColumnDefinition { Width = System.Windows.GridLength.Auto });
+ grid.ColumnDefinitions.Add(new System.Windows.Controls.ColumnDefinition { Width = System.Windows.GridLength.Auto });
+
+ UpdateItems(grid);
+ SetNativeControl(grid);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ switch (e.PropertyName)
+ {
+ case "Targets":
+ UpdateItems(Control);
+ break;
+ }
+ }
+
+ TileSize GetSize()
+ {
+ return RenderSize.Width >= 210 * 2 + Spacing ? TileSize.Medium : TileSize.Default;
+ }
+
+ void UpdateItems(System.Windows.Controls.Grid grid)
+ {
+ grid.Children.Clear();
+
+ grid.RowDefinitions.Clear();
+
+ var x = 0;
+ var y = 0;
+ foreach (Page target in Element.Targets)
+ {
+ if (x > 1)
+ {
+ x = 0;
+ y++;
+ }
+
+ if (x == 0)
+ grid.RowDefinitions.Add(new System.Windows.Controls.RowDefinition());
+
+ var hubTile = new HubTile { Title = target.Title, Source = new BitmapImage(new Uri(target.Icon, UriKind.Relative)), Margin = new System.Windows.Thickness(0, 0, Spacing, Spacing) };
+
+ if (target.BackgroundColor != Color.Default)
+ hubTile.Background = target.BackgroundColor.ToBrush();
+
+ Page tmp = target;
+ hubTile.Tap += (sender, args) => Element.SendTargetSelected(tmp);
+
+ hubTile.SetValue(System.Windows.Controls.Grid.RowProperty, y);
+ hubTile.SetValue(System.Windows.Controls.Grid.ColumnProperty, x);
+ hubTile.Size = GetSize();
+
+ var weakRef = new WeakReference(hubTile);
+ SizeChanged += (sender, args) =>
+ {
+ if (weakRef.IsAlive)
+ ((HubTile)weakRef.Target).Size = GetSize();
+ ((IVisualElementController)Element).NativeSizeChanged();
+ };
+
+ x++;
+ grid.Children.Add(hubTile);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/NavigationPageRenderer.cs b/Xamarin.Forms.Platform.WP8/NavigationPageRenderer.cs
new file mode 100644
index 00000000..6f290107
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/NavigationPageRenderer.cs
@@ -0,0 +1,209 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class NavigationPageRenderer : VisualElementRenderer<NavigationPage, FrameworkElement>
+ {
+ Page _currentRoot;
+ bool _isRemoving;
+
+ public NavigationPageRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<NavigationPage> e)
+ {
+ base.OnElementChanged(e);
+
+ Debug.WriteLine("Warning, Windows Phone backend does not support NavigationPage, falling back to global navigation.");
+
+ Action init = () =>
+ {
+ Element.PushRequested += PageOnPushed;
+ Element.PopRequested += PageOnPopped;
+ Element.PopToRootRequested += PageOnPoppedToRoot;
+ Element.RemovePageRequested += RemovePageRequested;
+ Element.InsertPageBeforeRequested += ElementOnInsertPageBeforeRequested;
+ Element.PropertyChanged += OnElementPropertyChanged;
+
+ var platform = (Platform)Element.Platform;
+ Element.ContainerArea = new Rectangle(new Point(0, 0), platform.Size);
+
+ platform.SizeChanged += (sender, args) => Element.ContainerArea = new Rectangle(new Point(0, 0), platform.Size);
+
+ List<Page> stack = GetStack();
+ if (stack.Count > 0)
+ UpdateRootPage(stack);
+ else
+ return;
+
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ for (var i = 0; i < stack.Count; i++)
+ PageOnPushed(this, new NavigationRequestedEventArgs(stack[i], false, i != 0));
+ });
+ };
+
+ if (Element.Platform == null)
+ Element.PlatformSet += (sender, args) => init();
+ else
+ init();
+
+ Loaded += (sender, args) => Element.SendAppearing();
+ Unloaded += OnUnloaded;
+ }
+
+ void ElementOnInsertPageBeforeRequested(object sender, NavigationRequestedEventArgs eventArgs)
+ {
+ if (Element.Platform == null)
+ return;
+ var platform = Element.Platform as Platform;
+ if (platform != null)
+ ((INavigation)platform).InsertPageBefore(eventArgs.Page, eventArgs.BeforePage);
+
+ List<Page> stack = GetStack();
+ stack.Insert(stack.IndexOf(eventArgs.BeforePage), eventArgs.Page);
+
+ UpdateRootPage(stack);
+ }
+
+ List<Page> GetStack()
+ {
+ int count = Element.InternalChildren.Count;
+ var stack = new List<Page>(count);
+ for (var i = 0; i < count; i++)
+ stack.Add((Page)Element.InternalChildren[i]);
+
+ return stack;
+ }
+
+ void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName != "Parent" || Element.RealParent != null)
+ return;
+
+ var platform = Element.Platform as Platform;
+
+ if (platform == null)
+ return;
+
+ for (var i = 0; i < Element.LogicalChildren.Count; i++)
+ {
+ var page = Element.LogicalChildren[i] as Page;
+ if (page != null)
+ platform.RemovePage(page, false);
+ }
+ }
+
+ void OnUnloaded(object sender, RoutedEventArgs args)
+ {
+ Element.SendDisappearing();
+ }
+
+ void PageOnPopped(object sender, NavigationRequestedEventArgs eventArg)
+ {
+ if (Element.Platform == null)
+ return;
+ var platform = Element.Platform as Platform;
+ if (platform != null)
+ eventArg.Task = platform.Pop(Element, eventArg.Animated).ContinueWith((t, o) => true, null);
+ }
+
+ void PageOnPoppedToRoot(object sender, NavigationRequestedEventArgs eventArgs)
+ {
+ if (Element.Platform == null)
+ return;
+ var platform = Element.Platform as Platform;
+ if (platform != null)
+ eventArgs.Task = platform.PopToRoot(Element, eventArgs.Animated).ContinueWith((t, o) => true, null);
+ }
+
+ void PageOnPushed(object sender, NavigationRequestedEventArgs e)
+ {
+ if (Element.Platform == null)
+ return;
+ var platform = Element.Platform as Platform;
+ if (platform != null)
+ {
+ if (e.Page == Element.StackCopy.LastOrDefault())
+ e.Page.IgnoresContainerArea = true;
+ e.Task = platform.PushCore(e.Page, Element, e.Animated, e.Realize).ContinueWith((t, o) => true, null);
+ }
+ }
+
+ void RemovePageRequested(object sender, NavigationRequestedEventArgs eventArgs)
+ {
+ if (Element.Platform == null)
+ return;
+ var platform = Element.Platform as Platform;
+ if (platform != null)
+ ((INavigation)platform).RemovePage(eventArgs.Page);
+
+ List<Page> stack = GetStack();
+ stack.Remove(eventArgs.Page);
+ _isRemoving = true;
+ UpdateRootPage(stack);
+ _isRemoving = false;
+ }
+
+ void UpdateRootPage(IReadOnlyList<Page> stack)
+ {
+ Page first = stack.FirstOrDefault();
+ if (first == _currentRoot)
+ return;
+
+ if (Children.Count > 0)
+ {
+ var renderer = Children[0] as IVisualElementRenderer;
+ if (renderer != null)
+ {
+ Children.RemoveAt(0);
+
+ var page = renderer.Element as Page;
+ if (page != null)
+ page.IgnoresContainerArea = false;
+
+ if (!stack.Contains(renderer.Element))
+ Platform.SetRenderer(renderer.Element, null);
+ }
+ }
+
+ _currentRoot = first;
+
+ if (first == null)
+ return;
+
+ first.IgnoresContainerArea = true;
+
+ IVisualElementRenderer firstRenderer = Platform.GetRenderer(first);
+ if (firstRenderer == null)
+ {
+ firstRenderer = Platform.CreateRenderer(first);
+ Platform.SetRenderer(first, firstRenderer);
+ }
+ var uiElement = (UIElement)firstRenderer;
+ var platform = Element.Platform as Platform;
+ Canvas canvas = platform?.GetCanvas();
+
+ //We could be swapping the visible page,
+ //so let's make sure we remove it
+ if (canvas.Children.Contains(uiElement))
+ canvas.Children.Remove(uiElement);
+ Children.Add(uiElement);
+
+ // we removed the previous root page, and the new root page is the one being presented
+ // at this time there's only 1 page now on the stack (the navigationpage with root)
+ // we need to update the platform to set this root page as the visible again
+ bool updateRoot = Element.CurrentPage == first && _isRemoving;
+ if (updateRoot)
+ platform.SetCurrent(Element, false);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/PageRenderer.cs b/Xamarin.Forms.Platform.WP8/PageRenderer.cs
new file mode 100644
index 00000000..6ba89ab5
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/PageRenderer.cs
@@ -0,0 +1,18 @@
+using System.Windows.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class PageRenderer : VisualElementRenderer<Page, Panel>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
+ {
+ // Set prior to calling base
+ Tracker = new BackgroundTracker<Panel>(BackgroundProperty) { Model = Element, Element = this };
+
+ base.OnElementChanged(e);
+
+ Loaded += (sender, args) => Element.SendAppearing();
+ Unloaded += (sender, args) => Element.SendDisappearing();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/PageToRendererConverter.cs b/Xamarin.Forms.Platform.WP8/PageToRendererConverter.cs
new file mode 100644
index 00000000..2c809c58
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/PageToRendererConverter.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Globalization;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class PageToRendererConverter : System.Windows.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var page = value as Page;
+ if (page == null)
+ return null;
+
+ IVisualElementRenderer renderer = Platform.CreateRenderer(page);
+ Platform.SetRenderer(page, renderer);
+ return renderer;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/PickerRenderer.cs b/Xamarin.Forms.Platform.WP8/PickerRenderer.cs
new file mode 100644
index 00000000..f9cd2d81
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/PickerRenderer.cs
@@ -0,0 +1,256 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Reflection;
+using System.Windows;
+using System.Windows.Controls;
+using Microsoft.Phone.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class PickerRenderer : ViewRenderer<Picker, FrameworkElement>
+ {
+ bool _isChanging;
+
+ FormsListPicker _listPicker;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
+ {
+ _listPicker = new FormsListPicker();
+
+ UpdateAlignment();
+ UpdateIsEnabled();
+
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ ((ObservableList<string>)Element.Items).CollectionChanged -= ItemsCollectionChanged;
+
+ ((ObservableList<string>)Element.Items).CollectionChanged += ItemsCollectionChanged;
+
+ _listPicker.ItemTemplate = (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["PickerItemTemplate"];
+ _listPicker.FullModeItemTemplate = (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["PickerFullItemTemplate"];
+ _listPicker.ExpansionMode = ExpansionMode.FullScreenOnly;
+ _listPicker.Items.Add(new ItemViewModel(" ") { MaxHeight = 0 });
+
+ _listPicker.ListPickerModeChanged += ListPickerModeChanged;
+
+ var grid = new System.Windows.Controls.Grid { Children = { _listPicker }, MaxWidth = Device.Info.PixelScreenSize.Width };
+ SetNativeControl(grid);
+
+ UpdatePicker();
+ _listPicker.SelectionChanged += PickerSelectionChanged;
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+ if (e.PropertyName == Picker.TitleProperty.PropertyName)
+ _listPicker.FullModeHeader = Element.Title;
+
+ if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled();
+
+ if (e.PropertyName == Picker.SelectedIndexProperty.PropertyName)
+ {
+ if (Element.SelectedIndex >= 0 && Element.SelectedIndex < Element.Items.Count)
+ _listPicker.SelectedIndex = Element.SelectedIndex + 1;
+ }
+
+ if (e.PropertyName == View.HorizontalOptionsProperty.PropertyName)
+ UpdateAlignment();
+ }
+
+ protected override void OnGotFocus(object sender, RoutedEventArgs args)
+ {
+ // Do nothing. ListPickerModeChanged is handling the IsFocusProperty setter
+ // Required because FrameworkElement.GotFocus and FrameworkElement.LostFocus () are fired by ListPicker.Open ()
+ }
+
+ protected override void OnLostFocus(object sender, RoutedEventArgs args)
+ {
+ // Do nothing. ListPickerModeChanged is handling the IsFocusProperty setter
+ // Required because FrameworkElement.GotFocus and FrameworkElement.LostFocus () are fired by ListPicker.Open ()
+ }
+
+ protected override void UpdateNativeWidget()
+ {
+ base.UpdateNativeWidget();
+ UpdateIsEnabled();
+ }
+
+ internal override void OnModelFocusChangeRequested(object sender, VisualElement.FocusRequestArgs args)
+ {
+ if (Control == null)
+ return;
+
+ if (args.Focus)
+ args.Result = OpenPickerPage();
+ else
+ {
+ args.Result = ClosePickerPage();
+ UnfocusControl(_listPicker);
+ }
+ }
+
+ bool ClosePickerPage()
+ {
+ FieldInfo pickerPageField = typeof(ListPicker).GetField("_listPickerPage", BindingFlags.NonPublic | BindingFlags.Instance);
+ var pickerPage = pickerPageField.GetValue(Control) as ListPickerPage;
+ typeof(ListPickerPage).InvokeMember("ClosePickerPage", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, Type.DefaultBinder, pickerPage, null);
+
+ return true;
+ }
+
+ void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ UpdateItems();
+ }
+
+ void ListPickerModeChanged(object sender, DependencyPropertyChangedEventArgs e)
+ {
+ if (e.OldValue == null || e.NewValue == null)
+ return;
+
+ var oldVal = (ListPickerMode)e.OldValue;
+ var newVal = (ListPickerMode)e.NewValue;
+
+ if (oldVal == ListPickerMode.Normal && newVal == ListPickerMode.Full)
+ {
+ // Picker Page is now showing
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
+ }
+ else if (oldVal == ListPickerMode.Full && newVal == ListPickerMode.Normal)
+ {
+ // PickerPage is now dismissed
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ }
+ }
+
+ bool OpenPickerPage()
+ {
+ bool result = _listPicker.Open();
+
+ if (result)
+ return true;
+
+ return false;
+ }
+
+ void PickerSelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (_isChanging)
+ return;
+
+ var picker = (ListPicker)sender;
+
+ // initializing picker
+ if (picker.SelectedIndex == -1)
+ return;
+
+ int elementSelectedIndex = picker.SelectedIndex - 1;
+ ((IElementController)Element).SetValueFromRenderer(Picker.SelectedIndexProperty, elementSelectedIndex);
+ }
+
+ void UpdateAlignment()
+ {
+ if (Element.HorizontalOptions.Alignment != LayoutAlignment.Fill)
+ _listPicker.HorizontalAlignment = HorizontalAlignment.Left;
+ }
+
+ void UpdateIsEnabled()
+ {
+ if (_listPicker != null)
+ _listPicker.IsEnabled = Element.IsEnabled;
+ }
+
+ void UpdateItems()
+ {
+ // supress notification of non-user generated events (e.g. adding\syncing list values)
+ _isChanging = true;
+ FormsListPicker picker = _listPicker;
+ // add/remove slots from control to match element
+ while (picker.Items.Count < Element.Items.Count + 1)
+ picker.Items.Add(new ItemViewModel(string.Empty));
+
+ while (picker.Items.Count > Element.Items.Count + 1)
+ picker.Items.RemoveAt(picker.Items.Count - 1);
+
+ // update all control values to match element values
+ for (var i = 0; i < Element.Items.Count; i++)
+ {
+ var item = (ItemViewModel)picker.Items[i + 1];
+ if (item.Data == Element.Items[i])
+ continue;
+
+ item.Data = Element.Items[i];
+ }
+
+ picker.SelectedIndex = Element.SelectedIndex + 1;
+
+ _isChanging = false;
+ }
+
+ void UpdatePicker()
+ {
+ _listPicker.FullModeHeader = Element.Title;
+ UpdateItems();
+ _listPicker.SelectedIndex = Element.SelectedIndex + 1;
+ }
+
+ class ItemViewModel : INotifyPropertyChanged
+ {
+ string _data;
+ int _maxHeight;
+ float _opacity;
+
+ public ItemViewModel(string item)
+ {
+ _opacity = 1;
+ _data = item;
+ _maxHeight = int.MaxValue;
+ }
+
+ public string Data
+ {
+ get { return _data; }
+ set
+ {
+ if (value == _data)
+ return;
+
+ _data = value;
+ PropertyChanged(this, new PropertyChangedEventArgs("Data"));
+ }
+ }
+
+ public int MaxHeight
+ {
+ get { return _maxHeight; }
+ set
+ {
+ if (value == _maxHeight)
+ return;
+
+ _maxHeight = value;
+ PropertyChanged(this, new PropertyChangedEventArgs("MaxHeight"));
+ }
+ }
+
+ public float Opacity
+ {
+ get { return _opacity; }
+ set
+ {
+ if (value == _opacity)
+ return;
+
+ _opacity = value;
+ PropertyChanged(this, new PropertyChangedEventArgs("Opacity"));
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged = delegate { };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/Platform.cs b/Xamarin.Forms.Platform.WP8/Platform.cs
new file mode 100644
index 00000000..363c6b84
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Platform.cs
@@ -0,0 +1,628 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using Microsoft.Phone.Controls;
+using Microsoft.Phone.Shell;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ // from mono
+ public class Platform : BindableObject, IPlatform, INavigation
+ {
+ internal static readonly BindableProperty RendererProperty = BindableProperty.CreateAttached("Renderer", typeof(IVisualElementRenderer), typeof(Platform), default(IVisualElementRenderer));
+
+ readonly TurnstileTransition _backwardInTransition = new TurnstileTransition { Mode = TurnstileTransitionMode.BackwardIn };
+
+ readonly TurnstileTransition _backwardOutTransition = new TurnstileTransition { Mode = TurnstileTransitionMode.BackwardOut };
+
+ readonly TurnstileTransition _forwardInTransition = new TurnstileTransition { Mode = TurnstileTransitionMode.ForwardIn };
+
+ readonly TurnstileTransition _forwardOutTransition = new TurnstileTransition { Mode = TurnstileTransitionMode.ForwardOut };
+
+ readonly NavigationModel _navModel = new NavigationModel();
+
+ readonly PhoneApplicationPage _page;
+
+ readonly Canvas _renderer;
+ readonly ToolbarTracker _tracker = new ToolbarTracker();
+
+ Page _currentDisplayedPage;
+ CustomMessageBox _visibleMessageBox;
+
+ internal Platform(PhoneApplicationPage page)
+ {
+ _tracker.SeparateMasterDetail = true;
+
+ page.BackKeyPress += OnBackKeyPress;
+ _page = page;
+
+ _renderer = new Canvas();
+ _renderer.SizeChanged += RendererSizeChanged;
+
+ _tracker.CollectionChanged += (sender, args) => UpdateToolbarItems();
+
+ ProgressIndicator indicator;
+ SystemTray.SetProgressIndicator(page, indicator = new ProgressIndicator { IsVisible = false, IsIndeterminate = true });
+
+ var busyCount = 0;
+ MessagingCenter.Subscribe(this, Page.BusySetSignalName, (Page sender, bool enabled) =>
+ {
+ busyCount = Math.Max(0, enabled ? busyCount + 1 : busyCount - 1);
+ indicator.IsVisible = busyCount > 0;
+ });
+
+ MessagingCenter.Subscribe(this, Page.AlertSignalName, (Page sender, AlertArguments arguments) =>
+ {
+ var messageBox = new CustomMessageBox { Title = arguments.Title, Message = arguments.Message };
+ if (arguments.Accept != null)
+ messageBox.LeftButtonContent = arguments.Accept;
+ messageBox.RightButtonContent = arguments.Cancel;
+ messageBox.Show();
+ _visibleMessageBox = messageBox;
+ messageBox.Dismissed += (o, args) =>
+ {
+ arguments.SetResult(args.Result == CustomMessageBoxResult.LeftButton);
+ _visibleMessageBox = null;
+ };
+ });
+
+ MessagingCenter.Subscribe(this, Page.ActionSheetSignalName, (Page sender, ActionSheetArguments arguments) =>
+ {
+ var messageBox = new CustomMessageBox { Title = arguments.Title };
+
+ var listBox = new ListBox { FontSize = 36, Margin = new System.Windows.Thickness(12) };
+ var itemSource = new List<string>();
+
+ if (!string.IsNullOrWhiteSpace(arguments.Destruction))
+ itemSource.Add(arguments.Destruction);
+ itemSource.AddRange(arguments.Buttons);
+ if (!string.IsNullOrWhiteSpace(arguments.Cancel))
+ itemSource.Add(arguments.Cancel);
+
+ listBox.ItemsSource = itemSource.Select(s => new TextBlock { Text = s, Margin = new System.Windows.Thickness(0, 12, 0, 12) });
+ messageBox.Content = listBox;
+
+ listBox.SelectionChanged += (o, args) => messageBox.Dismiss();
+ messageBox.Dismissed += (o, args) =>
+ {
+ string result = listBox.SelectedItem != null ? ((TextBlock)listBox.SelectedItem).Text : null;
+ arguments.SetResult(result);
+ _visibleMessageBox = null;
+ };
+
+ messageBox.Show();
+ _visibleMessageBox = messageBox;
+ });
+ }
+
+ internal Size Size
+ {
+ get { return new Size(_renderer.ActualWidth, _renderer.ActualHeight); }
+ }
+
+ Page Page { get; set; }
+
+ void INavigation.InsertPageBefore(Page page, Page before)
+ {
+ _navModel.InsertPageBefore(page, before);
+ }
+
+ IReadOnlyList<Page> INavigation.ModalStack
+ {
+ get { return _navModel.Roots.ToList(); }
+ }
+
+ IReadOnlyList<Page> INavigation.NavigationStack
+ {
+ get { return _navModel.Tree.Last(); }
+ }
+
+ Task<Page> INavigation.PopAsync()
+ {
+ return ((INavigation)this).PopAsync(true);
+ }
+
+ Task<Page> INavigation.PopAsync(bool animated)
+ {
+ return Pop(Page, animated);
+ }
+
+ Task<Page> INavigation.PopModalAsync()
+ {
+ return ((INavigation)this).PopModalAsync(true);
+ }
+
+ Task<Page> INavigation.PopModalAsync(bool animated)
+ {
+ var tcs = new TaskCompletionSource<Page>();
+ Page result = _navModel.PopModal();
+
+ IReadOnlyList<Page> last = _navModel.Tree.Last();
+ IEnumerable<Page> stack = last;
+ if (last.Count > 1)
+ stack = stack.Skip(1);
+
+ Page navRoot = stack.First();
+ Page current = _navModel.CurrentPage;
+ if (current == navRoot)
+ current = _navModel.Roots.Last(); // Navigation page itself, since nav root has a host
+
+ SetCurrent(current, animated, true, () => tcs.SetResult(result));
+ return tcs.Task;
+ }
+
+ Task INavigation.PopToRootAsync()
+ {
+ return ((INavigation)this).PopToRootAsync(true);
+ }
+
+ async Task INavigation.PopToRootAsync(bool animated)
+ {
+ await PopToRoot(Page, animated);
+ }
+
+ Task INavigation.PushAsync(Page root)
+ {
+ return ((INavigation)this).PushAsync(root, true);
+ }
+
+ Task INavigation.PushAsync(Page root, bool animated)
+ {
+ return Push(root, Page, animated);
+ }
+
+ Task INavigation.PushModalAsync(Page modal)
+ {
+ return ((INavigation)this).PushModalAsync(modal, true);
+ }
+
+ Task INavigation.PushModalAsync(Page modal, bool animated)
+ {
+ var tcs = new TaskCompletionSource<object>();
+ _navModel.PushModal(modal);
+ SetCurrent(_navModel.CurrentPage, animated, completedCallback: () => tcs.SetResult(null));
+ return tcs.Task;
+ }
+
+ void INavigation.RemovePage(Page page)
+ {
+ RemovePage(page, true);
+ }
+
+ SizeRequest IPlatform.GetNativeSize(VisualElement view, double widthConstraint, double heightConstraint)
+ {
+ // Hack around the fact that Canvas ignores the child constraints.
+ // It is entirely possible using Canvas as our base class is not wise.
+ // FIXME: This should not be an if statement. Probably need to define an interface here.
+ if (widthConstraint > 0 && heightConstraint > 0 && GetRenderer(view) != null)
+ {
+ IVisualElementRenderer element = GetRenderer(view);
+ return element.GetDesiredSize(widthConstraint, heightConstraint);
+ }
+
+ return new SizeRequest();
+ }
+
+ public static IVisualElementRenderer CreateRenderer(VisualElement element)
+ {
+ IVisualElementRenderer result = Registrar.Registered.GetHandler<IVisualElementRenderer>(element.GetType()) ?? new ViewRenderer();
+ result.SetElement(element);
+ return result;
+ }
+
+ public static IVisualElementRenderer GetRenderer(VisualElement self)
+ {
+ return (IVisualElementRenderer)self.GetValue(RendererProperty);
+ }
+
+ public static void SetRenderer(VisualElement self, IVisualElementRenderer renderer)
+ {
+ self.SetValue(RendererProperty, renderer);
+ self.IsPlatformEnabled = renderer != null;
+ }
+
+ internal Canvas GetCanvas()
+ {
+ return _renderer;
+ }
+
+ internal async Task<Page> Pop(Page ancestor, bool animated)
+ {
+ Page result = _navModel.Pop(ancestor);
+
+ Page navRoot = _navModel.Tree.Last().Skip(1).First();
+ Page current = _navModel.CurrentPage;
+
+ // The following code is a terrible horrible ugly hack that we are kind of stuck with for the time being
+ // Effectively what can happen is a TabbedPage with many navigation page children needs to have all those children in the
+ // nav stack. If you have multiple each of those roots needs to be skipped over.
+
+ // In general the check for the NavigationPage will always hit if the check for the Skip(1) hits, but since that check
+ // was always there it is left behind to ensure compatibility with previous behavior.
+ bool replaceWithRoot = current == navRoot;
+ var parent = current.Parent as NavigationPage;
+ if (parent != null)
+ {
+ if (parent.InternalChildren[0] == current)
+ replaceWithRoot = true;
+ }
+
+ if (replaceWithRoot)
+ current = _navModel.Roots.Last(); // Navigation page itself, since nav root has a host
+
+ await SetCurrent(current, animated, true);
+ return result;
+ }
+
+ internal async Task PopToRoot(Page ancestor, bool animated)
+ {
+ _navModel.PopToRoot(ancestor);
+ await SetCurrent(_navModel.CurrentPage, animated, true);
+ }
+
+ internal async Task PushCore(Page root, Page ancester, bool animated, bool realize = true)
+ {
+ _navModel.Push(root, ancester);
+ if (realize)
+ await SetCurrent(_navModel.CurrentPage, animated);
+
+ if (root.NavigationProxy.Inner == null)
+ root.NavigationProxy.Inner = this;
+ }
+
+ internal async void RemovePage(Page page, bool popCurrent)
+ {
+ if (popCurrent && _navModel.CurrentPage == page)
+ await ((INavigation)this).PopAsync();
+ else
+ _navModel.RemovePage(page);
+ }
+
+ internal Task SetCurrent(Page page, bool animated, bool popping = false, Action completedCallback = null)
+ {
+ var tcs = new TaskCompletionSource<bool>();
+ if (page == _currentDisplayedPage)
+ {
+ tcs.SetResult(true);
+ return tcs.Task;
+ }
+
+ if (!animated)
+ tcs.SetResult(true);
+
+ page.Platform = this;
+
+ if (GetRenderer(page) == null)
+ SetRenderer(page, CreateRenderer(page));
+
+ page.Layout(new Rectangle(0, 0, _renderer.ActualWidth, _renderer.ActualHeight));
+ IVisualElementRenderer pageRenderer = GetRenderer(page);
+ if (pageRenderer != null)
+ {
+ ((FrameworkElement)pageRenderer.ContainerElement).Width = _renderer.ActualWidth;
+ ((FrameworkElement)pageRenderer.ContainerElement).Height = _renderer.ActualHeight;
+ }
+
+ Page current = _currentDisplayedPage;
+ UIElement currentElement = null;
+ if (current != null)
+ currentElement = (UIElement)GetRenderer(current);
+
+ if (popping)
+ {
+ ITransition transitionOut = null;
+ if (current != null)
+ {
+ if (animated)
+ transitionOut = _backwardOutTransition.GetTransition(currentElement);
+ else
+ _renderer.Children.Remove(currentElement);
+ }
+
+ var pageElement = (UIElement)GetRenderer(page);
+
+ if (animated)
+ {
+ transitionOut.Completed += (s, e) =>
+ {
+ transitionOut.Stop();
+ _renderer.Children.Remove(currentElement);
+ UpdateToolbarTracker();
+
+ _renderer.Children.Add(pageElement);
+
+ ITransition transitionIn = _backwardInTransition.GetTransition(pageElement);
+ transitionIn.Completed += (si, ei) =>
+ {
+ transitionIn.Stop();
+ if (completedCallback != null)
+ completedCallback();
+
+ tcs.SetResult(true);
+ };
+ transitionIn.Begin();
+ };
+
+ transitionOut.Begin();
+ }
+ else
+ {
+ UpdateToolbarTracker();
+ _renderer.Children.Add(pageElement);
+ if (completedCallback != null)
+ completedCallback();
+ }
+ }
+ else
+ {
+ ITransition transitionOut = null;
+ if (current != null)
+ {
+ if (animated)
+ transitionOut = _forwardOutTransition.GetTransition(currentElement);
+ else
+ _renderer.Children.Remove(currentElement);
+ }
+
+ if (animated)
+ {
+ if (transitionOut != null)
+ {
+ transitionOut.Completed += (o, e) =>
+ {
+ _renderer.Children.Remove(currentElement);
+ transitionOut.Stop();
+
+ UpdateToolbarTracker();
+
+ var element = (UIElement)GetRenderer(page);
+ _renderer.Children.Add(element);
+ ITransition transitionIn = _forwardInTransition.GetTransition(element);
+ transitionIn.Completed += (s, ie) =>
+ {
+ transitionIn.Stop();
+ if (completedCallback != null)
+ completedCallback();
+ tcs.SetResult(true);
+ };
+ transitionIn.Begin();
+ };
+
+ transitionOut.Begin();
+ }
+ else
+ {
+ UpdateToolbarTracker();
+
+ _renderer.Children.Add((UIElement)GetRenderer(page));
+ ITransition transitionIn = _forwardInTransition.GetTransition((UIElement)GetRenderer(page));
+ transitionIn.Completed += (s, e) =>
+ {
+ transitionIn.Stop();
+ if (completedCallback != null)
+ completedCallback();
+
+ tcs.SetResult(true);
+ };
+ transitionIn.Begin();
+ }
+ }
+ else
+ {
+ _renderer.Children.Add((UIElement)GetRenderer(page));
+ UpdateToolbarTracker();
+ if (completedCallback != null)
+ completedCallback();
+ }
+ }
+
+ _currentDisplayedPage = page;
+
+ return tcs.Task;
+ }
+
+ internal void SetPage(Page newRoot)
+ {
+ if (newRoot == null)
+ return;
+
+ Page = newRoot;
+ _navModel.Clear();
+ _navModel.PushModal(newRoot);
+ SetCurrent(newRoot, false, true);
+
+ ((Application)newRoot.RealParent).NavigationProxy.Inner = this;
+ }
+
+ internal event EventHandler SizeChanged;
+
+ void OnBackKeyPress(object sender, CancelEventArgs e)
+ {
+ if (_visibleMessageBox != null)
+ {
+ _visibleMessageBox.Dismiss();
+ e.Cancel = true;
+ return;
+ }
+
+ Page lastRoot = _navModel.Roots.Last();
+
+ bool handled = lastRoot.SendBackButtonPressed();
+
+ e.Cancel = handled;
+ }
+
+ Task Push(Page root, Page ancester, bool animated)
+ {
+ return PushCore(root, ancester, animated);
+ }
+
+ void RendererSizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ UpdateFormSizes();
+ EventHandler handler = SizeChanged;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+
+ void UpdateFormSizes()
+ {
+ foreach (Page f in _navModel.Roots)
+ {
+ f.Layout(new Rectangle(0, 0, _renderer.ActualWidth, _renderer.ActualHeight));
+ IVisualElementRenderer pageRenderer = f.GetRenderer();
+ if (pageRenderer != null)
+ {
+ ((FrameworkElement)pageRenderer.ContainerElement).Width = _renderer.ActualWidth;
+ ((FrameworkElement)pageRenderer.ContainerElement).Height = _renderer.ActualHeight;
+ }
+ }
+ }
+
+ void UpdateToolbarItems()
+ {
+ if (_page.ApplicationBar == null)
+ _page.ApplicationBar = new ApplicationBar();
+
+ ToolbarItem[] items = _tracker.ToolbarItems.ToArray();
+ MasterDetailPage masterDetail = _tracker.Target.Descendants().Prepend(_tracker.Target).OfType<MasterDetailPage>().FirstOrDefault();
+
+ TaggedAppBarButton oldMasterDetailButton = _page.ApplicationBar.Buttons.OfType<TaggedAppBarButton>().FirstOrDefault(b => b.Tag is MasterDetailPage && b.Tag != masterDetail);
+
+ if (oldMasterDetailButton != null)
+ _page.ApplicationBar.Buttons.Remove(oldMasterDetailButton);
+
+ if (masterDetail != null)
+ {
+ if (masterDetail.ShouldShowToolbarButton())
+ {
+ if (_page.ApplicationBar.Buttons.OfType<TaggedAppBarButton>().All(b => b.Tag != masterDetail))
+ {
+ var button = new TaggedAppBarButton
+ {
+ IconUri = new Uri(masterDetail.Master.Icon ?? "ApplicationIcon.jpg", UriKind.Relative),
+ Text = masterDetail.Master.Title,
+ IsEnabled = true,
+ Tag = masterDetail
+ };
+ button.Click += (sender, args) =>
+ {
+ var masterDetailRenderer = GetRenderer(masterDetail) as MasterDetailRenderer;
+
+ if (masterDetailRenderer != null)
+ masterDetailRenderer.Toggle();
+ };
+ _page.ApplicationBar.Buttons.Add(button);
+ }
+ }
+ }
+
+ var buttonsToAdd = new List<TaggedAppBarButton>();
+ foreach (ToolbarItem item in items.Where(i => i.Order != ToolbarItemOrder.Secondary))
+ {
+ if (_page.ApplicationBar.Buttons.OfType<TaggedAppBarButton>().Any(b => b.Tag == item))
+ continue;
+
+ var button = new TaggedAppBarButton
+ {
+ IconUri = new Uri(item.Icon ?? "ApplicationIcon.jpg", UriKind.Relative),
+ Text = !string.IsNullOrWhiteSpace(item.Name) ? item.Text : (string)item.Icon ?? "ApplicationIcon.jpg",
+ IsEnabled = item.IsEnabled,
+ Tag = item
+ };
+ button.Click += (sender, args) => item.Activate();
+ buttonsToAdd.Add(button);
+ }
+
+ var menuItemsToAdd = new List<TaggedAppBarMenuItem>();
+ foreach (ToolbarItem item in items.Where(i => i.Order == ToolbarItemOrder.Secondary))
+ {
+ if (_page.ApplicationBar.MenuItems.OfType<TaggedAppBarMenuItem>().Any(b => b.Tag == item))
+ continue;
+
+ var button = new TaggedAppBarMenuItem { Text = !string.IsNullOrWhiteSpace(item.Name) ? item.Text : (string)item.Icon ?? "MenuItem", IsEnabled = true, Tag = item };
+ button.Click += (sender, args) => item.Activate();
+ menuItemsToAdd.Add(button);
+ }
+
+ TaggedAppBarButton[] deadButtons = _page.ApplicationBar.Buttons.OfType<TaggedAppBarButton>().Where(b => b.Tag is ToolbarItem && !items.Contains(b.Tag)).ToArray();
+
+ TaggedAppBarMenuItem[] deadMenuItems = _page.ApplicationBar.MenuItems.OfType<TaggedAppBarMenuItem>().Where(b => b.Tag is ToolbarItem && !items.Contains(b.Tag)).ToArray();
+
+ // we must remove the dead buttons before adding the new ones so we dont accidentally go over the limit during the tranistion
+ foreach (TaggedAppBarButton deadButton in deadButtons)
+ {
+ deadButton.Dispose();
+ _page.ApplicationBar.Buttons.Remove(deadButton);
+ }
+
+ foreach (TaggedAppBarMenuItem deadMenuItem in deadMenuItems)
+ _page.ApplicationBar.MenuItems.Remove(deadMenuItem);
+
+ // fixme, insert in order
+ foreach (TaggedAppBarButton newButton in buttonsToAdd)
+ _page.ApplicationBar.Buttons.Add(newButton);
+
+ foreach (TaggedAppBarMenuItem newMenuItem in menuItemsToAdd)
+ _page.ApplicationBar.MenuItems.Add(newMenuItem);
+
+ _page.ApplicationBar.IsVisible = _page.ApplicationBar.Buttons.Count > 0 || _page.ApplicationBar.MenuItems.Count > 0;
+ }
+
+ void UpdateToolbarTracker()
+ {
+ if (_navModel.Roots.Last() != null)
+ _tracker.Target = _navModel.Roots.Last();
+ }
+
+ class TaggedAppBarButton : ApplicationBarIconButton, IDisposable
+ {
+ bool _disposed;
+ object _tag;
+
+ public object Tag
+ {
+ get { return _tag; }
+ set
+ {
+ if (_tag == null && value is ToolbarItem)
+ (value as ToolbarItem).PropertyChanged += TaggedAppBarButton_PropertyChanged;
+ _tag = value;
+ }
+ }
+
+ public void Dispose()
+ {
+ if (_disposed)
+ return;
+ _disposed = true;
+
+ if (Tag != null && Tag is ToolbarItem)
+ (Tag as ToolbarItem).PropertyChanged -= TaggedAppBarButton_PropertyChanged;
+ }
+
+ void TaggedAppBarButton_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ var item = Tag as ToolbarItem;
+ if (item == null)
+ return;
+
+ if (e.PropertyName == MenuItem.IsEnabledProperty.PropertyName)
+ IsEnabled = item.IsEnabled;
+ else if (e.PropertyName == MenuItem.TextProperty.PropertyName)
+ Text = !string.IsNullOrWhiteSpace(item.Name) ? item.Text : (string)item.Icon ?? "ApplicationIcon.jpg";
+ else if (e.PropertyName == MenuItem.IconProperty.PropertyName)
+ IconUri = new Uri(item.Icon ?? "ApplicationIcon.jpg", UriKind.Relative);
+ }
+ }
+
+ class TaggedAppBarMenuItem : ApplicationBarMenuItem
+ {
+ public object Tag { get; set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/PlatformEffect.cs b/Xamarin.Forms.Platform.WP8/PlatformEffect.cs
new file mode 100644
index 00000000..3ee0f416
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/PlatformEffect.cs
@@ -0,0 +1,8 @@
+using System.Windows;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public abstract class PlatformEffect : PlatformEffect<FrameworkElement, FrameworkElement>
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ProgressBarRenderer.cs b/Xamarin.Forms.Platform.WP8/ProgressBarRenderer.cs
new file mode 100644
index 00000000..b027d674
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ProgressBarRenderer.cs
@@ -0,0 +1,35 @@
+using System.ComponentModel;
+using System.Windows;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class ProgressBarRenderer : ViewRenderer<ProgressBar, System.Windows.Controls.ProgressBar>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<ProgressBar> e)
+ {
+ base.OnElementChanged(e);
+
+ var progressBar = new System.Windows.Controls.ProgressBar { Minimum = 0, Maximum = 1, Value = Element.Progress };
+ progressBar.ValueChanged += ProgressBarOnValueChanged;
+
+ SetNativeControl(progressBar);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ switch (e.PropertyName)
+ {
+ case "Progress":
+ Control.Value = Element.Progress;
+ break;
+ }
+ }
+
+ void ProgressBarOnValueChanged(object sender, RoutedPropertyChangedEventArgs<double> routedPropertyChangedEventArgs)
+ {
+ Element?.InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/Properties/AssemblyInfo.cs b/Xamarin.Forms.Platform.WP8/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..f1be5df1
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Properties/AssemblyInfo.cs
@@ -0,0 +1,78 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.WinPhone;
+using TableView = Xamarin.Forms.TableView;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Xamarin.Forms.Platform.WP8")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("50e5d817-4ac1-46c0-8e20-260fb6ad16af")]
+[assembly: NeutralResourcesLanguage("en-US")]
+
+// View subclasses
+
+[assembly: ExportRenderer(typeof(BoxView), typeof(BoxViewRenderer))]
+[assembly: ExportRenderer(typeof(Entry), typeof(EntryRenderer))]
+[assembly: ExportRenderer(typeof(Editor), typeof(EditorRenderer))]
+[assembly: ExportRenderer(typeof(Label), typeof(LabelRenderer))]
+[assembly: ExportRenderer(typeof(Image), typeof(ImageRenderer))]
+[assembly: ExportRenderer(typeof(Button), typeof(ButtonRenderer))]
+[assembly: ExportRenderer(typeof(Slider), typeof(SliderRenderer))]
+[assembly: ExportRenderer(typeof(WebView), typeof(WebViewRenderer))]
+[assembly: ExportRenderer(typeof(SearchBar), typeof(SearchBarRenderer))]
+[assembly: ExportRenderer(typeof(Switch), typeof(SwitchRenderer))]
+[assembly: ExportRenderer(typeof(DatePicker), typeof(DatePickerRenderer))]
+[assembly: ExportRenderer(typeof(TimePicker), typeof(TimePickerRenderer))]
+[assembly: ExportRenderer(typeof(Picker), typeof(PickerRenderer))]
+[assembly: ExportRenderer(typeof(Stepper), typeof(StepperRenderer))]
+[assembly: ExportRenderer(typeof(ProgressBar), typeof(ProgressBarRenderer))]
+[assembly: ExportRenderer(typeof(ScrollView), typeof(ScrollViewRenderer))]
+[assembly: ExportRenderer(typeof(ActivityIndicator), typeof(ActivityIndicatorRenderer))]
+[assembly: ExportRenderer(typeof(Frame), typeof(FrameRenderer))]
+[assembly: ExportRenderer(typeof(NavigationMenu), typeof(NavigationMenuRenderer))]
+[assembly: ExportRenderer(typeof(ListView), typeof(ListViewRenderer))]
+[assembly: ExportRenderer(typeof(CarouselView), typeof(CarouselViewRenderer))]
+[assembly: ExportRenderer(typeof(TableView), typeof(TableViewRenderer))]
+[assembly: ExportRenderer(typeof(NativeViewWrapper), typeof(NativeViewWrapperRenderer))]
+
+// Form and subclasses
+
+[assembly: ExportRenderer(typeof(TabbedPage), typeof(TabbedPageRenderer))]
+[assembly: ExportRenderer(typeof(NavigationPage), typeof(NavigationPageRenderer))]
+[assembly: ExportRenderer(typeof(CarouselPage), typeof(CarouselPageRenderer))]
+[assembly: ExportRenderer(typeof(Page), typeof(PageRenderer))]
+[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(MasterDetailRenderer))]
+
+//ImageSources
+
+[assembly: ExportImageSourceHandler(typeof(FileImageSource), typeof(FileImageSourceHandler))]
+[assembly: ExportImageSourceHandler(typeof(StreamImageSource), typeof(StreamImagesourceHandler))]
+[assembly: ExportImageSourceHandler(typeof(UriImageSource), typeof(ImageLoaderSourceHandler))]
+
+// Cells
+
+[assembly: ExportCell(typeof(Cell), typeof(TextCellRenderer))]
+[assembly: ExportCell(typeof(ImageCell), typeof(ImageCellRenderer))]
+[assembly: ExportCell(typeof(EntryCell), typeof(EntryCellRenderer))]
+[assembly: ExportCell(typeof(SwitchCell), typeof(SwitchCellRenderer))]
+[assembly: ExportCell(typeof(ViewCell), typeof(ViewCellRenderer))]
+[assembly: Dependency(typeof(Deserializer))]
+[assembly: Dependency(typeof(ResourcesProvider))]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Core.WP8.UnitTests")] \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/RendererFactory.cs b/Xamarin.Forms.Platform.WP8/RendererFactory.cs
new file mode 100644
index 00000000..33896df3
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/RendererFactory.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public static class RendererFactory
+ {
+ [Obsolete("Use Platform.CreateRenderer")]
+ public static IVisualElementRenderer GetRenderer(VisualElement view)
+ {
+ return Platform.CreateRenderer(view);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ResourcesProvider.cs b/Xamarin.Forms.Platform.WP8/ResourcesProvider.cs
new file mode 100644
index 00000000..3eaf2a1f
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ResourcesProvider.cs
@@ -0,0 +1,59 @@
+using System.Windows.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ internal class ResourcesProvider : ISystemResourcesProvider
+ {
+ ResourceDictionary _dictionary;
+
+ public IResourceDictionary GetSystemResources()
+ {
+ _dictionary = new ResourceDictionary();
+
+ UpdateStyles();
+
+ return _dictionary;
+ }
+
+ Style GetListItemDetailTextStyle()
+ {
+ var result = new Style(typeof(Label));
+
+ result.Setters.Add(new Setter { Property = Label.FontSizeProperty, Value = 32 });
+
+ return result;
+ }
+
+ Style GetListItemTextStyle()
+ {
+ var result = new Style(typeof(Label));
+
+ result.Setters.Add(new Setter { Property = Label.FontSizeProperty, Value = 48 });
+
+ return result;
+ }
+
+ Style GetStyle(System.Windows.Style style, TextBlock hackbox)
+ {
+ hackbox.Style = style;
+
+ var result = new Style(typeof(Label));
+ result.Setters.Add(new Setter { Property = Label.FontFamilyProperty, Value = hackbox.FontFamily });
+
+ result.Setters.Add(new Setter { Property = Label.FontSizeProperty, Value = hackbox.FontSize });
+
+ return result;
+ }
+
+ void UpdateStyles()
+ {
+ var textBlock = new TextBlock();
+ _dictionary[Device.Styles.TitleStyleKey] = GetStyle((System.Windows.Style)System.Windows.Application.Current.Resources["PhoneTextTitle1Style"], textBlock);
+ _dictionary[Device.Styles.SubtitleStyleKey] = GetStyle((System.Windows.Style)System.Windows.Application.Current.Resources["PhoneTextTitle2Style"], textBlock);
+ _dictionary[Device.Styles.BodyStyleKey] = GetStyle((System.Windows.Style)System.Windows.Application.Current.Resources["PhoneTextNormalStyle"], textBlock);
+ _dictionary[Device.Styles.CaptionStyleKey] = GetStyle((System.Windows.Style)System.Windows.Application.Current.Resources["PhoneTextSmallStyle"], textBlock);
+ _dictionary[Device.Styles.ListItemTextStyleKey] = GetListItemTextStyle();
+ _dictionary[Device.Styles.ListItemDetailTextStyleKey] = GetListItemDetailTextStyle();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ScrollViewRenderer.cs b/Xamarin.Forms.Platform.WP8/ScrollViewRenderer.cs
new file mode 100644
index 00000000..6e19d8c4
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ScrollViewRenderer.cs
@@ -0,0 +1,194 @@
+using System;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class ScrollViewRenderer : ViewRenderer<ScrollView, ScrollViewer>
+ {
+ Animatable _animatable;
+
+ public ScrollViewRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected IScrollViewController Controller
+ {
+ get { return Element; }
+ }
+
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ SizeRequest result = base.GetDesiredSize(widthConstraint, heightConstraint);
+ result.Minimum = new Size(40, 40);
+ return result;
+ }
+
+ protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
+ {
+ if (Element == null)
+ return finalSize;
+
+ Element.IsInNativeLayout = true;
+
+ if (Control != null)
+ {
+ Control.Measure(finalSize);
+ Control.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
+ }
+
+ Element.IsInNativeLayout = false;
+
+ return finalSize;
+ }
+
+ protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize)
+ {
+ if (Element == null)
+ return new System.Windows.Size(0, 0);
+
+ double width = Math.Max(0, Element.Width);
+ double height = Math.Max(0, Element.Height);
+ return new System.Windows.Size(width, height);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<ScrollView> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ ((IScrollViewController)e.OldElement).ScrollToRequested -= OnScrollToRequested;
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new ScrollViewer { ManipulationMode = ManipulationMode.Control });
+ Control.LayoutUpdated += (sender, args) => { UpdateScrollPosition(); };
+ }
+ ((IScrollViewController)e.NewElement).ScrollToRequested += OnScrollToRequested;
+ }
+
+ SizeChanged += (sender, args) =>
+ {
+ Control.Width = ActualWidth;
+ Control.Height = ActualHeight;
+ };
+
+ UpdateOrientation();
+
+ LoadContent();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == "Content")
+ LoadContent();
+ else if (e.PropertyName == Layout.PaddingProperty.PropertyName)
+ UpdateMargins();
+ else if (e.PropertyName == ScrollView.OrientationProperty.PropertyName)
+ UpdateOrientation();
+ }
+
+ static double GetDistance(double start, double position, double v)
+ {
+ return start + (position - start) * v;
+ }
+
+ void LoadContent()
+ {
+ var lastContent = Control.Content as FrameworkElement;
+ if (lastContent != null)
+ lastContent.Margin = new System.Windows.Thickness(); //undo any damage we may have done to this renderer
+
+ View view = Element.Content;
+
+ if (view != null)
+ Platform.SetRenderer(view, Platform.CreateRenderer(view));
+
+ Control.Content = view != null ? Platform.GetRenderer(view) : null;
+
+ UpdateMargins();
+ }
+
+ void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
+ {
+ if (_animatable == null && e.ShouldAnimate)
+ _animatable = new Animatable();
+
+ ScrollToPosition position = e.Position;
+ double x = e.ScrollX;
+ double y = e.ScrollY;
+
+ if (e.Mode == ScrollToMode.Element)
+ {
+ Point itemPosition = Controller.GetScrollPositionForElement(e.Element as VisualElement, e.Position);
+ x = itemPosition.X;
+ y = itemPosition.Y;
+ }
+
+ if (Control.VerticalOffset == y && Control.HorizontalOffset == x)
+ return;
+
+ if (e.ShouldAnimate)
+ {
+ var animation = new Animation(v => { UpdateScrollOffset(GetDistance(Control.ViewportWidth, x, v), GetDistance(Control.ViewportHeight, y, v)); });
+
+ animation.Commit(_animatable, "ScrollTo", length: 500, easing: Easing.CubicInOut, finished: (v, d) =>
+ {
+ UpdateScrollOffset(x, y);
+ Controller.SendScrollFinished();
+ });
+ }
+ else
+ {
+ UpdateScrollOffset(x, y);
+ Controller.SendScrollFinished();
+ }
+ }
+
+ void UpdateMargins()
+ {
+ var element = Control.Content as FrameworkElement;
+ if (element == null)
+ return;
+
+ if (Element.Orientation == ScrollOrientation.Horizontal)
+ {
+ // need to add left/right margins
+ element.Margin = new System.Windows.Thickness(Element.Padding.Left, 0, Element.Padding.Right, 0);
+ }
+ else
+ {
+ // need to add top/bottom margins
+ element.Margin = new System.Windows.Thickness(0, Element.Padding.Top, 0, Element.Padding.Bottom);
+ }
+ }
+
+ void UpdateOrientation()
+ {
+ if (Element.Orientation == ScrollOrientation.Horizontal)
+ Control.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
+ else
+ Control.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled;
+ }
+
+ void UpdateScrollOffset(double x, double y)
+ {
+ if (Element.Orientation == ScrollOrientation.Horizontal)
+ Control.ScrollToHorizontalOffset(x);
+ else
+ Control.ScrollToVerticalOffset(y);
+ }
+
+ void UpdateScrollPosition()
+ {
+ if (Element != null)
+ Controller.SetScrolledPosition(Control.HorizontalOffset, Control.VerticalOffset);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/SearchBarRenderer.cs b/Xamarin.Forms.Platform.WP8/SearchBarRenderer.cs
new file mode 100644
index 00000000..b27851a8
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/SearchBarRenderer.cs
@@ -0,0 +1,159 @@
+using System.ComponentModel;
+using System.Windows.Input;
+using System.Windows.Media;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class SearchBarRenderer : ViewRenderer<SearchBar, FormsPhoneTextBox>
+ {
+ const string DefaultPlaceholder = "Search";
+ Brush _defaultPlaceholderColorBrush;
+
+ Brush _defaultTextColorBrush;
+
+ bool _fontApplied;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
+ {
+ base.OnElementChanged(e);
+
+ var scope = new InputScope();
+ var name = new InputScopeName();
+ name.NameValue = InputScopeNameValue.Search;
+ scope.Names.Add(name);
+
+ var phoneTextBox = new FormsPhoneTextBox { InputScope = scope };
+
+ phoneTextBox.KeyUp += PhoneTextBoxOnKeyUp;
+
+ phoneTextBox.TextChanged += PhoneTextBoxOnTextChanged;
+
+ SetNativeControl(phoneTextBox);
+
+ UpdateText();
+ UpdatePlaceholder();
+ UpdateAlignment();
+ UpdateFont();
+ UpdatePlaceholderColor();
+ UpdateTextColor();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == SearchBar.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == SearchBar.PlaceholderProperty.PropertyName)
+ UpdatePlaceholder();
+ else if (e.PropertyName == SearchBar.FontAttributesProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == SearchBar.FontFamilyProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == SearchBar.FontSizeProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == SearchBar.HorizontalTextAlignmentProperty.PropertyName)
+ UpdateAlignment();
+ else if (e.PropertyName == SearchBar.PlaceholderColorProperty.PropertyName)
+ UpdatePlaceholderColor();
+ else if (e.PropertyName == SearchBar.TextColorProperty.PropertyName)
+ UpdateTextColor();
+ }
+
+ protected override void UpdateBackgroundColor()
+ {
+ Control.Background = Element.BackgroundColor == Color.Default ? (Brush)System.Windows.Application.Current.Resources["PhoneTextBoxBrush"] : Element.BackgroundColor.ToBrush();
+ }
+
+ void PhoneTextBoxOnKeyUp(object sender, KeyEventArgs keyEventArgs)
+ {
+ if (keyEventArgs.Key == Key.Enter)
+ Element.OnSearchButtonPressed();
+ }
+
+ void PhoneTextBoxOnTextChanged(object sender, System.Windows.Controls.TextChangedEventArgs textChangedEventArgs)
+ {
+ ((IElementController)Element).SetValueFromRenderer(SearchBar.TextProperty, Control.Text);
+ }
+
+ void UpdateAlignment()
+ {
+ Control.TextAlignment = Element.HorizontalTextAlignment.ToNativeTextAlignment();
+ }
+
+ void UpdateFont()
+ {
+ if (Control == null)
+ return;
+
+ SearchBar searchbar = Element;
+
+ if (searchbar == null)
+ return;
+
+ bool searchbarIsDefault = searchbar.FontFamily == null && searchbar.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(SearchBar), true) && searchbar.FontAttributes == FontAttributes.None;
+
+ if (searchbarIsDefault && !_fontApplied)
+ return;
+
+ if (searchbarIsDefault)
+ {
+ Control.ClearValue(System.Windows.Controls.Control.FontStyleProperty);
+ Control.ClearValue(System.Windows.Controls.Control.FontSizeProperty);
+ Control.ClearValue(System.Windows.Controls.Control.FontFamilyProperty);
+ Control.ClearValue(System.Windows.Controls.Control.FontWeightProperty);
+ Control.ClearValue(System.Windows.Controls.Control.FontStretchProperty);
+ }
+ else
+ Control.ApplyFont(searchbar);
+
+ _fontApplied = true;
+ }
+
+ void UpdatePlaceholder()
+ {
+ Control.Hint = Element.Placeholder ?? DefaultPlaceholder;
+ }
+
+ void UpdatePlaceholderColor()
+ {
+ Color placeholderColor = Element.PlaceholderColor;
+
+ if (placeholderColor.IsDefault)
+ {
+ if (_defaultPlaceholderColorBrush == null)
+ return;
+
+ Control.PlaceholderForegroundBrush = _defaultPlaceholderColorBrush;
+ }
+
+ if (_defaultPlaceholderColorBrush == null)
+ _defaultPlaceholderColorBrush = Control.PlaceholderForegroundBrush;
+
+ Control.PlaceholderForegroundBrush = placeholderColor.ToBrush();
+ }
+
+ void UpdateText()
+ {
+ Control.Text = Element.Text ?? "";
+ }
+
+ void UpdateTextColor()
+ {
+ Color textColor = Element.TextColor;
+
+ if (textColor.IsDefault)
+ {
+ if (_defaultTextColorBrush == null)
+ return;
+
+ Control.Foreground = _defaultTextColorBrush;
+ }
+
+ if (_defaultTextColorBrush == null)
+ _defaultTextColorBrush = Control.Foreground;
+
+ Control.Foreground = textColor.ToBrush();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ServiceReferences.ClientConfig b/Xamarin.Forms.Platform.WP8/ServiceReferences.ClientConfig
new file mode 100644
index 00000000..26e884eb
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ServiceReferences.ClientConfig
@@ -0,0 +1,26 @@
+<configuration>
+ <system.serviceModel>
+ <bindings>
+ <basicHttpBinding>
+ <binding name="BasicHttpBinding_IGeocodeService" maxBufferSize="2147483647"
+ maxReceivedMessageSize="2147483647">
+ <security mode="None" />
+ </binding>
+ </basicHttpBinding>
+ <customBinding>
+ <binding name="CustomBinding_IGeocodeService">
+ <binaryMessageEncoding />
+ <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
+ </binding>
+ </customBinding>
+ </bindings>
+ <client>
+ <endpoint address="http://dev.virtualearth.net/webservices/v1/geocodeservice/GeocodeService.svc"
+ binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IGeocodeService"
+ contract="GeoService.IGeocodeService" name="BasicHttpBinding_IGeocodeService" />
+ <endpoint address="http://dev.virtualearth.net/webservices/v1/geocodeservice/GeocodeService.svc/binaryHttp"
+ binding="customBinding" bindingConfiguration="CustomBinding_IGeocodeService"
+ contract="GeoService.IGeocodeService" name="CustomBinding_IGeocodeService" />
+ </client>
+ </system.serviceModel>
+</configuration>
diff --git a/Xamarin.Forms.Platform.WP8/SliderRenderer.cs b/Xamarin.Forms.Platform.WP8/SliderRenderer.cs
new file mode 100644
index 00000000..40cd767d
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/SliderRenderer.cs
@@ -0,0 +1,43 @@
+using System.ComponentModel;
+using System.Windows;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class SliderRenderer : ViewRenderer<Slider, System.Windows.Controls.Slider>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<Slider> e)
+ {
+ base.OnElementChanged(e);
+
+ var wSlider = new System.Windows.Controls.Slider { Minimum = Element.Minimum, Maximum = Element.Maximum, Value = Element.Value };
+
+ SetNativeControl(wSlider);
+
+ wSlider.ValueChanged += HandleValueChanged;
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ switch (e.PropertyName)
+ {
+ case "Minimum":
+ Control.Minimum = Element.Minimum;
+ break;
+ case "Maximum":
+ Control.Maximum = Element.Maximum;
+ break;
+ case "Value":
+ if (Control.Value != Element.Value)
+ Control.Value = Element.Value;
+ break;
+ }
+ }
+
+ void HandleValueChanged(object sender, RoutedPropertyChangedEventArgs<double> routedPropertyChangedEventArgs)
+ {
+ ((IElementController)Element).SetValueFromRenderer(Slider.ValueProperty, Control.Value);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/StepperRenderer.cs b/Xamarin.Forms.Platform.WP8/StepperRenderer.cs
new file mode 100644
index 00000000..b459305f
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/StepperRenderer.cs
@@ -0,0 +1,68 @@
+using System;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using WButton = System.Windows.Controls.Button;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class StepperRenderer : ViewRenderer<Stepper, Border>
+ {
+ readonly StackPanel _panel = new StackPanel();
+ WButton _downButton;
+ WButton _upButton;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
+ {
+ base.OnElementChanged(e);
+
+ var border = new Border();
+ border.Child = _panel;
+ _panel.HorizontalAlignment = HorizontalAlignment.Right;
+ _panel.Orientation = Orientation.Horizontal;
+
+ _upButton = new WButton { Content = "+", Width = 100 };
+ _downButton = new WButton { Content = "-", Width = 100 };
+
+ _panel.Children.Add(_downButton);
+ _panel.Children.Add(_upButton);
+
+ SetNativeControl(border);
+
+ _upButton.Click += UpButtonOnClick;
+ _downButton.Click += DownButtonOnClick;
+
+ UpdateButtons();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ switch (e.PropertyName)
+ {
+ case "Minimum":
+ case "Maximum":
+ case "Value":
+ UpdateButtons();
+ break;
+ }
+ }
+
+ void DownButtonOnClick(object sender, RoutedEventArgs routedEventArgs)
+ {
+ ((IElementController)Element).SetValueFromRenderer(Stepper.ValueProperty, Math.Max(Element.Minimum, Element.Value - Element.Increment));
+ }
+
+ void UpButtonOnClick(object sender, RoutedEventArgs routedEventArgs)
+ {
+ ((IElementController)Element).SetValueFromRenderer(Stepper.ValueProperty, Math.Min(Element.Maximum, Element.Value + Element.Increment));
+ }
+
+ void UpdateButtons()
+ {
+ _upButton.IsEnabled = Element.Value < Element.Maximum;
+ _downButton.IsEnabled = Element.Value > Element.Minimum;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/SwitchRenderer.cs b/Xamarin.Forms.Platform.WP8/SwitchRenderer.cs
new file mode 100644
index 00000000..e64fe227
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/SwitchRenderer.cs
@@ -0,0 +1,50 @@
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using Microsoft.Phone.Controls.Primitives;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class SwitchRenderer : ViewRenderer<Switch, Border>
+ {
+ readonly ToggleSwitchButton _toggleSwitch = new ToggleSwitchButton();
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Switch> e)
+ {
+ base.OnElementChanged(e);
+
+ var container = new Border { Child = _toggleSwitch };
+ _toggleSwitch.IsChecked = Element.IsToggled;
+ _toggleSwitch.Checked += (sender, args) => ((IElementController)Element).SetValueFromRenderer(Switch.IsToggledProperty, true);
+ _toggleSwitch.Unchecked += (sender, args) => ((IElementController)Element).SetValueFromRenderer(Switch.IsToggledProperty, false);
+ _toggleSwitch.HorizontalAlignment = HorizontalAlignment.Right;
+
+ SetNativeControl(container);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Switch.IsToggledProperty.PropertyName)
+ {
+ if (_toggleSwitch.IsChecked != Element.IsToggled)
+ _toggleSwitch.IsChecked = Element.IsToggled;
+ }
+ else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ UpdateSwitchIsEnabled();
+ }
+
+ protected override void UpdateNativeWidget()
+ {
+ base.UpdateNativeWidget();
+
+ UpdateSwitchIsEnabled();
+ }
+
+ void UpdateSwitchIsEnabled()
+ {
+ _toggleSwitch.IsEnabled = Element.IsEnabled;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/TabbedPageRenderer.cs b/Xamarin.Forms.Platform.WP8/TabbedPageRenderer.cs
new file mode 100644
index 00000000..9192fc6f
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/TabbedPageRenderer.cs
@@ -0,0 +1,105 @@
+using System;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using Microsoft.Phone.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class TabbedPagePresenter : System.Windows.Controls.ContentPresenter
+ {
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ DependencyObject parent = VisualTreeHelper.GetParent(this);
+ while (parent != null && !(parent is PivotItem))
+ parent = VisualTreeHelper.GetParent(parent);
+
+ var pivotItem = parent as PivotItem;
+ if (pivotItem == null)
+ throw new Exception("No parent PivotItem found for tab");
+
+ pivotItem.SizeChanged += (s, e) =>
+ {
+ if (pivotItem.ActualWidth > 0 && pivotItem.ActualHeight > 0)
+ {
+ var tab = (Page)DataContext;
+ ((TabbedPage)tab.RealParent).ContainerArea = new Rectangle(0, 0, pivotItem.ActualWidth, pivotItem.ActualHeight);
+ }
+ };
+ }
+ }
+
+ public class TabbedPageRenderer : Pivot, IVisualElementRenderer
+ {
+ TabbedPage _page;
+ BackgroundTracker<Control> _tracker;
+
+ public TabbedPageRenderer()
+ {
+ SetBinding(TitleProperty, new System.Windows.Data.Binding("Title"));
+ SetBinding(ItemsSourceProperty, new System.Windows.Data.Binding("Children"));
+ HeaderTemplate = (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["TabbedPageHeader"];
+ ItemTemplate = (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["TabbedPage"];
+
+ SelectionChanged += OnSelectionChanged;
+ }
+
+ public UIElement ContainerElement
+ {
+ get { return this; }
+ }
+
+ public VisualElement Element
+ {
+ get { return _page; }
+ }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return new SizeRequest(new Size(widthConstraint, heightConstraint));
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ TabbedPage oldElement = _page;
+ _page = (TabbedPage)element;
+ _tracker = new BackgroundTracker<Control>(BackgroundProperty) { Model = _page, Element = this };
+
+ DataContext = element;
+
+ _page.PropertyChanged += OnPropertyChanged;
+
+ Loaded += (sender, args) => _page.SendAppearing();
+ Unloaded += (sender, args) => _page.SendDisappearing();
+
+ OnElementChanged(new VisualElementChangedEventArgs(_page, element));
+ }
+
+ protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ EventHandler<VisualElementChangedEventArgs> changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "CurrentPage")
+ {
+ Page current = _page.CurrentPage;
+ if (current != null)
+ SelectedItem = current;
+ }
+ }
+
+ void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ _page.CurrentPage = (Page)SelectedItem;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/TableView.xaml b/Xamarin.Forms.Platform.WP8/TableView.xaml
new file mode 100644
index 00000000..89c9cddb
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/TableView.xaml
@@ -0,0 +1,31 @@
+<Grid x:Class="Xamarin.Forms.Platform.WinPhone.TableView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ mc:Ignorable="d"
+ >
+
+ <Grid.Resources>
+ <ResourceDictionary>
+ <ResourceDictionary.MergedDictionaries>
+ <ResourceDictionary Source="WPResources.xaml" />
+ </ResourceDictionary.MergedDictionaries>
+ </ResourceDictionary>
+ </Grid.Resources>
+
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition />
+ </Grid.RowDefinitions>
+
+ <TextBlock Grid.Row="0" Text="{Binding Title,Converter={StaticResource UpperConverter}}" Style="{StaticResource PhoneTextSmallTitleStyle}" />
+ <ListBox Grid.Row="1" ItemsSource="{Binding}" ItemTemplate="{StaticResource TableGroup}">
+ <ListBox.ItemContainerStyle>
+ <Style TargetType="ListBoxItem">
+ <Setter Property="HorizontalContentAlignment" Value="Stretch" />
+ </Style>
+ </ListBox.ItemContainerStyle>
+ </ListBox>
+</Grid>
+
diff --git a/Xamarin.Forms.Platform.WP8/TableView.xaml.cs b/Xamarin.Forms.Platform.WP8/TableView.xaml.cs
new file mode 100644
index 00000000..dc3d1dcc
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/TableView.xaml.cs
@@ -0,0 +1,10 @@
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public partial class TableView : System.Windows.Controls.Grid
+ {
+ public TableView()
+ {
+ InitializeComponent();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/TableViewRenderer.cs b/Xamarin.Forms.Platform.WP8/TableViewRenderer.cs
new file mode 100644
index 00000000..84f205eb
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/TableViewRenderer.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Media;
+using Microsoft.Phone.Shell;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class TableViewRenderer : ViewRenderer<Xamarin.Forms.TableView, TableView>
+ {
+ TableView _view;
+
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ SizeRequest result = base.GetDesiredSize(widthConstraint, heightConstraint);
+ result.Minimum = new Size(40, 40);
+ return result;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.TableView> e)
+ {
+ base.OnElementChanged(e);
+
+ Element.ModelChanged += OnModelChanged;
+
+ _view = new TableView { DataContext = Element.Root };
+ _view.Tap += OnTapTable;
+ _view.Hold += OnLongPressTable;
+ SetNativeControl(_view);
+ }
+
+ bool FindIndices(GestureEventArgs e, out int sectionIndex, out int cellIndex)
+ {
+ sectionIndex = 0;
+ cellIndex = 0;
+
+ TableSection section = null;
+ Cell cell = null;
+
+ System.Windows.Point pos = e.GetPosition(System.Windows.Application.Current.RootVisual);
+ if (Device.Info.CurrentOrientation.IsLandscape())
+ {
+ double x = pos.Y;
+ double y = System.Windows.Application.Current.RootVisual.RenderSize.Width - pos.X + (SystemTray.IsVisible ? 72 : 0);
+ pos = new System.Windows.Point(x, y);
+ }
+ IEnumerable<UIElement> elements = VisualTreeHelper.FindElementsInHostCoordinates(pos, System.Windows.Application.Current.RootVisual);
+ foreach (FrameworkElement element in elements.OfType<FrameworkElement>())
+ {
+ if (cell == null)
+ cell = element.DataContext as Cell;
+ else if (section == null)
+ section = element.DataContext as TableSection;
+ else
+ break;
+ }
+
+ if (cell == null || section == null)
+ return false;
+
+ sectionIndex = Element.Root.IndexOf(section);
+ cellIndex = section.IndexOf(cell);
+ return true;
+ }
+
+ void OnLongPressTable(object sender, GestureEventArgs e)
+ {
+ int sectionIndex, cellIndex;
+ if (!FindIndices(e, out sectionIndex, out cellIndex))
+ return;
+
+ Element.Model.RowLongPressed(sectionIndex, cellIndex);
+ }
+
+ void OnModelChanged(object sender, EventArgs eventArgs)
+ {
+ _view.DataContext = Element.Root;
+ }
+
+ void OnTapTable(object sender, GestureEventArgs e)
+ {
+ int sectionIndex, cellIndex;
+ if (!FindIndices(e, out sectionIndex, out cellIndex))
+ return;
+
+ Element.Model.RowSelected(sectionIndex, cellIndex);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/TextAlignmentToHorizontalAlignmentConverter.cs b/Xamarin.Forms.Platform.WP8/TextAlignmentToHorizontalAlignmentConverter.cs
new file mode 100644
index 00000000..7f8aeef6
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/TextAlignmentToHorizontalAlignmentConverter.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Globalization;
+using System.Windows;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public sealed class TextAlignmentToHorizontalAlignmentConverter : System.Windows.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var alignment = (System.Windows.TextAlignment)value;
+
+ switch (alignment)
+ {
+ case System.Windows.TextAlignment.Center:
+ return HorizontalAlignment.Center;
+ case System.Windows.TextAlignment.Left:
+ return HorizontalAlignment.Left;
+ case System.Windows.TextAlignment.Right:
+ return HorizontalAlignment.Right;
+ default:
+ return HorizontalAlignment.Left;
+ }
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var alignment = (HorizontalAlignment)value;
+
+ switch (alignment)
+ {
+ case HorizontalAlignment.Left:
+ return System.Windows.TextAlignment.Left;
+ case HorizontalAlignment.Center:
+ return System.Windows.TextAlignment.Center;
+ case HorizontalAlignment.Right:
+ return System.Windows.TextAlignment.Right;
+ default:
+ return System.Windows.TextAlignment.Left;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/TextCellRenderer.cs b/Xamarin.Forms.Platform.WP8/TextCellRenderer.cs
new file mode 100644
index 00000000..b3c2453d
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/TextCellRenderer.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Windows.Input;
+using Microsoft.Phone.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class TextCellRenderer : ICellRenderer
+ {
+ public virtual System.Windows.DataTemplate GetTemplate(Cell cell)
+ {
+ if (cell.RealParent is ListView)
+ {
+ if (TemplatedItemsList<ItemsView<Cell>, Cell>.GetIsGroupHeader(cell))
+ return (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["ListViewHeaderTextCell"];
+
+ return (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["ListViewTextCell"];
+ }
+
+ return (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["TextCell"];
+ }
+ }
+
+ public class EntryCellRendererCompleted : ICommand
+ {
+ public bool CanExecute(object parameter)
+ {
+ return true;
+ }
+
+ public event EventHandler CanExecuteChanged;
+
+ public void Execute(object parameter)
+ {
+ var entryCell = (EntryCell)parameter;
+ entryCell.SendCompleted();
+ }
+ }
+
+ public class EntryCellPhoneTextBox : PhoneTextBox
+ {
+ public event EventHandler KeyboardReturnPressed;
+
+ protected override void OnKeyUp(KeyEventArgs e)
+ {
+ if (e.Key == Key.Enter)
+ {
+ EventHandler handler = KeyboardReturnPressed;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+ base.OnKeyUp(e);
+ }
+ }
+
+ public class EntryCellRenderer : ICellRenderer
+ {
+ public virtual System.Windows.DataTemplate GetTemplate(Cell cell)
+ {
+ return (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["EntryCell"];
+ }
+ }
+
+ public class ViewCellRenderer : ICellRenderer
+ {
+ public virtual System.Windows.DataTemplate GetTemplate(Cell cell)
+ {
+ return (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["ViewCell"];
+ }
+ }
+
+ public class SwitchCellRenderer : ICellRenderer
+ {
+ public virtual System.Windows.DataTemplate GetTemplate(Cell cell)
+ {
+ return (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["SwitchCell"];
+ }
+ }
+
+ public class ImageCellRenderer : ICellRenderer
+ {
+ public virtual System.Windows.DataTemplate GetTemplate(Cell cell)
+ {
+ if (cell.RealParent is ListView)
+ return (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["ListImageCell"];
+ return (System.Windows.DataTemplate)System.Windows.Application.Current.Resources["ImageCell"];
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/TimePickerRenderer.cs b/Xamarin.Forms.Platform.WP8/TimePickerRenderer.cs
new file mode 100644
index 00000000..70841d7a
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/TimePickerRenderer.cs
@@ -0,0 +1,60 @@
+using System;
+using System.ComponentModel;
+using System.Reflection;
+using Microsoft.Phone.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class TimePickerRenderer : ViewRenderer<TimePicker, Microsoft.Phone.Controls.TimePicker>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
+ {
+ base.OnElementChanged(e);
+
+ var timePicker = new Microsoft.Phone.Controls.TimePicker { Value = DateTime.Today.Add(Element.Time) };
+ timePicker.ValueChanged += TimePickerOnValueChanged;
+
+ SetNativeControl(timePicker);
+ UpdateFormatString();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == "Time")
+ Control.Value = DateTime.Today.Add(Element.Time);
+ else if (e.PropertyName == TimePicker.FormatProperty.PropertyName)
+ UpdateFormatString();
+ }
+
+ internal override void OnModelFocusChangeRequested(object sender, VisualElement.FocusRequestArgs args)
+ {
+ Microsoft.Phone.Controls.TimePicker control = Control;
+ if (control == null)
+ return;
+
+ if (args.Focus)
+ {
+ typeof(DateTimePickerBase).InvokeMember("OpenPickerPage", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, Type.DefaultBinder, control, null);
+ args.Result = true;
+ }
+ else
+ {
+ UnfocusControl(control);
+ args.Result = true;
+ }
+ }
+
+ void TimePickerOnValueChanged(object sender, DateTimeValueChangedEventArgs dateTimeValueChangedEventArgs)
+ {
+ if (Control.Value != null)
+ ((IElementController)Element).SetValueFromRenderer(TimePicker.TimeProperty, Control.Value.Value - DateTime.Today);
+ }
+
+ void UpdateFormatString()
+ {
+ Control.ValueStringFormat = "{0:" + Element.Format + "}";
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Cancel.png b/Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Cancel.png
new file mode 100644
index 00000000..4dd724f0
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Cancel.png
Binary files differ
diff --git a/Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Check.png b/Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Check.png
new file mode 100644
index 00000000..7a074666
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Check.png
Binary files differ
diff --git a/Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Delete.png b/Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Delete.png
new file mode 100644
index 00000000..95bb16da
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Delete.png
Binary files differ
diff --git a/Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Select.png b/Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Select.png
new file mode 100644
index 00000000..995deaaa
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Toolkit.Content/ApplicationBar.Select.png
Binary files differ
diff --git a/Xamarin.Forms.Platform.WP8/ViewExtensions.cs b/Xamarin.Forms.Platform.WP8/ViewExtensions.cs
new file mode 100644
index 00000000..1d46b3b2
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ViewExtensions.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public static class ViewExtensions
+ {
+ [Obsolete("Use Platform.GetRenderer")]
+ public static IVisualElementRenderer GetRenderer(this VisualElement self)
+ {
+ return Platform.GetRenderer(self);
+ }
+
+ [Obsolete("Use Platform.SetRenderer")]
+ public static void SetRenderer(this VisualElement self, IVisualElementRenderer renderer)
+ {
+ Platform.SetRenderer(self, renderer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ViewRenderer.cs b/Xamarin.Forms.Platform.WP8/ViewRenderer.cs
new file mode 100644
index 00000000..3f0d72c5
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ViewRenderer.cs
@@ -0,0 +1,47 @@
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Media;
+using WSize = System.Windows.Size;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class ViewRenderer<TElement, TNativeElement> : VisualElementRenderer<TElement, TNativeElement> where TElement : View where TNativeElement : FrameworkElement
+ {
+ }
+
+ public class ViewRenderer : ViewRenderer<View, FrameworkElement>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<View> e)
+ {
+ base.OnElementChanged(e);
+ SizeChanged += (sender, args) => UpdateClipToBounds();
+
+ UpdateBackgroundColor();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Layout.IsClippedToBoundsProperty.PropertyName)
+ UpdateClipToBounds();
+ }
+
+ protected override void UpdateNativeWidget()
+ {
+ base.UpdateNativeWidget();
+ UpdateClipToBounds();
+ }
+
+ void UpdateClipToBounds()
+ {
+ var layout = Element as Layout;
+ if (layout != null)
+ {
+ Clip = null;
+ if (layout.IsClippedToBounds)
+ Clip = new RectangleGeometry { Rect = new Rect(0, 0, ActualWidth, ActualHeight) };
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/ViewToRendererConverter.cs b/Xamarin.Forms.Platform.WP8/ViewToRendererConverter.cs
new file mode 100644
index 00000000..49b232a1
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/ViewToRendererConverter.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class ViewToRendererConverter : System.Windows.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var view = value as View;
+ if (view == null)
+ return null;
+
+ return new WrapperControl(view);
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+
+ class WrapperControl : ContentControl
+ {
+ readonly View _view;
+
+ public WrapperControl(View view)
+ {
+ _view = view;
+ _view.MeasureInvalidated += (sender, args) => InvalidateMeasure();
+
+ IVisualElementRenderer visualElementRenderer = Platform.CreateRenderer(view);
+ Platform.SetRenderer(view, visualElementRenderer);
+ Content = visualElementRenderer.ContainerElement;
+
+ // make sure we re-measure once the template is applied
+ var frameworkElement = visualElementRenderer.ContainerElement as FrameworkElement;
+ if (frameworkElement != null)
+ {
+ frameworkElement.Loaded += (sender, args) =>
+ {
+ _view.InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ InvalidateMeasure();
+ };
+ }
+ }
+
+ protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
+ {
+ _view.IsInNativeLayout = true;
+ Layout.LayoutChildIntoBoundingRegion(_view, new Rectangle(0, 0, finalSize.Width, finalSize.Height));
+ _view.IsInNativeLayout = false;
+
+ var content = Content as FrameworkElement;
+ content?.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
+ return finalSize;
+ }
+
+ protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize)
+ {
+ var content = Content as FrameworkElement;
+ content?.Measure(availableSize);
+ Size request = _view.Measure(availableSize.Width, availableSize.Height, MeasureFlags.IncludeMargins).Request;
+
+ System.Windows.Size result;
+ if (_view.HorizontalOptions.Alignment == LayoutAlignment.Fill && !double.IsInfinity(availableSize.Width) && availableSize.Width != 0)
+ result = new System.Windows.Size(availableSize.Width, request.Height);
+ else
+ result = new System.Windows.Size(request.Width, request.Height);
+
+ _view.Layout(new Rectangle(0, 0, result.Width, result.Width));
+ return result;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/VisualElementPackager.cs b/Xamarin.Forms.Platform.WP8/VisualElementPackager.cs
new file mode 100644
index 00000000..65f589fc
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/VisualElementPackager.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class VisualElementPackager
+ {
+ readonly Panel _panel;
+ readonly IVisualElementRenderer _renderer;
+ bool _loaded;
+
+ public VisualElementPackager(IVisualElementRenderer renderer)
+ {
+ if (renderer == null)
+ throw new ArgumentNullException("renderer");
+
+ _panel = renderer.ContainerElement as Panel;
+ if (_panel == null)
+ throw new ArgumentException("Renderer's container element must be a Panel or Panel subclass");
+
+ _renderer = renderer;
+ }
+
+ public void Load()
+ {
+ if (_loaded)
+ return;
+
+ _loaded = true;
+ _renderer.Element.ChildAdded += HandleChildAdded;
+ _renderer.Element.ChildRemoved += HandleChildRemoved;
+ _renderer.Element.ChildrenReordered += HandleChildrenReordered;
+
+ foreach (Element child in _renderer.Element.LogicalChildren)
+ HandleChildAdded(_renderer.Element, new ElementEventArgs(child));
+ }
+
+ void EnsureZIndex()
+ {
+ for (var index = 0; index < _renderer.Element.LogicalChildren.Count; index++)
+ {
+ var child = (VisualElement)_renderer.Element.LogicalChildren[index];
+ IVisualElementRenderer r = Platform.GetRenderer(child);
+ if (r == null)
+ continue;
+ // Even though this attached property is defined on Canvas, it actually works on all Panels
+ // Why? Microsoft.
+ Canvas.SetZIndex(r.ContainerElement, index + 1);
+ }
+ }
+
+ void HandleChildAdded(object sender, ElementEventArgs e)
+ {
+ var view = e.Element as VisualElement;
+
+ if (view == null)
+ return;
+
+ IVisualElementRenderer renderer;
+ Platform.SetRenderer(view, renderer = Platform.CreateRenderer(view));
+
+ _panel.Children.Add(renderer.ContainerElement);
+
+ EnsureZIndex();
+ }
+
+ void HandleChildRemoved(object sender, ElementEventArgs e)
+ {
+ var view = e.Element as VisualElement;
+
+ if (view == null)
+ return;
+
+ var renderer = Platform.GetRenderer(view) as UIElement;
+
+ if (renderer != null)
+ _panel.Children.Remove(renderer);
+
+ EnsureZIndex();
+ }
+
+ void HandleChildrenReordered(object sender, EventArgs e)
+ {
+ EnsureZIndex();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/VisualElementRenderer.cs b/Xamarin.Forms.Platform.WP8/VisualElementRenderer.cs
new file mode 100644
index 00000000..9ec274c5
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/VisualElementRenderer.cs
@@ -0,0 +1,326 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class VisualElementRenderer<TElement, TNativeElement> : Panel, IVisualElementRenderer, IEffectControlProvider where TElement : VisualElement where TNativeElement : FrameworkElement
+ {
+ readonly List<EventHandler<VisualElementChangedEventArgs>> _elementChangedHandlers = new List<EventHandler<VisualElementChangedEventArgs>>();
+
+ Brush _initialBrush;
+
+ VisualElementTracker _tracker;
+
+ public TNativeElement Control { get; private set; }
+
+ public TElement Element { get; private set; }
+
+ protected bool AutoPackage { get; set; } = true;
+
+ protected bool AutoTrack { get; set; } = true;
+
+ protected VisualElementTracker Tracker
+ {
+ get { return _tracker; }
+ set
+ {
+ if (_tracker == value)
+ return;
+
+ if (_tracker != null)
+ {
+ _tracker.Dispose();
+ _tracker.Updated -= HandleTrackerUpdated;
+ }
+
+ _tracker = value;
+
+ if (_tracker != null)
+ _tracker.Updated += HandleTrackerUpdated;
+ }
+ }
+
+ VisualElementPackager Packager { get; set; }
+
+ void IEffectControlProvider.RegisterEffect(Effect effect)
+ {
+ var platformEffect = effect as PlatformEffect;
+ if (platformEffect != null)
+ OnRegisterEffect(platformEffect);
+ }
+
+ public UIElement ContainerElement
+ {
+ get { return this; }
+ }
+
+ VisualElement IVisualElementRenderer.Element
+ {
+ get { return Element; }
+ }
+
+ event EventHandler<VisualElementChangedEventArgs> IVisualElementRenderer.ElementChanged
+ {
+ add { _elementChangedHandlers.Add(value); }
+ remove { _elementChangedHandlers.Remove(value); }
+ }
+
+ public virtual SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ if (Children.Count == 0)
+ return new SizeRequest();
+
+ var constraint = new System.Windows.Size(widthConstraint, heightConstraint);
+ var child = (FrameworkElement)Children[0];
+
+ child.Measure(constraint);
+ var result = new Size(Math.Ceiling(child.DesiredSize.Width), Math.Ceiling(child.DesiredSize.Height));
+
+ return new SizeRequest(result);
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ TElement oldElement = Element;
+ Element = (TElement)element;
+
+ if (oldElement != null)
+ {
+ oldElement.PropertyChanged -= OnElementPropertyChanged;
+ oldElement.FocusChangeRequested -= OnModelFocusChangeRequested;
+ }
+
+ Element.PropertyChanged += OnElementPropertyChanged;
+ Element.FocusChangeRequested += OnModelFocusChangeRequested;
+
+ if (AutoPackage && Packager == null)
+ Packager = new VisualElementPackager(this);
+
+ if (AutoTrack && Tracker == null)
+ {
+ Tracker = new VisualElementTracker<TElement, FrameworkElement> { Model = Element, Element = this };
+ }
+
+ // Disabled until reason for crashes with unhandled exceptions is discovered
+ // Without this some layouts may end up with improper sizes, however their children
+ // will position correctly
+ //Loaded += (sender, args) => {
+ if (Packager != null)
+ Packager.Load();
+ //};
+
+ OnElementChanged(new ElementChangedEventArgs<TElement>(oldElement, Element));
+
+ var controller = (IElementController)oldElement;
+ if (controller != null && controller.EffectControlProvider == this)
+ controller.EffectControlProvider = null;
+
+ controller = element;
+ if (controller != null)
+ controller.EffectControlProvider = this;
+ }
+
+ public event EventHandler<ElementChangedEventArgs<TElement>> ElementChanged;
+
+ protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
+ {
+ if (Element == null || finalSize.Width * finalSize.Height == 0)
+ return finalSize;
+
+ Element.IsInNativeLayout = true;
+
+ if (Control != null)
+ {
+ Control.Measure(finalSize);
+ Control.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
+ }
+
+ for (var i = 0; i < Element.LogicalChildren.Count; i++)
+ {
+ var child = Element.LogicalChildren[i] as VisualElement;
+ if (child == null)
+ continue;
+ IVisualElementRenderer renderer = child.GetRenderer();
+ if (renderer == null)
+ continue;
+ Rectangle bounds = child.Bounds;
+
+ renderer.ContainerElement.Arrange(new Rect(bounds.X, bounds.Y, Math.Max(0, bounds.Width), Math.Max(0, bounds.Height)));
+ }
+
+ Element.IsInNativeLayout = false;
+
+ return finalSize;
+ }
+
+ protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize)
+ {
+ if (Element == null || availableSize.Width * availableSize.Height == 0)
+ return new System.Windows.Size(0, 0);
+
+ Element.IsInNativeLayout = true;
+
+ for (var i = 0; i < Element.LogicalChildren.Count; i++)
+ {
+ var child = Element.LogicalChildren[i] as VisualElement;
+ if (child == null)
+ continue;
+ IVisualElementRenderer renderer = Platform.GetRenderer(child);
+ if (renderer == null)
+ continue;
+
+ try
+ {
+ renderer.ContainerElement.Measure(availableSize);
+ }
+ catch (NullReferenceException)
+ {
+ if (!IsExpectedTabbedPageMeasurementException(renderer))
+ throw;
+ }
+ }
+
+ double width = Math.Max(0, Element.Width);
+ double height = Math.Max(0, Element.Height);
+ var result = new System.Windows.Size(width, height);
+
+ if (Control != null)
+ {
+ double w = Element.Width;
+ double h = Element.Height;
+ if (w == -1)
+ w = availableSize.Width;
+ if (h == -1)
+ h = availableSize.Height;
+ w = Math.Max(0, w);
+ h = Math.Max(0, h);
+ Control.Measure(new System.Windows.Size(w, h));
+ }
+
+ Element.IsInNativeLayout = false;
+
+ return result;
+ }
+
+ protected virtual void OnElementChanged(ElementChangedEventArgs<TElement> e)
+ {
+ var args = new VisualElementChangedEventArgs(e.OldElement, e.NewElement);
+ for (var i = 0; i < _elementChangedHandlers.Count; i++)
+ _elementChangedHandlers[i](this, args);
+
+ EventHandler<ElementChangedEventArgs<TElement>> changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ UpdateEnabled();
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackgroundColor();
+ }
+
+ protected virtual void OnGotFocus(object sender, RoutedEventArgs args)
+ {
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
+ }
+
+ protected virtual void OnLostFocus(object sender, RoutedEventArgs args)
+ {
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ }
+
+ protected virtual void OnRegisterEffect(PlatformEffect effect)
+ {
+ effect.Container = this;
+ effect.Control = Control;
+ }
+
+ protected void SetNativeControl(TNativeElement element)
+ {
+ Control = element;
+
+ Children.Add(element);
+ Element.IsNativeStateConsistent = false;
+ element.Loaded += (sender, args) => Element.IsNativeStateConsistent = true;
+
+ element.GotFocus += OnGotFocus;
+ element.LostFocus += OnLostFocus;
+
+ _tracker.Child = element;
+
+ UpdateBackgroundColor();
+ }
+
+ protected virtual void UpdateBackgroundColor()
+ {
+ var control = Control as Control;
+ if (_initialBrush == null)
+ _initialBrush = control == null ? Background : control.Background;
+ if (control != null)
+ control.Background = Element.BackgroundColor != Color.Default ? Element.BackgroundColor.ToBrush() : _initialBrush;
+ else
+ Background = Element.BackgroundColor != Color.Default ? Element.BackgroundColor.ToBrush() : _initialBrush;
+ }
+
+ protected virtual void UpdateNativeWidget()
+ {
+ UpdateEnabled();
+ }
+
+ internal virtual void OnModelFocusChangeRequested(object sender, VisualElement.FocusRequestArgs args)
+ {
+ var control = Control as Control;
+ if (control == null)
+ return;
+
+ if (args.Focus)
+ args.Result = control.Focus();
+ else
+ {
+ UnfocusControl(control);
+ args.Result = true;
+ }
+ }
+
+ internal void UnfocusControl(Control control)
+ {
+ if (control == null || !control.IsEnabled)
+ return;
+ control.IsEnabled = false;
+ control.IsEnabled = true;
+ }
+
+ void HandleTrackerUpdated(object sender, EventArgs e)
+ {
+ UpdateNativeWidget();
+ }
+
+ static bool IsExpectedTabbedPageMeasurementException(IVisualElementRenderer renderer)
+ {
+ // The TabbedPageRenderer's underlying Pivot control throws a NRE if the tabbed page
+ // does not have any toolbar items and it's measured during an animated transition
+ // from a page which does have toolbar items
+
+ // The NRE happens before TabbedPageRenderer's MeasureOverride is even called,
+ // so unfortunately we have to handle it here
+
+ var tpr = renderer.ContainerElement as TabbedPageRenderer;
+
+ var tp = tpr?.Element as TabbedPage;
+
+ return tp?.ToolbarItems.Count == 0;
+ }
+
+ void UpdateEnabled()
+ {
+ if (Control is Control)
+ (Control as Control).IsEnabled = Element.IsEnabled;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/VisualElementTracker.cs b/Xamarin.Forms.Platform.WP8/VisualElementTracker.cs
new file mode 100644
index 00000000..8211ec63
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/VisualElementTracker.cs
@@ -0,0 +1,370 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Media;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public abstract class VisualElementTracker : IDisposable
+ {
+ public abstract FrameworkElement Child { get; set; }
+
+ public abstract void Dispose();
+
+ public event EventHandler Updated;
+
+ protected void OnUpdated()
+ {
+ if (Updated != null)
+ Updated(this, EventArgs.Empty);
+ }
+ }
+
+ public class VisualElementTracker<TModel, TElement> : VisualElementTracker where TModel : VisualElement where TElement : FrameworkElement
+ {
+ FrameworkElement _child;
+ bool _disposed;
+ TElement _element;
+
+ bool _invalidateArrangeNeeded;
+ bool _isPanning;
+ bool _isPinching;
+
+ TModel _model;
+ bool _touchFrameReportedEventSet;
+ int _touchPoints = 1;
+
+ public override FrameworkElement Child
+ {
+ get { return _child; }
+ set
+ {
+ if (_child == value)
+ return;
+ _child = value;
+ UpdateNativeControl();
+ }
+ }
+
+ public TElement Element
+ {
+ get { return _element; }
+ set
+ {
+ if (_element == value)
+ return;
+
+ if (_element != null)
+ {
+ _element.Tap -= ElementOnTap;
+ _element.DoubleTap -= ElementOnDoubleTap;
+ _element.ManipulationDelta -= OnManipulationDelta;
+ _element.ManipulationCompleted -= OnManipulationCompleted;
+ }
+
+ _element = value;
+
+ if (_element != null)
+ {
+ _element.Tap += ElementOnTap;
+ _element.DoubleTap += ElementOnDoubleTap;
+ _element.ManipulationDelta += OnManipulationDelta;
+ _element.ManipulationCompleted += OnManipulationCompleted;
+ }
+
+ UpdateNativeControl();
+ }
+ }
+
+ public TModel Model
+ {
+ get { return _model; }
+ set
+ {
+ if (_model == value)
+ return;
+
+ if (_model != null)
+ {
+ _model.BatchCommitted -= HandleRedrawNeeded;
+ _model.PropertyChanged -= HandlePropertyChanged;
+ }
+
+ _model = value;
+
+ if (_model != null)
+ {
+ _model.BatchCommitted += HandleRedrawNeeded;
+ _model.PropertyChanged += HandlePropertyChanged;
+ }
+
+ UpdateNativeControl();
+ }
+ }
+
+ public override void Dispose()
+ {
+ if (_disposed)
+ return;
+ _disposed = true;
+
+ if (_element != null)
+ {
+ _element.Tap -= ElementOnTap;
+ _element.DoubleTap -= ElementOnDoubleTap;
+ _element.ManipulationDelta -= OnManipulationDelta;
+ _element.ManipulationCompleted -= OnManipulationCompleted;
+ }
+
+ if (_model != null)
+ {
+ _model.BatchCommitted -= HandleRedrawNeeded;
+ _model.PropertyChanged -= HandlePropertyChanged;
+ }
+
+ Child = null;
+ Model = null;
+ Element = null;
+ }
+
+ protected virtual void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (Model.Batched)
+ {
+ if (e.PropertyName == VisualElement.XProperty.PropertyName || e.PropertyName == VisualElement.YProperty.PropertyName || e.PropertyName == VisualElement.WidthProperty.PropertyName ||
+ e.PropertyName == VisualElement.HeightProperty.PropertyName)
+ _invalidateArrangeNeeded = true;
+ return;
+ }
+
+ if (e.PropertyName == VisualElement.XProperty.PropertyName || e.PropertyName == VisualElement.YProperty.PropertyName || e.PropertyName == VisualElement.WidthProperty.PropertyName ||
+ e.PropertyName == VisualElement.HeightProperty.PropertyName)
+ MaybeInvalidate();
+ else if (e.PropertyName == VisualElement.AnchorXProperty.PropertyName || e.PropertyName == VisualElement.AnchorYProperty.PropertyName)
+ UpdateScaleAndRotation(Model, Element);
+ else if (e.PropertyName == VisualElement.ScaleProperty.PropertyName)
+ UpdateScaleAndRotation(Model, Element);
+ else if (e.PropertyName == VisualElement.TranslationXProperty.PropertyName || e.PropertyName == VisualElement.TranslationYProperty.PropertyName ||
+ e.PropertyName == VisualElement.RotationProperty.PropertyName || e.PropertyName == VisualElement.RotationXProperty.PropertyName || e.PropertyName == VisualElement.RotationYProperty.PropertyName)
+ UpdateRotation(Model, Element);
+ else if (e.PropertyName == VisualElement.IsVisibleProperty.PropertyName)
+ UpdateVisibility(Model, Element);
+ else if (e.PropertyName == VisualElement.OpacityProperty.PropertyName)
+ UpdateOpacity(Model, Element);
+ else if (e.PropertyName == VisualElement.InputTransparentProperty.PropertyName)
+ UpdateInputTransparent(Model, Element);
+ }
+
+ protected virtual void UpdateNativeControl()
+ {
+ if (Model == null || Element == null)
+ return;
+
+ UpdateOpacity(_model, _element);
+ UpdateScaleAndRotation(_model, _element);
+ UpdateInputTransparent(_model, _element);
+
+ if (_invalidateArrangeNeeded)
+ MaybeInvalidate();
+ _invalidateArrangeNeeded = false;
+
+ UpdateTouchFrameReportedEvent(_model);
+
+ OnUpdated();
+ }
+
+ void ElementOnDoubleTap(object sender, GestureEventArgs gestureEventArgs)
+ {
+ var view = Model as View;
+ if (view == null)
+ return;
+
+ foreach (TapGestureRecognizer gestureRecognizer in
+ view.GestureRecognizers.OfType<TapGestureRecognizer>().Where(g => g.NumberOfTapsRequired == 2))
+ {
+ gestureRecognizer.SendTapped(view);
+ gestureEventArgs.Handled = true;
+ }
+ }
+
+ void ElementOnTap(object sender, GestureEventArgs gestureEventArgs)
+ {
+ var view = Model as View;
+ if (view == null)
+ return;
+
+ foreach (TapGestureRecognizer gestureRecognizer in
+ view.GestureRecognizers.OfType<TapGestureRecognizer>().Where(g => g.NumberOfTapsRequired == 1))
+ {
+ gestureRecognizer.SendTapped(view);
+ gestureEventArgs.Handled = true;
+ }
+ }
+
+ void HandlePan(ManipulationDeltaEventArgs e, View view)
+ {
+ foreach (PanGestureRecognizer recognizer in
+ view.GestureRecognizers.GetGesturesFor<PanGestureRecognizer>().Where(g => g.TouchPoints == _touchPoints))
+ {
+ if (!_isPanning)
+ ((IPanGestureController)recognizer).SendPanStarted(view, Application.Current.PanGestureId);
+
+ double totalX = 0;
+ double totalY = 0;
+
+ // Translation and CumulativeManipulation will be 0 if we have more than one touch point because it thinks we're pinching,
+ // so we'll just go ahead and use the center point of the pinch gesture to figure out how much we're panning.
+ if (_touchPoints > 1 && e.PinchManipulation != null)
+ {
+ totalX = e.PinchManipulation.Current.Center.X - e.PinchManipulation.Original.Center.X;
+ totalY = e.PinchManipulation.Current.Center.Y - e.PinchManipulation.Original.Center.Y;
+ }
+ else
+ {
+ totalX = e.DeltaManipulation.Translation.X + e.CumulativeManipulation.Translation.X;
+ totalY = e.DeltaManipulation.Translation.Y + e.CumulativeManipulation.Translation.Y;
+ }
+
+ ((IPanGestureController)recognizer).SendPan(view, totalX, totalY, Application.Current.PanGestureId);
+ _isPanning = true;
+ }
+ }
+
+ void HandlePinch(ManipulationDeltaEventArgs e, View view)
+ {
+ if (e.PinchManipulation == null)
+ return;
+
+ IEnumerable<PinchGestureRecognizer> pinchGestures = view.GestureRecognizers.GetGesturesFor<PinchGestureRecognizer>();
+ System.Windows.Point translationPoint = e.ManipulationContainer.TransformToVisual(Element).Transform(e.PinchManipulation.Current.Center);
+ var scaleOriginPoint = new Point(translationPoint.X / view.Width, translationPoint.Y / view.Height);
+ foreach (var recognizer in pinchGestures)
+ {
+ if (!_isPinching)
+ ((IPinchGestureController)recognizer).SendPinchStarted(view, scaleOriginPoint);
+ ((IPinchGestureController)recognizer).SendPinch(view, e.PinchManipulation.DeltaScale, scaleOriginPoint);
+ }
+ _isPinching = true;
+ }
+
+ void HandleRedrawNeeded(object sender, EventArgs e)
+ {
+ UpdateNativeControl();
+ }
+
+ void MaybeInvalidate()
+ {
+ if (Model.IsInNativeLayout)
+ return;
+ var parent = (FrameworkElement)Element.Parent;
+ parent?.InvalidateMeasure();
+ Element.InvalidateMeasure();
+ }
+
+ void OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
+ {
+ var view = Model as View;
+ if (view == null)
+ return;
+
+ IEnumerable pinchGestures = view.GestureRecognizers.GetGesturesFor<PinchGestureRecognizer>();
+ foreach (var recognizer in pinchGestures)
+ ((IPinchGestureController)recognizer).SendPinchEnded(view);
+ _isPinching = false;
+
+ IEnumerable<PanGestureRecognizer> panGestures = view.GestureRecognizers.GetGesturesFor<PanGestureRecognizer>().Where(g => g.TouchPoints == _touchPoints);
+ foreach (PanGestureRecognizer recognizer in panGestures)
+ ((IPanGestureController)recognizer).SendPanCompleted(view, Application.Current.PanGestureId);
+ Application.Current.PanGestureId++;
+ _isPanning = false;
+ }
+
+ void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)
+ {
+ var view = Model as View;
+ if (view == null)
+ return;
+
+ HandlePinch(e, view);
+
+ HandlePan(e, view);
+ }
+
+ void Touch_FrameReported(object sender, TouchFrameEventArgs e)
+ {
+ _touchPoints = e.GetTouchPoints(Child).Count;
+ }
+
+ static void UpdateInputTransparent(VisualElement view, FrameworkElement frameworkElement)
+ {
+ frameworkElement.IsHitTestVisible = !view.InputTransparent;
+ }
+
+ static void UpdateOpacity(VisualElement view, FrameworkElement frameworkElement)
+ {
+ frameworkElement.Opacity = view.Opacity;
+ }
+
+ static void UpdateRotation(VisualElement view, FrameworkElement frameworkElement)
+ {
+ double anchorX = view.AnchorX;
+ double anchorY = view.AnchorY;
+ double rotationX = view.RotationX;
+ double rotationY = view.RotationY;
+ double rotation = view.Rotation;
+ double translationX = view.TranslationX;
+ double translationY = view.TranslationY;
+ double scale = view.Scale;
+
+ frameworkElement.Projection = new PlaneProjection
+ {
+ CenterOfRotationX = anchorX,
+ CenterOfRotationY = anchorY,
+ GlobalOffsetX = translationX / scale,
+ GlobalOffsetY = translationY / scale,
+ RotationX = -rotationX,
+ RotationY = -rotationY,
+ RotationZ = -rotation
+ };
+ }
+
+ static void UpdateScaleAndRotation(VisualElement view, FrameworkElement frameworkElement)
+ {
+ double anchorX = view.AnchorX;
+ double anchorY = view.AnchorY;
+ double scale = view.Scale;
+ frameworkElement.RenderTransformOrigin = new System.Windows.Point(anchorX, anchorY);
+ frameworkElement.RenderTransform = new ScaleTransform { ScaleX = scale, ScaleY = scale };
+
+ UpdateRotation(view, frameworkElement);
+ }
+
+ void UpdateTouchFrameReportedEvent(VisualElement model)
+ {
+ if (_touchFrameReportedEventSet)
+ return;
+
+ Touch.FrameReported -= Touch_FrameReported;
+ _touchFrameReportedEventSet = false;
+
+ var view = model as View;
+ if (view == null)
+ return;
+
+ if (!view.GestureRecognizers.GetGesturesFor<PanGestureRecognizer>().Any(g => g.TouchPoints > 1))
+ return;
+
+ Touch.FrameReported += Touch_FrameReported;
+ _touchFrameReportedEventSet = true;
+ }
+
+ static void UpdateVisibility(VisualElement view, FrameworkElement frameworkElement)
+ {
+ frameworkElement.Visibility = view.IsVisible ? Visibility.Visible : Visibility.Collapsed;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/WP8PlatformServices.cs b/Xamarin.Forms.Platform.WP8/WP8PlatformServices.cs
new file mode 100644
index 00000000..c20071f4
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/WP8PlatformServices.cs
@@ -0,0 +1,232 @@
+using System;
+using System.IO;
+using System.IO.IsolatedStorage;
+using System.Net;
+using System.Reflection;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Threading;
+using Windows.System;
+using Xamarin.Forms.Platform.WinPhone;
+
+namespace Xamarin.Forms
+{
+ internal class WP8PlatformServices : IPlatformServices
+ {
+ static readonly MD5CryptoServiceProvider Checksum = new MD5CryptoServiceProvider();
+
+ public void BeginInvokeOnMainThread(Action action)
+ {
+ Deployment.Current.Dispatcher.BeginInvoke(action);
+ }
+
+ public ITimer CreateTimer(Action<object> callback)
+ {
+ return new _Timer(new Timer(o => callback(o)));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, int dueTime, int period)
+ {
+ return new _Timer(new Timer(o => callback(o), state, dueTime, period));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, long dueTime, long period)
+ {
+ return new _Timer(new Timer(o => callback(o), state, dueTime, period));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, TimeSpan dueTime, TimeSpan period)
+ {
+ return new _Timer(new Timer(o => callback(o), state, dueTime, period));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, uint dueTime, uint period)
+ {
+ return new _Timer(new Timer(o => callback(o), state, dueTime, period));
+ }
+
+ public Assembly[] GetAssemblies()
+ {
+ return AppDomain.CurrentDomain.GetAssemblies();
+ }
+
+ public string GetMD5Hash(string input)
+ {
+ byte[] bytes = Checksum.ComputeHash(Encoding.UTF8.GetBytes(input));
+ var ret = new char[32];
+ for (var i = 0; i < 16; i++)
+ {
+ ret[i * 2] = (char)Hex(bytes[i] >> 4);
+ ret[i * 2 + 1] = (char)Hex(bytes[i] & 0xf);
+ }
+ return new string(ret);
+ }
+
+ public double GetNamedSize(NamedSize size, Type targetElementType, bool useOldSizes)
+ {
+ switch (size)
+ {
+ case NamedSize.Default:
+ if (typeof(Label).IsAssignableFrom(targetElementType))
+ return (double)System.Windows.Application.Current.Resources["PhoneFontSizeNormal"];
+ return (double)System.Windows.Application.Current.Resources["PhoneFontSizeMedium"];
+ case NamedSize.Micro:
+ return (double)System.Windows.Application.Current.Resources["PhoneFontSizeSmall"] - 3;
+ case NamedSize.Small:
+ return (double)System.Windows.Application.Current.Resources["PhoneFontSizeSmall"];
+ case NamedSize.Medium:
+ if (useOldSizes)
+ goto case NamedSize.Default;
+ return (double)System.Windows.Application.Current.Resources["PhoneFontSizeMedium"];
+ case NamedSize.Large:
+ return (double)System.Windows.Application.Current.Resources["PhoneFontSizeLarge"];
+ default:
+ throw new ArgumentOutOfRangeException("size");
+ }
+ }
+
+ public Task<Stream> GetStreamAsync(Uri uri, CancellationToken cancellationToken)
+ {
+ var tcs = new TaskCompletionSource<Stream>();
+
+ try
+ {
+ HttpWebRequest request = WebRequest.CreateHttp(uri);
+ request.AllowReadStreamBuffering = true;
+ request.BeginGetResponse(ar =>
+ {
+ if (cancellationToken.IsCancellationRequested)
+ {
+ tcs.SetCanceled();
+ return;
+ }
+
+ try
+ {
+ Stream stream = request.EndGetResponse(ar).GetResponseStream();
+ tcs.TrySetResult(stream);
+ }
+ catch (Exception ex)
+ {
+ tcs.TrySetException(ex);
+ }
+ }, null);
+ }
+ catch (Exception ex)
+ {
+ tcs.TrySetException(ex);
+ }
+
+ return tcs.Task;
+ }
+
+ public IIsolatedStorageFile GetUserStoreForApplication()
+ {
+ return new _IsolatedStorageFile(IsolatedStorageFile.GetUserStoreForApplication());
+ }
+
+ public bool IsInvokeRequired
+ {
+ get { return !Deployment.Current.Dispatcher.CheckAccess(); }
+ }
+
+ public void OpenUriAction(Uri uri)
+ {
+ Launcher.LaunchUriAsync(uri);
+ }
+
+ public void StartTimer(TimeSpan interval, Func<bool> callback)
+ {
+ var timer = new DispatcherTimer { Interval = interval };
+ timer.Start();
+ timer.Tick += (sender, args) =>
+ {
+ bool result = callback();
+ if (!result)
+ timer.Stop();
+ };
+ }
+
+ static int Hex(int v)
+ {
+ if (v < 10)
+ return '0' + v;
+ return 'a' + v - 10;
+ }
+
+ public class _Timer : ITimer
+ {
+ readonly Timer _timer;
+
+ public _Timer(Timer timer)
+ {
+ _timer = timer;
+ }
+
+ public void Change(int dueTime, int period)
+ {
+ _timer.Change(dueTime, period);
+ }
+
+ public void Change(long dueTime, long period)
+ {
+ _timer.Change(dueTime, period);
+ }
+
+ public void Change(TimeSpan dueTime, TimeSpan period)
+ {
+ _timer.Change(dueTime, period);
+ }
+
+ public void Change(uint dueTime, uint period)
+ {
+ _timer.Change(dueTime, period);
+ }
+ }
+
+ public class _IsolatedStorageFile : IIsolatedStorageFile
+ {
+ readonly IsolatedStorageFile _isolatedStorageFile;
+
+ public _IsolatedStorageFile(IsolatedStorageFile isolatedStorageFile)
+ {
+ _isolatedStorageFile = isolatedStorageFile;
+ }
+
+ public Task CreateDirectoryAsync(string path)
+ {
+ _isolatedStorageFile.CreateDirectory(path);
+ return Task.FromResult(true);
+ }
+
+ public Task<bool> GetDirectoryExistsAsync(string path)
+ {
+ return Task.FromResult(_isolatedStorageFile.DirectoryExists(path));
+ }
+
+ public Task<bool> GetFileExistsAsync(string path)
+ {
+ return Task.FromResult(_isolatedStorageFile.FileExists(path));
+ }
+
+ public Task<DateTimeOffset> GetLastWriteTimeAsync(string path)
+ {
+ return Task.FromResult(_isolatedStorageFile.GetLastWriteTime(path));
+ }
+
+ public Task<Stream> OpenFileAsync(string path, FileMode mode, FileAccess access)
+ {
+ Stream stream = _isolatedStorageFile.OpenFile(path, (System.IO.FileMode)mode, (System.IO.FileAccess)access);
+ return Task.FromResult(stream);
+ }
+
+ public Task<Stream> OpenFileAsync(string path, FileMode mode, FileAccess access, FileShare share)
+ {
+ Stream stream = _isolatedStorageFile.OpenFile(path, (System.IO.FileMode)mode, (System.IO.FileAccess)access, (System.IO.FileShare)share);
+ return Task.FromResult(stream);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/WPResources.xaml b/Xamarin.Forms.Platform.WP8/WPResources.xaml
new file mode 100644
index 00000000..6a234e60
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/WPResources.xaml
@@ -0,0 +1,542 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
+ xmlns:forms="clr-namespace:Xamarin.Forms.Platform.WinPhone"
+ xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
+ xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">
+
+ <forms:CaseConverter x:Key="UpperConverter" ConvertToUpper="True" />
+ <forms:CaseConverter x:Key="LowerConverter" ConvertToUpper="False" />
+ <forms:ColorConverter x:Key="ColorConverter" />
+ <forms:HeightConverter x:Key="HeightConverter" />
+ <forms:HorizontalTextAlignmentConverter x:Key="HorizontalTextAlignmentConverter" />
+ <forms:KeyboardConverter x:Key="KeyboardConverter"/>
+ <forms:ImageConverter x:Key="ImageConverter" />
+ <forms:ViewToRendererConverter x:Key="ViewToRenderer" />
+ <forms:PageToRendererConverter x:Key="PageToRenderer" />
+ <forms:CollapseWhenEmptyConverter x:Key="CollapseWhenEmpty" />
+ <forms:EntryCellRendererCompleted x:Key="EntryCellRendererCompleted" />
+
+ <Style x:Key="PhoneTextSmallTitleStyle" BasedOn="{StaticResource PhoneTextNormalStyle}" TargetType="TextBlock">
+ <Style.Setters>
+ <Setter Property="FontWeight" Value="Bold" />
+ </Style.Setters>
+ </Style>
+
+ <DataTemplate x:Key="CellTemplate">
+ <Border Background="Transparent">
+ <forms:CellControl Cell="{Binding}" HorizontalContentAlignment="Stretch" />
+ </Border>
+ </DataTemplate>
+
+ <DataTemplate x:Key="TableGroup">
+ <StackPanel Margin="0,20,0,0">
+ <TextBlock Text="{Binding Title,Converter={StaticResource LowerConverter}}" Style="{StaticResource PhoneTextGroupHeaderStyle}" />
+ <ItemsControl ItemsSource="{Binding}" ItemTemplate="{StaticResource CellTemplate}" />
+ </StackPanel>
+ </DataTemplate>
+
+ <DataTemplate x:Key="ViewCell">
+ <ContentPresenter Height="{Binding RenderHeight, Converter={StaticResource HeightConverter}}" Content="{Binding View,Converter={StaticResource ViewToRenderer}}" />
+ </DataTemplate>
+
+ <DataTemplate x:Key="View">
+ <ContentPresenter Content="{Binding Path=.,Converter={StaticResource ViewToRenderer}}" />
+ </DataTemplate>
+
+ <Style x:Key="HeaderJumpStyle" TargetType="phone:LongListSelector">
+ <Setter Property="GridCellSize" Value="113,113" />
+ <Setter Property="LayoutMode" Value="Grid" />
+ <Setter Property="ItemTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <Border Background="{StaticResource PhoneAccentBrush}" Margin="6">
+ <TextBlock Text="{Binding ShortName, Converter={StaticResource LowerConverter}}" Foreground="{StaticResource PhoneForegroundBrush}" FontSize="48" Padding="6" FontFamily="{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment="Left" VerticalAlignment="Bottom" />
+ </Border>
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <DataTemplate x:Key="ListViewHeader">
+ <forms:CellControl Cell="{Binding HeaderContent}" HorizontalContentAlignment="Left" ShowContextActions="False" />
+ </DataTemplate>
+
+ <DataTemplate x:Key="ListViewHeaderTextCell">
+ <Border Background="{StaticResource PhoneAccentBrush}" Height="{Binding RenderHeight, Converter={StaticResource HeightConverter}}" Margin="5" MinWidth="62" MinHeight="62">
+ <StackPanel Margin="6">
+ <StackPanel.Resources>
+ <Style TargetType="TextBlock">
+ <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiLight}" />
+ </Style>
+ </StackPanel.Resources>
+
+ <TextBlock FontSize="48"
+ Text="{Binding Text, Converter={StaticResource LowerConverter}}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding TextColor,Converter={StaticResource ColorConverter},ConverterParameter=PhoneForegroundBrush}" />
+
+ <TextBlock FontSize="32"
+ Text="{Binding Detail}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding DetailColor,Converter={StaticResource ColorConverter},ConverterParameter=PhoneAccentBrush}" />
+ </StackPanel>
+ </Border>
+ </DataTemplate>
+
+ <DataTemplate x:Key="TextCell">
+ <Button Name="button" Margin="0,10,0,0" Height="{Binding RenderHeight, Converter={StaticResource HeightConverter}}" IsEnabled="{Binding IsEnabled}">
+ <Button.Template>
+ <ControlTemplate>
+ <Grid Background="{Binding Background,RelativeSource={RelativeSource TemplatedParent}}">
+ <ContentPresenter />
+ </Grid>
+ </ControlTemplate>
+ </Button.Template>
+ <Button.Content>
+ <StackPanel>
+ <TextBlock
+ Style="{StaticResource PhoneTextExtraLargeStyle}"
+ Text="{Binding Text,Converter={StaticResource LowerConverter}}"
+ Foreground="{Binding TextColor,Converter={StaticResource ColorConverter},ConverterParameter=PhoneForegroundBrush}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ toolkit:TiltEffect.IsTiltEnabled="True"
+ />
+
+ <TextBlock
+ Style="{StaticResource PhoneTextAccentStyle}"
+ Text="{Binding Detail}"
+ Foreground="{Binding DetailColor,Converter={StaticResource ColorConverter},ConverterParameter=PhoneAccentBrush}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ toolkit:TiltEffect.IsTiltEnabled="True"
+ />
+ </StackPanel>
+ </Button.Content>
+ </Button>
+ </DataTemplate>
+
+ <DataTemplate x:Key="ImageCell">
+ <Button Name="button" Margin="0,10,0,0" Height="{Binding RenderHeight, Converter={StaticResource HeightConverter}}" IsEnabled="{Binding IsEnabled}">
+ <Button.Template>
+ <ControlTemplate>
+ <Grid Background="{Binding Background,RelativeSource={RelativeSource TemplatedParent}}">
+ <ContentPresenter />
+ </Grid>
+ </ControlTemplate>
+ </Button.Template>
+ <Button.Content>
+ <Grid Margin="10, 0, 0, 0">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="80"/>
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+
+ <Image
+ Grid.Column="0"
+ DataContext="{Binding ImageSource, Converter={StaticResource ImageConverter}}"
+ Source="{Binding Value}"
+ VerticalAlignment="Center"
+ />
+
+ <StackPanel Grid.Column="1">
+ <TextBlock
+ Style="{StaticResource PhoneTextExtraLargeStyle}"
+ Text="{Binding Text,Converter={StaticResource LowerConverter}}"
+ Foreground="{Binding TextColor,Converter={StaticResource ColorConverter},ConverterParameter=PhoneForegroundBrush}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ toolkit:TiltEffect.IsTiltEnabled="True"
+ />
+
+ <TextBlock
+ Style="{StaticResource PhoneTextAccentStyle}"
+ Text="{Binding Detail}"
+ Foreground="{Binding DetailColor,Converter={StaticResource ColorConverter},ConverterParameter=PhoneAccentBrush}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ toolkit:TiltEffect.IsTiltEnabled="True"
+ />
+ </StackPanel>
+ </Grid>
+ </Button.Content>
+ </Button>
+ </DataTemplate>
+
+ <DataTemplate x:Key="ListImageCell">
+ <Button Margin="0,10,0,0" Height="{Binding RenderHeight, Converter={StaticResource HeightConverter}}" IsEnabled="{Binding IsEnabled}">
+ <Button.Template>
+ <ControlTemplate>
+ <Grid Background="{Binding Background,RelativeSource={RelativeSource TemplatedParent}}">
+ <ContentPresenter />
+ </Grid>
+ </ControlTemplate>
+ </Button.Template>
+ <Button.Content>
+ <Grid Margin="10, 0, 0, 0">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="80"/>
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+
+ <Image
+ Grid.Column="0"
+ DataContext="{Binding ImageSource, Converter={StaticResource ImageConverter}}"
+ Source="{Binding Value}"
+ VerticalAlignment="Center"
+ />
+
+ <StackPanel Grid.Column="1">
+ <TextBlock
+ Style="{StaticResource PhoneTextLargeStyle}"
+ Text="{Binding Text}"
+ Foreground="{Binding TextColor,Converter={StaticResource ColorConverter},ConverterParameter=PhoneForegroundBrush}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ toolkit:TiltEffect.IsTiltEnabled="True"
+ forms:ListViewRenderer.HighlightWhenSelected="True"
+ />
+
+ <TextBlock
+ Style="{StaticResource PhoneTextAccentStyle}"
+ Text="{Binding Detail}"
+ Foreground="{Binding DetailColor,Converter={StaticResource ColorConverter},ConverterParameter=PhoneAccentBrush}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ toolkit:TiltEffect.IsTiltEnabled="True"
+ forms:ListViewRenderer.HighlightWhenSelected="True"
+ />
+ </StackPanel>
+ </Grid>
+ </Button.Content>
+ </Button>
+ </DataTemplate>
+
+ <DataTemplate x:Key="ListViewTextCell">
+ <Button Margin="0,10,0,0" Height="{Binding RenderHeight, Converter={StaticResource HeightConverter}}" IsEnabled="{Binding IsEnabled}">
+ <Button.Template>
+ <ControlTemplate>
+ <Grid Background="{Binding Background,RelativeSource={RelativeSource TemplatedParent}}">
+ <ContentPresenter />
+ </Grid>
+ </ControlTemplate>
+ </Button.Template>
+ <Button.Content>
+ <StackPanel>
+ <TextBlock
+ Style="{StaticResource PhoneTextLargeStyle}"
+ Text="{Binding Text}"
+ Foreground="{Binding TextColor,Converter={StaticResource ColorConverter},ConverterParameter=PhoneForegroundBrush}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ toolkit:TiltEffect.IsTiltEnabled="True"
+ forms:ListViewRenderer.HighlightWhenSelected="True"
+ />
+
+ <TextBlock
+ Style="{StaticResource PhoneTextAccentStyle}"
+ Text="{Binding Detail}"
+ Foreground="{Binding DetailColor,Converter={StaticResource ColorConverter},ConverterParameter=PhoneAccentBrush}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ toolkit:TiltEffect.IsTiltEnabled="True"
+ forms:ListViewRenderer.HighlightWhenSelected="True"
+ />
+ </StackPanel>
+ </Button.Content>
+ </Button>
+ </DataTemplate>
+
+ <DataTemplate x:Key="EntryCell">
+ <Grid HorizontalAlignment="Stretch">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+
+ <Grid.Children>
+ <TextBlock forms:ListViewRenderer.HighlightWhenSelected="True" Style="{StaticResource PhoneTextLargeStyle}"
+ Text="{Binding Label}"
+ Foreground="{Binding LabelColor,Converter={StaticResource ColorConverter},ConverterParameter=PhoneForegroundBrush}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ VerticalAlignment="Center"
+ Grid.Column="0"
+ />
+ <forms:EntryCellPhoneTextBox
+ IsEnabled="{Binding IsEnabled}"
+ Hint="{Binding Placeholder}"
+ Text="{Binding Text, Mode=TwoWay}"
+ InputScope="{Binding Keyboard, Converter={StaticResource KeyboardConverter}}"
+ VerticalAlignment="Center"
+ TextAlignment="{Binding HorizontalTextAlignment, Converter={StaticResource HorizontalTextAlignmentConverter}}"
+ Grid.Column="1"
+ >
+ <i:Interaction.Triggers>
+ <i:EventTrigger EventName="KeyboardReturnPressed">
+ <i:InvokeCommandAction Command="{StaticResource EntryCellRendererCompleted}" CommandParameter="{Binding}" />
+ </i:EventTrigger>
+ </i:Interaction.Triggers>
+ </forms:EntryCellPhoneTextBox>
+ </Grid.Children>
+ </Grid>
+ </DataTemplate>
+
+ <DataTemplate x:Key="SwitchCell">
+ <toolkit:ToggleSwitch Content="{Binding Text}" Height="{Binding RenderHeight, Converter={StaticResource HeightConverter}}"
+ IsChecked="{Binding On, Mode=TwoWay}" IsEnabled="{Binding IsEnabled}" FontFamily="{StaticResource PhoneFontFamilyNormal}" />
+ </DataTemplate>
+
+ <DataTemplate x:Key="TabbedPage">
+ <forms:TabbedPagePresenter Content="{Binding Converter={StaticResource PageToRenderer}}" />
+ </DataTemplate>
+
+ <DataTemplate x:Key="TabbedPageHeader">
+ <TextBlock Text="{Binding Title, Converter={StaticResource LowerConverter}}" />
+ </DataTemplate>
+
+ <DataTemplate x:Key="CarouselPage">
+ <forms:CarouselPagePresenter Content="{Binding Converter={StaticResource PageToRenderer}}" />
+ </DataTemplate>
+
+ <DataTemplate x:Key="PickerItemTemplate">
+ <StackPanel>
+ <TextBlock Text="{Binding Data}" Opacity="{Binding Opacity}"/>
+ </StackPanel>
+ </DataTemplate>
+
+ <DataTemplate x:Key="PickerFullItemTemplate">
+ <StackPanel MaxHeight="{Binding MaxHeight}">
+ <TextBlock Text="{Binding Data}" FontSize="43" />
+ </StackPanel>
+ </DataTemplate>
+
+ <!-- Overriding the PhoneTextBox Style so we can handle Placeholder alignment -->
+ <forms:TextAlignmentToHorizontalAlignmentConverter x:Key="AlignmentConverter" />
+ <Style TargetType="forms:FormsPhoneTextBox">
+ <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilyNormal}" />
+ <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}" />
+ <Setter Property="Background" Value="{StaticResource PhoneTextBoxBrush}" />
+ <Setter Property="Foreground" Value="{StaticResource PhoneTextBoxForegroundBrush}" />
+ <Setter Property="BorderBrush" Value="{StaticResource PhoneTextBoxBrush}" />
+ <Setter Property="SelectionBackground" Value="{StaticResource PhoneAccentBrush}" />
+ <Setter Property="SelectionForeground" Value="{StaticResource PhoneTextBoxSelectionForegroundBrush}" />
+ <Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}" />
+ <Setter Property="Padding" Value="{StaticResource PhoneBorderThickness}" />
+ <Setter Property="PlaceholderForegroundBrush" Value="{StaticResource PhoneTextBoxReadOnlyBrush}" />
+
+ <Setter Property="Template">
+ <Setter.Value>
+
+ <ControlTemplate TargetType="forms:FormsPhoneTextBox">
+
+ <Grid Background="Transparent" x:Name="RootGrid">
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal" />
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
+ Storyboard.TargetName="HintBorder">
+ <DiscreteObjectKeyFrame KeyTime="0">
+ <DiscreteObjectKeyFrame.Value>
+ <Visibility>Collapsed</Visibility>
+ </DiscreteObjectKeyFrame.Value>
+ </DiscreteObjectKeyFrame>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
+ Storyboard.TargetName="TextBorder">
+ <DiscreteObjectKeyFrame KeyTime="0">
+ <DiscreteObjectKeyFrame.Value>
+ <Visibility>Visible</Visibility>
+ </DiscreteObjectKeyFrame.Value>
+ </DiscreteObjectKeyFrame>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush"
+ Storyboard.TargetName="TextBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Margin"
+ Storyboard.TargetName="TextBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="0" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="HorizontalAlignment"
+ Storyboard.TargetName="Text">
+ <DiscreteObjectKeyFrame KeyTime="0">
+ <DiscreteObjectKeyFrame.Value>
+ <HorizontalAlignment>Stretch</HorizontalAlignment>
+ </DiscreteObjectKeyFrame.Value>
+ </DiscreteObjectKeyFrame>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="FocusStates">
+ <VisualState x:Name="Focused">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background"
+ Storyboard.TargetName="HintBorder">
+ <DiscreteObjectKeyFrame KeyTime="0"
+ Value="{StaticResource PhoneTextBoxEditBackgroundBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush"
+ Storyboard.TargetName="HintBorder">
+ <DiscreteObjectKeyFrame KeyTime="0"
+ Value="{StaticResource PhoneTextBoxEditBorderBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Unfocused" />
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="LengthIndicatorStates">
+ <VisualState x:Name="LengthIndicatorVisible">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
+ Storyboard.TargetName="LengthIndicator">
+ <DiscreteObjectKeyFrame KeyTime="0:0:0">
+ <DiscreteObjectKeyFrame.Value>
+ <Visibility>Visible</Visibility>
+ </DiscreteObjectKeyFrame.Value>
+ </DiscreteObjectKeyFrame>
+ </ObjectAnimationUsingKeyFrames>
+
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid"
+ Storyboard.TargetProperty="Margin">
+ <DiscreteObjectKeyFrame KeyTime="0:0:0"
+ Value="0, 0, 0, 27" />
+ </ObjectAnimationUsingKeyFrames>
+
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity"
+ Storyboard.TargetName="LengthIndicator">
+ <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="0.6" />
+ </ObjectAnimationUsingKeyFrames>
+
+ <DoubleAnimation Storyboard.TargetName="LengthIndicator"
+ Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.Y)"
+ To="32"
+ Duration="0:0:0.350">
+ <DoubleAnimation.EasingFunction>
+ <ExponentialEase Exponent="6" />
+ </DoubleAnimation.EasingFunction>
+ </DoubleAnimation>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="LengthIndicatorHidden">
+ <Storyboard>
+ <DoubleAnimation Storyboard.TargetName="LengthIndicator"
+ Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.Y)"
+ To="0"
+ Duration="0:0:0.350">
+ <DoubleAnimation.EasingFunction>
+ <ExponentialEase Exponent="6" />
+ </DoubleAnimation.EasingFunction>
+ </DoubleAnimation>
+
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid"
+ Storyboard.TargetProperty="Margin">
+ <DiscreteObjectKeyFrame KeyTime="0:0:0"
+ Value="0, 0, 0, 0" />
+ </ObjectAnimationUsingKeyFrames>
+
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity"
+ Storyboard.TargetName="LengthIndicator">
+ <DiscreteObjectKeyFrame KeyTime="0:0:0.350" Value="0" />
+ </ObjectAnimationUsingKeyFrames>
+
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
+ Storyboard.TargetName="LengthIndicator">
+ <DiscreteObjectKeyFrame KeyTime="0:0:0.350">
+ <DiscreteObjectKeyFrame.Value>
+ <Visibility>Collapsed</Visibility>
+ </DiscreteObjectKeyFrame.Value>
+ </DiscreteObjectKeyFrame>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+
+ <Border x:Name="LengthIndicatorBorder">
+ <TextBlock Foreground="{StaticResource PhoneContrastBackgroundBrush}"
+ HorizontalAlignment="Right"
+ TextAlignment="Right"
+ VerticalAlignment="Bottom"
+ Margin="{StaticResource PhoneMargin}"
+ FontSize="{StaticResource PhoneFontSizeNormal}"
+ Opacity="0"
+ x:Name="LengthIndicator">
+ <TextBlock.RenderTransform>
+ <TranslateTransform />
+ </TextBlock.RenderTransform>
+ </TextBlock>
+ </Border>
+
+ <Border x:Name="HintBorder"
+ BorderBrush="{TemplateBinding BorderBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}"
+ Background="{TemplateBinding Background}"
+ Margin="{StaticResource PhoneTouchTargetOverhang}">
+ <Grid>
+ <ContentControl x:Name="HintContent"
+ Style="{TemplateBinding HintStyle}"
+ Content="{TemplateBinding Hint}"
+ Foreground="{TemplateBinding PlaceholderForegroundBrush}"
+ Background="Transparent"
+ HorizontalAlignment="{Binding TextAlignment,
+ RelativeSource={RelativeSource Mode=TemplatedParent},
+ Converter={StaticResource AlignmentConverter}}"
+ VerticalAlignment="Center"
+ Margin="3,0,3,0"
+ Visibility="{TemplateBinding ActualHintVisibility}" />
+ <ContentControl x:Name="ContentElement"
+ BorderThickness="0"
+ HorizontalContentAlignment="Stretch"
+ Margin="{StaticResource PhoneTextBoxInnerMargin}"
+ Padding="{TemplateBinding Padding}"
+ VerticalContentAlignment="Stretch" />
+ </Grid>
+ </Border>
+ <Border x:Name="TextBorder"
+ BorderBrush="{StaticResource PhoneDisabledBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}"
+ Background="Transparent"
+ Margin="{StaticResource PhoneTouchTargetOverhang}"
+ Visibility="Collapsed">
+ <TextBox x:Name="Text"
+ Foreground="{StaticResource PhoneDisabledBrush}"
+ FontWeight="{TemplateBinding FontWeight}"
+ FontStyle="{TemplateBinding FontStyle}"
+ FontSize="{TemplateBinding FontSize}"
+ FontFamily="{TemplateBinding FontFamily}"
+ SelectionForeground="{TemplateBinding SelectionForeground}"
+ SelectionBackground="{TemplateBinding SelectionBackground}"
+ TextAlignment="{TemplateBinding TextAlignment}"
+ TextWrapping="{TemplateBinding TextWrapping}"
+ Text="{TemplateBinding DisabledText}"
+
+ HorizontalAlignment="Left" />
+ </Border>
+ <Border x:Name="ActionIconBorder"
+ Width="84"
+ Height="72"
+ Background="Transparent"
+ HorizontalAlignment="Right"
+ VerticalAlignment="Bottom">
+ <Image x:Name="ActionIcon"
+ Width="26"
+ Height="26"
+ Source="{TemplateBinding ActionIcon}" />
+ </Border>
+
+ <TextBlock x:Name="MeasurementTextBlock"
+ Margin="8"
+ IsHitTestVisible="False"
+ Opacity="0"
+ FontFamily="{TemplateBinding FontFamily}"
+ FontSize="{TemplateBinding FontSize}"
+ FontStretch="{TemplateBinding FontStretch}"
+ TextAlignment="{TemplateBinding TextAlignment}"
+ FontWeight="{TemplateBinding FontWeight}"
+ FontStyle="{TemplateBinding FontStyle}"
+ TextWrapping="{TemplateBinding TextWrapping}"
+ Text="{TemplateBinding Text}" />
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+</ResourceDictionary>
diff --git a/Xamarin.Forms.Platform.WP8/WebViewRenderer.cs b/Xamarin.Forms.Platform.WP8/WebViewRenderer.cs
new file mode 100644
index 00000000..4b3151b0
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/WebViewRenderer.cs
@@ -0,0 +1,166 @@
+using System;
+using System.ComponentModel;
+using System.IO;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Navigation;
+using Microsoft.Phone.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class WebViewRenderer : ViewRenderer<WebView, WebBrowser>, IWebViewRenderer
+ {
+ WebNavigationEvent _eventState;
+ bool _updating;
+
+ public async void LoadHtml(string html, string baseUrl)
+ {
+ string fileName = string.Format("formslocal_{0}.html", DateTime.Now.Ticks);
+ ;
+ await SaveToIsoStore(fileName, html);
+ Control.Navigate(new Uri(fileName, UriKind.Relative));
+ }
+
+ public void LoadUrl(string url)
+ {
+ Control.Source = new Uri(url, UriKind.RelativeOrAbsolute);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
+ {
+ base.OnElementChanged(e);
+
+ if (Control == null)
+ {
+ var webBrowser = new WebBrowser();
+ webBrowser.IsScriptEnabled = true;
+ webBrowser.Navigated += WebBrowserOnNavigated;
+ webBrowser.Navigating += WebBrowserOnNavigating;
+ webBrowser.NavigationFailed += WebBrowserOnNavigationFailed;
+ SetNativeControl(webBrowser);
+ }
+
+ if (e.OldElement != null)
+ {
+ e.OldElement.EvalRequested -= OnEvalRequested;
+ e.OldElement.GoBackRequested -= OnGoBackRequested;
+ e.OldElement.GoForwardRequested -= OnGoForwardRequested;
+ Control.DataContext = null;
+ }
+
+ if (e.NewElement != null)
+ {
+ e.NewElement.EvalRequested += OnEvalRequested;
+ e.NewElement.GoBackRequested += OnGoBackRequested;
+ e.NewElement.GoForwardRequested += OnGoForwardRequested;
+ Control.DataContext = e.NewElement;
+ }
+
+ Load();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ switch (e.PropertyName)
+ {
+ case "Source":
+ if (!_updating)
+ Load();
+ break;
+ }
+ }
+
+ void Load()
+ {
+ if (Element.Source != null)
+ Element.Source.Load(this);
+
+ UpdateCanGoBackForward();
+ }
+
+ void OnEvalRequested(object sender, EventArg<string> eventArg)
+ {
+ Control.Dispatcher.BeginInvoke(() => Control.InvokeScript("eval", eventArg.Data));
+ }
+
+ void OnGoBackRequested(object sender, EventArgs eventArgs)
+ {
+ if (Control.CanGoBack)
+ {
+ _eventState = WebNavigationEvent.Back;
+ Control.GoBack();
+ }
+
+ UpdateCanGoBackForward();
+ }
+
+ void OnGoForwardRequested(object sender, EventArgs eventArgs)
+ {
+ if (Control.CanGoForward)
+ {
+ _eventState = WebNavigationEvent.Forward;
+ Control.GoForward();
+ }
+ UpdateCanGoBackForward();
+ }
+
+ async Task SaveToIsoStore(string fileName, string html)
+ {
+ IIsolatedStorageFile store = Device.PlatformServices.GetUserStoreForApplication();
+ using(Stream file = await store.OpenFileAsync(fileName, FileMode.CreateNew, FileAccess.Write).ConfigureAwait(false))
+ {
+ byte[] bytes = Encoding.UTF8.GetBytes(html);
+ await file.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
+ }
+ }
+
+ void SendNavigated(UrlWebViewSource source, WebNavigationEvent evnt, WebNavigationResult result)
+ {
+ _updating = true;
+ ((IElementController)Element).SetValueFromRenderer(WebView.SourceProperty, source);
+ _updating = false;
+
+ Element.SendNavigated(new WebNavigatedEventArgs(evnt, source, source.Url, result));
+
+ UpdateCanGoBackForward();
+ _eventState = WebNavigationEvent.NewPage;
+ }
+
+ // Nasty hack because we cant bind this because OneWayToSource isn't a thing in WP8, yay
+ void UpdateCanGoBackForward()
+ {
+ Element.CanGoBack = Control.CanGoBack;
+ Element.CanGoForward = Control.CanGoForward;
+ }
+
+ void WebBrowserOnNavigated(object sender, System.Windows.Navigation.NavigationEventArgs navigationEventArgs)
+ {
+ string url = navigationEventArgs.Uri.IsAbsoluteUri ? navigationEventArgs.Uri.AbsoluteUri : navigationEventArgs.Uri.OriginalString;
+ SendNavigated(new UrlWebViewSource { Url = url }, _eventState, WebNavigationResult.Success);
+
+ UpdateCanGoBackForward();
+ }
+
+ void WebBrowserOnNavigating(object sender, NavigatingEventArgs navigatingEventArgs)
+ {
+ string url = navigatingEventArgs.Uri.IsAbsoluteUri ? navigatingEventArgs.Uri.AbsoluteUri : navigatingEventArgs.Uri.OriginalString;
+ var args = new WebNavigatingEventArgs(_eventState, new UrlWebViewSource { Url = url }, url);
+
+ Element.SendNavigating(args);
+
+ navigatingEventArgs.Cancel = args.Cancel;
+
+ // reset in this case because this is the last event we will get
+ if (args.Cancel)
+ _eventState = WebNavigationEvent.NewPage;
+ }
+
+ void WebBrowserOnNavigationFailed(object sender, NavigationFailedEventArgs navigationFailedEventArgs)
+ {
+ string url = navigationFailedEventArgs.Uri.IsAbsoluteUri ? navigationFailedEventArgs.Uri.AbsoluteUri : navigationFailedEventArgs.Uri.OriginalString;
+ SendNavigated(new UrlWebViewSource { Url = url }, _eventState, WebNavigationResult.Failure);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/WinPhoneTicker.cs b/Xamarin.Forms.Platform.WP8/WinPhoneTicker.cs
new file mode 100644
index 00000000..94b17246
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/WinPhoneTicker.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Windows.Threading;
+
+namespace Xamarin.Forms
+{
+ internal class WinPhoneTicker : Ticker
+ {
+ readonly DispatcherTimer _timer;
+
+ public WinPhoneTicker()
+ {
+ _timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(15) };
+ _timer.Tick += (sender, args) => SendSignals();
+ }
+
+ protected override void DisableTimer()
+ {
+ _timer.Stop();
+ }
+
+ protected override void EnableTimer()
+ {
+ _timer.Start();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/Xamarin.Forms.Platform.WP8.csproj b/Xamarin.Forms.Platform.WP8/Xamarin.Forms.Platform.WP8.csproj
new file mode 100644
index 00000000..29ebeae0
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/Xamarin.Forms.Platform.WP8.csproj
@@ -0,0 +1,245 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>10.0.20506</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{517B6AE0-792B-4665-9376-5CA33E539181}</ProjectGuid>
+ <ProjectTypeGuids>{C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Platform.WinPhone</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Platform.WP8</AssemblyName>
+ <TargetFrameworkIdentifier>WindowsPhone</TargetFrameworkIdentifier>
+ <TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
+ <SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
+ <SilverlightApplication>false</SilverlightApplication>
+ <ValidateXaml>true</ValidateXaml>
+ <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+ <ThrowErrorsInValidation>true</ThrowErrorsInValidation>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>Bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>Bin\Release</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>Bin\x86\Debug</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>Bin\x86\Release</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>Bin\ARM\Debug</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|ARM' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>Bin\ARM\Release</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|ARM'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\ARM\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="ActivityIndicatorRenderer.cs" />
+ <Compile Include="AlignmentExtensions.cs" />
+ <Compile Include="Animatable.cs" />
+ <Compile Include="AsyncValue.cs" />
+ <Compile Include="CellControl.cs" />
+ <Compile Include="CollapseWhenEmptyConverter.cs" />
+ <Compile Include="Deserializer.cs" />
+ <Compile Include="CustomContextMenu.cs" />
+ <Compile Include="ElementChangedEventArgs.cs" />
+ <Compile Include="ExportCellAttribute.cs" />
+ <Compile Include="ExportImageSourceHandlerAttribute.cs" />
+ <Compile Include="ExportRendererAttribute.cs" />
+ <Compile Include="Extensions.cs" />
+ <Compile Include="FontExtensions.cs" />
+ <Compile Include="Forms.cs" />
+ <Compile Include="FormsApplicationPage.cs" />
+ <Compile Include="FormsListPicker.cs" />
+ <Compile Include="FormsPhoneTextBox.cs" />
+ <Compile Include="FrameworkElementExtensions.cs" />
+ <Compile Include="LayoutExtensions.cs" />
+ <Compile Include="CarouselViewRenderer.cs" />
+ <Compile Include="MD5.cs" />
+ <Compile Include="MD5CryptoServiceProvider.cs" />
+ <Compile Include="NativeViewWrapper.cs" />
+ <Compile Include="NativeViewWrapperRenderer.cs" />
+ <Compile Include="PageToRendererConverter.cs" />
+ <Compile Include="PlatformEffect.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="BoxViewRenderer.cs" />
+ <Compile Include="ButtonRenderer.cs" />
+ <Compile Include="CarouselPageRenderer.cs" />
+ <Compile Include="Converters\CaseConverter.cs" />
+ <Compile Include="Converters\ColorConverter.cs" />
+ <Compile Include="Converters\ImageConverter.cs" />
+ <Compile Include="Converters\KeyboardConverter.cs" />
+ <Compile Include="Converters\HorizontalTextAlignmentConverter.cs" />
+ <Compile Include="CellTemplateSelector.cs" />
+ <Compile Include="ConvertExtensions.cs" />
+ <Compile Include="DataTemplateSelector.cs" />
+ <Compile Include="DatePickerRenderer.cs" />
+ <Compile Include="EditorRenderer.cs" />
+ <Compile Include="EntryRenderer.cs" />
+ <Compile Include="FrameRenderer.cs" />
+ <Compile Include="ICellRenderer.cs" />
+ <Compile Include="ImageRenderer.cs" />
+ <Compile Include="IVisualElementRenderer.cs" />
+ <Compile Include="LabelRenderer.cs" />
+ <Compile Include="ListViewRenderer.cs" />
+ <Compile Include="MasterDetailRenderer.cs" />
+ <Compile Include="NavigationMenuRenderer.cs" />
+ <Compile Include="NavigationPageRenderer.cs" />
+ <Compile Include="PageRenderer.cs" />
+ <Compile Include="Platform.cs" />
+ <Compile Include="ProgressBarRenderer.cs" />
+ <Compile Include="RendererFactory.cs" />
+ <Compile Include="ResourcesProvider.cs" />
+ <Compile Include="ScrollViewRenderer.cs" />
+ <Compile Include="SearchBarRenderer.cs" />
+ <Compile Include="SliderRenderer.cs" />
+ <Compile Include="StepperRenderer.cs" />
+ <Compile Include="SwitchRenderer.cs" />
+ <Compile Include="TabbedPageRenderer.cs" />
+ <Compile Include="TableView.xaml.cs">
+ <DependentUpon>TableView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="TableViewRenderer.cs" />
+ <Compile Include="TextAlignmentToHorizontalAlignmentConverter.cs" />
+ <Compile Include="TextCellRenderer.cs" />
+ <Compile Include="TimePickerRenderer.cs" />
+ <Compile Include="ViewExtensions.cs" />
+ <Compile Include="VisualElementPackager.cs" />
+ <Compile Include="ViewRenderer.cs" />
+ <Compile Include="ViewToRendererConverter.cs" />
+ <Compile Include="VisualElementRenderer.cs" />
+ <Compile Include="VisualElementTracker.cs" />
+ <Compile Include="WebViewRenderer.cs" />
+ <Compile Include="PickerRenderer.cs" />
+ <Compile Include="WinPhoneTicker.cs" />
+ <Compile Include="WP8PlatformServices.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="Microsoft.Phone.Controls, Version=8.0.0.0, Culture=neutral, PublicKeyToken=24eec0d8c86cda1e, processorArchitecture=MSIL" />
+ <Reference Include="Microsoft.Phone.Controls.Toolkit">
+ <HintPath>..\packages\WPtoolkit.4.2013.08.16\lib\wp8\Microsoft.Phone.Controls.Toolkit.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Windows.Interactivity, Version=3.9.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ <Content Include="ServiceReferences.ClientConfig" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="Toolkit.Content\ApplicationBar.Cancel.png" />
+ <Content Include="Toolkit.Content\ApplicationBar.Check.png" />
+ <Content Include="Toolkit.Content\ApplicationBar.Delete.png" />
+ <Content Include="Toolkit.Content\ApplicationBar.Select.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <Page Include="TableView.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="WPResources.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).$(TargetFrameworkVersion).Overrides.targets" />
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).CSharp.targets" />
+ <ProjectExtensions />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WP8/packages.config b/Xamarin.Forms.Platform.WP8/packages.config
new file mode 100644
index 00000000..d534d6e7
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="WPtoolkit" version="4.2013.08.16" targetFramework="wp80" />
+</packages>
diff --git a/Xamarin.Forms.Platform.WinRT.Phone/Forms.cs b/Xamarin.Forms.Platform.WinRT.Phone/Forms.cs
new file mode 100644
index 00000000..8d06004c
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Phone/Forms.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Diagnostics;
+using Windows.ApplicationModel.Activation;
+using Windows.Phone.UI.Input;
+using Windows.UI.ViewManagement;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+using Xamarin.Forms.Platform.WinRT;
+
+namespace Xamarin.Forms
+{
+ public static class Forms
+ {
+ public static void Init (IActivatedEventArgs launchActivatedEventArgs)
+ {
+ if (s_isInitialized)
+ return;
+
+ var accent = (SolidColorBrush)Windows.UI.Xaml.Application.Current.Resources["SystemColorControlAccentBrush"];
+ Color.Accent = Color.FromRgba (accent.Color.R, accent.Color.G, accent.Color.B, accent.Color.A);
+
+ Log.Listeners.Add (new DelegateLogListener ((c, m) => Debug.WriteLine (LogFormat, c, m)));
+
+ Windows.UI.Xaml.Application.Current.Resources.MergedDictionaries.Add (GetPhoneResources());
+
+ Device.OS = TargetPlatform.Windows;
+ Device.PlatformServices = new WindowsPhonePlatformServices (Window.Current.Dispatcher);
+ Device.Info = new WindowsDeviceInfo();
+ Device.Idiom = TargetIdiom.Phone;
+
+ Ticker.Default = new WindowsTicker();
+
+ ExpressionSearch.Default = new WindowsExpressionSearch();
+
+ Registrar.RegisterAll (new[] {
+ typeof (ExportRendererAttribute),
+ typeof (ExportCellAttribute),
+ typeof (ExportImageSourceHandlerAttribute)
+ });
+
+ MessagingCenter.Subscribe<Page, bool> (Device.PlatformServices, Page.BusySetSignalName, OnPageBusy);
+
+ HardwareButtons.BackPressed += OnBackPressed;
+
+ s_isInitialized = true;
+ s_state = launchActivatedEventArgs.PreviousExecutionState;
+ }
+
+ static void OnBackPressed (object sender, BackPressedEventArgs e)
+ {
+ Application app = Application.Current;
+ if (app == null)
+ return;
+
+ Page page = app.MainPage;
+ if (page == null)
+ return;
+
+ var platform = page.Platform as Platform.WinRT.Platform;
+ if (platform == null)
+ return;
+
+ e.Handled = platform.BackButtonPressed ();
+ }
+
+ static ApplicationExecutionState s_state;
+ static bool s_isInitialized;
+
+ const string LogFormat = "[{0}] {1}";
+
+ static async void OnPageBusy (Page sender, bool enabled)
+ {
+ StatusBar status = StatusBar.GetForCurrentView ();
+ if (enabled) {
+ status.ProgressIndicator.ProgressValue = null;
+ await status.ProgressIndicator.ShowAsync ();
+ } else
+ await status.ProgressIndicator.HideAsync ();
+ }
+
+ static Windows.UI.Xaml.ResourceDictionary GetPhoneResources ()
+ {
+ return new Windows.UI.Xaml.ResourceDictionary {
+ Source = new Uri ("ms-appx:///Xamarin.Forms.Platform.WinRT.Phone/PhoneResources.xbf")
+ };
+ }
+
+ static Windows.UI.Xaml.ResourceDictionary GetResources (UserControl control)
+ {
+ var gresources = control.Resources.MergedDictionaries[0];
+ control.Resources.MergedDictionaries.Remove (gresources);
+
+ return gresources;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Phone/FormsPivot.cs b/Xamarin.Forms.Platform.WinRT.Phone/FormsPivot.cs
new file mode 100644
index 00000000..d829b787
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Phone/FormsPivot.cs
@@ -0,0 +1,65 @@
+using System.Threading.Tasks;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class FormsPivot : Pivot, IToolbarProvider
+ {
+ public static readonly DependencyProperty ToolbarVisibilityProperty = DependencyProperty.Register("ToolbarVisibility", typeof(Visibility), typeof(FormsPivot),
+ new PropertyMetadata(Visibility.Collapsed));
+
+ public static readonly DependencyProperty ToolbarForegroundProperty = DependencyProperty.Register("ToolbarForeground", typeof(Brush), typeof(FormsPivot), new PropertyMetadata(default(Brush)));
+
+ public static readonly DependencyProperty ToolbarBackgroundProperty = DependencyProperty.Register("ToolbarBackground", typeof(Brush), typeof(FormsPivot), new PropertyMetadata(default(Brush)));
+
+ CommandBar _commandBar;
+
+ TaskCompletionSource<CommandBar> _commandBarTcs;
+
+ public Brush ToolbarBackground
+ {
+ get { return (Brush)GetValue(ToolbarBackgroundProperty); }
+ set { SetValue(ToolbarBackgroundProperty, value); }
+ }
+
+ public Brush ToolbarForeground
+ {
+ get { return (Brush)GetValue(ToolbarForegroundProperty); }
+ set { SetValue(ToolbarForegroundProperty, value); }
+ }
+
+ public Visibility ToolbarVisibility
+ {
+ get { return (Visibility)GetValue(ToolbarVisibilityProperty); }
+ set { SetValue(ToolbarVisibilityProperty, value); }
+ }
+
+ Task<CommandBar> IToolbarProvider.GetCommandBarAsync()
+ {
+ if (_commandBar != null)
+ return Task.FromResult(_commandBar);
+
+ _commandBarTcs = new TaskCompletionSource<CommandBar>();
+ ApplyTemplate();
+ return _commandBarTcs.Task;
+ }
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+ _commandBar = GetTemplateChild("CommandBar") as CommandBar;
+ TaskCompletionSource<CommandBar> tcs = _commandBarTcs;
+ if (tcs != null)
+ {
+ tcs.SetResult(_commandBar);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Phone/FormsTextBoxStyle.xaml b/Xamarin.Forms.Platform.WinRT.Phone/FormsTextBoxStyle.xaml
new file mode 100644
index 00000000..521a9059
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Phone/FormsTextBoxStyle.xaml
@@ -0,0 +1,121 @@
+<ResourceDictionary
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:forms="using:Xamarin.Forms.Platform.WinRT"
+ xmlns:system="using:System">
+
+ <forms:TextAlignmentToHorizontalAlignmentConverter x:Key="AlignmentConverter" />
+
+ <Style x:Key="FormsTextBoxStyle" TargetType="forms:FormsTextBox">
+ <Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}"/>
+ <Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}"/>
+ <Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}"/>
+ <Setter Property="SelectionHighlightColor" Value="{ThemeResource TextSelectionHighlightColorThemeBrush}"/>
+ <Setter Property="Background" Value="{ThemeResource TextBoxBackgroundThemeBrush}"/>
+ <Setter Property="BackgroundFocusBrush" Value="{ThemeResource TextBoxFocusedBackgroundThemeBrush}"/>
+ <Setter Property="BorderBrush" Value="{ThemeResource TextBoxBorderThemeBrush}"/>
+ <Setter Property="BorderThickness" Value="0"/>
+ <Setter Property="FontFamily" Value="{ThemeResource PhoneFontFamilyNormal}"/>
+ <Setter Property="FontSize" Value="{ThemeResource ContentControlFontSize}"/>
+ <Setter Property="PlaceholderForegroundBrush" Value="{ThemeResource TextBoxPlaceholderTextThemeBrush}" />
+ <Setter Property="TextWrapping" Value="NoWrap"/>
+ <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Auto"/>
+ <Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto"/>
+ <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden"/>
+ <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden"/>
+ <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False"/>
+ <Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
+ <Setter Property="Margin" Value="0"/>
+ <Setter Property="VerticalAlignment" Value="Top"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="forms:FormsTextBox">
+ <Grid Background="Transparent">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BorderElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="BorderElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="PlaceholderTextContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="HeaderContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledHeaderForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Normal">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="{ThemeResource TextControlBorderThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BorderElement"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Focused">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="BorderElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextSelectionHighlightColorThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PlaceholderTextContentPresenter"/>
+ <!-- The commented-out section below *should* work, at least according to the docs and examples; but
+ instead it just crashes the application as soon as you focus a textbox. So the forms textbox class handles this
+ state manually in the phone version. I'm leaving this here in case someone can figure it out, because the VSM
+ is a much more elegant solution. (e.g., see the UWP project, where this *does* work) -->
+ <!--<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BorderElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding BackgroundFocusBrush, RelativeSource={RelativeSource TemplatedParent}}"/>
+ </ObjectAnimationUsingKeyFrames>-->
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Border x:Name="BorderElement"
+ BorderBrush="{TemplateBinding BorderBrush}"
+ Background="{TemplateBinding Background}"
+ BorderThickness="{TemplateBinding BorderThickness}"
+ Grid.Row="1"/>
+ <ContentPresenter x:Name="HeaderContentPresenter"
+ ContentTemplate="{TemplateBinding HeaderTemplate}"
+ Content="{TemplateBinding Header}"
+ Margin="{ThemeResource TextControlHeaderMarginThemeThickness}"
+ Grid.Row="0" Style="{StaticResource HeaderContentPresenterStyle}"/>
+ <ScrollViewer x:Name="ContentElement"
+ AutomationProperties.AccessibilityView="Raw"
+ HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
+ HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
+ IsTabStop="False"
+ IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
+ IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
+ IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
+ Margin="{TemplateBinding BorderThickness}"
+ MinHeight="{ThemeResource TextControlThemeMinHeight}"
+ Padding="{TemplateBinding Padding}"
+ Grid.Row="1"
+ FontSize="{ThemeResource ContentControlFontSize}"
+ VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
+ VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
+ ZoomMode="Disabled"/>
+ <ContentControl x:Name="PlaceholderTextContentPresenter"
+ Content="{TemplateBinding PlaceholderText}"
+ Foreground="{TemplateBinding PlaceholderForegroundBrush}"
+ FontSize="{ThemeResource ContentControlFontSize}"
+ IsTabStop="False"
+ Margin="{ThemeResource RichEditBoxTextThemeMargin}"
+ Padding="{TemplateBinding Padding}"
+ Grid.Row="1"
+ HorizontalAlignment="{Binding TextAlignment, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource AlignmentConverter}}"/>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+</ResourceDictionary> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Phone/PhoneResources.xaml b/Xamarin.Forms.Platform.WinRT.Phone/PhoneResources.xaml
new file mode 100644
index 00000000..61f6667e
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Phone/PhoneResources.xaml
@@ -0,0 +1,694 @@
+<ResourceDictionary
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="using:Xamarin.Forms.Platform.WinRT">
+
+ <ResourceDictionary.MergedDictionaries>
+ <ResourceDictionary Source="Resources.xaml" />
+ <ResourceDictionary Source="FormsTextBoxStyle.xaml" />
+ </ResourceDictionary.MergedDictionaries>
+
+ <!-- Fixes button sizing, including background outside the border -->
+ <Thickness x:Key="PhoneTouchTargetOverhang">0</Thickness>
+ <Style TargetType="Button">
+ <Setter Property="MinHeight" Value="38.5" />
+ </Style>
+
+ <Style TargetType="local:FormsButton">
+ <Setter Property="MinHeight" Value="38.5" />
+ </Style>
+
+ <Style TargetType="ToggleSwitch">
+ <Setter Property="Foreground" Value="{ThemeResource ToggleSwitchForegroundThemeBrush}"/>
+ <Setter Property="HorizontalAlignment" Value="Stretch"/>
+ <Setter Property="VerticalAlignment" Value="Center"/>
+ <Setter Property="HorizontalContentAlignment" Value="Left"/>
+ <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
+ <Setter Property="FontWeight" Value="SemiBold"/>
+ <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
+ <Setter Property="Margin" Value="0"/>
+ <Setter Property="Padding" Value="0,0,25.5,0"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="ToggleSwitch">
+ <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal"/>
+ <VisualState x:Name="PointerOver"/>
+ <VisualState x:Name="Pressed"/>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="HeaderContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="OffContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="OnContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SwitchKnob">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchThumbDisabledBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="SwitchKnob">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchThumbDisabledBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="OuterBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchOuterBorderDisabledBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SwitchCurtain">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchCurtainDisabledBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="ToggleStates">
+ <VisualStateGroup.Transitions>
+ <VisualTransition x:Name="DraggingToOnTransition" From="Dragging" GeneratedDuration="0" To="On">
+ <Storyboard>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.KnobCurrentToOnOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" Storyboard.TargetName="SwitchKnob"/>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.CurtainCurrentToOnOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" Storyboard.TargetName="SwitchCurtain"/>
+ </Storyboard>
+ </VisualTransition>
+ <VisualTransition x:Name="DraggingToOffTransition" From="Dragging" GeneratedDuration="0" To="Off">
+ <Storyboard>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.KnobCurrentToOffOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" Storyboard.TargetName="SwitchKnob"/>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.CurtainCurrentToOffOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" Storyboard.TargetName="SwitchCurtain"/>
+ </Storyboard>
+ </VisualTransition>
+ <VisualTransition x:Name="OnToOffTransition" From="On" GeneratedDuration="0" To="Off">
+ <Storyboard>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.KnobOnToOffOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" Storyboard.TargetName="SwitchKnob"/>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.CurtainOnToOffOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" Storyboard.TargetName="SwitchCurtain"/>
+ </Storyboard>
+ </VisualTransition>
+ <VisualTransition x:Name="OffToOnTransition" From="Off" GeneratedDuration="0" To="On">
+ <Storyboard>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.KnobOffToOnOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" Storyboard.TargetName="SwitchKnob"/>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.CurtainOffToOnOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" Storyboard.TargetName="SwitchCurtain"/>
+ </Storyboard>
+ </VisualTransition>
+ </VisualStateGroup.Transitions>
+ <VisualState x:Name="Dragging"/>
+ <VisualState x:Name="Off">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="-64" Storyboard.TargetProperty="X" Storyboard.TargetName="CurtainTranslateTransform"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="On">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="CurtainTranslateTransform"/>
+ <DoubleAnimation Duration="0" To="56.5" Storyboard.TargetProperty="X" Storyboard.TargetName="KnobTranslateTransform"/>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="ContentStates">
+ <VisualState x:Name="OffContent">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="OffContentPresenter"/>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="OffContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="True"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="OnContent">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="OnContentPresenter"/>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="OnContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="True"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Grid Background="Transparent">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*"/>
+ <ColumnDefinition Width="13.5"/>
+ <ColumnDefinition Width="77"/>
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="9.5"/>
+ </Grid.RowDefinitions>
+ <ContentPresenter x:Name="HeaderContentPresenter" AutomationProperties.AccessibilityView="Raw" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" Foreground="{ThemeResource ToggleSwitchHeaderForegroundThemeBrush}" Margin="{TemplateBinding Padding}" Style="{StaticResource HeaderContentPresenterStyle}"/>
+ <Grid Margin="{TemplateBinding Padding}" Grid.Row="1">
+ <ContentPresenter x:Name="OffContentPresenter" AutomationProperties.AccessibilityView="Raw" ContentTemplate="{TemplateBinding OffContentTemplate}" Content="{TemplateBinding OffContent}" FontWeight="Normal" FontSize="{ThemeResource TextStyleExtraLargeFontSize}" FontFamily="{ThemeResource PhoneFontFamilyNormal}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="False" Opacity="0" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
+ <ContentPresenter x:Name="OnContentPresenter" AutomationProperties.AccessibilityView="Raw" ContentTemplate="{TemplateBinding OnContentTemplate}" Content="{TemplateBinding OnContent}" FontWeight="Normal" FontSize="{ThemeResource TextStyleExtraLargeFontSize}" FontFamily="{ThemeResource PhoneFontFamilyNormal}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="False" Opacity="0" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
+ </Grid>
+ <Grid Grid.Column="2" ManipulationMode="None" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Bottom">
+ <Grid x:Name="SwitchKnobBounds" Height="36">
+ <Border x:Name="OuterBorder" BorderBrush="{ThemeResource ToggleSwitchOuterBorderBorderThemeBrush}" BorderThickness="2.5" Margin="3,4.5,3,4.5">
+ <Border x:Name="InnerBorder" BorderBrush="{ThemeResource ToggleSwitchTrackBorderThemeBrush}" BorderThickness="2.5">
+ <ContentPresenter x:Name="SwitchCurtainBounds">
+ <ContentPresenter x:Name="SwitchCurtainClip">
+ <Rectangle x:Name="SwitchCurtain" Fill="{ThemeResource ToggleSwitchCurtainBackgroundThemeBrush}" Width="64">
+ <Rectangle.RenderTransform>
+ <TranslateTransform x:Name="CurtainTranslateTransform" X="-64"/>
+ </Rectangle.RenderTransform>
+ </Rectangle>
+ </ContentPresenter>
+ </ContentPresenter>
+ </Border>
+ </Border>
+ <Rectangle x:Name="SwitchKnob" Fill="{ThemeResource ToggleSwitchThumbBackgroundThemeBrush}" HorizontalAlignment="Left" Stroke="{ThemeResource ToggleSwitchThumbBorderThemeBrush}" StrokeThickness="2.5" Width="20.5">
+ <Rectangle.RenderTransform>
+ <TranslateTransform x:Name="KnobTranslateTransform"/>
+ </Rectangle.RenderTransform>
+ </Rectangle>
+ </Grid>
+ <Thumb x:Name="SwitchThumb" AutomationProperties.AccessibilityView="Raw" Margin="-13.5,-15.5,-13.5,-6.5">
+ <Thumb.Template>
+ <ControlTemplate TargetType="Thumb">
+ <Rectangle Fill="Transparent"/>
+ </ControlTemplate>
+ </Thumb.Template>
+ </Thumb>
+ </Grid>
+ </Grid>
+ </Border>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="FormsListViewItem" TargetType="ListViewItem">
+ <Setter Property="HorizontalContentAlignment" Value="Stretch" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="ListViewItem">
+ <Border x:Name="OuterContainer" RenderTransformOrigin="0.5,0.5">
+ <Border.RenderTransform>
+ <ScaleTransform x:Name="ContentScaleTransform"/>
+ </Border.RenderTransform>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualStateGroup.Transitions>
+ <VisualTransition From="Pressed" To="Normal">
+ <Storyboard>
+ <PointerUpThemeAnimation Storyboard.TargetName="TiltContainer"/>
+ </Storyboard>
+ </VisualTransition>
+ </VisualStateGroup.Transitions>
+ <VisualState x:Name="Normal"/>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <PointerDownThemeAnimation Storyboard.TargetName="TiltContainer"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="{ThemeResource ListViewItemDisabledThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="contentPresenter"/>
+ <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Stroke" Storyboard.TargetName="NormalRectangle">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource CheckBoxDisabledBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Fill" Storyboard.TargetName="CheckGlyph">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource CheckBoxDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="SelectedBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Fill" Storyboard.TargetName="SelectedEarmark">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Fill" Storyboard.TargetName="SelectedGlyph">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Grid x:Name="ReorderHintContent" Background="Transparent">
+ <Border x:Name="ContentContainer">
+ <Border x:Name="TiltContainer">
+ <Border x:Name="ContentBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
+ <Border.RenderTransform>
+ <TranslateTransform x:Name="ContentBorderTranslateTransform"/>
+ </Border.RenderTransform>
+ <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
+ </Border>
+ </Border>
+ </Border>
+ </Grid>
+ </Border>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="TabbedPageStyle" TargetType="local:FormsPivot">
+ <Setter Property="HeaderTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <TextBlock Text="{Binding Title}" />
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+
+ <Setter Property="ItemTemplate" Value="{ThemeResource ContainedPageTemplate}" />
+
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="local:FormsPivot">
+ <Grid x:Name="RootElement" Background="{TemplateBinding Background}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="Orientation">
+ <VisualState x:Name="Portrait">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Margin" Storyboard.TargetName="grdToolbar">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="0,25,0,0"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+
+ </VisualState>
+ <VisualState x:Name="Landscape">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Margin" Storyboard.TargetName="grdToolbar">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="0,19,0,0"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Grid x:Name="grdToolbar" Background="{TemplateBinding ToolbarBackground}" >
+ <TextBlock Padding="10,0,0,0" Text="{TemplateBinding Title}" VerticalAlignment="Center" Style="{ThemeResource HeaderTextBlockStyle}" Foreground="{TemplateBinding ToolbarForeground}" Visibility="{TemplateBinding ToolbarVisibility}" Height="79"/>
+ </Grid>
+ <ScrollViewer x:Name="ScrollViewer" HorizontalSnapPointsAlignment="Center" HorizontalSnapPointsType="MandatorySingle" HorizontalScrollBarVisibility="Hidden" Margin="{TemplateBinding Padding}" Grid.Row="1" Template="{StaticResource ScrollViewerScrollBarlessTemplate}" VerticalSnapPointsType="None" VerticalScrollBarVisibility="Disabled" VerticalScrollMode="Disabled" VerticalContentAlignment="Stretch" ZoomMode="Disabled">
+ <PivotPanel x:Name="Panel" VerticalAlignment="Stretch">
+ <PivotHeaderPanel x:Name="Header">
+ <PivotHeaderPanel.RenderTransform>
+ <CompositeTransform x:Name="HeaderTranslateTransform" TranslateX="0"/>
+ </PivotHeaderPanel.RenderTransform>
+ </PivotHeaderPanel>
+ <ItemsPresenter x:Name="PivotItemPresenter">
+ <ItemsPresenter.RenderTransform>
+ <TranslateTransform x:Name="ItemsPresenterTranslateTransform" X="0"/>
+ </ItemsPresenter.RenderTransform>
+ </ItemsPresenter>
+ </PivotPanel>
+ </ScrollViewer>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <DataTemplate x:Key="TextCell">
+ <StackPanel Margin="5,0,0,0" Height="{Binding RenderHeight, Converter={StaticResource HeightConverter}}">
+ <TextBlock
+ Text="{Binding Text}"
+ Style="{ThemeResource ListViewItemTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding TextColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}"
+ local:ListViewRenderer.HighlightWhenSelected="true"/>
+
+ <TextBlock
+ Text="{Binding Detail}"
+ Style="{ThemeResource ListViewItemContentTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding DetailColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}"
+ local:ListViewRenderer.HighlightWhenSelected="true"/>
+ </StackPanel>
+ </DataTemplate>
+
+ <DataTemplate x:Key="ListViewHeaderTextCell">
+ <Border Margin="5,0,0,0" Background="{ThemeResource SystemColorControlAccentBrush}" Height="{Binding RenderHeight, Converter={StaticResource HeightConverter}}" MinHeight="{Binding RenderHeight, Converter={StaticResource HeightConverter}, ConverterParameter=60}" MinWidth="60" Padding="6">
+ <StackPanel VerticalAlignment="Bottom">
+ <TextBlock
+ Text="{Binding Text}"
+ Style="{ThemeResource GroupHeaderTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding TextColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}" />
+
+ <TextBlock
+ Text="{Binding Detail}"
+ Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding DetailColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}" />
+ </StackPanel>
+ </Border>
+ </DataTemplate>
+
+ <DataTemplate x:Key="ImageCell">
+ <Grid Margin="5,0,0,0" Height="{Binding RenderHeight, Converter={StaticResource HeightConverter}}">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition />
+ </Grid.ColumnDefinitions>
+
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ </Grid.RowDefinitions>
+
+ <Image Grid.Column="0" Grid.RowSpan="2"
+ DataContext="{Binding ImageSource, Converter={StaticResource ImageConverter}}"
+ Source="{Binding Value}"
+ VerticalAlignment="Center" />
+
+ <TextBlock Grid.Column="1" Grid.Row="0"
+ Text="{Binding Text}"
+ Style="{ThemeResource ListViewItemContentTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding TextColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}"
+ local:ListViewRenderer.HighlightWhenSelected="true"/>
+
+ <TextBlock Grid.Column="1" Grid.Row="1"
+ Text="{Binding Detail}"
+ Style="{ThemeResource ListViewItemContentTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding DetailColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}"
+ local:ListViewRenderer.HighlightWhenSelected="true"/>
+ </Grid>
+ </DataTemplate>
+
+ <DataTemplate x:Key="SwitchCell">
+ <Grid Margin="5,0,0,0" Height="{Binding RenderHeight, Converter={StaticResource HeightConverter}}" HorizontalAlignment="Stretch">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="Auto" />
+ </Grid.ColumnDefinitions>
+
+ <TextBlock
+ Grid.Column="0" Text="{Binding Text}" VerticalAlignment="Center"
+ local:ListViewRenderer.HighlightWhenSelected="true"/>
+
+ <ToggleSwitch Grid.Column="1" IsOn="{Binding On, Mode=TwoWay}" OnContent="" OffContent="" VerticalAlignment="Center" />
+ </Grid>
+ </DataTemplate>
+
+ <DataTemplate x:Key="EntryCell">
+ <local:EntryCellTextBox Margin="5,0,0,0" IsEnabled="{Binding IsEnabled}" Header="{Binding}" Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" PlaceholderText="{Binding Placeholder}" TextAlignment="{Binding HorizontalTextAlignment,Converter={StaticResource HorizontalTextAlignmentConverter}}" InputScope="{Binding Keyboard,Converter={StaticResource KeyboardConverter}}" HorizontalAlignment="Stretch">
+ <local:EntryCellTextBox.HeaderTemplate>
+ <DataTemplate>
+ <TextBlock
+ Text="{Binding Label}"
+ Style="{ThemeResource ListViewItemTextBlockStyle}"
+ Foreground="{Binding LabelColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}"
+ local:ListViewRenderer.HighlightWhenSelected="true"/>
+ </DataTemplate>
+ </local:EntryCellTextBox.HeaderTemplate>
+ </local:EntryCellTextBox>
+ </DataTemplate>
+
+ <ControlTemplate x:Key="MasterDetailPopup">
+ <Grid Background="{TemplateBinding Background}">
+ <Grid.Resources>
+ <Style TargetType="local:PageControl" BasedOn="{StaticResource PageControlDefaultStyle}">
+ <Setter Property="Background" Value="Transparent" />
+ </Style>
+ </Grid.Resources>
+
+ <Popup x:Name="popup" IsLightDismissEnabled="true">
+ <Popup.ChildTransitions>
+ <TransitionCollection>
+ <PopupThemeTransition />
+ </TransitionCollection>
+ </Popup.ChildTransitions>
+
+ <Border Margin="0" Padding="0" BorderThickness="0" Background="{Binding Converter={StaticResource MasterBackgroundConverter}, RelativeSource={RelativeSource Mode=TemplatedParent}}">
+ <ContentPresenter x:Name="masterPresenter" />
+ </Border>
+ </Popup>
+
+ <ContentPresenter x:Name="detailPresenter" />
+ </Grid>
+ </ControlTemplate>
+
+ <Style x:Key="PageControlDefaultStyle" TargetType="local:PageControl">
+ <Setter Property="TitleBrush" Value="{ThemeResource DefaultTextForegroundThemeBrush}" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="local:PageControl">
+ <Grid Background="{TemplateBinding Background}">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+
+ <Grid Height="79" Background="{TemplateBinding NavigationBarBackground}" Visibility="{Binding ShowNavigationBar,RelativeSource={RelativeSource Mode=TemplatedParent},Converter={StaticResource BoolVisibilityConverter}}">
+ <TextBlock Margin="10,0,0,0" Name="title" Foreground="{TemplateBinding TitleBrush}" VerticalAlignment="Center" Style="{ThemeResource HeaderTextBlockStyle}" Text="{Binding Title}" />
+ </Grid>
+ <ContentPresenter x:Name="presenter" Grid.Row="1" ContentTransitions="{TemplateBinding ContentTransitions}" />
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style TargetType="local:PageControl" BasedOn="{StaticResource PageControlDefaultStyle}" />
+
+ <DataTemplate x:Key="TabbedPage">
+ <local:TabbedPagePresenter Content="{Binding Converter={StaticResource PageToRenderer}}" />
+ </DataTemplate>
+
+ <DataTemplate x:Key="TabbedPageHeader">
+ <TextBlock Text="{Binding Title}" />
+ </DataTemplate>
+
+ <Style x:Key="JumpListGrid" TargetType="GridView">
+ <Setter Property="Background" Value="#80000000" />
+ <Setter Property="ItemTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <Border Background="{ThemeResource SystemColorControlAccentBrush}" Padding="5" Margin="3" MinHeight="80" MinWidth="80">
+ <TextBlock Text="{Binding}" Style="{ThemeResource SubheaderTextBlockStyle}" VerticalAlignment="Bottom" />
+ </Border>
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <GroupStyle x:Key="ListViewGroup" HidesIfEmpty="False">
+ <GroupStyle.HeaderTemplate>
+ <DataTemplate>
+ <local:CellControl IsGroupHeader="true" HorizontalContentAlignment="Stretch" />
+ </DataTemplate>
+ </GroupStyle.HeaderTemplate>
+ </GroupStyle>
+
+ <Style TargetType="local:FormsTextBox">
+ <Setter Property="Background" Value="{ThemeResource TextBoxBackgroundThemeBrush}" />
+ <Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}" />
+ <Setter Property="FontSize" Value="{ThemeResource ContentControlFontSize}" />
+ </Style>
+
+ <Style TargetType="local:FormsComboBox">
+ <Setter Property="Foreground" Value="{ThemeResource ComboBoxForegroundThemeBrush}"/>
+ <Setter Property="Background" Value="{ThemeResource ComboBoxBackgroundThemeBrush}"/>
+ <Setter Property="BorderBrush" Value="{ThemeResource ComboBoxBorderThemeBrush}"/>
+ <Setter Property="BorderThickness" Value="{ThemeResource ComboBoxBorderThemeThickness}"/>
+ <Setter Property="HorizontalContentAlignment" Value="Left"/>
+ <Setter Property="FontFamily" Value="{ThemeResource PhoneFontFamilyNormal}"/>
+ <Setter Property="FontSize" Value="{ThemeResource ContentControlFontSize}"/>
+ <Setter Property="Margin" Value="0"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="local:FormsComboBox">
+ <Grid x:Name="ComboBoxGrid">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualStateGroup.Transitions>
+ <VisualTransition From="Pressed" To="PointerOver">
+ <Storyboard>
+ <PointerUpThemeAnimation Storyboard.TargetName="Background"/>
+ </Storyboard>
+ </VisualTransition>
+ <VisualTransition From="PointerOver" To="Normal">
+ <Storyboard>
+ <PointerUpThemeAnimation Storyboard.TargetName="Background"/>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="PlaceholderTextBlock">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource PhoneMidBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PlaceholderTextBlock">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualTransition>
+ <VisualTransition From="Pressed" To="Normal">
+ <Storyboard>
+ <PointerUpThemeAnimation Storyboard.TargetName="Background"/>
+ </Storyboard>
+ </VisualTransition>
+ </VisualStateGroup.Transitions>
+ <VisualState x:Name="Normal">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="{ThemeResource ComboBoxFlyoutListPlaceholderTextOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PlaceholderTextBlock"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="PointerOver"/>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <PointerDownThemeAnimation Storyboard.TargetName="Background"/>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxPressedBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxPressedBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="UserControl">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxPressedForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Highlighted">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxHighlightedBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxHighlightedBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="UserControl">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxHighlightedForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="HeaderContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxDisabledBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxDisabledBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="FlyoutButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxDisabledBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="UserControl">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="PlaceholderTextBlock">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PlaceholderTextBlock"/>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="PlaceholderTextContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="DropDownStates">
+ <VisualState x:Name="Opened">
+ <Storyboard>
+ <DoubleAnimation Duration="0:0:0.25" EnableDependentAnimation="True"
+ From="{Binding TemplateSettings.DropDownClosedHeight, RelativeSource={RelativeSource Mode=TemplatedParent}}"
+ To="{Binding TemplateSettings.DropDownOpenedHeight, RelativeSource={RelativeSource Mode=TemplatedParent}}"
+ Storyboard.TargetProperty="Height" Storyboard.TargetName="ItemsPresenterHost">
+ <DoubleAnimation.EasingFunction>
+ <ExponentialEase EasingMode="EaseInOut" Exponent="6"/>
+ </DoubleAnimation.EasingFunction>
+ </DoubleAnimation>
+ <DoubleAnimation Duration="0:0:0.25" To="{Binding TemplateSettings.DropDownOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}"
+ Storyboard.TargetProperty="Y"
+ Storyboard.TargetName="ItemsPresenterTranslateTransform">
+ <DoubleAnimation.EasingFunction>
+ <ExponentialEase EasingMode="EaseInOut" Exponent="6"/>
+ </DoubleAnimation.EasingFunction>
+ </DoubleAnimation>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="UserControl">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="True"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxHighlightedBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="UserControl">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ComboBoxHighlightedForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Closed">
+ <Storyboard>
+ <!-- Dummy zero-duration animation so we can hook into the closing animation -->
+ <DoubleAnimation Duration="0:0:0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ItemsPresenterHost" />
+ <DoubleAnimation Duration="0:0:0.2" EnableDependentAnimation="True"
+ From="{Binding TemplateSettings.DropDownOpenedHeight, RelativeSource={RelativeSource Mode=TemplatedParent}}"
+ To="{Binding TemplateSettings.DropDownClosedHeight, RelativeSource={RelativeSource Mode=TemplatedParent}}"
+ Storyboard.TargetProperty="Height" Storyboard.TargetName="ItemsPresenterHost">
+ <DoubleAnimation.EasingFunction>
+ <ExponentialEase EasingMode="EaseInOut" Exponent="6"/>
+ </DoubleAnimation.EasingFunction>
+ </DoubleAnimation>
+ <DoubleAnimation Duration="0:0:0.2"
+ To="{Binding TemplateSettings.DropDownOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}"
+ Storyboard.TargetProperty="Y" Storyboard.TargetName="ItemsPresenterTranslateTransform">
+ <DoubleAnimation.EasingFunction>
+ <ExponentialEase EasingMode="EaseInOut" Exponent="6"/>
+ </DoubleAnimation.EasingFunction>
+ </DoubleAnimation>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="PresenterStates">
+ <VisualState x:Name="Full"/>
+ <VisualState x:Name="InlineNormal">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FlyoutButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ShortListOuterBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="InlinePlaceholder">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FlyoutButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ShortListOuterBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
+ </ObjectAnimationUsingKeyFrames>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PlaceholderTextContentPresenter"/>
+ <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ItemsPresenter"/>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <ContentPresenter x:Name="HeaderContentPresenter" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" FlowDirection="{TemplateBinding FlowDirection}" HorizontalAlignment="Left" Margin="0,0,0,-4.5" Style="{StaticResource HeaderContentPresenterStyle}" Visibility="Collapsed"/>
+ <Button x:Name="FlyoutButton" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" FontWeight="Normal" FlowDirection="{TemplateBinding FlowDirection}" FontSize="{ThemeResource ContentControlFontSize}" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" MinHeight="{ThemeResource ComboBoxItemMinHeightThemeSize}" Padding="6.5,0,0,0" Grid.Row="1">
+ <ContentPresenter x:Name="ContentPresenter" Margin="0,0.8,0,0" MinHeight="32.5">
+ <TextBlock x:Name="PlaceholderTextBlock" Margin="0" Style="{StaticResource ComboBoxPlaceholderTextBlockStyle}" Text="{TemplateBinding PlaceholderText}"/>
+ </ContentPresenter>
+ </Button>
+ <Border x:Name="ShortListOuterBorder" Margin="{ThemeResource PhoneTouchTargetOverhang}" Grid.Row="1" Visibility="Collapsed">
+ <Border x:Name="Background" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
+ <UserControl x:Name="UserControl" Foreground="{TemplateBinding Foreground}" FlowDirection="{TemplateBinding FlowDirection}" IsHitTestVisible="False">
+ <Canvas x:Name="ItemsPresenterHost" HorizontalAlignment="Left" MinHeight="{ThemeResource ComboBoxItemMinHeightThemeSize}">
+ <ContentPresenter x:Name="PlaceholderTextContentPresenter" Content="{TemplateBinding PlaceholderText}" Margin="{ThemeResource ComboBoxPlaceholderTextThemeMargin}" Opacity="0" Style="{StaticResource PlaceholderContentPresenterStyle}"/>
+ <ItemsPresenter x:Name="ItemsPresenter" Margin="0,0.8,0,0">
+ <ItemsPresenter.RenderTransform>
+ <TranslateTransform x:Name="ItemsPresenterTranslateTransform"/>
+ </ItemsPresenter.RenderTransform>
+ </ItemsPresenter>
+ </Canvas>
+ </UserControl>
+ </Border>
+ </Border>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+</ResourceDictionary> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Phone/Properties/AssemblyInfo.cs b/Xamarin.Forms.Platform.WinRT.Phone/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..6f33e0c7
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Phone/Properties/AssemblyInfo.cs
@@ -0,0 +1,14 @@
+using System.Reflection;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.WinRT;
+
+[assembly: AssemblyTitle("Xamarin.Forms.Platform.WinRT.Phone")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: Dependency (typeof (WindowsPhoneResourcesProvider))]
+
+[assembly: ExportRenderer (typeof (SearchBar), typeof (SearchBarRenderer))]
+
+[assembly: ExportRenderer (typeof (TabbedPage), typeof (TabbedPageRenderer))] \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Phone/SearchBarRenderer.cs b/Xamarin.Forms.Platform.WinRT.Phone/SearchBarRenderer.cs
new file mode 100644
index 00000000..33bd782f
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Phone/SearchBarRenderer.cs
@@ -0,0 +1,160 @@
+using System;
+using System.ComponentModel;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ public class SearchBarRenderer
+ : ViewRenderer<SearchBar, SearchBox>
+ {
+ protected override void OnElementChanged (ElementChangedEventArgs<SearchBar> e)
+ {
+ if (e.NewElement != null) {
+ if (Control == null) {
+ SetNativeControl (new SearchBox ());
+ Control.QuerySubmitted += OnQuerySubmitted;
+ Control.QueryChanged += OnQueryChanged;
+ Control.Loaded += (sender, args) => {
+ _queryTextBox = Control.GetFirstDescendant<FormsTextBox> ();
+ UpdateTextColor ();
+ UpdatePlaceholderColor ();
+ };
+ }
+
+ UpdateText ();
+ UpdatePlaceholder ();
+ UpdateFont ();
+ UpdateAlignment ();
+ UpdatePlaceholderColor ();
+ UpdateTextColor ();
+ }
+
+ base.OnElementChanged (e);
+ }
+
+ protected override void OnElementPropertyChanged (object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged (sender, e);
+
+ if (e.PropertyName == SearchBar.TextProperty.PropertyName)
+ UpdateText ();
+ else if (e.PropertyName == SearchBar.PlaceholderProperty.PropertyName)
+ UpdatePlaceholder ();
+ else if (e.PropertyName == SearchBar.FontAttributesProperty.PropertyName)
+ UpdateFont ();
+ else if (e.PropertyName == SearchBar.FontFamilyProperty.PropertyName)
+ UpdateFont ();
+ else if (e.PropertyName == SearchBar.FontSizeProperty.PropertyName)
+ UpdateFont ();
+ else if (e.PropertyName == SearchBar.HorizontalTextAlignmentProperty.PropertyName)
+ UpdateAlignment ();
+ else if (e.PropertyName == SearchBar.PlaceholderColorProperty.PropertyName)
+ UpdatePlaceholderColor ();
+ else if (e.PropertyName == SearchBar.TextColorProperty.PropertyName)
+ UpdateTextColor ();
+ }
+
+ bool _fontApplied;
+
+ void OnQuerySubmitted (SearchBox sender, SearchBoxQuerySubmittedEventArgs e)
+ {
+ Element.OnSearchButtonPressed ();
+ }
+
+ void UpdatePlaceholder ()
+ {
+ Control.PlaceholderText = Element.Placeholder ?? string.Empty;
+ }
+
+ void UpdateFont ()
+ {
+ if (Control == null)
+ return;
+
+ var searchBar = Element;
+
+ if (searchBar == null)
+ return;
+
+ bool searchBarIsDefault = searchBar.FontFamily == null && searchBar.FontSize == Device.GetNamedSize (NamedSize.Default, typeof (SearchBar), true) && searchBar.FontAttributes == FontAttributes.None;
+
+ if (searchBarIsDefault && !_fontApplied)
+ return;
+
+ if (searchBarIsDefault) {
+ Control.ClearValue (Windows.UI.Xaml.Controls.Control.FontStyleProperty);
+ Control.ClearValue (Windows.UI.Xaml.Controls.Control.FontSizeProperty);
+ Control.ClearValue (Windows.UI.Xaml.Controls.Control.FontFamilyProperty);
+ Control.ClearValue (Windows.UI.Xaml.Controls.Control.FontWeightProperty);
+ Control.ClearValue (Windows.UI.Xaml.Controls.Control.FontStretchProperty);
+ } else {
+ Control.ApplyFont (searchBar);
+ }
+
+ _fontApplied = true;
+ }
+
+ void OnQueryChanged (SearchBox sender, SearchBoxQueryChangedEventArgs e)
+ {
+ ((IElementController) Element).SetValueFromRenderer (SearchBar.TextProperty, e.QueryText);
+ }
+
+ void UpdateText ()
+ {
+ Control.QueryText = Element.Text ?? string.Empty;
+ }
+
+ void UpdateAlignment ()
+ {
+ Control.HorizontalTextAlignment = Element.HorizontalTextAlignment;
+ }
+
+ void UpdateTextColor ()
+ {
+ if (_queryTextBox == null) {
+ return;
+ }
+
+ var textColor = Element.TextColor;
+
+ if (textColor.IsDefault)
+ {
+ if (_defaultTextColorBrush == null) {
+ return;
+ }
+
+ _queryTextBox.Foreground = _defaultTextColorBrush;
+ }
+
+ _defaultTextColorBrush = _defaultTextColorBrush ?? _queryTextBox.Foreground;
+
+ _queryTextBox.Foreground = textColor.ToBrush();
+ }
+
+ void UpdatePlaceholderColor ()
+ {
+ if (_queryTextBox == null) {
+ return;
+ }
+
+ var placeholderColor = Element.PlaceholderColor;
+
+ if (placeholderColor.IsDefault) {
+ if (_defaultPlaceholderColorBrush == null) {
+ return;
+ }
+
+ _queryTextBox.PlaceholderForegroundBrush = _defaultPlaceholderColorBrush;
+ }
+
+ _defaultPlaceholderColorBrush = _defaultPlaceholderColorBrush ?? _queryTextBox.PlaceholderForegroundBrush;
+
+ _queryTextBox.PlaceholderForegroundBrush = placeholderColor.ToBrush ();
+ }
+
+ FormsTextBox _queryTextBox;
+ Brush _defaultTextColorBrush;
+ Brush _defaultPlaceholderColorBrush;
+ }
+}
diff --git a/Xamarin.Forms.Platform.WinRT.Phone/SearchBox.xaml b/Xamarin.Forms.Platform.WinRT.Phone/SearchBox.xaml
new file mode 100644
index 00000000..3b609fe8
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Phone/SearchBox.xaml
@@ -0,0 +1,248 @@
+<Control
+ x:Class="Xamarin.Forms.Platform.WinRT.SearchBox"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:winRt="using:Xamarin.Forms.Platform.WinRT"
+ mc:Ignorable="d"
+ d:DesignHeight="300"
+ d:DesignWidth="400">
+
+ <Control.Resources>
+ <ResourceDictionary>
+ <ResourceDictionary.ThemeDictionaries>
+ <ResourceDictionary x:Key="Default">
+ <SolidColorBrush x:Key="SearchBoxBackgroundThemeBrush" Color="#CCFFFFFF" />
+ <SolidColorBrush x:Key="SearchBoxBorderThemeBrush" Color="#FF2A2A2A" />
+ <SolidColorBrush x:Key="SearchBoxDisabledBackgroundThemeBrush" Color="Transparent" />
+ <SolidColorBrush x:Key="SearchBoxDisabledTextThemeBrush" Color="#66FFFFFF" />
+ <SolidColorBrush x:Key="SearchBoxDisabledBorderThemeBrush" Color="#FF666666" />
+ <SolidColorBrush x:Key="SearchBoxPointerOverBackgroundThemeBrush" Color="#DDFFFFFF" />
+ <SolidColorBrush x:Key="SearchBoxPointerOverTextThemeBrush" Color="#99000000" />
+ <SolidColorBrush x:Key="SearchBoxPointerOverBorderThemeBrush" Color="#FFDDDDDD" />
+ <SolidColorBrush x:Key="SearchBoxFocusedBackgroundThemeBrush" Color="#FFFFFFFF" />
+ <SolidColorBrush x:Key="SearchBoxFocusedTextThemeBrush" Color="#FF000000" />
+ <SolidColorBrush x:Key="SearchBoxFocusedBorderThemeBrush" Color="#FF2A2A2A" />
+ <SolidColorBrush x:Key="SearchBoxButtonBackgroundThemeBrush" Color="#FF4617B4" />
+ <SolidColorBrush x:Key="SearchBoxButtonForegroundThemeBrush" Color="White" />
+ <SolidColorBrush x:Key="SearchBoxButtonPointerOverForegroundThemeBrush" Color="White" />
+ <SolidColorBrush x:Key="SearchBoxButtonPointerOverBackgroundThemeBrush" Color="#FF5F37BE" />
+ <SolidColorBrush x:Key="SearchBoxSeparatorSuggestionForegroundThemeBrush" Color="Black" />
+ <SolidColorBrush x:Key="SearchBoxHitHighlightForegroundThemeBrush" Color="#FF4617B4" />
+ <SolidColorBrush x:Key="SearchBoxHitHighlightSelectedForegroundThemeBrush" Color="#FFA38BDA" />
+ <SolidColorBrush x:Key="SearchBoxForegroundThemeBrush" Color="Black" />
+ </ResourceDictionary>
+ </ResourceDictionary.ThemeDictionaries>
+
+ <x:Double x:Key="SearchBoxTextBoxThemeMinHeight">28</x:Double>
+ <x:Double x:Key="SearchBoxContentThemeFontSize">15</x:Double>
+ <Thickness x:Key="SearchBoxThemePadding">8,4,8,4</Thickness>
+ <Thickness x:Key="SearchBoxBorderThemeThickness">2</Thickness>
+ <FontWeight x:Key="SearchBoxButtonThemeFontWeight">Normal</FontWeight>
+ <FontWeight x:Key="SearchBoxContentThemeFontWeight">Normal</FontWeight>
+ <winRt:TextAlignmentToHorizontalAlignmentConverter x:Key="AlignmentConverter" />
+ </ResourceDictionary>
+ </Control.Resources>
+
+ <Control.Style>
+ <Style TargetType="Control">
+ <Setter Property="Background" Value="{ThemeResource SearchBoxBackgroundThemeBrush}"/>
+ <Setter Property="BorderBrush" Value="{ThemeResource SearchBoxBorderThemeBrush}"/>
+ <Setter Property="BorderThickness" Value="{ThemeResource SearchBoxBorderThemeThickness}"/>
+ <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
+ <Setter Property="FontSize" Value="{ThemeResource SearchBoxContentThemeFontSize}"/>
+ <Setter Property="FontWeight" Value="{ThemeResource SearchBoxContentThemeFontWeight}"/>
+ <Setter Property="Foreground" Value="{ThemeResource SearchBoxForegroundThemeBrush}"/>
+ <Setter Property="Padding" Value="{ThemeResource SearchBoxThemePadding}"/>
+ <Setter Property="IsTabStop" Value="False"/>
+ <Setter Property="Typography.StylisticSet20" Value="True"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Grid x:Name="SearchBoxGrid">
+ <Grid.Resources>
+ <Style x:Key="SearchButtonStyle" TargetType="Button">
+ <Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}"/>
+ <Setter Property="IsTabStop" Value="False"/>
+ <Setter Property="VerticalAlignment" Value="Stretch"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="Button">
+ <Grid Background="Transparent">
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal"/>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="SearchGlyph">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonPointerOverForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchButtonBackground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonPointerOverBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="SearchGlyph">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedTextThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchButtonBackground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled"/>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="FocusStates">
+ <VisualState x:Name="Focused"/>
+ <VisualState x:Name="Unfocused"/>
+ <VisualState x:Name="PointerFocused"/>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Grid x:Name="SearchButtonBackground" Background="{TemplateBinding Background}">
+ <SymbolIcon x:Name="SearchGlyph" Symbol="Find" AutomationProperties.AccessibilityView="Raw" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
+ </Grid>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ <Style x:Key="SearchTextBoxStyle" TargetType="winRt:FormsTextBox">
+ <Setter Property="Margin" Value="0" />
+ <Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}"/>
+ <Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}"/>
+ <Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}"/>
+ <Setter Property="Background" Value="{ThemeResource TextBoxBackgroundThemeBrush}"/>
+ <Setter Property="BorderBrush" Value="{ThemeResource TextBoxBorderThemeBrush}"/>
+ <Setter Property="PlaceholderForegroundBrush" Value="{ThemeResource TextBoxPlaceholderTextThemeBrush}"/>
+ <Setter Property="SelectionHighlightColor" Value="{ThemeResource TextSelectionHighlightColorThemeBrush}"/>
+ <Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}"/>
+ <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
+ <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
+ <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden"/>
+ <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden"/>
+ <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False"/>
+ <Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="winRt:FormsTextBox">
+ <Grid>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BackgroundElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="BorderElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="PlaceholderTextContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Normal">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="{ThemeResource TextControlBackgroundThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundElement"/>
+ <DoubleAnimation Duration="0" To="{ThemeResource TextControlBorderThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BorderElement"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="{ThemeResource TextControlPointerOverBackgroundThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundElement"/>
+ <DoubleAnimation Duration="0" To="{ThemeResource TextControlPointerOverBorderThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BorderElement"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Focused"/>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="ButtonStates"/>
+ </VisualStateManager.VisualStateGroups>
+
+ <Border x:Name="BackgroundElement" Background="{TemplateBinding Background}" Margin="{TemplateBinding BorderThickness}" />
+ <Border x:Name="BorderElement" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" />
+ <ScrollViewer x:Name="ContentElement" AutomationProperties.AccessibilityView="Raw" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" IsTabStop="False" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" ZoomMode="Disabled"/>
+ <ContentControl x:Name="PlaceholderTextContentPresenter" Content="{TemplateBinding PlaceholderText}" Foreground="{TemplateBinding PlaceholderForegroundBrush}" IsHitTestVisible="False" IsTabStop="False" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"
+ HorizontalAlignment="{Binding TextAlignment,
+ RelativeSource={RelativeSource Mode=TemplatedParent},
+ Converter={StaticResource AlignmentConverter}}" />
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ </Grid.Resources>
+
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchBoxGrid">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding Background, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="SearchBoxBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding BorderBrush, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="SearchButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding Foreground, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchBoxGrid">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="SearchBoxBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="SearchButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledTextThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchTextBox">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Focused">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchBoxGrid">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="SearchBoxBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="SearchButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+
+ <Border x:Name="SearchBoxBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="Transparent">
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition/>
+ <ColumnDefinition Width="Auto"/>
+ </Grid.ColumnDefinitions>
+
+ <winRt:FormsTextBox x:Name="SearchTextBox" BorderThickness="0" Background="Transparent" Text="{Binding Path=QueryText, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" FontStyle="{TemplateBinding FontStyle}" InputScope="Search" MinHeight="{ThemeResource SearchBoxTextBoxThemeMinHeight}" MaxLength="2048" Padding="{TemplateBinding Padding}" Style="{StaticResource SearchTextBoxStyle}" TextWrapping="NoWrap" VerticalAlignment="Stretch"/>
+ <Button x:Name="SearchButton" AutomationProperties.AccessibilityView="Raw" Background="Transparent" Grid.Column="1" FontWeight="{ThemeResource SearchBoxButtonThemeFontWeight}" Style="{StaticResource SearchButtonStyle}"/>
+ </Grid>
+ </Border>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ </Control.Style>
+</Control> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Phone/SearchBox.xaml.cs b/Xamarin.Forms.Platform.WinRT.Phone/SearchBox.xaml.cs
new file mode 100644
index 00000000..4cc8ac1c
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Phone/SearchBox.xaml.cs
@@ -0,0 +1,157 @@
+using System;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ public class SearchBoxQuerySubmittedEventArgs
+ : EventArgs
+ {
+ }
+
+ public class SearchBoxQueryChangedEventArgs
+ : EventArgs
+ {
+ public SearchBoxQueryChangedEventArgs (string query)
+ {
+ QueryText = query;
+ }
+
+ public string QueryText
+ {
+ get;
+ private set;
+ }
+ }
+
+ public delegate void QueryChangedEventHandler (SearchBox search, SearchBoxQueryChangedEventArgs args);
+ public delegate void QuerySubmittedEventHandler (SearchBox search, SearchBoxQuerySubmittedEventArgs args);
+
+ public sealed partial class SearchBox
+ {
+ public SearchBox ()
+ {
+ InitializeComponent ();
+
+ IsEnabledChanged += OnIsEnabledChanged;
+ }
+
+ public event QuerySubmittedEventHandler QuerySubmitted;
+ public event QueryChangedEventHandler QueryChanged;
+
+ public static readonly DependencyProperty QueryTextProperty = DependencyProperty.Register (
+ "QueryText", typeof(string), typeof(SearchBox), new PropertyMetadata (null, OnQueryTextChanged));
+
+ public string QueryText
+ {
+ get { return (string)GetValue (QueryTextProperty); }
+ set { SetValue (QueryTextProperty, value); }
+ }
+
+ public static readonly DependencyProperty PlaceholderTextProperty = DependencyProperty.Register (
+ "PlaceholderText", typeof(string), typeof(SearchBox), new PropertyMetadata (null, OnPlaceholderChanged));
+
+ public string PlaceholderText
+ {
+ get { return (string)GetValue (PlaceholderTextProperty); }
+ set { SetValue (PlaceholderTextProperty, value); }
+ }
+
+ public static readonly DependencyProperty HorizontalTextAlignmentProperty = DependencyProperty.Register (
+ "HorizontalTextAlignment", typeof(string), typeof(SearchBox), new PropertyMetadata (null, OnAlignmentChanged));
+
+ public TextAlignment HorizontalTextAlignment
+ {
+ get { return (TextAlignment)GetValue (HorizontalTextAlignmentProperty); }
+ set { SetValue (HorizontalTextAlignmentProperty, value); }
+ }
+
+ protected override void OnApplyTemplate ()
+ {
+ base.OnApplyTemplate ();
+
+ GoToNormal ();
+
+ _searchTextBox = (TextBox)GetTemplateChild ("SearchTextBox");
+
+ ((Windows.UI.Xaml.Controls.Button) GetTemplateChild ("SearchButton")).Click += OnSearchButtonClicked;
+
+ UpdatePlaceholder ();
+ UpdateAlignment ();
+ }
+
+ protected override void OnGotFocus (RoutedEventArgs e)
+ {
+ base.OnGotFocus (e);
+
+ VisualStateManager.GoToState (this, "Focused", true);
+ }
+
+ protected override void OnLostFocus (RoutedEventArgs e)
+ {
+ base.OnLostFocus (e);
+
+ GoToNormal ();
+ }
+
+ void OnSearchButtonClicked (object sender, RoutedEventArgs e)
+ {
+ var querySubmitted = QuerySubmitted;
+ if (querySubmitted != null)
+ querySubmitted (this, new SearchBoxQuerySubmittedEventArgs());
+ }
+
+ TextBox _searchTextBox;
+
+ void GoToNormal ()
+ {
+ VisualStateManager.GoToState (this, (IsEnabled) ? "Normal" : "Disabled", false);
+ }
+
+ void UpdatePlaceholder ()
+ {
+ if (_searchTextBox == null)
+ return;
+
+ _searchTextBox.PlaceholderText = PlaceholderText;
+ }
+
+ void OnIsEnabledChanged (object sender, DependencyPropertyChangedEventArgs e)
+ {
+ string state = "Normal";
+ if (!(bool) e.NewValue)
+ state = "Disabled";
+ else if (FocusState != FocusState.Unfocused)
+ state = "Focused";
+
+ VisualStateManager.GoToState (this, state, true);
+ }
+
+ static void OnQueryTextChanged (DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var search = (SearchBox) d;
+ var changed = search.QueryChanged;
+ if (changed != null)
+ changed (search, new SearchBoxQueryChangedEventArgs ((string) e.NewValue));
+ }
+
+ static void OnPlaceholderChanged (DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ ((SearchBox) d).UpdatePlaceholder ();
+ }
+
+ static void OnAlignmentChanged (DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ ((SearchBox) d).UpdateAlignment ();
+ }
+
+ void UpdateAlignment ()
+ {
+ if (_searchTextBox == null) {
+ return;
+ }
+
+ _searchTextBox.TextAlignment = HorizontalTextAlignment.ToNativeTextAlignment();
+ }
+ }
+}
diff --git a/Xamarin.Forms.Platform.WinRT.Phone/TabbedPageRenderer.cs b/Xamarin.Forms.Platform.WinRT.Phone/TabbedPageRenderer.cs
new file mode 100644
index 00000000..9de3a623
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Phone/TabbedPageRenderer.cs
@@ -0,0 +1,284 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Automation;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ internal class TabbedPagePresenter : Windows.UI.Xaml.Controls.ContentPresenter
+ {
+ public TabbedPagePresenter ()
+ {
+ SizeChanged += (s, e) => {
+ if (ActualWidth > 0 && ActualHeight > 0) {
+ var tab = ((Page) DataContext);
+ ((TabbedPage) tab.RealParent).ContainerArea = new Rectangle (0, 0, ActualWidth, ActualHeight);
+ }
+ };
+ }
+ }
+
+ public class TabbedPageRenderer
+ : IVisualElementRenderer, ITitleProvider
+ {
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public FrameworkElement ContainerElement
+ {
+ get { return Control; }
+ }
+
+ VisualElement IVisualElementRenderer.Element
+ {
+ get { return Element; }
+ }
+
+ public Pivot Control
+ {
+ get;
+ private set;
+ }
+
+ public TabbedPage Element
+ {
+ get;
+ private set;
+ }
+
+ public void SetElement (VisualElement element)
+ {
+ if (element != null && !(element is TabbedPage))
+ throw new ArgumentException ("Element must be a TabbedPage", "element");
+
+ TabbedPage oldElement = Element;
+ Element = (TabbedPage) element;
+
+ if (oldElement != null) {
+ oldElement.PropertyChanged -= OnElementPropertyChanged;
+ ((INotifyCollectionChanged) oldElement.Children).CollectionChanged -= OnPagesChanged;
+ }
+
+ if (element != null) {
+ if (Control == null) {
+ Control = new FormsPivot {
+ Style = (Windows.UI.Xaml.Style) Windows.UI.Xaml.Application.Current.Resources["TabbedPageStyle"]
+ };
+ Control.HeaderTemplate = (Windows.UI.Xaml.DataTemplate)Windows.UI.Xaml.Application.Current.Resources["TabbedPageHeader"];
+ Control.ItemTemplate = (Windows.UI.Xaml.DataTemplate)Windows.UI.Xaml.Application.Current.Resources["TabbedPage"];
+
+ Control.SelectionChanged += OnSelectionChanged;
+
+ Tracker = new BackgroundTracker<Pivot> (Windows.UI.Xaml.Controls.Control.BackgroundProperty) {
+ Element = (Page) element,
+ Control = Control,
+ Container = Control
+ };
+
+ Control.Loaded += OnLoaded;
+ Control.Unloaded += OnUnloaded;
+ }
+
+ Control.DataContext = Element;
+ OnPagesChanged (Element.Children, new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Reset));
+ UpdateCurrentPage ();
+
+ ((INotifyCollectionChanged) Element.Children).CollectionChanged += OnPagesChanged;
+ element.PropertyChanged += OnElementPropertyChanged;
+
+ if (!string.IsNullOrEmpty (element.AutomationId))
+ Control.SetValue (AutomationProperties.AutomationIdProperty, element.AutomationId);
+ }
+
+ OnElementChanged (new VisualElementChangedEventArgs (oldElement, element));
+ }
+
+ public SizeRequest GetDesiredSize (double widthConstraint, double heightConstraint)
+ {
+ var constraint = new Windows.Foundation.Size (widthConstraint, heightConstraint);
+
+ var oldWidth = Control.Width;
+ var oldHeight = Control.Height;
+
+ Control.Height = double.NaN;
+ Control.Width = double.NaN;
+
+ Control.Measure (constraint);
+ var result = new Size (Math.Ceiling (Control.DesiredSize.Width), Math.Ceiling (Control.DesiredSize.Height));
+
+ Control.Width = oldWidth;
+ Control.Height = oldHeight;
+
+ return new SizeRequest (result);
+ }
+
+ public void Dispose ()
+ {
+ Dispose (true);
+ }
+
+ protected virtual void Dispose (bool disposing)
+ {
+ if (!disposing || _disposed)
+ return;
+
+ _disposed = true;
+ SetElement (null);
+ Tracker = null;
+ }
+
+ protected VisualElementTracker<Page, Pivot> Tracker
+ {
+ get
+ {
+ return _tracker;
+ }
+ set
+ {
+ if (_tracker == value)
+ return;
+
+ if (_tracker != null) {
+ _tracker.Dispose ();
+ /*this.tracker.Updated -= OnTrackerUpdated;*/
+ }
+
+ _tracker = value;
+
+ /*if (this.tracker != null)
+ this.tracker.Updated += OnTrackerUpdated;*/
+ }
+ }
+
+ bool ITitleProvider.ShowTitle
+ {
+ get
+ {
+ return _showTitle;
+ }
+
+ set
+ {
+ if (_showTitle == value)
+ return;
+ _showTitle = value;
+
+ (Control as FormsPivot).ToolbarVisibility = _showTitle ? Visibility.Visible : Visibility.Collapsed;
+ }
+ }
+
+ string ITitleProvider.Title
+ {
+ get
+ {
+ return (string)Control?.Title;
+ }
+
+ set
+ {
+ if (Control != null)
+ Control.Title = value;
+ }
+ }
+
+ Brush ITitleProvider.BarBackgroundBrush
+ {
+ set
+ {
+ (Control as FormsPivot).ToolbarBackground = value;
+ }
+ }
+
+ Brush ITitleProvider.BarForegroundBrush
+ {
+ set
+ {
+ (Control as FormsPivot).ToolbarForeground = value;
+ }
+ }
+
+ protected virtual void OnElementChanged (VisualElementChangedEventArgs e)
+ {
+ var changed = ElementChanged;
+ if (changed != null)
+ changed (this, e);
+ }
+
+ bool _disposed;
+ VisualElementTracker<Page, Pivot> _tracker;
+ bool _showTitle;
+
+ void OnPagesChanged (object sender, NotifyCollectionChangedEventArgs e)
+ {
+ e.Apply (Element.Children, Control.Items);
+
+ // Potential performance issue, UpdateLayout () is called for every page change
+ Control.UpdateLayout ();
+ }
+
+ void OnSelectionChanged (object sender, SelectionChangedEventArgs e)
+ {
+ if (Element == null)
+ return;
+
+ Page page = (e.AddedItems.Count > 0) ? (Page) e.AddedItems[0] : null;
+ Element.CurrentPage = page;
+ }
+
+ void OnElementPropertyChanged (object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "CurrentPage")
+ UpdateCurrentPage ();
+ }
+
+ void UpdateCurrentPage ()
+ {
+ Page page = Element.CurrentPage;
+ UpdateTitle (page);
+
+ if (page == null)
+ return;
+ Control.SelectedItem = page;
+ }
+
+ void OnLoaded (object sender, RoutedEventArgs args)
+ {
+ if (Element == null)
+ return;
+
+ Element.SendAppearing ();
+ }
+
+ void OnUnloaded (object sender, RoutedEventArgs args)
+ {
+ if (Element == null)
+ return;
+
+ Element.SendDisappearing ();
+ }
+
+ void OnTrackerUpdated (object sender, EventArgs e)
+ {
+
+ }
+
+ void UpdateTitle (Page child)
+ {
+ Control.ClearValue (Pivot.TitleProperty);
+
+ if (child == null)
+ return;
+ var renderer = Platform.GetRenderer (child);
+ var navigationRenderer = renderer as NavigationPageRenderer;
+ if (navigationRenderer != null) {
+ Control.Title = navigationRenderer.Title;
+ } else {
+ ((ITitleProvider) this).ShowTitle = false;
+ }
+
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhonePage.cs b/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhonePage.cs
new file mode 100644
index 00000000..51dfacc5
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhonePage.cs
@@ -0,0 +1,15 @@
+using System;
+using System.ComponentModel;
+using Windows.ApplicationModel;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ public abstract class WindowsPhonePage
+ : WindowsBasePage
+ {
+ protected override Platform CreatePlatform ()
+ {
+ return new WindowsPhonePlatform (this);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhonePlatform.cs b/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhonePlatform.cs
new file mode 100644
index 00000000..7564e673
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhonePlatform.cs
@@ -0,0 +1,41 @@
+using System.Threading.Tasks;
+using Windows.UI.ViewManagement;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ internal sealed class WindowsPhonePlatform
+ : Platform
+ {
+ public WindowsPhonePlatform (Windows.UI.Xaml.Controls.Page page)
+ : base (page)
+ {
+ _status = StatusBar.GetForCurrentView ();
+ _status.Showing += OnStatusBarShowing;
+ _status.Hiding += OnStatusBarHiding;
+ }
+
+ internal override Rectangle WindowBounds
+ {
+ get
+ {
+ bool landscape = Device.Info.CurrentOrientation.IsLandscape ();
+ double offset = (landscape) ? _status.OccludedRect.Width : _status.OccludedRect.Height;
+
+ Rectangle original = base.WindowBounds;
+ return new Rectangle (original.X, original.Y, original.Width - ((landscape) ? offset : 0), original.Height - ((landscape) ? 0 : offset));
+ }
+ }
+
+ readonly StatusBar _status;
+
+ void OnStatusBarHiding (StatusBar sender, object args)
+ {
+ UpdatePageSizes ();
+ }
+
+ void OnStatusBarShowing (StatusBar sender, object args)
+ {
+ UpdatePageSizes ();
+ }
+ }
+}
diff --git a/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhonePlatformServices.cs b/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhonePlatformServices.cs
new file mode 100644
index 00000000..37d2d4fb
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhonePlatformServices.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using Windows.ApplicationModel;
+using Windows.Storage;
+using Windows.UI.Core;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ internal class WindowsPhonePlatformServices
+ : WindowsBasePlatformServices
+ {
+ public WindowsPhonePlatformServices (CoreDispatcher dispatcher)
+ : base (dispatcher)
+ {
+ }
+
+ public override Assembly[] GetAssemblies()
+ {
+ var files = Package.Current.InstalledLocation.GetFilesAsync().AsTask().Result;
+
+ List<Assembly> assemblies = new List<Assembly> (files.Count);
+ for (int i = 0; i < files.Count; i++) {
+ StorageFile file = files[i];
+ if (file.Name.Length < 3)
+ continue;
+
+ string extension = file.Name.Substring (file.Name.Length - 3, 3).ToLower();
+ if (extension != "dll" && extension != "exe")
+ continue;
+
+ try {
+ Assembly assembly = Assembly.Load (new AssemblyName { Name = Path.GetFileNameWithoutExtension (file.Name) });
+ assemblies.Add (assembly);
+ } catch (IOException) {
+ } catch (BadImageFormatException) {
+ }
+ }
+
+ return assemblies.ToArray();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhoneResourcesProvider.cs b/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhoneResourcesProvider.cs
new file mode 100644
index 00000000..a4ae4e94
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Phone/WindowsPhoneResourcesProvider.cs
@@ -0,0 +1,72 @@
+using System;
+using Windows.UI.Text;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ internal sealed class WindowsPhoneResourcesProvider
+ : ISystemResourcesProvider
+ {
+ public IResourceDictionary GetSystemResources()
+ {
+ var windowsResources = Windows.UI.Xaml.Application.Current.Resources;
+
+ var resources = new ResourceDictionary ();
+ resources[Device.Styles.TitleStyleKey] = GetStyle ("HeaderTextBlockStyle");
+ resources[Device.Styles.SubtitleStyleKey] = GetStyle ("SubheaderTextBlockStyle");
+ resources[Device.Styles.BodyStyleKey] = GetStyle ("BodyTextBlockStyle");
+ resources[Device.Styles.CaptionStyleKey] = GetStyle ("BodyTextBlockStyle");
+ resources[Device.Styles.ListItemTextStyleKey] = GetStyle ("ListViewItemTextBlockStyle");
+ resources[Device.Styles.ListItemDetailTextStyleKey] = GetStyle ("ListViewItemContentTextBlockStyle");
+ return resources;
+ }
+
+ Style GetStyle (object nativeKey)
+ {
+ var style = (Windows.UI.Xaml.Style) Windows.UI.Xaml.Application.Current.Resources[nativeKey];
+
+ var formsStyle = new Style (typeof (Label));
+ foreach (var b in style.Setters) {
+ var setter = b as Windows.UI.Xaml.Setter;
+ if (setter == null)
+ continue;
+
+ // TODO: Need to implement a stealth pass-through for things we don't support
+
+ if (setter.Property == TextBlock.FontSizeProperty)
+ formsStyle.Setters.Add (Label.FontSizeProperty, setter.Value);
+ else if (setter.Property == TextBlock.FontFamilyProperty)
+ formsStyle.Setters.Add (Label.FontFamilyProperty, setter.Value);
+ else if (setter.Property == TextBlock.FontWeightProperty)
+ formsStyle.Setters.Add (Label.FontAttributesProperty, ToAttributes (Convert.ToUInt16 (setter.Value)));
+ else if (setter.Property == TextBlock.TextWrappingProperty)
+ formsStyle.Setters.Add (Label.LineBreakModeProperty, ToLineBreakMode ((TextWrapping) setter.Value));
+ }
+
+ return formsStyle;
+ }
+
+ static LineBreakMode ToLineBreakMode (TextWrapping value)
+ {
+ switch (value) {
+ case TextWrapping.Wrap:
+ return LineBreakMode.CharacterWrap;
+ case TextWrapping.WrapWholeWords:
+ return LineBreakMode.WordWrap;
+ default:
+ case TextWrapping.NoWrap:
+ return LineBreakMode.NoWrap;
+ }
+ }
+
+ static FontAttributes ToAttributes (ushort uweight)
+ {
+ if (uweight == FontWeights.Bold.Weight || uweight == FontWeights.SemiBold.Weight || uweight == FontWeights.ExtraBold.Weight) {
+ return FontAttributes.Bold;
+ }
+
+ return FontAttributes.None;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Phone/Xamarin.Forms.Platform.WinRT.Phone.csproj b/Xamarin.Forms.Platform.WinRT.Phone/Xamarin.Forms.Platform.WinRT.Phone.csproj
new file mode 100644
index 00000000..3bd9cce7
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Phone/Xamarin.Forms.Platform.WinRT.Phone.csproj
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{3361D52C-2E74-433E-8285-9C9A5C485977}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Platform.WinRT</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Platform.WinRT.Phone</AssemblyName>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <TargetPlatformVersion>8.1</TargetPlatformVersion>
+ <MinimumVisualStudioVersion>12</MinimumVisualStudioVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{76F1466A-8B6D-4E39-A767-685A06062A39};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\ARM\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+ <OutputPath>bin\ARM\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.WinRT\Xamarin.Forms.Platform.WinRT.csproj">
+ <Project>{f3fdd7ac-8899-4e41-bfd7-ec83403e736d}</Project>
+ <Name>Xamarin.Forms.Platform.WinRT</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="Forms.cs" />
+ <Compile Include="FormsPivot.cs" />
+ <Compile Include="SearchBarRenderer.cs" />
+ <Compile Include="TabbedPageRenderer.cs" />
+ <Compile Include="WindowsPhonePlatform.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="SearchBox.xaml.cs">
+ <DependentUpon>SearchBox.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="WindowsPhonePage.cs" />
+ <Compile Include="WindowsPhonePlatformServices.cs" />
+ <Compile Include="WindowsPhoneResourcesProvider.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Page Include="..\Xamarin.Forms.Platform.WinRT\Resources.xaml">
+ <Link>Resources.xaml</Link>
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="FormsTextBoxStyle.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Page>
+ <Page Include="PhoneResources.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Page>
+ <Page Include="SearchBox.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ </ItemGroup>
+ <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '12.0' ">
+ <VisualStudioVersion>12.0</VisualStudioVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(TargetPlatformIdentifier)' == '' ">
+ <TargetPlatformIdentifier>WindowsPhoneApp</TargetPlatformIdentifier>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/Forms.cs b/Xamarin.Forms.Platform.WinRT.Tablet/Forms.cs
new file mode 100644
index 00000000..cc5ef334
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Tablet/Forms.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using Windows.ApplicationModel.Activation;
+using Windows.Foundation.Metadata;
+using Windows.UI.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Media;
+#if WINDOWS_UWP
+using Xamarin.Forms.Platform.UWP;
+
+#else
+using Xamarin.Forms.Platform.WinRT;
+
+#endif
+
+namespace Xamarin.Forms
+{
+ public static class Forms
+ {
+ const string LogFormat = "[{0}] {1}";
+
+ static ApplicationExecutionState s_state;
+ static bool s_isInitialized;
+#if WINDOWS_UWP
+ public static void Init(IActivatedEventArgs launchActivatedEventArgs, IEnumerable<Assembly> rendererAssemblies = null)
+#else
+ public static void Init(IActivatedEventArgs launchActivatedEventArgs)
+#endif
+ {
+ if (s_isInitialized)
+ return;
+
+ var accent = (SolidColorBrush)Windows.UI.Xaml.Application.Current.Resources["SystemColorControlAccentBrush"];
+ Color.Accent = Color.FromRgba(accent.Color.R, accent.Color.G, accent.Color.B, accent.Color.A);
+
+ Log.Listeners.Add(new DelegateLogListener((c, m) => Debug.WriteLine(LogFormat, c, m)));
+
+ Windows.UI.Xaml.Application.Current.Resources.MergedDictionaries.Add(GetTabletResources());
+
+ Device.OS = TargetPlatform.Windows;
+ Device.Idiom = TargetIdiom.Tablet;
+ Device.PlatformServices = new WindowsPlatformServices(Window.Current.Dispatcher);
+ Device.Info = new WindowsDeviceInfo();
+
+#if WINDOWS_UWP
+ switch (DetectPlatform())
+ {
+ case Windows.Foundation.Metadata.Platform.Windows:
+ Device.Idiom = TargetIdiom.Desktop;
+ break;
+ case Windows.Foundation.Metadata.Platform.WindowsPhone:
+ Device.Idiom = TargetIdiom.Phone;
+ break;
+ default:
+ Device.Idiom = TargetIdiom.Tablet;
+ break;
+ }
+#endif
+ Ticker.Default = new WindowsTicker();
+
+ ExpressionSearch.Default = new WindowsExpressionSearch();
+
+#if WINDOWS_UWP
+ Registrar.ExtraAssemblies = rendererAssemblies?.ToArray();
+#endif
+
+ Registrar.RegisterAll(new[] { typeof(ExportRendererAttribute), typeof(ExportCellAttribute), typeof(ExportImageSourceHandlerAttribute) });
+
+ s_isInitialized = true;
+ s_state = launchActivatedEventArgs.PreviousExecutionState;
+
+#if WINDOWS_UWP
+ SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;
+#endif
+ }
+
+ static Windows.Foundation.Metadata.Platform DetectPlatform()
+ {
+#if WINDOWS_UWP
+ bool isHardwareButtonsAPIPresent = ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons");
+
+ if (isHardwareButtonsAPIPresent)
+ return Windows.Foundation.Metadata.Platform.WindowsPhone;
+#endif
+ return Windows.Foundation.Metadata.Platform.Windows;
+ }
+
+ static Windows.UI.Xaml.ResourceDictionary GetTabletResources()
+ {
+ return new Windows.UI.Xaml.ResourceDictionary {
+#if !WINDOWS_UWP
+ Source = new Uri("ms-appx:///Xamarin.Forms.Platform.WinRT.Tablet/TabletResources.xbf")
+#else
+ Source = new Uri("ms-appx:///Xamarin.Forms.Platform.UAP/Resources.xbf")
+#endif
+ };
+ }
+
+#if WINDOWS_UWP
+ static void OnBackRequested(object sender, BackRequestedEventArgs e)
+ {
+ Application app = Application.Current;
+ if (app == null)
+ return;
+
+ Page page = app.MainPage;
+ if (page == null)
+ return;
+
+ var platform = page.Platform as Platform.UWP.Platform;
+ if (platform == null)
+ return;
+
+ e.Handled = platform.BackButtonPressed();
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/FormsListViewItemPresenter.cs b/Xamarin.Forms.Platform.WinRT.Tablet/FormsListViewItemPresenter.cs
new file mode 100644
index 00000000..1e308867
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Tablet/FormsListViewItemPresenter.cs
@@ -0,0 +1,36 @@
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ // This exists to work around the fact that when you set these bindings in XAML and compile on Win10
+ // the resulting xbf file does not load correctly on Win8.1. MS has acknowledged the issue but has no fixed it.
+ // This hacks around the problem.
+ public class FormsListViewItemPresenter : ListViewItemPresenter
+ {
+ public FormsListViewItemPresenter()
+ {
+ var verticalContentAlignBinding = new Windows.UI.Xaml.Data.Binding
+ {
+ Path = new PropertyPath("VerticalContentAlignment"),
+ RelativeSource = new RelativeSource { Mode = RelativeSourceMode.TemplatedParent }
+ };
+ BindingOperations.SetBinding(this, VerticalContentAlignmentProperty, verticalContentAlignBinding);
+
+ var paddingBinding = new Windows.UI.Xaml.Data.Binding
+ {
+ Path = new PropertyPath("Padding"),
+ RelativeSource = new RelativeSource { Mode = RelativeSourceMode.TemplatedParent }
+ };
+ BindingOperations.SetBinding(this, PaddingProperty, paddingBinding);
+
+ var contentTransitionBinding = new Windows.UI.Xaml.Data.Binding
+ {
+ Path = new PropertyPath("ContentTransitions"),
+ RelativeSource = new RelativeSource { Mode = RelativeSourceMode.TemplatedParent }
+ };
+ BindingOperations.SetBinding(this, ContentTransitionsProperty, contentTransitionBinding);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/FormsSearchBox.cs b/Xamarin.Forms.Platform.WinRT.Tablet/FormsSearchBox.cs
new file mode 100644
index 00000000..633672f6
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Tablet/FormsSearchBox.cs
@@ -0,0 +1,18 @@
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ public class FormsSearchBox : SearchBox
+ {
+ public static readonly DependencyProperty HorizontalTextAlignmentProperty = DependencyProperty.Register(
+ "HorizontalTextAlignment", typeof (Windows.UI.Xaml.TextAlignment), typeof (FormsSearchBox),
+ new PropertyMetadata(Windows.UI.Xaml.TextAlignment.Left));
+
+ public Windows.UI.Xaml.TextAlignment HorizontalTextAlignment
+ {
+ get { return (Windows.UI.Xaml.TextAlignment)GetValue(HorizontalTextAlignmentProperty); }
+ set { SetValue(HorizontalTextAlignmentProperty, value); }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/FormsTextBoxStyle.xaml b/Xamarin.Forms.Platform.WinRT.Tablet/FormsTextBoxStyle.xaml
new file mode 100644
index 00000000..3e5f5646
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Tablet/FormsTextBoxStyle.xaml
@@ -0,0 +1,257 @@
+<ResourceDictionary
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:winRt="using:Xamarin.Forms.Platform.WinRT">
+
+ <winRt:TextAlignmentToHorizontalAlignmentConverter x:Key="AlignmentConverter" />
+ <Style TargetType="winRt:FormsTextBox" x:Key="FormsTextBoxStyle">
+ <!-- This is adapted from the default styling for TextBox -->
+
+ <Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
+ <Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
+ <Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}" />
+ <Setter Property="Background" Value="{ThemeResource TextBoxBackgroundThemeBrush}" />
+ <Setter Property="BorderBrush" Value="{ThemeResource TextBoxBorderThemeBrush}" />
+ <Setter Property="SelectionHighlightColor" Value="{ThemeResource TextSelectionHighlightColorThemeBrush}" />
+ <Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
+ <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
+ <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
+ <Setter Property="PlaceholderForegroundBrush" Value="{ThemeResource TextBoxPlaceholderTextThemeBrush}" />
+ <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
+ <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
+ <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
+ <Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="winRt:FormsTextBox">
+ <Grid>
+ <Grid.Resources>
+ <Style x:Name="DeleteButtonStyle" TargetType="Button">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="Button">
+ <Grid>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal" />
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames
+ Storyboard.TargetName="BackgroundElement"
+ Storyboard.TargetProperty="Background">
+ <DiscreteObjectKeyFrame KeyTime="0"
+ Value="{ThemeResource TextBoxButtonPointerOverBackgroundThemeBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames
+ Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="BorderBrush">
+ <DiscreteObjectKeyFrame KeyTime="0"
+ Value="{ThemeResource TextBoxButtonPointerOverBorderThemeBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames
+ Storyboard.TargetName="GlyphElement"
+ Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0"
+ Value="{ThemeResource TextBoxButtonPointerOverForegroundThemeBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames
+ Storyboard.TargetName="BackgroundElement"
+ Storyboard.TargetProperty="Background">
+ <DiscreteObjectKeyFrame KeyTime="0"
+ Value="{ThemeResource TextBoxButtonPressedBackgroundThemeBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames
+ Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="BorderBrush">
+ <DiscreteObjectKeyFrame KeyTime="0"
+ Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames
+ Storyboard.TargetName="GlyphElement"
+ Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0"
+ Value="{ThemeResource TextBoxButtonPressedForegroundThemeBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <DoubleAnimation
+ Storyboard.TargetName="BackgroundElement"
+ Storyboard.TargetProperty="Opacity"
+ To="0"
+ Duration="0" />
+ <DoubleAnimation Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="Opacity"
+ To="0"
+ Duration="0" />
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Border x:Name="BorderElement"
+ BorderBrush="{ThemeResource TextBoxButtonBorderThemeBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}" />
+ <Border x:Name="BackgroundElement"
+ Background="{ThemeResource TextBoxButtonBackgroundThemeBrush}"
+ Margin="{TemplateBinding BorderThickness}">
+ <TextBlock x:Name="GlyphElement"
+ Foreground="{ThemeResource TextBoxButtonForegroundThemeBrush}"
+ VerticalAlignment="Center"
+ HorizontalAlignment="Center"
+ FontStyle="Normal"
+ Text="&#xE0A4;"
+ FontFamily="{ThemeResource SymbolThemeFontFamily}"
+ AutomationProperties.AccessibilityView="Raw" />
+ </Border>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ </Grid.Resources>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
+ Storyboard.TargetProperty="Background">
+ <DiscreteObjectKeyFrame KeyTime="0"
+ Value="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="BorderBrush">
+ <DiscreteObjectKeyFrame KeyTime="0"
+ Value="{ThemeResource TextBoxDisabledBorderThemeBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement"
+ Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0"
+ Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames
+ Storyboard.TargetName="PlaceholderTextContentPresenter"
+ Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0"
+ Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Normal">
+ <Storyboard>
+ <DoubleAnimation Storyboard.TargetName="BackgroundElement"
+ Storyboard.TargetProperty="Opacity"
+ Duration="0"
+ To="{ThemeResource TextControlBackgroundThemeOpacity}" />
+ <DoubleAnimation Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="Opacity"
+ Duration="0"
+ To="{ThemeResource TextControlBorderThemeOpacity}" />
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <DoubleAnimation Storyboard.TargetName="BackgroundElement"
+ Storyboard.TargetProperty="Opacity"
+ Duration="0"
+ To="{ThemeResource TextControlPointerOverBackgroundThemeOpacity}" />
+ <DoubleAnimation Storyboard.TargetName="BorderElement"
+ Storyboard.TargetProperty="Opacity"
+ Duration="0"
+ To="{ThemeResource TextControlPointerOverBorderThemeOpacity}" />
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Focused" />
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="ButtonStates">
+ <VisualState x:Name="ButtonVisible">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="DeleteButton"
+ Storyboard.TargetProperty="Visibility">
+ <DiscreteObjectKeyFrame KeyTime="0">
+ <DiscreteObjectKeyFrame.Value>
+ <Visibility>Visible</Visibility>
+ </DiscreteObjectKeyFrame.Value>
+ </DiscreteObjectKeyFrame>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="ButtonCollapsed" />
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="Auto" />
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+ <Border x:Name="BackgroundElement"
+ Grid.Row="1"
+ Background="{TemplateBinding Background}"
+ Margin="{TemplateBinding BorderThickness}"
+ Grid.ColumnSpan="2"
+ Grid.RowSpan="1" />
+ <Border x:Name="BorderElement"
+ Grid.Row="1"
+ BorderBrush="{TemplateBinding BorderBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}"
+ Grid.ColumnSpan="2"
+ Grid.RowSpan="1" />
+ <ContentPresenter x:Name="HeaderContentPresenter"
+ Grid.Row="0"
+ Foreground="{ThemeResource TextBoxForegroundHeaderThemeBrush}"
+ Margin="0,4,0,4"
+ Grid.ColumnSpan="2"
+ Content="{TemplateBinding Header}"
+ ContentTemplate="{TemplateBinding HeaderTemplate}"
+ FontWeight="Semilight" />
+ <ScrollViewer x:Name="ContentElement"
+ Grid.Row="1"
+ HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
+ HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
+ VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
+ VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
+ IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
+ IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
+ IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
+ Margin="{TemplateBinding BorderThickness}"
+ Padding="{TemplateBinding Padding}"
+ IsTabStop="False"
+ AutomationProperties.AccessibilityView="Raw"
+ ZoomMode="Disabled" />
+ <!-- Converting the TextAlignment set for the control's input text to a HorizontalAlignment
+ so the PlaceholderText's alignment will match the input text -->
+ <ContentControl x:Name="PlaceholderTextContentPresenter"
+ Grid.Row="1"
+ Foreground="{TemplateBinding PlaceholderForegroundBrush}"
+ Margin="{TemplateBinding BorderThickness}"
+ Padding="{TemplateBinding Padding}"
+ IsTabStop="False"
+ Grid.ColumnSpan="2"
+ Content="{TemplateBinding PlaceholderText}"
+ IsHitTestVisible="False"
+ HorizontalAlignment="{Binding TextAlignment,
+ RelativeSource={RelativeSource Mode=TemplatedParent},
+ Converter={StaticResource AlignmentConverter}}" />
+ <Button x:Name="DeleteButton"
+ Grid.Row="1"
+ Style="{StaticResource DeleteButtonStyle}"
+ BorderThickness="{TemplateBinding BorderThickness}"
+ IsTabStop="False"
+ Grid.Column="1"
+ Visibility="Collapsed"
+ FontSize="{TemplateBinding FontSize}"
+ VerticalAlignment="Stretch" />
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+</ResourceDictionary> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/Properties/AssemblyInfo.cs b/Xamarin.Forms.Platform.WinRT.Tablet/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..610ee3db
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Tablet/Properties/AssemblyInfo.cs
@@ -0,0 +1,11 @@
+using System.Reflection;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.WinRT;
+
+[assembly: AssemblyTitle("Xamarin.Forms.Platform.WinRT.Phone")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCulture("")]
+[assembly: Dependency(typeof (WindowsResourcesProvider))]
+[assembly: ExportRenderer(typeof (SearchBar), typeof (SearchBarRenderer))]
+[assembly: ExportRenderer(typeof (TabbedPage), typeof (TabbedPageRenderer))] \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/SearchBarRenderer.cs b/Xamarin.Forms.Platform.WinRT.Tablet/SearchBarRenderer.cs
new file mode 100644
index 00000000..de713a91
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Tablet/SearchBarRenderer.cs
@@ -0,0 +1,165 @@
+using System.ComponentModel;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ public class SearchBarRenderer
+ : ViewRenderer<SearchBar, FormsSearchBox>
+ {
+ Brush _defaultPlaceholderColorBrush;
+ Brush _defaultTextColorBrush;
+
+ bool _fontApplied;
+
+ FormsTextBox _queryTextBox;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
+ {
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new FormsSearchBox());
+ Control.QuerySubmitted += OnQuerySubmitted;
+ Control.QueryChanged += OnQueryChanged;
+ Control.Loaded += (sender, args) =>
+ {
+ _queryTextBox = Control.GetFirstDescendant<FormsTextBox>();
+ UpdateTextColor();
+ UpdatePlaceholderColor();
+ };
+ }
+
+ UpdateText();
+ UpdatePlaceholder();
+ UpdateFont();
+ UpdateAlignment();
+ UpdatePlaceholderColor();
+ UpdateTextColor();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == SearchBar.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == SearchBar.PlaceholderProperty.PropertyName)
+ UpdatePlaceholder();
+ else if (e.PropertyName == SearchBar.FontAttributesProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == SearchBar.FontFamilyProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == SearchBar.FontSizeProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == SearchBar.HorizontalTextAlignmentProperty.PropertyName)
+ UpdateAlignment();
+ else if (e.PropertyName == SearchBar.PlaceholderColorProperty.PropertyName)
+ UpdatePlaceholderColor();
+ else if (e.PropertyName == SearchBar.TextColorProperty.PropertyName)
+ UpdateTextColor();
+ }
+
+ void OnQuerySubmitted(SearchBox sender, SearchBoxQuerySubmittedEventArgs e)
+ {
+ Element.OnSearchButtonPressed();
+ }
+
+ void UpdatePlaceholder()
+ {
+ Control.PlaceholderText = Element.Placeholder ?? string.Empty;
+ }
+
+ void UpdateFont()
+ {
+ if (Control == null)
+ return;
+
+ var searchBar = Element;
+
+ if (searchBar == null)
+ return;
+
+ var searchBarIsDefault = searchBar.FontFamily == null &&
+ searchBar.FontSize == Device.GetNamedSize(NamedSize.Default, typeof (SearchBar), true) &&
+ searchBar.FontAttributes == FontAttributes.None;
+
+ if (searchBarIsDefault && !_fontApplied)
+ return;
+
+ if (searchBarIsDefault)
+ {
+ Control.ClearValue(Windows.UI.Xaml.Controls.Control.FontStyleProperty);
+ Control.ClearValue(Windows.UI.Xaml.Controls.Control.FontSizeProperty);
+ Control.ClearValue(Windows.UI.Xaml.Controls.Control.FontFamilyProperty);
+ Control.ClearValue(Windows.UI.Xaml.Controls.Control.FontWeightProperty);
+ Control.ClearValue(Windows.UI.Xaml.Controls.Control.FontStretchProperty);
+ }
+ else
+ Control.ApplyFont(searchBar);
+
+ _fontApplied = true;
+ }
+
+ void OnQueryChanged(SearchBox sender, SearchBoxQueryChangedEventArgs e)
+ {
+ ((IElementController)Element).SetValueFromRenderer(SearchBar.TextProperty, e.QueryText);
+ }
+
+ void UpdateText()
+ {
+ Control.QueryText = Element.Text ?? string.Empty;
+ }
+
+ void UpdateAlignment()
+ {
+ Control.HorizontalTextAlignment = Element.HorizontalTextAlignment.ToNativeTextAlignment();
+ }
+
+ void UpdateTextColor()
+ {
+ if (_queryTextBox == null)
+ return;
+
+ var textColor = Element.TextColor;
+
+ if (textColor.IsDefault)
+ {
+ if (_defaultTextColorBrush == null)
+ return;
+
+ _queryTextBox.Foreground = _defaultTextColorBrush;
+ }
+
+ if (_defaultTextColorBrush == null)
+ _defaultTextColorBrush = _queryTextBox.Foreground;
+
+ _queryTextBox.Foreground = textColor.ToBrush();
+ }
+
+ void UpdatePlaceholderColor()
+ {
+ if (_queryTextBox == null)
+ return;
+
+ var placeholderColor = Element.PlaceholderColor;
+
+ if (placeholderColor.IsDefault)
+ {
+ if (_defaultPlaceholderColorBrush == null)
+ return;
+
+ _queryTextBox.PlaceholderForegroundBrush = _defaultPlaceholderColorBrush;
+ }
+
+ if (_defaultPlaceholderColorBrush == null)
+ _defaultPlaceholderColorBrush = _queryTextBox.PlaceholderForegroundBrush;
+
+ _queryTextBox.PlaceholderForegroundBrush = placeholderColor.ToBrush();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/TabbedPageRenderer.cs b/Xamarin.Forms.Platform.WinRT.Tablet/TabbedPageRenderer.cs
new file mode 100644
index 00000000..33923a49
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Tablet/TabbedPageRenderer.cs
@@ -0,0 +1,236 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media.Animation;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ public class TabbedPageRenderer
+ : IVisualElementRenderer
+ {
+ Canvas _canvas;
+
+ bool _disposed;
+ TabsControl _tabs;
+ VisualElementTracker<Page, Canvas> _tracker;
+
+ public TabbedPage Page
+ {
+ get { return (TabbedPage)Element; }
+ }
+
+ protected VisualElementTracker<Page, Canvas> Tracker
+ {
+ get { return _tracker; }
+ set
+ {
+ if (_tracker == value)
+ return;
+
+ if (_tracker != null)
+ _tracker.Dispose();
+
+ _tracker = value;
+ }
+ }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public FrameworkElement ContainerElement
+ {
+ get { return _canvas; }
+ }
+
+ public VisualElement Element { get; private set; }
+
+ public void SetElement(VisualElement element)
+ {
+ if (element != null && !(element is TabbedPage))
+ throw new ArgumentException("Element must be a TabbedPage", "element");
+
+ var oldElement = Page;
+ Element = element;
+
+ if (oldElement != null)
+ {
+ oldElement.PropertyChanged -= OnElementPropertyChanged;
+ ((INotifyCollectionChanged)oldElement.Children).CollectionChanged -= OnPagesChanged;
+ }
+
+ if (element != null)
+ {
+ if (_tracker == null)
+ {
+ _tabs = new TabsControl();
+
+ _canvas = new Canvas();
+
+ _canvas.ChildrenTransitions = new TransitionCollection
+ {
+ new EntranceThemeTransition()
+ };
+
+ Tracker = new BackgroundTracker<Canvas>(Panel.BackgroundProperty)
+ {
+ Element = (Page)element,
+ Control = _canvas,
+ Container = _canvas
+ };
+
+ _canvas.Loaded += OnLoaded;
+ _canvas.Unloaded += OnUnloaded;
+ }
+
+ _tabs.DataContext = element;
+
+ OnPagesChanged(Page.Children, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ UpdateCurrentPage();
+
+ ((INotifyCollectionChanged)Page.Children).CollectionChanged += OnPagesChanged;
+ element.PropertyChanged += OnElementPropertyChanged;
+ }
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+ }
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ if (_canvas.Children.Count == 0)
+ return new SizeRequest();
+
+ var constraint = new Windows.Foundation.Size(widthConstraint, heightConstraint);
+ var child = (FrameworkElement)_canvas.Children[0];
+
+ var oldWidth = child.Width;
+ var oldHeight = child.Height;
+
+ child.Height = double.NaN;
+ child.Width = double.NaN;
+
+ child.Measure(constraint);
+ var result = new Size(Math.Ceiling(child.DesiredSize.Width), Math.Ceiling(child.DesiredSize.Height));
+
+ child.Width = oldWidth;
+ child.Height = oldHeight;
+
+ return new SizeRequest(result);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposing || _disposed)
+ return;
+
+ _disposed = true;
+ SetElement(null);
+ Tracker = null;
+ }
+
+ protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ var changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ void OnPagesChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ e.Apply(Page.Children, _tabs.Items);
+ }
+
+ internal void OnTabSelected(Page tab)
+ {
+ CloseTabs();
+ Page.CurrentPage = tab;
+ }
+
+ void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "CurrentPage")
+ UpdateCurrentPage();
+ }
+
+ void UpdateCurrentPage()
+ {
+ var renderer = Page.CurrentPage.GetOrCreateRenderer();
+ _canvas.Children.Clear();
+
+ if (renderer != null)
+ _canvas.Children.Add(renderer.ContainerElement);
+ }
+
+ void OnLoaded(object sender, RoutedEventArgs args)
+ {
+ if (Page == null)
+ return;
+
+ ShowTabs();
+ Page.SendAppearing();
+ }
+
+ Windows.UI.Xaml.Controls.Page GetTopPage()
+ {
+ var frame = Window.Current.Content as Windows.UI.Xaml.Controls.Frame;
+ if (frame == null)
+ return null;
+
+ return frame.Content as Windows.UI.Xaml.Controls.Page;
+ }
+
+ AppBar GetOrCreateAppBar()
+ {
+ var npage = GetTopPage();
+ if (npage == null)
+ return null;
+
+ if (npage.TopAppBar == null)
+ npage.TopAppBar = new AppBar();
+
+ return npage.TopAppBar;
+ }
+
+ void ShowTabs()
+ {
+ var bar = GetOrCreateAppBar();
+ if (bar != null)
+ bar.Content = _tabs;
+ }
+
+ void CloseTabs()
+ {
+ var page = GetTopPage();
+ if (page == null)
+ return;
+
+ if (page.TopAppBar != null)
+ page.TopAppBar.IsOpen = false;
+ }
+
+ void RemoveTabs()
+ {
+ var page = GetTopPage();
+ if (page == null)
+ return;
+
+ // Explicitly unparent this.tabs so we can reuse
+ if (page.TopAppBar != null)
+ page.TopAppBar.Content = null;
+
+ page.TopAppBar = null;
+ }
+
+ void OnUnloaded(object sender, RoutedEventArgs args)
+ {
+ RemoveTabs();
+ if (Page != null)
+ Page.SendDisappearing();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/TabletResources.xaml b/Xamarin.Forms.Platform.WinRT.Tablet/TabletResources.xaml
new file mode 100644
index 00000000..51b9e1d7
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Tablet/TabletResources.xaml
@@ -0,0 +1,939 @@
+<ResourceDictionary
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="using:Xamarin.Forms.Platform.WinRT">
+
+ <ResourceDictionary.MergedDictionaries>
+ <ResourceDictionary Source="Resources.xaml" />
+ <ResourceDictionary Source="FormsTextBoxStyle.xaml" />
+ </ResourceDictionary.MergedDictionaries>
+
+ <SolidColorBrush x:Key="TabButtonPointerOverBackgroundBrush" Color="#44888888" />
+ <SolidColorBrush x:Key="TabButtonBackgroundBrush" Color="#29888888" />
+
+ <Style x:Key="FormsListViewItem" TargetType="ListViewItem">
+ <Setter Property="HorizontalContentAlignment" Value="Stretch" />
+ <Setter Property="Margin" Value="0" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="ListViewItem">
+ <local:FormsListViewItemPresenter
+ CheckBrush="{ThemeResource ListViewItemCheckThemeBrush}"
+ CheckHintBrush="{ThemeResource ListViewItemCheckHintThemeBrush}"
+ CheckSelectingBrush="{ThemeResource ListViewItemCheckSelectingThemeBrush}"
+ ContentMargin="0"
+ DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}"
+ DragBackground="{ThemeResource ListViewItemDragBackgroundThemeBrush}"
+ DragForeground="{ThemeResource ListViewItemDragForegroundThemeBrush}"
+ DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}"
+ FocusBorderBrush="{ThemeResource ListViewItemFocusBorderThemeBrush}"
+ PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}"
+ PointerOverBackground="{ThemeResource ListViewItemPointerOverBackgroundThemeBrush}"
+ PointerOverBackgroundMargin="0"
+ ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
+ SelectedBackground="{ThemeResource ListViewItemSelectedBackgroundThemeBrush}"
+ SelectedBorderThickness="{ThemeResource ListViewItemCompactSelectedBorderThemeThickness}"
+ SelectedForeground="{ThemeResource ListViewItemSelectedForegroundThemeBrush}"
+ SelectedPointerOverBackground="{ThemeResource ListViewItemSelectedPointerOverBackgroundThemeBrush}"
+ SelectedPointerOverBorderBrush="{ThemeResource ListViewItemSelectedPointerOverBorderThemeBrush}"
+ SelectionCheckMarkVisualEnabled="False" />
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <DataTemplate x:Key="TextCell">
+ <StackPanel Margin="5,4,4,9.5">
+ <TextBlock
+ Text="{Binding Text}"
+ Style="{ThemeResource TitleTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding TextColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}" />
+
+ <TextBlock
+ Text="{Binding Detail}"
+ Style="{ThemeResource BodyTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding DetailColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}" />
+ </StackPanel>
+ </DataTemplate>
+
+ <DataTemplate x:Key="ListViewHeaderTextCell">
+ <StackPanel Margin="5,4,4,9.5">
+ <TextBlock
+ Text="{Binding Text}"
+ Style="{ThemeResource SubheaderTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding TextColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}" />
+
+ <TextBlock
+ Text="{Binding Detail}"
+ Style="{ThemeResource BodyTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding DetailColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}" />
+ </StackPanel>
+ </DataTemplate>
+
+ <DataTemplate x:Key="ImageCell">
+ <Grid Margin="5,4,4,9.5">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition />
+ </Grid.ColumnDefinitions>
+
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ </Grid.RowDefinitions>
+
+ <Image Grid.Column="0" Grid.RowSpan="2"
+ DataContext="{Binding ImageSource, Converter={StaticResource ImageConverter}}"
+ Source="{Binding Value}"
+ VerticalAlignment="Center" />
+
+ <TextBlock Grid.Column="1" Grid.Row="0"
+ Text="{Binding Text}"
+ Style="{ThemeResource TitleTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding TextColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}" />
+
+ <TextBlock Grid.Column="1" Grid.Row="1"
+ Text="{Binding Detail}"
+ Style="{ThemeResource BodyTextBlockStyle}"
+ Visibility="{Binding Text,RelativeSource={RelativeSource Self}, Converter={StaticResource CollapseWhenEmpty}}"
+ Foreground="{Binding DetailColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}" />
+ </Grid>
+ </DataTemplate>
+
+ <DataTemplate x:Key="SwitchCell">
+ <Grid Margin="5,4,4,9.5" HorizontalAlignment="Stretch">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="Auto" />
+ </Grid.ColumnDefinitions>
+
+ <TextBlock Grid.Column="0" Text="{Binding Text}" VerticalAlignment="Center" Style="{ThemeResource TitleTextBlockStyle}" />
+
+ <ToggleSwitch Grid.Column="1" IsOn="{Binding On, Mode=TwoWay}" OnContent="" OffContent="" VerticalAlignment="Center" />
+ </Grid>
+ </DataTemplate>
+
+ <DataTemplate x:Key="EntryCell">
+ <local:EntryCellTextBox Margin="5,4,4,9.5" IsEnabled="{Binding IsEnabled}" Header="{Binding}" Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" PlaceholderText="{Binding Placeholder}" TextAlignment="{Binding HorizontalTextAlignment,Converter={StaticResource HorizontalTextAlignmentConverter}}" InputScope="{Binding Keyboard,Converter={StaticResource KeyboardConverter}}" HorizontalAlignment="Stretch">
+ <local:EntryCellTextBox.HeaderTemplate>
+ <DataTemplate>
+ <TextBlock Text="{Binding Label}" Style="{ThemeResource TitleTextBlockStyle}" Foreground="{Binding LabelColor, Converter={StaticResource ColorConverter}, ConverterParameter=DefaultTextForegroundThemeBrush}" />
+ </DataTemplate>
+ </local:EntryCellTextBox.HeaderTemplate>
+ </local:EntryCellTextBox>
+ </DataTemplate>
+
+ <DataTemplate x:Key="ViewCell">
+ <ContentControl DataContext="{Binding Cell}">
+ <ContentPresenter Height="{Binding RenderHeight, Converter={StaticResource HeightConverter}}" Content="{Binding View, Converter={StaticResource ViewToRenderer}}" />
+ </ContentControl>
+ </DataTemplate>
+
+ <Style x:Key="JumpListGrid" TargetType="GridView">
+ <Setter Property="ItemTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <Border Background="{ThemeResource SystemColorControlAccentBrush}" Padding="5" Margin="3" MinHeight="80" MinWidth="80">
+ <TextBlock Text="{Binding}" Style="{ThemeResource SubheaderTextBlockStyle}" VerticalAlignment="Bottom" />
+ </Border>
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <GroupStyle x:Key="ListViewGroup" HidesIfEmpty="False">
+ <GroupStyle.HeaderContainerStyle>
+ <Style TargetType="ListViewHeaderItem">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <local:ListGroupHeaderPresenter />
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ </GroupStyle.HeaderContainerStyle>
+ <GroupStyle.HeaderTemplate>
+ <DataTemplate>
+ <local:CellControl IsGroupHeader="true" HorizontalContentAlignment="Stretch" />
+ </DataTemplate>
+ </GroupStyle.HeaderTemplate>
+ </GroupStyle>
+
+ <Style TargetType="local:TabButton">
+ <Setter Property="MinWidth" Value="166" />
+ <Setter Property="Margin" Value="0,0,15,0" />
+ <Setter Property="Padding" Value="9.5" />
+ <Setter Property="HorizontalContentAlignment" Value="Stretch" />
+ <Setter Property="VerticalAlignment" Value="Stretch" />
+ <Setter Property="VerticalContentAlignment" Value="Bottom" />
+ <Setter Property="Background" Value="{ThemeResource TabButtonBackgroundBrush}" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Border x:Name="Border" Background="{TemplateBinding Background}" BorderThickness="0" Margin="{TemplateBinding Margin}">
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal" />
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <PointerDownThemeAnimation TargetName="Border" />
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabButtonPointerOverBackgroundBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPointerOverForegroundThemeBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="Background">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabButtonPointerOverBackgroundBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPointerOverForegroundThemeBrush}" />
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualStateGroup.Transitions>
+ <VisualTransition From="Pressed" To="Normal">
+ <Storyboard>
+ <PointerUpThemeAnimation TargetName="Border" />
+ </Storyboard>
+ </VisualTransition>
+ <VisualTransition From="Pressed" To="PointerOver">
+ <Storyboard>
+ <PointerUpThemeAnimation TargetName="Border" />
+ </Storyboard>
+ </VisualTransition>
+ </VisualStateGroup.Transitions>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+
+ <ContentPresenter x:Name="ContentPresenter" Margin="{TemplateBinding Padding}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
+ </Border>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style TargetType="local:TabsControl">
+ <Setter Property="Background" Value="{ThemeResource AppBarBackgroundThemeBrush}" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Border Background="{TemplateBinding Background}" BorderThickness="0">
+ <Grid Margin="19,13,19,13">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+
+ <TextBlock Grid.Row="0" Margin="9.5,0,0,9.5" Text="{Binding Title, Converter={StaticResource UpperConverter}}"
+ Opacity=".6" FontWeight="SemiBold" Foreground="{ThemeResource AppBarItemForegroundThemeBrush}"
+ Style="{ThemeResource BaseTextBlockStyle}" />
+
+ <ScrollViewer Grid.Row="1" VerticalScrollMode="Disabled" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Auto">
+ <ItemsPresenter />
+ </ScrollViewer>
+ </Grid>
+ </Border>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="ItemsPanel">
+ <Setter.Value>
+ <ItemsPanelTemplate>
+ <StackPanel Orientation="Horizontal" Margin="0,11,0,0" />
+ </ItemsPanelTemplate>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="ItemTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <local:TabButton>
+ <StackPanel VerticalAlignment="Bottom">
+ <Image DataContext="{Binding Icon, Converter={StaticResource ImageConverter}}" Source="{Binding Value}" HorizontalAlignment="Left" />
+ <TextBlock Margin="0,15,0,15" Text="{Binding Title, Converter={StaticResource UpperConverter}}"
+ Style="{ThemeResource CaptionTextBlockStyle}" FontWeight="SemiBold" Foreground="{ThemeResource AppBarItemForegroundThemeBrush}" HorizontalAlignment="Left" />
+ </StackPanel>
+ </local:TabButton>
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <ControlTemplate x:Key="MasterDetailSplit">
+ <Grid Background="{TemplateBinding Background}">
+ <Grid.Resources>
+ <Style TargetType="local:PageControl" BasedOn="{StaticResource PageControlDefaultStyle}">
+ <Setter Property="Background" Value="Transparent" />
+ <Setter Property="InvisibleBackButtonCollapsed" Value="True" />
+ </Style>
+ </Grid.Resources>
+
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+
+ <Border Grid.Column="0" Margin="0" Padding="0" Background="{Binding Converter={StaticResource MasterBackgroundConverter}, RelativeSource={RelativeSource Mode=TemplatedParent}}">
+ <ContentPresenter x:Name="masterPresenter" />
+ </Border>
+
+ <ContentPresenter x:Name="detailPresenter" Grid.Column="1" />
+ </Grid>
+ </ControlTemplate>
+
+ <ControlTemplate x:Key="MasterDetailPopup">
+ <Grid Background="{TemplateBinding Background}">
+ <Grid.Resources>
+ <Style TargetType="local:PageControl" BasedOn="{StaticResource PageControlDefaultStyle}">
+ <Setter Property="Background" Value="Transparent" />
+ </Style>
+ </Grid.Resources>
+
+ <Popup x:Name="popup" IsLightDismissEnabled="true">
+ <Popup.ChildTransitions>
+ <TransitionCollection>
+ <PaneThemeTransition Edge="Left" />
+ </TransitionCollection>
+ </Popup.ChildTransitions>
+
+ <Border Margin="0" Padding="0" BorderThickness="0" Background="{Binding Converter={StaticResource MasterBackgroundConverter}, RelativeSource={RelativeSource Mode=TemplatedParent}}">
+ <ContentPresenter x:Name="masterPresenter" />
+ </Border>
+ </Popup>
+
+ <ContentPresenter x:Name="detailPresenter" />
+ </Grid>
+ </ControlTemplate>
+
+ <Style x:Key="PageControlDefaultStyle" TargetType="local:PageControl">
+ <Setter Property="ContentMargin" Value="0" />
+ <Setter Property="TitleBrush" Value="{ThemeResource DefaultTextForegroundThemeBrush}" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="local:PageControl">
+ <Grid Background="{TemplateBinding Background}">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+
+ <Grid Grid.Row="0" Grid.Column="0" Height="79" VerticalAlignment="Center" Background="{TemplateBinding NavigationBarBackground}" Visibility="{Binding ShowNavigationBar,RelativeSource={RelativeSource Mode=TemplatedParent},Converter={StaticResource BoolVisibilityConverter}}">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" MinWidth="{Binding TitleInset,RelativeSource={RelativeSource TemplatedParent}}" />
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+
+ <AppBarButton x:Name="backButton" Grid.Column="0" Margin="0,6,0,0" Foreground="{TemplateBinding TitleBrush}" ToolTipService.ToolTip="{TemplateBinding BackButtonTitle}" HorizontalAlignment="Right" VerticalAlignment="Center" Visibility="Collapsed">
+ <AppBarButton.Icon>
+ <SymbolIcon Symbol="Back" />
+ </AppBarButton.Icon>
+ </AppBarButton>
+
+ <TextBlock Name="title" Padding="10,0,0,0" Grid.Column="1" Foreground="{TemplateBinding TitleBrush}" VerticalAlignment="Center" Style="{ThemeResource HeaderTextBlockStyle}" Text="{Binding Title}" />
+ </Grid>
+
+ <ContentPresenter Margin="{TemplateBinding ContentMargin}" ContentTransitions="{TemplateBinding ContentTransitions}" x:Name="presenter" Grid.Row="1" />
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style TargetType="local:PageControl" BasedOn="{StaticResource PageControlDefaultStyle}" />
+
+ <Style TargetType="local:FormsSearchBox">
+ <Setter Property="Background" Value="{ThemeResource SearchBoxBackgroundThemeBrush}"/>
+ <Setter Property="BorderBrush" Value="{ThemeResource SearchBoxBorderThemeBrush}"/>
+ <Setter Property="BorderThickness" Value="{ThemeResource SearchBoxBorderThemeThickness}"/>
+ <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
+ <Setter Property="FontSize" Value="{ThemeResource SearchBoxContentThemeFontSize}"/>
+ <Setter Property="FontWeight" Value="{ThemeResource SearchBoxContentThemeFontWeight}"/>
+ <Setter Property="Foreground" Value="{ThemeResource SearchBoxForegroundThemeBrush}"/>
+ <Setter Property="Padding" Value="{ThemeResource SearchBoxThemePadding}"/>
+ <Setter Property="IsTabStop" Value="False"/>
+ <Setter Property="Typography.StylisticSet20" Value="True"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="local:FormsSearchBox">
+ <Grid x:Name="SearchBoxGrid">
+ <Grid.Resources>
+ <Style x:Key="SearchButtonStyle" TargetType="Button">
+ <Setter Property="IsTabStop" Value="False"/>
+ <Setter Property="VerticalAlignment" Value="Stretch"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="Button">
+ <Grid Background="Transparent">
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal"/>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="SearchGlyph">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonPointerOverForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchButtonBackground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonPointerOverBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="SearchGlyph">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedTextThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchButtonBackground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled"/>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="FocusStates">
+ <VisualState x:Name="Focused"/>
+ <VisualState x:Name="Unfocused"/>
+ <VisualState x:Name="PointerFocused"/>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Grid x:Name="SearchButtonBackground" Background="{TemplateBinding Background}">
+ <TextBlock x:Name="SearchGlyph" AutomationProperties.AccessibilityView="Raw" Foreground="{TemplateBinding Foreground}" FontStyle="Normal" FontFamily="{ThemeResource SymbolThemeFontFamily}" HorizontalAlignment="Center" Text="&#xE094;" VerticalAlignment="Center"/>
+ </Grid>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ <Style x:Key="SearchTextBoxStyle" TargetType="local:FormsTextBox">
+ <Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}"/>
+ <Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}"/>
+ <Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}"/>
+ <Setter Property="PlaceholderForegroundBrush" Value="{ThemeResource TextBoxPlaceholderTextThemeBrush}"/>
+ <Setter Property="Background" Value="{ThemeResource TextBoxBackgroundThemeBrush}"/>
+ <Setter Property="BorderBrush" Value="{ThemeResource TextBoxBorderThemeBrush}"/>
+ <Setter Property="SelectionHighlightColor" Value="{ThemeResource TextSelectionHighlightColorThemeBrush}"/>
+ <Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}"/>
+ <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
+ <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
+ <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden"/>
+ <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden"/>
+ <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False"/>
+ <Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="local:FormsTextBox">
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BackgroundElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="BorderElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentElement">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="PlaceholderTextContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Normal">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="{ThemeResource TextControlBackgroundThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundElement"/>
+ <DoubleAnimation Duration="0" To="{ThemeResource TextControlBorderThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BorderElement"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="{ThemeResource TextControlPointerOverBackgroundThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundElement"/>
+ <DoubleAnimation Duration="0" To="{ThemeResource TextControlPointerOverBorderThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BorderElement"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Focused"/>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="ButtonStates"/>
+ </VisualStateManager.VisualStateGroups>
+ <Border x:Name="BackgroundElement" Background="{TemplateBinding Background}" Margin="{TemplateBinding BorderThickness}" Grid.Row="1" Grid.RowSpan="1"/>
+ <Border x:Name="BorderElement" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Grid.Row="1" Grid.RowSpan="1"/>
+ <ContentPresenter x:Name="HeaderContentPresenter" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" Foreground="{ThemeResource TextBoxForegroundHeaderThemeBrush}" FontWeight="Semilight" Margin="0,4,0,4" Grid.Row="0"/>
+ <ScrollViewer x:Name="ContentElement" AutomationProperties.AccessibilityView="Raw" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" IsTabStop="False" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Grid.Row="1" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" ZoomMode="Disabled"/>
+ <ContentControl x:Name="PlaceholderTextContentPresenter" Grid.ColumnSpan="2" Content="{TemplateBinding PlaceholderText}" Foreground="{TemplateBinding PlaceholderForegroundBrush}" IsHitTestVisible="False" IsTabStop="False" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Grid.Row="1"
+ HorizontalAlignment="{Binding TextAlignment,
+ RelativeSource={RelativeSource Mode=TemplatedParent},
+ Converter={StaticResource AlignmentConverter}}"/>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ </Grid.Resources>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchBoxGrid">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding Background, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="SearchBoxBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding BorderBrush, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="SearchButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding Foreground, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchBoxGrid">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxPointerOverBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="SearchBoxBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxPointerOverBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="SearchButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxPointerOverTextThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchBoxGrid">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="SearchBoxBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="SearchButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledTextThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchTextBox">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Focused">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchBoxGrid">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="SearchBoxBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="SearchButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="SearchSuggestionsPopupBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="FocusedDropDown">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="SearchBoxGrid">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="SearchBoxBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="SearchButton">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedTextThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="SearchSuggestionsPopupBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Border x:Name="SearchBoxBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="Transparent">
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition/>
+ <ColumnDefinition Width="Auto"/>
+ </Grid.ColumnDefinitions>
+ <local:FormsTextBox TextAlignment="{TemplateBinding HorizontalTextAlignment}" x:Name="SearchTextBox" BorderThickness="0" Background="Transparent" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" InputScope="Search" MinHeight="{ThemeResource SearchBoxTextBoxThemeMinHeight}" MaxLength="2048" Padding="{TemplateBinding Padding}" PlaceholderText="{TemplateBinding PlaceholderText}" Style="{StaticResource SearchTextBoxStyle}" TextWrapping="NoWrap" VerticalAlignment="Stretch"/>
+ <Button x:Name="SearchButton" AutomationProperties.AccessibilityView="Raw" Background="Transparent" Grid.Column="1" FontWeight="{ThemeResource SearchBoxButtonThemeFontWeight}" Style="{StaticResource SearchButtonStyle}"/>
+ </Grid>
+ </Border>
+ <Popup x:Name="SearchSuggestionsPopup" HorizontalAlignment="Left" VerticalAlignment="Bottom">
+ <Border x:Name="SearchSuggestionsPopupBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" MinWidth="{ThemeResource SearchBoxSuggestionPopupThemeMinWidth}">
+ <Border.Resources>
+ <Style x:Key="SearchSuggestionListViewItemStyle" TargetType="ListViewItem">
+ <Setter Property="Background" Value="Transparent"/>
+ <Setter Property="TabNavigation" Value="Local"/>
+ <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
+ <Setter Property="Margin" Value="0"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="ListViewItem">
+ <Border x:Name="OuterContainer">
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal"/>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PointerOverBorder"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <PointerDownThemeAnimation TargetName="ContentContainer"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="PointerOverPressed">
+ <Storyboard>
+ <PointerDownThemeAnimation TargetName="ContentContainer"/>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PointerOverBorder"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="{ThemeResource ListViewItemDisabledThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ListViewItemContentPresenter"/>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="FocusStates">
+ <VisualState x:Name="Focused">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisual"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Unfocused"/>
+ <VisualState x:Name="PointerFocused"/>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="SelectionStates">
+ <VisualState x:Name="Unselecting"/>
+ <VisualState x:Name="Unselected"/>
+ <VisualState x:Name="UnselectedPointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ListViewItemContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="UnselectedSwiping"/>
+ <VisualState x:Name="Selecting"/>
+ <VisualState x:Name="Selected">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectionBackground"/>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ListViewItemContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="SelectedSwiping"/>
+ <VisualState x:Name="SelectedUnfocused">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectionBackground"/>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ListViewItemContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Grid x:Name="ContentContainer">
+ <Rectangle x:Name="PointerOverBorder" Fill="{ThemeResource SearchBoxButtonBackgroundThemeBrush}" IsHitTestVisible="False" Opacity="0"/>
+ <Rectangle x:Name="FocusVisual" IsHitTestVisible="False" Opacity="0" Stroke="{ThemeResource ListViewItemFocusBorderThemeBrush}" StrokeThickness="2"/>
+ <Rectangle x:Name="SelectionBackground" Fill="{ThemeResource SearchBoxButtonBackgroundThemeBrush}" Opacity="0"/>
+ <ContentPresenter x:Name="ListViewItemContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" FontWeight="{Binding FontWeight, ElementName=SearchTextBox}" FontSize="{Binding FontSize, ElementName=SearchTextBox}" FontFamily="{Binding FontFamily, ElementName=SearchTextBox}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
+ </Grid>
+ </Border>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ </Border.Resources>
+ <Grid MaxHeight="{ThemeResource SearchBoxSuggestionPopupThemeMaxHeight}">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition/>
+ </Grid.RowDefinitions>
+ <Border x:Name="IMECandidateListContainer"/>
+ <Border x:Name="IMECandidateListSeparator" BorderBrush="{ThemeResource SearchBoxIMECandidateListSeparatorThemeBrush}" BorderThickness="{ThemeResource SearchBoxIMECandidateListSeparatorThemeThickness}" Grid.Row="1" Visibility="Collapsed"/>
+ <ListView x:Name="SearchSuggestionsList" Background="{ThemeResource TextBoxBackgroundThemeBrush}" IsTabStop="False" IsItemClickEnabled="true" Grid.Row="2">
+ <ListView.Resources>
+ <DataTemplate x:Name="HitHighlightedTextBlock">
+ <RichTextBlock x:Name="TextBlock" AutomationProperties.AccessibilityView="Raw" SelectionHighlightColor="{ThemeResource SearchBoxHitHighlightForegroundThemeBrush}" TextWrapping="Wrap" TextTrimming="WordEllipsis">
+ <RichTextBlock.Resources>
+ <DataTemplate x:Name="SelectedHitHighlightedRun">
+ <Run Foreground="{ThemeResource SearchBoxHitHighlightSelectedForegroundThemeBrush}"/>
+ </DataTemplate>
+ </RichTextBlock.Resources>
+ </RichTextBlock>
+ </DataTemplate>
+ </ListView.Resources>
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <Grid>
+ <ContentControl x:Name="QuerySuggestionTemplate" Typography.DiscretionaryLigatures="False" Margin="{ThemeResource SearchBoxQuerySuggestionThemeMargin}" Visibility="Collapsed" VerticalAlignment="Center"/>
+ <Grid x:Name="ResultSuggestionTemplate" Typography.DiscretionaryLigatures="False" Margin="{ThemeResource SearchBoxResultSuggestionThemeMargin}" Visibility="Collapsed">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition/>
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition/>
+ <RowDefinition/>
+ </Grid.RowDefinitions>
+ <Image x:Name="ResultSuggestionImage" Height="{ThemeResource SearchBoxResultSuggestionImageThemeHeight}" Margin="{ThemeResource SearchBoxSuggestionSubcomponentThemeMargin}" Grid.RowSpan="2" Width="{ThemeResource SearchBoxResultSuggestionImageThemeWidth}"/>
+ <ContentControl x:Name="ResultSuggestionText" Grid.Column="1" VerticalAlignment="Center"/>
+ <ContentControl x:Name="ResultSuggestionDetailText" Grid.Column="1" Grid.Row="1" VerticalAlignment="Center"/>
+ </Grid>
+ <Grid x:Name="SeparatorSuggestionTemplate" Typography.DiscretionaryLigatures="False" Margin="{ThemeResource SearchBoxSeparatorSuggestionThemeMargin}" Visibility="Collapsed">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition/>
+ </Grid.ColumnDefinitions>
+ <TextBlock x:Name="SeparatorSuggestionText" Margin="{ThemeResource SearchBoxSuggestionSubcomponentThemeMargin}" TextTrimming="WordEllipsis" VerticalAlignment="Center"/>
+ <Border BorderBrush="{ThemeResource SearchBoxSeparatorSuggestionForegroundThemeBrush}" BorderThickness="0,1,0,0" Grid.Column="1" VerticalAlignment="Center"/>
+ </Grid>
+ </Grid>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ <ListView.ItemContainerTransitions>
+ <TransitionCollection/>
+ </ListView.ItemContainerTransitions>
+ <ListView.ItemContainerStyle>
+ <StaticResource ResourceKey="SearchSuggestionListViewItemStyle"/>
+ </ListView.ItemContainerStyle>
+ </ListView>
+ </Grid>
+ </Border>
+ </Popup>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style TargetType="ToggleSwitch">
+ <Setter Property="Foreground" Value="{ThemeResource ToggleSwitchForegroundThemeBrush}"/>
+ <Setter Property="HorizontalAlignment" Value="Left"/>
+ <Setter Property="VerticalAlignment" Value="Center"/>
+ <Setter Property="HorizontalContentAlignment" Value="Left"/>
+ <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
+ <Setter Property="FontWeight" Value="SemiBold"/>
+ <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
+ <Setter Property="MinWidth" Value="154"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="ToggleSwitch">
+ <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal"/>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SwitchCurtain">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchCurtainPointerOverBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="InnerBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchTrackPointerOverBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SwitchKnob">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchThumbPointerOverBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="SwitchKnob">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchThumbPointerOverBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SwitchCurtain">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchCurtainPressedBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="InnerBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchTrackPressedBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SwitchKnob">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchThumbPressedBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="SwitchKnob">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchThumbPressedForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="HeaderContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchHeaderDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="OffContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="OnContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="OuterBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchOuterBorderDisabledBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="InnerBorder">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchTrackDisabledBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SwitchKnob">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchThumbDisabledBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="SwitchKnob">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchThumbDisabledBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SwitchCurtain">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchCurtainDisabledBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="ToggleStates">
+ <VisualStateGroup.Transitions>
+ <VisualTransition x:Name="DraggingToOnTransition" From="Dragging" GeneratedDuration="0" To="On">
+ <Storyboard>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.KnobCurrentToOnOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" TargetName="SwitchKnob"/>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.CurtainCurrentToOnOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" TargetName="SwitchCurtain"/>
+ </Storyboard>
+ </VisualTransition>
+ <VisualTransition x:Name="DraggingToOffTransition" From="Dragging" GeneratedDuration="0" To="Off">
+ <Storyboard>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.KnobCurrentToOffOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" TargetName="SwitchKnob"/>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.CurtainCurrentToOffOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" TargetName="SwitchCurtain"/>
+ </Storyboard>
+ </VisualTransition>
+ <VisualTransition x:Name="OnToOffTransition" From="On" GeneratedDuration="0" To="Off">
+ <Storyboard>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.KnobOnToOffOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" TargetName="SwitchKnob"/>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.CurtainOnToOffOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" TargetName="SwitchCurtain"/>
+ </Storyboard>
+ </VisualTransition>
+ <VisualTransition x:Name="OffToOnTransition" From="Off" GeneratedDuration="0" To="On">
+ <Storyboard>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.KnobOffToOnOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" TargetName="SwitchKnob"/>
+ <RepositionThemeAnimation FromHorizontalOffset="{Binding TemplateSettings.CurtainOffToOnOffset, RelativeSource={RelativeSource Mode=TemplatedParent}}" TargetName="SwitchCurtain"/>
+ </Storyboard>
+ </VisualTransition>
+ </VisualStateGroup.Transitions>
+ <VisualState x:Name="Dragging"/>
+ <VisualState x:Name="Off">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="-44" Storyboard.TargetProperty="X" Storyboard.TargetName="CurtainTranslateTransform"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="On">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="CurtainTranslateTransform"/>
+ <DoubleAnimation Duration="0" To="38" Storyboard.TargetProperty="X" Storyboard.TargetName="KnobTranslateTransform"/>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="ContentStates">
+ <VisualState x:Name="OffContent">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="OffContentPresenter"/>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="OffContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0">
+ <DiscreteObjectKeyFrame.Value>
+ <x:Boolean>True</x:Boolean>
+ </DiscreteObjectKeyFrame.Value>
+ </DiscreteObjectKeyFrame>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="OnContent">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="OnContentPresenter"/>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="OnContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0">
+ <DiscreteObjectKeyFrame.Value>
+ <x:Boolean>True</x:Boolean>
+ </DiscreteObjectKeyFrame.Value>
+ </DiscreteObjectKeyFrame>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="FocusStates">
+ <VisualState x:Name="Focused">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisualWhite"/>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisualBlack"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Unfocused"/>
+ <VisualState x:Name="PointerFocused"/>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+ <ContentPresenter x:Name="HeaderContentPresenter" AutomationProperties.AccessibilityView="Raw" Grid.ColumnSpan="2" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" Foreground="{ThemeResource ToggleSwitchHeaderForegroundThemeBrush}" FontWeight="Semilight" Margin="6"/>
+ <Grid Margin="{TemplateBinding Padding}" Grid.Row="1">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="7"/>
+ <ColumnDefinition Width="Auto"/>
+ </Grid.ColumnDefinitions>
+ <ContentPresenter x:Name="OffContentPresenter" AutomationProperties.AccessibilityView="Raw" ContentTemplate="{TemplateBinding OffContentTemplate}" Content="{TemplateBinding OffContent}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="False" Margin="6,5,0,16" MinWidth="65" Opacity="0" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
+ <ContentPresenter x:Name="OnContentPresenter" AutomationProperties.AccessibilityView="Raw" ContentTemplate="{TemplateBinding OnContentTemplate}" Content="{TemplateBinding OnContent}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="False" Margin="6,5,0,16" MinWidth="65" Opacity="0" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
+ <Grid Background="Transparent" Grid.Column="2" ManipulationMode="None">
+ <Grid x:Name="SwitchKnobBounds" Height="19" Margin="13,5,13,16">
+ <Border x:Name="OuterBorder" BorderBrush="{ThemeResource ToggleSwitchOuterBorderBorderThemeBrush}" BorderThickness="2">
+ <Border x:Name="InnerBorder" BorderBrush="{ThemeResource ToggleSwitchTrackBorderThemeBrush}" BorderThickness="1" Background="{ThemeResource ToggleSwitchTrackBackgroundThemeBrush}">
+ <ContentPresenter x:Name="SwitchCurtainBounds">
+ <ContentPresenter x:Name="SwitchCurtainClip">
+ <Rectangle x:Name="SwitchCurtain" Fill="{ThemeResource ToggleSwitchCurtainBackgroundThemeBrush}" Width="44">
+ <Rectangle.RenderTransform>
+ <TranslateTransform x:Name="CurtainTranslateTransform" X="-44"/>
+ </Rectangle.RenderTransform>
+ </Rectangle>
+ </ContentPresenter>
+ </ContentPresenter>
+ </Border>
+ </Border>
+ <Rectangle x:Name="SwitchKnob" Fill="{ThemeResource ToggleSwitchThumbBackgroundThemeBrush}" HorizontalAlignment="Left" Stroke="{ThemeResource ToggleSwitchThumbBorderThemeBrush}" StrokeThickness="1" Width="12">
+ <Rectangle.RenderTransform>
+ <TranslateTransform x:Name="KnobTranslateTransform"/>
+ </Rectangle.RenderTransform>
+ </Rectangle>
+ <Rectangle x:Name="FocusVisualWhite" Margin="-3" Opacity="0" StrokeDashOffset="1.5" StrokeEndLineCap="Square" Stroke="{ThemeResource FocusVisualWhiteStrokeThemeBrush}" StrokeDashArray="1,1"/>
+ <Rectangle x:Name="FocusVisualBlack" Margin="-3" Opacity="0" StrokeDashOffset="0.5" StrokeEndLineCap="Square" Stroke="{ThemeResource FocusVisualBlackStrokeThemeBrush}" StrokeDashArray="1,1"/>
+ </Grid>
+ <Thumb x:Name="SwitchThumb" AutomationProperties.AccessibilityView="Raw">
+ <Thumb.Template>
+ <ControlTemplate TargetType="Thumb">
+ <Rectangle Fill="Transparent"/>
+ </ControlTemplate>
+ </Thumb.Template>
+ </Thumb>
+ </Grid>
+ </Grid>
+ </Grid>
+ </Border>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+</ResourceDictionary>
+
diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/TabsControl.cs b/Xamarin.Forms.Platform.WinRT.Tablet/TabsControl.cs
new file mode 100644
index 00000000..d98a27a0
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Tablet/TabsControl.cs
@@ -0,0 +1,50 @@
+using System;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ public class TabSelectedEventArgs
+ : EventArgs
+ {
+ public TabSelectedEventArgs(Page tab)
+ {
+ if (tab == null)
+ throw new ArgumentNullException("tab");
+
+ Tab = tab;
+ }
+
+ public Page Tab { get; private set; }
+ }
+
+ public class TabButton
+ : Windows.UI.Xaml.Controls.Button
+ {
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+ Click += OnClick;
+ }
+
+ void OnClick(object sender, RoutedEventArgs routedEventArgs)
+ {
+ var page = DataContext as Page;
+ if (page == null)
+ return;
+
+ var parent = page.RealParent as TabbedPage;
+ if (parent == null)
+ return;
+
+ var renderer = Platform.GetRenderer(parent) as TabbedPageRenderer;
+ if (renderer != null)
+ renderer.OnTabSelected(page);
+ }
+ }
+
+ public class TabsControl
+ : ItemsControl
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/WindowsPage.cs b/Xamarin.Forms.Platform.WinRT.Tablet/WindowsPage.cs
new file mode 100644
index 00000000..ba5cec09
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Tablet/WindowsPage.cs
@@ -0,0 +1,17 @@
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class WindowsPage : WindowsBasePage
+ {
+ protected override Platform CreatePlatform()
+ {
+ return new WindowsPlatform(this);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/WindowsPlatform.cs b/Xamarin.Forms.Platform.WinRT.Tablet/WindowsPlatform.cs
new file mode 100644
index 00000000..ce7e5fd7
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Tablet/WindowsPlatform.cs
@@ -0,0 +1,16 @@
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal sealed class WindowsPlatform : Platform
+ {
+ public WindowsPlatform(Windows.UI.Xaml.Controls.Page page) : base(page)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/WindowsPlatformServices.cs b/Xamarin.Forms.Platform.WinRT.Tablet/WindowsPlatformServices.cs
new file mode 100644
index 00000000..d729713d
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Tablet/WindowsPlatformServices.cs
@@ -0,0 +1,17 @@
+using Windows.UI.Core;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal class WindowsPlatformServices : WindowsBasePlatformServices
+ {
+ public WindowsPlatformServices(CoreDispatcher dispatcher) : base(dispatcher)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/WindowsResourcesProvider.cs b/Xamarin.Forms.Platform.WinRT.Tablet/WindowsResourcesProvider.cs
new file mode 100644
index 00000000..9c1351b0
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Tablet/WindowsResourcesProvider.cs
@@ -0,0 +1,82 @@
+using System;
+using Windows.UI.Text;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal sealed class WindowsResourcesProvider : ISystemResourcesProvider
+ {
+ public IResourceDictionary GetSystemResources()
+ {
+ Windows.UI.Xaml.ResourceDictionary windowsResources = Windows.UI.Xaml.Application.Current.Resources;
+
+ var resources = new ResourceDictionary();
+ resources[Device.Styles.TitleStyleKey] = GetStyle("HeaderTextBlockStyle");
+ resources[Device.Styles.SubtitleStyleKey] = GetStyle("SubheaderTextBlockStyle");
+ resources[Device.Styles.BodyStyleKey] = GetStyle("BodyTextBlockStyle");
+ resources[Device.Styles.CaptionStyleKey] = GetStyle("CaptionTextBlockStyle");
+#if WINDOWS_UWP
+ resources[Device.Styles.ListItemTextStyleKey] = GetStyle("BaseTextBlockStyle");
+#else
+ resources[Device.Styles.ListItemTextStyleKey] = GetStyle("TitleTextBlockStyle");
+#endif
+ resources[Device.Styles.ListItemDetailTextStyleKey] = GetStyle("BodyTextBlockStyle");
+ return resources;
+ }
+
+ Style GetStyle(object nativeKey)
+ {
+ var style = (Windows.UI.Xaml.Style)Windows.UI.Xaml.Application.Current.Resources[nativeKey];
+
+ var formsStyle = new Style(typeof(Label));
+ foreach (SetterBase b in style.Setters)
+ {
+ var setter = b as Windows.UI.Xaml.Setter;
+ if (setter == null)
+ continue;
+
+ // TODO: Need to implement a stealth pass-through for things we don't support
+
+ if (setter.Property == TextBlock.FontSizeProperty)
+ formsStyle.Setters.Add(Label.FontSizeProperty, setter.Value);
+ else if (setter.Property == TextBlock.FontFamilyProperty)
+ formsStyle.Setters.Add(Label.FontFamilyProperty, setter.Value);
+ else if (setter.Property == TextBlock.FontWeightProperty)
+ formsStyle.Setters.Add(Label.FontAttributesProperty, ToAttributes(Convert.ToUInt16(setter.Value)));
+ else if (setter.Property == TextBlock.TextWrappingProperty)
+ formsStyle.Setters.Add(Label.LineBreakModeProperty, ToLineBreakMode((TextWrapping)setter.Value));
+ }
+
+ return formsStyle;
+ }
+
+ static FontAttributes ToAttributes(ushort uweight)
+ {
+ if (uweight == FontWeights.Bold.Weight || uweight == FontWeights.SemiBold.Weight || uweight == FontWeights.ExtraBold.Weight)
+ return FontAttributes.Bold;
+
+ return FontAttributes.None;
+ }
+
+ static LineBreakMode ToLineBreakMode(TextWrapping value)
+ {
+ switch (value)
+ {
+ case TextWrapping.Wrap:
+ return LineBreakMode.CharacterWrap;
+ case TextWrapping.WrapWholeWords:
+ return LineBreakMode.WordWrap;
+ default:
+ case TextWrapping.NoWrap:
+ return LineBreakMode.NoWrap;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT.Tablet/Xamarin.Forms.Platform.WinRT.Tablet.csproj b/Xamarin.Forms.Platform.WinRT.Tablet/Xamarin.Forms.Platform.WinRT.Tablet.csproj
new file mode 100644
index 00000000..22c153f9
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT.Tablet/Xamarin.Forms.Platform.WinRT.Tablet.csproj
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Platform.WinRT</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Platform.WinRT.Tablet</AssemblyName>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <TargetPlatformVersion>8.1</TargetPlatformVersion>
+ <MinimumVisualStudioVersion>12</MinimumVisualStudioVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\ARM\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+ <OutputPath>bin\ARM\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>ARM</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x64\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ <OutputPath>bin\x64\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\x86\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>bin\x86\Release\</OutputPath>
+ <DefineConstants>TRACE;NETFX_CORE;WINDOWS_APP</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoWarn>;2008</NoWarn>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform.WinRT\Xamarin.Forms.Platform.WinRT.csproj">
+ <Project>{f3fdd7ac-8899-4e41-bfd7-ec83403e736d}</Project>
+ <Name>Xamarin.Forms.Platform.WinRT</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="Forms.cs" />
+ <Compile Include="FormsListViewItemPresenter.cs" />
+ <Compile Include="FormsSearchBox.cs" />
+ <Compile Include="SearchBarRenderer.cs" />
+ <Compile Include="TabbedPageRenderer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="TabsControl.cs" />
+ <Compile Include="WindowsPlatform.cs" />
+ <Compile Include="WindowsPage.cs" />
+ <Compile Include="WindowsPlatformServices.cs" />
+ <Compile Include="WindowsResourcesProvider.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Page Include="..\Xamarin.Forms.Platform.WinRT\Resources.xaml">
+ <Link>Resources.xaml</Link>
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="FormsTextBoxStyle.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="TabletResources.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Page>
+ </ItemGroup>
+ <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '12.0' ">
+ <VisualStudioVersion>12.0</VisualStudioVersion>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ActivityIndicatorRenderer.cs b/Xamarin.Forms.Platform.WinRT/ActivityIndicatorRenderer.cs
new file mode 100644
index 00000000..5c36afda
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ActivityIndicatorRenderer.cs
@@ -0,0 +1,68 @@
+using System.ComponentModel;
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class ActivityIndicatorRenderer : ViewRenderer<ActivityIndicator, Windows.UI.Xaml.Controls.ProgressBar>
+ {
+ object _foregroundDefault;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<ActivityIndicator> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new Windows.UI.Xaml.Controls.ProgressBar { IsIndeterminate = true });
+
+ Control.Loaded += OnControlLoaded;
+ }
+
+ // UpdateColor() called when loaded to ensure we can cache dynamic default colors
+ UpdateIsRunning();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == ActivityIndicator.IsRunningProperty.PropertyName)
+ UpdateIsRunning();
+ else if (e.PropertyName == ActivityIndicator.ColorProperty.PropertyName)
+ UpdateColor();
+ }
+
+ void OnControlLoaded(object sender, RoutedEventArgs routedEventArgs)
+ {
+ _foregroundDefault = Control.GetForegroundCache();
+ UpdateColor();
+ }
+
+ void UpdateColor()
+ {
+ Color color = Element.Color;
+ if (color.IsDefault)
+ {
+ Control.RestoreForegroundCache(_foregroundDefault);
+ }
+ else
+ {
+ Control.Foreground = color.ToBrush();
+ }
+ }
+
+ void UpdateIsRunning()
+ {
+ Opacity = Element.IsRunning ? 1 : 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/AlignmentExtensions.cs b/Xamarin.Forms.Platform.WinRT/AlignmentExtensions.cs
new file mode 100644
index 00000000..aa6f926a
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/AlignmentExtensions.cs
@@ -0,0 +1,39 @@
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal static class AlignmentExtensions
+ {
+ internal static Windows.UI.Xaml.TextAlignment ToNativeTextAlignment(this TextAlignment alignment)
+ {
+ switch (alignment)
+ {
+ case TextAlignment.Center:
+ return Windows.UI.Xaml.TextAlignment.Center;
+ case TextAlignment.End:
+ return Windows.UI.Xaml.TextAlignment.Right;
+ default:
+ return Windows.UI.Xaml.TextAlignment.Left;
+ }
+ }
+
+ internal static VerticalAlignment ToNativeVerticalAlignment(this TextAlignment alignment)
+ {
+ switch (alignment)
+ {
+ case TextAlignment.Center:
+ return VerticalAlignment.Center;
+ case TextAlignment.End:
+ return VerticalAlignment.Bottom;
+ default:
+ return VerticalAlignment.Top;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/AsyncValue.cs b/Xamarin.Forms.Platform.WinRT/AsyncValue.cs
new file mode 100644
index 00000000..4cfbb833
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/AsyncValue.cs
@@ -0,0 +1,95 @@
+//
+// AsyncValue.cs
+//
+// Author:
+// Eric Maupin <me@ermau.com>
+//
+// Copyright (c) 2013-2014 Xamarin, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Threading.Tasks;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal sealed class AsyncValue<T> : INotifyPropertyChanged
+ {
+ readonly T _defaultValue;
+ readonly Task<T> _valueTask;
+ bool _isRunning = true;
+
+ public AsyncValue(Task<T> valueTask, T defaultValue)
+ {
+ if (valueTask == null)
+ throw new ArgumentNullException("valueTask");
+
+ _valueTask = valueTask;
+ _defaultValue = defaultValue;
+
+ TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext();
+
+ _valueTask.ContinueWith(t => { IsRunning = false; }, scheduler);
+
+ _valueTask.ContinueWith(t => { OnPropertyChanged("Value"); }, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, scheduler);
+ }
+
+ public bool IsRunning
+ {
+ get { return _isRunning; }
+ set
+ {
+ if (_isRunning == value)
+ return;
+
+ _isRunning = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public T Value
+ {
+ get
+ {
+ if (_valueTask.Status != TaskStatus.RanToCompletion)
+ return _defaultValue;
+
+ return _valueTask.Result;
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/BackgroundTracker.cs b/Xamarin.Forms.Platform.WinRT/BackgroundTracker.cs
new file mode 100644
index 00000000..c7474015
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/BackgroundTracker.cs
@@ -0,0 +1,82 @@
+using System;
+using System.ComponentModel;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Media.Imaging;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal sealed class BackgroundTracker<T> : VisualElementTracker<Page, T> where T : FrameworkElement
+ {
+ readonly DependencyProperty _backgroundProperty;
+ bool _backgroundNeedsUpdate = true;
+
+ public BackgroundTracker(DependencyProperty backgroundProperty)
+ {
+ if (backgroundProperty == null)
+ throw new ArgumentNullException("backgroundProperty");
+
+ _backgroundProperty = backgroundProperty;
+ }
+
+ protected override void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName || e.PropertyName == Page.BackgroundImageProperty.PropertyName)
+ {
+ UpdateBackground();
+ }
+
+ base.OnPropertyChanged(sender, e);
+ }
+
+ protected override void UpdateNativeControl()
+ {
+ base.UpdateNativeControl();
+
+ if (_backgroundNeedsUpdate)
+ UpdateBackground();
+ }
+
+ void UpdateBackground()
+ {
+ if (Element == null)
+ return;
+
+ FrameworkElement element = Control ?? Container;
+ if (element == null)
+ return;
+
+ string backgroundImage = Element.BackgroundImage;
+ if (backgroundImage != null)
+ {
+ Uri uri;
+ if (!Uri.TryCreate(backgroundImage, UriKind.RelativeOrAbsolute, out uri) || !uri.IsAbsoluteUri)
+ uri = new Uri("ms-appx:///" + backgroundImage);
+
+ element.SetValue(_backgroundProperty, new ImageBrush { ImageSource = new BitmapImage(uri) });
+ }
+ else
+ {
+ Color backgroundColor = Element.BackgroundColor;
+ if (!backgroundColor.IsDefault)
+ {
+ element.SetValue(_backgroundProperty, backgroundColor.ToBrush());
+ }
+ else
+ {
+ object localBackground = element.ReadLocalValue(_backgroundProperty);
+ if (localBackground != null && localBackground != DependencyProperty.UnsetValue)
+ element.ClearValue(_backgroundProperty);
+ }
+ }
+
+ _backgroundNeedsUpdate = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/BoolToVisibilityConverter.cs b/Xamarin.Forms.Platform.WinRT/BoolToVisibilityConverter.cs
new file mode 100644
index 00000000..357cba3f
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/BoolToVisibilityConverter.cs
@@ -0,0 +1,30 @@
+using System;
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public sealed class BoolToVisibilityConverter : Windows.UI.Xaml.Data.IValueConverter
+ {
+ public bool FalseIsVisible { get; set; }
+
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ var v = (bool)value;
+ if (FalseIsVisible)
+ v = !v;
+
+ return v ? Visibility.Visible : Visibility.Collapsed;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/BoxViewRenderer.cs b/Xamarin.Forms.Platform.WinRT/BoxViewRenderer.cs
new file mode 100644
index 00000000..2e77c89d
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/BoxViewRenderer.cs
@@ -0,0 +1,31 @@
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Shapes;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class BoxViewRenderer : ViewRenderer<BoxView, Windows.UI.Xaml.Shapes.Rectangle>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var rect = new Windows.UI.Xaml.Shapes.Rectangle();
+ rect.DataContext = Element;
+ rect.SetBinding(Shape.FillProperty, new Windows.UI.Xaml.Data.Binding { Converter = new ColorConverter(), Path = new PropertyPath("Color") });
+
+ SetNativeControl(rect);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ButtonRenderer.cs b/Xamarin.Forms.Platform.WinRT/ButtonRenderer.cs
new file mode 100644
index 00000000..60ee6418
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ButtonRenderer.cs
@@ -0,0 +1,160 @@
+using System;
+using System.ComponentModel;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Media.Imaging;
+using WThickness = Windows.UI.Xaml.Thickness;
+using WButton = Windows.UI.Xaml.Controls.Button;
+using WImage = Windows.UI.Xaml.Controls.Image;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class ButtonRenderer : ViewRenderer<Button, FormsButton>
+ {
+ bool _fontApplied;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var button = new FormsButton();
+ button.Click += OnButtonClick;
+ SetNativeControl(button);
+ }
+
+ UpdateContent();
+
+ if (Element.BackgroundColor != Color.Default)
+ UpdateBackground();
+
+ if (Element.TextColor != Color.Default)
+ UpdateTextColor();
+
+ if (Element.BorderColor != Color.Default)
+ UpdateBorderColor();
+
+ if (Element.BorderWidth != 0)
+ UpdateBorderWidth();
+
+ if (Element.BorderRadius != (int)Button.BorderRadiusProperty.DefaultValue)
+ UpdateBorderRadius();
+
+ UpdateFont();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Button.TextProperty.PropertyName || e.PropertyName == Button.ImageProperty.PropertyName)
+ {
+ UpdateContent();
+ }
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ {
+ UpdateBackground();
+ }
+ else if (e.PropertyName == Button.TextColorProperty.PropertyName)
+ {
+ UpdateTextColor();
+ }
+ else if (e.PropertyName == Button.FontProperty.PropertyName)
+ {
+ UpdateFont();
+ }
+ else if (e.PropertyName == Button.BorderColorProperty.PropertyName)
+ {
+ UpdateBorderColor();
+ }
+ else if (e.PropertyName == Button.BorderWidthProperty.PropertyName)
+ {
+ UpdateBorderWidth();
+ }
+ else if (e.PropertyName == Button.BorderRadiusProperty.PropertyName)
+ {
+ UpdateBorderRadius();
+ }
+ }
+
+ void OnButtonClick(object sender, RoutedEventArgs e)
+ {
+ Button buttonView = Element;
+ if (buttonView != null)
+ ((IButtonController)buttonView).SendClicked();
+ }
+
+ void UpdateBackground()
+ {
+ Control.Background = Element.BackgroundColor != Color.Default ? Element.BackgroundColor.ToBrush() : (Brush)Windows.UI.Xaml.Application.Current.Resources["ButtonBackgroundThemeBrush"];
+ }
+
+ void UpdateBorderColor()
+ {
+ Control.BorderBrush = Element.BorderColor != Color.Default ? Element.BorderColor.ToBrush() : (Brush)Windows.UI.Xaml.Application.Current.Resources["ButtonBorderThemeBrush"];
+ }
+
+ void UpdateBorderRadius()
+ {
+ Control.BorderRadius = Element.BorderRadius;
+ }
+
+ void UpdateBorderWidth()
+ {
+ Control.BorderThickness = Element.BorderWidth == 0d ? new WThickness(3) : new WThickness(Element.BorderWidth);
+ }
+
+ void UpdateContent()
+ {
+ if (Element.Image != null)
+ {
+ var panel = new StackPanel { Orientation = Orientation.Horizontal };
+
+ var image = new WImage { Source = new BitmapImage(new Uri("ms-appx:///" + Element.Image.File)), Width = 30, Height = 30, Margin = new WThickness(0, 0, 20, 0) };
+ panel.Children.Add(image);
+ image.ImageOpened += (sender, args) => { ((IButtonController)Element).NativeSizeChanged(); };
+
+ if (Element.Text != null)
+ {
+ panel.Children.Add(new TextBlock { Text = Element.Text });
+ }
+
+ Control.Content = panel;
+ }
+ else
+ {
+ Control.Content = Element.Text;
+ }
+ }
+
+ void UpdateFont()
+ {
+ if (Control == null || Element == null)
+ return;
+
+ if (Element.Font == Font.Default && !_fontApplied)
+ return;
+
+ Font fontToApply = Element.Font == Font.Default ? Font.SystemFontOfSize(NamedSize.Medium) : Element.Font;
+
+ Control.ApplyFont(fontToApply);
+ _fontApplied = true;
+ }
+
+ void UpdateTextColor()
+ {
+ Control.Foreground = Element.TextColor != Color.Default ? Element.TextColor.ToBrush() : (Brush)Windows.UI.Xaml.Application.Current.Resources["DefaultTextForegroundThemeBrush"];
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/CarouselPageRenderer.cs b/Xamarin.Forms.Platform.WinRT/CarouselPageRenderer.cs
new file mode 100644
index 00000000..8b5e52b5
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/CarouselPageRenderer.cs
@@ -0,0 +1,180 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Automation;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class CarouselPageRenderer : FlipView, IVisualElementRenderer
+ {
+ bool _fromUpdate;
+ bool _disposed;
+
+ BackgroundTracker<FlipView> _tracker;
+
+ public CarouselPageRenderer()
+ {
+ VirtualizingStackPanel.SetVirtualizationMode(this, VirtualizationMode.Standard);
+ ItemTemplate = (Windows.UI.Xaml.DataTemplate)Windows.UI.Xaml.Application.Current.Resources["ContainedPageTemplate"];
+ SelectionChanged += OnSelectionChanged;
+ Loaded += OnLoaded;
+ Unloaded += OnUnloaded;
+ }
+
+ public CarouselPage Element { get; private set; }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ public FrameworkElement ContainerElement
+ {
+ get { return this; }
+ }
+
+ VisualElement IVisualElementRenderer.Element
+ {
+ get { return Element; }
+ }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ var constraint = new Windows.Foundation.Size(widthConstraint, heightConstraint);
+
+ double oldWidth = Width;
+ double oldHeight = Height;
+
+ Height = double.NaN;
+ Width = double.NaN;
+
+ Measure(constraint);
+ var result = new Size(Math.Ceiling(DesiredSize.Width), Math.Ceiling(DesiredSize.Height));
+
+ Width = oldWidth;
+ Height = oldHeight;
+
+ return new SizeRequest(result);
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ var newPage = element as CarouselPage;
+ if (element != null && newPage == null)
+ throw new ArgumentException("element must be a CarouselPage");
+
+ CarouselPage oldPage = Element;
+ Element = newPage;
+
+ if (oldPage != null)
+ {
+ oldPage.SendDisappearing();
+ ((INotifyCollectionChanged)oldPage.Children).CollectionChanged -= OnChildrenChanged;
+ oldPage.PropertyChanged -= OnElementPropertyChanged;
+ }
+
+ if (newPage != null)
+ {
+ if (_tracker == null)
+ {
+ _tracker = new BackgroundTracker<FlipView>(BackgroundProperty) { Control = this };
+ }
+
+ _tracker.Element = newPage;
+
+ for (var i = 0; i < newPage.Children.Count; i++)
+ Items.Add(newPage.Children[i]);
+
+ ((INotifyCollectionChanged)newPage.Children).CollectionChanged += OnChildrenChanged;
+ newPage.PropertyChanged += OnElementPropertyChanged;
+
+ UpdateCurrentPage();
+ newPage.SendAppearing();
+ }
+
+ OnElementChanged(new ElementChangedEventArgs<CarouselPage>(oldPage, newPage));
+
+ if (!string.IsNullOrEmpty(Element?.AutomationId))
+ SetValue(AutomationProperties.AutomationIdProperty, Element.AutomationId);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposing || _disposed)
+ return;
+
+ if (_tracker != null)
+ {
+ _tracker.Dispose();
+ _tracker = null;
+ }
+
+ _disposed = true;
+ Element?.SendDisappearing();
+ SetElement(null);
+ }
+
+ protected virtual void OnElementChanged(ElementChangedEventArgs<CarouselPage> e)
+ {
+ EventHandler<VisualElementChangedEventArgs> changed = ElementChanged;
+ if (changed != null)
+ changed(this, new VisualElementChangedEventArgs(e.OldElement, e.NewElement));
+ }
+
+ protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "CurrentPage")
+ {
+ UpdateCurrentPage();
+ }
+ }
+
+ void OnChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ e.Apply(Element.Children, Items);
+ }
+
+ void OnLoaded(object sender, RoutedEventArgs e)
+ {
+ Element?.SendAppearing();
+ }
+
+ void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (_fromUpdate)
+ return;
+
+ var page = (ContentPage)SelectedItem;
+ ContentPage currentPage = Element.CurrentPage;
+ if (currentPage == page)
+ return;
+ currentPage?.SendDisappearing();
+ Element.CurrentPage = page;
+ page?.SendAppearing();
+ }
+
+ void OnUnloaded(object sender, RoutedEventArgs e)
+ {
+ Element?.SendDisappearing();
+ }
+
+ void UpdateCurrentPage()
+ {
+ _fromUpdate = true;
+
+ SelectedItem = Element.CurrentPage;
+
+ _fromUpdate = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/CarouselViewRenderer.cs b/Xamarin.Forms.Platform.WinRT/CarouselViewRenderer.cs
new file mode 100644
index 00000000..3e1fd096
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/CarouselViewRenderer.cs
@@ -0,0 +1,220 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+using WFlipView = Windows.UI.Xaml.Controls.FlipView;
+using WBinding = Windows.UI.Xaml.Data.Binding;
+using WApp = Windows.UI.Xaml.Application;
+using WSize = Windows.Foundation.Size;
+using WDataTemplate = Windows.UI.Xaml.DataTemplate;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class CarouselViewRenderer : ViewRenderer<CarouselView, FrameworkElement>
+ {
+ WFlipView _flipView;
+
+ bool _leftAdd;
+
+ ICarouselViewController Controller
+ {
+ get { return Element; }
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<CarouselView> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ {
+ _flipView.SelectionChanged -= SelectionChanged;
+ _flipView.ItemsSource = null;
+ Element.CollectionChanged -= CollectionChanged;
+ }
+
+ if (e.NewElement != null)
+ {
+ if (_flipView == null)
+ {
+ _flipView = new FlipView { IsSynchronizedWithCurrentItem = false, ItemTemplate = (WDataTemplate)WApp.Current.Resources["ItemTemplate"] };
+ }
+
+ _flipView.ItemsSource = Element.ItemsSource;
+ _flipView.SelectedIndex = Element.Position;
+ _flipView.SelectionChanged += SelectionChanged;
+ Element.CollectionChanged += CollectionChanged;
+ }
+
+ if (_flipView != Control)
+ SetNativeControl(_flipView);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "Position" && _flipView.SelectedIndex != Element.Position)
+ {
+ if (!_leftAdd)
+ _flipView.SelectedIndex = Element.Position;
+ _leftAdd = false;
+ }
+
+ base.OnElementPropertyChanged(sender, e);
+ }
+
+ void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ Controller.SendSelectedPositionChanged(_flipView.SelectedIndex);
+
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ if (e.NewStartingIndex <= Element.Position)
+ {
+ _leftAdd = true;
+ int position = Element.Position + e.NewItems.Count;
+ PositionChanged(position);
+ }
+ break;
+
+ case NotifyCollectionChangedAction.Move:
+ break;
+
+ case NotifyCollectionChangedAction.Remove:
+ if (Element.Count == 0)
+ throw new InvalidOperationException("CarouselView must retain a least one item.");
+
+ if (e.OldStartingIndex < Element.Position)
+ PositionChanged(Element.Position - e.OldItems.Count);
+ break;
+
+ case NotifyCollectionChangedAction.Replace:
+ break;
+
+ case NotifyCollectionChangedAction.Reset:
+ break;
+
+ default:
+ throw new Exception($"Enum value '{(int)e.Action}' is not a member of NotifyCollectionChangedAction enumeration.");
+ }
+ }
+
+ void PositionChanged(int position)
+ {
+ if (!_leftAdd)
+ _flipView.SelectedIndex = position;
+ Element.Position = position;
+ Controller.SendSelectedPositionChanged(position);
+ }
+
+ void SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ object[] addedItems = e.AddedItems.ToArray();
+ object[] removedItems = e.RemovedItems.ToArray();
+
+ object addedItem = addedItems.SingleOrDefault();
+ if (addedItem != null)
+ {
+ PositionChanged(_flipView.SelectedIndex);
+ Controller.SendSelectedItemChanged(addedItems.Single());
+ }
+ }
+ }
+
+ public class ItemControl : ContentControl
+ {
+ CarouselView _carouselView;
+ object _item;
+ View _view;
+
+ public ItemControl()
+ {
+ DataContextChanged += OnDataContextChanged;
+ }
+
+ CarouselView CarouselView => LoadCarouselView();
+
+ IItemViewController Controller => CarouselView;
+
+ protected override WSize ArrangeOverride(WSize finalSize)
+ {
+ _view.Layout(new Rectangle(0, 0, CarouselView.Width, CarouselView.Height));
+ return base.ArrangeOverride(finalSize);
+ }
+
+ protected override WSize MeasureOverride(WSize availableSize)
+ {
+ LoadCarouselView();
+
+ if (_item != null)
+ {
+ SetDataContext(_item);
+ _item = null;
+ }
+
+ return base.MeasureOverride(availableSize);
+ }
+
+ CarouselView LoadCarouselView()
+ {
+ if (_carouselView != null)
+ return _carouselView;
+
+ DependencyObject parent = VisualTreeHelper.GetParent(this);
+ CarouselViewRenderer renderer = default(CarouselViewRenderer);
+
+ do
+ {
+ if (parent == null)
+ return null;
+
+ renderer = parent as CarouselViewRenderer;
+ if (renderer != null)
+ break;
+
+ parent = VisualTreeHelper.GetParent(parent);
+ } while (true);
+
+ _carouselView = renderer.Element;
+ return _carouselView;
+ }
+
+ void OnDataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
+ {
+ object item = args.NewValue;
+
+ if (_carouselView != null)
+ SetDataContext(item);
+
+ else if (item != null)
+ _item = item;
+ }
+
+ void SetDataContext(object item)
+ {
+ // type item
+ object type = Controller.GetItemType(item);
+
+ // activate item
+ _view = Controller.CreateView(type);
+ _view.Parent = CarouselView;
+ _view.Layout(new Rectangle(0, 0, CarouselView.Width, CarouselView.Height));
+
+ // render item
+ IVisualElementRenderer renderer = Platform.CreateRenderer(_view);
+ Platform.SetRenderer(_view, renderer);
+ Content = renderer;
+
+ // bind item
+ Controller.BindView(_view, item);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/CaseConverter.cs b/Xamarin.Forms.Platform.WinRT/CaseConverter.cs
new file mode 100644
index 00000000..7f8a9009
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/CaseConverter.cs
@@ -0,0 +1,29 @@
+using System;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class CaseConverter : Windows.UI.Xaml.Data.IValueConverter
+ {
+ public bool ConvertToUpper { get; set; }
+
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ if (value == null)
+ return null;
+
+ var v = (string)value;
+ return ConvertToUpper ? v.ToUpper() : v.ToLower();
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotSupportedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/CellControl.cs b/Xamarin.Forms.Platform.WinRT/CellControl.cs
new file mode 100644
index 00000000..a47c9646
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/CellControl.cs
@@ -0,0 +1,342 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using Windows.UI.Input;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class CellControl : ContentControl
+ {
+ public static readonly DependencyProperty CellProperty = DependencyProperty.Register("Cell", typeof(object), typeof(CellControl),
+ new PropertyMetadata(null, (o, e) => ((CellControl)o).SetSource((Cell)e.OldValue, (Cell)e.NewValue)));
+
+ public static readonly DependencyProperty IsGroupHeaderProperty = DependencyProperty.Register("IsGroupHeader", typeof(bool), typeof(CellControl), null);
+
+ internal static readonly BindableProperty MeasuredEstimateProperty = BindableProperty.Create("MeasuredEstimate", typeof(double), typeof(ListView), -1d);
+ readonly Lazy<ListView> _listView;
+ readonly PropertyChangedEventHandler _propertyChangedHandler;
+
+ IList<MenuItem> _contextActions;
+ Windows.UI.Xaml.DataTemplate _currentTemplate;
+ bool _isListViewRealized;
+ object _newValue;
+
+ public CellControl()
+ {
+ _listView = new Lazy<ListView>(GetListView);
+
+ DataContextChanged += OnDataContextChanged;
+
+ Unloaded += (sender, args) =>
+ {
+ Cell cell = Cell;
+ if (cell != null)
+ cell.SendDisappearing();
+ };
+
+ _propertyChangedHandler = OnCellPropertyChanged;
+ }
+
+ public Cell Cell
+ {
+ get { return (Cell)GetValue(CellProperty); }
+ set { SetValue(CellProperty, value); }
+ }
+
+ public bool IsGroupHeader
+ {
+ get { return (bool)GetValue(IsGroupHeaderProperty); }
+ set { SetValue(IsGroupHeaderProperty, value); }
+ }
+
+ protected FrameworkElement CellContent
+ {
+ get { return (FrameworkElement)Content; }
+ }
+
+ protected override Windows.Foundation.Size MeasureOverride(Windows.Foundation.Size availableSize)
+ {
+ ListView lv = _listView.Value;
+
+ // set the Cell now that we have a reference to the ListView, since it will have been skipped
+ // on DataContextChanged.
+ if (_newValue != null)
+ {
+ SetCell(_newValue);
+ _newValue = null;
+ }
+
+ if (Content == null)
+ {
+ if (lv != null)
+ {
+ if (lv.HasUnevenRows)
+ {
+ var estimate = (double)lv.GetValue(MeasuredEstimateProperty);
+ if (estimate > -1)
+ return new Windows.Foundation.Size(availableSize.Width, estimate);
+ }
+ else
+ {
+ double rowHeight = lv.RowHeight;
+ if (rowHeight > -1)
+ return new Windows.Foundation.Size(availableSize.Width, rowHeight);
+ }
+ }
+
+ return new Windows.Foundation.Size(0, 0);
+ }
+
+ // Children still need measure called on them
+ Windows.Foundation.Size result = base.MeasureOverride(availableSize);
+
+ if (lv != null)
+ {
+ lv.SetValue(MeasuredEstimateProperty, result.Height);
+ }
+
+ return result;
+ }
+
+ static string GetDisplayTextFromGroup(ListView lv, TemplatedItemsList<ItemsView<Cell>, Cell> group)
+ {
+ string displayBinding = null;
+
+ if (lv.GroupDisplayBinding != null)
+ displayBinding = group.Name;
+
+ if (lv.GroupShortNameBinding != null)
+ displayBinding = group.ShortName;
+
+ // TODO: what if they set both? should it default to the ShortName, like it will here?
+ // ShortNames binding did not appear to be functional before.
+ return displayBinding;
+ }
+
+ static TemplatedItemsList<ItemsView<Cell>, Cell> GetGroup(object newContext, ListView lv)
+ {
+ int groupIndex = lv.TemplatedItems.GetGlobalIndexOfGroup(newContext);
+ TemplatedItemsList<ItemsView<Cell>, Cell> group = lv.TemplatedItems.GetGroup(groupIndex);
+ return group;
+ }
+
+ ListView GetListView()
+ {
+ DependencyObject parent = VisualTreeHelper.GetParent(this);
+ while (parent != null)
+ {
+ var lv = parent as ListViewRenderer;
+ if (lv != null)
+ {
+ _isListViewRealized = true;
+ return lv.Element;
+ }
+
+ parent = VisualTreeHelper.GetParent(parent);
+ }
+
+ return null;
+ }
+
+ Windows.UI.Xaml.DataTemplate GetTemplate(Cell cell)
+ {
+ var renderer = Registrar.Registered.GetHandler<ICellRenderer>(cell.GetType());
+ return renderer.GetTemplate(cell);
+ }
+
+ void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "HasContextActions")
+ {
+ SetupContextMenu();
+ }
+ }
+
+ void OnClick(object sender, PointerRoutedEventArgs e)
+ {
+ PointerPoint point = e.GetCurrentPoint(CellContent);
+ if (point.Properties.PointerUpdateKind != PointerUpdateKind.RightButtonReleased)
+ return;
+
+ OpenContextMenu();
+ }
+
+ void OnContextActionsChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ var flyout = FlyoutBase.GetAttachedFlyout(CellContent) as MenuFlyout;
+ if (flyout != null)
+ {
+ flyout.Items.Clear();
+ SetupMenuItems(flyout);
+ }
+ }
+
+ void OnDataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
+ {
+ // We don't want to set the Cell until the ListView is realized, just in case the
+ // Cell has an ItemTemplate. Instead, we'll store the new data item, and it will be
+ // set on MeasureOverrideDelegate. However, if the parent is a TableView, we'll already
+ // have a complete Cell object to work with, so we can move ahead.
+ if (_isListViewRealized || args.NewValue is Cell)
+ SetCell(args.NewValue);
+ else if (args.NewValue != null)
+ _newValue = args.NewValue;
+ }
+
+ void OnLongTap(object sender, HoldingRoutedEventArgs e)
+ {
+ if (e.HoldingState == HoldingState.Started)
+ OpenContextMenu();
+ }
+
+ void OnOpenContext(object sender, RightTappedRoutedEventArgs e)
+ {
+ FlyoutBase.ShowAttachedFlyout(CellContent);
+ }
+
+ void OpenContextMenu()
+ {
+ if (FlyoutBase.GetAttachedFlyout(CellContent) == null)
+ {
+ var flyout = new MenuFlyout();
+ SetupMenuItems(flyout);
+
+ ((INotifyCollectionChanged)Cell.ContextActions).CollectionChanged += OnContextActionsChanged;
+
+ _contextActions = Cell.ContextActions;
+ FlyoutBase.SetAttachedFlyout(CellContent, flyout);
+ }
+
+ FlyoutBase.ShowAttachedFlyout(CellContent);
+ }
+
+ void SetCell(object newContext)
+ {
+ var cell = newContext as Cell;
+
+ if (ReferenceEquals(Cell?.BindingContext, newContext))
+ return;
+
+ // If there is a ListView, load the Cell content from the ItemTemplate.
+ // Otherwise, the given Cell is already a templated Cell from a TableView.
+ ListView lv = _listView.Value;
+ if (lv != null)
+ {
+ bool isGroupHeader = IsGroupHeader;
+ DataTemplate template = isGroupHeader ? lv.GroupHeaderTemplate : lv.ItemTemplate;
+
+ if (template is DataTemplateSelector)
+ {
+ template = ((DataTemplateSelector)template).SelectTemplate(newContext, lv);
+ }
+
+ if (template != null)
+ {
+ cell = template.CreateContent() as Cell;
+ cell.BindingContext = newContext;
+ }
+ else
+ {
+ string textContent = newContext.ToString();
+
+ if (isGroupHeader)
+ {
+ TemplatedItemsList<ItemsView<Cell>, Cell> group = GetGroup(newContext, lv);
+ textContent = GetDisplayTextFromGroup(lv, group);
+ }
+
+ cell = lv.CreateDefaultCell(textContent);
+ }
+
+ // A TableView cell should already have its parent,
+ // but we need to set the parent for a ListView cell.
+ cell.Parent = lv;
+
+ // This provides the Group Header styling (e.g., larger font, etc.) when the
+ // template is loaded later.
+ TemplatedItemsList<ItemsView<Cell>, Cell>.SetIsGroupHeader(cell, isGroupHeader);
+ }
+
+ Cell = cell;
+ }
+
+ void SetSource(Cell oldCell, Cell newCell)
+ {
+ if (oldCell != null)
+ {
+ oldCell.PropertyChanged -= _propertyChangedHandler;
+ oldCell.SendDisappearing();
+ }
+
+ if (newCell != null)
+ {
+ newCell.SendAppearing();
+
+ UpdateContent(newCell);
+ SetupContextMenu();
+
+ newCell.PropertyChanged += _propertyChangedHandler;
+ }
+ }
+
+ void SetupContextMenu()
+ {
+ if (CellContent == null || Cell == null)
+ return;
+
+ if (!Cell.HasContextActions)
+ {
+ CellContent.Holding -= OnLongTap;
+ CellContent.PointerReleased -= OnClick;
+ if (_contextActions != null)
+ {
+ ((INotifyCollectionChanged)_contextActions).CollectionChanged -= OnContextActionsChanged;
+ _contextActions = null;
+ }
+
+ FlyoutBase.SetAttachedFlyout(CellContent, null);
+ return;
+ }
+
+ CellContent.PointerReleased += OnClick;
+ CellContent.Holding += OnLongTap;
+ }
+
+ void SetupMenuItems(MenuFlyout flyout)
+ {
+ foreach (MenuItem item in Cell.ContextActions)
+ {
+ var flyoutItem = new MenuFlyoutItem();
+ flyoutItem.SetBinding(MenuFlyoutItem.TextProperty, "Text");
+ flyoutItem.Command = new MenuItemCommand(item);
+ flyoutItem.DataContext = item;
+
+ flyout.Items.Add(flyoutItem);
+ }
+ }
+
+ void UpdateContent(Cell newCell)
+ {
+ Windows.UI.Xaml.DataTemplate dt = GetTemplate(newCell);
+ if (dt != _currentTemplate || Content == null)
+ {
+ _currentTemplate = dt;
+ Content = dt.LoadContent();
+ }
+
+ ((FrameworkElement)Content).DataContext = newCell;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/CollapseWhenEmptyConverter.cs b/Xamarin.Forms.Platform.WinRT/CollapseWhenEmptyConverter.cs
new file mode 100644
index 00000000..311d315b
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/CollapseWhenEmptyConverter.cs
@@ -0,0 +1,33 @@
+using System;
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class CollapseWhenEmptyConverter : Windows.UI.Xaml.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ var length = 0;
+
+ var s = value as string;
+ if (s != null)
+ length = s.Length;
+
+ if (value is int)
+ length = (int)value;
+
+ return length > 0 ? Visibility.Visible : Visibility.Collapsed;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotSupportedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ColorConverter.cs b/Xamarin.Forms.Platform.WinRT/ColorConverter.cs
new file mode 100644
index 00000000..3866e435
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ColorConverter.cs
@@ -0,0 +1,30 @@
+using System;
+using Windows.UI;
+using Windows.UI.Xaml.Media;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public sealed class ColorConverter : Windows.UI.Xaml.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ var color = (Color)value;
+ var defaultColorKey = (string)parameter;
+
+ Brush defaultBrush = defaultColorKey != null ? (Brush)Windows.UI.Xaml.Application.Current.Resources[defaultColorKey] : new SolidColorBrush(Colors.Transparent);
+
+ return color == Color.Default ? defaultBrush : color.ToBrush();
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ConvertExtensions.cs b/Xamarin.Forms.Platform.WinRT/ConvertExtensions.cs
new file mode 100644
index 00000000..961c0422
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ConvertExtensions.cs
@@ -0,0 +1,23 @@
+using Windows.UI.Xaml.Media;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal static class ConvertExtensions
+ {
+ public static Brush ToBrush(this Color color)
+ {
+ return new SolidColorBrush(color.ToWindowsColor());
+ }
+
+ public static Windows.UI.Color ToWindowsColor(this Color color)
+ {
+ return Windows.UI.Color.FromArgb((byte)(color.A * 255), (byte)(color.R * 255), (byte)(color.G * 255), (byte)(color.B * 255));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/DatePickerRenderer.cs b/Xamarin.Forms.Platform.WinRT/DatePickerRenderer.cs
new file mode 100644
index 00000000..23f134f2
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/DatePickerRenderer.cs
@@ -0,0 +1,97 @@
+using System;
+using System.ComponentModel;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class DatePickerRenderer : ViewRenderer<DatePicker, FormsDatePicker>, IWrapperAware
+ {
+ public void NotifyWrapped()
+ {
+ if (Control != null)
+ {
+ Control.ForceInvalidate += PickerOnForceInvalidate;
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && Control != null)
+ {
+ Control.ForceInvalidate -= PickerOnForceInvalidate;
+ Control.DateChanged -= OnControlDateChanged;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
+ {
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var picker = new FormsDatePicker();
+ picker.DateChanged += OnControlDateChanged;
+ SetNativeControl(picker);
+ }
+
+ UpdateMinimumDate();
+ UpdateMaximumDate();
+ UpdateDate(e.NewElement.Date);
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == DatePicker.DateProperty.PropertyName)
+ UpdateDate(Element.Date);
+ else if (e.PropertyName == DatePicker.MaximumDateProperty.PropertyName)
+ UpdateMaximumDate();
+ else if (e.PropertyName == DatePicker.MinimumDateProperty.PropertyName)
+ UpdateMinimumDate();
+ }
+
+ void OnControlDateChanged(object sender, DatePickerValueChangedEventArgs e)
+ {
+ Element.Date = e.NewDate.Date;
+ DateTime currentDate = Element.Date;
+ if (currentDate != e.NewDate.Date) // Match coerced value
+ UpdateDate(currentDate);
+
+ Element.InvalidateMeasure(InvalidationTrigger.SizeRequestChanged);
+ }
+
+ void PickerOnForceInvalidate(object sender, EventArgs eventArgs)
+ {
+ Element?.InvalidateMeasure(InvalidationTrigger.SizeRequestChanged);
+ }
+
+ void UpdateDate(DateTime date)
+ {
+ Control.Date = date;
+ }
+
+ void UpdateMaximumDate()
+ {
+ DateTime maxdate = Element.MaximumDate;
+ Control.MaxYear = new DateTimeOffset(maxdate.Date);
+ }
+
+ void UpdateMinimumDate()
+ {
+ DateTime mindate = Element.MinimumDate;
+ Control.MinYear = new DateTimeOffset(mindate);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/DefaultRenderer.cs b/Xamarin.Forms.Platform.WinRT/DefaultRenderer.cs
new file mode 100644
index 00000000..8f08dfa8
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/DefaultRenderer.cs
@@ -0,0 +1,14 @@
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal sealed class DefaultRenderer : ViewRenderer<View, FrameworkElement>
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/EditorRenderer.cs b/Xamarin.Forms.Platform.WinRT/EditorRenderer.cs
new file mode 100644
index 00000000..d6236871
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/EditorRenderer.cs
@@ -0,0 +1,155 @@
+using System.ComponentModel;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class EditorRenderer : ViewRenderer<Editor, TextBox>
+ {
+ bool _fontApplied;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
+ {
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var textBox = new TextBox { AcceptsReturn = true, TextWrapping = TextWrapping.Wrap };
+
+ textBox.TextChanged += OnNativeTextChanged;
+ textBox.LostFocus += OnLostFocus;
+
+ SetNativeControl(textBox);
+ }
+
+ UpdateText();
+ UpdateInputScope();
+ UpdateTextColor();
+ UpdateFont();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Editor.TextColorProperty.PropertyName)
+ {
+ UpdateTextColor();
+ }
+ else if (e.PropertyName == Editor.FontAttributesProperty.PropertyName)
+ {
+ UpdateFont();
+ }
+ else if (e.PropertyName == Editor.FontFamilyProperty.PropertyName)
+ {
+ UpdateFont();
+ }
+ else if (e.PropertyName == Editor.FontSizeProperty.PropertyName)
+ {
+ UpdateFont();
+ }
+ else if (e.PropertyName == Editor.TextProperty.PropertyName)
+ {
+ UpdateText();
+ }
+
+ base.OnElementPropertyChanged(sender, e);
+ }
+
+ void OnLostFocus(object sender, RoutedEventArgs e)
+ {
+ Element?.SendCompleted();
+ }
+
+ void OnNativeTextChanged(object sender, Windows.UI.Xaml.Controls.TextChangedEventArgs args)
+ {
+ Element?.SetValueCore(Editor.TextProperty, Control.Text);
+ }
+
+ void UpdateFont()
+ {
+ if (Control == null)
+ return;
+
+ Editor editor = Element;
+
+ if (editor == null)
+ return;
+
+ bool editorIsDefault = editor.FontFamily == null && editor.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(Editor), true) && editor.FontAttributes == FontAttributes.None;
+
+ if (editorIsDefault && !_fontApplied)
+ return;
+
+ if (editorIsDefault)
+ {
+ // ReSharper disable AccessToStaticMemberViaDerivedType
+ // Resharper wants to simplify 'TextBox' to 'Control', but then it'll conflict with the property 'Control'
+ Control.ClearValue(TextBox.FontStyleProperty);
+ Control.ClearValue(TextBox.FontSizeProperty);
+ Control.ClearValue(TextBox.FontFamilyProperty);
+ Control.ClearValue(TextBox.FontWeightProperty);
+ Control.ClearValue(TextBox.FontStretchProperty);
+ // ReSharper restore AccessToStaticMemberViaDerivedType
+ }
+ else
+ {
+ Control.ApplyFont(editor);
+ }
+
+ _fontApplied = true;
+ }
+
+ void UpdateInputScope()
+ {
+ var custom = Element.Keyboard as CustomKeyboard;
+ if (custom != null)
+ {
+ Control.IsTextPredictionEnabled = (custom.Flags & KeyboardFlags.Suggestions) != 0;
+ Control.IsSpellCheckEnabled = (custom.Flags & KeyboardFlags.Spellcheck) != 0;
+ }
+ else
+ {
+ Control.ClearValue(TextBox.IsTextPredictionEnabledProperty);
+ Control.ClearValue(TextBox.IsSpellCheckEnabledProperty);
+ }
+
+ Control.InputScope = Element.Keyboard.ToInputScope();
+ }
+
+ void UpdateText()
+ {
+ string newText = Element.Text ?? "";
+
+ if (Control.Text == newText)
+ {
+ return;
+ }
+
+ Control.Text = newText;
+ Control.SelectionStart = Control.Text.Length;
+ }
+
+ void UpdateTextColor()
+ {
+ Color textColor = Element.TextColor;
+
+ if (textColor.IsDefault || !Element.IsEnabled)
+ {
+ // ReSharper disable once AccessToStaticMemberViaDerivedType
+ Control.ClearValue(TextBox.ForegroundProperty);
+ }
+ else
+ {
+ Control.Foreground = textColor.ToBrush();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/EntryCellTextBox.cs b/Xamarin.Forms.Platform.WinRT/EntryCellTextBox.cs
new file mode 100644
index 00000000..e280e18a
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/EntryCellTextBox.cs
@@ -0,0 +1,30 @@
+using Windows.System;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Input;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class EntryCellTextBox : TextBox
+ {
+ protected override void OnKeyUp(KeyRoutedEventArgs e)
+ {
+ if (e.Key == VirtualKey.Enter)
+ {
+ var cell = DataContext as EntryCell;
+ if (cell != null)
+ {
+ cell.SendCompleted();
+ e.Handled = true;
+ }
+ }
+
+ base.OnKeyUp(e);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/EntryRenderer.cs b/Xamarin.Forms.Platform.WinRT/EntryRenderer.cs
new file mode 100644
index 00000000..f02abe3c
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/EntryRenderer.cs
@@ -0,0 +1,212 @@
+using System.ComponentModel;
+using Windows.System;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class EntryRenderer : ViewRenderer<Entry, FormsTextBox>
+ {
+ Brush _backgroundColorFocusedDefaultBrush;
+
+ bool _fontApplied;
+ Brush _placeholderDefaultBrush;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var textBox = new FormsTextBox { Style = Windows.UI.Xaml.Application.Current.Resources["FormsTextBoxStyle"] as Windows.UI.Xaml.Style };
+
+ textBox.TextChanged += OnNativeTextChanged;
+ textBox.KeyUp += TextBoxOnKeyUp;
+ SetNativeControl(textBox);
+ }
+
+ UpdateIsPassword();
+ UpdateText();
+ UpdatePlaceholder();
+ UpdateTextColor();
+ UpdateFont();
+ UpdateInputScope();
+ UpdateAlignment();
+ UpdatePlaceholderColor();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Entry.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Entry.IsPasswordProperty.PropertyName)
+ UpdateIsPassword();
+ else if (e.PropertyName == Entry.PlaceholderProperty.PropertyName)
+ UpdatePlaceholder();
+ else if (e.PropertyName == Entry.TextColorProperty.PropertyName)
+ UpdateTextColor();
+ else if (e.PropertyName == InputView.KeyboardProperty.PropertyName)
+ UpdateInputScope();
+ else if (e.PropertyName == Entry.FontAttributesProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Entry.FontFamilyProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Entry.FontSizeProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Entry.HorizontalTextAlignmentProperty.PropertyName)
+ UpdateAlignment();
+ else if (e.PropertyName == Entry.PlaceholderColorProperty.PropertyName)
+ UpdatePlaceholderColor();
+ }
+
+ protected override void UpdateBackgroundColor()
+ {
+ base.UpdateBackgroundColor();
+
+ if (Control == null)
+ {
+ return;
+ }
+
+ // By default some platforms have alternate default background colors when focused
+ Color backgroundColor = Element.BackgroundColor;
+ if (backgroundColor.IsDefault)
+ {
+ if (_backgroundColorFocusedDefaultBrush == null)
+ {
+ return;
+ }
+
+ Control.BackgroundFocusBrush = _backgroundColorFocusedDefaultBrush;
+ return;
+ }
+
+ if (_backgroundColorFocusedDefaultBrush == null)
+ {
+ _backgroundColorFocusedDefaultBrush = Control.BackgroundFocusBrush;
+ }
+
+ Control.BackgroundFocusBrush = backgroundColor.ToBrush();
+ }
+
+ void OnNativeTextChanged(object sender, Windows.UI.Xaml.Controls.TextChangedEventArgs args)
+ {
+ Element.SetValueCore(Entry.TextProperty, Control.Text);
+ }
+
+ void TextBoxOnKeyUp(object sender, KeyRoutedEventArgs args)
+ {
+ if (args.Key != VirtualKey.Enter)
+ return;
+
+ Element.SendCompleted();
+ }
+
+ void UpdateAlignment()
+ {
+ Control.TextAlignment = Element.HorizontalTextAlignment.ToNativeTextAlignment();
+ }
+
+ void UpdateFont()
+ {
+ if (Control == null)
+ return;
+
+ Entry entry = Element;
+
+ if (entry == null)
+ return;
+
+ bool entryIsDefault = entry.FontFamily == null && entry.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(Entry), true) && entry.FontAttributes == FontAttributes.None;
+
+ if (entryIsDefault && !_fontApplied)
+ return;
+
+ if (entryIsDefault)
+ {
+ // ReSharper disable AccessToStaticMemberViaDerivedType
+ // Resharper wants to simplify 'FormsTextBox' to 'Control', but then it'll conflict with the property 'Control'
+ Control.ClearValue(FormsTextBox.FontStyleProperty);
+ Control.ClearValue(FormsTextBox.FontSizeProperty);
+ Control.ClearValue(FormsTextBox.FontFamilyProperty);
+ Control.ClearValue(FormsTextBox.FontWeightProperty);
+ Control.ClearValue(FormsTextBox.FontStretchProperty);
+ // ReSharper restore AccessToStaticMemberViaDerivedType
+ }
+ else
+ {
+ Control.ApplyFont(entry);
+ }
+
+ _fontApplied = true;
+ }
+
+ void UpdateInputScope()
+ {
+ var custom = Element.Keyboard as CustomKeyboard;
+ if (custom != null)
+ {
+ Control.IsTextPredictionEnabled = (custom.Flags & KeyboardFlags.Suggestions) != 0;
+ Control.IsSpellCheckEnabled = (custom.Flags & KeyboardFlags.Spellcheck) != 0;
+ }
+
+ Control.InputScope = Element.Keyboard.ToInputScope();
+ }
+
+ void UpdateIsPassword()
+ {
+ Control.IsPassword = Element.IsPassword;
+ }
+
+ void UpdatePlaceholder()
+ {
+ Control.PlaceholderText = Element.Placeholder ?? "";
+ }
+
+ void UpdatePlaceholderColor()
+ {
+ Color placeholderColor = Element.PlaceholderColor;
+
+ if (placeholderColor.IsDefault)
+ {
+ if (_placeholderDefaultBrush == null)
+ {
+ return;
+ }
+
+ // Use the cached default brush
+ Control.PlaceholderForegroundBrush = _placeholderDefaultBrush;
+ return;
+ }
+
+ if (_placeholderDefaultBrush == null)
+ {
+ // Cache the default brush in case we need to set the color back to default
+ _placeholderDefaultBrush = Control.PlaceholderForegroundBrush;
+ }
+
+ Control.PlaceholderForegroundBrush = placeholderColor.ToBrush();
+ }
+
+ void UpdateText()
+ {
+ Control.Text = Element.Text ?? "";
+ }
+
+ void UpdateTextColor()
+ {
+ Control.Foreground = Element.TextColor.ToBrush();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ExportRendererAttribute.cs b/Xamarin.Forms.Platform.WinRT/ExportRendererAttribute.cs
new file mode 100644
index 00000000..650ec0de
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ExportRendererAttribute.cs
@@ -0,0 +1,34 @@
+using System;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class ExportRendererAttribute : HandlerAttribute
+ {
+ public ExportRendererAttribute(Type handler, Type target) : base(handler, target)
+ {
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class ExportCellAttribute : HandlerAttribute
+ {
+ public ExportCellAttribute(Type handler, Type target) : base(handler, target)
+ {
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class ExportImageSourceHandlerAttribute : HandlerAttribute
+ {
+ public ExportImageSourceHandlerAttribute(Type handler, Type target) : base(handler, target)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/Extensions.cs b/Xamarin.Forms.Platform.WinRT/Extensions.cs
new file mode 100644
index 00000000..3d4431f1
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/Extensions.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Runtime.CompilerServices;
+using Windows.Foundation;
+using Windows.UI;
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal static class Extensions
+ {
+ public static ConfiguredTaskAwaitable<T> DontSync<T>(this IAsyncOperation<T> self)
+ {
+ return self.AsTask().ConfigureAwait(false);
+ }
+
+ public static ConfiguredTaskAwaitable DontSync(this IAsyncAction self)
+ {
+ return self.AsTask().ConfigureAwait(false);
+ }
+
+ public static Windows.UI.Color GetIdealForegroundForBackgroundColor(this Windows.UI.Color backgroundColor)
+ {
+ var nThreshold = 105;
+ int bgLuminance = Convert.ToInt32(backgroundColor.R * 0.2 + backgroundColor.G * 0.7 + backgroundColor.B * 0.1);
+
+ Windows.UI.Color foregroundColor = 255 - bgLuminance < nThreshold ? Colors.Black : Colors.White;
+ return foregroundColor;
+ }
+
+ public static void SetBinding(this FrameworkElement self, DependencyProperty property, string path)
+ {
+ self.SetBinding(property, new Windows.UI.Xaml.Data.Binding { Path = new PropertyPath(path) });
+ }
+
+ public static void SetBinding(this FrameworkElement self, DependencyProperty property, string path, Windows.UI.Xaml.Data.IValueConverter converter)
+ {
+ self.SetBinding(property, new Windows.UI.Xaml.Data.Binding { Path = new PropertyPath(path), Converter = converter });
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/FileImageSourceHandler.cs b/Xamarin.Forms.Platform.WinRT/FileImageSourceHandler.cs
new file mode 100644
index 00000000..c9c6f16b
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/FileImageSourceHandler.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Windows.UI.Xaml.Media.Imaging;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public sealed class FileImageSourceHandler : IImageSourceHandler
+ {
+ public Task<Windows.UI.Xaml.Media.ImageSource> LoadImageAsync(ImageSource imagesoure, CancellationToken cancellationToken = new CancellationToken())
+ {
+ Windows.UI.Xaml.Media.ImageSource image = null;
+ var filesource = imagesoure as FileImageSource;
+ if (filesource != null)
+ {
+ string file = filesource.File;
+ image = new BitmapImage(new Uri("ms-appx:///" + file));
+ }
+
+ return Task.FromResult(image);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/FileImageSourcePathConverter.cs b/Xamarin.Forms.Platform.WinRT/FileImageSourcePathConverter.cs
new file mode 100644
index 00000000..64468f5e
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/FileImageSourcePathConverter.cs
@@ -0,0 +1,26 @@
+using System;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal class FileImageSourcePathConverter : Windows.UI.Xaml.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ var source = (FileImageSource)value;
+ string uri = "ms-appx:///" + (source != null ? source.File : string.Empty);
+ return new BitmapIcon { UriSource = new Uri(uri) };
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/FontExtensions.cs b/Xamarin.Forms.Platform.WinRT/FontExtensions.cs
new file mode 100644
index 00000000..efab6118
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/FontExtensions.cs
@@ -0,0 +1,75 @@
+using System;
+using Windows.UI.Text;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Documents;
+using Windows.UI.Xaml.Media;
+using WApplication = Windows.UI.Xaml.Application;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public static class FontExtensions
+ {
+ public static void ApplyFont(this Control self, Font font)
+ {
+ self.FontSize = font.UseNamedSize ? font.NamedSize.GetFontSize() : font.FontSize;
+ self.FontFamily = !string.IsNullOrEmpty(font.FontFamily) ? new FontFamily(font.FontFamily) : (FontFamily)WApplication.Current.Resources["ContentControlThemeFontFamily"];
+ self.FontStyle = font.FontAttributes.HasFlag(FontAttributes.Italic) ? FontStyle.Italic : FontStyle.Normal;
+ self.FontWeight = font.FontAttributes.HasFlag(FontAttributes.Bold) ? FontWeights.Bold : FontWeights.Normal;
+ }
+
+ public static void ApplyFont(this TextBlock self, Font font)
+ {
+ self.FontSize = font.UseNamedSize ? font.NamedSize.GetFontSize() : font.FontSize;
+ self.FontFamily = !string.IsNullOrEmpty(font.FontFamily) ? new FontFamily(font.FontFamily) : (FontFamily)WApplication.Current.Resources["ContentControlThemeFontFamily"];
+ self.FontStyle = font.FontAttributes.HasFlag(FontAttributes.Italic) ? FontStyle.Italic : FontStyle.Normal;
+ self.FontWeight = font.FontAttributes.HasFlag(FontAttributes.Bold) ? FontWeights.Bold : FontWeights.Normal;
+ }
+
+ public static void ApplyFont(this TextElement self, Font font)
+ {
+ self.FontSize = font.UseNamedSize ? font.NamedSize.GetFontSize() : font.FontSize;
+ self.FontFamily = !string.IsNullOrEmpty(font.FontFamily) ? new FontFamily(font.FontFamily) : (FontFamily)WApplication.Current.Resources["ContentControlThemeFontFamily"];
+ self.FontStyle = font.FontAttributes.HasFlag(FontAttributes.Italic) ? FontStyle.Italic : FontStyle.Normal;
+ self.FontWeight = font.FontAttributes.HasFlag(FontAttributes.Bold) ? FontWeights.Bold : FontWeights.Normal;
+ }
+
+ internal static void ApplyFont(this Control self, IFontElement element)
+ {
+ self.FontSize = element.FontSize;
+ self.FontFamily = !string.IsNullOrEmpty(element.FontFamily) ? new FontFamily(element.FontFamily) : (FontFamily)WApplication.Current.Resources["ContentControlThemeFontFamily"];
+ self.FontStyle = element.FontAttributes.HasFlag(FontAttributes.Italic) ? FontStyle.Italic : FontStyle.Normal;
+ self.FontWeight = element.FontAttributes.HasFlag(FontAttributes.Bold) ? FontWeights.Bold : FontWeights.Normal;
+ }
+
+ internal static double GetFontSize(this NamedSize size)
+ {
+ // These are values pulled from the mapped sizes on Windows Phone, WinRT has no equivalent sizes, only intents.
+ switch (size)
+ {
+ case NamedSize.Default:
+ return (double)WApplication.Current.Resources["ControlContentThemeFontSize"];
+ case NamedSize.Micro:
+ return 18.667 - 3;
+ case NamedSize.Small:
+ return 18.667;
+ case NamedSize.Medium:
+ return 22.667;
+ case NamedSize.Large:
+ return 32;
+ default:
+ throw new ArgumentOutOfRangeException("size");
+ }
+ }
+
+ internal static bool IsDefault(this IFontElement self)
+ {
+ return self.FontFamily == null && self.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(Label), true) && self.FontAttributes == FontAttributes.None;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/FormsButton.cs b/Xamarin.Forms.Platform.WinRT/FormsButton.cs
new file mode 100644
index 00000000..73c2f922
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/FormsButton.cs
@@ -0,0 +1,46 @@
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class FormsButton : Windows.UI.Xaml.Controls.Button
+ {
+ public static readonly DependencyProperty BorderRadiusProperty = DependencyProperty.Register("BorderRadius", typeof(int), typeof(FormsButton),
+ new PropertyMetadata(default(int), OnBorderRadiusChanged));
+
+ Border _border;
+
+ public int BorderRadius
+ {
+ get { return (int)GetValue(BorderRadiusProperty); }
+ set { SetValue(BorderRadiusProperty, value); }
+ }
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ _border = GetTemplateChild("Border") as Border;
+ UpdateBorderRadius();
+ }
+
+ static void OnBorderRadiusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ ((FormsButton)d).UpdateBorderRadius();
+ }
+
+ void UpdateBorderRadius()
+ {
+ if (_border == null)
+ return;
+
+ _border.CornerRadius = new CornerRadius(BorderRadius);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/FormsComboBox.cs b/Xamarin.Forms.Platform.WinRT/FormsComboBox.cs
new file mode 100644
index 00000000..f693c942
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/FormsComboBox.cs
@@ -0,0 +1,68 @@
+using System;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media.Animation;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class FormsComboBox : ComboBox
+ {
+ internal bool IsClosingAnimated { get; private set; }
+
+ internal bool IsFullScreen => Device.Idiom == TargetIdiom.Phone && Items != null && Items.Count > 5;
+
+ internal bool IsOpeningAnimated { get; private set; }
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ if (Device.Idiom == TargetIdiom.Phone)
+ {
+ // If we're running on the phone, we have to give the PickerRenderer hooks
+ // into the opening and closing animations so it can handle them smoothly
+ // and measure at the appropriate times
+
+ var openedState = GetTemplateChild("Opened") as VisualState;
+ if (openedState != null)
+ {
+ openedState.Storyboard.Completed += (sender, o) => OnOpenAnimationCompleted();
+ IsOpeningAnimated = true;
+ }
+
+ var closedState = GetTemplateChild("Closed") as VisualState;
+
+ // On the phone, this is a dummy animation we've added to the closed state in the VSM
+ // Since it finishes immediately, we can use its Completed event to signal that the
+ // closing animation has started
+ var closedSignalAnimation = closedState?.Storyboard.Children[0] as DoubleAnimation;
+
+ if (closedSignalAnimation != null)
+ {
+ closedSignalAnimation.Completed += (sender, o) => OnClosedAnimationStarted();
+ IsClosingAnimated = true;
+ }
+ }
+ }
+
+ protected virtual void OnClosedAnimationStarted()
+ {
+ ClosedAnimationStarted?.Invoke(this, EventArgs.Empty);
+ }
+
+ protected virtual void OnOpenAnimationCompleted()
+ {
+ OpenAnimationCompleted?.Invoke(this, EventArgs.Empty);
+ }
+
+ internal event EventHandler<EventArgs> ClosedAnimationStarted;
+
+ internal event EventHandler<EventArgs> OpenAnimationCompleted;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/FormsDatePicker.cs b/Xamarin.Forms.Platform.WinRT/FormsDatePicker.cs
new file mode 100644
index 00000000..44127423
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/FormsDatePicker.cs
@@ -0,0 +1,76 @@
+using System;
+using Windows.UI.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class FormsDatePicker : Windows.UI.Xaml.Controls.DatePicker
+ {
+ public FormsDatePicker()
+ {
+ if (Device.Idiom == TargetIdiom.Desktop || Device.Idiom == TargetIdiom.Tablet)
+ {
+ Loaded += (sender, args) => { Window.Current.Activated += WindowOnActivated; };
+ Unloaded += (sender, args) => { Window.Current.Activated -= WindowOnActivated; };
+ }
+ }
+
+ public event EventHandler<EventArgs> ForceInvalidate;
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ if (Device.Idiom == TargetIdiom.Desktop || Device.Idiom == TargetIdiom.Tablet)
+ {
+ // Look for the combo boxes which make up a DatePicker on Windows 8.1
+ // So we can hook into their closed events and invalidate them if necessary
+
+ var dayPicker = GetTemplateChild("DayPicker") as ComboBox;
+ if (dayPicker != null)
+ {
+ dayPicker.DropDownClosed += PickerOnDropDownClosed;
+ }
+
+ var monthPicker = GetTemplateChild("MonthPicker") as ComboBox;
+ if (monthPicker != null)
+ {
+ monthPicker.DropDownClosed += PickerOnDropDownClosed;
+ }
+
+ var yearPicker = GetTemplateChild("YearPicker") as ComboBox;
+ if (yearPicker != null)
+ {
+ yearPicker.DropDownClosed += PickerOnDropDownClosed;
+ }
+ }
+ }
+
+ void PickerOnDropDownClosed(object sender, object o)
+ {
+ // If the DatePicker is in a TableView or ListView and the user
+ // opens one of the dropdowns but does not actually change the value,
+ // when the dropdown closes, the selected value will go blank
+ // To fix this, we have to invalidate the control
+ // This only applies to Windows 8.1
+ ForceInvalidate?.Invoke(this, EventArgs.Empty);
+ }
+
+ void WindowOnActivated(object sender, WindowActivatedEventArgs windowActivatedEventArgs)
+ {
+ // If the DatePicker is in a TableView or ListView, when the application loses and then regains focus
+ // the TextBlock/ComboBox controls (UWP and 8.1, respectively) which display its selected value
+ // will go blank.
+ // To fix this, we have to signal the renderer to invalidate if
+ // Window.Activated occurs.
+ ForceInvalidate?.Invoke(this, EventArgs.Empty);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/FormsTextBox.cs b/Xamarin.Forms.Platform.WinRT/FormsTextBox.cs
new file mode 100644
index 00000000..03725cd8
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/FormsTextBox.cs
@@ -0,0 +1,332 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Windows.UI.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ /// <summary>
+ /// An intermediate class for injecting bindings for things the default
+ /// textbox doesn't allow us to bind/modify
+ /// </summary>
+ public class FormsTextBox : TextBox
+ {
+ const char ObfuscationCharacter = '●';
+
+ public static readonly DependencyProperty PlaceholderForegroundBrushProperty = DependencyProperty.Register("PlaceholderForegroundBrush", typeof(Brush), typeof(FormsTextBox),
+ new PropertyMetadata(default(Brush)));
+
+ public static readonly DependencyProperty PlaceholderForegroundFocusBrushProperty = DependencyProperty.Register("PlaceholderForegroundFocusBrush", typeof(Brush), typeof(FormsTextBox),
+ new PropertyMetadata(default(Brush)));
+
+ public static readonly DependencyProperty ForegroundFocusBrushProperty = DependencyProperty.Register("ForegroundFocusBrush", typeof(Brush), typeof(FormsTextBox), new PropertyMetadata(default(Brush)));
+
+ public static readonly DependencyProperty BackgroundFocusBrushProperty = DependencyProperty.Register("BackgroundFocusBrush", typeof(Brush), typeof(FormsTextBox), new PropertyMetadata(default(Brush)));
+
+ public static readonly DependencyProperty IsPasswordProperty = DependencyProperty.Register("IsPassword", typeof(bool), typeof(FormsTextBox), new PropertyMetadata(default(bool), OnIsPasswordChanged));
+
+ public new static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(FormsTextBox), new PropertyMetadata("", TextPropertyChanged));
+
+ static InputScope s_passwordInputScope;
+ Border _borderElement;
+ InputScope _cachedInputScope;
+ bool _cachedPredictionsSetting;
+ bool _cachedSpellCheckSetting;
+ CancellationTokenSource _cts;
+ bool _internalChangeFlag;
+
+ public FormsTextBox()
+ {
+ TextChanged += OnTextChanged;
+ SelectionChanged += OnSelectionChanged;
+ }
+
+ public Brush BackgroundFocusBrush
+ {
+ get { return (Brush)GetValue(BackgroundFocusBrushProperty); }
+ set { SetValue(BackgroundFocusBrushProperty, value); }
+ }
+
+ public Brush ForegroundFocusBrush
+ {
+ get { return (Brush)GetValue(ForegroundFocusBrushProperty); }
+ set { SetValue(ForegroundFocusBrushProperty, value); }
+ }
+
+ public bool IsPassword
+ {
+ get { return (bool)GetValue(IsPasswordProperty); }
+ set { SetValue(IsPasswordProperty, value); }
+ }
+
+ public Brush PlaceholderForegroundBrush
+ {
+ get { return (Brush)GetValue(PlaceholderForegroundBrushProperty); }
+ set { SetValue(PlaceholderForegroundBrushProperty, value); }
+ }
+
+ public Brush PlaceholderForegroundFocusBrush
+ {
+ get { return (Brush)GetValue(PlaceholderForegroundFocusBrushProperty); }
+ set { SetValue(PlaceholderForegroundFocusBrushProperty, value); }
+ }
+
+ public new string Text
+ {
+ get { return (string)GetValue(TextProperty); }
+ set { SetValue(TextProperty, value); }
+ }
+
+ static InputScope PasswordInputScope
+ {
+ get
+ {
+ if (s_passwordInputScope != null)
+ {
+ return s_passwordInputScope;
+ }
+
+ s_passwordInputScope = new InputScope();
+ var name = new InputScopeName { NameValue = InputScopeNameValue.Default };
+ s_passwordInputScope.Names.Add(name);
+
+ return s_passwordInputScope;
+ }
+ }
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ if (Device.Idiom == TargetIdiom.Phone)
+ {
+ // If we're on the phone, we need to grab this from the template
+ // so we can manually handle it's background when focused
+ _borderElement = (Border)GetTemplateChild("BorderElement");
+ }
+ }
+
+ protected override void OnGotFocus(RoutedEventArgs e)
+ {
+ base.OnGotFocus(e);
+
+ // If we're on the phone, the Visual State Manager crashes if we try to
+ // handle alternate background colors in the focus state; we have to do
+ // it manually here
+ if (Device.Idiom == TargetIdiom.Phone && _borderElement != null)
+ {
+ _borderElement.Background = BackgroundFocusBrush;
+ }
+ }
+
+ void DelayObfuscation()
+ {
+ int lengthDifference = base.Text.Length - Text.Length;
+
+ string updatedRealText = DetermineTextFromPassword(Text, base.Text);
+
+ if (Text == updatedRealText)
+ {
+ // Nothing to do
+ return;
+ }
+
+ Text = updatedRealText;
+
+ // Cancel any pending delayed obfuscation
+ _cts?.Cancel();
+ _cts = null;
+
+ string newText;
+
+ if (lengthDifference != 1)
+ {
+ // Either More than one character got added in this text change (e.g., a paste operation)
+ // Or characters were removed. Either way, we don't need to do the delayed obfuscation dance
+ newText = Obfuscate();
+ }
+ else
+ {
+ // Only one character was added; we need to leave it visible for a brief time period
+ // Obfuscate all but the last character for now
+ newText = Obfuscate(true);
+
+ // Leave the last character visible until a new character is added
+ // or sufficient time has passed
+ if (_cts == null)
+ {
+ _cts = new CancellationTokenSource();
+ }
+
+ Task.Run(async () =>
+ {
+ await Task.Delay(TimeSpan.FromSeconds(0.5), _cts.Token);
+ _cts.Token.ThrowIfCancellationRequested();
+ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ base.Text = Obfuscate();
+ SelectionStart = base.Text.Length;
+ });
+ }, _cts.Token);
+ }
+
+ if (base.Text == newText)
+ {
+ return;
+ }
+
+ base.Text = newText;
+ SelectionStart = base.Text.Length;
+ }
+
+ static string DetermineTextFromPassword(string realText, string passwordText)
+ {
+ if (realText.Length == passwordText.Length)
+ {
+ return realText;
+ }
+
+ if (passwordText.Length == 0)
+ {
+ return "";
+ }
+
+ if (passwordText.Length < realText.Length)
+ {
+ return realText.Substring(0, passwordText.Length);
+ }
+
+ int lengthDifference = passwordText.Length - realText.Length;
+
+ return realText + passwordText.Substring(passwordText.Length - lengthDifference, lengthDifference);
+ }
+
+ string Obfuscate(bool leaveLastVisible = false)
+ {
+ if (leaveLastVisible && Text.Length == 1)
+ {
+ return Text;
+ }
+
+ if (leaveLastVisible && Text.Length > 1)
+ {
+ return new string(ObfuscationCharacter, Text.Length - 1) + Text.Substring(Text.Length - 1, 1);
+ }
+
+ return new string(ObfuscationCharacter, Text.Length);
+ }
+
+ static void OnIsPasswordChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
+ {
+ var textBox = (FormsTextBox)dependencyObject;
+ textBox.UpdateInputScope();
+ textBox.SyncBaseText();
+ }
+
+ void OnSelectionChanged(object sender, RoutedEventArgs routedEventArgs)
+ {
+ if (!IsPassword)
+ {
+ return;
+ }
+
+ // Prevent the user from selecting any text in the password box by forcing all selection
+ // to zero-length at the end of the Text
+ // This simulates the "do not allow clipboard copy" behavior the PasswordBox control has
+ if (SelectionLength > 0 || SelectionStart < Text.Length)
+ {
+ SelectionLength = 0;
+ SelectionStart = Text.Length;
+ }
+ }
+
+ void OnTextChanged(object sender, Windows.UI.Xaml.Controls.TextChangedEventArgs textChangedEventArgs)
+ {
+ if (IsPassword)
+ {
+ // If we're not on a phone, we can just obfuscate any input
+ if (Device.Idiom != TargetIdiom.Phone)
+ {
+ string updatedRealText = DetermineTextFromPassword(Text, base.Text);
+
+ if (Text == updatedRealText)
+ {
+ // Nothing to do
+ return;
+ }
+
+ Text = updatedRealText;
+
+ string updatedText = Obfuscate();
+
+ if (base.Text != updatedText)
+ {
+ base.Text = updatedText;
+ SelectionStart = base.Text.Length;
+ }
+
+ return;
+ }
+
+ // If we are on the phone, we might need to delay obfuscating the last character
+ DelayObfuscation();
+ }
+ else if (base.Text != Text)
+ {
+ // Not in password mode, so we just need to make the "real" text match
+ // what's in the textbox; the internalChange flag keeps the TextProperty
+ // synchronization from happening
+ _internalChangeFlag = true;
+ Text = base.Text;
+ _internalChangeFlag = false;
+ }
+ }
+
+ void SyncBaseText()
+ {
+ if (_internalChangeFlag)
+ {
+ return;
+ }
+
+ base.Text = IsPassword ? Obfuscate() : Text;
+
+ SelectionStart = base.Text.Length;
+ }
+
+ static void TextPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
+ {
+ var textBox = (FormsTextBox)dependencyObject;
+ textBox.SyncBaseText();
+ }
+
+ void UpdateInputScope()
+ {
+ if (IsPassword)
+ {
+ _cachedInputScope = InputScope;
+ _cachedSpellCheckSetting = IsSpellCheckEnabled;
+ _cachedPredictionsSetting = IsTextPredictionEnabled;
+ InputScope = PasswordInputScope; // Change to default input scope so we don't have suggestions, etc.
+ IsTextPredictionEnabled = false; // Force the other text modification options off
+ IsSpellCheckEnabled = false;
+ }
+ else
+ {
+ InputScope = _cachedInputScope;
+ IsSpellCheckEnabled = _cachedSpellCheckSetting;
+ IsTextPredictionEnabled = _cachedPredictionsSetting;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/FormsTimePicker.cs b/Xamarin.Forms.Platform.WinRT/FormsTimePicker.cs
new file mode 100644
index 00000000..976c56f4
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/FormsTimePicker.cs
@@ -0,0 +1,76 @@
+using System;
+using Windows.UI.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class FormsTimePicker : Windows.UI.Xaml.Controls.TimePicker
+ {
+ public FormsTimePicker()
+ {
+ if (Device.Idiom == TargetIdiom.Desktop || Device.Idiom == TargetIdiom.Tablet)
+ {
+ Loaded += (sender, args) => { Window.Current.Activated += WindowOnActivated; };
+ Unloaded += (sender, args) => { Window.Current.Activated -= WindowOnActivated; };
+ }
+ }
+
+ public event EventHandler<EventArgs> ForceInvalidate;
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ if (Device.Idiom == TargetIdiom.Desktop || Device.Idiom == TargetIdiom.Tablet)
+ {
+ // Look for the combo boxes which make up a TimePicker on Windows 8.1
+ // So we can hook into their closed events and invalidate them if necessary
+
+ var hourPicker = GetTemplateChild("HourPicker") as ComboBox;
+ if (hourPicker != null)
+ {
+ hourPicker.DropDownClosed += PickerOnDropDownClosed;
+ }
+
+ var minutePicker = GetTemplateChild("MinutePicker") as ComboBox;
+ if (minutePicker != null)
+ {
+ minutePicker.DropDownClosed += PickerOnDropDownClosed;
+ }
+
+ var periodPicker = GetTemplateChild("PeriodPicker") as ComboBox;
+ if (periodPicker != null)
+ {
+ periodPicker.DropDownClosed += PickerOnDropDownClosed;
+ }
+ }
+ }
+
+ void PickerOnDropDownClosed(object sender, object o)
+ {
+ // If the TimePicker is in a TableView or ListView and the user
+ // opens one of the dropdowns but does not actually change the value,
+ // when the dropdown closes, the selected value will go blank
+ // To fix this, we have to invalidate the control
+ // This only applies to Windows 8.1
+ ForceInvalidate?.Invoke(this, EventArgs.Empty);
+ }
+
+ void WindowOnActivated(object sender, WindowActivatedEventArgs windowActivatedEventArgs)
+ {
+ // If the TimePicker is in a TableView or ListView, when the application loses focus
+ // the TextBlock/ComboBox controls (UWP and 8.1, respectively) which display its selected value
+ // will go blank.
+ // To fix this, we have to signal the renderer to invalidate if
+ // Window.Activated occurs.
+ ForceInvalidate?.Invoke(this, EventArgs.Empty);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/FrameRenderer.cs b/Xamarin.Forms.Platform.WinRT/FrameRenderer.cs
new file mode 100644
index 00000000..7dcac435
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/FrameRenderer.cs
@@ -0,0 +1,71 @@
+using System.ComponentModel;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class FrameRenderer : ViewRenderer<Frame, Border>
+ {
+ public FrameRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ SetNativeControl(new Border());
+
+ PackChild();
+ UpdateBorder();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == "Content")
+ {
+ PackChild();
+ }
+ else if (e.PropertyName == Frame.OutlineColorProperty.PropertyName || e.PropertyName == Frame.HasShadowProperty.PropertyName)
+ {
+ UpdateBorder();
+ }
+ }
+
+ void PackChild()
+ {
+ if (Element.Content == null)
+ return;
+
+ IVisualElementRenderer renderer = Element.Content.GetOrCreateRenderer();
+ Control.Child = renderer.ContainerElement;
+ }
+
+ void UpdateBorder()
+ {
+ Control.CornerRadius = new CornerRadius(5);
+ if (Element.OutlineColor != Color.Default)
+ {
+ Control.BorderBrush = Element.OutlineColor.ToBrush();
+ Control.BorderThickness = new Windows.UI.Xaml.Thickness(1);
+ }
+ else
+ {
+ Control.BorderBrush = new Color(0, 0, 0, 0).ToBrush();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/FrameworkElementExtensions.cs b/Xamarin.Forms.Platform.WinRT/FrameworkElementExtensions.cs
new file mode 100644
index 00000000..64b2daab
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/FrameworkElementExtensions.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+using WBinding = Windows.UI.Xaml.Data.Binding;
+using WBindingExpression = Windows.UI.Xaml.Data.BindingExpression;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal static class FrameworkElementExtensions
+ {
+ static readonly Lazy<ConcurrentDictionary<Type, DependencyProperty>> ForegroundProperties =
+ new Lazy<ConcurrentDictionary<Type, DependencyProperty>>(() => new ConcurrentDictionary<Type, DependencyProperty>());
+
+ public static Brush GetForeground(this FrameworkElement element)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ return (Brush)element.GetValue(GetForegroundProperty(element));
+ }
+
+ public static WBinding GetForegroundBinding(this FrameworkElement element)
+ {
+ WBindingExpression expr = element.GetBindingExpression(GetForegroundProperty(element));
+ if (expr == null)
+ return null;
+
+ return expr.ParentBinding;
+ }
+
+ public static object GetForegroundCache(this FrameworkElement element)
+ {
+ WBinding binding = GetForegroundBinding(element);
+ if (binding != null)
+ return binding;
+
+ return GetForeground(element);
+ }
+
+ public static void RestoreForegroundCache(this FrameworkElement element, object cache)
+ {
+ var binding = cache as WBinding;
+ if (binding != null)
+ SetForeground(element, binding);
+ else
+ SetForeground(element, (Brush)cache);
+ }
+
+ public static void SetForeground(this FrameworkElement element, Brush foregroundBrush)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ element.SetValue(GetForegroundProperty(element), foregroundBrush);
+ }
+
+ public static void SetForeground(this FrameworkElement element, WBinding binding)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ element.SetBinding(GetForegroundProperty(element), binding);
+ }
+
+ internal static T GetFirstDescendant<T>(this DependencyObject element) where T : FrameworkElement
+ {
+ int count = VisualTreeHelper.GetChildrenCount(element);
+ for (var i = 0; i < count; i++)
+ {
+ DependencyObject child = VisualTreeHelper.GetChild(element, i);
+
+ T target = child as T ?? GetFirstDescendant<T>(child);
+ if (target != null)
+ return target;
+ }
+
+ return null;
+ }
+
+ static DependencyProperty GetForegroundProperty(FrameworkElement element)
+ {
+ if (element is Control)
+ return Control.ForegroundProperty;
+ if (element is TextBlock)
+ return TextBlock.ForegroundProperty;
+
+ Type type = element.GetType();
+
+ DependencyProperty foregroundProperty;
+ if (!ForegroundProperties.Value.TryGetValue(type, out foregroundProperty))
+ {
+ FieldInfo field = type.GetFields().FirstOrDefault(f => f.Name == "ForegroundProperty");
+ if (field == null)
+ throw new ArgumentException("type is not a Foregroundable type");
+
+ var property = (DependencyProperty)field.GetValue(null);
+ ForegroundProperties.Value.TryAdd(type, property);
+
+ return property;
+ }
+
+ return foregroundProperty;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/HeightConverter.cs b/Xamarin.Forms.Platform.WinRT/HeightConverter.cs
new file mode 100644
index 00000000..8ae73795
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/HeightConverter.cs
@@ -0,0 +1,32 @@
+using System;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public sealed class HeightConverter : Windows.UI.Xaml.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ double def;
+
+ var ps = parameter as string;
+ if (string.IsNullOrWhiteSpace(ps) || !double.TryParse(ps, out def))
+ {
+ def = double.NaN;
+ }
+
+ var val = (double)value;
+ return val > 0 ? val : def;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/HorizontalTextAlignmentConverter.cs b/Xamarin.Forms.Platform.WinRT/HorizontalTextAlignmentConverter.cs
new file mode 100644
index 00000000..f4f26d1a
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/HorizontalTextAlignmentConverter.cs
@@ -0,0 +1,24 @@
+using System;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class HorizontalTextAlignmentConverter : Windows.UI.Xaml.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ var textAlign = (TextAlignment)value;
+ return textAlign.ToNativeTextAlignment();
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotSupportedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ICellRenderer.cs b/Xamarin.Forms.Platform.WinRT/ICellRenderer.cs
new file mode 100644
index 00000000..e34d2db2
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ICellRenderer.cs
@@ -0,0 +1,14 @@
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public interface ICellRenderer : IRegisterable
+ {
+ Windows.UI.Xaml.DataTemplate GetTemplate(Cell cell);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/IImageSourceHandler.cs b/Xamarin.Forms.Platform.WinRT/IImageSourceHandler.cs
new file mode 100644
index 00000000..91eff534
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/IImageSourceHandler.cs
@@ -0,0 +1,16 @@
+using System.Threading;
+using System.Threading.Tasks;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public interface IImageSourceHandler : IRegisterable
+ {
+ Task<Windows.UI.Xaml.Media.ImageSource> LoadImageAsync(ImageSource imagesoure, CancellationToken cancellationToken = default(CancellationToken));
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ITitleProvider.cs b/Xamarin.Forms.Platform.WinRT/ITitleProvider.cs
new file mode 100644
index 00000000..cd17b09e
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ITitleProvider.cs
@@ -0,0 +1,21 @@
+using Windows.UI.Xaml.Media;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal interface ITitleProvider
+ {
+ Brush BarBackgroundBrush { set; }
+
+ Brush BarForegroundBrush { set; }
+
+ bool ShowTitle { get; set; }
+
+ string Title { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/IToolbarProvider.cs b/Xamarin.Forms.Platform.WinRT/IToolbarProvider.cs
new file mode 100644
index 00000000..0db54b02
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/IToolbarProvider.cs
@@ -0,0 +1,16 @@
+using System.Threading.Tasks;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal interface IToolbarProvider
+ {
+ Task<CommandBar> GetCommandBarAsync();
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/IVisualElementRenderer.cs b/Xamarin.Forms.Platform.WinRT/IVisualElementRenderer.cs
new file mode 100644
index 00000000..4db9c1a6
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/IVisualElementRenderer.cs
@@ -0,0 +1,23 @@
+using System;
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public interface IVisualElementRenderer : IRegisterable, IDisposable
+ {
+ FrameworkElement ContainerElement { get; }
+
+ VisualElement Element { get; }
+
+ event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint);
+ void SetElement(VisualElement element);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/IWrapperAware.cs b/Xamarin.Forms.Platform.WinRT/IWrapperAware.cs
new file mode 100644
index 00000000..aff90133
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/IWrapperAware.cs
@@ -0,0 +1,14 @@
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal interface IWrapperAware
+ {
+ void NotifyWrapped();
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ImageConverter.cs b/Xamarin.Forms.Platform.WinRT/ImageConverter.cs
new file mode 100644
index 00000000..e111be4c
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ImageConverter.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Threading.Tasks;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class ImageConverter : Windows.UI.Xaml.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ var source = (ImageSource)value;
+ IImageSourceHandler handler;
+
+ if (source != null && (handler = Registrar.Registered.GetHandler<IImageSourceHandler>(source.GetType())) != null)
+ {
+ Task<Windows.UI.Xaml.Media.ImageSource> task = handler.LoadImageAsync(source);
+ return new AsyncValue<Windows.UI.Xaml.Media.ImageSource>(task, null);
+ }
+
+ return null;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotSupportedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ImageLoaderSourceHandler.cs b/Xamarin.Forms.Platform.WinRT/ImageLoaderSourceHandler.cs
new file mode 100644
index 00000000..c9c711e0
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ImageLoaderSourceHandler.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Windows.Storage.Streams;
+using Windows.UI.Xaml.Media.Imaging;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public sealed class ImageLoaderSourceHandler : IImageSourceHandler
+ {
+ public async Task<Windows.UI.Xaml.Media.ImageSource> LoadImageAsync(ImageSource imagesoure, CancellationToken cancellationToken = new CancellationToken())
+ {
+ var imageLoader = imagesoure as UriImageSource;
+ if (imageLoader?.Uri == null)
+ return null;
+
+ Stream streamImage = await imageLoader.GetStreamAsync(cancellationToken);
+ if (streamImage == null || !streamImage.CanRead)
+ {
+ return null;
+ }
+
+ using(IRandomAccessStream stream = streamImage.AsRandomAccessStream())
+ {
+ try
+ {
+ var image = new BitmapImage();
+ await image.SetSourceAsync(stream);
+ return image;
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex);
+
+ // Because this literally throws System.Exception
+ // According to https://msdn.microsoft.com/library/windows/apps/jj191522
+ // this can happen if the image data is bad or the app is close to its
+ // memory limit
+ return null;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ImageRenderer.cs b/Xamarin.Forms.Platform.WinRT/ImageRenderer.cs
new file mode 100644
index 00000000..47c674c7
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ImageRenderer.cs
@@ -0,0 +1,132 @@
+using System;
+using System.ComponentModel;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Media.Imaging;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class ImageRenderer : ViewRenderer<Image, Windows.UI.Xaml.Controls.Image>
+ {
+ bool _measured;
+
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ if (Control.Source == null)
+ return new SizeRequest();
+
+ _measured = true;
+
+ var result = new Size { Width = ((BitmapImage)Control.Source).PixelWidth, Height = ((BitmapImage)Control.Source).PixelHeight };
+
+ return new SizeRequest(result);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (Control != null)
+ {
+ Control.ImageOpened -= OnImageOpened;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var image = new Windows.UI.Xaml.Controls.Image();
+ image.ImageOpened += OnImageOpened;
+ SetNativeControl(image);
+ }
+
+ UpdateSource();
+ UpdateAspect();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Image.SourceProperty.PropertyName)
+ UpdateSource();
+ else if (e.PropertyName == Image.AspectProperty.PropertyName)
+ UpdateAspect();
+ }
+
+ static Stretch GetStretch(Aspect aspect)
+ {
+ switch (aspect)
+ {
+ case Aspect.Fill:
+ return Stretch.Fill;
+ case Aspect.AspectFill:
+ return Stretch.UniformToFill;
+ default:
+ case Aspect.AspectFit:
+ return Stretch.Uniform;
+ }
+ }
+
+ void OnImageOpened(object sender, RoutedEventArgs routedEventArgs)
+ {
+ if (_measured)
+ {
+ RefreshImage();
+ }
+ }
+
+ void RefreshImage()
+ {
+ Element?.InvalidateMeasure(InvalidationTrigger.RendererReady);
+ }
+
+ void UpdateAspect()
+ {
+ Control.Stretch = GetStretch(Element.Aspect);
+ }
+
+ async void UpdateSource()
+ {
+ Element.SetValueCore(Image.IsLoadingPropertyKey, true);
+
+ ImageSource source = Element.Source;
+ IImageSourceHandler handler;
+ if (source != null && (handler = Registrar.Registered.GetHandler<IImageSourceHandler>(source.GetType())) != null)
+ {
+ Windows.UI.Xaml.Media.ImageSource imagesource;
+ try
+ {
+ imagesource = await handler.LoadImageAsync(source);
+ }
+ catch (OperationCanceledException)
+ {
+ imagesource = null;
+ }
+
+ // In the time it takes to await the imagesource, some zippy little app
+ // might have disposed of this Image already.
+ if (Control != null)
+ Control.Source = imagesource;
+
+ RefreshImage();
+ }
+ else
+ Control.Source = null;
+
+ Element?.SetValueCore(Image.IsLoadingPropertyKey, false);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/KeyboardConverter.cs b/Xamarin.Forms.Platform.WinRT/KeyboardConverter.cs
new file mode 100644
index 00000000..0cbd6a55
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/KeyboardConverter.cs
@@ -0,0 +1,27 @@
+using System;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class KeyboardConverter : Windows.UI.Xaml.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ var keyboard = value as Keyboard;
+ if (keyboard == null)
+ return null;
+
+ return keyboard.ToInputScope();
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/KeyboardExtensions.cs b/Xamarin.Forms.Platform.WinRT/KeyboardExtensions.cs
new file mode 100644
index 00000000..331e5269
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/KeyboardExtensions.cs
@@ -0,0 +1,57 @@
+using System;
+using Windows.UI.Xaml.Input;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public static class KeyboardExtensions
+ {
+ public static InputScope ToInputScope(this Keyboard self)
+ {
+ if (self == null)
+ throw new ArgumentNullException("self");
+
+ var result = new InputScope();
+ var name = new InputScopeName();
+ if (self == Keyboard.Default)
+ {
+ name.NameValue = InputScopeNameValue.Default;
+ }
+ else if (self == Keyboard.Chat)
+ {
+ name.NameValue = InputScopeNameValue.Chat;
+ }
+ else if (self == Keyboard.Email)
+ {
+ name.NameValue = InputScopeNameValue.EmailSmtpAddress;
+ }
+ else if (self == Keyboard.Numeric)
+ {
+ name.NameValue = InputScopeNameValue.Number;
+ }
+ else if (self == Keyboard.Telephone)
+ {
+ name.NameValue = InputScopeNameValue.TelephoneNumber;
+ }
+ else if (self == Keyboard.Text)
+ {
+ name.NameValue = InputScopeNameValue.Default;
+ }
+ else if (self == Keyboard.Url)
+ {
+ name.NameValue = InputScopeNameValue.Url;
+ }
+ else
+ {
+ name.NameValue = InputScopeNameValue.Default;
+ }
+ result.Names.Add(name);
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/LabelRenderer.cs b/Xamarin.Forms.Platform.WinRT/LabelRenderer.cs
new file mode 100644
index 00000000..41a0b477
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/LabelRenderer.cs
@@ -0,0 +1,202 @@
+using System;
+using System.ComponentModel;
+using Windows.Foundation;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Documents;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public static class FormattedStringExtensions
+ {
+ public static Run ToRun(this Span span)
+ {
+ var run = new Run { Text = span.Text };
+
+ if (span.ForegroundColor != Color.Default)
+ run.Foreground = span.ForegroundColor.ToBrush();
+
+ if (!span.IsDefault())
+ run.ApplyFont(span.Font);
+
+ return run;
+ }
+ }
+
+ public class LabelRenderer : ViewRenderer<Label, TextBlock>
+ {
+ bool _fontApplied;
+
+ protected override Windows.Foundation.Size ArrangeOverride(Windows.Foundation.Size finalSize)
+ {
+ if (Element == null)
+ return finalSize;
+ double childHeight = Math.Max(0, Math.Min(Element.Height, Control.DesiredSize.Height));
+ var rect = new Rect();
+
+ switch (Element.VerticalTextAlignment)
+ {
+ case TextAlignment.Start:
+ break;
+ default:
+ case TextAlignment.Center:
+ rect.Y = (int)((finalSize.Height - childHeight) / 2);
+ break;
+ case TextAlignment.End:
+ rect.Y = finalSize.Height - childHeight;
+ break;
+ }
+ rect.Height = childHeight;
+ rect.Width = finalSize.Width;
+ Control.Arrange(rect);
+ return finalSize;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new TextBlock());
+ }
+
+ UpdateText(Control);
+ UpdateColor(Control);
+ UpdateAlign(Control);
+ UpdateFont(Control);
+ UpdateLineBreakMode(Control);
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Label.TextProperty.PropertyName)
+ UpdateText(Control);
+ else if (e.PropertyName == Label.TextColorProperty.PropertyName)
+ UpdateColor(Control);
+ else if (e.PropertyName == Label.HorizontalTextAlignmentProperty.PropertyName || e.PropertyName == Label.VerticalTextAlignmentProperty.PropertyName)
+ UpdateAlign(Control);
+ else if (e.PropertyName == Label.FontProperty.PropertyName)
+ UpdateFont(Control);
+ else if (e.PropertyName == Label.LineBreakModeProperty.PropertyName)
+ UpdateLineBreakMode(Control);
+
+ base.OnElementPropertyChanged(sender, e);
+ }
+
+ void UpdateAlign(TextBlock textBlock)
+ {
+ if (textBlock == null)
+ return;
+
+ Label label = Element;
+ if (label == null)
+ return;
+
+ textBlock.TextAlignment = label.HorizontalTextAlignment.ToNativeTextAlignment();
+ textBlock.VerticalAlignment = label.VerticalTextAlignment.ToNativeVerticalAlignment();
+ }
+
+ void UpdateColor(TextBlock textBlock)
+ {
+ if (textBlock == null)
+ return;
+
+ Label label = Element;
+ if (label != null && label.TextColor != Color.Default)
+ {
+ textBlock.Foreground = label.TextColor.ToBrush();
+ }
+ else
+ {
+ textBlock.ClearValue(TextBlock.ForegroundProperty);
+ }
+ }
+
+ void UpdateFont(TextBlock textBlock)
+ {
+ if (textBlock == null)
+ return;
+
+ Label label = Element;
+ if (label == null || (label.IsDefault() && !_fontApplied))
+ return;
+
+ Font fontToApply = label.IsDefault() ? Font.SystemFontOfSize(NamedSize.Medium) : label.Font;
+
+ textBlock.ApplyFont(fontToApply);
+ _fontApplied = true;
+ }
+
+ void UpdateLineBreakMode(TextBlock textBlock)
+ {
+ if (textBlock == null)
+ return;
+
+ switch (Element.LineBreakMode)
+ {
+ case LineBreakMode.NoWrap:
+ textBlock.TextTrimming = TextTrimming.Clip;
+ textBlock.TextWrapping = TextWrapping.NoWrap;
+ break;
+ case LineBreakMode.WordWrap:
+ textBlock.TextTrimming = TextTrimming.None;
+ textBlock.TextWrapping = TextWrapping.Wrap;
+ break;
+ case LineBreakMode.CharacterWrap:
+ textBlock.TextTrimming = TextTrimming.WordEllipsis;
+ textBlock.TextWrapping = TextWrapping.Wrap;
+ break;
+ case LineBreakMode.HeadTruncation:
+ textBlock.TextTrimming = TextTrimming.WordEllipsis;
+ textBlock.TextWrapping = TextWrapping.NoWrap;
+ break;
+ case LineBreakMode.TailTruncation:
+ textBlock.TextTrimming = TextTrimming.WordEllipsis;
+ textBlock.TextWrapping = TextWrapping.NoWrap;
+ break;
+ case LineBreakMode.MiddleTruncation:
+ textBlock.TextTrimming = TextTrimming.WordEllipsis;
+ textBlock.TextWrapping = TextWrapping.NoWrap;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ void UpdateText(TextBlock textBlock)
+ {
+ if (textBlock == null)
+ return;
+
+ Label label = Element;
+ if (label != null)
+ {
+ FormattedString formatted = label.FormattedText;
+
+ if (formatted == null)
+ {
+ textBlock.Text = label.Text ?? string.Empty;
+ }
+ else
+ {
+ textBlock.Inlines.Clear();
+
+ for (var i = 0; i < formatted.Spans.Count; i++)
+ {
+ textBlock.Inlines.Add(formatted.Spans[i].ToRun());
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/LayoutExtensions.cs b/Xamarin.Forms.Platform.WinRT/LayoutExtensions.cs
new file mode 100644
index 00000000..6991b322
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/LayoutExtensions.cs
@@ -0,0 +1,33 @@
+using System.Collections.Generic;
+using Windows.UI.Xaml;
+using WSize = Windows.Foundation.Size;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public delegate SizeRequest? GetDesiredSizeDelegate(NativeViewWrapperRenderer renderer, double widthConstraint, double heightConstraint);
+
+ public delegate WSize? ArrangeOverrideDelegate(NativeViewWrapperRenderer renderer, WSize finalSize);
+
+ public delegate WSize? MeasureOverrideDelegate(NativeViewWrapperRenderer renderer, WSize availableSize);
+
+ public static class LayoutExtensions
+ {
+ public static void Add(this IList<View> children, FrameworkElement view, GetDesiredSizeDelegate getDesiredSizeDelegate = null, ArrangeOverrideDelegate arrangeOverrideDelegate = null,
+ MeasureOverrideDelegate measureOverrideDelegate = null)
+ {
+ children.Add(view.ToView(getDesiredSizeDelegate, arrangeOverrideDelegate, measureOverrideDelegate));
+ }
+
+ public static View ToView(this FrameworkElement view, GetDesiredSizeDelegate getDesiredSizeDelegate = null, ArrangeOverrideDelegate arrangeOverrideDelegate = null,
+ MeasureOverrideDelegate measureOverrideDelegate = null)
+ {
+ return new NativeViewWrapper(view, getDesiredSizeDelegate, arrangeOverrideDelegate, measureOverrideDelegate);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/LayoutRenderer.cs b/Xamarin.Forms.Platform.WinRT/LayoutRenderer.cs
new file mode 100644
index 00000000..86748dc8
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/LayoutRenderer.cs
@@ -0,0 +1,55 @@
+using System.ComponentModel;
+using Windows.Foundation;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Media;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class LayoutRenderer : ViewRenderer<Layout, FrameworkElement>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<Layout> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ {
+ SizeChanged -= OnSizeChanged;
+ }
+
+ if (e.NewElement != null)
+ {
+ SizeChanged += OnSizeChanged;
+
+ UpdateClipToBounds();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Layout.IsClippedToBoundsProperty.PropertyName)
+ UpdateClipToBounds();
+ }
+
+ void OnSizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ UpdateClipToBounds();
+ }
+
+ void UpdateClipToBounds()
+ {
+ Clip = null;
+ if (Element.IsClippedToBounds)
+ {
+ Clip = new RectangleGeometry { Rect = new Rect(0, 0, ActualWidth, ActualHeight) };
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ListGroupHeaderPresenter.cs b/Xamarin.Forms.Platform.WinRT/ListGroupHeaderPresenter.cs
new file mode 100644
index 00000000..45818977
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ListGroupHeaderPresenter.cs
@@ -0,0 +1,46 @@
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class ListGroupHeaderPresenter : Windows.UI.Xaml.Controls.ContentPresenter
+ {
+ void OnTapped(object sender, TappedRoutedEventArgs tappedRoutedEventArgs)
+ {
+ var element = VisualTreeHelper.GetParent(this) as FrameworkElement;
+ while (element != null)
+ {
+ var list = element as Windows.UI.Xaml.Controls.ListView;
+ if (list != null)
+ element = list.SemanticZoomOwner;
+
+ if (element == null)
+ break;
+
+ var zoom = element as SemanticZoom;
+ if (zoom != null)
+ {
+ zoom.ToggleActiveView();
+
+ var grid = zoom.ZoomedOutView as GridView;
+ if (grid != null)
+ {
+ grid.MakeVisible(new SemanticZoomLocation { Item = DataContext });
+ }
+
+ return;
+ }
+
+ element = VisualTreeHelper.GetParent(element) as FrameworkElement;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ListViewGroupStyleSelector.cs b/Xamarin.Forms.Platform.WinRT/ListViewGroupStyleSelector.cs
new file mode 100644
index 00000000..066f5681
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ListViewGroupStyleSelector.cs
@@ -0,0 +1,18 @@
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class ListViewGroupStyleSelector : GroupStyleSelector
+ {
+ protected override GroupStyle SelectGroupStyleCore(object group, uint level)
+ {
+ return (GroupStyle)Windows.UI.Xaml.Application.Current.Resources["ListViewGroup"];
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ListViewRenderer.cs b/Xamarin.Forms.Platform.WinRT/ListViewRenderer.cs
new file mode 100644
index 00000000..5c231738
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ListViewRenderer.cs
@@ -0,0 +1,634 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading.Tasks;
+using Windows.Foundation;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using WListView = Windows.UI.Xaml.Controls.ListView;
+using WBinding = Windows.UI.Xaml.Data.Binding;
+using WApp = Windows.UI.Xaml.Application;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class ListViewRenderer : ViewRenderer<ListView, FrameworkElement>
+ {
+#if !WINDOWS_UWP
+ public static readonly DependencyProperty HighlightWhenSelectedProperty = DependencyProperty.RegisterAttached("HighlightWhenSelected", typeof(bool), typeof(ListViewRenderer),
+ new PropertyMetadata(false));
+
+ public static bool GetHighlightWhenSelected(DependencyObject dependencyObject)
+ {
+ return (bool)dependencyObject.GetValue(HighlightWhenSelectedProperty);
+ }
+
+ public static void SetHighlightWhenSelected(DependencyObject dependencyObject, bool value)
+ {
+ dependencyObject.SetValue(HighlightWhenSelectedProperty, value);
+ }
+#endif
+
+ protected WListView List { get; private set; }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ {
+ e.OldElement.ItemSelected -= OnElementItemSelected;
+ e.OldElement.ScrollToRequested -= OnElementScrollToRequested;
+ }
+
+ if (e.NewElement != null)
+ {
+ e.NewElement.ItemSelected += OnElementItemSelected;
+ e.NewElement.ScrollToRequested += OnElementScrollToRequested;
+
+ if (List == null)
+ {
+ List = new WListView
+ {
+ IsSynchronizedWithCurrentItem = false,
+ ItemTemplate = (Windows.UI.Xaml.DataTemplate)WApp.Current.Resources["CellTemplate"],
+ HeaderTemplate = (Windows.UI.Xaml.DataTemplate)WApp.Current.Resources["View"],
+ FooterTemplate = (Windows.UI.Xaml.DataTemplate)WApp.Current.Resources["View"],
+ ItemContainerStyle = (Windows.UI.Xaml.Style)WApp.Current.Resources["FormsListViewItem"],
+ GroupStyleSelector = (GroupStyleSelector)WApp.Current.Resources["ListViewGroupSelector"]
+ };
+
+ // In order to support tapping on elements within a list item, we handle
+ // ListView.Tapped (which can be handled by child elements in the list items
+ // and prevented from bubbling up) rather than ListView.ItemClick
+ List.Tapped += ListOnTapped;
+
+ if (ShouldCustomHighlight)
+ {
+ List.SelectionChanged += OnControlSelectionChanged;
+ }
+
+ List.SetBinding(ItemsControl.ItemsSourceProperty, "");
+ }
+
+ // WinRT throws an exception if you set ItemsSource directly to a CVS, so bind it.
+ List.DataContext = new CollectionViewSource { Source = Element.ItemsSource, IsSourceGrouped = Element.IsGroupingEnabled };
+
+ UpdateGrouping();
+ UpdateHeader();
+ UpdateFooter();
+ ClearSizeEstimate();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == ListView.IsGroupingEnabledProperty.PropertyName)
+ {
+ UpdateGrouping();
+ }
+ else if (e.PropertyName == ListView.HeaderProperty.PropertyName)
+ {
+ UpdateHeader();
+ }
+ else if (e.PropertyName == ListView.FooterProperty.PropertyName)
+ {
+ UpdateFooter();
+ }
+ else if (e.PropertyName == ListView.RowHeightProperty.PropertyName)
+ {
+ ClearSizeEstimate();
+ }
+ else if (e.PropertyName == ListView.HasUnevenRowsProperty.PropertyName)
+ {
+ ClearSizeEstimate();
+ }
+ else if (e.PropertyName == ListView.ItemTemplateProperty.PropertyName)
+ {
+ ClearSizeEstimate();
+ }
+ else if (e.PropertyName == ListView.ItemsSourceProperty.PropertyName)
+ {
+ ClearSizeEstimate();
+ ((CollectionViewSource)List.DataContext).Source = Element.ItemsSource;
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (List != null)
+ {
+ List.Tapped -= ListOnTapped;
+
+ if (ShouldCustomHighlight)
+ {
+ List.SelectionChanged -= OnControlSelectionChanged;
+ }
+
+ List.DataContext = null;
+ List = null;
+ }
+
+ if (_zoom != null)
+ {
+ _zoom.ViewChangeCompleted -= OnViewChangeCompleted;
+ _zoom = null;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ static IEnumerable<T> FindDescendants<T>(DependencyObject dobj) where T : DependencyObject
+ {
+ int count = VisualTreeHelper.GetChildrenCount(dobj);
+ for (var i = 0; i < count; i++)
+ {
+ DependencyObject element = VisualTreeHelper.GetChild(dobj, i);
+ if (element is T)
+ yield return (T)element;
+
+ foreach (T descendant in FindDescendants<T>(element))
+ yield return descendant;
+ }
+ }
+
+ sealed class BrushedElement
+ {
+ bool _isBound;
+
+ public BrushedElement(FrameworkElement element, WBinding brushBinding = null, Brush brush = null)
+ {
+ Element = element;
+ BrushBinding = brushBinding;
+ Brush = brush;
+ }
+
+ public Brush Brush { get; }
+
+ public WBinding BrushBinding { get; }
+
+ public FrameworkElement Element { get; }
+
+ public bool IsBound
+ {
+ get { return BrushBinding != null; }
+ }
+ }
+
+ SemanticZoom _zoom;
+ ScrollViewer _scrollViewer;
+ ContentControl _headerControl;
+ readonly List<BrushedElement> _highlightedElements = new List<BrushedElement>();
+
+ bool ShouldCustomHighlight
+ {
+ get
+ {
+#if WINDOWS_UWP
+ return false;
+#else
+ return Device.Idiom == TargetIdiom.Phone;
+#endif
+ }
+ }
+
+ void ClearSizeEstimate()
+ {
+ Element.ClearValue(CellControl.MeasuredEstimateProperty);
+ }
+
+ void UpdateFooter()
+ {
+ List.Footer = ((IListViewController)Element).FooterElement;
+ }
+
+ void UpdateHeader()
+ {
+ List.Header = ((IListViewController)Element).HeaderElement;
+ }
+
+ void UpdateGrouping()
+ {
+ bool grouping = Element.IsGroupingEnabled;
+
+ ((CollectionViewSource)List.DataContext).IsSourceGrouped = grouping;
+
+ if (grouping && Element.TemplatedItems.ShortNames != null)
+ {
+ if (_zoom == null)
+ {
+ ScrollViewer.SetIsVerticalScrollChainingEnabled(List, false);
+
+ var grid = new GridView { ItemsSource = Element.TemplatedItems.ShortNames, Style = (Windows.UI.Xaml.Style)WApp.Current.Resources["JumpListGrid"] };
+
+ ScrollViewer.SetIsHorizontalScrollChainingEnabled(grid, false);
+
+ _zoom = new SemanticZoom { IsZoomOutButtonEnabled = false, ZoomedOutView = grid };
+
+ // Since we reuse our ScrollTo, we have to wait until the change completes or ChangeView has odd behavior.
+ _zoom.ViewChangeCompleted += OnViewChangeCompleted;
+
+ // Specific order to let SNC unparent the ListView for us
+ SetNativeControl(_zoom);
+ _zoom.ZoomedInView = List;
+ }
+ else
+ {
+ _zoom.CanChangeViews = true;
+ }
+ }
+ else
+ {
+ if (_zoom != null)
+ _zoom.CanChangeViews = false;
+ else if (List != Control)
+ SetNativeControl(List);
+ }
+ }
+
+ async void OnViewChangeCompleted(object sender, SemanticZoomViewChangedEventArgs e)
+ {
+ if (e.IsSourceZoomedInView)
+ return;
+
+ // HACK: Technically more than one short name could be the same, this will potentially find the wrong one in that case
+ var item = (string)e.SourceItem.Item;
+
+ int index = Element.TemplatedItems.ShortNames.IndexOf(item);
+ if (index == -1)
+ return;
+
+ TemplatedItemsList<ItemsView<Cell>, Cell> til = Element.TemplatedItems.GetGroup(index);
+ if (til.Count == 0)
+ return; // FIXME
+
+ // Delay until after the SemanticZoom change _actually_ finishes, fixes tons of odd issues on Phone w/ virtualization.
+ if (Device.Idiom == TargetIdiom.Phone)
+ await Task.Delay(1);
+
+ ScrollTo(til.ListProxy.ProxiedEnumerable, til.ListProxy[0], ScrollToPosition.Start, true, true);
+ }
+
+ async void ScrollTo(object group, object item, ScrollToPosition toPosition, bool shouldAnimate, bool includeGroup = false, bool previouslyFailed = false)
+ {
+ ScrollViewer viewer = GetScrollViewer();
+ if (viewer == null)
+ {
+ RoutedEventHandler loadedHandler = null;
+ loadedHandler = async (o, e) =>
+ {
+ List.Loaded -= loadedHandler;
+
+ // Here we try to avoid an exception, see explanation at bottom
+ await Dispatcher.RunIdleAsync(args => { ScrollTo(group, item, toPosition, shouldAnimate, includeGroup); });
+ };
+ List.Loaded += loadedHandler;
+ return;
+ }
+
+ Tuple<int, int> location = Element.TemplatedItems.GetGroupAndIndexOfItem(group, item);
+ if (location.Item1 == -1 || location.Item2 == -1)
+ return;
+
+ object[] t = Element.TemplatedItems.GetGroup(location.Item1).ItemsSource.Cast<object>().ToArray();
+ object c = t[location.Item2];
+
+ double viewportHeight = viewer.ViewportHeight;
+
+ var semanticLocation = new SemanticZoomLocation { Item = c };
+
+ switch (toPosition)
+ {
+ case ScrollToPosition.Start:
+ {
+ List.ScrollIntoView(c, ScrollIntoViewAlignment.Leading);
+ return;
+ }
+
+ case ScrollToPosition.MakeVisible:
+ {
+ List.ScrollIntoView(c, ScrollIntoViewAlignment.Default);
+ return;
+ }
+
+ case ScrollToPosition.End:
+ case ScrollToPosition.Center:
+ {
+ var content = (FrameworkElement)List.ItemTemplate.LoadContent();
+ content.DataContext = c;
+ content.Measure(new Windows.Foundation.Size(viewer.ActualWidth, double.PositiveInfinity));
+
+ double tHeight = content.DesiredSize.Height;
+
+ if (toPosition == ScrollToPosition.Center)
+ semanticLocation.Bounds = new Rect(0, viewportHeight / 2 - tHeight / 2, 0, 0);
+ else
+ semanticLocation.Bounds = new Rect(0, viewportHeight - tHeight, 0, 0);
+
+ break;
+ }
+ }
+
+ // Waiting for loaded doesn't seem to be enough anymore; the ScrollViewer does not appear until after Loaded.
+ // Even if the ScrollViewer is present, an invoke at low priority fails (E_FAIL) presumably because the items are
+ // still loading. An invoke at idle sometimes work, but isn't reliable enough, so we'll just have to commit
+ // treason and use a blanket catch for the E_FAIL and try again.
+ try
+ {
+ List.MakeVisible(semanticLocation);
+ }
+ catch (Exception)
+ {
+ if (previouslyFailed)
+ return;
+
+ Task.Delay(1).ContinueWith(ct => { ScrollTo(group, item, toPosition, shouldAnimate, includeGroup, true); }, TaskScheduler.FromCurrentSynchronizationContext()).WatchForError();
+ }
+ }
+
+ void OnElementScrollToRequested(object sender, ScrollToRequestedEventArgs e)
+ {
+ ScrollTo(e.Group, e.Item, e.Position, e.ShouldAnimate);
+ }
+
+ T GetFirstDescendant<T>(DependencyObject element) where T : FrameworkElement
+ {
+ int count = VisualTreeHelper.GetChildrenCount(element);
+ for (var i = 0; i < count; i++)
+ {
+ DependencyObject child = VisualTreeHelper.GetChild(element, i);
+
+ T target = child as T ?? GetFirstDescendant<T>(child);
+ if (target != null)
+ return target;
+ }
+
+ return null;
+ }
+
+ ContentControl GetHeaderControl()
+ {
+ if (_headerControl == null)
+ {
+ ScrollViewer viewer = GetScrollViewer();
+ if (viewer == null)
+ return null;
+
+ var presenter = GetFirstDescendant<ItemsPresenter>(viewer);
+ if (presenter == null)
+ return null;
+
+ _headerControl = GetFirstDescendant<ContentControl>(presenter);
+ }
+
+ return _headerControl;
+ }
+
+ ScrollViewer GetScrollViewer()
+ {
+ if (_scrollViewer == null)
+ {
+ _scrollViewer = List.GetFirstDescendant<ScrollViewer>();
+ }
+
+ return _scrollViewer;
+ }
+
+ void OnElementItemSelected(object sender, SelectedItemChangedEventArgs e)
+ {
+ if (Element == null)
+ return;
+
+ if (_deferSelection)
+ {
+ // If we get more than one of these, that's okay; we only want the latest one
+ _deferredSelectedItemChangedEvent = new Tuple<object, SelectedItemChangedEventArgs>(sender, e);
+ return;
+ }
+
+ if (e.SelectedItem == null)
+ {
+ List.SelectedIndex = -1;
+ return;
+ }
+
+ var index = 0;
+ if (Element.IsGroupingEnabled)
+ {
+ int selectedItemIndex = Element.TemplatedItems.GetGlobalIndexOfItem(e.SelectedItem);
+ var leftOver = 0;
+ int groupIndex = Element.TemplatedItems.GetGroupIndexFromGlobal(selectedItemIndex, out leftOver);
+
+ index = selectedItemIndex - (groupIndex + 1);
+ }
+ else
+ {
+ index = Element.TemplatedItems.GetGlobalIndexOfItem(e.SelectedItem);
+ }
+
+ List.SelectedIndex = index;
+ }
+
+ void ListOnTapped(object sender, TappedRoutedEventArgs args)
+ {
+ var orig = args.OriginalSource as DependencyObject;
+ int index = -1;
+
+ // Work our way up the tree until we find the actual list item
+ // the user tapped on
+ while (orig != null && orig != List)
+ {
+ var lv = orig as ListViewItem;
+
+ if (lv != null)
+ {
+ index = Element.TemplatedItems.GetGlobalIndexOfItem(lv.Content);
+ break;
+ }
+
+ orig = VisualTreeHelper.GetParent(orig);
+ }
+
+ if (index > -1)
+ {
+ OnListItemClicked(index);
+ }
+ }
+
+ void OnListItemClicked(int index)
+ {
+#if !WINDOWS_UWP
+ // If we're on the phone , we need to cache the selected item in case the handler
+ // we're about to call changes any item indexes;
+ // in some cases, those index changes will throw an exception we can't catch if
+ // the listview has an item selected
+ object selectedItem = null;
+ if (Device.Idiom == TargetIdiom.Phone)
+ {
+ selectedItem = List.SelectedItem;
+ List.SelectedIndex = -1;
+ _deferSelection = true;
+ }
+#endif
+
+ Element.NotifyRowTapped(index);
+
+#if !WINDOWS_UWP
+
+ if (Device.Idiom != TargetIdiom.Phone || List == null)
+ {
+ return;
+ }
+
+ _deferSelection = false;
+
+ if (_deferredSelectedItemChangedEvent != null)
+ {
+ // If there was a selection change attempt while RowTapped was being handled, replay it
+ OnElementItemSelected(_deferredSelectedItemChangedEvent.Item1, _deferredSelectedItemChangedEvent.Item2);
+ _deferredSelectedItemChangedEvent = null;
+ }
+ else if (List?.SelectedIndex == -1 && selectedItem != null)
+ {
+ // Otherwise, set the selection back to whatever it was before all this started
+ List.SelectedItem = selectedItem;
+ }
+#endif
+ }
+
+ void OnControlSelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ RestorePreviousSelectedVisual();
+
+ if (e.AddedItems.Count == 0)
+ return;
+
+ object cell = e.AddedItems[0];
+ if (cell == null)
+ return;
+
+ if (ShouldCustomHighlight)
+ {
+ FrameworkElement element = FindElement(cell);
+ if (element != null)
+ {
+ SetSelectedVisual(element);
+ }
+ }
+ }
+
+ FrameworkElement FindElement(object cell)
+ {
+ foreach (CellControl selector in FindDescendants<CellControl>(List))
+ {
+ if (ReferenceEquals(cell, selector.DataContext))
+ return selector;
+ }
+
+ return null;
+ }
+
+#if WINDOWS_UWP
+ void RestorePreviousSelectedVisual()
+ {
+ }
+
+ void SetSelectedVisual(FrameworkElement element)
+ {
+ }
+#else
+ void RestorePreviousSelectedVisual()
+ {
+ foreach (BrushedElement highlight in _highlightedElements)
+ {
+ if (highlight.IsBound)
+ {
+ highlight.Element.SetForeground(highlight.BrushBinding);
+ }
+ else
+ {
+ highlight.Element.SetForeground(highlight.Brush);
+ }
+ }
+
+ _highlightedElements.Clear();
+ }
+
+ void SetSelectedVisual(FrameworkElement element)
+ {
+ // Find all labels in children and set their foreground color to accent color
+ IEnumerable<FrameworkElement> elementsToHighlight = FindPhoneHighlights(element);
+ var systemAccentBrush = (Brush)WApp.Current.Resources["SystemColorControlAccentBrush"];
+
+ foreach (FrameworkElement toHighlight in elementsToHighlight)
+ {
+ Brush brush = null;
+ WBinding binding = toHighlight.GetForegroundBinding();
+ if (binding == null)
+ brush = toHighlight.GetForeground();
+
+ var brushedElement = new BrushedElement(toHighlight, binding, brush);
+ _highlightedElements.Add(brushedElement);
+
+ toHighlight.SetForeground(systemAccentBrush);
+ }
+ }
+
+ IEnumerable<FrameworkElement> FindPhoneHighlights(FrameworkElement element)
+ {
+ FrameworkElement parent = element;
+ while (true)
+ {
+ element = parent;
+ if (element is CellControl)
+ break;
+
+ parent = VisualTreeHelper.GetParent(element) as FrameworkElement;
+ if (parent == null)
+ {
+ parent = element;
+ break;
+ }
+ }
+
+ return FindPhoneHighlightCore(parent);
+ }
+
+ IEnumerable<FrameworkElement> FindPhoneHighlightCore(DependencyObject element)
+ {
+ int children = VisualTreeHelper.GetChildrenCount(element);
+ for (var i = 0; i < children; i++)
+ {
+ DependencyObject child = VisualTreeHelper.GetChild(element, i);
+
+ var label = child as LabelRenderer;
+ var childElement = child as FrameworkElement;
+ if (childElement != null && (GetHighlightWhenSelected(childElement) || label != null))
+ {
+ if (label != null)
+ yield return label.Control;
+ else
+ yield return childElement;
+ }
+
+ foreach (FrameworkElement recursedElement in FindPhoneHighlightCore(childElement))
+ yield return recursedElement;
+ }
+ }
+#endif
+
+ bool _deferSelection;
+ Tuple<object, SelectedItemChangedEventArgs> _deferredSelectedItemChangedEvent;
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/MasterBackgroundConverter.cs b/Xamarin.Forms.Platform.WinRT/MasterBackgroundConverter.cs
new file mode 100644
index 00000000..aa82f56d
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/MasterBackgroundConverter.cs
@@ -0,0 +1,75 @@
+using System;
+using Windows.UI;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class MasterBackgroundConverter : Windows.UI.Xaml.Data.IValueConverter
+ {
+ // Obtained by comparing the Mail apps master section background to the detail background
+ const double Shift = 0.03;
+
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ SolidColorBrush brush = null;
+
+ var element = value as FrameworkElement;
+ if (element != null)
+ {
+ while (brush == null && element != null)
+ {
+ DependencyProperty property = GetBackgroundProperty(element);
+ if (property != null)
+ {
+ value = element.GetValue(property);
+ brush = value as SolidColorBrush;
+ if (brush != null && brush.Color == Colors.Transparent)
+ brush = null;
+ }
+
+ element = VisualTreeHelper.GetParent(element) as FrameworkElement;
+ }
+ }
+
+ brush = value as SolidColorBrush;
+ if (brush != null)
+ {
+ Windows.UI.Color wcolor = brush.Color;
+ Color color = Color.FromRgba(wcolor.R, wcolor.G, wcolor.B, wcolor.A);
+
+ double delta = Shift;
+ if (color.Luminosity > .6)
+ delta = -Shift;
+
+ color = color.AddLuminosity(delta);
+
+ return new SolidColorBrush(color.ToWindowsColor());
+ }
+
+ return null;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotImplementedException();
+ }
+
+ static DependencyProperty GetBackgroundProperty(FrameworkElement element)
+ {
+ if (element is Control)
+ return Control.BackgroundProperty;
+ if (element is Panel)
+ return Panel.BackgroundProperty;
+
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/MasterDetailControl.cs b/Xamarin.Forms.Platform.WinRT/MasterDetailControl.cs
new file mode 100644
index 00000000..c325b42a
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/MasterDetailControl.cs
@@ -0,0 +1,168 @@
+using System;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Media;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ public class MasterDetailControl : Control
+ {
+ public static readonly DependencyProperty MasterContentProperty = DependencyProperty.Register("MasterContent", typeof(object), typeof(MasterDetailControl),
+ new PropertyMetadata(null, (d, e) => ((MasterDetailControl)d).UpdateMaster()));
+
+ public static readonly DependencyProperty DetailContentProperty = DependencyProperty.Register("DetailContent", typeof(object), typeof(MasterDetailControl),
+ new PropertyMetadata(null, (d, e) => ((MasterDetailControl)d).UpdateDetail()));
+
+ public static readonly DependencyProperty IsMasterVisibleProperty = DependencyProperty.Register("IsMasterVisible", typeof(bool), typeof(MasterDetailControl),
+ new PropertyMetadata(false, (d, e) => ((MasterDetailControl)d).UpdateMaster()));
+
+ public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(MasterDetailControl),
+ new PropertyMetadata("", (d, e) => ((MasterDetailControl)d).UpdateTitle()));
+
+ public static readonly DependencyProperty DetailTitleVisibilityProperty = DependencyProperty.Register("DetailTitleVisibility", typeof(Visibility), typeof(MasterDetailControl),
+ new PropertyMetadata(Visibility.Collapsed, (d, e) => ((MasterDetailControl)d).UpdateToolbar()));
+
+ public static readonly DependencyProperty ToolbarForegroundProperty = DependencyProperty.Register("ToolbarForeground", typeof(Brush), typeof(MasterDetailControl),
+ new PropertyMetadata(default(Brush), (d, e) => ((MasterDetailControl)d).UpdateToolbar()));
+
+ public static readonly DependencyProperty ToolbarBackgroundProperty = DependencyProperty.Register("ToolbarBackground", typeof(Brush), typeof(MasterDetailControl),
+ new PropertyMetadata(default(Brush), (d, e) => ((MasterDetailControl)d).UpdateToolbar()));
+
+ Windows.UI.Xaml.Controls.Grid _grd;
+
+ Windows.UI.Xaml.Controls.ContentPresenter _masterPresenter;
+ Windows.UI.Xaml.Controls.ContentPresenter _detailPresenter;
+ Popup _popup;
+ TextBlock _txbTitle;
+
+ public object DetailContent
+ {
+ get { return GetValue(DetailContentProperty); }
+ set { SetValue(DetailContentProperty, value); }
+ }
+
+ public Visibility DetailTitleVisibility
+ {
+ get { return (Visibility)GetValue(DetailTitleVisibilityProperty); }
+ set { SetValue(DetailTitleVisibilityProperty, value); }
+ }
+
+ public bool IsMasterVisible
+ {
+ get { return (bool)GetValue(IsMasterVisibleProperty); }
+ set { SetValue(IsMasterVisibleProperty, value); }
+ }
+
+ public object MasterContent
+ {
+ get { return GetValue(MasterContentProperty); }
+ set { SetValue(MasterContentProperty, value); }
+ }
+
+ public string Title
+ {
+ get { return (string)GetValue(TitleProperty); }
+ set { SetValue(TitleProperty, value); }
+ }
+
+ public Brush ToolbarBackground
+ {
+ get { return (Brush)GetValue(ToolbarBackgroundProperty); }
+ set { SetValue(ToolbarBackgroundProperty, value); }
+ }
+
+ public Brush ToolbarForeground
+ {
+ get { return (Brush)GetValue(ToolbarForegroundProperty); }
+ set { SetValue(ToolbarForegroundProperty, value); }
+ }
+
+ public event EventHandler UserClosedPopover;
+
+ protected override void OnApplyTemplate()
+ {
+ if (_masterPresenter != null)
+ {
+ // Despite itself being unparented when the template changes, the presenters' children still think they're
+ // parented and so the new presenters throw when the content is assigned to them.
+ _masterPresenter.Content = null;
+ _masterPresenter = null;
+ }
+
+ if (_detailPresenter != null)
+ {
+ _detailPresenter.Content = null;
+ _detailPresenter = null;
+ }
+
+ if (_popup != null)
+ {
+ _popup.Closed -= OnPopupClosed;
+ _popup = null;
+ }
+
+ base.OnApplyTemplate();
+
+ _masterPresenter = GetTemplateChild("masterPresenter") as Windows.UI.Xaml.Controls.ContentPresenter;
+ _detailPresenter = GetTemplateChild("detailPresenter") as Windows.UI.Xaml.Controls.ContentPresenter;
+ _txbTitle = GetTemplateChild("txbTitle") as TextBlock;
+ _grd = GetTemplateChild("grdToolbar") as Windows.UI.Xaml.Controls.Grid;
+
+ _popup = GetTemplateChild("popup") as Popup;
+ if (_popup != null)
+ _popup.Closed += OnPopupClosed;
+
+ UpdateMaster();
+ UpdateDetail();
+ UpdateTitle();
+ UpdateToolbar();
+ }
+
+ void OnPopupClosed(object sender, object e)
+ {
+ EventHandler closed = UserClosedPopover;
+ if (closed != null)
+ closed(this, EventArgs.Empty);
+ }
+
+ void UpdateDetail()
+ {
+ if (_detailPresenter == null)
+ return;
+
+ _detailPresenter.Content = DetailContent;
+ }
+
+ void UpdateMaster()
+ {
+ if (_masterPresenter == null)
+ return;
+
+ bool visible = IsMasterVisible;
+ _masterPresenter.Visibility = visible ? Visibility.Visible : Visibility.Collapsed;
+ _masterPresenter.Content = MasterContent;
+
+ if (_popup != null)
+ _popup.IsOpen = visible;
+ }
+
+ void UpdateTitle()
+ {
+ if (_txbTitle == null)
+ return;
+
+ _txbTitle.Text = Title ?? "";
+ }
+
+ void UpdateToolbar()
+ {
+ if (_txbTitle == null)
+ return;
+
+ _grd.Visibility = DetailTitleVisibility;
+ _grd.Background = ToolbarBackground;
+ _txbTitle.Foreground = ToolbarForeground;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/MasterDetailPageRenderer.cs b/Xamarin.Forms.Platform.WinRT/MasterDetailPageRenderer.cs
new file mode 100644
index 00000000..314cc794
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/MasterDetailPageRenderer.cs
@@ -0,0 +1,291 @@
+using System;
+using System.ComponentModel;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ public class MasterDetailPageRenderer : IVisualElementRenderer, ITitleProvider
+ {
+ MasterDetailControl _container;
+
+ bool _disposed;
+ IVisualElementRenderer _masterRenderer;
+ IVisualElementRenderer _detailRenderer;
+ bool _showTitle;
+ VisualElementTracker<Page, PageControl> _tracker;
+
+ public MasterDetailPage Element { get; private set; }
+
+ protected VisualElementTracker<Page, PageControl> Tracker
+ {
+ get { return _tracker; }
+ set
+ {
+ if (_tracker == value)
+ return;
+
+ if (_tracker != null)
+ {
+ _tracker.Dispose();
+ }
+
+ _tracker = value;
+ }
+ }
+
+ bool IsPopoverFullScreen
+ {
+ get { return Device.Idiom == TargetIdiom.Phone; }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ Brush ITitleProvider.BarBackgroundBrush
+ {
+ set { _container.ToolbarBackground = value; }
+ }
+
+ Brush ITitleProvider.BarForegroundBrush
+ {
+ set { _container.ToolbarForeground = value; }
+ }
+
+ bool ITitleProvider.ShowTitle
+ {
+ get { return _showTitle; }
+
+ set
+ {
+ if (_showTitle == value)
+ return;
+ _showTitle = value;
+ if (_showTitle)
+ _container.DetailTitleVisibility = Visibility.Visible;
+ else
+ _container.DetailTitleVisibility = Visibility.Collapsed;
+ }
+ }
+
+ string ITitleProvider.Title
+ {
+ get { return _container.Title; }
+
+ set { _container.Title = value; }
+ }
+
+ public FrameworkElement ContainerElement
+ {
+ get { return _container; }
+ }
+
+ VisualElement IVisualElementRenderer.Element
+ {
+ get { return Element; }
+ }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return new SizeRequest(new Size(Device.Info.ScaledScreenSize.Width, Device.Info.ScaledScreenSize.Height));
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ if (element != null && !(element is MasterDetailPage))
+ throw new ArgumentException("Element must be a Page", "element");
+
+ MasterDetailPage oldElement = Element;
+ Element = (MasterDetailPage)element;
+
+ if (oldElement != null)
+ {
+ oldElement.PropertyChanged -= OnElementPropertyChanged;
+ }
+
+ if (element != null)
+ {
+ if (_container == null)
+ {
+ _container = new MasterDetailControl();
+ _container.UserClosedPopover += OnUserClosedPopover;
+ _container.SizeChanged += OnNativeSizeChanged;
+
+ Tracker = new BackgroundTracker<PageControl>(Control.BackgroundProperty) { Element = (Page)element, Container = _container };
+
+ _container.Loaded += OnLoaded;
+ _container.Unloaded += OnUnloaded;
+ }
+
+ element.PropertyChanged += OnElementPropertyChanged;
+ UpdateBehavior();
+ SetMaster(Element.Master);
+ SetDetail(Element.Detail);
+ UpdateIsPresented();
+ }
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposing || _disposed)
+ return;
+
+ _disposed = true;
+
+ SetElement(null);
+ }
+
+ protected void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ EventHandler<VisualElementChangedEventArgs> changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "Master")
+ SetMaster(Element.Master);
+ else if (e.PropertyName == "Detail")
+ SetDetail(Element.Detail);
+ else if (e.PropertyName == MasterDetailPage.IsPresentedProperty.PropertyName)
+ UpdateIsPresented();
+ else if (e.PropertyName == MasterDetailPage.MasterBehaviorProperty.PropertyName)
+ UpdateBehavior();
+ else if (e.PropertyName == Page.TitleProperty.PropertyName)
+ UpdateTitle();
+ }
+
+ bool GetIsMasterAPopover()
+ {
+ // TODO: Support tablet being shrunk to a very small size
+ return !Element.ShouldShowSplitMode;
+ }
+
+ void OnLoaded(object sender, RoutedEventArgs args)
+ {
+ if (Element == null)
+ return;
+
+ Element.SendAppearing();
+ }
+
+ void OnNativeSizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ UpdateBounds(e.NewSize);
+ }
+
+ void OnUnloaded(object sender, RoutedEventArgs args)
+ {
+ if (Element == null)
+ return;
+
+ Element.SendDisappearing();
+ }
+
+ void OnUserClosedPopover(object sender, EventArgs e)
+ {
+ if (Element != null)
+ ((IElementController)Element).SetValueFromRenderer(MasterDetailPage.IsPresentedProperty, false);
+ }
+
+ void SetDetail(Page detailPage)
+ {
+ ((ITitleProvider)this).ShowTitle = detailPage is NavigationPage;
+
+ if (_detailRenderer != null)
+ {
+ FrameworkElement native = _detailRenderer.ContainerElement;
+ _container.DetailContent = null;
+ _detailRenderer = null;
+ }
+
+ if (detailPage == null)
+ return;
+
+ _detailRenderer = detailPage.GetOrCreateRenderer();
+ _container.DetailContent = _detailRenderer.ContainerElement;
+ UpdateTitle();
+ }
+
+ void SetMaster(Page masterPage)
+ {
+ if (_masterRenderer != null)
+ {
+ FrameworkElement native = _masterRenderer.ContainerElement;
+ _container.MasterContent = null;
+ _masterRenderer = null;
+ }
+
+ if (masterPage == null)
+ return;
+
+ _masterRenderer = masterPage.GetOrCreateRenderer();
+ _container.MasterContent = _masterRenderer.ContainerElement;
+ }
+
+ void UpdateBehavior()
+ {
+ string key = GetIsMasterAPopover() ? "MasterDetailPopup" : "MasterDetailSplit";
+ _container.Template = (Windows.UI.Xaml.Controls.ControlTemplate)Windows.UI.Xaml.Application.Current.Resources[key];
+ }
+
+ void UpdateBounds(bool isPresented)
+ {
+ UpdateBounds(new Windows.Foundation.Size(_container.ActualWidth, _container.ActualHeight), isPresented);
+ }
+
+ void UpdateBounds(Windows.Foundation.Size constraint)
+ {
+ UpdateBounds(constraint, Element.IsPresented);
+ }
+
+ void UpdateBounds(Windows.Foundation.Size constraint, bool isPresented)
+ {
+ if (constraint.Width <= 0 || constraint.Height <= 0)
+ return;
+
+ bool isPopover = GetIsMasterAPopover();
+ double masterWidth = 0;
+ if (isPresented || isPopover)
+ {
+ if (isPopover && IsPopoverFullScreen)
+ masterWidth = constraint.Width;
+ else
+ masterWidth = constraint.Width * .3;
+ }
+
+ double detailWidth = constraint.Width;
+ if (!isPopover)
+ detailWidth -= masterWidth;
+
+ Element.MasterBounds = new Rectangle(0, 0, masterWidth, constraint.Height);
+ Element.DetailBounds = new Rectangle(0, 0, detailWidth, constraint.Height);
+ }
+
+ void UpdateIsPresented()
+ {
+ UpdateBehavior();
+
+ bool isPresented = !GetIsMasterAPopover() || Element.IsPresented;
+ _container.IsMasterVisible = isPresented;
+
+ UpdateBounds(isPresented);
+ }
+
+ void UpdateTitle()
+ {
+ if (Element?.Detail == null)
+ return;
+
+ ((ITitleProvider)this).Title = (Element.Detail as NavigationPage)?.CurrentPage?.Title ?? Element.Title ?? Element?.Title;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/MenuItemCommand.cs b/Xamarin.Forms.Platform.WinRT/MenuItemCommand.cs
new file mode 100644
index 00000000..31574b44
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/MenuItemCommand.cs
@@ -0,0 +1,48 @@
+using System;
+using System.ComponentModel;
+using System.Windows.Input;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal class MenuItemCommand : ICommand
+ {
+ readonly MenuItem _menuItem;
+
+ public MenuItemCommand(MenuItem item)
+ {
+ _menuItem = item;
+ _menuItem.PropertyChanged += OnElementPropertyChanged;
+ }
+
+ public virtual bool CanExecute(object parameter)
+ {
+ return _menuItem.IsEnabled;
+ }
+
+ public event EventHandler CanExecuteChanged;
+
+ public void Execute(object parameter)
+ {
+ _menuItem.Activate();
+ }
+
+ void OnCanExecuteChanged()
+ {
+ EventHandler changed = CanExecuteChanged;
+ if (changed != null)
+ changed(this, EventArgs.Empty);
+ }
+
+ void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ OnCanExecuteChanged();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/NativeViewWrapper.cs b/Xamarin.Forms.Platform.WinRT/NativeViewWrapper.cs
new file mode 100644
index 00000000..824f0eed
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/NativeViewWrapper.cs
@@ -0,0 +1,30 @@
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class NativeViewWrapper : View
+ {
+ public NativeViewWrapper(FrameworkElement nativeElement, GetDesiredSizeDelegate getDesiredSizeDelegate = null, ArrangeOverrideDelegate arrangeOverrideDelegate = null,
+ MeasureOverrideDelegate measureOverrideDelegate = null)
+ {
+ GetDesiredSizeDelegate = getDesiredSizeDelegate;
+ ArrangeOverrideDelegate = arrangeOverrideDelegate;
+ MeasureOverrideDelegate = measureOverrideDelegate;
+ NativeElement = nativeElement;
+ }
+
+ public ArrangeOverrideDelegate ArrangeOverrideDelegate { get; set; }
+
+ public GetDesiredSizeDelegate GetDesiredSizeDelegate { get; }
+
+ public MeasureOverrideDelegate MeasureOverrideDelegate { get; set; }
+
+ public FrameworkElement NativeElement { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/NativeViewWrapperRenderer.cs b/Xamarin.Forms.Platform.WinRT/NativeViewWrapperRenderer.cs
new file mode 100644
index 00000000..0e669774
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/NativeViewWrapperRenderer.cs
@@ -0,0 +1,74 @@
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class NativeViewWrapperRenderer : ViewRenderer<NativeViewWrapper, FrameworkElement>
+ {
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ if (Element?.GetDesiredSizeDelegate == null)
+ {
+ return base.GetDesiredSize(widthConstraint, heightConstraint);
+ }
+
+ // The user has specified a different implementation of GetDesiredSize
+ SizeRequest? result = Element.GetDesiredSizeDelegate(this, widthConstraint, heightConstraint);
+
+ // If the delegate returns a SizeRequest, we use it;
+ // if it returns null, fall back to the default implementation
+ return result ?? base.GetDesiredSize(widthConstraint, heightConstraint);
+ }
+
+ protected override Windows.Foundation.Size ArrangeOverride(Windows.Foundation.Size finalSize)
+ {
+ if (Element?.ArrangeOverrideDelegate == null)
+ {
+ return base.ArrangeOverride(finalSize);
+ }
+
+ // The user has specified a different implementation of ArrangeOverride
+ Windows.Foundation.Size? result = Element.ArrangeOverrideDelegate(this, finalSize);
+
+ // If the delegate returns a Size, we use it;
+ // if it returns null, fall back to the default implementation
+ return result ?? base.ArrangeOverride(finalSize);
+ }
+
+ protected Windows.Foundation.Size MeasureOverride()
+ {
+ return MeasureOverride(new Windows.Foundation.Size());
+ }
+
+ protected override Windows.Foundation.Size MeasureOverride(Windows.Foundation.Size availableSize)
+ {
+ if (Element?.MeasureOverrideDelegate == null)
+ {
+ return base.MeasureOverride(availableSize);
+ }
+
+ // The user has specified a different implementation of MeasureOverride
+ Windows.Foundation.Size? result = Element.MeasureOverrideDelegate(this, availableSize);
+
+ // If the delegate returns a Size, we use it;
+ // if it returns null, fall back to the default implementation
+ return result ?? base.MeasureOverride(availableSize);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<NativeViewWrapper> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement == null)
+ {
+ SetNativeControl(Element.NativeElement);
+ Control.LayoutUpdated += (sender, args) => { Element?.InvalidateMeasure(InvalidationTrigger.MeasureChanged); };
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/NavigationPageRenderer.cs b/Xamarin.Forms.Platform.WinRT/NavigationPageRenderer.cs
new file mode 100644
index 00000000..1e48d7ea
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/NavigationPageRenderer.cs
@@ -0,0 +1,554 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading.Tasks;
+using Windows.Devices.Input;
+using Windows.UI.Input;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Automation;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Media.Animation;
+#if WINDOWS_UWP
+using Windows.UI.Xaml.Data;
+using Windows.UI.Core;
+
+#endif
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class NavigationPageRenderer : IVisualElementRenderer, ITitleProvider, IToolbarProvider
+#if WINDOWS_UWP
+ , IToolBarForegroundBinder
+#endif
+ {
+ PageControl _container;
+ Page _currentPage;
+ Page _previousPage;
+
+ bool _disposed;
+#if WINDOWS_UWP
+ SystemNavigationManager _navManager;
+#endif
+ MasterDetailPage _parentMasterDetailPage;
+ TabbedPage _parentTabbedPage;
+ bool _showTitle = true;
+ VisualElementTracker<Page, PageControl> _tracker;
+ ContentThemeTransition _transition;
+
+ public NavigationPage Element { get; private set; }
+
+ protected VisualElementTracker<Page, PageControl> Tracker
+ {
+ get { return _tracker; }
+ set
+ {
+ if (_tracker == value)
+ return;
+
+ if (_tracker != null)
+ _tracker.Dispose();
+
+ _tracker = value;
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ Brush ITitleProvider.BarBackgroundBrush
+ {
+ set
+ {
+ _container.NavigationBarBackground = value;
+ UpdateTitleOnParents();
+ }
+ }
+
+ Brush ITitleProvider.BarForegroundBrush
+ {
+ set
+ {
+ _container.TitleBrush = value;
+ UpdateTitleOnParents();
+ }
+ }
+
+ bool ITitleProvider.ShowTitle
+ {
+ get { return _showTitle; }
+ set
+ {
+ if (_showTitle == value)
+ return;
+
+ _showTitle = value;
+ UpdateNavigationBarVisible();
+ UpdateTitleOnParents();
+ }
+ }
+
+ public string Title
+ {
+ get { return _currentPage?.Title; }
+
+ set { }
+ }
+
+ Task<CommandBar> IToolbarProvider.GetCommandBarAsync()
+ {
+ return ((IToolbarProvider)_container)?.GetCommandBarAsync();
+ }
+
+ public FrameworkElement ContainerElement
+ {
+ get { return _container; }
+ }
+
+ VisualElement IVisualElementRenderer.Element
+ {
+ get { return Element; }
+ }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ var constraint = new Windows.Foundation.Size(widthConstraint, heightConstraint);
+ IVisualElementRenderer childRenderer = Platform.GetRenderer(Element.CurrentPage);
+ FrameworkElement child = childRenderer.ContainerElement;
+
+ double oldWidth = child.Width;
+ double oldHeight = child.Height;
+
+ child.Height = double.NaN;
+ child.Width = double.NaN;
+
+ child.Measure(constraint);
+ var result = new Size(Math.Ceiling(child.DesiredSize.Width), Math.Ceiling(child.DesiredSize.Height));
+
+ child.Width = oldWidth;
+ child.Height = oldHeight;
+
+ return new SizeRequest(result);
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ if (element != null && !(element is NavigationPage))
+ throw new ArgumentException("Element must be a Page", "element");
+
+ NavigationPage oldElement = Element;
+ Element = (NavigationPage)element;
+
+ if (oldElement != null)
+ {
+ oldElement.PushRequested -= OnPushRequested;
+ oldElement.PopRequested -= OnPopRequested;
+ oldElement.InternalChildren.CollectionChanged -= OnChildrenChanged;
+ oldElement.PropertyChanged -= OnElementPropertyChanged;
+ }
+
+ if (element != null)
+ {
+ if (_container == null)
+ {
+ _container = new PageControl();
+ _container.PointerPressed += OnPointerPressed;
+ _container.SizeChanged += OnNativeSizeChanged;
+ _container.BackClicked += OnBackClicked;
+
+ Tracker = new BackgroundTracker<PageControl>(Control.BackgroundProperty) { Element = (Page)element, Container = _container };
+
+ SetPage(Element.CurrentPage, false, false);
+
+ _container.Loaded += OnLoaded;
+ _container.Unloaded += OnUnloaded;
+ }
+
+ _container.DataContext = Element.CurrentPage;
+
+ UpdatePadding();
+ LookupRelevantParents();
+ UpdateTitleColor();
+ UpdateNavigationBarBackground();
+ Element.PropertyChanged += OnElementPropertyChanged;
+ Element.PushRequested += OnPushRequested;
+ Element.PopRequested += OnPopRequested;
+ Element.InternalChildren.CollectionChanged += OnChildrenChanged;
+
+ if (!string.IsNullOrEmpty(Element.AutomationId))
+ _container.SetValue(AutomationProperties.AutomationIdProperty, Element.AutomationId);
+
+ PushExistingNavigationStack();
+ }
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+ }
+
+ protected void Dispose(bool disposing)
+ {
+ if (!disposing || _disposed)
+ return;
+ Element?.SendDisappearing();
+ _disposed = true;
+
+ _container.PointerPressed -= OnPointerPressed;
+ _container.SizeChanged -= OnNativeSizeChanged;
+ _container.BackClicked -= OnBackClicked;
+
+ SetElement(null);
+ SetPage(null, false, true);
+ _previousPage = null;
+
+ if (_parentTabbedPage != null)
+ _parentTabbedPage.PropertyChanged -= MultiPagePropertyChanged;
+
+ if (_parentMasterDetailPage != null)
+ _parentMasterDetailPage.PropertyChanged -= MultiPagePropertyChanged;
+ }
+
+ protected void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ EventHandler<VisualElementChangedEventArgs> changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ Brush GetBarBackgroundBrush()
+ {
+#if WINDOWS_UWP
+ object defaultColor = Windows.UI.Xaml.Application.Current.Resources["SystemControlBackgroundChromeMediumLowBrush"];
+#else
+ object defaultColor = Windows.UI.Xaml.Application.Current.Resources["ApplicationPageBackgroundThemeBrush"];
+#endif
+ if (Element.BarBackgroundColor.IsDefault && defaultColor != null)
+ return (Brush)defaultColor;
+ return Element.BarBackgroundColor.ToBrush();
+ }
+
+ Brush GetBarForegroundBrush()
+ {
+ object defaultColor = Windows.UI.Xaml.Application.Current.Resources["ApplicationForegroundThemeBrush"];
+ if (Element.BarTextColor.IsDefault)
+ return (Brush)defaultColor;
+ return Element.BarTextColor.ToBrush();
+ }
+
+ Task<CommandBar> GetCommandBarAsync()
+ {
+ var platform = (Platform)Element.Platform;
+ IToolbarProvider toolbarProvider = platform.GetToolbarProvider();
+ if (toolbarProvider == null)
+ return Task.FromResult<CommandBar>(null);
+
+ return toolbarProvider.GetCommandBarAsync();
+ }
+
+ bool GetIsNavBarPossible()
+ {
+ return _showTitle;
+ }
+
+ IToolbarProvider GetToolbarProvider()
+ {
+ var platform = (Platform)Element.Platform;
+ return platform.GetToolbarProvider();
+ }
+
+ void LookupRelevantParents()
+ {
+ IEnumerable<Page> parentPages = Element.GetParentPages();
+
+ if (_parentTabbedPage != null)
+ _parentTabbedPage.PropertyChanged -= MultiPagePropertyChanged;
+ if (_parentMasterDetailPage != null)
+ _parentMasterDetailPage.PropertyChanged -= MultiPagePropertyChanged;
+
+ foreach (Page parentPage in parentPages)
+ {
+ _parentTabbedPage = parentPage as TabbedPage;
+ _parentMasterDetailPage = parentPage as MasterDetailPage;
+ }
+
+ if (_parentTabbedPage != null)
+ _parentTabbedPage.PropertyChanged += MultiPagePropertyChanged;
+ if (_parentMasterDetailPage != null)
+ _parentMasterDetailPage.PropertyChanged += MultiPagePropertyChanged;
+#if WINDOWS_UWP
+ ((ITitleProvider)this).ShowTitle = _parentTabbedPage == null && _parentMasterDetailPage == null;
+#else
+ if (Device.Idiom == TargetIdiom.Phone && _parentTabbedPage != null)
+ ((ITitleProvider)this).ShowTitle = false;
+ else
+ ((ITitleProvider)this).ShowTitle = true;
+#endif
+ UpdateTitleOnParents();
+ }
+
+ void MultiPagePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "CurrentPage" || e.PropertyName == "Detail")
+ UpdateTitleOnParents();
+ }
+
+ async void OnBackClicked(object sender, RoutedEventArgs e)
+ {
+ await Element.PopAsync();
+ }
+
+ void OnChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ UpdateBackButton();
+ }
+
+ void OnCurrentPagePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == NavigationPage.HasBackButtonProperty.PropertyName)
+ UpdateBackButton();
+ else if (e.PropertyName == NavigationPage.BackButtonTitleProperty.PropertyName)
+ UpdateBackButtonTitle();
+ else if (e.PropertyName == NavigationPage.HasNavigationBarProperty.PropertyName)
+ UpdateNavigationBarVisible();
+ }
+
+ void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == NavigationPage.BarTextColorProperty.PropertyName)
+ UpdateTitleColor();
+ else if (e.PropertyName == NavigationPage.BarBackgroundColorProperty.PropertyName)
+ UpdateNavigationBarBackground();
+ else if (e.PropertyName == Page.PaddingProperty.PropertyName)
+ UpdatePadding();
+ }
+
+ void OnLoaded(object sender, RoutedEventArgs args)
+ {
+ if (Element == null)
+ return;
+
+#if WINDOWS_UWP
+ _navManager = SystemNavigationManager.GetForCurrentView();
+#endif
+ Element.SendAppearing();
+ UpdateBackButton();
+ UpdateTitleOnParents();
+ }
+
+ void OnNativeSizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ UpdateContainerArea();
+ }
+
+ void OnPointerPressed(object sender, PointerRoutedEventArgs e)
+ {
+ if (e.Handled)
+ return;
+
+ PointerPoint point = e.GetCurrentPoint(_container);
+ if (point == null)
+ return;
+
+ if (point.PointerDevice.PointerDeviceType != PointerDeviceType.Mouse)
+ return;
+
+ if (point.Properties.IsXButton1Pressed)
+ {
+ e.Handled = true;
+ OnBackClicked(_container, e);
+ }
+ }
+
+ void OnPopRequested(object sender, NavigationRequestedEventArgs e)
+ {
+ var newCurrent = (Page)Element.InternalChildren[Element.InternalChildren.Count - 2];
+ SetPage(newCurrent, e.Animated, true);
+ }
+
+ void OnPushRequested(object sender, NavigationRequestedEventArgs e)
+ {
+ SetPage(e.Page, e.Animated, false);
+ }
+
+ void OnUnloaded(object sender, RoutedEventArgs args)
+ {
+ if (Element == null)
+ return;
+
+ Element.SendDisappearing();
+ }
+
+ void PushExistingNavigationStack()
+ {
+ for (int i = Element.StackCopy.Count - 1; i >= 0; i--)
+ SetPage(Element.StackCopy.ElementAt(i), false, false);
+ }
+
+ void SetPage(Page page, bool isAnimated, bool isPopping)
+ {
+ if (_currentPage != null)
+ {
+ if (isPopping)
+ _currentPage.Cleanup();
+
+ _container.Content = null;
+
+ _currentPage.PropertyChanged -= OnCurrentPagePropertyChanged;
+ }
+
+ _previousPage = _currentPage;
+ _currentPage = page;
+
+ if (page == null)
+ return;
+
+ UpdateBackButton();
+ UpdateBackButtonTitle();
+
+ page.PropertyChanged += OnCurrentPagePropertyChanged;
+
+ IVisualElementRenderer renderer = page.GetOrCreateRenderer();
+
+ UpdateNavigationBarVisible();
+ UpdateTitleOnParents();
+
+ if (isAnimated && _transition == null)
+ {
+ _transition = new ContentThemeTransition();
+ _container.ContentTransitions = new TransitionCollection();
+ }
+
+ if (!isAnimated && _transition != null)
+ _container.ContentTransitions.Remove(_transition);
+ else if (isAnimated && _container.ContentTransitions.Count == 0)
+ _container.ContentTransitions.Add(_transition);
+
+ _container.Content = renderer.ContainerElement;
+ _container.DataContext = page;
+ }
+
+ void UpdateBackButton()
+ {
+ bool showBackButton = Element.InternalChildren.Count > 1 && NavigationPage.GetHasBackButton(_currentPage);
+ _container.ShowBackButton = showBackButton;
+
+#if WINDOWS_UWP
+ if (_navManager != null)
+ {
+ _navManager.AppViewBackButtonVisibility = showBackButton ? AppViewBackButtonVisibility.Visible : AppViewBackButtonVisibility.Collapsed;
+ }
+#endif
+ }
+
+ void UpdateBackButtonTitle()
+ {
+ string title = null;
+ if (_previousPage != null)
+ title = NavigationPage.GetBackButtonTitle(_previousPage);
+
+ _container.BackButtonTitle = title;
+ }
+
+ void UpdateContainerArea()
+ {
+ Element.ContainerArea = new Rectangle(0, 0, _container.ContentWidth, _container.ContentHeight);
+ }
+
+ void UpdateNavigationBarBackground()
+ {
+ (this as ITitleProvider).BarBackgroundBrush = GetBarBackgroundBrush();
+ }
+
+ void UpdateNavigationBarVisible()
+ {
+ UpdateTitleOnParents();
+
+ bool showing = _container.ShowNavigationBar;
+ bool newValue = GetIsNavBarPossible() && NavigationPage.GetHasNavigationBar(_currentPage);
+ if (showing == newValue)
+ return;
+
+ _container.ShowNavigationBar = newValue;
+
+ // Force ContentHeight/Width to update, doesn't work from inside PageControl for some reason
+ _container.UpdateLayout();
+ UpdateContainerArea();
+ }
+
+ void UpdatePadding()
+ {
+ _container.TitleInset = Element.Padding.Left;
+ }
+
+ void UpdateTitleColor()
+ {
+ (this as ITitleProvider).BarForegroundBrush = GetBarForegroundBrush();
+ }
+
+ async void UpdateTitleOnParents()
+ {
+ if (Element == null)
+ return;
+
+ ITitleProvider render = null;
+ if (_parentTabbedPage != null)
+ {
+ render = Platform.GetRenderer(_parentTabbedPage) as ITitleProvider;
+ if (render != null)
+ render.ShowTitle = (_parentTabbedPage.CurrentPage == Element) && NavigationPage.GetHasNavigationBar(_currentPage);
+ }
+
+ if (_parentMasterDetailPage != null)
+ {
+ render = Platform.GetRenderer(_parentMasterDetailPage) as ITitleProvider;
+ if (render != null)
+ render.ShowTitle = (_parentMasterDetailPage.Detail == Element) && NavigationPage.GetHasNavigationBar(_currentPage);
+ }
+
+ if (render != null && render.ShowTitle)
+ {
+ render.Title = _currentPage.Title;
+ render.BarBackgroundBrush = GetBarBackgroundBrush();
+ render.BarForegroundBrush = GetBarForegroundBrush();
+#if WINDOWS_UWP
+ await (Element.Platform as Platform).UpdateToolbarItems();
+#endif
+ }
+ else if (_showTitle)
+ {
+#if WINDOWS_UWP
+ await (Element.Platform as Platform).UpdateToolbarItems();
+#endif
+ }
+ }
+
+#if WINDOWS_UWP
+ public void BindForegroundColor(AppBar appBar)
+ {
+ SetAppBarForegroundBinding(appBar);
+ }
+
+ public void BindForegroundColor(AppBarButton button)
+ {
+ SetAppBarForegroundBinding(button);
+ }
+
+ void SetAppBarForegroundBinding(FrameworkElement element)
+ {
+ element.SetBinding(Control.ForegroundProperty,
+ new Windows.UI.Xaml.Data.Binding { Path = new PropertyPath("TitleBrush"), Source = _container, RelativeSource = new RelativeSource { Mode = RelativeSourceMode.TemplatedParent } });
+ }
+#endif
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/PageControl.xaml b/Xamarin.Forms.Platform.WinRT/PageControl.xaml
new file mode 100644
index 00000000..1f4872e2
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/PageControl.xaml
@@ -0,0 +1,10 @@
+<ContentControl
+ x:Class="Xamarin.Forms.Platform.WinRT.PageControl"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ mc:Ignorable="d" d:DesignWidth="1024"
+ HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
+
+</ContentControl> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/PageControl.xaml.cs b/Xamarin.Forms.Platform.WinRT/PageControl.xaml.cs
new file mode 100644
index 00000000..0991db42
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/PageControl.xaml.cs
@@ -0,0 +1,166 @@
+using System.Threading.Tasks;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public sealed partial class PageControl : IToolbarProvider
+ {
+ public static readonly DependencyProperty InvisibleBackButtonCollapsedProperty = DependencyProperty.Register("InvisibleBackButtonCollapsed", typeof(bool), typeof(PageControl),
+ new PropertyMetadata(true, OnInvisibleBackButtonCollapsedChanged));
+
+ public static readonly DependencyProperty ShowBackButtonProperty = DependencyProperty.Register("ShowBackButton", typeof(bool), typeof(PageControl),
+ new PropertyMetadata(false, OnShowBackButtonChanged));
+
+ public static readonly DependencyProperty ShowNavigationBarProperty = DependencyProperty.Register("ShowNavigationBar", typeof(bool), typeof(PageControl), new PropertyMetadata(true));
+
+ public static readonly DependencyProperty NavigationBarBackgroundProperty = DependencyProperty.Register("NavigationBarBackground", typeof(Brush), typeof(PageControl),
+ new PropertyMetadata(default(Brush)));
+
+ public static readonly DependencyProperty BackButtonTitleProperty = DependencyProperty.Register("BackButtonTitle", typeof(string), typeof(PageControl), new PropertyMetadata(false));
+
+ public static readonly DependencyProperty ContentMarginProperty = DependencyProperty.Register("ContentMargin", typeof(Windows.UI.Xaml.Thickness), typeof(PageControl),
+ new PropertyMetadata(default(Windows.UI.Xaml.Thickness)));
+
+ public static readonly DependencyProperty TitleInsetProperty = DependencyProperty.Register("TitleInset", typeof(double), typeof(PageControl), new PropertyMetadata(default(double)));
+
+ public static readonly DependencyProperty TitleBrushProperty = DependencyProperty.Register("TitleBrush", typeof(Brush), typeof(PageControl), new PropertyMetadata(null));
+
+ AppBarButton _backButton;
+ CommandBar _commandBar;
+
+ TaskCompletionSource<CommandBar> _commandBarTcs;
+ Windows.UI.Xaml.Controls.ContentPresenter _presenter;
+
+ public PageControl()
+ {
+ InitializeComponent();
+ }
+
+ public string BackButtonTitle
+ {
+ get { return (string)GetValue(BackButtonTitleProperty); }
+ set { SetValue(BackButtonTitleProperty, value); }
+ }
+
+ public double ContentHeight
+ {
+ get { return _presenter != null ? _presenter.ActualHeight : 0; }
+ }
+
+ public Windows.UI.Xaml.Thickness ContentMargin
+ {
+ get { return (Windows.UI.Xaml.Thickness)GetValue(ContentMarginProperty); }
+ set { SetValue(ContentMarginProperty, value); }
+ }
+
+ public double ContentWidth
+ {
+ get { return _presenter != null ? _presenter.ActualWidth : 0; }
+ }
+
+ public bool InvisibleBackButtonCollapsed
+ {
+ get { return (bool)GetValue(InvisibleBackButtonCollapsedProperty); }
+ set { SetValue(InvisibleBackButtonCollapsedProperty, value); }
+ }
+
+ public Brush NavigationBarBackground
+ {
+ get { return (Brush)GetValue(NavigationBarBackgroundProperty); }
+ set { SetValue(NavigationBarBackgroundProperty, value); }
+ }
+
+ public bool ShowBackButton
+ {
+ get { return (bool)GetValue(ShowBackButtonProperty); }
+ set { SetValue(ShowBackButtonProperty, value); }
+ }
+
+ public bool ShowNavigationBar
+ {
+ get { return (bool)GetValue(ShowNavigationBarProperty); }
+ set { SetValue(ShowNavigationBarProperty, value); }
+ }
+
+ public Brush TitleBrush
+ {
+ get { return (Brush)GetValue(TitleBrushProperty); }
+ set { SetValue(TitleBrushProperty, value); }
+ }
+
+ public double TitleInset
+ {
+ get { return (double)GetValue(TitleInsetProperty); }
+ set { SetValue(TitleInsetProperty, value); }
+ }
+
+ Task<CommandBar> IToolbarProvider.GetCommandBarAsync()
+ {
+ if (_commandBar != null)
+ return Task.FromResult(_commandBar);
+
+ _commandBarTcs = new TaskCompletionSource<CommandBar>();
+ ApplyTemplate();
+ return _commandBarTcs.Task;
+ }
+
+ public event RoutedEventHandler BackClicked;
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ _backButton = GetTemplateChild("backButton") as AppBarButton;
+ if (_backButton != null)
+ _backButton.Click += OnBackClicked;
+
+ _presenter = GetTemplateChild("presenter") as Windows.UI.Xaml.Controls.ContentPresenter;
+
+ _commandBar = GetTemplateChild("CommandBar") as CommandBar;
+
+ TaskCompletionSource<CommandBar> tcs = _commandBarTcs;
+ if (tcs != null)
+ {
+ tcs.SetResult(_commandBar);
+ }
+ }
+
+ void OnBackClicked(object sender, RoutedEventArgs e)
+ {
+ RoutedEventHandler clicked = BackClicked;
+ if (clicked != null)
+ clicked(this, e);
+ }
+
+ static void OnInvisibleBackButtonCollapsedChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
+ {
+ ((PageControl)dependencyObject).UpdateBackButton();
+ }
+
+ static void OnShowBackButtonChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
+ {
+ ((PageControl)dependencyObject).UpdateBackButton();
+ }
+
+ void UpdateBackButton()
+ {
+ if (_backButton == null)
+ return;
+
+ if (ShowBackButton)
+ _backButton.Visibility = Visibility.Visible;
+ else
+ _backButton.Visibility = InvisibleBackButtonCollapsed ? Visibility.Collapsed : Visibility.Visible;
+
+ _backButton.Opacity = ShowBackButton ? 1 : 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/PageRenderer.cs b/Xamarin.Forms.Platform.WinRT/PageRenderer.cs
new file mode 100644
index 00000000..d33ff028
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/PageRenderer.cs
@@ -0,0 +1,80 @@
+using System.Collections.ObjectModel;
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class PageRenderer : VisualElementRenderer<Page, FrameworkElement>
+ {
+ bool _disposed;
+
+ bool _loaded;
+
+ protected override void Dispose(bool disposing)
+ {
+ if (!disposing || _disposed)
+ return;
+
+ _disposed = true;
+
+ if (Element != null)
+ {
+ ReadOnlyCollection<Element> children = Element.LogicalChildren;
+ for (var i = 0; i < children.Count; i++)
+ {
+ var visualChild = children[i] as VisualElement;
+ visualChild?.Cleanup();
+ }
+ Element?.SendDisappearing();
+ }
+
+ base.Dispose();
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ {
+ e.OldElement.SendDisappearing();
+ }
+
+ if (e.NewElement != null)
+ {
+ if (e.OldElement == null)
+ {
+ Loaded += OnLoaded;
+ Unloaded += OnUnloaded;
+
+ Tracker = new BackgroundTracker<FrameworkElement>(BackgroundProperty);
+ }
+
+ if (_loaded)
+ e.NewElement.SendAppearing();
+ }
+ }
+
+ void OnLoaded(object sender, RoutedEventArgs args)
+ {
+ var carouselPage = Element?.Parent as CarouselPage;
+ if (carouselPage != null && carouselPage.Children[0] != Element)
+ {
+ return;
+ }
+ _loaded = true;
+ Element?.SendAppearing();
+ }
+
+ void OnUnloaded(object sender, RoutedEventArgs args)
+ {
+ _loaded = false;
+ Element?.SendDisappearing();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/PageToRenderedElementConverter.cs b/Xamarin.Forms.Platform.WinRT/PageToRenderedElementConverter.cs
new file mode 100644
index 00000000..68e23d31
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/PageToRenderedElementConverter.cs
@@ -0,0 +1,31 @@
+using System;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class PageToRenderedElementConverter : Windows.UI.Xaml.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ var page = value as Page;
+ if (page == null)
+ return null;
+
+ IVisualElementRenderer renderer = page.GetOrCreateRenderer();
+ if (renderer == null)
+ return null;
+
+ return renderer.ContainerElement;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotImplementedException();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/PickerRenderer.cs b/Xamarin.Forms.Platform.WinRT/PickerRenderer.cs
new file mode 100644
index 00000000..a7fcbb41
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/PickerRenderer.cs
@@ -0,0 +1,147 @@
+using System;
+using System.ComponentModel;
+using System.Threading.Tasks;
+using Windows.UI.Core;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class PickerRenderer : ViewRenderer<Picker, FormsComboBox>
+ {
+ bool _isAnimating;
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (Control != null)
+ {
+ _isAnimating = false;
+ Control.SelectionChanged -= OnControlSelectionChanged;
+ Control.DropDownOpened -= OnDropDownOpenStateChanged;
+ Control.DropDownClosed -= OnDropDownOpenStateChanged;
+ Control.OpenAnimationCompleted -= ControlOnOpenAnimationCompleted;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
+ {
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new FormsComboBox());
+ Control.SelectionChanged += OnControlSelectionChanged;
+ Control.DropDownOpened += OnDropDownOpenStateChanged;
+ Control.DropDownClosed += OnDropDownOpenStateChanged;
+ Control.OpenAnimationCompleted += ControlOnOpenAnimationCompleted;
+ Control.ClosedAnimationStarted += ControlOnClosedAnimationStarted;
+ }
+
+ Control.ItemsSource = Element.Items;
+
+ UpdateTitle();
+ UpdateSelectedIndex();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Picker.SelectedIndexProperty.PropertyName)
+ UpdateSelectedIndex();
+ else if (e.PropertyName == Picker.TitleProperty.PropertyName)
+ UpdateTitle();
+ }
+
+ void ControlOnClosedAnimationStarted(object sender, EventArgs eventArgs)
+ {
+ if (!Control.IsFullScreen)
+ {
+ // Start refreshing while the control's closing animation runs;
+ // OnDropDownOpenStateChanged will take care of stopping the refresh
+ StartAnimationRefresh();
+ }
+ }
+
+ void ControlOnOpenAnimationCompleted(object sender, EventArgs eventArgs)
+ {
+ _isAnimating = false;
+ if (!Control.IsFullScreen)
+ {
+ // Force a final redraw after the closing animation has completed
+ Element?.InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+ }
+
+ void OnControlSelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (Element != null)
+ Element.SelectedIndex = Control.SelectedIndex;
+ }
+
+ void OnDropDownOpenStateChanged(object sender, object o)
+ {
+ if (Control.IsDropDownOpen)
+ {
+ if (Control.IsOpeningAnimated && !Control.IsFullScreen)
+ {
+ // Start running the animation refresh;
+ // ControlOnOpenAnimationCompleted will take care of stopping it
+ StartAnimationRefresh();
+ }
+ else
+ {
+ Element?.InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+ }
+ else
+ {
+ // The ComboBox is now closed; if we were animating the closure, stop
+ _isAnimating = false;
+ // and force the final redraw
+ Element?.InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+ }
+
+ /// <summary>
+ /// Forces redraw of the control during opening/closing animations to provide
+ /// a smoother sliding animation for the surrounding controls
+ /// Only applies on the phone and only when there are fewer than 6 items in the picker
+ /// </summary>
+ void StartAnimationRefresh()
+ {
+ _isAnimating = true;
+ Task.Factory.StartNew(async () =>
+ {
+ while (_isAnimating)
+ {
+ await Task.Delay(16);
+ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Element?.InvalidateMeasure(InvalidationTrigger.MeasureChanged));
+ }
+ });
+ }
+
+ void UpdateSelectedIndex()
+ {
+ Control.SelectedIndex = Element.SelectedIndex;
+ }
+
+ void UpdateTitle()
+ {
+ Control.Header = Element.Title;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/Platform.cs b/Xamarin.Forms.Platform.WinRT/Platform.cs
new file mode 100644
index 00000000..df16ddc9
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/Platform.cs
@@ -0,0 +1,721 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+using Windows.UI;
+using Windows.UI.Popups;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Media.Animation;
+
+#if WINDOWS_UWP
+using Windows.Foundation.Metadata;
+using Windows.UI.ViewManagement;
+#endif
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public abstract class Platform : IPlatform, INavigation, IToolbarProvider
+ {
+ internal static readonly BindableProperty RendererProperty = BindableProperty.CreateAttached("Renderer", typeof(IVisualElementRenderer), typeof(Platform), default(IVisualElementRenderer));
+
+ public static IVisualElementRenderer GetRenderer(VisualElement element)
+ {
+ return (IVisualElementRenderer)element.GetValue(RendererProperty);
+ }
+
+ public static void SetRenderer(VisualElement element, IVisualElementRenderer value)
+ {
+ element.SetValue(RendererProperty, value);
+ element.IsPlatformEnabled = value != null;
+ }
+
+ public static IVisualElementRenderer CreateRenderer(VisualElement element)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ IVisualElementRenderer renderer = Registrar.Registered.GetHandler<IVisualElementRenderer>(element.GetType()) ?? new DefaultRenderer();
+ renderer.SetElement(element);
+ return renderer;
+ }
+
+ internal Platform(Windows.UI.Xaml.Controls.Page page)
+ {
+ if (page == null)
+ throw new ArgumentNullException("page");
+
+ _page = page;
+
+ _container = new Canvas { Style = (Windows.UI.Xaml.Style)Windows.UI.Xaml.Application.Current.Resources["RootContainerStyle"] };
+
+ _page.Content = _container;
+
+ _container.SizeChanged += OnRendererSizeChanged;
+
+ MessagingCenter.Subscribe(this, Page.BusySetSignalName, (Page sender, bool enabled) =>
+ {
+ Windows.UI.Xaml.Controls.ProgressBar indicator = GetBusyIndicator();
+ indicator.Visibility = enabled ? Visibility.Visible : Visibility.Collapsed;
+ });
+
+ _toolbarTracker.CollectionChanged += OnToolbarItemsChanged;
+
+ MessagingCenter.Subscribe<Page, AlertArguments>(this, Page.AlertSignalName, OnPageAlert);
+ MessagingCenter.Subscribe<Page, ActionSheetArguments>(this, Page.ActionSheetSignalName, OnPageActionSheet);
+
+ UpdateBounds();
+
+#if WINDOWS_UWP
+ if (ApiInformation.IsTypePresent(typeof(StatusBar).ToString()))
+ {
+ StatusBar statusBar = StatusBar.GetForCurrentView();
+ statusBar.Showing += (sender, args) => UpdateBounds();
+ statusBar.Hiding += (sender, args) => UpdateBounds();
+ }
+#endif
+ }
+
+ internal void SetPage(Page newRoot)
+ {
+ if (newRoot == null)
+ throw new ArgumentNullException("newRoot");
+
+ _navModel.Clear();
+
+ _navModel.Push(newRoot, null);
+ newRoot.NavigationProxy.Inner = this;
+ SetCurrent(newRoot, false, true);
+ }
+
+ public IReadOnlyList<Page> NavigationStack
+ {
+ get { return _navModel.Tree.Last(); }
+ }
+
+ public IReadOnlyList<Page> ModalStack
+ {
+ get { return _navModel.Modals.ToList(); }
+ }
+
+ Task INavigation.PushAsync(Page root)
+ {
+ return ((INavigation)this).PushAsync(root, true);
+ }
+
+ Task<Page> INavigation.PopAsync()
+ {
+ return ((INavigation)this).PopAsync(true);
+ }
+
+ Task INavigation.PopToRootAsync()
+ {
+ return ((INavigation)this).PopToRootAsync(true);
+ }
+
+ Task INavigation.PushAsync(Page root, bool animated)
+ {
+ throw new InvalidOperationException("PushAsync is not supported globally on Windows, please use a NavigationPage.");
+ }
+
+ Task<Page> INavigation.PopAsync(bool animated)
+ {
+ throw new InvalidOperationException("PopAsync is not supported globally on Windows, please use a NavigationPage.");
+ }
+
+ Task INavigation.PopToRootAsync(bool animated)
+ {
+ throw new InvalidOperationException("PopToRootAsync is not supported globally on Windows, please use a NavigationPage.");
+ }
+
+ void INavigation.RemovePage(Page page)
+ {
+ throw new InvalidOperationException("RemovePage is not supported globally on Windows, please use a NavigationPage.");
+ }
+
+ void INavigation.InsertPageBefore(Page page, Page before)
+ {
+ throw new InvalidOperationException("InsertPageBefore is not supported globally on Windows, please use a NavigationPage.");
+ }
+
+ Task INavigation.PushModalAsync(Page page)
+ {
+ return ((INavigation)this).PushModalAsync(page, true);
+ }
+
+ Task<Page> INavigation.PopModalAsync()
+ {
+ return ((INavigation)this).PopModalAsync(true);
+ }
+
+ Task INavigation.PushModalAsync(Page page, bool animated)
+ {
+ if (page == null)
+ throw new ArgumentNullException("page");
+
+ var tcs = new TaskCompletionSource<bool>();
+ _navModel.PushModal(page);
+ SetCurrent(page, animated, completedCallback: () => tcs.SetResult(true));
+ page.NavigationProxy.Inner = this;
+ return tcs.Task;
+ }
+
+ Task<Page> INavigation.PopModalAsync(bool animated)
+ {
+ var tcs = new TaskCompletionSource<Page>();
+ Page result = _navModel.PopModal();
+ SetCurrent(_navModel.CurrentPage, animated, true, () => tcs.SetResult(result));
+ return tcs.Task;
+ }
+
+ SizeRequest IPlatform.GetNativeSize(VisualElement element, double widthConstraint, double heightConstraint)
+ {
+ // Hack around the fact that Canvas ignores the child constraints.
+ // It is entirely possible using Canvas as our base class is not wise.
+ // FIXME: This should not be an if statement. Probably need to define an interface here.
+ if (widthConstraint > 0 && heightConstraint > 0)
+ {
+ IVisualElementRenderer elementRenderer = GetRenderer(element);
+ if (elementRenderer != null)
+ return elementRenderer.GetDesiredSize(widthConstraint, heightConstraint);
+ }
+
+ return new SizeRequest();
+ }
+
+ internal virtual Rectangle WindowBounds
+ {
+ get { return _bounds; }
+ }
+
+ internal void UpdatePageSizes()
+ {
+ Rectangle bounds = WindowBounds;
+ if (bounds.IsEmpty)
+ return;
+ foreach (Page root in _navModel.Roots)
+ {
+ root.Layout(bounds);
+ IVisualElementRenderer renderer = GetRenderer(root);
+ if (renderer != null)
+ {
+ renderer.ContainerElement.Width = _container.ActualWidth;
+ renderer.ContainerElement.Height = _container.ActualHeight;
+ }
+ }
+ }
+
+ internal IToolbarProvider GetToolbarProvider()
+ {
+ IToolbarProvider provider = null;
+
+ Page element = _currentPage;
+ while (element != null)
+ {
+ provider = GetRenderer(element) as IToolbarProvider;
+ if (provider != null)
+ break;
+
+ var pageContainer = element as IPageContainer<Page>;
+ element = pageContainer?.CurrentPage;
+ }
+
+ if (provider != null && _toolbarProvider == null)
+ ClearCommandBar();
+
+ return provider;
+ }
+
+ internal async Task UpdateToolbarItems()
+ {
+ CommandBar commandBar = await GetCommandBarAsync();
+ if (commandBar != null)
+ {
+ commandBar.PrimaryCommands.Clear();
+ commandBar.SecondaryCommands.Clear();
+#if WINDOWS_UWP
+ if (_page.BottomAppBar != null || _page.TopAppBar != null)
+ {
+ _page.BottomAppBar = null;
+ _page.TopAppBar = null;
+ _page.InvalidateMeasure();
+ }
+#endif
+ }
+
+#if !WINDOWS_UWP
+ commandBar = AddOpenMasterButton(commandBar);
+#endif
+
+#if WINDOWS_UWP
+ var toolBarProvider = GetToolbarProvider() as IToolBarForegroundBinder;
+#endif
+
+ foreach (ToolbarItem item in _toolbarTracker.ToolbarItems.OrderBy(ti => ti.Priority))
+ {
+ if (commandBar == null)
+ commandBar = CreateCommandBar();
+
+#if WINDOWS_UWP
+ toolBarProvider?.BindForegroundColor(commandBar);
+#endif
+
+ var button = new AppBarButton();
+ button.SetBinding(AppBarButton.LabelProperty, "Text");
+ button.SetBinding(AppBarButton.IconProperty, "Icon", _fileImageSourcePathConverter);
+ button.Command = new MenuItemCommand(item);
+ button.DataContext = item;
+
+#if WINDOWS_UWP
+ toolBarProvider?.BindForegroundColor(button);
+#endif
+
+ ToolbarItemOrder order = item.Order == ToolbarItemOrder.Default ? ToolbarItemOrder.Primary : item.Order;
+ if (order == ToolbarItemOrder.Primary)
+ commandBar.PrimaryCommands.Add(button);
+ else
+ commandBar.SecondaryCommands.Add(button);
+ }
+
+ if (commandBar?.PrimaryCommands.Count + commandBar?.SecondaryCommands.Count == 0)
+ ClearCommandBar();
+ }
+
+#if !WINDOWS_UWP
+ CommandBar AddOpenMasterButton(CommandBar commandBar)
+ {
+ if (!_toolbarTracker.HaveMasterDetail)
+ {
+ return commandBar;
+ }
+
+ if (commandBar == null)
+ {
+ commandBar = CreateCommandBar();
+ }
+
+ Page target = _toolbarTracker.Target;
+ var mdp = target as MasterDetailPage;
+ while (mdp == null)
+ {
+ var container = target as IPageContainer<Page>;
+ if (container == null)
+ {
+ break;
+ }
+
+ target = container.CurrentPage;
+ mdp = container.CurrentPage as MasterDetailPage;
+ }
+
+ if (mdp == null || !mdp.ShouldShowToolbarButton())
+ {
+ return commandBar;
+ }
+
+ var openMaster = new AppBarButton { DataContext = mdp };
+ openMaster.SetBinding(AppBarButton.LabelProperty, "Master.Title");
+ openMaster.SetBinding(AppBarButton.IconProperty, "Master.Icon", _fileImageSourcePathConverter);
+ openMaster.Click += (s, a) => { mdp.IsPresented = !mdp.IsPresented; };
+
+ commandBar.PrimaryCommands.Add(openMaster);
+
+ return commandBar;
+ }
+#endif
+
+ Rectangle _bounds;
+ readonly Canvas _container;
+ readonly Windows.UI.Xaml.Controls.Page _page;
+ Windows.UI.Xaml.Controls.ProgressBar _busyIndicator;
+ Page _currentPage;
+ readonly NavigationModel _navModel = new NavigationModel();
+ readonly ToolbarTracker _toolbarTracker = new ToolbarTracker();
+ readonly FileImageSourcePathConverter _fileImageSourcePathConverter = new FileImageSourcePathConverter();
+
+ IToolbarProvider _toolbarProvider;
+
+ class ToolbarProvider : IToolbarProvider
+ {
+ readonly Task<CommandBar> _commandBar;
+
+ public ToolbarProvider(CommandBar commandBar)
+ {
+ _commandBar = Task.FromResult(commandBar);
+ }
+
+ public CommandBar CommandBar => _commandBar.Result;
+
+ public Task<CommandBar> GetCommandBarAsync()
+ {
+ return _commandBar;
+ }
+ }
+
+ Windows.UI.Xaml.Controls.ProgressBar GetBusyIndicator()
+ {
+ if (_busyIndicator == null)
+ {
+ _busyIndicator = new Windows.UI.Xaml.Controls.ProgressBar { IsIndeterminate = true, Visibility = Visibility.Collapsed, VerticalAlignment = VerticalAlignment.Top };
+
+ Canvas.SetZIndex(_busyIndicator, 1);
+ _container.Children.Add(_busyIndicator);
+ }
+
+ return _busyIndicator;
+ }
+
+ internal bool BackButtonPressed()
+ {
+ if (_currentActionSheet != null)
+ {
+ CancelActionSheet();
+ return true;
+ }
+
+ Page lastRoot = _navModel.Roots.Last();
+
+ bool handled = lastRoot.SendBackButtonPressed();
+
+ if (!handled && _navModel.Tree.Count > 1)
+ {
+ Page removed = _navModel.PopModal();
+ if (removed != null)
+ {
+ SetCurrent(_navModel.CurrentPage, true, true);
+ handled = true;
+ }
+ }
+
+ return handled;
+ }
+
+ void CancelActionSheet()
+ {
+ if (_currentActionSheet == null)
+ return;
+
+ _actionSheetOptions.SetResult(null);
+ _actionSheetOptions = null;
+ _currentActionSheet.IsOpen = false;
+ _currentActionSheet = null;
+ }
+
+ void UpdateBounds()
+ {
+ _bounds = new Rectangle(0, 0, _page.ActualWidth, _page.ActualHeight);
+#if WINDOWS_UWP
+ if (ApiInformation.IsTypePresent(typeof(StatusBar).ToString()))
+ {
+ StatusBar statusBar = StatusBar.GetForCurrentView();
+
+ bool landscape = Device.Info.CurrentOrientation.IsLandscape();
+ double offset = landscape ? statusBar.OccludedRect.Width : statusBar.OccludedRect.Height;
+
+ _bounds = new Rectangle(0, 0, _page.ActualWidth - (landscape ? offset : 0), _page.ActualHeight - (landscape ? 0 : offset));
+ }
+#endif
+ }
+
+ void OnRendererSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs)
+ {
+ UpdateBounds();
+ UpdatePageSizes();
+ }
+
+ async void SetCurrent(Page newPage, bool animated, bool popping = false, Action completedCallback = null)
+ {
+ if (newPage == _currentPage)
+ return;
+
+ newPage.Platform = this;
+
+ if (_currentPage != null)
+ {
+ Page previousPage = _currentPage;
+ IVisualElementRenderer previousRenderer = GetRenderer(previousPage);
+ _container.Children.Remove(previousRenderer.ContainerElement);
+
+ if (popping)
+ previousPage.Cleanup();
+ }
+
+ newPage.Layout(new Rectangle(0, 0, _page.ActualWidth, _page.ActualHeight));
+
+ IVisualElementRenderer pageRenderer = newPage.GetOrCreateRenderer();
+ _container.Children.Add(pageRenderer.ContainerElement);
+
+ pageRenderer.ContainerElement.Width = _container.ActualWidth;
+ pageRenderer.ContainerElement.Height = _container.ActualHeight;
+
+ if (completedCallback != null)
+ completedCallback();
+
+ _currentPage = newPage;
+
+ UpdateToolbarTracker();
+ UpdateToolbarTitle(newPage);
+ await UpdateToolbarItems();
+ }
+
+ void UpdateToolbarTitle(Page page)
+ {
+ if (_toolbarProvider == null)
+ return;
+
+ ((ToolbarProvider)_toolbarProvider).CommandBar.Content = page.Title;
+ }
+
+ Task<CommandBar> IToolbarProvider.GetCommandBarAsync()
+ {
+ return GetCommandBarAsync();
+ }
+
+ async Task<CommandBar> GetCommandBarAsync()
+ {
+#if !WINDOWS_UWP
+ return _page.BottomAppBar as CommandBar;
+#else
+ IToolbarProvider provider = GetToolbarProvider();
+ var titleProvider = provider as ITitleProvider;
+ if (provider == null || (titleProvider != null && !titleProvider.ShowTitle))
+ return null;
+
+ return await provider.GetCommandBarAsync();
+#endif
+ }
+
+ CommandBar CreateCommandBar()
+ {
+#if !WINDOWS_UWP
+ var commandBar = new CommandBar();
+ _page.BottomAppBar = commandBar;
+ return commandBar;
+#else
+ var bar = new FormsCommandBar();
+ if (Device.Idiom != TargetIdiom.Phone)
+ bar.Style = (Windows.UI.Xaml.Style)Windows.UI.Xaml.Application.Current.Resources["TitleToolbar"];
+
+ _toolbarProvider = new ToolbarProvider(bar);
+
+ if (Device.Idiom == TargetIdiom.Phone)
+ _page.BottomAppBar = bar;
+ else
+ _page.TopAppBar = bar;
+
+ return bar;
+#endif
+ }
+
+ void ClearCommandBar()
+ {
+#if !WINDOWS_UWP
+ _page.BottomAppBar = null;
+#else
+ if (_toolbarProvider != null)
+ {
+ _toolbarProvider = null;
+ if (Device.Idiom == TargetIdiom.Phone)
+ _page.BottomAppBar = null;
+ else
+ _page.TopAppBar = null;
+ }
+#endif
+ }
+
+ async void OnToolbarItemsChanged(object sender, EventArgs e)
+ {
+ await UpdateToolbarItems();
+ }
+
+ void UpdateToolbarTracker()
+ {
+ Page last = _navModel.Roots.Last();
+ if (last != null)
+ _toolbarTracker.Target = last;
+ }
+
+ ActionSheetArguments _actionSheetOptions;
+ Popup _currentActionSheet;
+
+#if WINDOWS_UWP
+ async void OnPageActionSheet(Page sender, ActionSheetArguments options)
+ {
+ List<string> buttons = options.Buttons.ToList();
+
+ var list = new Windows.UI.Xaml.Controls.ListView
+ {
+ Style = (Windows.UI.Xaml.Style)Windows.UI.Xaml.Application.Current.Resources["ActionSheetList"],
+ ItemsSource = buttons,
+ IsItemClickEnabled = true
+ };
+
+ var dialog = new ContentDialog
+ {
+ Template = (Windows.UI.Xaml.Controls.ControlTemplate)Windows.UI.Xaml.Application.Current.Resources["MyContentDialogControlTemplate"],
+ Content = list,
+ Style = (Windows.UI.Xaml.Style)Windows.UI.Xaml.Application.Current.Resources["ActionSheetStyle"]
+ };
+
+ if (options.Title != null)
+ dialog.Title = options.Title;
+
+ list.ItemClick += (s, e) =>
+ {
+ dialog.Hide();
+ options.SetResult((string)e.ClickedItem);
+ };
+
+ _actionSheetOptions = options;
+
+ if (options.Cancel != null)
+ dialog.SecondaryButtonText = options.Cancel;
+
+ if (options.Destruction != null)
+ dialog.PrimaryButtonText = options.Destruction;
+
+ ContentDialogResult result = await dialog.ShowAsync();
+ if (result == ContentDialogResult.Secondary)
+ options.SetResult(options.Cancel);
+ else if (result == ContentDialogResult.Primary)
+ options.SetResult(options.Destruction);
+ }
+#else
+ void OnPageActionSheet(Page sender, ActionSheetArguments options)
+ {
+ var finalArguments = new List<string>();
+ if (options.Destruction != null)
+ finalArguments.Add(options.Destruction);
+ if (options.Buttons != null)
+ finalArguments.AddRange(options.Buttons);
+ if (options.Cancel != null)
+ finalArguments.Add(options.Cancel);
+
+ var list = new Windows.UI.Xaml.Controls.ListView
+ {
+ Style = (Windows.UI.Xaml.Style)Windows.UI.Xaml.Application.Current.Resources["ActionSheetList"],
+ ItemsSource = finalArguments,
+ IsItemClickEnabled = true
+ };
+
+ list.ItemClick += (s, e) =>
+ {
+ _currentActionSheet.IsOpen = false;
+ _currentActionSheet = null;
+ options.SetResult((string)e.ClickedItem);
+ };
+
+ _actionSheetOptions = options;
+
+ Size size = Device.Info.ScaledScreenSize;
+
+ var stack = new StackPanel
+ {
+ MinWidth = 100,
+ Children =
+ {
+ new TextBlock
+ {
+ Text = options.Title ?? string.Empty,
+ Style = (Windows.UI.Xaml.Style)Windows.UI.Xaml.Application.Current.Resources["TitleTextBlockStyle"],
+ Margin = new Windows.UI.Xaml.Thickness(0, 0, 0, 10),
+ Visibility = options.Title != null ? Visibility.Visible : Visibility.Collapsed
+ },
+ list
+ }
+ };
+
+ var border = new Border
+ {
+ Child = stack,
+ BorderBrush = new SolidColorBrush(Colors.White),
+ BorderThickness = new Windows.UI.Xaml.Thickness(1),
+ Padding = new Windows.UI.Xaml.Thickness(15),
+ Background = (Brush)Windows.UI.Xaml.Application.Current.Resources["AppBarBackgroundThemeBrush"]
+ };
+
+ Windows.UI.Xaml.Controls.Grid.SetRow(border, 1);
+ Windows.UI.Xaml.Controls.Grid.SetColumn(border, 1);
+
+ var container = new Windows.UI.Xaml.Controls.Grid
+ {
+ RowDefinitions =
+ {
+ new Windows.UI.Xaml.Controls.RowDefinition { Height = new Windows.UI.Xaml.GridLength(1, Windows.UI.Xaml.GridUnitType.Star) },
+ new Windows.UI.Xaml.Controls.RowDefinition { Height = new Windows.UI.Xaml.GridLength(0, Windows.UI.Xaml.GridUnitType.Auto) },
+ new Windows.UI.Xaml.Controls.RowDefinition { Height = new Windows.UI.Xaml.GridLength(1, Windows.UI.Xaml.GridUnitType.Star) }
+ },
+ ColumnDefinitions =
+ {
+ new Windows.UI.Xaml.Controls.ColumnDefinition { Width = new Windows.UI.Xaml.GridLength(1, Windows.UI.Xaml.GridUnitType.Star) },
+ new Windows.UI.Xaml.Controls.ColumnDefinition { Width = new Windows.UI.Xaml.GridLength(0, Windows.UI.Xaml.GridUnitType.Auto) },
+ new Windows.UI.Xaml.Controls.ColumnDefinition { Width = new Windows.UI.Xaml.GridLength(1, Windows.UI.Xaml.GridUnitType.Star) }
+ },
+ Height = size.Height,
+ Width = size.Width,
+ Children = { border }
+ };
+
+ var bgPopup = new Popup { Child = new Canvas { Width = size.Width, Height = size.Height, Background = new SolidColorBrush(new Windows.UI.Color { A = 128, R = 0, G = 0, B = 0 }) } };
+
+ bgPopup.IsOpen = true;
+
+ _currentActionSheet = new Popup { ChildTransitions = new TransitionCollection { new PopupThemeTransition() }, IsLightDismissEnabled = true, Child = container };
+
+ _currentActionSheet.Closed += (s, e) =>
+ {
+ bgPopup.IsOpen = false;
+ CancelActionSheet();
+ };
+
+ if (Device.Idiom == TargetIdiom.Phone)
+ {
+ double height = WindowBounds.Height;
+ stack.Height = height;
+ stack.Width = size.Width;
+ border.BorderThickness = new Windows.UI.Xaml.Thickness(0);
+
+ _currentActionSheet.Height = height;
+ _currentActionSheet.VerticalOffset = size.Height - height;
+ }
+
+ _currentActionSheet.IsOpen = true;
+ }
+#endif
+
+ async void OnPageAlert(Page sender, AlertArguments options)
+ {
+ string content = options.Message ?? options.Title ?? string.Empty;
+
+ MessageDialog dialog;
+ if (options.Message == null || options.Title == null)
+ dialog = new MessageDialog(content);
+ else
+ dialog = new MessageDialog(options.Message, options.Title);
+
+ if (options.Accept != null)
+ {
+ dialog.Commands.Add(new UICommand(options.Accept));
+ dialog.DefaultCommandIndex = (uint)dialog.Commands.Count - 1;
+ }
+
+ if (options.Cancel != null)
+ {
+ dialog.Commands.Add(new UICommand(options.Cancel));
+ dialog.CancelCommandIndex = 0;
+ }
+
+ IUICommand command = await dialog.ShowAsync();
+ options.SetResult(command.Label == options.Accept);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/PlatformEffect.cs b/Xamarin.Forms.Platform.WinRT/PlatformEffect.cs
new file mode 100644
index 00000000..cd2991eb
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/PlatformEffect.cs
@@ -0,0 +1,14 @@
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public abstract class PlatformEffect : PlatformEffect<FrameworkElement, FrameworkElement>
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ProgressBarRenderer.cs b/Xamarin.Forms.Platform.WinRT/ProgressBarRenderer.cs
new file mode 100644
index 00000000..87f1e35e
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ProgressBarRenderer.cs
@@ -0,0 +1,59 @@
+using System.ComponentModel;
+using Windows.UI.Xaml.Controls.Primitives;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class ProgressBarRenderer : ViewRenderer<ProgressBar, Windows.UI.Xaml.Controls.ProgressBar>
+ {
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (Control != null)
+ {
+ Control.ValueChanged -= ProgressBarOnValueChanged;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<ProgressBar> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var progressBar = new Windows.UI.Xaml.Controls.ProgressBar { Minimum = 0, Maximum = 1 };
+
+ progressBar.ValueChanged += ProgressBarOnValueChanged;
+
+ SetNativeControl(progressBar);
+ }
+
+ Control.Value = e.NewElement.Progress;
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == ProgressBar.ProgressProperty.PropertyName)
+ Control.Value = Element.Progress;
+ }
+
+ void ProgressBarOnValueChanged(object sender, RangeBaseValueChangedEventArgs rangeBaseValueChangedEventArgs)
+ {
+ Element?.InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/Properties/AssemblyInfo.cs b/Xamarin.Forms.Platform.WinRT/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..f24feecf
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/Properties/AssemblyInfo.cs
@@ -0,0 +1,57 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.WinRT;
+
+[assembly: AssemblyTitle("Xamarin.Forms.Platform.WinRT")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Platform.WinRT.Tablet")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Platform.WinRT.Phone")]
+[assembly: Dependency(typeof(WindowsSerializer))]
+
+// Views
+
+[assembly: ExportRenderer(typeof(Layout), typeof(LayoutRenderer))]
+[assembly: ExportRenderer(typeof(BoxView), typeof(BoxViewRenderer))]
+[assembly: ExportRenderer(typeof(Image), typeof(ImageRenderer))]
+[assembly: ExportRenderer(typeof(Label), typeof(LabelRenderer))]
+[assembly: ExportRenderer(typeof(Button), typeof(ButtonRenderer))]
+[assembly: ExportRenderer(typeof(ListView), typeof(ListViewRenderer))]
+[assembly: ExportRenderer(typeof(CarouselView), typeof(CarouselViewRenderer))]
+[assembly: ExportRenderer(typeof(ScrollView), typeof(ScrollViewRenderer))]
+[assembly: ExportRenderer(typeof(ProgressBar), typeof(ProgressBarRenderer))]
+[assembly: ExportRenderer(typeof(Slider), typeof(SliderRenderer))]
+[assembly: ExportRenderer(typeof(Switch), typeof(SwitchRenderer))]
+[assembly: ExportRenderer(typeof(WebView), typeof(WebViewRenderer))]
+[assembly: ExportRenderer(typeof(Frame), typeof(FrameRenderer))]
+[assembly: ExportRenderer(typeof(ActivityIndicator), typeof(ActivityIndicatorRenderer))]
+[assembly: ExportRenderer(typeof(Editor), typeof(EditorRenderer))]
+[assembly: ExportRenderer(typeof(Picker), typeof(PickerRenderer))]
+[assembly: ExportRenderer(typeof(TimePicker), typeof(TimePickerRenderer))]
+[assembly: ExportRenderer(typeof(DatePicker), typeof(DatePickerRenderer))]
+[assembly: ExportRenderer(typeof(Stepper), typeof(StepperRenderer))]
+[assembly: ExportRenderer(typeof(Entry), typeof(EntryRenderer))]
+[assembly: ExportRenderer(typeof(TableView), typeof(TableViewRenderer))]
+[assembly: ExportRenderer(typeof(NativeViewWrapper), typeof(NativeViewWrapperRenderer))]
+
+//ImageSources
+
+[assembly: ExportImageSourceHandler(typeof(FileImageSource), typeof(FileImageSourceHandler))]
+[assembly: ExportImageSourceHandler(typeof(StreamImageSource), typeof(StreamImagesourceHandler))]
+[assembly: ExportImageSourceHandler(typeof(UriImageSource), typeof(ImageLoaderSourceHandler))]
+
+// Pages
+
+[assembly: ExportRenderer(typeof(Page), typeof(PageRenderer))]
+[assembly: ExportRenderer(typeof(NavigationPage), typeof(NavigationPageRenderer))]
+[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(MasterDetailPageRenderer))]
+[assembly: ExportRenderer(typeof(CarouselPage), typeof(CarouselPageRenderer))]
+
+// Cells
+
+[assembly: ExportCell(typeof(Cell), typeof(TextCellRenderer))]
+[assembly: ExportCell(typeof(ImageCell), typeof(ImageCellRenderer))]
+[assembly: ExportCell(typeof(EntryCell), typeof(EntryCellRenderer))]
+[assembly: ExportCell(typeof(SwitchCell), typeof(SwitchCellRenderer))]
+[assembly: ExportCell(typeof(ViewCell), typeof(ViewCellRenderer))] \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/RendererFactory.cs b/Xamarin.Forms.Platform.WinRT/RendererFactory.cs
new file mode 100644
index 00000000..576950c3
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/RendererFactory.cs
@@ -0,0 +1,19 @@
+using System;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public static class RendererFactory
+ {
+ [Obsolete("Use Platform.CreateRenderer")]
+ public static IVisualElementRenderer CreateRenderer(VisualElement element)
+ {
+ return Platform.CreateRenderer(element);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/Resources.xaml b/Xamarin.Forms.Platform.WinRT/Resources.xaml
new file mode 100644
index 00000000..fe135a89
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/Resources.xaml
@@ -0,0 +1,87 @@
+<ResourceDictionary
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:forms="using:Xamarin.Forms.Platform.WinRT">
+
+ <forms:CaseConverter x:Key="LowerConverter" ConvertToUpper="False" />
+ <forms:CaseConverter x:Key="UpperConverter" ConvertToUpper="True" />
+ <forms:HeightConverter x:Key="HeightConverter" />
+ <forms:CollapseWhenEmptyConverter x:Key="CollapseWhenEmpty" />
+ <forms:BoolToVisibilityConverter x:Key="BoolVisibilityConverter" />
+ <forms:PageToRenderedElementConverter x:Key="PageToRenderer" />
+ <forms:ImageConverter x:Key="ImageConverter" />
+ <forms:ViewToRendererConverter x:Key="ViewToRenderer" />
+ <forms:ColorConverter x:Key="ColorConverter" />
+ <forms:HorizontalTextAlignmentConverter x:Key="HorizontalTextAlignmentConverter" />
+ <forms:KeyboardConverter x:Key="KeyboardConverter" />
+ <forms:MasterBackgroundConverter x:Key="MasterBackgroundConverter" />
+
+ <Style x:Key="RootContainerStyle" TargetType="Canvas">
+ <Setter Property="Background" Value="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
+ </Style>
+
+ <Style x:Key="ActionSheetList" TargetType="ListView">
+ <Setter Property="SelectionMode" Value="None" />
+ <Setter Property="ItemContainerStyle">
+ <Setter.Value>
+ <Style TargetType="ListViewItem">
+ <Setter Property="Margin" Value="0" />
+ <Setter Property="HorizontalContentAlignment" Value="Stretch" />
+ </Style>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="ItemTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <TextBlock Text="{Binding}" HorizontalAlignment="Stretch" VerticalAlignment="Center" Style="{ThemeResource SubheaderTextBlockStyle}" />
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <DataTemplate x:Key="ItemTemplate">
+ <forms:ItemControl HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" />
+ </DataTemplate>
+
+ <DataTemplate x:Key="CellTemplate">
+ <forms:CellControl HorizontalContentAlignment="Stretch" />
+ </DataTemplate>
+
+ <DataTemplate x:Key="TableRoot">
+ <TextBlock Margin="0,20,0,0" Text="{Binding Title,Converter={StaticResource LowerConverter}}" Style="{ThemeResource HeaderTextBlockStyle}" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=Self},Converter={StaticResource CollapseWhenEmpty}}" />
+ </DataTemplate>
+
+ <DataTemplate x:Key="TableSection">
+ <TextBlock Margin="0,20,0,0" Text="{Binding Title,Converter={StaticResource LowerConverter}}" Style="{ThemeResource SubheaderTextBlockStyle}" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=Self},Converter={StaticResource CollapseWhenEmpty}}" />
+ </DataTemplate>
+
+ <forms:ListViewGroupStyleSelector x:Key="ListViewGroupSelector" />
+
+ <DataTemplate x:Key="ViewCell">
+ <ContentControl DataContext="{Binding Cell}">
+ <ContentPresenter Height="{Binding RenderHeight, Converter={StaticResource HeightConverter}}" Content="{Binding View, Converter={StaticResource ViewToRenderer}}" />
+ </ContentControl>
+ </DataTemplate>
+
+ <DataTemplate x:Key="ContainedPageTemplate">
+ <ContentPresenter Content="{Binding Converter={StaticResource PageToRenderer}}">
+ <ContentPresenter.Resources>
+ <Style TargetType="forms:PageControl">
+ <Setter Property="Background" Value="Transparent" />
+ </Style>
+ </ContentPresenter.Resources>
+ </ContentPresenter>
+ </DataTemplate>
+
+ <DataTemplate x:Key="View">
+ <ContentPresenter Content="{Binding Converter={StaticResource ViewToRenderer}}" />
+ </DataTemplate>
+
+ <Style TargetType="TextBox">
+ <Setter Property="Margin" Value="0" />
+ </Style>
+
+ <DataTemplate x:Key="PushPinTemplate">
+ <Path Data="M 50.7361,983.661 C 44.1895,983.661 38.8369,988.97 38.8369,995.517 39.8649,1003.3 45.246,1008.1 49.8547,1014.12 50.2838,1014.66 51.2336,1014.66 51.6619,1014.12 52.1384,1013.48 52.7575,1012.73 53.4248,1011.91 55.0322,1012.07 56.4727,1012.32 57.5676,1012.71 58.407,1013 59.06,1013.33 59.4192,1013.63 59.7784,1013.93 59.7716,1014.11 59.7716,1014.16 59.7716,1014.21 59.7716,1014.39 59.4192,1014.69 59.06,1014.99 58.407,1015.32 57.5676,1015.61 55.8888,1016.2 53.4519,1016.63 50.7361,1016.63 48.0204,1016.63 45.5399,1016.2 43.8611,1015.61 43.0218,1015.32 42.3695,1014.99 42.0103,1014.69 41.6504,1014.39 41.6135,1014.21 41.6135,1014.16 41.6135,1014.11 41.6511,1013.93 42.0103,1013.63 42.3695,1013.33 43.0218,1013 43.8611,1012.71 44.3158,1012.55 44.8455,1012.35 45.4039,1012.22 L 43.8611,1010.33 C 43.6124,1010.4 43.3441,1010.46 43.1119,1010.55 42.1005,1010.9 41.2318,1011.31 40.5555,1011.87 39.8799,1012.43 39.3216,1013.22 39.3216,1014.16 39.3216,1015.1 39.8799,1015.85 40.5555,1016.41 41.2318,1016.97 42.1005,1017.42 43.1119,1017.77 45.1356,1018.48 47.8025,1018.92 50.7362,1018.92 54.437,1018.81 57.9892,1018.36 60.8733,1016.41 62.5084,1014.79 62.0756,1013.4 60.8733,1011.87 60.1969,1011.31 59.3726,1010.9 58.3612,1010.55 57.4331,1010.22 56.3503,1009.94 55.1878,1009.75 56.1992,1008.51 57.2362,1007.18 58.2289,1005.79 60.5599,1002.51 62.5918,998.968 62.5918,995.517 62.5918,988.97 57.2836,983.661 50.7362,983.661 Z M 50.7361,989.655 C 47.571,989.655 44.9627,992.219 44.9627,995.385 44.9627,998.55 47.571,1001.16 50.7361,1001.16 53.902,1001.16 56.4659,998.55 56.4659,995.385 56.4659,992.219 53.902,989.655 50.7361,989.655 Z M 50.7361,991.947 C 52.6591,991.947 54.174,993.462 54.174,995.385 54.174,997.307 52.6591,998.866 50.7361,998.866 48.8139,998.866 47.2546,997.307 47.2546,995.385 47.2546,993.462 48.8139,991.947 50.7361,991.947 Z" Fill="#000000" />
+ </DataTemplate>
+</ResourceDictionary> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ScrollViewRenderer.cs b/Xamarin.Forms.Platform.WinRT/ScrollViewRenderer.cs
new file mode 100644
index 00000000..6938a76e
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ScrollViewRenderer.cs
@@ -0,0 +1,194 @@
+using System;
+using System.ComponentModel;
+using Windows.Foundation;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class ScrollViewRenderer : ViewRenderer<ScrollView, ScrollViewer>
+ {
+ VisualElement _currentView;
+
+ public ScrollViewRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected IScrollViewController Controller
+ {
+ get { return Element; }
+ }
+
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ SizeRequest result = base.GetDesiredSize(widthConstraint, heightConstraint);
+ result.Minimum = new Size(40, 40);
+ return result;
+ }
+
+ protected override Windows.Foundation.Size ArrangeOverride(Windows.Foundation.Size finalSize)
+ {
+ if (Element == null)
+ return finalSize;
+
+ Element.IsInNativeLayout = true;
+
+ Control?.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
+
+ Element.IsInNativeLayout = false;
+
+ return finalSize;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (Control != null)
+ {
+ Control.ViewChanged -= OnViewChanged;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override Windows.Foundation.Size MeasureOverride(Windows.Foundation.Size availableSize)
+ {
+ if (Element == null)
+ return new Windows.Foundation.Size(0, 0);
+
+ double width = Math.Max(0, Element.Width);
+ double height = Math.Max(0, Element.Height);
+ var result = new Windows.Foundation.Size(width, height);
+
+ Control?.Measure(result);
+
+ return result;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<ScrollView> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ {
+ ((IScrollViewController)e.OldElement).ScrollToRequested -= OnScrollToRequested;
+ }
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new ScrollViewer { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto });
+
+ Control.ViewChanged += OnViewChanged;
+ }
+
+ Controller.ScrollToRequested += OnScrollToRequested;
+
+ UpdateOrientation();
+
+ LoadContent();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == "Content")
+ LoadContent();
+ else if (e.PropertyName == Layout.PaddingProperty.PropertyName)
+ UpdateMargins();
+ else if (e.PropertyName == ScrollView.OrientationProperty.PropertyName)
+ UpdateOrientation();
+ }
+
+ void LoadContent()
+ {
+ if (_currentView != null)
+ {
+ _currentView.Cleanup();
+ }
+
+ _currentView = Element.Content;
+
+ IVisualElementRenderer renderer = null;
+ if (_currentView != null)
+ {
+ renderer = _currentView.GetOrCreateRenderer();
+ }
+
+ Control.Content = renderer != null ? renderer.ContainerElement : null;
+
+ UpdateMargins();
+ }
+
+ void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
+ {
+ double x = e.ScrollX, y = e.ScrollY;
+
+ ScrollToMode mode = e.Mode;
+ if (mode == ScrollToMode.Element)
+ {
+ Point pos = Controller.GetScrollPositionForElement((VisualElement)e.Element, e.Position);
+ x = pos.X;
+ y = pos.Y;
+ mode = ScrollToMode.Position;
+ }
+
+ if (mode == ScrollToMode.Position)
+ {
+ Control.ChangeView(x, y, null, !e.ShouldAnimate);
+ }
+ }
+
+ void OnViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
+ {
+ Controller.SetScrolledPosition(Control.HorizontalOffset, Control.VerticalOffset);
+
+ if (!e.IsIntermediate)
+ Controller.SendScrollFinished();
+ }
+
+ void UpdateMargins()
+ {
+ var element = Control.Content as FrameworkElement;
+ if (element == null)
+ return;
+
+ switch (Element.Orientation)
+ {
+ case ScrollOrientation.Horizontal:
+ // need to add left/right margins
+ element.Margin = new Windows.UI.Xaml.Thickness(Element.Padding.Left, 0, Element.Padding.Right, 0);
+ break;
+ case ScrollOrientation.Vertical:
+ // need to add top/bottom margins
+ element.Margin = new Windows.UI.Xaml.Thickness(0, Element.Padding.Top, 0, Element.Padding.Bottom);
+ break;
+ case ScrollOrientation.Both:
+ // need to add all margins
+ element.Margin = new Windows.UI.Xaml.Thickness(Element.Padding.Left, Element.Padding.Top, Element.Padding.Right, Element.Padding.Bottom);
+ break;
+ }
+ }
+
+ void UpdateOrientation()
+ {
+ if (Element.Orientation == ScrollOrientation.Horizontal || Element.Orientation == ScrollOrientation.Both)
+ {
+ Control.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
+ }
+ else
+ {
+ Control.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/SliderRenderer.cs b/Xamarin.Forms.Platform.WinRT/SliderRenderer.cs
new file mode 100644
index 00000000..ee7a8adc
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/SliderRenderer.cs
@@ -0,0 +1,59 @@
+using System;
+using System.ComponentModel;
+using Windows.UI.Xaml.Controls.Primitives;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class SliderRenderer : ViewRenderer<Slider, Windows.UI.Xaml.Controls.Slider>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<Slider> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var slider = new Windows.UI.Xaml.Controls.Slider();
+ SetNativeControl(slider);
+
+ slider.ValueChanged += OnNativeValueCHanged;
+ }
+
+ double stepping = Math.Min((e.NewElement.Maximum - e.NewElement.Minimum) / 10, 1);
+ Control.StepFrequency = stepping;
+ Control.SmallChange = stepping;
+
+ Control.Minimum = e.NewElement.Minimum;
+ Control.Maximum = e.NewElement.Maximum;
+ Control.Value = e.NewElement.Value;
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Slider.MinimumProperty.PropertyName)
+ Control.Minimum = Element.Minimum;
+ else if (e.PropertyName == Slider.MaximumProperty.PropertyName)
+ Control.Maximum = Element.Maximum;
+ else if (e.PropertyName == Slider.ValueProperty.PropertyName)
+ {
+ if (Control.Value != Element.Value)
+ Control.Value = Element.Value;
+ }
+ }
+
+ void OnNativeValueCHanged(object sender, RangeBaseValueChangedEventArgs e)
+ {
+ ((IElementController)Element).SetValueFromRenderer(Slider.ValueProperty, e.NewValue);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/StepperControl.xaml b/Xamarin.Forms.Platform.WinRT/StepperControl.xaml
new file mode 100644
index 00000000..f4ab46c2
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/StepperControl.xaml
@@ -0,0 +1,90 @@
+<UserControl
+ x:Class="Xamarin.Forms.Platform.WinRT.StepperControl"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="using:Xamarin.Forms.Platform.WinRT"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ mc:Ignorable="d"
+ d:DesignHeight="300"
+ d:DesignWidth="400">
+
+ <ContentControl>
+ <Grid>
+ <Grid.Resources>
+ <Style TargetType="Button">
+ <Setter Property="Margin" Value="0" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="Button">
+ <Grid>
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal"/>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Border">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPointerOverBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPointerOverForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Border">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPressedBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPressedForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Border">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonDisabledBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="Border">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonDisabledBorderThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="FocusStates">
+ <VisualState x:Name="Focused">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisualWhite"/>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisualBlack"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Unfocused"/>
+ <VisualState x:Name="PointerFocused"/>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ <Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="0">
+ <ContentPresenter x:Name="ContentPresenter" AutomationProperties.AccessibilityView="Raw" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
+ </Border>
+ <Rectangle x:Name="FocusVisualWhite" IsHitTestVisible="False" Opacity="0" StrokeDashOffset="1.5" StrokeEndLineCap="Square" Stroke="{ThemeResource FocusVisualWhiteStrokeThemeBrush}" StrokeDashArray="1,1"/>
+ <Rectangle x:Name="FocusVisualBlack" IsHitTestVisible="False" Opacity="0" StrokeDashOffset="0.5" StrokeEndLineCap="Square" Stroke="{ThemeResource FocusVisualBlackStrokeThemeBrush}" StrokeDashArray="1,1"/>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ </Grid.Resources>
+
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+
+ <Button Name="Minus" Grid.Column="0" Content="-" Click="OnMinusClicked" BorderThickness="2,2,1,2" />
+ <Button Name="Plus" Grid.Column="1" Content="+" Click="OnPlusClicked" BorderThickness="1,2,2,2" />
+ </Grid>
+ </ContentControl>
+</UserControl> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/StepperControl.xaml.cs b/Xamarin.Forms.Platform.WinRT/StepperControl.xaml.cs
new file mode 100644
index 00000000..49a4632f
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/StepperControl.xaml.cs
@@ -0,0 +1,94 @@
+using System;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+namespace Xamarin.Forms.Platform.WinRT
+{
+ public sealed partial class StepperControl : UserControl
+ {
+ public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(StepperControl), new PropertyMetadata(default(double), OnValueChanged));
+
+ public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(double), typeof(StepperControl), new PropertyMetadata(default(double), OnMaxMinChanged));
+
+ public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum", typeof(double), typeof(StepperControl), new PropertyMetadata(default(double), OnMaxMinChanged));
+
+ public static readonly DependencyProperty IncrementProperty = DependencyProperty.Register("Increment", typeof(double), typeof(StepperControl),
+ new PropertyMetadata(default(double), OnIncrementChanged));
+
+ public StepperControl()
+ {
+ InitializeComponent();
+ }
+
+ public double Increment
+ {
+ get { return (double)GetValue(IncrementProperty); }
+ set { SetValue(IncrementProperty, value); }
+ }
+
+ public double Maximum
+ {
+ get { return (double)GetValue(MaximumProperty); }
+ set { SetValue(MaximumProperty, value); }
+ }
+
+ public double Minimum
+ {
+ get { return (double)GetValue(MinimumProperty); }
+ set { SetValue(MinimumProperty, value); }
+ }
+
+ public double Value
+ {
+ get { return (double)GetValue(ValueProperty); }
+ set { SetValue(ValueProperty, value); }
+ }
+
+ public event EventHandler ValueChanged;
+
+ static void OnIncrementChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var stepper = (StepperControl)d;
+ stepper.UpdateEnabled(stepper.Value);
+ }
+
+ static void OnMaxMinChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var stepper = (StepperControl)d;
+ stepper.UpdateEnabled(stepper.Value);
+ }
+
+ void OnMinusClicked(object sender, RoutedEventArgs e)
+ {
+ UpdateValue(-Increment);
+ }
+
+ void OnPlusClicked(object sender, RoutedEventArgs e)
+ {
+ UpdateValue(+Increment);
+ }
+
+ static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var stepper = (StepperControl)d;
+ stepper.UpdateEnabled((double)e.NewValue);
+
+ EventHandler changed = stepper.ValueChanged;
+ if (changed != null)
+ changed(d, EventArgs.Empty);
+ }
+
+ void UpdateEnabled(double value)
+ {
+ double increment = Increment;
+ Plus.IsEnabled = value + increment <= Maximum;
+ Minus.IsEnabled = value - increment >= Minimum;
+ }
+
+ void UpdateValue(double delta)
+ {
+ double newValue = Value + delta;
+ Value = newValue;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/StepperRenderer.cs b/Xamarin.Forms.Platform.WinRT/StepperRenderer.cs
new file mode 100644
index 00000000..7a4724cf
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/StepperRenderer.cs
@@ -0,0 +1,72 @@
+using System;
+using System.ComponentModel;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class StepperRenderer : ViewRenderer<Stepper, StepperControl>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new StepperControl());
+ Control.ValueChanged += OnControlValue;
+ }
+
+ UpdateMaximum();
+ UpdateMinimum();
+ UpdateValue();
+ UpdateIncrement();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Stepper.ValueProperty.PropertyName)
+ UpdateValue();
+ else if (e.PropertyName == Stepper.MaximumProperty.PropertyName)
+ UpdateMaximum();
+ else if (e.PropertyName == Stepper.MinimumProperty.PropertyName)
+ UpdateMinimum();
+ else if (e.PropertyName == Stepper.IncrementProperty.PropertyName)
+ UpdateIncrement();
+ }
+
+ void OnControlValue(object sender, EventArgs e)
+ {
+ Element.SetValueCore(Stepper.ValueProperty, Control.Value);
+ }
+
+ void UpdateIncrement()
+ {
+ Control.Increment = Element.Increment;
+ }
+
+ void UpdateMaximum()
+ {
+ Control.Maximum = Element.Maximum;
+ }
+
+ void UpdateMinimum()
+ {
+ Control.Minimum = Element.Minimum;
+ }
+
+ void UpdateValue()
+ {
+ Control.Value = Element.Value;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/StreamImagesourceHandler.cs b/Xamarin.Forms.Platform.WinRT/StreamImagesourceHandler.cs
new file mode 100644
index 00000000..ecf8c0db
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/StreamImagesourceHandler.cs
@@ -0,0 +1,36 @@
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Windows.UI.Xaml.Media.Imaging;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public sealed class StreamImagesourceHandler : IImageSourceHandler
+ {
+ public async Task<Windows.UI.Xaml.Media.ImageSource> LoadImageAsync(ImageSource imagesource, CancellationToken cancellationToken = new CancellationToken())
+ {
+ BitmapImage bitmapimage = null;
+
+ var streamsource = imagesource as StreamImageSource;
+ if (streamsource != null && streamsource.Stream != null)
+ {
+ using(Stream stream = await streamsource.GetStreamAsync(cancellationToken))
+ {
+ if (stream == null)
+ return null;
+ bitmapimage = new BitmapImage();
+ await bitmapimage.SetSourceAsync(stream.AsRandomAccessStream());
+ }
+ }
+
+ return bitmapimage;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/SwitchRenderer.cs b/Xamarin.Forms.Platform.WinRT/SwitchRenderer.cs
new file mode 100644
index 00000000..ebc08ad6
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/SwitchRenderer.cs
@@ -0,0 +1,50 @@
+using System.ComponentModel;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class SwitchRenderer : ViewRenderer<Switch, ToggleSwitch>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<Switch> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var control = new ToggleSwitch();
+ control.Toggled += OnNativeToggled;
+ control.ClearValue(ToggleSwitch.OnContentProperty);
+ control.ClearValue(ToggleSwitch.OffContentProperty);
+
+ SetNativeControl(control);
+ }
+
+ Control.IsOn = Element.IsToggled;
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Switch.IsToggledProperty.PropertyName)
+ {
+ Control.IsOn = Element.IsToggled;
+ }
+ }
+
+ void OnNativeToggled(object sender, RoutedEventArgs routedEventArgs)
+ {
+ ((IElementController)Element).SetValueFromRenderer(Switch.IsToggledProperty, Control.IsOn);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/TableViewRenderer.cs b/Xamarin.Forms.Platform.WinRT/TableViewRenderer.cs
new file mode 100644
index 00000000..c5750c79
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/TableViewRenderer.cs
@@ -0,0 +1,85 @@
+using System;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Data;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class TableViewRenderer : ViewRenderer<TableView, Windows.UI.Xaml.Controls.ListView>
+ {
+ bool _ignoreSelectionEvent;
+
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ SizeRequest result = base.GetDesiredSize(widthConstraint, heightConstraint);
+ result.Minimum = new Size(40, 40);
+ return result;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<TableView> e)
+ {
+ if (e.OldElement != null)
+ {
+ e.OldElement.ModelChanged -= OnModelChanged;
+ }
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new Windows.UI.Xaml.Controls.ListView
+ {
+ ItemContainerStyle = (Windows.UI.Xaml.Style)Windows.UI.Xaml.Application.Current.Resources["FormsListViewItem"],
+ ItemTemplate = (Windows.UI.Xaml.DataTemplate)Windows.UI.Xaml.Application.Current.Resources["CellTemplate"],
+ GroupStyle = { new GroupStyle { HidesIfEmpty = false, HeaderTemplate = (Windows.UI.Xaml.DataTemplate)Windows.UI.Xaml.Application.Current.Resources["TableSection"] } },
+ HeaderTemplate = (Windows.UI.Xaml.DataTemplate)Windows.UI.Xaml.Application.Current.Resources["TableRoot"],
+ SelectionMode = ListViewSelectionMode.Single
+ });
+
+ // You can't set ItemsSource directly to a CollectionViewSource, it crashes.
+ Control.SetBinding(ItemsControl.ItemsSourceProperty, "");
+ Control.SelectionChanged += OnSelectionChanged;
+ }
+
+ e.NewElement.ModelChanged += OnModelChanged;
+ OnModelChanged(e.NewElement, EventArgs.Empty);
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ void OnModelChanged(object sender, EventArgs e)
+ {
+ Control.Header = Element.Root;
+
+ // This auto-selects the first item in the new DataContext, so we just null it and ignore the selection
+ // as this selection isn't driven by user input
+ _ignoreSelectionEvent = true;
+ Control.DataContext = new CollectionViewSource { Source = Element.Root, IsSourceGrouped = true };
+ _ignoreSelectionEvent = false;
+ }
+
+ void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (!_ignoreSelectionEvent)
+ {
+ foreach (object item in e.AddedItems)
+ {
+ var cell = item as Cell;
+ if (cell != null)
+ {
+ Element.Model.RowSelected(cell);
+ break;
+ }
+ }
+ }
+
+ Control.SelectedItem = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/TaskExtensions.cs b/Xamarin.Forms.Platform.WinRT/TaskExtensions.cs
new file mode 100644
index 00000000..332e8a64
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/TaskExtensions.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Windows.Foundation;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal static class TaskExtensions
+ {
+ public static void WatchForError(this IAsyncAction self)
+ {
+ self.AsTask().WatchForError();
+ }
+
+ public static void WatchForError<T>(this IAsyncOperation<T> self)
+ {
+ self.AsTask().WatchForError();
+ }
+
+ public static void WatchForError(this Task self)
+ {
+ SynchronizationContext context = SynchronizationContext.Current;
+ if (context == null)
+ return;
+
+ self.ContinueWith(t =>
+ {
+ Exception exception = t.Exception.InnerExceptions.Count > 1 ? t.Exception : t.Exception.InnerException;
+
+ context.Post(e => { throw (Exception)e; }, exception);
+ }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/TextAlignmentToHorizontalAlignmentConverter.cs b/Xamarin.Forms.Platform.WinRT/TextAlignmentToHorizontalAlignmentConverter.cs
new file mode 100644
index 00000000..8f95af1e
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/TextAlignmentToHorizontalAlignmentConverter.cs
@@ -0,0 +1,48 @@
+using System;
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public sealed class TextAlignmentToHorizontalAlignmentConverter : Windows.UI.Xaml.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ var alignment = (Windows.UI.Xaml.TextAlignment)value;
+
+ switch (alignment)
+ {
+ case Windows.UI.Xaml.TextAlignment.Center:
+ return HorizontalAlignment.Center;
+ case Windows.UI.Xaml.TextAlignment.Left:
+ return HorizontalAlignment.Left;
+ case Windows.UI.Xaml.TextAlignment.Right:
+ return HorizontalAlignment.Right;
+ default:
+ return HorizontalAlignment.Left;
+ }
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ var alignment = (HorizontalAlignment)value;
+
+ switch (alignment)
+ {
+ case HorizontalAlignment.Left:
+ return Windows.UI.Xaml.TextAlignment.Left;
+ case HorizontalAlignment.Center:
+ return Windows.UI.Xaml.TextAlignment.Center;
+ case HorizontalAlignment.Right:
+ return Windows.UI.Xaml.TextAlignment.Right;
+ default:
+ return Windows.UI.Xaml.TextAlignment.Left;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/TextCellRenderer.cs b/Xamarin.Forms.Platform.WinRT/TextCellRenderer.cs
new file mode 100644
index 00000000..7adf009d
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/TextCellRenderer.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Windows.Input;
+using WDataTemplate = Windows.UI.Xaml.DataTemplate;
+using WApplication = Windows.UI.Xaml.Application;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class TextCellRenderer : ICellRenderer
+ {
+ public virtual WDataTemplate GetTemplate(Cell cell)
+ {
+ if (cell.RealParent is ListView)
+ {
+ if (TemplatedItemsList<ItemsView<Cell>, Cell>.GetIsGroupHeader(cell))
+ return (WDataTemplate)WApplication.Current.Resources["ListViewHeaderTextCell"];
+
+ //return (WDataTemplate) WApplication.Current.Resources["ListViewTextCell"];
+ }
+
+ return (WDataTemplate)WApplication.Current.Resources["TextCell"];
+ }
+ }
+
+ public class EntryCellRendererCompleted : ICommand
+ {
+ public bool CanExecute(object parameter)
+ {
+ return true;
+ }
+
+ public event EventHandler CanExecuteChanged;
+
+ public void Execute(object parameter)
+ {
+ var entryCell = (EntryCell)parameter;
+ entryCell.SendCompleted();
+ }
+ }
+
+ public class EntryCellRenderer : ICellRenderer
+ {
+ public virtual WDataTemplate GetTemplate(Cell cell)
+ {
+ return (WDataTemplate)WApplication.Current.Resources["EntryCell"];
+ }
+ }
+
+ public class ViewCellRenderer : ICellRenderer
+ {
+ public virtual WDataTemplate GetTemplate(Cell cell)
+ {
+ return (WDataTemplate)WApplication.Current.Resources["ViewCell"];
+ }
+ }
+
+ public class SwitchCellRenderer : ICellRenderer
+ {
+ public virtual WDataTemplate GetTemplate(Cell cell)
+ {
+ return (WDataTemplate)WApplication.Current.Resources["SwitchCell"];
+ }
+ }
+
+ public class ImageCellRenderer : ICellRenderer
+ {
+ public virtual WDataTemplate GetTemplate(Cell cell)
+ {
+ //if (cell.Parent is ListView)
+ // return (WDataTemplate)WApplication.Current.Resources["ListImageCell"];
+ return (WDataTemplate)WApplication.Current.Resources["ImageCell"];
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/TimePickerRenderer.cs b/Xamarin.Forms.Platform.WinRT/TimePickerRenderer.cs
new file mode 100644
index 00000000..3aa5fdca
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/TimePickerRenderer.cs
@@ -0,0 +1,75 @@
+using System;
+using System.ComponentModel;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class TimePickerRenderer : ViewRenderer<TimePicker, FormsTimePicker>, IWrapperAware
+ {
+ public void NotifyWrapped()
+ {
+ if (Control != null)
+ {
+ Control.ForceInvalidate += PickerOnForceInvalidate;
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && Control != null)
+ {
+ Control.ForceInvalidate -= PickerOnForceInvalidate;
+ Control.TimeChanged -= OnControlTimeChanged;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
+ {
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var picker = new FormsTimePicker();
+ picker.TimeChanged += OnControlTimeChanged;
+ SetNativeControl(picker);
+ }
+
+ UpdateTime();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == TimePicker.TimeProperty.PropertyName)
+ UpdateTime();
+ }
+
+ void OnControlTimeChanged(object sender, TimePickerValueChangedEventArgs e)
+ {
+ Element.Time = e.NewTime;
+ Element?.InvalidateMeasure(InvalidationTrigger.SizeRequestChanged);
+ }
+
+ void PickerOnForceInvalidate(object sender, EventArgs eventArgs)
+ {
+ Element?.InvalidateMeasure(InvalidationTrigger.SizeRequestChanged);
+ }
+
+ void UpdateTime()
+ {
+ Control.Time = Element.Time;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ViewExtensions.cs b/Xamarin.Forms.Platform.WinRT/ViewExtensions.cs
new file mode 100644
index 00000000..9e382ab9
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ViewExtensions.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal static class ViewExtensions
+ {
+ public static IEnumerable<Page> GetParentPages(this Page target)
+ {
+ var result = new List<Page>();
+ var parent = target.Parent as Page;
+ while (!Application.IsApplicationOrNull(parent))
+ {
+ result.Add(parent);
+ parent = parent.Parent as Page;
+ }
+
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ViewRenderer.cs b/Xamarin.Forms.Platform.WinRT/ViewRenderer.cs
new file mode 100644
index 00000000..148da1b3
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ViewRenderer.cs
@@ -0,0 +1,37 @@
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Automation;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class ViewRenderer<TElement, TNativeElement> : VisualElementRenderer<TElement, TNativeElement> where TElement : View where TNativeElement : FrameworkElement
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<TElement> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null)
+ {
+ UpdateBackgroundColor();
+ }
+ }
+
+ protected override void SetAutomationId(string id)
+ {
+ if (Control == null)
+ {
+ base.SetAutomationId(id);
+ }
+ else
+ {
+ SetValue(AutomationProperties.AutomationIdProperty, $"{id}_Container");
+ Control.SetValue(AutomationProperties.AutomationIdProperty, id);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/ViewToRendererConverter.cs b/Xamarin.Forms.Platform.WinRT/ViewToRendererConverter.cs
new file mode 100644
index 00000000..1c078d93
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/ViewToRendererConverter.cs
@@ -0,0 +1,113 @@
+using System;
+using Windows.Foundation;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class ViewToRendererConverter : Windows.UI.Xaml.Data.IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ var view = value as View;
+ if (view == null)
+ {
+ var page = value as Page;
+ if (page != null)
+ {
+ IVisualElementRenderer renderer = page.GetOrCreateRenderer();
+ return renderer.ContainerElement;
+ }
+ }
+
+ if (view == null)
+ return null;
+
+ return new WrapperControl(view);
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotSupportedException();
+ }
+
+ class WrapperControl : ContentControl
+ {
+ readonly View _view;
+
+ public WrapperControl(View view)
+ {
+ _view = view;
+ _view.MeasureInvalidated += (sender, args) => { InvalidateMeasure(); };
+
+ IVisualElementRenderer renderer = Platform.CreateRenderer(view);
+ Platform.SetRenderer(view, renderer);
+
+ NotifyWrapperAwareDescendants(view, renderer);
+
+ Content = renderer.ContainerElement;
+
+ // make sure we re-measure once the template is applied
+ FrameworkElement frameworkElement = renderer.ContainerElement;
+ if (frameworkElement != null)
+ frameworkElement.Loaded += (sender, args) => InvalidateMeasure();
+ }
+
+ protected override Windows.Foundation.Size ArrangeOverride(Windows.Foundation.Size finalSize)
+ {
+ _view.IsInNativeLayout = true;
+ Layout.LayoutChildIntoBoundingRegion(_view, new Rectangle(0, 0, finalSize.Width, finalSize.Height));
+ _view.IsInNativeLayout = false;
+
+ var content = Content as FrameworkElement;
+ content.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
+ return finalSize;
+ }
+
+ protected override Windows.Foundation.Size MeasureOverride(Windows.Foundation.Size availableSize)
+ {
+ var content = Content as FrameworkElement;
+ content?.Measure(availableSize);
+ Size request = _view.Measure(availableSize.Width, availableSize.Height, MeasureFlags.IncludeMargins).Request;
+
+ var result = new Windows.Foundation.Size();
+ if (_view.HorizontalOptions.Alignment == LayoutAlignment.Fill && !double.IsInfinity(availableSize.Width) && availableSize.Width != 0)
+ {
+ result = new Windows.Foundation.Size(availableSize.Width, request.Height);
+ }
+ else
+ {
+ result = new Windows.Foundation.Size(request.Width, request.Height);
+ }
+
+ _view.Layout(new Rectangle(0, 0, result.Width, result.Width));
+ return result;
+ }
+
+ void NotifyWrapperAwareDescendants(Element currentView, IVisualElementRenderer currentRenderer)
+ {
+ // If any of the child renderers need to handle anything differently because they're in
+ // a wrapper in a list view, let them know that they're being wrapped
+ var wrapperAwareRenderer = currentRenderer as IWrapperAware;
+ wrapperAwareRenderer?.NotifyWrapped();
+
+ foreach (Element child in currentView.LogicalChildren)
+ {
+ var childView = child as View;
+ if (childView == null)
+ {
+ continue;
+ }
+
+ NotifyWrapperAwareDescendants(childView, Platform.GetRenderer(childView));
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/VisualElementChangedEventArgs.cs b/Xamarin.Forms.Platform.WinRT/VisualElementChangedEventArgs.cs
new file mode 100644
index 00000000..d703901c
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/VisualElementChangedEventArgs.cs
@@ -0,0 +1,30 @@
+using System;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class VisualElementChangedEventArgs : ElementChangedEventArgs<VisualElement>
+ {
+ public VisualElementChangedEventArgs(VisualElement oldElement, VisualElement newElement) : base(oldElement, newElement)
+ {
+ }
+ }
+
+ public class ElementChangedEventArgs<TElement> : EventArgs where TElement : Element
+ {
+ public ElementChangedEventArgs(TElement oldElement, TElement newElement)
+ {
+ OldElement = oldElement;
+ NewElement = newElement;
+ }
+
+ public TElement NewElement { get; private set; }
+
+ public TElement OldElement { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/VisualElementExtensions.cs b/Xamarin.Forms.Platform.WinRT/VisualElementExtensions.cs
new file mode 100644
index 00000000..9dfd12bb
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/VisualElementExtensions.cs
@@ -0,0 +1,56 @@
+using System;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public static class VisualElementExtensions
+ {
+ public static IVisualElementRenderer GetOrCreateRenderer(this VisualElement self)
+ {
+ if (self == null)
+ throw new ArgumentNullException("self");
+
+ IVisualElementRenderer renderer = Platform.GetRenderer(self);
+ if (renderer == null)
+ {
+ renderer = RendererFactory.CreateRenderer(self);
+ Platform.SetRenderer(self, renderer);
+ }
+
+ return renderer;
+ }
+
+ internal static void Cleanup(this VisualElement self)
+ {
+ if (self == null)
+ throw new ArgumentNullException("self");
+
+ IVisualElementRenderer renderer = Platform.GetRenderer(self);
+
+ foreach (Element element in self.Descendants())
+ {
+ var visual = element as VisualElement;
+ if (visual == null)
+ continue;
+
+ IVisualElementRenderer childRenderer = Platform.GetRenderer(visual);
+ if (childRenderer != null)
+ {
+ childRenderer.Dispose();
+ Platform.SetRenderer(visual, null);
+ }
+ }
+
+ if (renderer != null)
+ {
+ renderer.Dispose();
+ Platform.SetRenderer(self, null);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/VisualElementPackager.cs b/Xamarin.Forms.Platform.WinRT/VisualElementPackager.cs
new file mode 100644
index 00000000..1c4036e0
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/VisualElementPackager.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.ObjectModel;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class VisualElementPackager : IDisposable
+ {
+ readonly int _column;
+ readonly int _columnSpan;
+
+ readonly Panel _panel;
+ readonly IVisualElementRenderer _renderer;
+ readonly int _row;
+ readonly int _rowSpan;
+ bool _disposed;
+ bool _isLoaded;
+
+ public VisualElementPackager(IVisualElementRenderer renderer)
+ {
+ if (renderer == null)
+ throw new ArgumentNullException("renderer");
+
+ _renderer = renderer;
+
+ _panel = renderer.ContainerElement as Panel;
+ if (_panel == null)
+ throw new ArgumentException("Renderer's container element must be a Panel");
+ }
+
+ public VisualElementPackager(IVisualElementRenderer renderer, int row = 0, int rowSpan = 0, int column = 0, int columnSpan = 0) : this(renderer)
+ {
+ _row = row;
+ _rowSpan = rowSpan;
+ _column = column;
+ _columnSpan = columnSpan;
+ }
+
+ public void Dispose()
+ {
+ if (_disposed)
+ return;
+
+ _disposed = true;
+
+ VisualElement element = _renderer.Element;
+ if (element != null)
+ {
+ element.ChildAdded -= OnChildAdded;
+ element.ChildRemoved -= OnChildRemoved;
+ }
+ }
+
+ public void Load()
+ {
+ if (_isLoaded)
+ return;
+
+ _isLoaded = true;
+ _renderer.Element.ChildAdded += OnChildAdded;
+ _renderer.Element.ChildRemoved += OnChildRemoved;
+
+ ReadOnlyCollection<Element> children = _renderer.Element.LogicalChildren;
+ for (var i = 0; i < children.Count; i++)
+ {
+ OnChildAdded(_renderer.Element, new ElementEventArgs(children[i]));
+ }
+ }
+
+ void EnsureZIndex()
+ {
+ if (_renderer.Element.LogicalChildren.Count == 0)
+ return;
+
+ for (var z = 0; z < _renderer.Element.LogicalChildren.Count; z++)
+ {
+ var child = _renderer.Element.LogicalChildren[z] as VisualElement;
+ if (child == null)
+ continue;
+
+ IVisualElementRenderer childRenderer = Platform.GetRenderer(child);
+
+ if (childRenderer == null)
+ {
+ continue;
+ }
+
+ Canvas.SetZIndex(childRenderer.ContainerElement, z + 1);
+ }
+ }
+
+ void OnChildAdded(object sender, ElementEventArgs e)
+ {
+ var view = e.Element as VisualElement;
+
+ if (view == null)
+ return;
+
+ IVisualElementRenderer childRenderer = Platform.CreateRenderer(view);
+ Platform.SetRenderer(view, childRenderer);
+
+ if (_row > 0)
+ Windows.UI.Xaml.Controls.Grid.SetRow(childRenderer.ContainerElement, _row);
+ if (_rowSpan > 0)
+ Windows.UI.Xaml.Controls.Grid.SetRowSpan(childRenderer.ContainerElement, _rowSpan);
+ if (_column > 0)
+ Windows.UI.Xaml.Controls.Grid.SetColumn(childRenderer.ContainerElement, _column);
+ if (_columnSpan > 0)
+ Windows.UI.Xaml.Controls.Grid.SetColumnSpan(childRenderer.ContainerElement, _columnSpan);
+
+ _panel.Children.Add(childRenderer.ContainerElement);
+
+ EnsureZIndex();
+ }
+
+ void OnChildRemoved(object sender, ElementEventArgs e)
+ {
+ var view = e.Element as VisualElement;
+
+ if (view == null)
+ return;
+
+ IVisualElementRenderer childRenderer = Platform.GetRenderer(view);
+ if (childRenderer != null)
+ {
+ if (_row > 0)
+ childRenderer.ContainerElement.ClearValue(Windows.UI.Xaml.Controls.Grid.RowProperty);
+ if (_rowSpan > 0)
+ childRenderer.ContainerElement.ClearValue(Windows.UI.Xaml.Controls.Grid.RowSpanProperty);
+ if (_column > 0)
+ childRenderer.ContainerElement.ClearValue(Windows.UI.Xaml.Controls.Grid.ColumnProperty);
+ if (_columnSpan > 0)
+ childRenderer.ContainerElement.ClearValue(Windows.UI.Xaml.Controls.Grid.ColumnSpanProperty);
+
+ _panel.Children.Remove(childRenderer.ContainerElement);
+
+ view.Cleanup();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs b/Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs
new file mode 100644
index 00000000..96565d74
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs
@@ -0,0 +1,401 @@
+using System;
+using System.ComponentModel;
+using Windows.Foundation;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Automation;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class VisualElementRenderer<TElement, TNativeElement> : Panel, IVisualElementRenderer, IDisposable, IEffectControlProvider where TElement : VisualElement
+ where TNativeElement : FrameworkElement
+ {
+ bool _disposed;
+ EventHandler<VisualElementChangedEventArgs> _elementChangedHandlers;
+ VisualElementTracker<TElement, TNativeElement> _tracker;
+
+ public TNativeElement Control { get; private set; }
+
+ public TElement Element { get; private set; }
+
+ protected bool AutoPackage { get; set; } = true;
+
+ protected bool AutoTrack { get; set; } = true;
+
+ protected VisualElementTracker<TElement, TNativeElement> Tracker
+ {
+ get { return _tracker; }
+ set
+ {
+ if (_tracker == value)
+ return;
+
+ if (_tracker != null)
+ {
+ _tracker.Dispose();
+ _tracker.Updated -= OnTrackerUpdated;
+ }
+
+ _tracker = value;
+
+ if (_tracker != null)
+ {
+ _tracker.Updated += OnTrackerUpdated;
+ UpdateTracker();
+ }
+ }
+ }
+
+ VisualElementPackager Packager { get; set; }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ void IEffectControlProvider.RegisterEffect(Effect effect)
+ {
+ var platformEffect = effect as PlatformEffect;
+ if (platformEffect != null)
+ OnRegisterEffect(platformEffect);
+ }
+
+ public FrameworkElement ContainerElement
+ {
+ get { return this; }
+ }
+
+ VisualElement IVisualElementRenderer.Element
+ {
+ get { return Element; }
+ }
+
+ event EventHandler<VisualElementChangedEventArgs> IVisualElementRenderer.ElementChanged
+ {
+ add
+ {
+ if (_elementChangedHandlers == null)
+ _elementChangedHandlers = value;
+ else
+ _elementChangedHandlers = (EventHandler<VisualElementChangedEventArgs>)Delegate.Combine(_elementChangedHandlers, value);
+ }
+
+ remove { _elementChangedHandlers = (EventHandler<VisualElementChangedEventArgs>)Delegate.Remove(_elementChangedHandlers, value); }
+ }
+
+ public virtual SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ if (Children.Count == 0)
+ return new SizeRequest();
+
+ var constraint = new Windows.Foundation.Size(widthConstraint, heightConstraint);
+ TNativeElement child = Control;
+
+ child.Measure(constraint);
+ var result = new Size(Math.Ceiling(child.DesiredSize.Width), Math.Ceiling(child.DesiredSize.Height));
+
+ return new SizeRequest(result);
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ TElement oldElement = Element;
+ Element = (TElement)element;
+
+ if (oldElement != null)
+ {
+ oldElement.PropertyChanged -= OnElementPropertyChanged;
+ oldElement.FocusChangeRequested -= OnElementFocusChangeRequested;
+ }
+
+ if (element != null)
+ {
+ Element.PropertyChanged += OnElementPropertyChanged;
+ Element.FocusChangeRequested += OnElementFocusChangeRequested;
+
+ if (AutoPackage && Packager == null)
+ Packager = new VisualElementPackager(this);
+
+ if (AutoTrack && Tracker == null)
+ {
+ Tracker = new VisualElementTracker<TElement, TNativeElement>();
+ }
+
+ // Disabled until reason for crashes with unhandled exceptions is discovered
+ // Without this some layouts may end up with improper sizes, however their children
+ // will position correctly
+ //Loaded += (sender, args) => {
+ if (Packager != null)
+ Packager.Load();
+ //};
+ }
+
+ OnElementChanged(new ElementChangedEventArgs<TElement>(oldElement, Element));
+
+ var controller = (IElementController)oldElement;
+ if (controller != null && controller.EffectControlProvider == this)
+ {
+ controller.EffectControlProvider = null;
+ }
+
+ controller = element;
+ if (controller != null)
+ controller.EffectControlProvider = this;
+ }
+
+ public event EventHandler<ElementChangedEventArgs<TElement>> ElementChanged;
+
+ protected override Windows.Foundation.Size ArrangeOverride(Windows.Foundation.Size finalSize)
+ {
+ if (Element == null || finalSize.Width * finalSize.Height == 0)
+ return finalSize;
+
+ Element.IsInNativeLayout = true;
+
+ if (Control != null)
+ {
+ Control.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
+ }
+
+ for (var i = 0; i < Element.LogicalChildren.Count; i++)
+ {
+ var child = Element.LogicalChildren[i] as VisualElement;
+ if (child == null)
+ continue;
+ IVisualElementRenderer renderer = Platform.GetRenderer(child);
+ if (renderer == null)
+ continue;
+ Rectangle bounds = child.Bounds;
+
+ renderer.ContainerElement.Arrange(new Rect(bounds.X, bounds.Y, Math.Max(0, bounds.Width), Math.Max(0, bounds.Height)));
+ }
+
+ Element.IsInNativeLayout = false;
+
+ return finalSize;
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposing || _disposed)
+ return;
+
+ _disposed = true;
+
+ Tracker?.Dispose();
+ Tracker = null;
+
+ Packager?.Dispose();
+ Packager = null;
+
+ SetNativeControl(null);
+ SetElement(null);
+ }
+
+ protected override Windows.Foundation.Size MeasureOverride(Windows.Foundation.Size availableSize)
+ {
+ if (Element == null || availableSize.Width * availableSize.Height == 0)
+ return new Windows.Foundation.Size(0, 0);
+
+ Element.IsInNativeLayout = true;
+
+ for (var i = 0; i < Element.LogicalChildren.Count; i++)
+ {
+ var child = Element.LogicalChildren[i] as VisualElement;
+ if (child == null)
+ continue;
+ IVisualElementRenderer renderer = Platform.GetRenderer(child);
+ if (renderer == null)
+ continue;
+
+ renderer.ContainerElement.Measure(availableSize);
+ }
+
+ double width = Math.Max(0, Element.Width);
+ double height = Math.Max(0, Element.Height);
+ var result = new Windows.Foundation.Size(width, height);
+ if (Control != null)
+ {
+ double w = Element.Width;
+ double h = Element.Height;
+ if (w == -1)
+ w = availableSize.Width;
+ if (h == -1)
+ h = availableSize.Height;
+ w = Math.Max(0, w);
+ h = Math.Max(0, h);
+ Control.Measure(new Windows.Foundation.Size(w, h));
+ }
+
+ Element.IsInNativeLayout = false;
+
+ return result;
+ }
+
+ protected virtual void OnElementChanged(ElementChangedEventArgs<TElement> e)
+ {
+ var args = new VisualElementChangedEventArgs(e.OldElement, e.NewElement);
+ if (_elementChangedHandlers != null)
+ _elementChangedHandlers(this, args);
+
+ EventHandler<ElementChangedEventArgs<TElement>> changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ UpdateEnabled();
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackgroundColor();
+ }
+
+ protected virtual void OnRegisterEffect(PlatformEffect effect)
+ {
+ effect.Container = this;
+ effect.Control = Control;
+ }
+
+ protected virtual void SetAutomationId(string id)
+ {
+ SetValue(AutomationProperties.AutomationIdProperty, id);
+ }
+
+ protected void SetNativeControl(TNativeElement control)
+ {
+ TNativeElement oldControl = Control;
+ Control = control;
+
+ if (oldControl != null)
+ {
+ Children.Remove(oldControl);
+
+ oldControl.Loaded -= OnControlLoaded;
+ oldControl.GotFocus -= OnControlGotFocus;
+ oldControl.LostFocus -= OnControlLostFocus;
+ }
+
+ UpdateTracker();
+
+ if (control == null)
+ return;
+
+ Control.HorizontalAlignment = HorizontalAlignment.Stretch;
+ Control.VerticalAlignment = VerticalAlignment.Stretch;
+
+ Children.Add(control);
+
+ Element.IsNativeStateConsistent = false;
+ control.Loaded += OnControlLoaded;
+
+ control.GotFocus += OnControlGotFocus;
+ control.LostFocus += OnControlLostFocus;
+
+ UpdateBackgroundColor();
+
+ if (Element != null && !string.IsNullOrEmpty(Element.AutomationId))
+ SetAutomationId(Element.AutomationId);
+ }
+
+ protected virtual void UpdateBackgroundColor()
+ {
+ Color backgroundColor = Element.BackgroundColor;
+ var control = Control as Control;
+ if (control != null)
+ {
+ if (!backgroundColor.IsDefault)
+ {
+ control.Background = backgroundColor.ToBrush();
+ }
+ else
+ {
+ control.ClearValue(Windows.UI.Xaml.Controls.Control.BackgroundProperty);
+ }
+ }
+ else
+ {
+ if (!backgroundColor.IsDefault)
+ {
+ Background = backgroundColor.ToBrush();
+ }
+ else
+ {
+ ClearValue(BackgroundProperty);
+ }
+ }
+ }
+
+ protected virtual void UpdateNativeControl()
+ {
+ UpdateEnabled();
+ }
+
+ internal virtual void OnElementFocusChangeRequested(object sender, VisualElement.FocusRequestArgs args)
+ {
+ var control = Control as Control;
+ if (control == null)
+ return;
+
+ if (args.Focus)
+ args.Result = control.Focus(FocusState.Programmatic);
+ else
+ {
+ UnfocusControl(control);
+ args.Result = true;
+ }
+ }
+
+ internal void UnfocusControl(Control control)
+ {
+ if (control == null || !control.IsEnabled)
+ return;
+
+ control.IsEnabled = false;
+ control.IsEnabled = true;
+ }
+
+ void OnControlGotFocus(object sender, RoutedEventArgs args)
+ {
+ ((IVisualElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
+ }
+
+ void OnControlLoaded(object sender, RoutedEventArgs args)
+ {
+ Element.IsNativeStateConsistent = true;
+ }
+
+ void OnControlLostFocus(object sender, RoutedEventArgs args)
+ {
+ ((IVisualElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ }
+
+ void OnTrackerUpdated(object sender, EventArgs e)
+ {
+ UpdateNativeControl();
+ }
+
+ void UpdateEnabled()
+ {
+ var control = Control as Control;
+ if (control != null)
+ control.IsEnabled = Element.IsEnabled;
+ }
+
+ void UpdateTracker()
+ {
+ if (_tracker == null)
+ return;
+
+ _tracker.Control = Control;
+ _tracker.Element = Element;
+ _tracker.Container = ContainerElement;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/VisualElementTracker.cs b/Xamarin.Forms.Platform.WinRT/VisualElementTracker.cs
new file mode 100644
index 00000000..0c3f7595
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/VisualElementTracker.cs
@@ -0,0 +1,534 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class VisualElementTracker<TElement, TNativeElement> : IDisposable where TElement : VisualElement where TNativeElement : FrameworkElement
+ {
+ readonly NotifyCollectionChangedEventHandler _collectionChangedHandler;
+ readonly List<uint> _fingers = new List<uint>();
+ FrameworkElement _container;
+ TNativeElement _control;
+ TElement _element;
+
+ bool _invalidateArrangeNeeded;
+
+ bool _isDisposed;
+ bool _isPanning;
+ bool _isPinching;
+ bool _wasPanGestureStartedSent;
+ bool _wasPinchGestureStartedSent;
+
+ public VisualElementTracker()
+ {
+ _collectionChangedHandler = ModelGestureRecognizersOnCollectionChanged;
+ }
+
+ public FrameworkElement Container
+ {
+ get { return _container; }
+ set
+ {
+ if (_container == value)
+ return;
+
+ if (_container != null)
+ {
+ _container.Tapped -= OnTap;
+ _container.DoubleTapped -= OnDoubleTap;
+ _container.ManipulationDelta -= OnManipulationDelta;
+ _container.ManipulationStarted -= OnManipulationStarted;
+ _container.ManipulationCompleted -= OnManipulationCompleted;
+ _container.PointerPressed -= OnPointerPressed;
+ _container.PointerExited -= OnPointerExited;
+ _container.PointerReleased -= OnPointerReleased;
+ _container.PointerCanceled -= OnPointerCanceled;
+ }
+
+ _container = value;
+
+ UpdatingGestureRecognizers();
+
+ UpdateNativeControl();
+ }
+ }
+
+ public TNativeElement Control
+ {
+ get { return _control; }
+ set
+ {
+ if (_control == value)
+ return;
+
+ _control = value;
+ UpdateNativeControl();
+ }
+ }
+
+ public TElement Element
+ {
+ get { return _element; }
+ set
+ {
+ if (_element == value)
+ return;
+
+ if (_element != null)
+ {
+ _element.BatchCommitted -= OnRedrawNeeded;
+ _element.PropertyChanged -= OnPropertyChanged;
+
+ var view = _element as View;
+ if (view != null)
+ {
+ var oldRecognizers = (ObservableCollection<IGestureRecognizer>)view.GestureRecognizers;
+ oldRecognizers.CollectionChanged -= _collectionChangedHandler;
+ }
+ }
+
+ _element = value;
+
+ if (_element != null)
+ {
+ _element.BatchCommitted += OnRedrawNeeded;
+ _element.PropertyChanged += OnPropertyChanged;
+
+ var view = _element as View;
+ if (view != null)
+ {
+ var newRecognizers = (ObservableCollection<IGestureRecognizer>)view.GestureRecognizers;
+ newRecognizers.CollectionChanged += _collectionChangedHandler;
+ }
+ }
+
+ UpdateNativeControl();
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ public event EventHandler Updated;
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_isDisposed)
+ return;
+
+ _isDisposed = true;
+
+ if (!disposing)
+ return;
+
+ if (_container != null)
+ {
+ _container.PointerPressed -= OnPointerPressed;
+ _container.PointerExited -= OnPointerExited;
+ _container.PointerReleased -= OnPointerReleased;
+ _container.PointerCanceled -= OnPointerCanceled;
+ _container.Tapped -= OnTap;
+ _container.DoubleTapped -= OnDoubleTap;
+ _container.ManipulationDelta -= OnManipulationDelta;
+ _container.ManipulationStarted -= OnManipulationStarted;
+ _container.ManipulationCompleted -= OnManipulationCompleted;
+ }
+
+ if (_element != null)
+ {
+ _element.BatchCommitted -= OnRedrawNeeded;
+ _element.PropertyChanged -= OnPropertyChanged;
+
+ var view = _element as View;
+ if (view != null)
+ {
+ var oldRecognizers = (ObservableCollection<IGestureRecognizer>)view.GestureRecognizers;
+ oldRecognizers.CollectionChanged -= _collectionChangedHandler;
+ }
+ }
+
+ Control = null;
+ Element = null;
+ Container = null;
+ }
+
+ protected virtual void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (Element.Batched)
+ {
+ if (e.PropertyName == VisualElement.XProperty.PropertyName || e.PropertyName == VisualElement.YProperty.PropertyName || e.PropertyName == VisualElement.WidthProperty.PropertyName ||
+ e.PropertyName == VisualElement.HeightProperty.PropertyName)
+ {
+ _invalidateArrangeNeeded = true;
+ }
+ return;
+ }
+
+ if (e.PropertyName == VisualElement.XProperty.PropertyName || e.PropertyName == VisualElement.YProperty.PropertyName || e.PropertyName == VisualElement.WidthProperty.PropertyName ||
+ e.PropertyName == VisualElement.HeightProperty.PropertyName)
+ {
+ MaybeInvalidate();
+ }
+ else if (e.PropertyName == VisualElement.AnchorXProperty.PropertyName || e.PropertyName == VisualElement.AnchorYProperty.PropertyName)
+ {
+ UpdateScaleAndRotation(Element, Container);
+ }
+ else if (e.PropertyName == VisualElement.ScaleProperty.PropertyName)
+ {
+ UpdateScaleAndRotation(Element, Container);
+ }
+ else if (e.PropertyName == VisualElement.TranslationXProperty.PropertyName || e.PropertyName == VisualElement.TranslationYProperty.PropertyName ||
+ e.PropertyName == VisualElement.RotationProperty.PropertyName || e.PropertyName == VisualElement.RotationXProperty.PropertyName || e.PropertyName == VisualElement.RotationYProperty.PropertyName)
+ {
+ UpdateRotation(Element, Container);
+ }
+ else if (e.PropertyName == VisualElement.IsVisibleProperty.PropertyName)
+ {
+ UpdateVisibility(Element, Container);
+ }
+ else if (e.PropertyName == VisualElement.OpacityProperty.PropertyName)
+ {
+ UpdateOpacity(Element, Container);
+ }
+ else if (e.PropertyName == VisualElement.InputTransparentProperty.PropertyName)
+ {
+ UpdateInputTransparent(Element, Container);
+ }
+ }
+
+ protected virtual void UpdateNativeControl()
+ {
+ if (Element == null || Container == null)
+ return;
+
+ UpdateVisibility(Element, Container);
+ UpdateOpacity(Element, Container);
+ UpdateScaleAndRotation(Element, Container);
+ UpdateInputTransparent(Element, Container);
+
+ if (_invalidateArrangeNeeded)
+ {
+ MaybeInvalidate();
+ }
+ _invalidateArrangeNeeded = false;
+
+ OnUpdated();
+ }
+
+ void HandlePan(ManipulationDeltaRoutedEventArgs e, View view)
+ {
+ if (view == null)
+ return;
+
+ _isPanning = true;
+
+ foreach (PanGestureRecognizer recognizer in view.GestureRecognizers.GetGesturesFor<PanGestureRecognizer>().Where(g => g.TouchPoints == _fingers.Count))
+ {
+ if (!_wasPanGestureStartedSent)
+ {
+ ((IPanGestureController)recognizer).SendPanStarted(view, Application.Current.PanGestureId);
+ }
+ ((IPanGestureController)recognizer).SendPan(view, e.Delta.Translation.X + e.Cumulative.Translation.X, e.Delta.Translation.Y + e.Cumulative.Translation.Y, Application.Current.PanGestureId);
+ }
+ _wasPanGestureStartedSent = true;
+ }
+
+ void HandlePinch(ManipulationDeltaRoutedEventArgs e, View view)
+ {
+ if (_fingers.Count < 2 || view == null)
+ return;
+
+ _isPinching = true;
+
+ Windows.Foundation.Point translationPoint = e.Container.TransformToVisual(Container).TransformPoint(e.Position);
+
+ var scaleOriginPoint = new Point(translationPoint.X / view.Width, translationPoint.Y / view.Height);
+ IEnumerable<PinchGestureRecognizer> pinchGestures = view.GestureRecognizers.GetGesturesFor<PinchGestureRecognizer>();
+ foreach (PinchGestureRecognizer recognizer in pinchGestures)
+ {
+ if (!_wasPinchGestureStartedSent)
+ {
+ ((IPinchGestureController)recognizer).SendPinchStarted(view, scaleOriginPoint);
+ }
+ ((IPinchGestureController)recognizer).SendPinch(view, e.Delta.Scale, scaleOriginPoint);
+ }
+ _wasPinchGestureStartedSent = true;
+ }
+
+ void MaybeInvalidate()
+ {
+ if (Element.IsInNativeLayout)
+ return;
+ var parent = (FrameworkElement)Container.Parent;
+ parent?.InvalidateMeasure();
+ Container.InvalidateMeasure();
+ }
+
+ void ModelGestureRecognizersOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
+ {
+ UpdatingGestureRecognizers();
+ }
+
+ void OnDoubleTap(object sender, DoubleTappedRoutedEventArgs e)
+ {
+ var view = Element as View;
+ if (view == null)
+ return;
+
+ IEnumerable<TapGestureRecognizer> doubleTapGestures = view.GestureRecognizers.GetGesturesFor<TapGestureRecognizer>(g => g.NumberOfTapsRequired == 2);
+ foreach (TapGestureRecognizer recognizer in doubleTapGestures)
+ recognizer.SendTapped(view);
+ }
+
+ void OnManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
+ {
+ PinchComplete(true);
+ PanComplete(true);
+ }
+
+ void OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
+ {
+ var view = Element as View;
+ if (view == null)
+ return;
+
+ HandlePinch(e, view);
+ HandlePan(e, view);
+ }
+
+ void OnManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
+ {
+ var view = Element as View;
+ if (view == null)
+ return;
+ _wasPinchGestureStartedSent = false;
+ _wasPanGestureStartedSent = false;
+ }
+
+ void OnPointerCanceled(object sender, PointerRoutedEventArgs e)
+ {
+ uint id = e.Pointer.PointerId;
+ if (_fingers.Contains(id))
+ _fingers.Remove(id);
+
+ PinchComplete(false);
+ PanComplete(false);
+ }
+
+ void OnPointerExited(object sender, PointerRoutedEventArgs e)
+ {
+ uint id = e.Pointer.PointerId;
+ if (_fingers.Contains(id))
+ _fingers.Remove(id);
+
+ PinchComplete(true);
+ PanComplete(true);
+ }
+
+ void OnPointerPressed(object sender, PointerRoutedEventArgs e)
+ {
+ uint id = e.Pointer.PointerId;
+ if (!_fingers.Contains(id))
+ _fingers.Add(id);
+ }
+
+ void OnPointerReleased(object sender, PointerRoutedEventArgs e)
+ {
+ uint id = e.Pointer.PointerId;
+ if (_fingers.Contains(id))
+ _fingers.Remove(id);
+
+ PinchComplete(true);
+ PanComplete(true);
+ }
+
+ void OnRedrawNeeded(object sender, EventArgs e)
+ {
+ UpdateNativeControl();
+ }
+
+ void OnTap(object sender, TappedRoutedEventArgs e)
+ {
+ var view = Element as View;
+ if (view == null)
+ return;
+
+ IEnumerable<TapGestureRecognizer> tapGestures = view.GestureRecognizers.GetGesturesFor<TapGestureRecognizer>(g => g.NumberOfTapsRequired == 1);
+ foreach (TapGestureRecognizer recognizer in tapGestures)
+ {
+ recognizer.SendTapped(view);
+ e.Handled = true;
+ }
+ }
+
+ void OnUpdated()
+ {
+ if (Updated != null)
+ Updated(this, EventArgs.Empty);
+ }
+
+ void PanComplete(bool success)
+ {
+ var view = Element as View;
+ if (view == null || !_isPanning)
+ return;
+
+ foreach (PanGestureRecognizer recognizer in view.GestureRecognizers.GetGesturesFor<PanGestureRecognizer>().Where(g => g.TouchPoints == _fingers.Count))
+ {
+ if (success)
+ {
+ ((IPanGestureController)recognizer).SendPanCompleted(view, Application.Current.PanGestureId);
+ }
+ else
+ {
+ ((IPanGestureController)recognizer).SendPanCanceled(view, Application.Current.PanGestureId);
+ }
+ }
+
+ Application.Current.PanGestureId++;
+ _isPanning = false;
+ }
+
+ void PinchComplete(bool success)
+ {
+ var view = Element as View;
+ if (view == null || !_isPinching)
+ return;
+
+ IEnumerable<PinchGestureRecognizer> pinchGestures = view.GestureRecognizers.GetGesturesFor<PinchGestureRecognizer>();
+ foreach (PinchGestureRecognizer recognizer in pinchGestures)
+ {
+ if (success)
+ {
+ ((IPinchGestureController)recognizer).SendPinchEnded(view);
+ }
+ else
+ {
+ ((IPinchGestureController)recognizer).SendPinchCanceled(view);
+ }
+ }
+
+ _isPinching = false;
+ }
+
+ static void UpdateInputTransparent(VisualElement view, FrameworkElement frameworkElement)
+ {
+ frameworkElement.IsHitTestVisible = !view.InputTransparent;
+ }
+
+ static void UpdateOpacity(VisualElement view, FrameworkElement frameworkElement)
+ {
+ frameworkElement.Opacity = view.Opacity;
+ }
+
+ static void UpdateRotation(VisualElement view, FrameworkElement frameworkElement)
+ {
+ double anchorX = view.AnchorX;
+ double anchorY = view.AnchorY;
+ double rotationX = view.RotationX;
+ double rotationY = view.RotationY;
+ double rotation = view.Rotation;
+ double translationX = view.TranslationX;
+ double translationY = view.TranslationY;
+ double scale = view.Scale;
+
+ if (rotationX % 360 == 0 && rotationY % 360 == 0 && rotation % 360 == 0 && translationX == 0 && translationY == 0 && scale == 1)
+ {
+ frameworkElement.Projection = null;
+ }
+ else
+ {
+ frameworkElement.Projection = new PlaneProjection
+ {
+ CenterOfRotationX = anchorX,
+ CenterOfRotationY = anchorY,
+ GlobalOffsetX = translationX / scale,
+ GlobalOffsetY = translationY / scale,
+ RotationX = -rotationX,
+ RotationY = -rotationY,
+ RotationZ = -rotation
+ };
+ }
+ }
+
+ static void UpdateScaleAndRotation(VisualElement view, FrameworkElement frameworkElement)
+ {
+ double anchorX = view.AnchorX;
+ double anchorY = view.AnchorY;
+ double scale = view.Scale;
+ frameworkElement.RenderTransformOrigin = new Windows.Foundation.Point(anchorX, anchorY);
+ frameworkElement.RenderTransform = new ScaleTransform { ScaleX = scale, ScaleY = scale };
+
+ UpdateRotation(view, frameworkElement);
+ }
+
+ static void UpdateVisibility(VisualElement view, FrameworkElement frameworkElement)
+ {
+ frameworkElement.Visibility = view.IsVisible ? Visibility.Visible : Visibility.Collapsed;
+ }
+
+ void UpdatingGestureRecognizers()
+ {
+ var view = Element as View;
+ IList<IGestureRecognizer> gestures = view?.GestureRecognizers;
+
+ if (_container == null || gestures == null)
+ return;
+
+ _container.Tapped -= OnTap;
+ _container.DoubleTapped -= OnDoubleTap;
+ _container.ManipulationDelta -= OnManipulationDelta;
+ _container.ManipulationStarted -= OnManipulationStarted;
+ _container.ManipulationCompleted -= OnManipulationCompleted;
+ _container.PointerPressed -= OnPointerPressed;
+ _container.PointerExited -= OnPointerExited;
+ _container.PointerReleased -= OnPointerReleased;
+ _container.PointerCanceled -= OnPointerCanceled;
+
+ if (gestures.GetGesturesFor<TapGestureRecognizer>(g => g.NumberOfTapsRequired == 1).GetEnumerator().MoveNext())
+ _container.Tapped += OnTap;
+
+ if (gestures.GetGesturesFor<TapGestureRecognizer>(g => g.NumberOfTapsRequired == 2).GetEnumerator().MoveNext())
+ _container.DoubleTapped += OnDoubleTap;
+
+ bool hasPinchGesture = gestures.GetGesturesFor<PinchGestureRecognizer>().GetEnumerator().MoveNext();
+ bool hasPanGesture = gestures.GetGesturesFor<PanGestureRecognizer>().GetEnumerator().MoveNext();
+ if (!hasPinchGesture && !hasPanGesture)
+ return;
+
+ //We can't handle ManipulationMode.Scale and System , so we don't support pinch/pan on a scrollview
+ if (Element is ScrollView)
+ {
+ if (hasPinchGesture)
+ Log.Warning("Gestures", "PinchGestureRecognizer is not supported on a ScrollView in Windows Platforms");
+ if (hasPanGesture)
+ Log.Warning("Gestures", "PanGestureRecognizer is not supported on a ScrollView in Windows Platforms");
+ return;
+ }
+
+ _container.ManipulationMode = ManipulationModes.Scale | ManipulationModes.TranslateX | ManipulationModes.TranslateY;
+ _container.ManipulationDelta += OnManipulationDelta;
+ _container.ManipulationStarted += OnManipulationStarted;
+ _container.ManipulationCompleted += OnManipulationCompleted;
+ _container.PointerPressed += OnPointerPressed;
+ _container.PointerExited += OnPointerExited;
+ _container.PointerReleased += OnPointerReleased;
+ _container.PointerCanceled += OnPointerCanceled;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/WebViewRenderer.cs b/Xamarin.Forms.Platform.WinRT/WebViewRenderer.cs
new file mode 100644
index 00000000..8074f3f1
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/WebViewRenderer.cs
@@ -0,0 +1,174 @@
+using System;
+using System.ComponentModel;
+using Windows.UI.Core;
+using Windows.UI.Xaml.Controls;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public class WebViewRenderer : ViewRenderer<WebView, Windows.UI.Xaml.Controls.WebView>, IWebViewRenderer
+ {
+ WebNavigationEvent _eventState;
+ bool _updating;
+
+ public void LoadHtml(string html, string baseUrl)
+ {
+ /*
+ * FIXME: If baseUrl is a file URL, set the Base property to its path.
+ * Otherwise, it doesn't seem as if WebBrowser can handle it.
+ */
+ Control.NavigateToString(html);
+ }
+
+ public void LoadUrl(string url)
+ {
+ Control.Source = new Uri(url);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (Control != null)
+ {
+ Control.NavigationStarting -= OnNavigationStarted;
+ Control.NavigationCompleted -= OnNavigationCompleted;
+ Control.NavigationFailed -= OnNavigationFailed;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ {
+ e.OldElement.EvalRequested -= OnEvalRequested;
+ e.OldElement.GoBackRequested -= OnGoBackRequested;
+ e.OldElement.GoForwardRequested -= OnGoForwardRequested;
+ }
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var webView = new Windows.UI.Xaml.Controls.WebView();
+ webView.NavigationStarting += OnNavigationStarted;
+ webView.NavigationCompleted += OnNavigationCompleted;
+ webView.NavigationFailed += OnNavigationFailed;
+ SetNativeControl(webView);
+ }
+
+ e.NewElement.EvalRequested += OnEvalRequested;
+ e.NewElement.GoForwardRequested += OnGoForwardRequested;
+ e.NewElement.GoBackRequested += OnGoBackRequested;
+
+ Load();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == WebView.SourceProperty.PropertyName)
+ {
+ if (!_updating)
+ Load();
+ }
+ }
+
+ void Load()
+ {
+ if (Element.Source != null)
+ Element.Source.Load(this);
+
+ UpdateCanGoBackForward();
+ }
+
+ async void OnEvalRequested(object sender, EventArg<string> eventArg)
+ {
+ await Control.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Control.InvokeScript("eval", new[] { eventArg.Data }));
+ }
+
+ void OnGoBackRequested(object sender, EventArgs eventArgs)
+ {
+ if (Control.CanGoBack)
+ {
+ _eventState = WebNavigationEvent.Back;
+ Control.GoBack();
+ }
+
+ UpdateCanGoBackForward();
+ }
+
+ void OnGoForwardRequested(object sender, EventArgs eventArgs)
+ {
+ if (Control.CanGoForward)
+ {
+ _eventState = WebNavigationEvent.Forward;
+ Control.GoForward();
+ }
+
+ UpdateCanGoBackForward();
+ }
+
+ void OnNavigationCompleted(Windows.UI.Xaml.Controls.WebView sender, WebViewNavigationCompletedEventArgs e)
+ {
+ if (e.Uri != null)
+ SendNavigated(new UrlWebViewSource { Url = e.Uri.AbsoluteUri }, _eventState, WebNavigationResult.Success);
+
+ UpdateCanGoBackForward();
+ }
+
+ void OnNavigationFailed(object sender, WebViewNavigationFailedEventArgs e)
+ {
+ if (e.Uri != null)
+ SendNavigated(new UrlWebViewSource { Url = e.Uri.AbsoluteUri }, _eventState, WebNavigationResult.Failure);
+ }
+
+ void OnNavigationStarted(Windows.UI.Xaml.Controls.WebView sender, WebViewNavigationStartingEventArgs e)
+ {
+ Uri uri = e.Uri;
+
+ if (uri != null)
+ {
+ var args = new WebNavigatingEventArgs(_eventState, new UrlWebViewSource { Url = uri.AbsoluteUri }, uri.AbsoluteUri);
+
+ Element.SendNavigating(args);
+ e.Cancel = args.Cancel;
+
+ // reset in this case because this is the last event we will get
+ if (args.Cancel)
+ _eventState = WebNavigationEvent.NewPage;
+ }
+ }
+
+ void SendNavigated(UrlWebViewSource source, WebNavigationEvent evnt, WebNavigationResult result)
+ {
+ _updating = true;
+ ((IElementController)Element).SetValueFromRenderer(WebView.SourceProperty, source);
+ _updating = false;
+
+ Element.SendNavigated(new WebNavigatedEventArgs(evnt, source, source.Url, result));
+
+ UpdateCanGoBackForward();
+ _eventState = WebNavigationEvent.NewPage;
+ }
+
+ // Nasty hack because we cant bind this because OneWayToSource isn't a thing in WP8, yay
+ void UpdateCanGoBackForward()
+ {
+ Element.CanGoBack = Control.CanGoBack;
+ Element.CanGoForward = Control.CanGoForward;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/WindowsBasePage.cs b/Xamarin.Forms.Platform.WinRT/WindowsBasePage.cs
new file mode 100644
index 00000000..31973212
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/WindowsBasePage.cs
@@ -0,0 +1,56 @@
+using System;
+using System.ComponentModel;
+using Windows.ApplicationModel;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ public abstract class WindowsBasePage : Windows.UI.Xaml.Controls.Page
+ {
+ public WindowsBasePage()
+ {
+ Windows.UI.Xaml.Application.Current.Suspending += OnApplicationSuspending;
+ Windows.UI.Xaml.Application.Current.Resuming += OnApplicationResuming;
+ }
+
+ protected Platform Platform { get; private set; }
+
+ protected abstract Platform CreatePlatform();
+
+ protected void LoadApplication(Application application)
+ {
+ if (application == null)
+ throw new ArgumentNullException("application");
+
+ Application.Current = application;
+ Platform = CreatePlatform();
+ Platform.SetPage(Application.Current.MainPage);
+ application.PropertyChanged += OnApplicationPropertyChanged;
+
+ Application.Current.SendStart();
+ }
+
+ void OnApplicationPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "MainPage")
+ Platform.SetPage(Application.Current.MainPage);
+ }
+
+ void OnApplicationResuming(object sender, object e)
+ {
+ Application.Current.SendResume();
+ }
+
+ async void OnApplicationSuspending(object sender, SuspendingEventArgs e)
+ {
+ SuspendingDeferral deferral = e.SuspendingOperation.GetDeferral();
+ await Application.Current.SendSleepAsync();
+ deferral.Complete();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/WindowsBasePlatformServices.cs b/Xamarin.Forms.Platform.WinRT/WindowsBasePlatformServices.cs
new file mode 100644
index 00000000..bff32b78
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/WindowsBasePlatformServices.cs
@@ -0,0 +1,179 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net.Http;
+using System.Reflection;
+using System.Runtime.InteropServices.WindowsRuntime;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Core;
+using Windows.Security.Cryptography;
+using Windows.Security.Cryptography.Core;
+using Windows.Storage;
+using Windows.Storage.Search;
+using Windows.Storage.Streams;
+using Windows.System;
+using Windows.UI.Core;
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal abstract class WindowsBasePlatformServices : IPlatformServices
+ {
+ CoreDispatcher _dispatcher;
+
+ public WindowsBasePlatformServices(CoreDispatcher dispatcher)
+ {
+ if (dispatcher == null)
+ throw new ArgumentNullException("dispatcher");
+
+ _dispatcher = dispatcher;
+ }
+
+ public void BeginInvokeOnMainThread(Action action)
+ {
+ _dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => action()).WatchForError();
+ }
+
+ public ITimer CreateTimer(Action<object> callback)
+ {
+ return new WindowsTimer(new Timer(o => callback(o), null, Timeout.Infinite, Timeout.Infinite));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, int dueTime, int period)
+ {
+ return new WindowsTimer(new Timer(o => callback(o), state, dueTime, period));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, long dueTime, long period)
+ {
+ return CreateTimer(callback, state, TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(period));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, TimeSpan dueTime, TimeSpan period)
+ {
+ return new WindowsTimer(new Timer(o => callback(o), state, dueTime, period));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, uint dueTime, uint period)
+ {
+ return CreateTimer(callback, state, TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(period));
+ }
+
+ public virtual Assembly[] GetAssemblies()
+ {
+ var options = new QueryOptions { FileTypeFilter = { ".exe", ".dll" } };
+
+ StorageFileQueryResult query = Package.Current.InstalledLocation.CreateFileQueryWithOptions(options);
+ IReadOnlyList<StorageFile> files = query.GetFilesAsync().AsTask().Result;
+
+ var assemblies = new List<Assembly>(files.Count);
+ for (var i = 0; i < files.Count; i++)
+ {
+ StorageFile file = files[i];
+ try
+ {
+ Assembly assembly = Assembly.Load(new AssemblyName { Name = Path.GetFileNameWithoutExtension(file.Name) });
+
+ assemblies.Add(assembly);
+ }
+ catch (IOException)
+ {
+ }
+ catch (BadImageFormatException)
+ {
+ }
+ }
+
+ Assembly thisAssembly = GetType().GetTypeInfo().Assembly;
+ // this happens with .NET Native
+ if (!assemblies.Contains(thisAssembly))
+ assemblies.Add(thisAssembly);
+
+ return assemblies.ToArray();
+ }
+
+ public string GetMD5Hash(string input)
+ {
+ HashAlgorithmProvider algorithm = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Md5);
+ IBuffer buffer = algorithm.HashData(Encoding.Unicode.GetBytes(input).AsBuffer());
+ return CryptographicBuffer.EncodeToHexString(buffer);
+ }
+
+ public double GetNamedSize(NamedSize size, Type targetElementType, bool useOldSizes)
+ {
+ return size.GetFontSize();
+ }
+
+ public async Task<Stream> GetStreamAsync(Uri uri, CancellationToken cancellationToken)
+ {
+ using(var client = new HttpClient())
+ {
+ HttpResponseMessage streamResponse = await client.GetAsync(uri.AbsoluteUri).ConfigureAwait(false);
+ return await streamResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
+ }
+ }
+
+ public IIsolatedStorageFile GetUserStoreForApplication()
+ {
+ return new WindowsIsolatedStorage(ApplicationData.Current.LocalFolder);
+ }
+
+ public bool IsInvokeRequired => !CoreApplication.MainView.CoreWindow.Dispatcher.HasThreadAccess;
+
+ public void OpenUriAction(Uri uri)
+ {
+ Launcher.LaunchUriAsync(uri).WatchForError();
+ }
+
+ public void StartTimer(TimeSpan interval, Func<bool> callback)
+ {
+ var timer = new DispatcherTimer { Interval = interval };
+ timer.Start();
+ timer.Tick += (sender, args) =>
+ {
+ bool result = callback();
+ if (!result)
+ timer.Stop();
+ };
+ }
+
+ internal class WindowsTimer : ITimer
+ {
+ readonly Timer _timer;
+
+ public WindowsTimer(Timer timer)
+ {
+ _timer = timer;
+ }
+
+ public void Change(int dueTime, int period)
+ {
+ _timer.Change(dueTime, period);
+ }
+
+ public void Change(long dueTime, long period)
+ {
+ Change(TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(period));
+ }
+
+ public void Change(TimeSpan dueTime, TimeSpan period)
+ {
+ _timer.Change(dueTime, period);
+ }
+
+ public void Change(uint dueTime, uint period)
+ {
+ Change(TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(period));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/WindowsDeviceInfo.cs b/Xamarin.Forms.Platform.WinRT/WindowsDeviceInfo.cs
new file mode 100644
index 00000000..f3d6d100
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/WindowsDeviceInfo.cs
@@ -0,0 +1,110 @@
+using System;
+using Windows.Foundation;
+using Windows.Graphics.Display;
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal class WindowsDeviceInfo : DeviceInfo
+ {
+ DisplayInformation _information;
+ bool _isDisposed;
+
+ public WindowsDeviceInfo()
+ {
+ // TODO: Screen size and DPI can change at any time
+ _information = DisplayInformation.GetForCurrentView();
+ _information.OrientationChanged += OnOrientationChanged;
+ CurrentOrientation = GetDeviceOrientation(_information.CurrentOrientation);
+ }
+
+ public override Size PixelScreenSize
+ {
+ get
+ {
+ double scaling = ScalingFactor;
+ Size scaled = ScaledScreenSize;
+ double width = Math.Round(scaled.Width * scaling);
+ double height = Math.Round(scaled.Height * scaling);
+
+ return new Size(width, height);
+ }
+ }
+
+ public override Size ScaledScreenSize
+ {
+ get
+ {
+ Rect windowSize = Window.Current.Bounds;
+ return new Size(windowSize.Width, windowSize.Height);
+ }
+ }
+
+ public override double ScalingFactor
+ {
+ get
+ {
+ ResolutionScale scale = _information.ResolutionScale;
+ switch (scale)
+ {
+ case ResolutionScale.Scale120Percent:
+ return 1.2;
+ case ResolutionScale.Scale140Percent:
+ return 1.4;
+ case ResolutionScale.Scale150Percent:
+ return 1.5;
+ case ResolutionScale.Scale160Percent:
+ return 1.6;
+ case ResolutionScale.Scale180Percent:
+ return 1.8;
+ case ResolutionScale.Scale225Percent:
+ return 2.25;
+ case ResolutionScale.Scale100Percent:
+ default:
+ return 1;
+ }
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (_isDisposed)
+ return;
+
+ _isDisposed = true;
+ _information.OrientationChanged -= OnOrientationChanged;
+ _information = null;
+
+ base.Dispose(disposing);
+ }
+
+ static DeviceOrientation GetDeviceOrientation(DisplayOrientations orientations)
+ {
+ switch (orientations)
+ {
+ case DisplayOrientations.Landscape:
+ case DisplayOrientations.LandscapeFlipped:
+ return DeviceOrientation.Landscape;
+
+ case DisplayOrientations.Portrait:
+ case DisplayOrientations.PortraitFlipped:
+ return DeviceOrientation.Portrait;
+
+ default:
+ case DisplayOrientations.None:
+ return DeviceOrientation.Other;
+ }
+ }
+
+ void OnOrientationChanged(DisplayInformation sender, object args)
+ {
+ CurrentOrientation = GetDeviceOrientation(sender.CurrentOrientation);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/WindowsExpressionSearch.cs b/Xamarin.Forms.Platform.WinRT/WindowsExpressionSearch.cs
new file mode 100644
index 00000000..778cc135
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/WindowsExpressionSearch.cs
@@ -0,0 +1,170 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal sealed class WindowsExpressionSearch : IExpressionSearch
+ {
+ List<object> _results;
+ Type _targeType;
+
+ public List<T> FindObjects<T>(Expression expression) where T : class
+ {
+ _results = new List<object>();
+ _targeType = typeof(T);
+
+ Visit(expression);
+
+ List<T> final = _results.Cast<T>().ToList();
+ _results = null;
+ return final;
+ }
+
+ void Visit(Expression expression)
+ {
+ if (expression == null)
+ return;
+
+ switch (expression.NodeType)
+ {
+ case ExpressionType.Negate:
+ case ExpressionType.NegateChecked:
+ case ExpressionType.Not:
+ case ExpressionType.Convert:
+ case ExpressionType.ConvertChecked:
+ case ExpressionType.ArrayLength:
+ case ExpressionType.Quote:
+ case ExpressionType.TypeAs:
+ case ExpressionType.UnaryPlus:
+ Visit(((UnaryExpression)expression).Operand);
+ break;
+ case ExpressionType.Add:
+ case ExpressionType.AddChecked:
+ case ExpressionType.Subtract:
+ case ExpressionType.SubtractChecked:
+ case ExpressionType.Multiply:
+ case ExpressionType.MultiplyChecked:
+ case ExpressionType.Divide:
+ case ExpressionType.Modulo:
+ case ExpressionType.Power:
+ case ExpressionType.And:
+ case ExpressionType.AndAlso:
+ case ExpressionType.Or:
+ case ExpressionType.OrElse:
+ case ExpressionType.LessThan:
+ case ExpressionType.LessThanOrEqual:
+ case ExpressionType.GreaterThan:
+ case ExpressionType.GreaterThanOrEqual:
+ case ExpressionType.Equal:
+ case ExpressionType.NotEqual:
+ case ExpressionType.Coalesce:
+ case ExpressionType.ArrayIndex:
+ case ExpressionType.RightShift:
+ case ExpressionType.LeftShift:
+ case ExpressionType.ExclusiveOr:
+ var binary = (BinaryExpression)expression;
+ Visit(binary.Left);
+ Visit(binary.Right);
+ Visit(binary.Conversion);
+ break;
+ case ExpressionType.TypeIs:
+ Visit(((TypeBinaryExpression)expression).Expression);
+ break;
+ case ExpressionType.Conditional:
+ var conditional = (ConditionalExpression)expression;
+ Visit(conditional.Test);
+ Visit(conditional.IfTrue);
+ Visit(conditional.IfFalse);
+ break;
+ case ExpressionType.MemberAccess:
+ VisitMemberAccess((MemberExpression)expression);
+ break;
+ case ExpressionType.Call:
+ var methodCall = (MethodCallExpression)expression;
+ Visit(methodCall.Object);
+ VisitList(methodCall.Arguments, Visit);
+ break;
+ case ExpressionType.Lambda:
+ Visit(((LambdaExpression)expression).Body);
+ break;
+ case ExpressionType.New:
+ VisitList(((NewExpression)expression).Arguments, Visit);
+ break;
+ case ExpressionType.NewArrayInit:
+ case ExpressionType.NewArrayBounds:
+ VisitList(((NewArrayExpression)expression).Expressions, Visit);
+ break;
+ case ExpressionType.Invoke:
+ var invocation = (InvocationExpression)expression;
+ VisitList(invocation.Arguments, Visit);
+ Visit(invocation.Expression);
+ break;
+ case ExpressionType.MemberInit:
+ var init = (MemberInitExpression)expression;
+ VisitList(init.NewExpression.Arguments, Visit);
+ VisitList(init.Bindings, VisitBinding);
+ break;
+ case ExpressionType.ListInit:
+ var init1 = (ListInitExpression)expression;
+ VisitList(init1.NewExpression.Arguments, Visit);
+ VisitList(init1.Initializers, initializer => VisitList(initializer.Arguments, Visit));
+ break;
+ case ExpressionType.Constant:
+ break;
+ default:
+ throw new ArgumentException(string.Format("Unhandled expression type: '{0}'", expression.NodeType));
+ }
+ }
+
+ void VisitBinding(MemberBinding binding)
+ {
+ switch (binding.BindingType)
+ {
+ case MemberBindingType.Assignment:
+ Visit(((MemberAssignment)binding).Expression);
+ break;
+ case MemberBindingType.MemberBinding:
+ VisitList(((MemberMemberBinding)binding).Bindings, VisitBinding);
+ break;
+ case MemberBindingType.ListBinding:
+ VisitList(((MemberListBinding)binding).Initializers, initializer => VisitList(initializer.Arguments, Visit));
+ break;
+ default:
+ throw new ArgumentException(string.Format("Unhandled binding type '{0}'", binding.BindingType));
+ }
+ }
+
+ static void VisitList<TList>(IEnumerable<TList> list, Action<TList> visitor)
+ {
+ foreach (TList element in list)
+ {
+ visitor(element);
+ }
+ }
+
+ // All important magic happens here
+ void VisitMemberAccess(MemberExpression member)
+ {
+ if (member.Expression is ConstantExpression && member.Member is FieldInfo)
+ {
+ object container = ((ConstantExpression)member.Expression).Value;
+ object value = ((FieldInfo)member.Member).GetValue(container);
+
+ if (_targeType.IsInstanceOfType(value))
+ {
+ _results.Add(value);
+ }
+ }
+ Visit(member.Expression);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/WindowsIsolatedStorage.cs b/Xamarin.Forms.Platform.WinRT/WindowsIsolatedStorage.cs
new file mode 100644
index 00000000..a6e48fea
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/WindowsIsolatedStorage.cs
@@ -0,0 +1,119 @@
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using Windows.Storage;
+using Windows.Storage.FileProperties;
+using Windows.Storage.Streams;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal class WindowsIsolatedStorage : IIsolatedStorageFile
+ {
+ StorageFolder _folder;
+
+ public WindowsIsolatedStorage(StorageFolder folder)
+ {
+ if (folder == null)
+ throw new ArgumentNullException("folder");
+
+ _folder = folder;
+ }
+
+ public Task CreateDirectoryAsync(string path)
+ {
+ return _folder.CreateFolderAsync(path).AsTask();
+ }
+
+ public async Task<bool> GetDirectoryExistsAsync(string path)
+ {
+ try
+ {
+ await _folder.GetFolderAsync(path).AsTask().ConfigureAwait(false);
+ return true;
+ }
+ catch (FileNotFoundException)
+ {
+ return false;
+ }
+ }
+
+ public async Task<bool> GetFileExistsAsync(string path)
+ {
+ try
+ {
+ await _folder.GetFileAsync(path).AsTask().ConfigureAwait(false);
+ return true;
+ }
+ catch (FileNotFoundException)
+ {
+ return false;
+ }
+ }
+
+ public async Task<DateTimeOffset> GetLastWriteTimeAsync(string path)
+ {
+ StorageFile file = await _folder.GetFileAsync(path).AsTask().ConfigureAwait(false);
+ BasicProperties properties = await file.GetBasicPropertiesAsync().AsTask().ConfigureAwait(false);
+ return properties.DateModified;
+ }
+
+ public async Task<Stream> OpenFileAsync(string path, FileMode mode, FileAccess access)
+ {
+ StorageFile file;
+
+ switch (mode)
+ {
+ case FileMode.CreateNew:
+ file = await _folder.CreateFileAsync(path, CreationCollisionOption.FailIfExists).AsTask().ConfigureAwait(false);
+ break;
+
+ case FileMode.Create:
+ case FileMode.Truncate: // TODO See if ReplaceExisting already truncates
+ file = await _folder.CreateFileAsync(path, CreationCollisionOption.ReplaceExisting).AsTask().ConfigureAwait(false);
+ break;
+
+ case FileMode.OpenOrCreate:
+ case FileMode.Append:
+ file = await _folder.CreateFileAsync(path, CreationCollisionOption.OpenIfExists).AsTask().ConfigureAwait(false);
+ break;
+
+ case FileMode.Open:
+ file = await _folder.GetFileAsync(path);
+ break;
+
+ default:
+ throw new ArgumentException("mode was an invalid FileMode", "mode");
+ }
+
+ switch (access)
+ {
+ case FileAccess.Read:
+ return await file.OpenStreamForReadAsync().ConfigureAwait(false);
+ case FileAccess.Write:
+ Stream stream = await file.OpenStreamForWriteAsync().ConfigureAwait(false);
+ if (mode == FileMode.Append)
+ stream.Position = stream.Length;
+
+ return stream;
+
+ case FileAccess.ReadWrite:
+ IRandomAccessStream randStream = await file.OpenAsync(FileAccessMode.ReadWrite).AsTask().ConfigureAwait(false);
+ return randStream.AsStream();
+
+ default:
+ throw new ArgumentException("access was an invalid FileAccess", "access");
+ }
+ }
+
+ public Task<Stream> OpenFileAsync(string path, FileMode mode, FileAccess access, FileShare share)
+ {
+ return OpenFileAsync(path, mode, access);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/WindowsSerializer.cs b/Xamarin.Forms.Platform.WinRT/WindowsSerializer.cs
new file mode 100644
index 00000000..4e0ad794
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/WindowsSerializer.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Threading.Tasks;
+using Windows.Storage;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal sealed class WindowsSerializer : IDeserializer
+ {
+ const string PropertyStoreFile = "PropertyStore.forms";
+
+ public async Task<IDictionary<string, object>> DeserializePropertiesAsync()
+ {
+ try
+ {
+ StorageFile file = await ApplicationData.Current.RoamingFolder.GetFileAsync(PropertyStoreFile).DontSync();
+ using(Stream stream = (await file.OpenReadAsync().DontSync()).AsStreamForRead())
+ {
+ if (stream.Length == 0)
+ return new Dictionary<string, object>(4);
+
+ var serializer = new DataContractSerializer(typeof(IDictionary<string, object>));
+ return (IDictionary<string, object>)serializer.ReadObject(stream);
+ }
+ }
+ catch (FileNotFoundException)
+ {
+ return new Dictionary<string, object>(4);
+ }
+ }
+
+ public async Task SerializePropertiesAsync(IDictionary<string, object> properties)
+ {
+ StorageFile file = await ApplicationData.Current.RoamingFolder.CreateFileAsync(PropertyStoreFile, CreationCollisionOption.ReplaceExisting).DontSync();
+ using(StorageStreamTransaction transaction = await file.OpenTransactedWriteAsync().DontSync())
+ {
+ try
+ {
+ Stream stream = transaction.Stream.AsStream();
+ var serializer = new DataContractSerializer(typeof(IDictionary<string, object>));
+ serializer.WriteObject(stream, properties);
+ await transaction.CommitAsync().DontSync();
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine("Could not move new serialized property file over old: " + e.Message);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/WindowsTicker.cs b/Xamarin.Forms.Platform.WinRT/WindowsTicker.cs
new file mode 100644
index 00000000..2e8d941d
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/WindowsTicker.cs
@@ -0,0 +1,32 @@
+using System;
+using Windows.UI.Xaml;
+
+#if WINDOWS_UWP
+
+namespace Xamarin.Forms.Platform.UWP
+#else
+
+namespace Xamarin.Forms.Platform.WinRT
+#endif
+{
+ internal class WindowsTicker : Ticker
+ {
+ DispatcherTimer _timer;
+
+ public WindowsTicker()
+ {
+ _timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(15) };
+ _timer.Tick += (sender, args) => SendSignals();
+ }
+
+ protected override void DisableTimer()
+ {
+ _timer.Stop();
+ }
+
+ protected override void EnableTimer()
+ {
+ _timer.Start();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.WinRT/Xamarin.Forms.Platform.WinRT.csproj b/Xamarin.Forms.Platform.WinRT/Xamarin.Forms.Platform.WinRT.csproj
new file mode 100644
index 00000000..e5793114
--- /dev/null
+++ b/Xamarin.Forms.Platform.WinRT/Xamarin.Forms.Platform.WinRT.csproj
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{F3FDD7AC-8899-4E41-BFD7-EC83403E736D}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Platform.WinRT</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Platform.WinRT</AssemblyName>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ </PropertyGroup>
+ <Choose>
+ <When Condition=" '$(OS)' != 'Unix' ">
+ <PropertyGroup>
+ <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Profile32</TargetFrameworkProfile>
+ </PropertyGroup>
+ </When>
+ <When Condition=" '$(OS)' == 'Unix' ">
+ <PropertyGroup>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
+ </PropertyGroup>
+ </When>
+ </Choose>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .NET Framework is automatically included -->
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup Condition=" '$(OS)' != 'Unix' ">
+ <TargetPlatform Include="WindowsPhoneApp, Version=8.1" />
+ <TargetPlatform Include="Windows, Version=8.1" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup Condition=" '$(OS)' != 'Unix' ">
+ <Compile Include="CarouselViewRenderer.cs" />
+ <Compile Include="NativeViewWrapper.cs" />
+ <Compile Include="NativeViewWrapperRenderer.cs" />
+ <Compile Include="ViewExtensions.cs" />
+ <Compile Include="LayoutExtensions.cs" />
+ <Compile Include="PlatformEffect.cs" />
+ <Compile Include="FormsComboBox.cs" />
+ <Compile Include="IWrapperAware.cs" />
+ <Compile Include="FormsDatePicker.cs" />
+ <Compile Include="FormsTimePicker.cs" />
+ <Compile Include="FormsTextBox.cs" />
+ <Compile Include="ITitleProvider.cs" />
+ <Compile Include="IToolbarProvider.cs" />
+ <Compile Include="FrameworkElementExtensions.cs" />
+ <Compile Include="ActivityIndicatorRenderer.cs" />
+ <Compile Include="AsyncValue.cs" />
+ <Compile Include="BackgroundTracker.cs" />
+ <Compile Include="BoolToVisibilityConverter.cs" />
+ <Compile Include="ButtonRenderer.cs" />
+ <Compile Include="CarouselPageRenderer.cs" />
+ <Compile Include="CellControl.cs" />
+ <Compile Include="CollapseWhenEmptyConverter.cs" />
+ <Compile Include="ColorConverter.cs" />
+ <Compile Include="ConvertExtensions.cs" />
+ <Compile Include="DatePickerRenderer.cs" />
+ <Compile Include="DefaultRenderer.cs" />
+ <Compile Include="EditorRenderer.cs" />
+ <Compile Include="EntryCellTextBox.cs" />
+ <Compile Include="EntryRenderer.cs" />
+ <Compile Include="ExportRendererAttribute.cs" />
+ <Compile Include="FileImageSourcePathConverter.cs" />
+ <Compile Include="FormsButton.cs" />
+ <Compile Include="FrameRenderer.cs" />
+ <Compile Include="ImageConverter.cs" />
+ <Compile Include="KeyboardConverter.cs" />
+ <Compile Include="KeyboardExtensions.cs" />
+ <Compile Include="ListGroupHeaderPresenter.cs" />
+ <Compile Include="ListViewGroupStyleSelector.cs" />
+ <Compile Include="MasterBackgroundConverter.cs" />
+ <Compile Include="MasterDetailControl.cs" />
+ <Compile Include="MasterDetailPageRenderer.cs" />
+ <Compile Include="MenuItemCommand.cs" />
+ <Compile Include="PageToRenderedElementConverter.cs" />
+ <Compile Include="PickerRenderer.cs" />
+ <Compile Include="StepperControl.xaml.cs">
+ <DependentUpon>StepperControl.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="StepperRenderer.cs" />
+ <Compile Include="TableViewRenderer.cs" />
+ <Compile Include="TimePickerRenderer.cs" />
+ <Compile Include="ViewToRendererConverter.cs" />
+ <Compile Include="VisualElementExtensions.cs" />
+ <Compile Include="Extensions.cs" />
+ <Compile Include="FileImageSourceHandler.cs" />
+ <Compile Include="FontExtensions.cs" />
+ <Compile Include="HeightConverter.cs" />
+ <Compile Include="ICellRenderer.cs" />
+ <Compile Include="IImageSourceHandler.cs" />
+ <Compile Include="ImageLoaderSourceHandler.cs" />
+ <Compile Include="ImageRenderer.cs" />
+ <Compile Include="IVisualElementRenderer.cs" />
+ <Compile Include="LabelRenderer.cs" />
+ <Compile Include="CaseConverter.cs" />
+ <Compile Include="ListViewRenderer.cs" />
+ <Compile Include="NavigationPageRenderer.cs" />
+ <Compile Include="PageControl.xaml.cs">
+ <DependentUpon>PageControl.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Platform.cs" />
+ <Compile Include="ProgressBarRenderer.cs" />
+ <Compile Include="RendererFactory.cs" />
+ <Compile Include="BoxViewRenderer.cs" />
+ <Compile Include="LayoutRenderer.cs" />
+ <Compile Include="PageRenderer.cs" />
+ <Compile Include="ScrollViewRenderer.cs" />
+ <Compile Include="SliderRenderer.cs" />
+ <Compile Include="StreamImagesourceHandler.cs" />
+ <Compile Include="SwitchRenderer.cs" />
+ <Compile Include="TaskExtensions.cs" />
+ <Compile Include="TextCellRenderer.cs" />
+ <Compile Include="ViewRenderer.cs" />
+ <Compile Include="VisualElementPackager.cs" />
+ <Compile Include="VisualElementRenderer.cs" />
+ <Compile Include="VisualElementTracker.cs" />
+ <Compile Include="WebViewRenderer.cs" />
+ <Compile Include="WindowsBasePage.cs" />
+ <Compile Include="WindowsExpressionSearch.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="WindowsDeviceInfo.cs" />
+ <Compile Include="WindowsIsolatedStorage.cs" />
+ <Compile Include="WindowsBasePlatformServices.cs" />
+ <Compile Include="WindowsSerializer.cs" />
+ <Compile Include="WindowsTicker.cs" />
+ <Compile Include="VisualElementChangedEventArgs.cs" />
+ <Compile Include="HorizontalTextAlignmentConverter.cs" />
+ <Compile Include="AlignmentExtensions.cs" />
+ <Compile Include="TextAlignmentToHorizontalAlignmentConverter.cs" />
+ <Page Include="PageControl.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="StepperControl.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/CADisplayLinkTicker.cs b/Xamarin.Forms.Platform.iOS/CADisplayLinkTicker.cs
new file mode 100644
index 00000000..29dd732a
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/CADisplayLinkTicker.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Concurrent;
+using System.Threading;
+#if __UNIFIED__
+using UIKit;
+using CoreAnimation;
+using Foundation;
+
+#else
+using MonoTouch.UIKit;
+using MonoTouch.CoreAnimation;
+using MonoTouch.Foundation;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ internal class CADisplayLinkTicker : Ticker
+ {
+ readonly BlockingCollection<Action> _queue = new BlockingCollection<Action>();
+ CADisplayLink _link;
+
+ public CADisplayLinkTicker()
+ {
+ var thread = new Thread(StartThread);
+ thread.Start();
+ }
+
+ internal new static CADisplayLinkTicker Default
+ {
+ get { return Ticker.Default as CADisplayLinkTicker; }
+ }
+
+ public void Invoke(Action action)
+ {
+ _queue.Add(action);
+ }
+
+ protected override void DisableTimer()
+ {
+ if (_link != null)
+ {
+ _link.RemoveFromRunLoop(NSRunLoop.Current, NSRunLoop.NSRunLoopCommonModes);
+ _link.Dispose();
+ }
+ _link = null;
+ }
+
+ protected override void EnableTimer()
+ {
+ _link = CADisplayLink.Create(() => SendSignals());
+ _link.AddToRunLoop(NSRunLoop.Current, NSRunLoop.NSRunLoopCommonModes);
+ }
+
+ void StartThread()
+ {
+ while (true)
+ {
+ var action = _queue.Take();
+ var previous = UIApplication.CheckForIllegalCrossThreadCalls;
+ UIApplication.CheckForIllegalCrossThreadCalls = false;
+
+ CATransaction.Begin();
+ action.Invoke();
+
+ while (_queue.TryTake(out action))
+ action.Invoke();
+ CATransaction.Commit();
+
+ UIApplication.CheckForIllegalCrossThreadCalls = previous;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Cells/CellRenderer.cs b/Xamarin.Forms.Platform.iOS/Cells/CellRenderer.cs
new file mode 100644
index 00000000..c01a7774
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Cells/CellRenderer.cs
@@ -0,0 +1,77 @@
+using System;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class CellRenderer : IRegisterable
+ {
+ static readonly BindableProperty RealCellProperty = BindableProperty.CreateAttached("RealCell", typeof(UITableViewCell), typeof(Cell), null);
+
+ EventHandler _onForceUpdateSizeRequested;
+
+ public virtual UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
+ {
+ var tvc = reusableCell as CellTableViewCell ?? new CellTableViewCell(UITableViewCellStyle.Default, item.GetType().FullName);
+
+ tvc.Cell = item;
+
+ WireUpForceUpdateSizeRequested(item, tvc, tv);
+
+ tvc.TextLabel.Text = item.ToString();
+
+ UpdateBackground(tvc, item);
+ return tvc;
+ }
+
+ protected void UpdateBackground(UITableViewCell tableViewCell, Cell cell)
+ {
+ if (TemplatedItemsList<ItemsView<Cell>, Cell>.GetIsGroupHeader(cell))
+ {
+ if (UIDevice.CurrentDevice.CheckSystemVersion(7, 0))
+ tableViewCell.BackgroundColor = new UIColor(247f / 255f, 247f / 255f, 247f / 255f, 1);
+ }
+ else
+ {
+ // Must be set to a solid color or blending issues will occur
+ var bgColor = UIColor.White;
+
+ var element = cell.RealParent as VisualElement;
+ if (element != null)
+ bgColor = element.BackgroundColor == Color.Default ? bgColor : element.BackgroundColor.ToUIColor();
+
+ tableViewCell.BackgroundColor = bgColor;
+ }
+ }
+
+ protected void WireUpForceUpdateSizeRequested(Cell cell, UITableViewCell nativeCell, UITableView tableView)
+ {
+ cell.ForceUpdateSizeRequested -= _onForceUpdateSizeRequested;
+
+ _onForceUpdateSizeRequested = delegate
+ {
+ var index = tableView.IndexPathForCell(nativeCell);
+ if (index != null)
+ tableView.ReloadRows(new[] { index }, UITableViewRowAnimation.None);
+ };
+
+ cell.ForceUpdateSizeRequested += _onForceUpdateSizeRequested;
+ }
+
+ internal static UITableViewCell GetRealCell(BindableObject cell)
+ {
+ return (UITableViewCell)cell.GetValue(RealCellProperty);
+ }
+
+ internal static void SetRealCell(BindableObject cell, UITableViewCell renderer)
+ {
+ cell.SetValue(RealCellProperty, renderer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Cells/CellTableViewCell.cs b/Xamarin.Forms.Platform.iOS/Cells/CellTableViewCell.cs
new file mode 100644
index 00000000..a9265868
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Cells/CellTableViewCell.cs
@@ -0,0 +1,96 @@
+using System;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class CellTableViewCell : UITableViewCell, INativeElementView
+ {
+ Cell _cell;
+
+ public Action<object, PropertyChangedEventArgs> PropertyChanged;
+
+ public CellTableViewCell(UITableViewCellStyle style, string key) : base(style, key)
+ {
+ }
+
+ public Cell Cell
+ {
+ get { return _cell; }
+ set
+ {
+ if (_cell == value)
+ return;
+
+ if (_cell != null)
+ Device.BeginInvokeOnMainThread(_cell.SendDisappearing);
+ _cell = value;
+ if (_cell != null)
+ Device.BeginInvokeOnMainThread(_cell.SendAppearing);
+ }
+ }
+
+ public Element Element => Cell;
+
+ public void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (PropertyChanged != null)
+ PropertyChanged(this, e);
+ }
+
+ internal static UITableViewCell GetNativeCell(UITableView tableView, Cell cell, bool recycleCells = false, string templateId = "")
+ {
+ var id = cell.GetType().FullName;
+
+ var renderer = (CellRenderer)Registrar.Registered.GetHandler(cell.GetType());
+
+ ContextActionsCell contextCell = null;
+ UITableViewCell reusableCell = null;
+ if (cell.HasContextActions || recycleCells)
+ {
+ contextCell = (ContextActionsCell)tableView.DequeueReusableCell(ContextActionsCell.Key + templateId);
+ if (contextCell == null)
+ {
+ contextCell = new ContextActionsCell(templateId);
+ reusableCell = tableView.DequeueReusableCell(id);
+ }
+ else
+ {
+ contextCell.Close();
+ reusableCell = contextCell.ContentCell;
+
+ if (reusableCell.ReuseIdentifier.ToString() != id)
+ reusableCell = null;
+ }
+ }
+ else
+ reusableCell = tableView.DequeueReusableCell(id);
+
+ var nativeCell = renderer.GetCell(cell, reusableCell, tableView);
+
+ var cellWithContent = nativeCell;
+
+ // Sometimes iOS for returns a dequeued cell whose Layer is hidden.
+ // This prevents it from showing up, so lets turn it back on!
+ if (cellWithContent.Layer.Hidden)
+ cellWithContent.Layer.Hidden = false;
+
+ if (contextCell != null)
+ {
+ contextCell.Update(tableView, cell, nativeCell);
+ nativeCell = contextCell;
+ }
+
+ // Because the layer was hidden we need to layout the cell by hand
+ if (cellWithContent != null)
+ cellWithContent.LayoutSubviews();
+
+ return nativeCell;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Cells/EntryCellRenderer.cs b/Xamarin.Forms.Platform.iOS/Cells/EntryCellRenderer.cs
new file mode 100644
index 00000000..1af49b4a
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Cells/EntryCellRenderer.cs
@@ -0,0 +1,186 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class EntryCellRenderer : CellRenderer
+ {
+ static readonly Color DefaultTextColor = Color.Black;
+
+ public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
+ {
+ var entryCell = (EntryCell)item;
+
+ var tvc = reusableCell as EntryCellTableViewCell;
+ if (tvc == null)
+ tvc = new EntryCellTableViewCell(item.GetType().FullName);
+ else
+ {
+ tvc.Cell.PropertyChanged -= OnCellPropertyChanged;
+ tvc.TextFieldTextChanged -= OnTextFieldTextChanged;
+ tvc.KeyboardDoneButtonPressed -= OnKeyBoardDoneButtonPressed;
+ }
+
+ SetRealCell(item, tvc);
+
+ tvc.Cell = item;
+ tvc.Cell.PropertyChanged += OnCellPropertyChanged;
+ tvc.TextFieldTextChanged += OnTextFieldTextChanged;
+ tvc.KeyboardDoneButtonPressed += OnKeyBoardDoneButtonPressed;
+
+ WireUpForceUpdateSizeRequested(item, tvc, tv);
+
+ UpdateBackground(tvc, entryCell);
+ UpdateLabel(tvc, entryCell);
+ UpdateText(tvc, entryCell);
+ UpdateKeyboard(tvc, entryCell);
+ UpdatePlaceholder(tvc, entryCell);
+ UpdateLabelColor(tvc, entryCell);
+ UpdateHorizontalTextAlignment(tvc, entryCell);
+ UpdateIsEnabled(tvc, entryCell);
+
+ return tvc;
+ }
+
+ static void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ var entryCell = (EntryCell)sender;
+ var realCell = (EntryCellTableViewCell)GetRealCell(entryCell);
+
+ if (e.PropertyName == EntryCell.LabelProperty.PropertyName)
+ UpdateLabel(realCell, entryCell);
+ else if (e.PropertyName == EntryCell.TextProperty.PropertyName)
+ UpdateText(realCell, entryCell);
+ else if (e.PropertyName == EntryCell.PlaceholderProperty.PropertyName)
+ UpdatePlaceholder(realCell, entryCell);
+ else if (e.PropertyName == EntryCell.KeyboardProperty.PropertyName)
+ UpdateKeyboard(realCell, entryCell);
+ else if (e.PropertyName == EntryCell.LabelColorProperty.PropertyName)
+ UpdateLabelColor(realCell, entryCell);
+ else if (e.PropertyName == EntryCell.HorizontalTextAlignmentProperty.PropertyName)
+ UpdateHorizontalTextAlignment(realCell, entryCell);
+ else if (e.PropertyName == Cell.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled(realCell, entryCell);
+ }
+
+ static void OnKeyBoardDoneButtonPressed(object sender, EventArgs e)
+ {
+ var cell = (EntryCellTableViewCell)sender;
+ var model = (EntryCell)cell.Cell;
+
+ model.SendCompleted();
+ }
+
+ static void OnTextFieldTextChanged(object sender, EventArgs eventArgs)
+ {
+ var cell = (EntryCellTableViewCell)sender;
+ var model = (EntryCell)cell.Cell;
+
+ model.Text = cell.TextField.Text;
+ }
+
+ static void UpdateHorizontalTextAlignment(EntryCellTableViewCell cell, EntryCell entryCell)
+ {
+ cell.TextField.TextAlignment = entryCell.HorizontalTextAlignment.ToNativeTextAlignment();
+ }
+
+ static void UpdateIsEnabled(EntryCellTableViewCell cell, EntryCell entryCell)
+ {
+ cell.UserInteractionEnabled = entryCell.IsEnabled;
+ cell.TextLabel.Enabled = entryCell.IsEnabled;
+ cell.DetailTextLabel.Enabled = entryCell.IsEnabled;
+ cell.TextField.Enabled = entryCell.IsEnabled;
+ }
+
+ static void UpdateKeyboard(EntryCellTableViewCell cell, EntryCell entryCell)
+ {
+ cell.TextField.ApplyKeyboard(entryCell.Keyboard);
+ }
+
+ static void UpdateLabel(EntryCellTableViewCell cell, EntryCell entryCell)
+ {
+ cell.TextLabel.Text = entryCell.Label;
+ }
+
+ static void UpdateLabelColor(EntryCellTableViewCell cell, EntryCell entryCell)
+ {
+ cell.TextLabel.TextColor = entryCell.LabelColor.ToUIColor(DefaultTextColor);
+ }
+
+ static void UpdatePlaceholder(EntryCellTableViewCell cell, EntryCell entryCell)
+ {
+ cell.TextField.Placeholder = entryCell.Placeholder;
+ }
+
+ static void UpdateText(EntryCellTableViewCell cell, EntryCell entryCell)
+ {
+ if (cell.TextField.Text == entryCell.Text)
+ return;
+ // double sets side effect on iOS, YAY
+ cell.TextField.Text = entryCell.Text;
+ }
+
+ class EntryCellTableViewCell : CellTableViewCell
+ {
+ public EntryCellTableViewCell(string cellName) : base(UITableViewCellStyle.Value1, cellName)
+ {
+ TextField = new UITextField(new RectangleF(0, 0, 100, 30)) { BorderStyle = UITextBorderStyle.None };
+
+ TextField.EditingChanged += TextFieldOnEditingChanged;
+ TextField.ShouldReturn = OnShouldReturn;
+
+ ContentView.AddSubview(TextField);
+ }
+
+ public UITextField TextField { get; }
+
+ public event EventHandler KeyboardDoneButtonPressed;
+
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+
+ // simple algorithm to generally line up entries
+ var start = (nfloat)Math.Round(Math.Max(Frame.Width * 0.3, TextLabel.Frame.Right + 10));
+ TextField.Frame = new RectangleF(start, (Frame.Height - 30) / 2, Frame.Width - TextLabel.Frame.Left - start, 30);
+ // Centers TextField Content (iOS6)
+ TextField.VerticalAlignment = UIControlContentVerticalAlignment.Center;
+ }
+
+ public event EventHandler TextFieldTextChanged;
+
+ bool OnShouldReturn(UITextField view)
+ {
+ var handler = KeyboardDoneButtonPressed;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+
+ TextField.ResignFirstResponder();
+ return true;
+ }
+
+ void TextFieldOnEditingChanged(object sender, EventArgs eventArgs)
+ {
+ var handler = TextFieldTextChanged;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Cells/ImageCellRenderer.cs b/Xamarin.Forms.Platform.iOS/Cells/ImageCellRenderer.cs
new file mode 100644
index 00000000..ade59e82
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Cells/ImageCellRenderer.cs
@@ -0,0 +1,70 @@
+using System.ComponentModel;
+using System.Threading.Tasks;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class ImageCellRenderer : TextCellRenderer
+ {
+ public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
+ {
+ var result = (CellTableViewCell)base.GetCell(item, reusableCell, tv);
+
+ var imageCell = (ImageCell)item;
+
+ WireUpForceUpdateSizeRequested(item, result, tv);
+
+ SetImage(imageCell, result);
+
+ return result;
+ }
+
+ protected override void HandlePropertyChanged(object sender, PropertyChangedEventArgs args)
+ {
+ var tvc = (CellTableViewCell)sender;
+ var imageCell = (ImageCell)tvc.Cell;
+
+ base.HandlePropertyChanged(sender, args);
+
+ if (args.PropertyName == ImageCell.ImageSourceProperty.PropertyName)
+ SetImage(imageCell, tvc);
+ }
+
+ async void SetImage(ImageCell cell, CellTableViewCell target)
+ {
+ var source = cell.ImageSource;
+
+ target.ImageView.Image = null;
+
+ IImageSourceHandler handler;
+
+ if (source != null && (handler = Registrar.Registered.GetHandler<IImageSourceHandler>(source.GetType())) != null)
+ {
+ UIImage uiimage;
+ try
+ {
+ uiimage = await handler.LoadImageAsync(source).ConfigureAwait(false);
+ }
+ catch (TaskCanceledException)
+ {
+ uiimage = null;
+ }
+
+ NSRunLoop.Main.BeginInvokeOnMainThread(() =>
+ {
+ target.ImageView.Image = uiimage;
+ target.SetNeedsLayout();
+ });
+ }
+ else
+ target.ImageView.Image = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Cells/SwitchCellRenderer.cs b/Xamarin.Forms.Platform.iOS/Cells/SwitchCellRenderer.cs
new file mode 100644
index 00000000..ed7ddc10
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Cells/SwitchCellRenderer.cs
@@ -0,0 +1,94 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class SwitchCellRenderer : CellRenderer
+ {
+ const string CellName = "Xamarin.SwitchCell";
+
+ public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
+ {
+ var tvc = reusableCell as CellTableViewCell;
+ UISwitch uiSwitch = null;
+ if (tvc == null)
+ tvc = new CellTableViewCell(UITableViewCellStyle.Value1, CellName);
+ else
+ {
+ uiSwitch = tvc.AccessoryView as UISwitch;
+ tvc.Cell.PropertyChanged -= OnCellPropertyChanged;
+ }
+
+ SetRealCell(item, tvc);
+
+ if (uiSwitch == null)
+ {
+ uiSwitch = new UISwitch(new RectangleF());
+ uiSwitch.ValueChanged += OnSwitchValueChanged;
+ tvc.AccessoryView = uiSwitch;
+ }
+
+ var boolCell = (SwitchCell)item;
+
+ tvc.Cell = item;
+ tvc.Cell.PropertyChanged += OnCellPropertyChanged;
+ tvc.AccessoryView = uiSwitch;
+ tvc.TextLabel.Text = boolCell.Text;
+
+ uiSwitch.On = boolCell.On;
+
+ WireUpForceUpdateSizeRequested(item, tvc, tv);
+
+ UpdateBackground(tvc, item);
+ UpdateIsEnabled(tvc, boolCell);
+
+ return tvc;
+ }
+
+ void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ var boolCell = (SwitchCell)sender;
+ var realCell = (CellTableViewCell)GetRealCell(boolCell);
+
+ if (e.PropertyName == SwitchCell.OnProperty.PropertyName)
+ ((UISwitch)realCell.AccessoryView).SetState(boolCell.On, true);
+ else if (e.PropertyName == SwitchCell.TextProperty.PropertyName)
+ realCell.TextLabel.Text = boolCell.Text;
+ else if (e.PropertyName == Cell.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled(realCell, boolCell);
+ }
+
+ void OnSwitchValueChanged(object sender, EventArgs eventArgs)
+ {
+ var view = (UIView)sender;
+ var sw = (UISwitch)view;
+
+ CellTableViewCell realCell = null;
+ while (view.Superview != null && realCell == null)
+ {
+ view = view.Superview;
+ realCell = view as CellTableViewCell;
+ }
+
+ if (realCell != null)
+ ((SwitchCell)realCell.Cell).On = sw.On;
+ }
+
+ void UpdateIsEnabled(CellTableViewCell cell, SwitchCell switchCell)
+ {
+ cell.UserInteractionEnabled = switchCell.IsEnabled;
+ cell.TextLabel.Enabled = switchCell.IsEnabled;
+ cell.DetailTextLabel.Enabled = switchCell.IsEnabled;
+ var uiSwitch = cell.AccessoryView as UISwitch;
+ if (uiSwitch != null)
+ uiSwitch.Enabled = switchCell.IsEnabled;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Cells/TextCellRenderer.cs b/Xamarin.Forms.Platform.iOS/Cells/TextCellRenderer.cs
new file mode 100644
index 00000000..41c43341
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Cells/TextCellRenderer.cs
@@ -0,0 +1,73 @@
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class TextCellRenderer : CellRenderer
+ {
+ static readonly Color DefaultDetailColor = new Color(.32, .4, .57);
+ static readonly Color DefaultTextColor = Color.Black;
+
+ public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
+ {
+ var textCell = (TextCell)item;
+
+ var tvc = reusableCell as CellTableViewCell;
+ if (tvc == null)
+ tvc = new CellTableViewCell(UITableViewCellStyle.Subtitle, item.GetType().FullName);
+ else
+ tvc.Cell.PropertyChanged -= tvc.HandlePropertyChanged;
+
+ tvc.Cell = textCell;
+ textCell.PropertyChanged += tvc.HandlePropertyChanged;
+ tvc.PropertyChanged = HandlePropertyChanged;
+
+ tvc.TextLabel.Text = textCell.Text;
+ tvc.DetailTextLabel.Text = textCell.Detail;
+ tvc.TextLabel.TextColor = textCell.TextColor.ToUIColor(DefaultTextColor);
+ tvc.DetailTextLabel.TextColor = textCell.DetailColor.ToUIColor(DefaultDetailColor);
+
+ WireUpForceUpdateSizeRequested(item, tvc, tv);
+
+ UpdateIsEnabled(tvc, textCell);
+
+ UpdateBackground(tvc, item);
+
+ return tvc;
+ }
+
+ protected virtual void HandlePropertyChanged(object sender, PropertyChangedEventArgs args)
+ {
+ var tvc = (CellTableViewCell)sender;
+ var textCell = (TextCell)tvc.Cell;
+ if (args.PropertyName == TextCell.TextProperty.PropertyName)
+ {
+ tvc.TextLabel.Text = ((TextCell)tvc.Cell).Text;
+ tvc.TextLabel.SizeToFit();
+ }
+ else if (args.PropertyName == TextCell.DetailProperty.PropertyName)
+ {
+ tvc.DetailTextLabel.Text = ((TextCell)tvc.Cell).Detail;
+ tvc.DetailTextLabel.SizeToFit();
+ }
+ else if (args.PropertyName == TextCell.TextColorProperty.PropertyName)
+ tvc.TextLabel.TextColor = textCell.TextColor.ToUIColor(DefaultTextColor);
+ else if (args.PropertyName == TextCell.DetailColorProperty.PropertyName)
+ tvc.DetailTextLabel.TextColor = textCell.DetailColor.ToUIColor(DefaultTextColor);
+ else if (args.PropertyName == Cell.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled(tvc, textCell);
+ }
+
+ static void UpdateIsEnabled(CellTableViewCell cell, TextCell entryCell)
+ {
+ cell.UserInteractionEnabled = entryCell.IsEnabled;
+ cell.TextLabel.Enabled = entryCell.IsEnabled;
+ cell.DetailTextLabel.Enabled = entryCell.IsEnabled;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Cells/ViewCellRenderer.cs b/Xamarin.Forms.Platform.iOS/Cells/ViewCellRenderer.cs
new file mode 100644
index 00000000..b1416295
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Cells/ViewCellRenderer.cs
@@ -0,0 +1,176 @@
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+using System.Drawing;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class ViewCellRenderer : CellRenderer
+ {
+ public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
+ {
+ var viewCell = (ViewCell)item;
+
+ var cell = reusableCell as ViewTableCell;
+ if (cell == null)
+ cell = new ViewTableCell(item.GetType().FullName);
+ else
+ cell.ViewCell.PropertyChanged -= ViewCellPropertyChanged;
+
+ viewCell.PropertyChanged += ViewCellPropertyChanged;
+ cell.ViewCell = viewCell;
+
+ WireUpForceUpdateSizeRequested(item, cell, tv);
+
+ UpdateBackground(cell, item);
+ UpdateIsEnabled(cell, viewCell);
+ return cell;
+ }
+
+ static void UpdateIsEnabled(ViewTableCell cell, ViewCell viewCell)
+ {
+ cell.UserInteractionEnabled = viewCell.IsEnabled;
+ cell.TextLabel.Enabled = viewCell.IsEnabled;
+ }
+
+ void ViewCellPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ var viewCell = (ViewCell)sender;
+ var realCell = (ViewTableCell)GetRealCell(viewCell);
+
+ if (e.PropertyName == Cell.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled(realCell, viewCell);
+ }
+
+ internal class ViewTableCell : UITableViewCell, INativeElementView
+ {
+ WeakReference<IVisualElementRenderer> _rendererRef;
+
+ ViewCell _viewCell;
+
+ public ViewTableCell(string key) : base(UITableViewCellStyle.Default, key)
+ {
+ }
+
+ public ViewCell ViewCell
+ {
+ get { return _viewCell; }
+ set
+ {
+ if (_viewCell == value)
+ return;
+ UpdateCell(value);
+ }
+ }
+
+ Element INativeElementView.Element
+ {
+ get { return ViewCell; }
+ }
+
+ public override void LayoutSubviews()
+ {
+ //This sets the content views frame.
+ base.LayoutSubviews();
+
+ var contentFrame = ContentView.Frame;
+
+ Layout.LayoutChildIntoBoundingRegion(ViewCell.View, contentFrame.ToRectangle());
+
+ if (_rendererRef == null)
+ return;
+
+ IVisualElementRenderer renderer;
+ if (_rendererRef.TryGetTarget(out renderer))
+ renderer.NativeView.Frame = contentFrame;
+ }
+
+ public override SizeF SizeThatFits(SizeF size)
+ {
+ IVisualElementRenderer renderer;
+ if (!_rendererRef.TryGetTarget(out renderer))
+ return base.SizeThatFits(size);
+
+ double width = size.Width;
+ var height = size.Height > 0 ? size.Height : double.PositiveInfinity;
+ var result = renderer.Element.Measure(width, height);
+
+ // make sure to add in the separator
+ return new SizeF(size.Width, (float)result.Request.Height + 1f / UIScreen.MainScreen.Scale);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ IVisualElementRenderer renderer;
+ if (_rendererRef != null && _rendererRef.TryGetTarget(out renderer) && renderer.Element != null)
+ {
+ var platform = renderer.Element.Platform as Platform;
+ if (platform != null)
+ platform.DisposeModelAndChildrenRenderers(renderer.Element);
+
+ _rendererRef = null;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ IVisualElementRenderer GetNewRenderer()
+ {
+ var newRenderer = Platform.CreateRenderer(_viewCell.View);
+ _rendererRef = new WeakReference<IVisualElementRenderer>(newRenderer);
+ ContentView.AddSubview(newRenderer.NativeView);
+ return newRenderer;
+ }
+
+ void UpdateCell(ViewCell cell)
+ {
+ if (_viewCell != null)
+ Device.BeginInvokeOnMainThread(_viewCell.SendDisappearing);
+
+ _viewCell = cell;
+ Device.BeginInvokeOnMainThread(_viewCell.SendAppearing);
+
+ IVisualElementRenderer renderer;
+ if (_rendererRef == null || !_rendererRef.TryGetTarget(out renderer))
+ renderer = GetNewRenderer();
+ else
+ {
+ if (renderer.Element != null && renderer == Platform.GetRenderer(renderer.Element))
+ renderer.Element.ClearValue(Platform.RendererProperty);
+
+ var type = Registrar.Registered.GetHandlerType(_viewCell.View.GetType());
+ if (renderer.GetType() == type || (renderer is Platform.DefaultRenderer && type == null))
+ renderer.SetElement(_viewCell.View);
+ else
+ {
+ //when cells are getting reused the element could be already set to another cell
+ //so we should dispose based on the renderer and not the renderer.Element
+ var platform = renderer.Element.Platform as Platform;
+ platform.DisposeRendererAndChildren(renderer);
+ renderer = GetNewRenderer();
+ }
+ }
+
+ Platform.SetRenderer(_viewCell.View, renderer);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/ContextActionCell.cs b/Xamarin.Forms.Platform.iOS/ContextActionCell.cs
new file mode 100644
index 00000000..a2409c62
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/ContextActionCell.cs
@@ -0,0 +1,715 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Collections.Generic;
+using System.Drawing;
+using Xamarin.Forms.Platform.iOS.Resources;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ internal class ContextActionsCell : UITableViewCell, INativeElementView
+ {
+ public const string Key = "ContextActionsCell";
+
+ static readonly UIImage DestructiveBackground;
+ static readonly UIImage NormalBackground;
+ readonly List<UIButton> _buttons = new List<UIButton>();
+ readonly List<MenuItem> _menuItems = new List<MenuItem>();
+
+ Cell _cell;
+ UIButton _moreButton;
+ UIScrollView _scroller;
+ UITableView _tableView;
+
+ static ContextActionsCell()
+ {
+ var rect = new RectangleF(0, 0, 1, 1);
+ var size = rect.Size;
+
+ UIGraphics.BeginImageContext(size);
+ var context = UIGraphics.GetCurrentContext();
+ context.SetFillColor(1, 0, 0, 1);
+ context.FillRect(rect);
+ DestructiveBackground = UIGraphics.GetImageFromCurrentImageContext();
+
+ context.SetFillColor(UIColor.LightGray.ToColor().ToCGColor());
+ context.FillRect(rect);
+
+ NormalBackground = UIGraphics.GetImageFromCurrentImageContext();
+
+ context.Dispose();
+ }
+
+ public ContextActionsCell() : base(UITableViewCellStyle.Default, Key)
+ {
+ }
+
+ public ContextActionsCell(string templateId) : base(UITableViewCellStyle.Default, Key + templateId)
+ {
+ }
+
+ public UITableViewCell ContentCell { get; private set; }
+
+ public bool IsOpen
+ {
+ get { return ScrollDelegate.IsOpen; }
+ }
+
+ ContextScrollViewDelegate ScrollDelegate
+ {
+ get { return (ContextScrollViewDelegate)_scroller.Delegate; }
+ }
+
+ Element INativeElementView.Element
+ {
+ get
+ {
+ var boxedCell = ContentCell as INativeElementView;
+ if (boxedCell == null)
+ {
+ throw new InvalidOperationException($"Implement {nameof(INativeElementView)} on cell renderer: {ContentCell.GetType().AssemblyQualifiedName}");
+ }
+
+ return boxedCell.Element;
+ }
+ }
+
+ public void Close()
+ {
+ _scroller.ContentOffset = new PointF(0, 0);
+ }
+
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+
+ if (_scroller == null || (_scroller != null && _scroller.Frame == Bounds))
+ return;
+
+ Update(_tableView, _cell, ContentCell);
+
+ _scroller.Frame = Bounds;
+ ContentCell.Frame = Bounds;
+
+ if (ContentCell is ViewCellRenderer.ViewTableCell && ContentCell.Subviews.Length > 0 && Math.Abs(ContentCell.Subviews[0].Frame.Height - Bounds.Height) > 1)
+ {
+ // Something goes weird inside iOS where LayoutSubviews wont get called when updating the bounds if the user
+ // forces us to flip flop between a ContextActionCell and a normal cell in the middle of actually displaying the cell
+ // so here we are going to hack it a forced update. Leave room for 1px of play because the border is 1 or .5px and must
+ // be accounted for.
+ //
+ // Fixes https://bugzilla.xamarin.com/show_bug.cgi?id=39450
+ ContentCell.LayoutSubviews();
+ }
+ }
+
+ public void PrepareForDeselect()
+ {
+ ScrollDelegate.PrepareForDeselect(_scroller);
+ }
+
+ public override SizeF SizeThatFits(SizeF size)
+ {
+ return ContentCell.SizeThatFits(size);
+ }
+
+ public void Update(UITableView tableView, Cell cell, UITableViewCell nativeCell)
+ {
+ var parentListView = cell.RealParent as ListView;
+ var recycling = parentListView != null && parentListView.CachingStrategy == ListViewCachingStrategy.RecycleElement;
+ if (_cell != cell && recycling)
+ {
+ if (_cell != null)
+ ((INotifyCollectionChanged)_cell.ContextActions).CollectionChanged -= OnContextItemsChanged;
+
+ ((INotifyCollectionChanged)cell.ContextActions).CollectionChanged += OnContextItemsChanged;
+ }
+
+ var height = Frame.Height;
+ var width = tableView.Frame.Width;
+
+ nativeCell.Frame = new RectangleF(0, 0, width, height);
+ nativeCell.SetNeedsLayout();
+
+ var handler = new PropertyChangedEventHandler(OnMenuItemPropertyChanged);
+
+ _tableView = tableView;
+ SetupSelection(tableView);
+
+ if (_cell != null)
+ {
+ if (!recycling)
+ _cell.PropertyChanged -= OnCellPropertyChanged;
+ if (_menuItems.Count > 0)
+ {
+ if (!recycling)
+ ((INotifyCollectionChanged)_cell.ContextActions).CollectionChanged -= OnContextItemsChanged;
+
+ foreach (var item in _menuItems)
+ item.PropertyChanged -= handler;
+ }
+
+ _menuItems.Clear();
+ }
+
+ _menuItems.AddRange(cell.ContextActions);
+
+ _cell = cell;
+ if (!recycling)
+ {
+ cell.PropertyChanged += OnCellPropertyChanged;
+ ((INotifyCollectionChanged)_cell.ContextActions).CollectionChanged += OnContextItemsChanged;
+ }
+
+ var isOpen = false;
+
+ if (_scroller == null)
+ {
+ _scroller = new UIScrollView(new RectangleF(0, 0, width, height));
+ _scroller.ScrollsToTop = false;
+ _scroller.ShowsHorizontalScrollIndicator = false;
+
+ if (Forms.IsiOS8OrNewer)
+ _scroller.PreservesSuperviewLayoutMargins = true;
+
+ ContentView.AddSubview(_scroller);
+ }
+ else
+ {
+ _scroller.Frame = new RectangleF(0, 0, width, height);
+ isOpen = ScrollDelegate.IsOpen;
+
+ for (var i = 0; i < _buttons.Count; i++)
+ {
+ var b = _buttons[i];
+ b.RemoveFromSuperview();
+ b.Dispose();
+ }
+
+ _buttons.Clear();
+
+ ScrollDelegate.Unhook(_scroller);
+ ScrollDelegate.Dispose();
+ }
+
+ if (ContentCell != nativeCell)
+ {
+ if (ContentCell != null)
+ {
+ ContentCell.RemoveFromSuperview();
+ ContentCell = null;
+ }
+
+ ContentCell = nativeCell;
+
+ //Hack: if we have a ImageCell the insets are slightly different,
+ //the inset numbers user below were taken using the Reveal app from the default cells
+ if ((ContentCell as CellTableViewCell)?.Cell is ImageCell)
+ {
+ nfloat imageCellInsetLeft = 57;
+ nfloat imageCellInsetRight = 0;
+ if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad)
+ {
+ imageCellInsetLeft = 89;
+ imageCellInsetRight = imageCellInsetLeft / 2;
+ }
+ SeparatorInset = new UIEdgeInsets(0, imageCellInsetLeft, 0, imageCellInsetRight);
+ }
+
+ _scroller.AddSubview(nativeCell);
+ }
+
+ SetupButtons(width, height);
+
+ UIView container = null;
+
+ var totalWidth = width;
+ for (var i = _buttons.Count - 1; i >= 0; i--)
+ {
+ var b = _buttons[i];
+ totalWidth += b.Frame.Width;
+
+ if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
+ _scroller.AddSubview(b);
+ else
+ {
+ if (container == null)
+ {
+ container = new iOS7ButtonContainer(b.Frame.Width);
+ _scroller.InsertSubview(container, 0);
+ }
+
+ container.AddSubview(b);
+ }
+ }
+
+ _scroller.Delegate = new ContextScrollViewDelegate(container, _buttons, isOpen);
+ _scroller.ContentSize = new SizeF(totalWidth, height);
+
+ if (isOpen)
+ _scroller.SetContentOffset(new PointF(ScrollDelegate.ButtonsWidth, 0), false);
+ else
+ _scroller.SetContentOffset(new PointF(0, 0), false);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (_scroller != null)
+ {
+ _scroller.Dispose();
+ _scroller = null;
+ }
+
+ _tableView = null;
+
+ if (_moreButton != null)
+ {
+ _moreButton.Dispose();
+ _moreButton = null;
+ }
+
+ for (var i = 0; i < _buttons.Count; i++)
+ _buttons[i].Dispose();
+
+ _buttons.Clear();
+ _menuItems.Clear();
+
+ if (_cell != null)
+ {
+ if (_cell.HasContextActions)
+ ((INotifyCollectionChanged)_cell.ContextActions).CollectionChanged -= OnContextItemsChanged;
+ _cell = null;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ void ActivateMore()
+ {
+ var displayed = new HashSet<nint>();
+ for (var i = 0; i < _buttons.Count; i++)
+ {
+ var tag = _buttons[i].Tag;
+ if (tag >= 0)
+ displayed.Add(tag);
+ }
+
+ var frame = _moreButton.Frame;
+ if (!Forms.IsiOS8OrNewer)
+ {
+ var container = _moreButton.Superview;
+ frame = new RectangleF(container.Frame.X, 0, frame.Width, frame.Height);
+ }
+
+ var x = frame.X - _scroller.ContentOffset.X;
+
+ var path = _tableView.IndexPathForCell(this);
+ var rowPosition = _tableView.RectForRowAtIndexPath(path);
+ var sourceRect = new RectangleF(x, rowPosition.Y, rowPosition.Width, rowPosition.Height);
+
+ if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
+ {
+ var actionSheet = new MoreActionSheetController();
+
+ for (var i = 0; i < _cell.ContextActions.Count; i++)
+ {
+ if (displayed.Contains(i))
+ continue;
+
+ var item = _cell.ContextActions[i];
+ var weakItem = new WeakReference<MenuItem>(item);
+ var action = UIAlertAction.Create(item.Text, UIAlertActionStyle.Default, a =>
+ {
+ _scroller.SetContentOffset(new PointF(0, 0), true);
+ MenuItem mi;
+ if (weakItem.TryGetTarget(out mi))
+ mi.Activate();
+ });
+ actionSheet.AddAction(action);
+ }
+
+ var controller = GetController();
+ if (controller == null)
+ throw new InvalidOperationException("No UIViewController found to present.");
+
+ if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone)
+ {
+ var cancel = UIAlertAction.Create(StringResources.Cancel, UIAlertActionStyle.Cancel, null);
+ actionSheet.AddAction(cancel);
+ }
+ else
+ {
+ actionSheet.PopoverPresentationController.SourceView = _tableView;
+ actionSheet.PopoverPresentationController.SourceRect = sourceRect;
+ }
+
+ controller.PresentViewController(actionSheet, true, null);
+ }
+ else
+ {
+ var d = new MoreActionSheetDelegate { Scroller = _scroller, Items = new List<MenuItem>() };
+
+ var actionSheet = new UIActionSheet(null, d);
+
+ for (var i = 0; i < _cell.ContextActions.Count; i++)
+ {
+ if (displayed.Contains(i))
+ continue;
+
+ var item = _cell.ContextActions[i];
+ d.Items.Add(item);
+ actionSheet.AddButton(item.Text);
+ }
+
+ if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone)
+ {
+ var index = actionSheet.AddButton(StringResources.Cancel);
+ actionSheet.CancelButtonIndex = index;
+ }
+
+ actionSheet.ShowFrom(sourceRect, _tableView, true);
+ }
+ }
+
+ void CullButtons(nfloat acceptableTotalWidth, ref bool needMoreButton, ref nfloat largestButtonWidth)
+ {
+ while (largestButtonWidth * (_buttons.Count + (needMoreButton ? 1 : 0)) > acceptableTotalWidth && _buttons.Count > 1)
+ {
+ needMoreButton = true;
+
+ var button = _buttons[_buttons.Count - 1];
+ _buttons.RemoveAt(_buttons.Count - 1);
+
+ if (largestButtonWidth == button.Frame.Width)
+ largestButtonWidth = GetLargestWidth();
+ }
+
+ if (needMoreButton && _cell.ContextActions.Count - _buttons.Count == 1)
+ _buttons.RemoveAt(_buttons.Count - 1);
+ }
+
+ UIButton GetButton(MenuItem item)
+ {
+ var button = new UIButton(new RectangleF(0, 0, 1, 1));
+
+ if (!item.IsDestructive)
+ button.SetBackgroundImage(NormalBackground, UIControlState.Normal);
+ else
+ button.SetBackgroundImage(DestructiveBackground, UIControlState.Normal);
+
+ button.SetTitle(item.Text, UIControlState.Normal);
+ button.TitleEdgeInsets = new UIEdgeInsets(0, 15, 0, 15);
+
+ button.Enabled = item.IsEnabled;
+
+ return button;
+ }
+
+ UIViewController GetController()
+ {
+ Element e = _cell;
+ while (e.RealParent != null)
+ {
+ var renderer = Platform.GetRenderer((VisualElement)e.RealParent);
+ if (renderer.ViewController != null)
+ return renderer.ViewController;
+
+ e = e.RealParent;
+ }
+
+ return null;
+ }
+
+ nfloat GetLargestWidth()
+ {
+ nfloat largestWidth = 0;
+ for (var i = 0; i < _buttons.Count; i++)
+ {
+ var frame = _buttons[i].Frame;
+ if (frame.Width > largestWidth)
+ largestWidth = frame.Width;
+ }
+
+ return largestWidth;
+ }
+
+ void OnButtonActivated(object sender, EventArgs e)
+ {
+ var button = (UIButton)sender;
+ if (button.Tag == -1)
+ ActivateMore();
+ else
+ {
+ _scroller.SetContentOffset(new PointF(0, 0), true);
+ _cell.ContextActions[(int)button.Tag].Activate();
+ }
+ }
+
+ void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "HasContextActions")
+ {
+ var parentListView = _cell.RealParent as ListView;
+ var recycling = parentListView != null && parentListView.CachingStrategy == ListViewCachingStrategy.RecycleElement;
+ if (!recycling)
+ ReloadRow();
+ }
+ }
+
+ void OnContextItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ var parentListView = _cell.RealParent as ListView;
+ var recycling = parentListView != null && parentListView.CachingStrategy == ListViewCachingStrategy.RecycleElement;
+ if (recycling)
+ Update(_tableView, _cell, ContentCell);
+ else
+ ReloadRow();
+ // TODO: Perhaps make this nicer if it's open while adding
+ }
+
+ void OnMenuItemPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ var parentListView = _cell.RealParent as ListView;
+ var recycling = parentListView != null && parentListView.CachingStrategy == ListViewCachingStrategy.RecycleElement;
+ if (recycling)
+ Update(_tableView, _cell, ContentCell);
+ else
+ ReloadRow();
+ }
+
+ void ReloadRow()
+ {
+ if (_scroller.ContentOffset.X > 0)
+ {
+ ((ContextScrollViewDelegate)_scroller.Delegate).ClosedCallback = () =>
+ {
+ ReloadRowCore();
+ ((ContextScrollViewDelegate)_scroller.Delegate).ClosedCallback = null;
+ };
+
+ _scroller.SetContentOffset(new PointF(0, 0), true);
+ }
+ else
+ ReloadRowCore();
+ }
+
+ void ReloadRowCore()
+ {
+ if (_cell.RealParent == null)
+ return;
+
+ var path = _cell.GetIndexPath();
+
+ var selected = path.Equals(_tableView.IndexPathForSelectedRow);
+
+ _tableView.ReloadRows(new[] { path }, UITableViewRowAnimation.None);
+
+ if (selected)
+ {
+ _tableView.SelectRow(path, false, UITableViewScrollPosition.None);
+ _tableView.Source.RowSelected(_tableView, path);
+ }
+ }
+
+ UIView SetupButtons(nfloat width, nfloat height)
+ {
+ MenuItem destructive = null;
+ nfloat largestWidth = 0, acceptableSize = width * 0.80f;
+
+ for (var i = 0; i < _cell.ContextActions.Count; i++)
+ {
+ var item = _cell.ContextActions[i];
+
+ if (_buttons.Count == 3)
+ {
+ if (destructive != null)
+ break;
+ if (!item.IsDestructive)
+ continue;
+
+ _buttons.RemoveAt(_buttons.Count - 1);
+ }
+
+ if (item.IsDestructive)
+ destructive = item;
+
+ var button = GetButton(item);
+ button.Tag = i;
+ var buttonWidth = button.TitleLabel.SizeThatFits(new SizeF(width, height)).Width + 30;
+ if (buttonWidth > largestWidth)
+ largestWidth = buttonWidth;
+
+ if (destructive == item)
+ _buttons.Insert(0, button);
+ else
+ _buttons.Add(button);
+ }
+
+ var needMore = _cell.ContextActions.Count > _buttons.Count;
+
+ if (_cell.ContextActions.Count > 2)
+ CullButtons(acceptableSize, ref needMore, ref largestWidth);
+
+ var resize = false;
+ if (needMore)
+ {
+ if (largestWidth * 2 > acceptableSize)
+ {
+ largestWidth = acceptableSize / 2;
+ resize = true;
+ }
+
+ var button = new UIButton(new RectangleF(0, 0, largestWidth, height));
+ button.SetBackgroundImage(NormalBackground, UIControlState.Normal);
+ button.TitleEdgeInsets = new UIEdgeInsets(0, 15, 0, 15);
+ button.SetTitle(StringResources.More, UIControlState.Normal);
+
+ var moreWidth = button.TitleLabel.SizeThatFits(new SizeF(width, height)).Width + 30;
+ if (moreWidth > largestWidth)
+ {
+ largestWidth = moreWidth;
+ CullButtons(acceptableSize, ref needMore, ref largestWidth);
+
+ if (largestWidth * 2 > acceptableSize)
+ {
+ largestWidth = acceptableSize / 2;
+ resize = true;
+ }
+ }
+
+ button.Tag = -1;
+ button.TouchUpInside += OnButtonActivated;
+ if (resize)
+ button.TitleLabel.AdjustsFontSizeToFitWidth = true;
+
+ _moreButton = button;
+ _buttons.Add(button);
+ }
+
+ var handler = new PropertyChangedEventHandler(OnMenuItemPropertyChanged);
+ var totalWidth = _buttons.Count * largestWidth;
+ for (var n = 0; n < _buttons.Count; n++)
+ {
+ var b = _buttons[n];
+
+ if (b.Tag >= 0)
+ {
+ var item = _cell.ContextActions[(int)b.Tag];
+ item.PropertyChanged += handler;
+ }
+
+ var offset = (n + 1) * largestWidth;
+
+ var x = width - offset;
+ if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
+ x += totalWidth;
+
+ b.Frame = new RectangleF(x, 0, largestWidth, height);
+ if (resize)
+ b.TitleLabel.AdjustsFontSizeToFitWidth = true;
+
+ b.SetNeedsLayout();
+
+ if (b != _moreButton)
+ b.TouchUpInside += OnButtonActivated;
+ }
+
+ return null;
+ }
+
+ void SetupSelection(UITableView table)
+ {
+ for (var i = 0; i < table.GestureRecognizers.Length; i++)
+ {
+ var r = table.GestureRecognizers[i] as SelectGestureRecognizer;
+ if (r != null)
+ return;
+ }
+
+ _tableView.AddGestureRecognizer(new SelectGestureRecognizer());
+ }
+
+ class SelectGestureRecognizer : UITapGestureRecognizer
+ {
+ NSIndexPath _lastPath;
+
+ public SelectGestureRecognizer() : base(Tapped)
+ {
+ ShouldReceiveTouch = (recognizer, touch) =>
+ {
+ var table = (UITableView)View;
+ var pos = touch.LocationInView(table);
+
+ _lastPath = table.IndexPathForRowAtPoint(pos);
+ if (_lastPath == null)
+ return false;
+
+ var cell = table.CellAt(_lastPath) as ContextActionsCell;
+
+ return cell != null;
+ };
+ }
+
+ static void Tapped(UIGestureRecognizer recognizer)
+ {
+ var selector = (SelectGestureRecognizer)recognizer;
+
+ var table = (UITableView)recognizer.View;
+
+ if (!selector._lastPath.Equals(table.IndexPathForSelectedRow))
+ table.SelectRow(selector._lastPath, false, UITableViewScrollPosition.None);
+ table.Source.RowSelected(table, selector._lastPath);
+ }
+ }
+
+ class MoreActionSheetController : UIAlertController
+ {
+ public override UIAlertControllerStyle PreferredStyle
+ {
+ get { return UIAlertControllerStyle.ActionSheet; }
+ }
+
+ public override void WillRotate(UIInterfaceOrientation toInterfaceOrientation, double duration)
+ {
+ DismissViewController(false, null);
+ }
+ }
+
+ class MoreActionSheetDelegate : UIActionSheetDelegate
+ {
+ public List<MenuItem> Items;
+ public UIScrollView Scroller;
+
+ public override void Clicked(UIActionSheet actionSheet, nint buttonIndex)
+ {
+ if (buttonIndex == Items.Count)
+ return; // Cancel button
+
+ Scroller.SetContentOffset(new PointF(0, 0), true);
+
+ // do not activate a -1 index when dismissing by clicking outside the popover
+ if (buttonIndex >= 0)
+ Items[(int)buttonIndex].Activate();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/ContextScrollViewDelegate.cs b/Xamarin.Forms.Platform.iOS/ContextScrollViewDelegate.cs
new file mode 100644
index 00000000..47ce0714
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/ContextScrollViewDelegate.cs
@@ -0,0 +1,298 @@
+using System;
+using System.Drawing;
+using System.Collections.Generic;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+#if __UNIFIED__
+using NSAction = System.Action;
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ internal class iOS7ButtonContainer : UIView
+ {
+ readonly nfloat _buttonWidth;
+
+ public iOS7ButtonContainer(nfloat buttonWidth) : base(new RectangleF(0, 0, 0, 0))
+ {
+ _buttonWidth = buttonWidth;
+ ClipsToBounds = true;
+ }
+
+ public override void LayoutSubviews()
+ {
+ var width = Frame.Width;
+ nfloat takenSpace = 0;
+
+ for (var i = 0; i < Subviews.Length; i++)
+ {
+ var view = Subviews[i];
+
+ var pos = Subviews.Length - i;
+ var x = width - _buttonWidth * pos;
+ view.Frame = new RectangleF(x, 0, view.Frame.Width, view.Frame.Height);
+
+ takenSpace += view.Frame.Width;
+ }
+ }
+ }
+
+ internal class ContextScrollViewDelegate : UIScrollViewDelegate
+ {
+ readonly nfloat _finalButtonSize;
+ UIView _backgroundView;
+ List<UIButton> _buttons;
+ UITapGestureRecognizer _closer;
+ UIView _container;
+ GlobalCloseContextGestureRecognizer _globalCloser;
+
+ bool _isDisposed;
+
+ UITableView _table;
+
+ public ContextScrollViewDelegate(UIView container, List<UIButton> buttons, bool isOpen)
+ {
+ IsOpen = isOpen;
+ _container = container;
+ _buttons = buttons;
+
+ for (var i = 0; i < buttons.Count; i++)
+ {
+ var b = buttons[i];
+ b.Hidden = !isOpen;
+
+ ButtonsWidth += b.Frame.Width;
+ _finalButtonSize = b.Frame.Width;
+ }
+ }
+
+ public nfloat ButtonsWidth { get; }
+
+ public Action ClosedCallback { get; set; }
+
+ public bool IsOpen { get; private set; }
+
+ public override void DraggingStarted(UIScrollView scrollView)
+ {
+ if (!IsOpen)
+ SetButtonsShowing(true);
+
+ var cell = GetContextCell(scrollView);
+ if (!cell.Selected)
+ return;
+
+ if (!IsOpen)
+ RemoveHighlight(scrollView);
+ }
+
+ public void PrepareForDeselect(UIScrollView scrollView)
+ {
+ RestoreHighlight(scrollView);
+ }
+
+ public override void Scrolled(UIScrollView scrollView)
+ {
+ var width = _finalButtonSize;
+ var count = _buttons.Count;
+
+ if (!UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
+ _container.Frame = new RectangleF(scrollView.Frame.Width, 0, scrollView.ContentOffset.X, scrollView.Frame.Height);
+ else
+ {
+ var ioffset = scrollView.ContentOffset.X / (float)count;
+
+ if (ioffset > width)
+ width = ioffset + 1;
+
+ for (var i = count - 1; i >= 0; i--)
+ {
+ var b = _buttons[i];
+ var rect = b.Frame;
+ b.Frame = new RectangleF(scrollView.Frame.Width + (count - (i + 1)) * ioffset, 0, width, rect.Height);
+ }
+ }
+
+ if (scrollView.ContentOffset.X == 0)
+ {
+ IsOpen = false;
+ SetButtonsShowing(false);
+ RestoreHighlight(scrollView);
+
+ ClearCloserRecognizer(scrollView);
+
+ if (ClosedCallback != null)
+ ClosedCallback();
+ }
+ }
+
+ public void Unhook(UIScrollView scrollView)
+ {
+ RestoreHighlight(scrollView);
+ ClearCloserRecognizer(scrollView);
+ }
+
+ public override void WillEndDragging(UIScrollView scrollView, PointF velocity, ref PointF targetContentOffset)
+ {
+ var width = ButtonsWidth;
+ var x = targetContentOffset.X;
+ var parentThreshold = scrollView.Frame.Width * .4f;
+ var contentThreshold = width * .8f;
+
+ if (x >= parentThreshold || x >= contentThreshold)
+ {
+ IsOpen = true;
+ targetContentOffset = new PointF(width, 0);
+ RemoveHighlight(scrollView);
+
+ if (_globalCloser == null)
+ {
+ UIView view = scrollView;
+ while (view.Superview != null)
+ {
+ view = view.Superview;
+
+ NSAction close = () =>
+ {
+ if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
+ RestoreHighlight(scrollView);
+
+ IsOpen = false;
+ scrollView.SetContentOffset(new PointF(0, 0), true);
+
+ ClearCloserRecognizer(scrollView);
+ };
+
+ var table = view as UITableView;
+ if (table != null)
+ {
+ _table = table;
+ _globalCloser = new GlobalCloseContextGestureRecognizer(scrollView, _buttons, close);
+ _globalCloser.ShouldRecognizeSimultaneously = (recognizer, r) => r == _table.PanGestureRecognizer;
+ table.AddGestureRecognizer(_globalCloser);
+
+ _closer = new UITapGestureRecognizer(close);
+ var cell = GetContextCell(scrollView);
+ cell.ContentCell.AddGestureRecognizer(_closer);
+ }
+ }
+ }
+ }
+ else
+ {
+ ClearCloserRecognizer(scrollView);
+
+ IsOpen = false;
+ targetContentOffset = new PointF(0, 0);
+
+ if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
+ RestoreHighlight(scrollView);
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (_isDisposed)
+ return;
+
+ _isDisposed = true;
+
+ if (disposing)
+ {
+ ClosedCallback = null;
+
+ _table = null;
+ _backgroundView = null;
+ _container = null;
+
+ _buttons = null;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ void ClearCloserRecognizer(UIScrollView scrollView)
+ {
+ if (_globalCloser == null)
+ return;
+
+ var cell = GetContextCell(scrollView);
+ cell.ContentCell.RemoveGestureRecognizer(_closer);
+ _closer.Dispose();
+ _closer = null;
+
+ _table.RemoveGestureRecognizer(_globalCloser);
+ _table = null;
+ _globalCloser.Dispose();
+ _globalCloser = null;
+ }
+
+ ContextActionsCell GetContextCell(UIScrollView scrollView)
+ {
+ var view = scrollView.Superview.Superview;
+ var cell = view as ContextActionsCell;
+ while (view.Superview != null)
+ {
+ cell = view as ContextActionsCell;
+ if (cell != null)
+ break;
+
+ view = view.Superview;
+ }
+
+ return cell;
+ }
+
+ void RemoveHighlight(UIScrollView scrollView)
+ {
+ var subviews = scrollView.Superview.Superview.Subviews;
+
+ var count = 0;
+ for (var i = 0; i < subviews.Length; i++)
+ {
+ var s = subviews[i];
+ if (s.Frame.Height > 1)
+ count++;
+ }
+
+ if (count <= 1)
+ return;
+
+ _backgroundView = subviews[0];
+ _backgroundView.RemoveFromSuperview();
+
+ var cell = GetContextCell(scrollView);
+ cell.SelectionStyle = UITableViewCellSelectionStyle.None;
+ }
+
+ void RestoreHighlight(UIScrollView scrollView)
+ {
+ if (_backgroundView == null)
+ return;
+
+ var cell = GetContextCell(scrollView);
+ cell.SelectionStyle = UITableViewCellSelectionStyle.Default;
+ cell.SetSelected(true, false);
+
+ scrollView.Superview.Superview.InsertSubview(_backgroundView, 0);
+ _backgroundView = null;
+ }
+
+ void SetButtonsShowing(bool show)
+ {
+ for (var i = 0; i < _buttons.Count; i++)
+ _buttons[i].Hidden = !show;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Deserializer.cs b/Xamarin.Forms.Platform.iOS/Deserializer.cs
new file mode 100644
index 00000000..bdab44df
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Deserializer.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO.IsolatedStorage;
+using System.Runtime.Serialization;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ internal class Deserializer : IDeserializer
+ {
+ const string PropertyStoreFile = "PropertyStore.forms";
+
+ public Task<IDictionary<string, object>> DeserializePropertiesAsync()
+ {
+ // Deserialize property dictionary to local storage
+ // Make sure to use Internal
+ return Task.Run(() =>
+ {
+ using(var store = IsolatedStorageFile.GetUserStoreForApplication())
+ using(var stream = store.OpenFile(PropertyStoreFile, System.IO.FileMode.OpenOrCreate))
+ using(var reader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max))
+ {
+ if (stream.Length == 0)
+ return null;
+
+ try
+ {
+ var dcs = new DataContractSerializer(typeof(Dictionary<string, object>));
+ return (IDictionary<string, object>)dcs.ReadObject(reader);
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine("Could not deserialize properties: " + e.Message);
+ Log.Warning("Xamarin.Forms PropertyStore", $"Exception while reading Application properties: {e}");
+ }
+ }
+
+ return null;
+ });
+ }
+
+ public Task SerializePropertiesAsync(IDictionary<string, object> properties)
+ {
+ properties = new Dictionary<string, object>(properties);
+ // Serialize property dictionary to local storage
+ // Make sure to use Internal
+ return Task.Run(() =>
+ {
+ var success = false;
+ using(var store = IsolatedStorageFile.GetUserStoreForApplication())
+ using(var stream = store.OpenFile(PropertyStoreFile + ".tmp", System.IO.FileMode.OpenOrCreate))
+ using(var writer = XmlDictionaryWriter.CreateBinaryWriter(stream))
+ {
+ try
+ {
+ var dcs = new DataContractSerializer(typeof(Dictionary<string, object>));
+ dcs.WriteObject(writer, properties);
+ writer.Flush();
+ success = true;
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine("Could not serialize properties: " + e.Message);
+ Log.Warning("Xamarin.Forms PropertyStore", $"Exception while writing Application properties: {e}");
+ }
+ }
+
+ if (!success)
+ return;
+ using(var store = IsolatedStorageFile.GetUserStoreForApplication())
+ {
+ try
+ {
+ if (store.FileExists(PropertyStoreFile))
+ store.DeleteFile(PropertyStoreFile);
+ store.MoveFile(PropertyStoreFile + ".tmp", PropertyStoreFile);
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine("Could not move new serialized property file over old: " + e.Message);
+ Log.Warning("Xamarin.Forms PropertyStore", $"Exception while writing Application properties: {e}");
+ }
+ }
+ });
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/ElementChangedEventArgs.cs b/Xamarin.Forms.Platform.iOS/ElementChangedEventArgs.cs
new file mode 100644
index 00000000..560cfd1c
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/ElementChangedEventArgs.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class VisualElementChangedEventArgs : ElementChangedEventArgs<VisualElement>
+ {
+ public VisualElementChangedEventArgs(VisualElement oldElement, VisualElement newElement) : base(oldElement, newElement)
+ {
+ }
+ }
+
+ public class ElementChangedEventArgs<TElement> : EventArgs where TElement : Element
+ {
+ public ElementChangedEventArgs(TElement oldElement, TElement newElement)
+ {
+ OldElement = oldElement;
+ NewElement = newElement;
+ }
+
+ public TElement NewElement { get; private set; }
+
+ public TElement OldElement { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/EventTracker.cs b/Xamarin.Forms.Platform.iOS/EventTracker.cs
new file mode 100644
index 00000000..16ccd505
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/EventTracker.cs
@@ -0,0 +1,303 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class EventTracker : IDisposable
+ {
+ readonly NotifyCollectionChangedEventHandler _collectionChangedHandler;
+
+ readonly Dictionary<IGestureRecognizer, UIGestureRecognizer> _gestureRecognizers = new Dictionary<IGestureRecognizer, UIGestureRecognizer>();
+
+ readonly IVisualElementRenderer _renderer;
+ bool _disposed;
+ UIView _handler;
+
+ double _previousScale = 1.0;
+ UITouchEventArgs _shouldReceive;
+
+ public EventTracker(IVisualElementRenderer renderer)
+ {
+ if (renderer == null)
+ throw new ArgumentNullException("renderer");
+
+ _collectionChangedHandler = ModelGestureRecognizersOnCollectionChanged;
+
+ _renderer = renderer;
+ _renderer.ElementChanged += OnElementChanged;
+ }
+
+ ObservableCollection<IGestureRecognizer> ElementGestureRecognizers
+ {
+ get
+ {
+ if (_renderer?.Element is View)
+ return ((View)_renderer.Element).GestureRecognizers as ObservableCollection<IGestureRecognizer>;
+ return null;
+ }
+ }
+
+ public void Dispose()
+ {
+ if (_disposed)
+ return;
+
+ _disposed = true;
+
+ foreach (var kvp in _gestureRecognizers)
+ {
+ _handler.RemoveGestureRecognizer(kvp.Value);
+ kvp.Value.Dispose();
+ }
+
+ _gestureRecognizers.Clear();
+
+ if (ElementGestureRecognizers != null)
+ ElementGestureRecognizers.CollectionChanged -= _collectionChangedHandler;
+
+ _handler = null;
+ }
+
+ public void LoadEvents(UIView handler)
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(null);
+
+ _shouldReceive = (r, t) => t.View is IVisualElementRenderer;
+
+ _handler = handler;
+ OnElementChanged(this, new VisualElementChangedEventArgs(null, _renderer.Element));
+ }
+
+ protected virtual UIGestureRecognizer GetNativeRecognizer(IGestureRecognizer recognizer)
+ {
+ if (recognizer == null)
+ return null;
+
+ var weakRecognizer = new WeakReference(recognizer);
+ var weakEventTracker = new WeakReference(this);
+
+ var tapRecognizer = recognizer as TapGestureRecognizer;
+ if (tapRecognizer != null)
+ {
+ var uiRecognizer = CreateTapRecognizer(1, tapRecognizer.NumberOfTapsRequired, r =>
+ {
+ var tapGestureRecognizer = weakRecognizer.Target as TapGestureRecognizer;
+ var eventTracker = weakEventTracker.Target as EventTracker;
+ var view = eventTracker?._renderer?.Element as View;
+
+ if (tapGestureRecognizer != null && view != null)
+ tapGestureRecognizer.SendTapped(view);
+ });
+ return uiRecognizer;
+ }
+
+ var pinchRecognizer = recognizer as PinchGestureRecognizer;
+ if (pinchRecognizer != null)
+ {
+ double startingScale = 1;
+ var uiRecognizer = CreatePinchRecognizer(r =>
+ {
+ var pinchGestureRecognizer = weakRecognizer.Target as IPinchGestureController;
+ var eventTracker = weakEventTracker.Target as EventTracker;
+ var view = eventTracker?._renderer?.Element as View;
+
+ if (pinchGestureRecognizer != null && eventTracker != null && view != null)
+ {
+ var oldScale = eventTracker._previousScale;
+ var originPoint = r.LocationInView(null);
+ originPoint = UIApplication.SharedApplication.KeyWindow.ConvertPointToView(originPoint, eventTracker._renderer.NativeView);
+ var scaledPoint = new Point(originPoint.X / view.Width, originPoint.Y / view.Height);
+
+ switch (r.State)
+ {
+ case UIGestureRecognizerState.Began:
+ if (r.NumberOfTouches < 2)
+ return;
+ pinchGestureRecognizer.SendPinchStarted(view, scaledPoint);
+ startingScale = view.Scale;
+ break;
+ case UIGestureRecognizerState.Changed:
+ if (r.NumberOfTouches < 2 && pinchGestureRecognizer.IsPinching)
+ {
+ r.State = UIGestureRecognizerState.Ended;
+ pinchGestureRecognizer.SendPinchEnded(view);
+ return;
+ }
+
+ var delta = 1.0;
+ var dif = Math.Abs(r.Scale - oldScale) * startingScale;
+ if (oldScale < r.Scale)
+ delta = 1 + dif;
+ if (oldScale > r.Scale)
+ delta = 1 - dif;
+
+ pinchGestureRecognizer.SendPinch(view, delta, scaledPoint);
+ eventTracker._previousScale = r.Scale;
+ break;
+ case UIGestureRecognizerState.Cancelled:
+ case UIGestureRecognizerState.Failed:
+ if (pinchGestureRecognizer.IsPinching)
+ pinchGestureRecognizer.SendPinchCanceled(view);
+ break;
+ case UIGestureRecognizerState.Ended:
+ if (pinchGestureRecognizer.IsPinching)
+ pinchGestureRecognizer.SendPinchEnded(view);
+ eventTracker._previousScale = 1;
+ break;
+ }
+ }
+ });
+ return uiRecognizer;
+ }
+
+ var panRecognizer = recognizer as PanGestureRecognizer;
+ if (panRecognizer != null)
+ {
+ var uiRecognizer = CreatePanRecognizer(panRecognizer.TouchPoints, r =>
+ {
+ var eventTracker = weakEventTracker.Target as EventTracker;
+ var view = eventTracker?._renderer?.Element as View;
+
+ var panGestureRecognizer = weakRecognizer.Target as IPanGestureController;
+ if (panGestureRecognizer != null && view != null)
+ {
+ switch (r.State)
+ {
+ case UIGestureRecognizerState.Began:
+ if (r.NumberOfTouches != panRecognizer.TouchPoints)
+ return;
+ panGestureRecognizer.SendPanStarted(view, Application.Current.PanGestureId);
+ break;
+ case UIGestureRecognizerState.Changed:
+ if (r.NumberOfTouches != panRecognizer.TouchPoints)
+ {
+ r.State = UIGestureRecognizerState.Ended;
+ panGestureRecognizer.SendPanCompleted(view, Application.Current.PanGestureId);
+ Application.Current.PanGestureId++;
+ return;
+ }
+ var translationInView = r.TranslationInView(_handler);
+ panGestureRecognizer.SendPan(view, translationInView.X, translationInView.Y, Application.Current.PanGestureId);
+ break;
+ case UIGestureRecognizerState.Cancelled:
+ case UIGestureRecognizerState.Failed:
+ panGestureRecognizer.SendPanCanceled(view, Application.Current.PanGestureId);
+ Application.Current.PanGestureId++;
+ break;
+ case UIGestureRecognizerState.Ended:
+ if (r.NumberOfTouches != panRecognizer.TouchPoints)
+ {
+ panGestureRecognizer.SendPanCompleted(view, Application.Current.PanGestureId);
+ Application.Current.PanGestureId++;
+ }
+ break;
+ }
+ }
+ });
+ return uiRecognizer;
+ }
+
+ return null;
+ }
+
+ UIPanGestureRecognizer CreatePanRecognizer(int numTouches, Action<UIPanGestureRecognizer> action)
+ {
+ var result = new UIPanGestureRecognizer(action);
+ result.MinimumNumberOfTouches = result.MaximumNumberOfTouches = (uint)numTouches;
+ return result;
+ }
+
+ UIPinchGestureRecognizer CreatePinchRecognizer(Action<UIPinchGestureRecognizer> action)
+ {
+ var result = new UIPinchGestureRecognizer(action);
+ return result;
+ }
+
+ UITapGestureRecognizer CreateTapRecognizer(int numFingers, int numTaps, Action<UITapGestureRecognizer> action)
+ {
+ var result = new UITapGestureRecognizer(action);
+ result.NumberOfTouchesRequired = (uint)numFingers;
+ result.NumberOfTapsRequired = (uint)numTaps;
+ return result;
+ }
+
+ void LoadRecognizers()
+ {
+ if (ElementGestureRecognizers == null)
+ return;
+
+ foreach (var recognizer in ElementGestureRecognizers)
+ {
+ if (_gestureRecognizers.ContainsKey(recognizer))
+ continue;
+
+ var nativeRecognizer = GetNativeRecognizer(recognizer);
+ if (nativeRecognizer != null)
+ {
+ nativeRecognizer.ShouldReceiveTouch = _shouldReceive;
+ _handler.AddGestureRecognizer(nativeRecognizer);
+
+ _gestureRecognizers[recognizer] = nativeRecognizer;
+ }
+ }
+
+ var toRemove = _gestureRecognizers.Keys.Where(key => !ElementGestureRecognizers.Contains(key)).ToArray();
+ foreach (var gestureRecognizer in toRemove)
+ {
+ var uiRecognizer = _gestureRecognizers[gestureRecognizer];
+ _gestureRecognizers.Remove(gestureRecognizer);
+
+ _handler.RemoveGestureRecognizer(uiRecognizer);
+ uiRecognizer.Dispose();
+ }
+ }
+
+ void ModelGestureRecognizersOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
+ {
+ LoadRecognizers();
+ }
+
+ void OnElementChanged(object sender, VisualElementChangedEventArgs e)
+ {
+ if (e.OldElement != null)
+ {
+ // unhook
+ var oldView = e.OldElement as View;
+ if (oldView != null)
+ {
+ var oldRecognizers = (ObservableCollection<IGestureRecognizer>)oldView.GestureRecognizers;
+ oldRecognizers.CollectionChanged -= _collectionChangedHandler;
+ }
+ }
+
+ if (e.NewElement != null)
+ {
+ // hook
+ if (ElementGestureRecognizers != null)
+ {
+ ElementGestureRecognizers.CollectionChanged += _collectionChangedHandler;
+ LoadRecognizers();
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/ExportCellAttribute.cs b/Xamarin.Forms.Platform.iOS/ExportCellAttribute.cs
new file mode 100644
index 00000000..96aec6cb
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/ExportCellAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class ExportCellAttribute : HandlerAttribute
+ {
+ public ExportCellAttribute(Type handler, Type target) : base(handler, target)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/ExportImageSourceHandlerAttribute.cs b/Xamarin.Forms.Platform.iOS/ExportImageSourceHandlerAttribute.cs
new file mode 100644
index 00000000..4c5c01fb
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/ExportImageSourceHandlerAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class ExportImageSourceHandlerAttribute : HandlerAttribute
+ {
+ public ExportImageSourceHandlerAttribute(Type handler, Type target) : base(handler, target)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/ExportRendererAttribute.cs b/Xamarin.Forms.Platform.iOS/ExportRendererAttribute.cs
new file mode 100644
index 00000000..50bba17f
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/ExportRendererAttribute.cs
@@ -0,0 +1,29 @@
+using System;
+using UIKit;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class ExportRendererAttribute : HandlerAttribute
+ {
+ public ExportRendererAttribute(Type handler, Type target, UIUserInterfaceIdiom idiom) : base(handler, target)
+ {
+ Idiomatic = true;
+ Idiom = idiom;
+ }
+
+ public ExportRendererAttribute(Type handler, Type target) : base(handler, target)
+ {
+ Idiomatic = false;
+ }
+
+ internal UIUserInterfaceIdiom Idiom { get; }
+
+ internal bool Idiomatic { get; }
+
+ public override bool ShouldRegister()
+ {
+ return !Idiomatic || Idiom == UIDevice.CurrentDevice.UserInterfaceIdiom;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Extensions/ArrayExtensions.cs b/Xamarin.Forms.Platform.iOS/Extensions/ArrayExtensions.cs
new file mode 100644
index 00000000..9adafecb
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Extensions/ArrayExtensions.cs
@@ -0,0 +1,38 @@
+using System;
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ internal static class ArrayExtensions
+ {
+ public static T[] Insert<T>(this T[] self, int index, T item)
+ {
+ var result = new T[self.Length + 1];
+ if (index > 0)
+ Array.Copy(self, result, index);
+
+ result[index] = item;
+
+ if (index < self.Length)
+ Array.Copy(self, index, result, index + 1, result.Length - index - 1);
+
+ return result;
+ }
+
+ public static T[] Remove<T>(this T[] self, T item)
+ {
+ return self.RemoveAt(self.IndexOf(item));
+ }
+
+ public static T[] RemoveAt<T>(this T[] self, int index)
+ {
+ var result = new T[self.Length - 1];
+ if (index > 0)
+ Array.Copy(self, result, index);
+
+ if (index < self.Length - 1)
+ Array.Copy(self, index + 1, result, index, self.Length - index - 1);
+
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Extensions/CellExtensions.cs b/Xamarin.Forms.Platform.iOS/Extensions/CellExtensions.cs
new file mode 100644
index 00000000..ca05bc54
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Extensions/CellExtensions.cs
@@ -0,0 +1,41 @@
+using System;
+#if __UNIFIED__
+using Foundation;
+
+#else
+using MonoTouch.Foundation;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ internal static class CellExtensions
+ {
+ internal static NSIndexPath GetIndexPath(this Cell self)
+ {
+ if (self == null)
+ throw new ArgumentNullException("self");
+
+ NSIndexPath path;
+
+ if (self.RealParent is ListView)
+ {
+ var section = 0;
+ var til = TemplatedItemsList<ItemsView<Cell>, Cell>.GetGroup(self);
+ if (til != null)
+ section = TemplatedItemsList<ItemsView<Cell>, Cell>.GetIndex(til.HeaderContent);
+
+ var row = TemplatedItemsList<ItemsView<Cell>, Cell>.GetIndex(self);
+ path = NSIndexPath.FromRowSection(row, section);
+ }
+ else if (self.RealParent is TableView)
+ {
+ var tmPath = TableView.TableSectionModel.GetPath(self);
+ path = NSIndexPath.FromRowSection(tmPath.Item2, tmPath.Item1);
+ }
+ else
+ throw new NotSupportedException("Unknown cell parent type");
+
+ return path;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Extensions/ColorExtensions.cs b/Xamarin.Forms.Platform.iOS/Extensions/ColorExtensions.cs
new file mode 100644
index 00000000..f512e157
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Extensions/ColorExtensions.cs
@@ -0,0 +1,99 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+#if __UNIFIED__
+using CoreAnimation;
+using CoreGraphics;
+using Foundation;
+using UIKit;
+#else
+using MonoTouch.CoreAnimation;
+using MonoTouch.CoreGraphics;
+using MonoTouch.Foundation;
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public static class ColorExtensions
+ {
+ internal static readonly UIColor Black = UIColor.Black;
+ internal static readonly UIColor SeventyPercentGrey = new UIColor(0.7f, 0.7f, 0.7f, 1);
+
+ public static CGColor ToCGColor(this Color color)
+ {
+ return new CGColor((float)color.R, (float)color.G, (float)color.B, (float)color.A);
+ }
+
+ public static Color ToColor(this UIColor color)
+ {
+ nfloat red;
+ nfloat green;
+ nfloat blue;
+ nfloat alpha;
+ color.GetRGBA(out red, out green, out blue, out alpha);
+ return new Color(red, green, blue, alpha);
+ }
+
+ public static UIColor ToUIColor(this Color color)
+ {
+ return new UIColor((float)color.R, (float)color.G, (float)color.B, (float)color.A);
+ }
+
+ public static UIColor ToUIColor(this Color color, Color defaultColor)
+ {
+ if (color.IsDefault)
+ return defaultColor.ToUIColor();
+
+ return color.ToUIColor();
+ }
+
+ public static UIColor ToUIColor(this Color color, UIColor defaultColor)
+ {
+ if (color.IsDefault)
+ return defaultColor;
+
+ return color.ToUIColor();
+ }
+ }
+
+ public static class PointExtensions
+ {
+ public static Point ToPoint(this PointF point)
+ {
+ return new Point(point.X, point.Y);
+ }
+ }
+
+ public static class SizeExtensions
+ {
+ public static SizeF ToSizeF(this Size size)
+ {
+ return new SizeF((float)size.Width, (float)size.Height);
+ }
+ }
+
+ public static class RectangleExtensions
+ {
+ public static Rectangle ToRectangle(this RectangleF rect)
+ {
+ return new Rectangle(rect.X, rect.Y, rect.Width, rect.Height);
+ }
+
+ public static RectangleF ToRectangleF(this Rectangle rect)
+ {
+ return new RectangleF((nfloat)rect.X, (nfloat)rect.Y, (nfloat)rect.Width, (nfloat)rect.Height);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Extensions/DateExtensions.cs b/Xamarin.Forms.Platform.iOS/Extensions/DateExtensions.cs
new file mode 100644
index 00000000..a75e7a69
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Extensions/DateExtensions.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+#if __UNIFIED__
+using CoreAnimation;
+using CoreGraphics;
+using Foundation;
+using UIKit;
+
+#else
+using MonoTouch.CoreAnimation;
+using MonoTouch.CoreGraphics;
+using MonoTouch.Foundation;
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public static class DateExtensions
+ {
+ public static DateTime ToDateTime(this NSDate date)
+ {
+ return new DateTime(2001, 1, 1, 0, 0, 0).AddSeconds(date.SecondsSinceReferenceDate);
+ }
+
+ public static NSDate ToNSDate(this DateTime date)
+ {
+ return NSDate.FromTimeIntervalSinceReferenceDate((date - new DateTime(2001, 1, 1, 0, 0, 0)).TotalSeconds);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Extensions/Extensions.cs b/Xamarin.Forms.Platform.iOS/Extensions/Extensions.cs
new file mode 100644
index 00000000..e74fed8d
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Extensions/Extensions.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public static class Extensions
+ {
+ public static void ApplyKeyboard(this IUITextInput textInput, Keyboard keyboard)
+ {
+ textInput.AutocapitalizationType = UITextAutocapitalizationType.None;
+ textInput.AutocorrectionType = UITextAutocorrectionType.No;
+ textInput.SpellCheckingType = UITextSpellCheckingType.No;
+
+ if (keyboard == Keyboard.Default)
+ {
+ textInput.AutocapitalizationType = UITextAutocapitalizationType.Sentences;
+ textInput.AutocorrectionType = UITextAutocorrectionType.Default;
+ textInput.SpellCheckingType = UITextSpellCheckingType.Default;
+ textInput.KeyboardType = UIKeyboardType.Default;
+ }
+ else if (keyboard == Keyboard.Chat)
+ {
+ textInput.AutocapitalizationType = UITextAutocapitalizationType.Sentences;
+ textInput.AutocorrectionType = UITextAutocorrectionType.Yes;
+ }
+ else if (keyboard == Keyboard.Email)
+ textInput.KeyboardType = UIKeyboardType.EmailAddress;
+ else if (keyboard == Keyboard.Numeric)
+ textInput.KeyboardType = UIKeyboardType.DecimalPad;
+ else if (keyboard == Keyboard.Telephone)
+ textInput.KeyboardType = UIKeyboardType.PhonePad;
+ else if (keyboard == Keyboard.Text)
+ {
+ textInput.AutocapitalizationType = UITextAutocapitalizationType.Sentences;
+ textInput.AutocorrectionType = UITextAutocorrectionType.Yes;
+ textInput.SpellCheckingType = UITextSpellCheckingType.Yes;
+ }
+ else if (keyboard == Keyboard.Url)
+ textInput.KeyboardType = UIKeyboardType.Url;
+ else if (keyboard is CustomKeyboard)
+ {
+ var custom = (CustomKeyboard)keyboard;
+ var capitalizedSentenceEnabled = (custom.Flags & KeyboardFlags.CapitalizeSentence) == KeyboardFlags.CapitalizeSentence;
+ var spellcheckEnabled = (custom.Flags & KeyboardFlags.Spellcheck) == KeyboardFlags.Spellcheck;
+ var suggestionsEnabled = (custom.Flags & KeyboardFlags.Suggestions) == KeyboardFlags.Suggestions;
+
+ textInput.AutocapitalizationType = capitalizedSentenceEnabled ? UITextAutocapitalizationType.Sentences : UITextAutocapitalizationType.None;
+ textInput.AutocorrectionType = suggestionsEnabled ? UITextAutocorrectionType.Yes : UITextAutocorrectionType.No;
+ textInput.SpellCheckingType = spellcheckEnabled ? UITextSpellCheckingType.Yes : UITextSpellCheckingType.No;
+ }
+ }
+
+ internal static DeviceOrientation ToDeviceOrientation(this UIDeviceOrientation orientation)
+ {
+ switch (orientation)
+ {
+ case UIDeviceOrientation.Portrait:
+ return DeviceOrientation.Portrait;
+ case UIDeviceOrientation.PortraitUpsideDown:
+ return DeviceOrientation.PortraitDown;
+ case UIDeviceOrientation.LandscapeLeft:
+ return DeviceOrientation.LandscapeLeft;
+ case UIDeviceOrientation.LandscapeRight:
+ return DeviceOrientation.LandscapeRight;
+ default:
+ return DeviceOrientation.Other;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Extensions/ToolbarItemExtensions.cs b/Xamarin.Forms.Platform.iOS/Extensions/ToolbarItemExtensions.cs
new file mode 100644
index 00000000..71bdbbac
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Extensions/ToolbarItemExtensions.cs
@@ -0,0 +1,228 @@
+using System;
+using System.Drawing;
+using System.ComponentModel;
+#if __UNIFIED__
+using CoreGraphics;
+using UIKit;
+#else
+using MonoTouch.CoreGraphics;
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public static class ToolbarItemExtensions
+ {
+ public static UIBarButtonItem ToUIBarButtonItem(this ToolbarItem item, bool forceName = false)
+ {
+ return item.Order == ToolbarItemOrder.Secondary ? new SecondaryToolbarItem(item) : (UIBarButtonItem)new PrimaryToolbarItem(item, forceName);
+ }
+
+ sealed class PrimaryToolbarItem : UIBarButtonItem
+ {
+ readonly bool _forceName;
+ readonly ToolbarItem _item;
+
+ public PrimaryToolbarItem(ToolbarItem item, bool forceName)
+ {
+ _forceName = forceName;
+ _item = item;
+
+ if (!string.IsNullOrEmpty(item.Icon) && !forceName)
+ UpdateIconAndStyle();
+ else
+ UpdateTextAndStyle();
+ UpdateIsEnabled();
+
+ Clicked += (sender, e) => item.Activate();
+ item.PropertyChanged += OnPropertyChanged;
+
+ if (item != null && !string.IsNullOrEmpty(item.AutomationId))
+ AccessibilityIdentifier = item.AutomationId;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ _item.PropertyChanged -= OnPropertyChanged;
+ base.Dispose(disposing);
+ }
+
+ void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == MenuItem.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled();
+ else if (e.PropertyName == MenuItem.TextProperty.PropertyName)
+ {
+ if (string.IsNullOrEmpty(_item.Icon) || _forceName)
+ UpdateTextAndStyle();
+ }
+ else if (e.PropertyName == MenuItem.IconProperty.PropertyName)
+ {
+ if (!_forceName)
+ {
+ if (!string.IsNullOrEmpty(_item.Icon))
+ UpdateIconAndStyle();
+ else
+ UpdateTextAndStyle();
+ }
+ }
+ }
+
+ void UpdateIconAndStyle()
+ {
+ var image = UIImage.FromBundle(_item.Icon);
+ Image = image;
+ Style = UIBarButtonItemStyle.Plain;
+ }
+
+ void UpdateIsEnabled()
+ {
+ Enabled = _item.IsEnabled;
+ }
+
+ void UpdateTextAndStyle()
+ {
+ Title = _item.Text;
+ Style = UIBarButtonItemStyle.Bordered;
+ Image = null;
+ }
+ }
+
+ sealed class SecondaryToolbarItem : UIBarButtonItem
+ {
+ readonly ToolbarItem _item;
+
+ public SecondaryToolbarItem(ToolbarItem item) : base(new SecondaryToolbarItemContent())
+ {
+ _item = item;
+ UpdateText();
+ UpdateIcon();
+ UpdateIsEnabled();
+
+ ((SecondaryToolbarItemContent)CustomView).TouchUpInside += (sender, e) => item.Activate();
+ item.PropertyChanged += OnPropertyChanged;
+
+ if (item != null && !string.IsNullOrEmpty(item.AutomationId))
+ AccessibilityIdentifier = item.AutomationId;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ _item.PropertyChanged -= OnPropertyChanged;
+ base.Dispose(disposing);
+ }
+
+ void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == MenuItem.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == MenuItem.IconProperty.PropertyName)
+ UpdateIcon();
+ else if (e.PropertyName == MenuItem.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled();
+ }
+
+ void UpdateIcon()
+ {
+ ((SecondaryToolbarItemContent)CustomView).Image = string.IsNullOrEmpty(_item.Icon) ? null : new UIImage(_item.Icon);
+ }
+
+ void UpdateIsEnabled()
+ {
+ ((UIControl)CustomView).Enabled = _item.IsEnabled;
+ }
+
+ void UpdateText()
+ {
+ ((SecondaryToolbarItemContent)CustomView).Text = _item.Text;
+ }
+
+ sealed class SecondaryToolbarItemContent : UIControl
+ {
+ readonly UIImageView _imageView;
+ readonly UILabel _label;
+
+ public SecondaryToolbarItemContent() : base(new RectangleF(0, 0, 75, 20))
+ {
+ BackgroundColor = UIColor.Clear;
+ _imageView = new UIImageView { BackgroundColor = UIColor.Clear };
+ AddSubview(_imageView);
+
+ _label = new UILabel { BackgroundColor = UIColor.Clear, Lines = 1, LineBreakMode = UILineBreakMode.TailTruncation, Font = UIFont.SystemFontOfSize(10) };
+ AddSubview(_label);
+ }
+
+ public override bool Enabled
+ {
+ get { return base.Enabled; }
+ set
+ {
+ base.Enabled = value;
+ _label.Enabled = value;
+ _imageView.Alpha = value ? 1f : 0.25f;
+ }
+ }
+
+ public UIImage Image
+ {
+ get { return _imageView.Image; }
+ set { _imageView.Image = value; }
+ }
+
+ public string Text
+ {
+ get { return _label.Text; }
+ set { _label.Text = value; }
+ }
+
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+
+ const float padding = 5f;
+ var imageSize = _imageView.SizeThatFits(Bounds.Size);
+ var fullStringSize = _label.SizeThatFits(Bounds.Size);
+
+ if (imageSize.Width > 0 && (string.IsNullOrEmpty(Text) || fullStringSize.Width > Bounds.Width / 3))
+ {
+ _imageView.Frame = new RectangleF(PointF.Empty, imageSize);
+ _imageView.Center = new PointF(Bounds.GetMidX(), Bounds.GetMidY());
+ _label.Hidden = true;
+ return;
+ }
+
+ _label.Hidden = false;
+ var availableWidth = Bounds.Width - padding * 3 - imageSize.Width;
+ var stringSize = _label.SizeThatFits(new SizeF(availableWidth, Bounds.Height - padding * 2));
+
+ availableWidth = Bounds.Width;
+ availableWidth -= stringSize.Width;
+ availableWidth -= imageSize.Width;
+
+ var x = availableWidth / 2;
+
+ var frame = new RectangleF(new PointF(x, Bounds.GetMidY() - imageSize.Height / 2), imageSize);
+ _imageView.Frame = frame;
+
+ frame.X = frame.Right + (imageSize.Width > 0 ? padding : 0);
+ frame.Size = stringSize;
+ frame.Height = Bounds.Height;
+ frame.Y = 0;
+ _label.Frame = frame;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Extensions/UIViewExtensions.cs b/Xamarin.Forms.Platform.iOS/Extensions/UIViewExtensions.cs
new file mode 100644
index 00000000..9847867c
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Extensions/UIViewExtensions.cs
@@ -0,0 +1,66 @@
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public static class UIViewExtensions
+ {
+ public static IEnumerable<UIView> Descendants(this UIView self)
+ {
+ if (self.Subviews == null)
+ return Enumerable.Empty<UIView>();
+ return self.Subviews.Concat(self.Subviews.SelectMany(s => s.Descendants()));
+ }
+
+ public static SizeRequest GetSizeRequest(this UIView self, double widthConstraint, double heightConstraint, double minimumWidth = -1, double minimumHeight = -1)
+ {
+ var s = self.SizeThatFits(new SizeF((float)widthConstraint, (float)heightConstraint));
+ var request = new Size(s.Width == float.PositiveInfinity ? double.PositiveInfinity : s.Width, s.Height == float.PositiveInfinity ? double.PositiveInfinity : s.Height);
+ var minimum = new Size(minimumWidth < 0 ? request.Width : minimumWidth, minimumHeight < 0 ? request.Height : minimumHeight);
+ return new SizeRequest(request, minimum);
+ }
+
+ internal static T FindDescendantView<T>(this UIView view) where T : UIView
+ {
+ var queue = new Queue<UIView>();
+ queue.Enqueue(view);
+
+ while (queue.Count > 0)
+ {
+ var descendantView = queue.Dequeue();
+
+ var result = descendantView as T;
+ if (result != null)
+ return result;
+
+ for (var i = 0; i < descendantView.Subviews.Length; i++)
+ queue.Enqueue(descendantView.Subviews[i]);
+ }
+
+ return null;
+ }
+
+ internal static UIView FindFirstResponder(this UIView view)
+ {
+ if (view.IsFirstResponder)
+ return view;
+
+ foreach (var subView in view.Subviews)
+ {
+ var firstResponder = subView.FindFirstResponder();
+ if (firstResponder != null)
+ return firstResponder;
+ }
+
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Extensions/ViewExtensions.cs b/Xamarin.Forms.Platform.iOS/Extensions/ViewExtensions.cs
new file mode 100644
index 00000000..9ded0632
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Extensions/ViewExtensions.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public static class ViewExtensions
+ {
+ public static IEnumerable<Page> GetParentPages(this Page target)
+ {
+ var result = new List<Page>();
+ var parent = target.RealParent as Page;
+ while (!Application.IsApplicationOrNull(parent))
+ {
+ result.Add(parent);
+ parent = parent.RealParent as Page;
+ }
+
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Forms.cs b/Xamarin.Forms.Platform.iOS/Forms.cs
new file mode 100644
index 00000000..b7a41826
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Forms.cs
@@ -0,0 +1,373 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.IO.IsolatedStorage;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Net.Http;
+using System.Reflection;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+#if __UNIFIED__
+using UIKit;
+using CoreFoundation;
+using Foundation;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.CoreFoundation;
+using MonoTouch.Foundation;
+#endif
+using Xamarin.Forms.Platform.iOS;
+
+namespace Xamarin.Forms
+{
+ public static class Forms
+ {
+ //Preserve GetCallingAssembly
+ static readonly bool nevertrue = false;
+
+ static bool? s_isiOS7OrNewer;
+
+ static bool? s_isiOS8OrNewer;
+
+ static bool? s_isiOS9OrNewer;
+
+ static Forms()
+ {
+ if (nevertrue)
+ Assembly.GetCallingAssembly();
+ }
+
+ public static bool IsInitialized { get; private set; }
+
+ internal static bool IsiOS7OrNewer
+ {
+ get
+ {
+ if (!s_isiOS7OrNewer.HasValue)
+ s_isiOS7OrNewer = UIDevice.CurrentDevice.CheckSystemVersion(7, 0);
+ return s_isiOS7OrNewer.Value;
+ }
+ }
+
+ internal static bool IsiOS8OrNewer
+ {
+ get
+ {
+ if (!s_isiOS8OrNewer.HasValue)
+ s_isiOS8OrNewer = UIDevice.CurrentDevice.CheckSystemVersion(8, 0);
+ return s_isiOS8OrNewer.Value;
+ }
+ }
+
+ internal static bool IsiOS9OrNewer
+ {
+ get
+ {
+ if (!s_isiOS9OrNewer.HasValue)
+ s_isiOS9OrNewer = UIDevice.CurrentDevice.CheckSystemVersion(9, 0);
+ return s_isiOS9OrNewer.Value;
+ }
+ }
+
+ public static void Init()
+ {
+ if (IsInitialized)
+ return;
+ IsInitialized = true;
+ Color.Accent = Color.FromRgba(50, 79, 133, 255);
+
+ Log.Listeners.Add(new DelegateLogListener((c, m) => Trace.WriteLine(m, c)));
+
+ Device.OS = TargetPlatform.iOS;
+ Device.PlatformServices = new IOSPlatformServices();
+ Device.Info = new IOSDeviceInfo();
+
+ Ticker.Default = new CADisplayLinkTicker();
+ Registrar.RegisterAll(new[] { typeof(ExportRendererAttribute), typeof(ExportCellAttribute), typeof(ExportImageSourceHandlerAttribute) });
+
+ Device.Idiom = UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad ? TargetIdiom.Tablet : TargetIdiom.Phone;
+
+ ExpressionSearch.Default = new iOSExpressionSearch();
+ }
+
+ public static event EventHandler<ViewInitializedEventArgs> ViewInitialized;
+
+ internal static void SendViewInitialized(this VisualElement self, UIView nativeView)
+ {
+ var viewInitialized = ViewInitialized;
+ if (viewInitialized != null)
+ viewInitialized(self, new ViewInitializedEventArgs { View = self, NativeView = nativeView });
+ }
+
+ class iOSExpressionSearch : ExpressionVisitor, IExpressionSearch
+ {
+ List<object> _results;
+ Type _targetType;
+
+ public List<T> FindObjects<T>(Expression expression) where T : class
+ {
+ _results = new List<object>();
+ _targetType = typeof(T);
+ Visit(expression);
+ return _results.Select(o => o as T).ToList();
+ }
+
+ protected override Expression VisitMember(MemberExpression node)
+ {
+ if (node.Expression is ConstantExpression && node.Member is FieldInfo)
+ {
+ var container = ((ConstantExpression)node.Expression).Value;
+ var value = ((FieldInfo)node.Member).GetValue(container);
+
+ if (_targetType.IsInstanceOfType(value))
+ _results.Add(value);
+ }
+ return base.VisitMember(node);
+ }
+ }
+
+ internal class IOSDeviceInfo : DeviceInfo
+ {
+ readonly NSObject _notification;
+ readonly Size _scaledScreenSize;
+ readonly double _scalingFactor;
+
+ public IOSDeviceInfo()
+ {
+ _notification = UIDevice.Notifications.ObserveOrientationDidChange((sender, args) => CurrentOrientation = UIDevice.CurrentDevice.Orientation.ToDeviceOrientation());
+
+ _scalingFactor = UIScreen.MainScreen.Scale;
+ _scaledScreenSize = new Size(UIScreen.MainScreen.Bounds.Width, UIScreen.MainScreen.Bounds.Height);
+ PixelScreenSize = new Size(_scaledScreenSize.Width * _scalingFactor, _scaledScreenSize.Height * _scalingFactor);
+ }
+
+ public override Size PixelScreenSize { get; }
+
+ public override Size ScaledScreenSize
+ {
+ get { return _scaledScreenSize; }
+ }
+
+ public override double ScalingFactor
+ {
+ get { return _scalingFactor; }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ _notification.Dispose();
+ base.Dispose(disposing);
+ }
+ }
+
+ class IOSPlatformServices : IPlatformServices
+ {
+ static readonly MD5CryptoServiceProvider Checksum = new MD5CryptoServiceProvider();
+
+ public void BeginInvokeOnMainThread(Action action)
+ {
+ NSRunLoop.Main.BeginInvokeOnMainThread(action.Invoke);
+ }
+
+ public ITimer CreateTimer(Action<object> callback)
+ {
+ return new _Timer(new Timer(o => callback(o)));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, int dueTime, int period)
+ {
+ return new _Timer(new Timer(o => callback(o), state, dueTime, period));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, long dueTime, long period)
+ {
+ return new _Timer(new Timer(o => callback(o), state, dueTime, period));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, TimeSpan dueTime, TimeSpan period)
+ {
+ return new _Timer(new Timer(o => callback(o), state, dueTime, period));
+ }
+
+ public ITimer CreateTimer(Action<object> callback, object state, uint dueTime, uint period)
+ {
+ return new _Timer(new Timer(o => callback(o), state, dueTime, period));
+ }
+
+ public Assembly[] GetAssemblies()
+ {
+ return AppDomain.CurrentDomain.GetAssemblies();
+ }
+
+ public string GetMD5Hash(string input)
+ {
+ var bytes = Checksum.ComputeHash(Encoding.UTF8.GetBytes(input));
+ var ret = new char[32];
+ for (var i = 0; i < 16; i++)
+ {
+ ret[i * 2] = (char)Hex(bytes[i] >> 4);
+ ret[i * 2 + 1] = (char)Hex(bytes[i] & 0xf);
+ }
+ return new string(ret);
+ }
+
+ public double GetNamedSize(NamedSize size, Type targetElementType, bool useOldSizes)
+ {
+ // We make these up anyway, so new sizes didn't really change
+ // iOS docs say default button font size is 15, default label font size is 17 so we use those as the defaults.
+ switch (size)
+ {
+ case NamedSize.Default:
+ return typeof(Button).IsAssignableFrom(targetElementType) ? 15 : 17;
+ case NamedSize.Micro:
+ return 12;
+ case NamedSize.Small:
+ return 14;
+ case NamedSize.Medium:
+ return 17;
+ case NamedSize.Large:
+ return 22;
+ default:
+ throw new ArgumentOutOfRangeException("size");
+ }
+ }
+
+ public async Task<Stream> GetStreamAsync(Uri uri, CancellationToken cancellationToken)
+ {
+ using(var client = GetHttpClient())
+ using(var response = await client.GetAsync(uri, cancellationToken))
+ return await response.Content.ReadAsStreamAsync();
+ }
+
+ public IIsolatedStorageFile GetUserStoreForApplication()
+ {
+ return new _IsolatedStorageFile(IsolatedStorageFile.GetUserStoreForApplication());
+ }
+
+ public bool IsInvokeRequired
+ {
+ get { return !NSThread.IsMain; }
+ }
+
+ public void OpenUriAction(Uri uri)
+ {
+ UIApplication.SharedApplication.OpenUrl(new NSUrl(uri.AbsoluteUri));
+ }
+
+ public void StartTimer(TimeSpan interval, Func<bool> callback)
+ {
+ NSTimer timer = null;
+#if __UNIFIED__
+ timer = NSTimer.CreateRepeatingScheduledTimer(interval, t =>
+ {
+#else
+ timer = NSTimer.CreateRepeatingScheduledTimer (interval, () => {
+ #endif
+ if (!callback())
+#if __UNIFIED__
+ t.Invalidate();
+#else
+ timer.Invalidate ();
+ #endif
+ });
+ NSRunLoop.Main.AddTimer(timer, NSRunLoopMode.Common);
+ }
+
+ HttpClient GetHttpClient()
+ {
+ var proxy = CFNetwork.GetSystemProxySettings();
+ var handler = new HttpClientHandler();
+ if (!string.IsNullOrEmpty(proxy.HTTPProxy))
+ {
+ handler.Proxy = CFNetwork.GetDefaultProxy();
+ handler.UseProxy = true;
+ }
+ return new HttpClient(handler);
+ }
+
+ static int Hex(int v)
+ {
+ if (v < 10)
+ return '0' + v;
+ return 'a' + v - 10;
+ }
+
+ public class _Timer : ITimer
+ {
+ readonly Timer _timer;
+
+ public _Timer(Timer timer)
+ {
+ _timer = timer;
+ }
+
+ public void Change(int dueTime, int period)
+ {
+ _timer.Change(dueTime, period);
+ }
+
+ public void Change(long dueTime, long period)
+ {
+ _timer.Change(dueTime, period);
+ }
+
+ public void Change(TimeSpan dueTime, TimeSpan period)
+ {
+ _timer.Change(dueTime, period);
+ }
+
+ public void Change(uint dueTime, uint period)
+ {
+ _timer.Change(dueTime, period);
+ }
+ }
+
+ public class _IsolatedStorageFile : IIsolatedStorageFile
+ {
+ readonly IsolatedStorageFile _isolatedStorageFile;
+
+ public _IsolatedStorageFile(IsolatedStorageFile isolatedStorageFile)
+ {
+ _isolatedStorageFile = isolatedStorageFile;
+ }
+
+ public Task CreateDirectoryAsync(string path)
+ {
+ _isolatedStorageFile.CreateDirectory(path);
+ return Task.FromResult(true);
+ }
+
+ public Task<bool> GetDirectoryExistsAsync(string path)
+ {
+ return Task.FromResult(_isolatedStorageFile.DirectoryExists(path));
+ }
+
+ public Task<bool> GetFileExistsAsync(string path)
+ {
+ return Task.FromResult(_isolatedStorageFile.FileExists(path));
+ }
+
+ public Task<DateTimeOffset> GetLastWriteTimeAsync(string path)
+ {
+ return Task.FromResult(_isolatedStorageFile.GetLastWriteTime(path));
+ }
+
+ public Task<Stream> OpenFileAsync(string path, FileMode mode, FileAccess access)
+ {
+ Stream stream = _isolatedStorageFile.OpenFile(path, (System.IO.FileMode)mode, (System.IO.FileAccess)access);
+ return Task.FromResult(stream);
+ }
+
+ public Task<Stream> OpenFileAsync(string path, FileMode mode, FileAccess access, FileShare share)
+ {
+ Stream stream = _isolatedStorageFile.OpenFile(path, (System.IO.FileMode)mode, (System.IO.FileAccess)access, (System.IO.FileShare)share);
+ return Task.FromResult(stream);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/FormsApplicationDelegate.cs b/Xamarin.Forms.Platform.iOS/FormsApplicationDelegate.cs
new file mode 100644
index 00000000..a4342473
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/FormsApplicationDelegate.cs
@@ -0,0 +1,151 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+#if __UNIFIED__
+using Foundation;
+using UIKit;
+
+#else
+using MonoTouch.Foundation;
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class FormsApplicationDelegate : UIApplicationDelegate
+ {
+ Application _application;
+ bool _isSuspended;
+ UIWindow _window;
+
+ protected FormsApplicationDelegate()
+ {
+ }
+
+ public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
+ {
+ return true;
+ }
+
+ // now in background
+ public override void DidEnterBackground(UIApplication uiApplication)
+ {
+ // applicationDidEnterBackground
+ }
+
+ // finish initialization before display to user
+ public override bool FinishedLaunching(UIApplication uiApplication, NSDictionary launchOptions)
+ {
+ // check contents of launch options and evaluate why the app was launched and respond
+ // initialize the important data structures
+ // prepare you apps window and views for display
+ // keep lightweight, anything long winded should be executed asynchronously on a secondary thread.
+ // application:didFinishLaunchingWithOptions
+ _window = new UIWindow(UIScreen.MainScreen.Bounds);
+
+ if (_application == null)
+ throw new InvalidOperationException("You MUST invoke LoadApplication () before calling base.FinishedLaunching ()");
+
+ SetMainPage();
+ _application.SendStart();
+ return true;
+ }
+
+ // about to become foreground, last minute preparatuin
+ public override void OnActivated(UIApplication uiApplication)
+ {
+ // applicationDidBecomeActive
+ // execute any OpenGL ES drawing calls
+ if (_application != null && _isSuspended)
+ {
+ _isSuspended = false;
+ _application.SendResume();
+ }
+ }
+
+ // transitioning to background
+ public override async void OnResignActivation(UIApplication uiApplication)
+ {
+ // applicationWillResignActive
+ if (_application != null)
+ {
+ _isSuspended = true;
+ await _application.SendSleepAsync();
+ }
+ }
+
+ public override void UserActivityUpdated(UIApplication application, NSUserActivity userActivity)
+ {
+ }
+
+ // from background to foreground, not yet active
+ public override void WillEnterForeground(UIApplication uiApplication)
+ {
+ // applicationWillEnterForeground
+ }
+
+ // TODO where to execute heavy code, storing state, sending to server, etc
+
+ // first chance to execute code at launch time
+ public override bool WillFinishLaunching(UIApplication uiApplication, NSDictionary launchOptions)
+ {
+ // check contents of launch options and evaluate why the app was launched and respond
+ // initialize the important data structures
+ // prepare you apps window and views for display
+ // keep lightweight, anything long winded should be executed asynchronously on a secondary thread.
+ // application:willFinishLaunchingWithOptions
+ // Restore ui state here
+ return true;
+ }
+
+ // app is being terminated, not called if you app is suspended
+ public override void WillTerminate(UIApplication uiApplication)
+ {
+ // applicationWillTerminate
+ //application.SendTerminate ();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && _application != null)
+ _application.PropertyChanged -= ApplicationOnPropertyChanged;
+
+ base.Dispose(disposing);
+ }
+
+ protected void LoadApplication(Application application)
+ {
+ if (application == null)
+ throw new ArgumentNullException("application");
+
+ Application.Current = application;
+ _application = application;
+
+ application.PropertyChanged += ApplicationOnPropertyChanged;
+ }
+
+ void ApplicationOnPropertyChanged(object sender, PropertyChangedEventArgs args)
+ {
+ if (args.PropertyName == "MainPage")
+ UpdateMainPage();
+ }
+
+ void SetMainPage()
+ {
+ UpdateMainPage();
+ _window.MakeKeyAndVisible();
+ }
+
+ void UpdateMainPage()
+ {
+ if (_application.MainPage == null)
+ return;
+
+ var platformRenderer = (PlatformRenderer)_window.RootViewController;
+ _window.RootViewController = _application.MainPage.CreateViewController();
+ if (platformRenderer != null)
+ ((IDisposable)platformRenderer.Platform).Dispose();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/GlobalCloseContextGestureRecognizer.cs b/Xamarin.Forms.Platform.iOS/GlobalCloseContextGestureRecognizer.cs
new file mode 100644
index 00000000..fa76b982
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/GlobalCloseContextGestureRecognizer.cs
@@ -0,0 +1,72 @@
+using System.Collections.Generic;
+using System.Drawing;
+#if __UNIFIED__
+using Foundation;
+using UIKit;
+#else
+using MonoTouch.Foundation;
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+using NSAction = System.Action;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ internal class GlobalCloseContextGestureRecognizer : UIGestureRecognizer
+ {
+ List<UIButton> _buttons;
+ UIScrollView _scrollView;
+
+ public GlobalCloseContextGestureRecognizer(UIScrollView scrollView, List<UIButton> buttons, NSAction activated) : base(activated)
+ {
+ _scrollView = scrollView;
+ _buttons = buttons;
+
+ ShouldReceiveTouch = OnShouldReceiveTouch;
+ }
+
+ public override void TouchesBegan(NSSet touches, UIEvent evt)
+ {
+ State = UIGestureRecognizerState.Began;
+ base.TouchesBegan(touches, evt);
+ }
+
+ public override void TouchesEnded(NSSet touches, UIEvent evt)
+ {
+ State = UIGestureRecognizerState.Recognized;
+ base.TouchesEnded(touches, evt);
+ }
+
+ public override void TouchesMoved(NSSet touches, UIEvent evt)
+ {
+ State = UIGestureRecognizerState.Recognized;
+ base.TouchesMoved(touches, evt);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (disposing)
+ {
+ _buttons = null;
+ _scrollView = null;
+ }
+ }
+
+ bool OnShouldReceiveTouch(UIGestureRecognizer r, UITouch t)
+ {
+ var scrollPos = t.LocationInView(_scrollView);
+ var rect = new RectangleF(0, 0, _scrollView.ContentSize.Width, _scrollView.ContentSize.Height);
+ return !rect.Contains(scrollPos);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/IVisualElementRenderer.cs b/Xamarin.Forms.Platform.iOS/IVisualElementRenderer.cs
new file mode 100644
index 00000000..5ffabf08
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/IVisualElementRenderer.cs
@@ -0,0 +1,27 @@
+using System;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public interface IVisualElementRenderer : IDisposable, IRegisterable
+ {
+ VisualElement Element { get; }
+
+ UIView NativeView { get; }
+
+ UIViewController ViewController { get; }
+
+ event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint);
+
+ void SetElement(VisualElement element);
+
+ void SetElementSize(Size size);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/LayoutExtensions.cs b/Xamarin.Forms.Platform.iOS/LayoutExtensions.cs
new file mode 100644
index 00000000..6e7f5738
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/LayoutExtensions.cs
@@ -0,0 +1,36 @@
+using System.Collections.Generic;
+#if __UNIFIED__
+using CoreGraphics;
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+#if !__UNIFIED__
+ // Save ourselves a ton of ugly ifdefs below
+using CGSize = System.Drawing.SizeF;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public delegate SizeRequest? GetDesiredSizeDelegate(NativeViewWrapperRenderer renderer, double widthConstraint, double heightConstraint);
+
+ public delegate CGSize? SizeThatFitsDelegate(CGSize size);
+
+ public delegate bool LayoutSubviewsDelegate();
+
+ public static class LayoutExtensions
+ {
+ public static void Add(this IList<View> children, UIView view, GetDesiredSizeDelegate getDesiredSizeDelegate = null, SizeThatFitsDelegate sizeThatFitsDelegate = null,
+ LayoutSubviewsDelegate layoutSubViews = null)
+ {
+ children.Add(view.ToView(getDesiredSizeDelegate, sizeThatFitsDelegate, layoutSubViews));
+ }
+
+ public static View ToView(this UIView view, GetDesiredSizeDelegate getDesiredSizeDelegate = null, SizeThatFitsDelegate sizeThatFitsDelegate = null, LayoutSubviewsDelegate layoutSubViews = null)
+ {
+ return new NativeViewWrapper(view, getDesiredSizeDelegate, sizeThatFitsDelegate, layoutSubViews);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/NativeViewWrapper.cs b/Xamarin.Forms.Platform.iOS/NativeViewWrapper.cs
new file mode 100644
index 00000000..209aca80
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/NativeViewWrapper.cs
@@ -0,0 +1,35 @@
+using System.Collections.Generic;
+#if __UNIFIED__
+using CoreGraphics;
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+#if !__UNIFIED__
+ // Save ourselves a ton of ugly ifdefs below
+using CGSize = System.Drawing.SizeF;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class NativeViewWrapper : View
+ {
+ public NativeViewWrapper(UIView nativeView, GetDesiredSizeDelegate getDesiredSizeDelegate = null, SizeThatFitsDelegate sizeThatFitsDelegate = null, LayoutSubviewsDelegate layoutSubViews = null)
+ {
+ GetDesiredSizeDelegate = getDesiredSizeDelegate;
+ SizeThatFitsDelegate = sizeThatFitsDelegate;
+ LayoutSubViews = layoutSubViews;
+ NativeView = nativeView;
+ }
+
+ public GetDesiredSizeDelegate GetDesiredSizeDelegate { get; }
+
+ public LayoutSubviewsDelegate LayoutSubViews { get; set; }
+
+ public UIView NativeView { get; }
+
+ public SizeThatFitsDelegate SizeThatFitsDelegate { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/NativeViewWrapperRenderer.cs b/Xamarin.Forms.Platform.iOS/NativeViewWrapperRenderer.cs
new file mode 100644
index 00000000..3d3e6868
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/NativeViewWrapperRenderer.cs
@@ -0,0 +1,72 @@
+using System.Collections.Generic;
+#if __UNIFIED__
+using CoreGraphics;
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+#if !__UNIFIED__
+ // Save ourselves a ton of ugly ifdefs below
+using CGSize = System.Drawing.SizeF;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class NativeViewWrapperRenderer : ViewRenderer<NativeViewWrapper, UIView>
+ {
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ if (Element?.GetDesiredSizeDelegate == null)
+ return base.GetDesiredSize(widthConstraint, heightConstraint);
+
+ // The user has specified a different implementation of GetDesiredSize
+ var result = Element.GetDesiredSizeDelegate(this, widthConstraint, heightConstraint);
+
+ // If the GetDesiredSize delegate returns a SizeRequest, we use it; if it returns null,
+ // fall back to the default implementation
+ return result ?? base.GetDesiredSize(widthConstraint, heightConstraint);
+ }
+
+ public override void LayoutSubviews()
+ {
+ if (Element?.LayoutSubViews == null)
+ {
+ Element?.InvalidateMeasure(InvalidationTrigger.MeasureChanged);
+ base.LayoutSubviews();
+ return;
+ }
+
+ // The user has specified a different implementation of LayoutSubviews
+ var handled = Element.LayoutSubViews();
+
+ if (!handled)
+ {
+ // If the delegate wasn't able to handle the request, fall back to the default implementation
+ base.LayoutSubviews();
+ }
+ }
+
+ public override CGSize SizeThatFits(CGSize size)
+ {
+ if (Element?.SizeThatFitsDelegate == null)
+ return base.SizeThatFits(size);
+
+ // The user has specified a different implementation of SizeThatFits
+ var result = Element.SizeThatFitsDelegate(size);
+
+ // If the delegate returns a value, we use it;
+ // if it returns null, fall back to the default implementation
+ return result ?? base.SizeThatFits(size);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<NativeViewWrapper> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement == null)
+ SetNativeControl(Element.NativeView);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/PageExtensions.cs b/Xamarin.Forms.Platform.iOS/PageExtensions.cs
new file mode 100644
index 00000000..07da048a
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/PageExtensions.cs
@@ -0,0 +1,33 @@
+using System;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms
+{
+ public static class PageExtensions
+ {
+ public static UIViewController CreateViewController(this Page view)
+ {
+ if (!Forms.IsInitialized)
+ throw new InvalidOperationException("call Forms.Init() before this");
+
+ if (!(view.RealParent is Application))
+ {
+ Application app = new DefaultApplication();
+ app.MainPage = view;
+ }
+
+ var result = new Platform.iOS.Platform();
+ result.SetPage(view);
+ return result.ViewController;
+ }
+
+ class DefaultApplication : Application
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Platform.cs b/Xamarin.Forms.Platform.iOS/Platform.cs
new file mode 100644
index 00000000..0293e75f
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Platform.cs
@@ -0,0 +1,505 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+#if __UNIFIED__
+using CoreGraphics;
+using Foundation;
+using ObjCRuntime;
+using UIKit;
+#else
+using MonoTouch;
+using MonoTouch.CoreAnimation;
+using MonoTouch.CoreFoundation;
+using MonoTouch.CoreGraphics;
+using MonoTouch.UIKit;
+using System.Drawing;
+using MonoTouch.CoreAnimation;
+using MonoTouch.Foundation;
+using MonoTouch.ObjCRuntime;
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class Platform : BindableObject, IPlatform, INavigation, IDisposable
+ {
+ internal static readonly BindableProperty RendererProperty = BindableProperty.CreateAttached("Renderer", typeof(IVisualElementRenderer), typeof(Platform), default(IVisualElementRenderer),
+ propertyChanged: (bindable, oldvalue, newvalue) =>
+ {
+ var view = bindable as VisualElement;
+ if (view != null)
+ view.IsPlatformEnabled = newvalue != null;
+ });
+
+ readonly int _alertPadding = 10;
+
+ readonly List<Page> _modals;
+ readonly PlatformRenderer _renderer;
+ bool _animateModals = true;
+ bool _appeared;
+
+ bool _disposed;
+
+ internal Platform()
+ {
+ _renderer = new PlatformRenderer(this);
+ _modals = new List<Page>();
+
+ var busyCount = 0;
+ MessagingCenter.Subscribe(this, Page.BusySetSignalName, (Page sender, bool enabled) =>
+ {
+ if (!PageIsChildOfPlatform(sender))
+ return;
+ busyCount = Math.Max(0, enabled ? busyCount + 1 : busyCount - 1);
+ UIApplication.SharedApplication.NetworkActivityIndicatorVisible = busyCount > 0;
+ });
+
+ MessagingCenter.Subscribe(this, Page.AlertSignalName, (Page sender, AlertArguments arguments) =>
+ {
+ if (!PageIsChildOfPlatform(sender))
+ return;
+
+ if (Forms.IsiOS8OrNewer)
+ {
+ var alert = UIAlertController.Create(arguments.Title, arguments.Message, UIAlertControllerStyle.Alert);
+ var oldFrame = alert.View.Frame;
+ alert.View.Frame = new RectangleF(oldFrame.X, oldFrame.Y, oldFrame.Width, oldFrame.Height - _alertPadding * 2);
+ alert.AddAction(UIAlertAction.Create(arguments.Cancel, UIAlertActionStyle.Cancel, a => arguments.SetResult(false)));
+ if (arguments.Accept != null)
+ alert.AddAction(UIAlertAction.Create(arguments.Accept, UIAlertActionStyle.Default, a => arguments.SetResult(true)));
+ var page = _modals.Any() ? _modals.Last() : Page;
+ var vc = GetRenderer(page).ViewController;
+ vc.PresentViewController(alert, true, null);
+ }
+ else
+ {
+ UIAlertView alertView;
+ if (arguments.Accept != null)
+ alertView = new UIAlertView(arguments.Title, arguments.Message, null, arguments.Cancel, arguments.Accept);
+ else
+ alertView = new UIAlertView(arguments.Title, arguments.Message, null, arguments.Cancel);
+
+ alertView.Dismissed += (o, args) => arguments.SetResult(args.ButtonIndex != 0);
+ alertView.Show();
+ }
+ });
+
+ MessagingCenter.Subscribe(this, Page.ActionSheetSignalName, (Page sender, ActionSheetArguments arguments) =>
+ {
+ if (!PageIsChildOfPlatform(sender))
+ return;
+
+ var pageRoot = sender;
+ while (!Application.IsApplicationOrNull(pageRoot.RealParent))
+ pageRoot = (Page)pageRoot.RealParent;
+ var pageRenderer = GetRenderer(pageRoot);
+
+ if (Forms.IsiOS8OrNewer)
+ {
+ var alert = UIAlertController.Create(arguments.Title, null, UIAlertControllerStyle.ActionSheet);
+
+ if (arguments.Cancel != null)
+ {
+ alert.AddAction(UIAlertAction.Create(arguments.Cancel, UIAlertActionStyle.Cancel, a => arguments.SetResult(arguments.Cancel)));
+ }
+
+ if (arguments.Destruction != null)
+ {
+ alert.AddAction(UIAlertAction.Create(arguments.Destruction, UIAlertActionStyle.Destructive, a => arguments.SetResult(arguments.Destruction)));
+ }
+
+ foreach (var label in arguments.Buttons)
+ {
+ if (label == null)
+ continue;
+
+ var blabel = label;
+ alert.AddAction(UIAlertAction.Create(blabel, UIAlertActionStyle.Default, a => arguments.SetResult(blabel)));
+ }
+
+ if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad)
+ {
+ UIDevice.CurrentDevice.BeginGeneratingDeviceOrientationNotifications();
+ var observer = NSNotificationCenter.DefaultCenter.AddObserver(UIDevice.OrientationDidChangeNotification,
+ n => { alert.PopoverPresentationController.SourceRect = pageRenderer.ViewController.View.Bounds; });
+
+ arguments.Result.Task.ContinueWith(t =>
+ {
+ NSNotificationCenter.DefaultCenter.RemoveObserver(observer);
+ UIDevice.CurrentDevice.EndGeneratingDeviceOrientationNotifications();
+ }, TaskScheduler.FromCurrentSynchronizationContext());
+
+ alert.PopoverPresentationController.SourceView = pageRenderer.ViewController.View;
+ alert.PopoverPresentationController.SourceRect = pageRenderer.ViewController.View.Bounds;
+ alert.PopoverPresentationController.PermittedArrowDirections = 0; // No arrow
+ }
+
+ pageRenderer.ViewController.PresentViewController(alert, true, null);
+ }
+ else
+ {
+ var actionSheet = new UIActionSheet(arguments.Title, null, arguments.Cancel, arguments.Destruction, arguments.Buttons.ToArray());
+
+ actionSheet.ShowInView(pageRenderer.NativeView);
+
+ actionSheet.Clicked += (o, args) =>
+ {
+ string title = null;
+ if (args.ButtonIndex != -1)
+ title = actionSheet.ButtonTitle(args.ButtonIndex);
+
+ // iOS 8 always calls WillDismiss twice, once with the real result, and again with -1.
+ arguments.Result.TrySetResult(title);
+ };
+ }
+ });
+ }
+
+ internal UIViewController ViewController
+ {
+ get { return _renderer; }
+ }
+
+ Page Page { get; set; }
+
+ Application TargetApplication
+ {
+ get
+ {
+ if (Page == null)
+ return null;
+ return Page.RealParent as Application;
+ }
+ }
+
+ void IDisposable.Dispose()
+ {
+ if (_disposed)
+ return;
+ _disposed = true;
+
+ Page.DescendantRemoved -= HandleChildRemoved;
+ MessagingCenter.Unsubscribe<Page, ActionSheetArguments>(this, Page.ActionSheetSignalName);
+ MessagingCenter.Unsubscribe<Page, AlertArguments>(this, Page.AlertSignalName);
+ MessagingCenter.Unsubscribe<Page, bool>(this, Page.BusySetSignalName);
+
+ DisposeModelAndChildrenRenderers(Page);
+ foreach (var modal in _modals)
+ DisposeModelAndChildrenRenderers(modal);
+
+ _renderer.Dispose();
+ }
+
+ void INavigation.InsertPageBefore(Page page, Page before)
+ {
+ throw new InvalidOperationException("InsertPageBefore is not supported globally on iOS, please use a NavigationPage.");
+ }
+
+ IReadOnlyList<Page> INavigation.ModalStack
+ {
+ get { return _modals; }
+ }
+
+ IReadOnlyList<Page> INavigation.NavigationStack
+ {
+ get { return new List<Page>(); }
+ }
+
+ Task<Page> INavigation.PopAsync()
+ {
+ return ((INavigation)this).PopAsync(true);
+ }
+
+ Task<Page> INavigation.PopAsync(bool animated)
+ {
+ throw new InvalidOperationException("PopAsync is not supported globally on iOS, please use a NavigationPage.");
+ }
+
+ Task<Page> INavigation.PopModalAsync()
+ {
+ return ((INavigation)this).PopModalAsync(true);
+ }
+
+ async Task<Page> INavigation.PopModalAsync(bool animated)
+ {
+ var modal = _modals.Last();
+ _modals.Remove(modal);
+ modal.DescendantRemoved -= HandleChildRemoved;
+
+ var controller = GetRenderer(modal) as UIViewController;
+
+ if (_modals.Count >= 1 && controller != null)
+ await controller.DismissViewControllerAsync(animated);
+ else
+ await _renderer.DismissViewControllerAsync(animated);
+
+ DisposeModelAndChildrenRenderers(modal);
+
+ return modal;
+ }
+
+ Task INavigation.PopToRootAsync()
+ {
+ return ((INavigation)this).PopToRootAsync(true);
+ }
+
+ Task INavigation.PopToRootAsync(bool animated)
+ {
+ throw new InvalidOperationException("PopToRootAsync is not supported globally on iOS, please use a NavigationPage.");
+ }
+
+ Task INavigation.PushAsync(Page root)
+ {
+ return ((INavigation)this).PushAsync(root, true);
+ }
+
+ Task INavigation.PushAsync(Page root, bool animated)
+ {
+ throw new InvalidOperationException("PushAsync is not supported globally on iOS, please use a NavigationPage.");
+ }
+
+ Task INavigation.PushModalAsync(Page modal)
+ {
+ return ((INavigation)this).PushModalAsync(modal, true);
+ }
+
+ Task INavigation.PushModalAsync(Page modal, bool animated)
+ {
+ _modals.Add(modal);
+ modal.Platform = this;
+
+ modal.DescendantRemoved += HandleChildRemoved;
+
+ if (_appeared)
+ return PresentModal(modal, _animateModals && animated);
+ return Task.FromResult<object>(null);
+ }
+
+ void INavigation.RemovePage(Page page)
+ {
+ throw new InvalidOperationException("RemovePage is not supported globally on iOS, please use a NavigationPage.");
+ }
+
+ SizeRequest IPlatform.GetNativeSize(VisualElement view, double widthConstraint, double heightConstraint)
+ {
+ var renderView = GetRenderer(view);
+ if (renderView == null || renderView.NativeView == null)
+ return new SizeRequest(Size.Zero);
+
+ return renderView.GetDesiredSize(widthConstraint, heightConstraint);
+ }
+
+ public static IVisualElementRenderer CreateRenderer(VisualElement element)
+ {
+ var t = element.GetType();
+ var renderer = Registrar.Registered.GetHandler<IVisualElementRenderer>(t) ?? new DefaultRenderer();
+ renderer.SetElement(element);
+ return renderer;
+ }
+
+ public static IVisualElementRenderer GetRenderer(VisualElement bindable)
+ {
+ return (IVisualElementRenderer)bindable.GetValue(RendererProperty);
+ }
+
+ public static void SetRenderer(VisualElement bindable, IVisualElementRenderer value)
+ {
+ bindable.SetValue(RendererProperty, value);
+ }
+
+ protected override void OnBindingContextChanged()
+ {
+ SetInheritedBindingContext(Page, BindingContext);
+
+ base.OnBindingContextChanged();
+ }
+
+ internal void DidAppear()
+ {
+ _animateModals = false;
+ TargetApplication.NavigationProxy.Inner = this;
+ _animateModals = true;
+ }
+
+ internal void DisposeModelAndChildrenRenderers(Element view)
+ {
+ IVisualElementRenderer renderer;
+ foreach (VisualElement child in view.Descendants())
+ {
+ renderer = GetRenderer(child);
+ child.ClearValue(RendererProperty);
+
+ if (renderer != null)
+ {
+ renderer.NativeView.RemoveFromSuperview();
+ renderer.Dispose();
+ }
+ }
+
+ renderer = GetRenderer((VisualElement)view);
+ if (renderer != null)
+ {
+ if (renderer.ViewController != null)
+ {
+ var modalWrapper = renderer.ViewController.ParentViewController as ModalWrapper;
+ if (modalWrapper != null)
+ modalWrapper.Dispose();
+ }
+
+ renderer.NativeView.RemoveFromSuperview();
+ renderer.Dispose();
+ }
+ view.ClearValue(RendererProperty);
+ }
+
+ internal void DisposeRendererAndChildren(IVisualElementRenderer rendererToRemove)
+ {
+ if (rendererToRemove == null)
+ return;
+
+ if (rendererToRemove.Element != null && GetRenderer(rendererToRemove.Element) == rendererToRemove)
+ rendererToRemove.Element.ClearValue(RendererProperty);
+
+ var subviews = rendererToRemove.NativeView.Subviews;
+ for (var i = 0; i < subviews.Length; i++)
+ {
+ var childRenderer = subviews[i] as IVisualElementRenderer;
+ if (childRenderer != null)
+ DisposeRendererAndChildren(childRenderer);
+ }
+
+ rendererToRemove.NativeView.RemoveFromSuperview();
+ rendererToRemove.Dispose();
+ }
+
+ internal void LayoutSubviews()
+ {
+ if (Page == null)
+ return;
+
+ var rootRenderer = GetRenderer(Page);
+
+ if (rootRenderer == null)
+ return;
+
+ rootRenderer.SetElementSize(new Size(_renderer.View.Bounds.Width, _renderer.View.Bounds.Height));
+ }
+
+ internal void SetPage(Page newRoot)
+ {
+ if (newRoot == null)
+ return;
+ if (Page != null)
+ throw new NotImplementedException();
+ Page = newRoot;
+
+ if (_appeared == false)
+ return;
+
+ Page.Platform = this;
+ AddChild(Page);
+
+ Page.DescendantRemoved += HandleChildRemoved;
+
+ TargetApplication.NavigationProxy.Inner = this;
+ }
+
+ internal void WillAppear()
+ {
+ if (_appeared)
+ return;
+
+ _renderer.View.BackgroundColor = UIColor.White;
+ _renderer.View.ContentMode = UIViewContentMode.Redraw;
+
+ Page.Platform = this;
+ AddChild(Page);
+
+ Page.DescendantRemoved += HandleChildRemoved;
+
+ _appeared = true;
+ }
+
+ void AddChild(VisualElement view)
+ {
+ if (!Application.IsApplicationOrNull(view.RealParent))
+ Console.Error.WriteLine("Tried to add parented view to canvas directly");
+
+ if (GetRenderer(view) == null)
+ {
+ var viewRenderer = CreateRenderer(view);
+ SetRenderer(view, viewRenderer);
+
+ _renderer.View.AddSubview(viewRenderer.NativeView);
+ if (viewRenderer.ViewController != null)
+ _renderer.AddChildViewController(viewRenderer.ViewController);
+ viewRenderer.NativeView.Frame = new RectangleF(0, 0, _renderer.View.Bounds.Width, _renderer.View.Bounds.Height);
+ viewRenderer.SetElementSize(new Size(_renderer.View.Bounds.Width, _renderer.View.Bounds.Height));
+ }
+ else
+ Console.Error.WriteLine("Potential view double add");
+ }
+
+ void HandleChildRemoved(object sender, ElementEventArgs e)
+ {
+ var view = e.Element;
+ DisposeModelAndChildrenRenderers(view);
+ }
+
+ bool PageIsChildOfPlatform(Page page)
+ {
+ while (!Application.IsApplicationOrNull(page.RealParent))
+ page = (Page)page.RealParent;
+
+ return Page == page || _modals.Contains(page);
+ }
+
+ async Task PresentModal(Page modal, bool animated)
+ {
+ var modalRenderer = GetRenderer(modal);
+ if (modalRenderer == null)
+ {
+ modalRenderer = CreateRenderer(modal);
+ SetRenderer(modal, modalRenderer);
+ }
+
+ var wrapper = new ModalWrapper(modalRenderer);
+
+ if (_modals.Count > 1)
+ {
+ var topPage = _modals[_modals.Count - 2];
+ var controller = GetRenderer(topPage) as UIViewController;
+ if (controller != null)
+ {
+ await controller.PresentViewControllerAsync(wrapper, animated);
+ await Task.Delay(5);
+ return;
+ }
+ }
+
+ // One might wonder why these delays are here... well thats a great question. It turns out iOS will claim the
+ // presentation is complete before it really is. It does not however inform you when it is really done (and thus
+ // would be safe to dismiss the VC). Fortunately this is almost never an issue
+ await _renderer.PresentViewControllerAsync(wrapper, animated);
+ await Task.Delay(5);
+ }
+
+ internal class DefaultRenderer : VisualElementRenderer<VisualElement>
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/PlatformEffect.cs b/Xamarin.Forms.Platform.iOS/PlatformEffect.cs
new file mode 100644
index 00000000..436ef6d7
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/PlatformEffect.cs
@@ -0,0 +1,14 @@
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public abstract class PlatformEffect : PlatformEffect<UIView, UIView>
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/PlatformRenderer.cs b/Xamarin.Forms.Platform.iOS/PlatformRenderer.cs
new file mode 100644
index 00000000..43534b2b
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/PlatformRenderer.cs
@@ -0,0 +1,85 @@
+using System;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ internal class ModalWrapper : UIViewController
+ {
+ IVisualElementRenderer _modal;
+
+ internal ModalWrapper(IVisualElementRenderer modal)
+ {
+ _modal = modal;
+
+ View.BackgroundColor = UIColor.White;
+ View.AddSubview(modal.ViewController.View);
+ AddChildViewController(modal.ViewController);
+
+ modal.ViewController.DidMoveToParentViewController(this);
+ }
+
+ public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
+ {
+ return UIInterfaceOrientationMask.All;
+ }
+
+ public override void ViewDidLayoutSubviews()
+ {
+ base.ViewDidLayoutSubviews();
+ if (_modal != null)
+ _modal.SetElementSize(new Size(View.Bounds.Width, View.Bounds.Height));
+ }
+
+ public override void ViewWillAppear(bool animated)
+ {
+ View.BackgroundColor = UIColor.White;
+ base.ViewWillAppear(animated);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ _modal = null;
+ base.Dispose(disposing);
+ }
+ }
+
+ internal class PlatformRenderer : UIViewController
+ {
+ internal PlatformRenderer(Platform platform)
+ {
+ Platform = platform;
+ }
+
+ public Platform Platform { get; set; }
+
+ public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
+ {
+ return UIInterfaceOrientationMask.All;
+ }
+
+ public override void ViewDidAppear(bool animated)
+ {
+ Platform.DidAppear();
+ base.ViewDidAppear(animated);
+ }
+
+ public override void ViewDidLayoutSubviews()
+ {
+ base.ViewDidLayoutSubviews();
+ Platform.LayoutSubviews();
+ }
+
+ public override void ViewWillAppear(bool animated)
+ {
+ View.BackgroundColor = UIColor.White;
+ Platform.WillAppear();
+ base.ViewWillAppear(animated);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Properties/AssemblyInfo.cs b/Xamarin.Forms.Platform.iOS/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..8ebe9ba1
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Properties/AssemblyInfo.cs
@@ -0,0 +1,69 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.iOS;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+[assembly: AssemblyTitle("Xamarin.Forms.Platform.iOS")]
+[assembly: AssemblyDescription("iOS Backend for Xamarin.Forms")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCulture("")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
+[assembly: ExportRenderer(typeof(BoxView), typeof(BoxRenderer))]
+[assembly: ExportRenderer(typeof(Entry), typeof(EntryRenderer))]
+[assembly: ExportRenderer(typeof(Editor), typeof(EditorRenderer))]
+[assembly: ExportRenderer(typeof(Label), typeof(LabelRenderer))]
+[assembly: ExportRenderer(typeof(Image), typeof(ImageRenderer))]
+[assembly: ExportRenderer(typeof(Button), typeof(ButtonRenderer))]
+[assembly: ExportRenderer(typeof(TableView), typeof(TableViewRenderer))]
+[assembly: ExportRenderer(typeof(Slider), typeof(SliderRenderer))]
+[assembly: ExportRenderer(typeof(WebView), typeof(WebViewRenderer))]
+[assembly: ExportRenderer(typeof(SearchBar), typeof(SearchBarRenderer))]
+[assembly: ExportRenderer(typeof(Switch), typeof(SwitchRenderer))]
+[assembly: ExportRenderer(typeof(DatePicker), typeof(DatePickerRenderer))]
+[assembly: ExportRenderer(typeof(TimePicker), typeof(TimePickerRenderer))]
+[assembly: ExportRenderer(typeof(Picker), typeof(PickerRenderer))]
+[assembly: ExportRenderer(typeof(Stepper), typeof(StepperRenderer))]
+[assembly: ExportRenderer(typeof(ProgressBar), typeof(ProgressBarRenderer))]
+[assembly: ExportRenderer(typeof(ScrollView), typeof(ScrollViewRenderer))]
+[assembly: ExportRenderer(typeof(Toolbar), typeof(ToolbarRenderer))]
+[assembly: ExportRenderer(typeof(ActivityIndicator), typeof(ActivityIndicatorRenderer))]
+[assembly: ExportRenderer(typeof(Frame), typeof(FrameRenderer))]
+[assembly: ExportRenderer(typeof(NavigationMenu), typeof(NavigationMenuRenderer))]
+[assembly: ExportRenderer(typeof(ListView), typeof(ListViewRenderer))]
+[assembly: ExportRenderer(typeof(CarouselView), typeof(CarouselViewRenderer))]
+[assembly: ExportRenderer(typeof(OpenGLView), typeof(OpenGLViewRenderer))]
+[assembly: ExportRenderer(typeof(NativeViewWrapper), typeof(NativeViewWrapperRenderer))]
+[assembly: ExportRenderer(typeof(TabbedPage), typeof(TabbedRenderer))]
+[assembly: ExportRenderer(typeof(NavigationPage), typeof(NavigationRenderer))]
+[assembly: ExportRenderer(typeof(CarouselPage), typeof(CarouselPageRenderer))]
+[assembly: ExportRenderer(typeof(Page), typeof(PageRenderer))]
+[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(PhoneMasterDetailRenderer), UIUserInterfaceIdiom.Phone)]
+[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(TabletMasterDetailRenderer), UIUserInterfaceIdiom.Pad)]
+[assembly: ExportCell(typeof(Cell), typeof(CellRenderer))]
+[assembly: ExportCell(typeof(ImageCell), typeof(ImageCellRenderer))]
+[assembly: ExportCell(typeof(EntryCell), typeof(EntryCellRenderer))]
+[assembly: ExportCell(typeof(TextCell), typeof(TextCellRenderer))]
+[assembly: ExportCell(typeof(ViewCell), typeof(ViewCellRenderer))]
+[assembly: ExportCell(typeof(SwitchCell), typeof(SwitchCellRenderer))]
+[assembly: ExportImageSourceHandler(typeof(FileImageSource), typeof(FileImageSourceHandler))]
+[assembly: ExportImageSourceHandler(typeof(StreamImageSource), typeof(StreamImagesourceHandler))]
+[assembly: ExportImageSourceHandler(typeof(UriImageSource), typeof(ImageLoaderSourceHandler))]
+[assembly: InternalsVisibleTo("iOSUnitTests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Platform")]
+[assembly: Xamarin.Forms.Dependency(typeof(Deserializer))]
+[assembly: Xamarin.Forms.Dependency(typeof(ResourcesProvider))]
+[assembly: Preserve] \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/RendererFactory.cs b/Xamarin.Forms.Platform.iOS/RendererFactory.cs
new file mode 100644
index 00000000..ff37905a
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/RendererFactory.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public static class RendererFactory
+ {
+ [Obsolete("Use Platform.CreateRenderer")]
+ public static IVisualElementRenderer GetRenderer(VisualElement view)
+ {
+ return Platform.CreateRenderer(view);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/RendererPool.cs b/Xamarin.Forms.Platform.iOS/RendererPool.cs
new file mode 100644
index 00000000..25df358d
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/RendererPool.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public sealed class RendererPool
+ {
+ readonly Dictionary<Type, Stack<IVisualElementRenderer>> _freeRenderers = new Dictionary<Type, Stack<IVisualElementRenderer>>();
+
+ readonly VisualElement _oldElement;
+
+ readonly IVisualElementRenderer _parent;
+
+ public RendererPool(IVisualElementRenderer renderer, VisualElement oldElement)
+ {
+ if (renderer == null)
+ throw new ArgumentNullException("renderer");
+
+ if (oldElement == null)
+ throw new ArgumentNullException("oldElement");
+
+ _oldElement = oldElement;
+ _parent = renderer;
+ }
+
+ public IVisualElementRenderer GetFreeRenderer(VisualElement view)
+ {
+ if (view == null)
+ throw new ArgumentNullException("view");
+
+ var rendererType = Registrar.Registered.GetHandlerType(view.GetType()) ?? typeof(ViewRenderer);
+
+ Stack<IVisualElementRenderer> renderers;
+ if (!_freeRenderers.TryGetValue(rendererType, out renderers) || renderers.Count == 0)
+ return null;
+
+ var renderer = renderers.Pop();
+ renderer.SetElement(view);
+ return renderer;
+ }
+
+ public void UpdateNewElement(VisualElement newElement)
+ {
+ if (newElement == null)
+ throw new ArgumentNullException("newElement");
+
+ var sameChildrenTypes = true;
+
+ var oldChildren = _oldElement.LogicalChildren;
+ var newChildren = newElement.LogicalChildren;
+
+ if (oldChildren.Count == newChildren.Count)
+ {
+ for (var i = 0; i < oldChildren.Count; i++)
+ {
+ if (oldChildren[i].GetType() != newChildren[i].GetType())
+ {
+ sameChildrenTypes = false;
+ break;
+ }
+ }
+ }
+ else
+ sameChildrenTypes = false;
+
+ if (!sameChildrenTypes)
+ {
+ ClearRenderers(_parent);
+ FillChildrenWithRenderers(newElement);
+ }
+ else
+ UpdateRenderers(newElement);
+ }
+
+ void ClearRenderers(IVisualElementRenderer renderer)
+ {
+ if (renderer == null)
+ return;
+
+ var subviews = renderer.NativeView.Subviews;
+ for (var i = 0; i < subviews.Length; i++)
+ {
+ var childRenderer = subviews[i] as IVisualElementRenderer;
+ if (childRenderer != null)
+ {
+ PushRenderer(childRenderer);
+
+ if (ReferenceEquals(childRenderer, Platform.GetRenderer(childRenderer.Element)))
+ childRenderer.Element.ClearValue(Platform.RendererProperty);
+ }
+
+ subviews[i].RemoveFromSuperview();
+ }
+ }
+
+ void FillChildrenWithRenderers(VisualElement element)
+ {
+ foreach (var logicalChild in element.LogicalChildren)
+ {
+ var child = logicalChild as VisualElement;
+ if (child != null)
+ {
+ var renderer = GetFreeRenderer(child) ?? Platform.CreateRenderer(child);
+ Platform.SetRenderer(child, renderer);
+
+ _parent.NativeView.AddSubview(renderer.NativeView);
+ }
+ }
+ }
+
+ void PushRenderer(IVisualElementRenderer renderer)
+ {
+ var rendererType = renderer.GetType();
+
+ Stack<IVisualElementRenderer> renderers;
+ if (!_freeRenderers.TryGetValue(rendererType, out renderers))
+ _freeRenderers[rendererType] = renderers = new Stack<IVisualElementRenderer>();
+
+ renderers.Push(renderer);
+ }
+
+ void UpdateRenderers(Element newElement)
+ {
+ if (newElement.LogicalChildren.Count == 0)
+ return;
+
+ var subviews = _parent.NativeView.Subviews;
+ for (var i = 0; i < subviews.Length; i++)
+ {
+ var childRenderer = subviews[i] as IVisualElementRenderer;
+ if (childRenderer == null)
+ continue;
+
+ var x = (int)childRenderer.NativeView.Layer.ZPosition / 1000;
+ var element = newElement.LogicalChildren[x] as VisualElement;
+ if (element == null)
+ continue;
+
+ if (childRenderer.Element != null && ReferenceEquals(childRenderer, Platform.GetRenderer(childRenderer.Element)))
+ childRenderer.Element.ClearValue(Platform.RendererProperty);
+
+ childRenderer.SetElement(element);
+ Platform.SetRenderer(element, childRenderer);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/ActivityIndicatorRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/ActivityIndicatorRenderer.cs
new file mode 100644
index 00000000..0ef8741f
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/ActivityIndicatorRenderer.cs
@@ -0,0 +1,53 @@
+using System.Drawing;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class ActivityIndicatorRenderer : ViewRenderer<ActivityIndicator, UIActivityIndicatorView>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<ActivityIndicator> e)
+ {
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new UIActivityIndicatorView(RectangleF.Empty) { ActivityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray });
+ }
+
+ UpdateColor();
+ UpdateIsRunning();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == ActivityIndicator.ColorProperty.PropertyName)
+ UpdateColor();
+ else if (e.PropertyName == ActivityIndicator.IsRunningProperty.PropertyName)
+ UpdateIsRunning();
+ }
+
+ void UpdateColor()
+ {
+ Control.Color = Element.Color == Color.Default ? null : Element.Color.ToUIColor();
+ }
+
+ void UpdateIsRunning()
+ {
+ if (Element.IsRunning)
+ Control.StartAnimating();
+ else
+ Control.StopAnimating();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/AlignmentExtensions.cs b/Xamarin.Forms.Platform.iOS/Renderers/AlignmentExtensions.cs
new file mode 100644
index 00000000..01d0bf66
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/AlignmentExtensions.cs
@@ -0,0 +1,25 @@
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ internal static class AlignmentExtensions
+ {
+ internal static UITextAlignment ToNativeTextAlignment(this TextAlignment alignment)
+ {
+ switch (alignment)
+ {
+ case TextAlignment.Center:
+ return UITextAlignment.Center;
+ case TextAlignment.End:
+ return UITextAlignment.Right;
+ default:
+ return UITextAlignment.Left;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/BoxRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/BoxRenderer.cs
new file mode 100644
index 00000000..f60ed6c1
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/BoxRenderer.cs
@@ -0,0 +1,78 @@
+using System.ComponentModel;
+using System.Drawing;
+#if __UNIFIED__
+using UIKit;
+using CoreGraphics;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.CoreGraphics;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class BoxRenderer : VisualElementRenderer<BoxView>
+ {
+ UIColor _colorToRenderer;
+
+ SizeF _previousSize;
+
+ public override void Draw(RectangleF rect)
+ {
+ using(var context = UIGraphics.GetCurrentContext())
+ {
+ _colorToRenderer.SetFill();
+ context.FillRect(rect);
+ }
+ base.Draw(rect);
+
+ _previousSize = Bounds.Size;
+ }
+
+ public override void LayoutSubviews()
+ {
+ if (_previousSize != Bounds.Size)
+ SetNeedsDisplay();
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e)
+ {
+ base.OnElementChanged(e);
+
+ if (Element != null)
+ SetBackgroundColor(Element.BackgroundColor);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+ if (e.PropertyName == BoxView.ColorProperty.PropertyName)
+ SetBackgroundColor(Element.BackgroundColor);
+ else if (e.PropertyName == VisualElement.IsVisibleProperty.PropertyName && Element.IsVisible)
+ SetNeedsDisplay();
+ }
+
+ protected override void SetBackgroundColor(Color color)
+ {
+ if (Element == null)
+ return;
+
+ var elementColor = Element.Color;
+ if (!elementColor.IsDefault)
+ _colorToRenderer = elementColor.ToUIColor();
+ else
+ _colorToRenderer = color.ToUIColor();
+
+ SetNeedsDisplay();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/ButtonRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/ButtonRenderer.cs
new file mode 100644
index 00000000..3fa84d1d
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/ButtonRenderer.cs
@@ -0,0 +1,190 @@
+using System;
+using System.Drawing;
+using System.Linq;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+using CoreGraphics;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.CoreGraphics;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class ButtonRenderer : ViewRenderer<Button, UIButton>
+ {
+ UIColor _buttonTextColorDefaultDisabled;
+ UIColor _buttonTextColorDefaultHighlighted;
+ UIColor _buttonTextColorDefaultNormal;
+
+ public override SizeF SizeThatFits(SizeF size)
+ {
+ var result = base.SizeThatFits(size);
+ result.Height = 44; // Apple docs
+ //Compensate for the insets
+ if (!Control.ImageView.Hidden)
+ result.Width += 10;
+ return result;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (Control != null)
+ Control.TouchUpInside -= OnButtonTouchUpInside;
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new UIButton(UIButtonType.RoundedRect));
+
+ _buttonTextColorDefaultNormal = Control.TitleColor(UIControlState.Normal);
+ _buttonTextColorDefaultHighlighted = Control.TitleColor(UIControlState.Highlighted);
+ _buttonTextColorDefaultDisabled = Control.TitleColor(UIControlState.Disabled);
+
+ Control.TouchUpInside += OnButtonTouchUpInside;
+ }
+
+ UpdateText();
+ UpdateFont();
+ UpdateBorder();
+ UpdateImage();
+ UpdateTextColor();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Button.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Button.TextColorProperty.PropertyName)
+ UpdateTextColor();
+ else if (e.PropertyName == Button.FontProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Button.BorderWidthProperty.PropertyName || e.PropertyName == Button.BorderRadiusProperty.PropertyName || e.PropertyName == Button.BorderColorProperty.PropertyName)
+ UpdateBorder();
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackgroundVisibility();
+ else if (e.PropertyName == Button.ImageProperty.PropertyName)
+ UpdateImage();
+ }
+
+ void OnButtonTouchUpInside(object sender, EventArgs eventArgs)
+ {
+ if (Element != null)
+ ((IButtonController)Element).SendClicked();
+ }
+
+ void UpdateBackgroundVisibility()
+ {
+ if (Forms.IsiOS7OrNewer)
+ return;
+
+ var model = Element;
+ var shouldDrawImage = model.BackgroundColor == Color.Default;
+
+ foreach (var control in Control.Subviews.Where(sv => !(sv is UILabel)))
+ control.Alpha = shouldDrawImage ? 1.0f : 0.0f;
+ }
+
+ void UpdateBorder()
+ {
+ var uiButton = Control;
+ var button = Element;
+
+ if (button.BorderColor != Color.Default)
+ uiButton.Layer.BorderColor = button.BorderColor.ToCGColor();
+
+ uiButton.Layer.BorderWidth = (float)button.BorderWidth;
+ uiButton.Layer.CornerRadius = button.BorderRadius;
+
+ UpdateBackgroundVisibility();
+ }
+
+ void UpdateFont()
+ {
+ Control.TitleLabel.Font = Element.ToUIFont();
+ }
+
+ async void UpdateImage()
+ {
+ IImageSourceHandler handler;
+ var source = Element.Image;
+ if (source != null && (handler = Registrar.Registered.GetHandler<IImageSourceHandler>(source.GetType())) != null)
+ {
+ UIImage uiimage;
+ try
+ {
+ uiimage = await handler.LoadImageAsync(source, scale: (float)UIScreen.MainScreen.Scale);
+ }
+ catch (OperationCanceledException)
+ {
+ uiimage = null;
+ }
+ var button = Control;
+ if (button != null && uiimage != null)
+ {
+ if (Forms.IsiOS7OrNewer)
+ button.SetImage(uiimage.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal), UIControlState.Normal);
+ else
+ button.SetImage(uiimage, UIControlState.Normal);
+ button.ImageView.ContentMode = UIViewContentMode.ScaleAspectFit;
+
+ Control.ImageEdgeInsets = new UIEdgeInsets(0, 0, 0, 10);
+ Control.TitleEdgeInsets = new UIEdgeInsets(0, 10, 0, 0);
+ }
+ }
+ else
+ {
+ Control.SetImage(null, UIControlState.Normal);
+ Control.ImageEdgeInsets = new UIEdgeInsets(0, 0, 0, 0);
+ Control.TitleEdgeInsets = new UIEdgeInsets(0, 0, 0, 0);
+ }
+ ((IVisualElementController)Element).NativeSizeChanged();
+ }
+
+ void UpdateText()
+ {
+ Control.SetTitle(Element.Text, UIControlState.Normal);
+ }
+
+ void UpdateTextColor()
+ {
+ if (Element.TextColor == Color.Default)
+ {
+ Control.SetTitleColor(_buttonTextColorDefaultNormal, UIControlState.Normal);
+ Control.SetTitleColor(_buttonTextColorDefaultHighlighted, UIControlState.Highlighted);
+ Control.SetTitleColor(_buttonTextColorDefaultDisabled, UIControlState.Disabled);
+ }
+ else
+ {
+ Control.SetTitleColor(Element.TextColor.ToUIColor(), UIControlState.Normal);
+ Control.SetTitleColor(Element.TextColor.ToUIColor(), UIControlState.Highlighted);
+ Control.SetTitleColor(_buttonTextColorDefaultDisabled, UIControlState.Disabled);
+
+ if (Forms.IsiOS7OrNewer)
+ Control.TintColor = Element.TextColor.ToUIColor();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/CarouselPageRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/CarouselPageRenderer.cs
new file mode 100644
index 00000000..16e97cd2
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/CarouselPageRenderer.cs
@@ -0,0 +1,395 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Drawing;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat = System.Single;
+using nint = System.Int32;
+using nuint = System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class CarouselPageRenderer : UIViewController, IVisualElementRenderer
+ {
+ bool _appeared;
+ Dictionary<Page, UIView> _containerMap;
+ bool _disposed;
+ EventTracker _events;
+ bool _ignoreNativeScrolling;
+ UIScrollView _scrollView;
+ VisualElementTracker _tracker;
+
+ public CarouselPageRenderer()
+ {
+ if (!Forms.IsiOS7OrNewer)
+ WantsFullScreenLayout = true;
+ }
+
+ protected CarouselPage Carousel
+ {
+ get { return (CarouselPage)Element; }
+ }
+
+ protected int SelectedIndex
+ {
+ get { return (int)(_scrollView.ContentOffset.X / _scrollView.Frame.Width); }
+ set { ScrollToPage(value); }
+ }
+
+ public VisualElement Element { get; private set; }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return NativeView.GetSizeRequest(widthConstraint, heightConstraint);
+ }
+
+ public UIView NativeView
+ {
+ get { return View; }
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ VisualElement oldElement = Element;
+ Element = element;
+ _containerMap = new Dictionary<Page, UIView>();
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+
+ if (element != null)
+ element.SendViewInitialized(NativeView);
+ }
+
+ public void SetElementSize(Size size)
+ {
+ Element.Layout(new Rectangle(Element.X, Element.Y, size.Width, size.Height));
+ }
+
+ public UIViewController ViewController
+ {
+ get { return this; }
+ }
+
+ public override void DidRotate(UIInterfaceOrientation fromInterfaceOrientation)
+ {
+ _ignoreNativeScrolling = false;
+ View.SetNeedsLayout();
+ }
+
+ public override void ViewDidAppear(bool animated)
+ {
+ base.ViewDidAppear(animated);
+
+ if (_appeared || _disposed)
+ return;
+
+ _appeared = true;
+ Carousel.SendAppearing();
+ }
+
+ public override void ViewDidDisappear(bool animated)
+ {
+ base.ViewDidDisappear(animated);
+
+ if (!_appeared || _disposed)
+ return;
+
+ _appeared = false;
+ Carousel.SendDisappearing();
+ }
+
+ public override void ViewDidLayoutSubviews()
+ {
+ base.ViewDidLayoutSubviews();
+
+ View.Frame = View.Superview.Bounds;
+ _scrollView.Frame = View.Bounds;
+
+ PositionChildren();
+ UpdateCurrentPage(false);
+ }
+
+ public override void ViewDidLoad()
+ {
+ base.ViewDidLoad();
+
+ _tracker = new VisualElementTracker(this);
+ _events = new EventTracker(this);
+ _events.LoadEvents(View);
+
+ _scrollView = new UIScrollView { ShowsHorizontalScrollIndicator = false };
+
+ _scrollView.DecelerationEnded += OnDecelerationEnded;
+
+ UpdateBackground();
+
+ View.Add(_scrollView);
+
+ for (var i = 0; i < Element.LogicalChildren.Count; i++)
+ {
+ Element element = Element.LogicalChildren[i];
+ var child = element as ContentPage;
+ if (child != null)
+ InsertPage(child, i);
+ }
+
+ PositionChildren();
+
+ Carousel.PropertyChanged += OnPropertyChanged;
+ Carousel.PagesChanged += OnPagesChanged;
+ }
+
+ public override void ViewDidUnload()
+ {
+ base.ViewDidUnload();
+
+ if (_scrollView != null)
+ _scrollView.DecelerationEnded -= OnDecelerationEnded;
+
+ if (Carousel != null)
+ {
+ Carousel.PropertyChanged -= OnPropertyChanged;
+ Carousel.PagesChanged -= OnPagesChanged;
+ }
+ }
+
+ public override void WillRotate(UIInterfaceOrientation toInterfaceOrientation, double duration)
+ {
+ _ignoreNativeScrolling = true;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ if (_scrollView != null)
+ _scrollView.DecelerationEnded -= OnDecelerationEnded;
+
+ if (Carousel != null)
+ {
+ Carousel.PropertyChanged -= OnPropertyChanged;
+ Carousel.PagesChanged -= OnPagesChanged;
+ }
+
+ Platform.SetRenderer(Element, null);
+
+ Clear();
+
+ if (_scrollView != null)
+ {
+ _scrollView.DecelerationEnded -= OnDecelerationEnded;
+ _scrollView.RemoveFromSuperview();
+ _scrollView = null;
+ }
+
+ if (_appeared)
+ {
+ _appeared = false;
+ Carousel.SendDisappearing();
+ }
+
+ if (_events != null)
+ {
+ _events.Dispose();
+ _events = null;
+ }
+
+ if (_tracker != null)
+ {
+ _tracker.Dispose();
+ _tracker = null;
+ }
+
+ Element = null;
+ _disposed = true;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ EventHandler<VisualElementChangedEventArgs> changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ void Clear()
+ {
+ foreach (KeyValuePair<Page, UIView> kvp in _containerMap)
+ {
+ kvp.Value.RemoveFromSuperview();
+ IVisualElementRenderer renderer = Platform.GetRenderer(kvp.Key);
+ if (renderer != null)
+ {
+ renderer.ViewController.RemoveFromParentViewController();
+ renderer.NativeView.RemoveFromSuperview();
+ Platform.SetRenderer(kvp.Key, null);
+ }
+ }
+ _containerMap.Clear();
+ }
+
+ void InsertPage(ContentPage page, int index)
+ {
+ IVisualElementRenderer renderer = Platform.GetRenderer(page);
+ if (renderer == null)
+ {
+ renderer = Platform.CreateRenderer(page);
+ Platform.SetRenderer(page, renderer);
+ }
+
+ UIView container = new PageContainer(page);
+ container.AddSubview(renderer.NativeView);
+ _containerMap[page] = container;
+
+ AddChildViewController(renderer.ViewController);
+ _scrollView.InsertSubview(container, index);
+
+ if ((index == 0 && SelectedIndex == 0) || (index < SelectedIndex))
+ ScrollToPage(SelectedIndex + 1, false);
+ }
+
+ void OnDecelerationEnded(object sender, EventArgs eventArgs)
+ {
+ if (_ignoreNativeScrolling || SelectedIndex >= Element.LogicalChildren.Count)
+ return;
+
+ Carousel.CurrentPage = (ContentPage)Element.LogicalChildren[SelectedIndex];
+ }
+
+ void OnPagesChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ _ignoreNativeScrolling = true;
+
+ NotifyCollectionChangedAction action = e.Apply((o, i, c) => InsertPage((ContentPage)o, i), (o, i) => RemovePage((ContentPage)o, i), Reset);
+ PositionChildren();
+
+ _ignoreNativeScrolling = false;
+
+ if (action == NotifyCollectionChangedAction.Reset)
+ {
+ int index = Carousel.CurrentPage != null ? CarouselPage.GetIndex(Carousel.CurrentPage) : 0;
+ if (index < 0)
+ index = 0;
+
+ ScrollToPage(index);
+ }
+ }
+
+ void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "CurrentPage")
+ UpdateCurrentPage();
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackground();
+ else if (e.PropertyName == Page.BackgroundImageProperty.PropertyName)
+ UpdateBackground();
+ }
+
+ void PositionChildren()
+ {
+ nfloat x = 0;
+ RectangleF bounds = View.Bounds;
+ foreach (ContentPage child in ((CarouselPage)Element).Children)
+ {
+ UIView container = _containerMap[child];
+
+ container.Frame = new RectangleF(x, bounds.Y, bounds.Width, bounds.Height);
+ x += bounds.Width;
+ }
+
+ _scrollView.PagingEnabled = true;
+ _scrollView.ContentSize = new SizeF(bounds.Width * ((CarouselPage)Element).Children.Count, bounds.Height);
+ }
+
+ void RemovePage(ContentPage page, int index)
+ {
+ UIView container = _containerMap[page];
+ container.RemoveFromSuperview();
+ _containerMap.Remove(page);
+
+ IVisualElementRenderer renderer = Platform.GetRenderer(page);
+ if (renderer == null)
+ return;
+
+ renderer.ViewController.RemoveFromParentViewController();
+ renderer.NativeView.RemoveFromSuperview();
+ }
+
+ void Reset()
+ {
+ Clear();
+
+ for (var i = 0; i < Element.LogicalChildren.Count; i++)
+ {
+ Element element = Element.LogicalChildren[i];
+ var child = element as ContentPage;
+ if (child != null)
+ InsertPage(child, i);
+ }
+ }
+
+ void ScrollToPage(int index, bool animated = true)
+ {
+ if (_scrollView.ContentOffset.X == index * _scrollView.Frame.Width)
+ return;
+
+ _scrollView.SetContentOffset(new PointF(index * _scrollView.Frame.Width, 0), animated);
+ }
+
+ void UpdateBackground()
+ {
+ string bgImage = ((Page)Element).BackgroundImage;
+ if (!string.IsNullOrEmpty(bgImage))
+ {
+ View.BackgroundColor = UIColor.FromPatternImage(UIImage.FromBundle(bgImage));
+ return;
+ }
+ Color bgColor = Element.BackgroundColor;
+ if (bgColor.IsDefault)
+ View.BackgroundColor = UIColor.White;
+ else
+ View.BackgroundColor = bgColor.ToUIColor();
+ }
+
+ void UpdateCurrentPage(bool animated = true)
+ {
+ ContentPage current = Carousel.CurrentPage;
+ if (current != null)
+ ScrollToPage(CarouselPage.GetIndex(current), animated);
+ }
+
+ class PageContainer : UIView
+ {
+ public PageContainer(VisualElement element)
+ {
+ Element = element;
+ }
+
+ public VisualElement Element { get; }
+
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+
+ if (Subviews.Length > 0)
+ Subviews[0].Frame = new RectangleF(0, 0, (float)Element.Width, (float)Element.Height);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/CarouselViewRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/CarouselViewRenderer.cs
new file mode 100644
index 00000000..26ef16cc
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/CarouselViewRenderer.cs
@@ -0,0 +1,454 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ /// <summary>
+ /// UICollectionView visualizes a collection of data. UICollectionViews are created indirectly by first creating a
+ /// CarouselViewController from which the CollectionView is accessed via the CollectionView property.
+ /// The CarouselViewController functionality is exposed through a set of interfaces (aka "conforms to" in the Apple
+ /// docs).
+ /// When Xamarin exposed CarouselViewRenderer the following interfaces where implemented as virtual methods:
+ /// UICollectionViewSource
+ /// UIScrollViewDelegate
+ /// UICollectionViewDelegate Allow you to manage the selection and highlighting of items in a collection view
+ /// UICollectionViewDataSource Creation and configuration of cells and supplementary views used to display data
+ /// The interfaces only implement required method while the UICollectionView exposes optional methods via
+ /// ExportAttribute.
+ /// The C# method name may be aliased. For example, C# "GetCell" maps to obj-C "CellForItemAtIndexPath".
+ /// <seealso cref="https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICollectionView_class/" />
+ /// </summary>
+ public class CarouselViewRenderer : ViewRenderer<CarouselView, UICollectionView>
+ {
+ const int DefaultMinimumDimension = 44;
+ static readonly UIColor DefaultBackgroundColor = UIColor.White;
+
+ CarouselViewController.Layout _layout;
+ int _position;
+
+ CarouselViewController CarouselViewController { get; set; }
+
+ new UIScrollView Control
+ {
+ get
+ {
+ Initialize();
+ return base.Control;
+ }
+ }
+
+ ICarouselViewController Controller
+ {
+ get { return Element; }
+ }
+
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return Control.GetSizeRequest(widthConstraint, heightConstraint, DefaultMinimumDimension, DefaultMinimumDimension);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<CarouselView> e)
+ {
+ base.OnElementChanged(e);
+ Initialize();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "Position")
+ // not ideal; the event is raised before the animation to move completes (or even starts)
+ ScrollToPosition(Element.Position);
+
+ base.OnElementPropertyChanged(sender, e);
+ }
+
+ void Initialize()
+ {
+ // cache hit?
+ var carouselView = base.Control;
+ if (carouselView != null)
+ return;
+
+ CarouselViewController = new CarouselViewController(this, _layout = new CarouselViewController.Layout(UICollectionViewScrollDirection.Horizontal), Element.Position);
+
+ // hook up on position changed event
+ // not ideal; the event is raised upon releasing the swipe instead of animation completion
+ _layout.OnSwipeOffsetChosen += o => OnPositionChange(o);
+
+ // hook up crud events
+ Element.CollectionChanged += OnCollectionChanged;
+
+ // populate cache
+ SetNativeControl(CarouselViewController.CollectionView);
+ }
+
+ void OnCollectionChanged(object source, NotifyCollectionChangedEventArgs e)
+ {
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ CarouselViewController.ReloadData();
+
+ if (e.NewStartingIndex <= _position)
+ ShiftPosition(e.NewItems.Count);
+
+ break;
+
+ case NotifyCollectionChangedAction.Move:
+ for (var i = 0; i < e.NewItems.Count; i++)
+ {
+ CarouselViewController.MoveItem(e.OldStartingIndex + i, e.NewStartingIndex + i);
+ }
+ break;
+
+ case NotifyCollectionChangedAction.Remove:
+ if (Element.Count == 0)
+ throw new InvalidOperationException("CarouselView must retain a least one item.");
+
+ if (e.OldStartingIndex == _position)
+ {
+ CarouselViewController.DeleteItems(Enumerable.Range(e.OldStartingIndex, e.OldItems.Count));
+ if (_position == Element.Count)
+ _position--;
+ OnItemChange(_position);
+ }
+
+ else
+ {
+ CarouselViewController.ReloadData();
+
+ if (e.OldStartingIndex < _position)
+ ShiftPosition(-e.OldItems.Count);
+ }
+
+ break;
+
+ case NotifyCollectionChangedAction.Replace:
+ CarouselViewController.ReloadItems(Enumerable.Range(e.OldStartingIndex, e.OldItems.Count));
+ break;
+
+ case NotifyCollectionChangedAction.Reset:
+ CarouselViewController.ReloadData();
+ break;
+
+ default:
+ throw new Exception();
+ }
+ }
+
+ void OnItemChange(int position)
+ {
+ var item = Controller.GetItem(position);
+ Controller.SendSelectedItemChanged(item);
+ }
+
+ bool OnPositionChange(int position)
+ {
+ if (position == _position)
+ return false;
+
+ _position = position;
+
+ Controller.SendSelectedPositionChanged(position);
+ OnItemChange(position);
+ return true;
+ }
+
+ void ScrollToPosition(int position, bool animated = true)
+ {
+ if (!OnPositionChange(position))
+ return;
+
+ CarouselViewController.ScrollToPosition(position, animated);
+ }
+
+ void ShiftPosition(int offset)
+ {
+ // By default the position remains the same which causes an animation in the case
+ // of the added/removed position preceding the current position. I prefer the constructed
+ // Android behavior whereby the item remains the same and the position changes.
+ ScrollToPosition(_position + offset, false);
+ }
+ }
+
+ internal sealed class CarouselViewController : UICollectionViewController
+ {
+ readonly Dictionary<object, int> _typeIdByType;
+ UICollectionViewLayout _layout;
+ int _nextItemTypeId;
+ int _originPosition;
+
+ public Action<int> OnBind;
+ public Action<int> OnSwipeTargetChosen;
+
+ public CarouselViewController(CarouselViewRenderer renderer, UICollectionViewLayout layout, int originPosition) : base(layout)
+ {
+ Renderer = renderer;
+ _typeIdByType = new Dictionary<object, int>();
+ _nextItemTypeId = 0;
+ _layout = layout;
+ _originPosition = originPosition;
+ }
+
+ ICarouselViewController Controller
+ {
+ get { return Element; }
+ }
+
+ CarouselView Element
+ {
+ get { return Renderer.Element; }
+ }
+
+ CarouselViewRenderer Renderer { get; }
+
+ public void DeleteItems(IEnumerable<int> positions)
+ {
+ var indices = positions.Select(o => NSIndexPath.FromRowSection(o, 0)).ToArray();
+ CollectionView.DeleteItems(indices);
+ }
+
+ public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
+ {
+ var index = indexPath.Row;
+
+ if (_originPosition != 0)
+ index = _originPosition;
+
+ var item = Controller.GetItem(index);
+ var itemType = Controller.GetItemType(item);
+
+ var itemTypeId = default(int);
+ if (!_typeIdByType.TryGetValue(itemType, out itemTypeId))
+ {
+ _typeIdByType[itemType] = itemTypeId = _nextItemTypeId++;
+ CollectionView.RegisterClassForCell(typeof(Cell), itemTypeId.ToString());
+ }
+
+ var cell = (Cell)CollectionView.DequeueReusableCell(itemTypeId.ToString(), indexPath);
+ cell.Initialize(Element, itemType, item, index);
+
+ // a semantically weak approach to OnAppearing; decided not to expose as such
+ if (cell.OnBind == null)
+ cell.OnBind += o => OnBind?.Invoke(o);
+
+ return cell;
+ }
+
+ public override nint GetItemsCount(UICollectionView collectionView, nint section)
+ {
+ var result = Element.Count;
+ return result;
+ }
+
+ public void MoveItem(int oldPosition, int newPosition)
+ {
+ base.MoveItem(CollectionView, NSIndexPath.FromRowSection(oldPosition, 0), NSIndexPath.FromRowSection(newPosition, 0));
+ }
+
+ public override nint NumberOfSections(UICollectionView collectionView)
+ {
+ return 1;
+ }
+
+ public void ReloadData() => CollectionView.ReloadData();
+
+ public void ReloadItems(IEnumerable<int> positions)
+ {
+ var indices = positions.Select(o => NSIndexPath.FromRowSection(o, 0)).ToArray();
+ CollectionView.ReloadItems(indices);
+ }
+
+ public void ScrollToPosition(int position, bool animated = true)
+ {
+ CollectionView.ScrollToItem(NSIndexPath.FromRowSection(position, 0), UICollectionViewScrollPosition.CenteredHorizontally, animated);
+ }
+
+ public override void ViewDidLoad()
+ {
+ base.ViewDidLoad();
+
+ CollectionView.PagingEnabled = true;
+ CollectionView.BackgroundColor = UIColor.Clear;
+ }
+
+ public override void WillDisplayCell(UICollectionView collectionView, UICollectionViewCell cell, NSIndexPath indexPath)
+ {
+ if (_originPosition == 0)
+ return;
+
+ // Ideally position zero would not be rendered in memory however it is.
+ // Thankfully, position zero is not displyed; position originPosition is rendered and displayed.
+ ScrollToPosition(_originPosition, false);
+ _originPosition = 0;
+ }
+
+ [Export("collectionView:layout:sizeForItemAtIndexPath:")]
+ SizeF GetSizeForItem(UICollectionView collectionView, UICollectionViewLayout layout, NSIndexPath indexPath)
+ {
+ return collectionView.Frame.Size;
+ }
+
+ internal new sealed class Layout : UICollectionViewFlowLayout
+ {
+ static readonly nfloat ZeroMinimumInteritemSpacing = 0;
+ static readonly nfloat ZeroMinimumLineSpacing = 0;
+
+ int _width;
+
+ public Action<int> OnSwipeOffsetChosen;
+
+ public Layout(UICollectionViewScrollDirection scrollDirection)
+ {
+ ScrollDirection = scrollDirection;
+ MinimumInteritemSpacing = ZeroMinimumInteritemSpacing;
+ MinimumLineSpacing = ZeroMinimumLineSpacing;
+ }
+
+ public override SizeF CollectionViewContentSize
+ {
+ get
+ {
+ var result = base.CollectionViewContentSize;
+ return result;
+ }
+ }
+
+ public override UICollectionViewLayoutAttributes FinalLayoutAttributesForDisappearingItem(NSIndexPath itemIndexPath)
+ {
+ return base.FinalLayoutAttributesForDisappearingItem(itemIndexPath);
+ }
+
+ public override NSIndexPath GetTargetIndexPathForInteractivelyMovingItem(NSIndexPath previousIndexPath, PointF position)
+ {
+ var result = base.GetTargetIndexPathForInteractivelyMovingItem(previousIndexPath, position);
+ return result;
+ }
+
+ public override UICollectionViewLayoutAttributes InitialLayoutAttributesForAppearingItem(NSIndexPath itemIndexPath)
+ {
+ return base.InitialLayoutAttributesForAppearingItem(itemIndexPath);
+ }
+
+ public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect(RectangleF rect)
+ {
+ // couldn't figure a way to use these values to compute when an element appeared to disappeared. YMMV
+ var result = base.LayoutAttributesForElementsInRect(rect);
+ foreach (var item in result)
+ {
+ var index = item.IndexPath;
+ var category = item.RepresentedElementCategory;
+ var kind = item.RepresentedElementKind;
+
+ var hidden = item.Hidden;
+ var bounds = item.Bounds;
+ var frame = item.Frame;
+ var center = item.Center;
+
+ _width = (int)item.Bounds.Width;
+ }
+ return result;
+ }
+
+ public override bool ShouldInvalidateLayoutForBoundsChange(RectangleF newBounds)
+ {
+ return true;
+ }
+
+ public override PointF TargetContentOffset(PointF proposedContentOffset, PointF scrollingVelocity)
+ {
+ var result = base.TargetContentOffset(proposedContentOffset, scrollingVelocity);
+ OnSwipeOffsetChosen?.Invoke((int)result.X / _width);
+ return result;
+ }
+
+ public override PointF TargetContentOffsetForProposedContentOffset(PointF proposedContentOffset)
+ {
+ var result = base.TargetContentOffsetForProposedContentOffset(proposedContentOffset);
+ return result;
+ }
+ }
+
+ sealed class Cell : UICollectionViewCell
+ {
+ IItemViewController _controller;
+ int _position;
+ IVisualElementRenderer _renderer;
+ View _view;
+
+ public Action<int> OnBind;
+
+ [Export("initWithFrame:")]
+ internal Cell(RectangleF frame) : base(frame)
+ {
+ _position = -1;
+ }
+
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+
+ _renderer.Element.Layout(new Rectangle(0, 0, ContentView.Frame.Width, ContentView.Frame.Height));
+ }
+
+ internal void Initialize(IItemViewController controller, object itemType, object item, int position)
+ {
+ _position = position;
+
+ if (_controller == null)
+ {
+ _controller = controller;
+
+ // create view
+ _view = controller.CreateView(itemType);
+
+ // bind view
+ Bind(item, position);
+
+ // render view
+ _renderer = Platform.CreateRenderer(_view);
+ Platform.SetRenderer(_view, _renderer);
+
+ // attach view
+ var uiView = _renderer.NativeView;
+ ContentView.AddSubview(uiView);
+ }
+ else
+ Bind(item, position);
+ }
+
+ void Bind(object item, int position)
+ {
+ //if (position != this.position)
+ // controller.SendPositionDisappearing (this.position);
+
+ _position = position;
+ OnBind?.Invoke(position);
+
+ _controller.BindView(_view, item);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/DatePickerRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/DatePickerRenderer.cs
new file mode 100644
index 00000000..fd2b1549
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/DatePickerRenderer.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Drawing;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ internal class NoCaretField : UITextField
+ {
+ public NoCaretField() : base(new RectangleF())
+ {
+ }
+
+ public override RectangleF GetCaretRectForPosition(UITextPosition position)
+ {
+ return new RectangleF();
+ }
+ }
+
+ public class DatePickerRenderer : ViewRenderer<DatePicker, UITextField>
+ {
+ UIDatePicker _picker;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement == null)
+ {
+ var entry = new NoCaretField { BorderStyle = UITextBorderStyle.RoundedRect };
+
+ entry.Started += OnStarted;
+ entry.Ended += OnEnded;
+
+ _picker = new UIDatePicker { Mode = UIDatePickerMode.Date, TimeZone = new NSTimeZone("UTC") };
+
+ _picker.ValueChanged += HandleValueChanged;
+
+ var width = UIScreen.MainScreen.Bounds.Width;
+ var toolbar = new UIToolbar(new RectangleF(0, 0, width, 44)) { BarStyle = UIBarStyle.Default, Translucent = true };
+ var spacer = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);
+ var doneButton = new UIBarButtonItem(UIBarButtonSystemItem.Done, (o, a) => entry.ResignFirstResponder());
+
+ toolbar.SetItems(new[] { spacer, doneButton }, false);
+
+ entry.InputView = _picker;
+ entry.InputAccessoryView = toolbar;
+
+ SetNativeControl(entry);
+ }
+
+ if (e.NewElement != null)
+ {
+ UpdateDateFromModel(false);
+ UpdateMaximumDate();
+ UpdateMinimumDate();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == DatePicker.DateProperty.PropertyName || e.PropertyName == DatePicker.FormatProperty.PropertyName)
+ UpdateDateFromModel(true);
+ else if (e.PropertyName == DatePicker.MinimumDateProperty.PropertyName)
+ UpdateMinimumDate();
+ else if (e.PropertyName == DatePicker.MaximumDateProperty.PropertyName)
+ UpdateMaximumDate();
+ }
+
+ void HandleValueChanged(object sender, EventArgs e)
+ {
+ if (Element != null)
+ ((IElementController)Element).SetValueFromRenderer(DatePicker.DateProperty, _picker.Date.ToDateTime().Date);
+ }
+
+ void OnEnded(object sender, EventArgs eventArgs)
+ {
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ }
+
+ void OnStarted(object sender, EventArgs eventArgs)
+ {
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
+ }
+
+ void UpdateDateFromModel(bool animate)
+ {
+ if (_picker.Date.ToDateTime().Date != Element.Date.Date)
+ _picker.SetDate(Element.Date.ToNSDate(), animate);
+
+ Control.Text = Element.Date.ToString(Element.Format);
+ }
+
+ void UpdateMaximumDate()
+ {
+ _picker.MaximumDate = Element.MaximumDate.ToNSDate();
+ }
+
+ void UpdateMinimumDate()
+ {
+ _picker.MinimumDate = Element.MinimumDate.ToNSDate();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/EditorRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/EditorRenderer.cs
new file mode 100644
index 00000000..4d5a3f99
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/EditorRenderer.cs
@@ -0,0 +1,159 @@
+using System;
+using System.Drawing;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class EditorRenderer : ViewRenderer<Editor, UITextView>
+ {
+ UIToolbar _accessoryView;
+
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ if (!Forms.IsiOS7OrNewer)
+ {
+ // Avoid crash iOS 6. iOS 6, I hate you. Why you no like Infinite size?
+ return base.GetDesiredSize(Math.Min(widthConstraint, 2000), Math.Min(heightConstraint, 2000));
+ }
+ return base.GetDesiredSize(widthConstraint, heightConstraint);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ Control.Changed -= HandleChanged;
+ Control.Started -= OnStarted;
+ Control.Ended -= OnEnded;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
+ {
+ base.OnElementChanged(e);
+
+ if (Control == null)
+ {
+ SetNativeControl(new UITextView(RectangleF.Empty));
+
+ if (Device.Idiom == TargetIdiom.Phone)
+ {
+ // iPhone does not have a dismiss keyboard button
+ var keyboardWidth = UIScreen.MainScreen.Bounds.Width;
+ _accessoryView = new UIToolbar(new RectangleF(0, 0, keyboardWidth, 44)) { BarStyle = UIBarStyle.Default, Translucent = true };
+
+ var spacer = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);
+ var doneButton = new UIBarButtonItem(UIBarButtonSystemItem.Done, (o, a) =>
+ {
+ Control.ResignFirstResponder();
+ Element.SendCompleted();
+ });
+ _accessoryView.SetItems(new[] { spacer, doneButton }, false);
+ Control.InputAccessoryView = _accessoryView;
+ }
+
+ Control.Changed += HandleChanged;
+ Control.Started += OnStarted;
+ Control.Ended += OnEnded;
+ }
+
+ if (e.NewElement != null)
+ {
+ UpdateText();
+ UpdateFont();
+ UpdateTextColor();
+ UpdateKeyboard();
+ UpdateEditable();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Editor.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Xamarin.Forms.InputView.KeyboardProperty.PropertyName)
+ UpdateKeyboard();
+ else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ UpdateEditable();
+ else if (e.PropertyName == Editor.TextColorProperty.PropertyName)
+ UpdateTextColor();
+ else if (e.PropertyName == Editor.FontAttributesProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Editor.FontFamilyProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Editor.FontSizeProperty.PropertyName)
+ UpdateFont();
+ }
+
+ void HandleChanged(object sender, EventArgs e)
+ {
+ ((IElementController)Element).SetValueFromRenderer(Editor.TextProperty, Control.Text);
+ }
+
+ void OnEnded(object sender, EventArgs eventArgs)
+ {
+ Element.SetValue(VisualElement.IsFocusedPropertyKey, false);
+ Element.SendCompleted();
+ }
+
+ void OnStarted(object sender, EventArgs eventArgs)
+ {
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
+ }
+
+ void UpdateEditable()
+ {
+ Control.Editable = Element.IsEnabled;
+ Control.UserInteractionEnabled = Element.IsEnabled;
+
+ if (Control.InputAccessoryView != null)
+ Control.InputAccessoryView.Hidden = !Element.IsEnabled;
+ }
+
+ void UpdateFont()
+ {
+ Control.Font = Element.ToUIFont();
+ }
+
+ void UpdateKeyboard()
+ {
+ Control.ApplyKeyboard(Element.Keyboard);
+ }
+
+ void UpdateText()
+ {
+ // ReSharper disable once RedundantCheckBeforeAssignment
+ if (Control.Text != Element.Text)
+ Control.Text = Element.Text;
+ }
+
+ void UpdateTextColor()
+ {
+ var textColor = Element.TextColor;
+
+ if (textColor.IsDefault)
+ Control.TextColor = UIColor.Black;
+ else
+ Control.TextColor = textColor.ToUIColor();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs
new file mode 100644
index 00000000..734a56be
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs
@@ -0,0 +1,184 @@
+using System;
+using System.Drawing;
+using System.Runtime.Remoting.Channels;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class EntryRenderer : ViewRenderer<Entry, UITextField>
+ {
+ UIColor _defaultTextColor;
+
+ public EntryRenderer()
+ {
+ Frame = new RectangleF(0, 20, 320, 40);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (Control != null)
+ {
+ Control.EditingDidBegin -= OnEditingBegan;
+ Control.EditingChanged -= OnEditingChanged;
+ Control.EditingDidEnd -= OnEditingEnded;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
+ {
+ base.OnElementChanged(e);
+
+ var textField = Control;
+
+ if (Control == null)
+ {
+ SetNativeControl(textField = new UITextField(RectangleF.Empty));
+
+ _defaultTextColor = textField.TextColor;
+ textField.BorderStyle = UITextBorderStyle.RoundedRect;
+
+ textField.EditingChanged += OnEditingChanged;
+
+ textField.ShouldReturn = OnShouldReturn;
+
+ textField.EditingDidBegin += OnEditingBegan;
+ textField.EditingDidEnd += OnEditingEnded;
+ }
+
+ if (e.NewElement != null)
+ {
+ UpdatePlaceholder();
+ UpdatePassword();
+ UpdateText();
+ UpdateColor();
+ UpdateFont();
+ UpdateKeyboard();
+ UpdateAlignment();
+ }
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Entry.PlaceholderProperty.PropertyName || e.PropertyName == Entry.PlaceholderColorProperty.PropertyName)
+ UpdatePlaceholder();
+ else if (e.PropertyName == Entry.IsPasswordProperty.PropertyName)
+ UpdatePassword();
+ else if (e.PropertyName == Entry.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Entry.TextColorProperty.PropertyName)
+ UpdateColor();
+ else if (e.PropertyName == Xamarin.Forms.InputView.KeyboardProperty.PropertyName)
+ UpdateKeyboard();
+ else if (e.PropertyName == Entry.HorizontalTextAlignmentProperty.PropertyName)
+ UpdateAlignment();
+ else if (e.PropertyName == Entry.FontAttributesProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Entry.FontFamilyProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Entry.FontSizeProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ {
+ UpdateColor();
+ UpdatePlaceholder();
+ }
+
+ base.OnElementPropertyChanged(sender, e);
+ }
+
+ void OnEditingBegan(object sender, EventArgs e)
+ {
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
+ }
+
+ void OnEditingChanged(object sender, EventArgs eventArgs)
+ {
+ ((IElementController)Element).SetValueFromRenderer(Entry.TextProperty, Control.Text);
+ }
+
+ void OnEditingEnded(object sender, EventArgs e)
+ {
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ }
+
+ bool OnShouldReturn(UITextField view)
+ {
+ Control.ResignFirstResponder();
+ Element.SendCompleted();
+ return true;
+ }
+
+ void UpdateAlignment()
+ {
+ Control.TextAlignment = Element.HorizontalTextAlignment.ToNativeTextAlignment();
+ }
+
+ void UpdateColor()
+ {
+ var textColor = Element.TextColor;
+
+ if (textColor.IsDefault || !Element.IsEnabled)
+ Control.TextColor = _defaultTextColor;
+ else
+ Control.TextColor = textColor.ToUIColor();
+ }
+
+ void UpdateFont()
+ {
+ Control.Font = Element.ToUIFont();
+ }
+
+ void UpdateKeyboard()
+ {
+ Control.ApplyKeyboard(Element.Keyboard);
+ }
+
+ void UpdatePassword()
+ {
+ if (Element.IsPassword && Control.IsFirstResponder)
+ {
+ Control.Enabled = false;
+ Control.SecureTextEntry = true;
+ Control.Enabled = Element.IsEnabled;
+ Control.BecomeFirstResponder();
+ }
+ else
+ Control.SecureTextEntry = Element.IsPassword;
+ }
+
+ void UpdatePlaceholder()
+ {
+ var formatted = (FormattedString)Element.Placeholder;
+
+ if (formatted == null)
+ return;
+
+ var targetColor = Element.PlaceholderColor;
+
+ // Placeholder default color is 70% gray
+ // https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITextField_Class/index.html#//apple_ref/occ/instp/UITextField/placeholder
+
+ var color = Element.IsEnabled && !targetColor.IsDefault ? targetColor : ColorExtensions.SeventyPercentGrey.ToColor();
+
+ Control.AttributedPlaceholder = formatted.ToAttributed(Element, color);
+ }
+
+ void UpdateText()
+ {
+ // ReSharper disable once RedundantCheckBeforeAssignment
+ if (Control.Text != Element.Text)
+ Control.Text = Element.Text;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/ExportCellAttribute.cs b/Xamarin.Forms.Platform.iOS/Renderers/ExportCellAttribute.cs
new file mode 100644
index 00000000..1abf0d7f
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/ExportCellAttribute.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage (AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class ExportCellAttribute : HandlerAttribute {
+ public ExportCellAttribute (Type handler, Type target)
+ : base (handler, target) {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/ExportImageSourceHandlerAttribute.cs b/Xamarin.Forms.Platform.iOS/Renderers/ExportImageSourceHandlerAttribute.cs
new file mode 100644
index 00000000..59e96e1f
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/ExportImageSourceHandlerAttribute.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage (AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class ExportImageSourceHandlerAttribute : HandlerAttribute {
+ public ExportImageSourceHandlerAttribute (Type handler, Type target)
+ : base (handler, target) {
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/ExportRendererAttribute.cs b/Xamarin.Forms.Platform.iOS/Renderers/ExportRendererAttribute.cs
new file mode 100644
index 00000000..899056da
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/ExportRendererAttribute.cs
@@ -0,0 +1,30 @@
+using System;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms
+{
+ [AttributeUsage (AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class ExportRendererAttribute : HandlerAttribute {
+ internal bool Idiomatic { get; private set; }
+ internal UIUserInterfaceIdiom Idiom { get; private set; }
+
+ public ExportRendererAttribute (Type handler, Type target, UIUserInterfaceIdiom idiom)
+ : base (handler, target) {
+ Idiomatic = true;
+ Idiom = idiom;
+ }
+
+ public ExportRendererAttribute (Type handler, Type target)
+ : base (handler, target) {
+ Idiomatic = false;
+ }
+
+ public override bool ShouldRegister () {
+ return !Idiomatic || Idiom == UIDevice.CurrentDevice.UserInterfaceIdiom;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/FontExtensions.cs b/Xamarin.Forms.Platform.iOS/Renderers/FontExtensions.cs
new file mode 100644
index 00000000..07afcfaf
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/FontExtensions.cs
@@ -0,0 +1,205 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public static class FontExtensions
+ {
+ static readonly Dictionary<ToUIFontKey, UIFont> ToUiFont = new Dictionary<ToUIFontKey, UIFont>();
+
+ public static UIFont ToUIFont(this Font self)
+ {
+ var size = (float)self.FontSize;
+ if (self.UseNamedSize)
+ {
+ switch (self.NamedSize)
+ {
+ case NamedSize.Micro:
+ size = 12;
+ break;
+ case NamedSize.Small:
+ size = 14;
+ break;
+ case NamedSize.Medium:
+ size = 17; // as defined by iOS documentation
+ break;
+ case NamedSize.Large:
+ size = 22;
+ break;
+ default:
+ size = 17;
+ break;
+ }
+ }
+
+ var bold = self.FontAttributes.HasFlag(FontAttributes.Bold);
+ var italic = self.FontAttributes.HasFlag(FontAttributes.Italic);
+
+ if (self.FontFamily != null)
+ {
+ try
+ {
+ if (UIFont.FamilyNames.Contains(self.FontFamily) && Forms.IsiOS7OrNewer)
+ {
+ var descriptor = new UIFontDescriptor().CreateWithFamily(self.FontFamily);
+
+ if (bold || italic)
+ {
+ var traits = (UIFontDescriptorSymbolicTraits)0;
+ if (bold)
+ traits = traits | UIFontDescriptorSymbolicTraits.Bold;
+ if (italic)
+ traits = traits | UIFontDescriptorSymbolicTraits.Italic;
+
+ descriptor = descriptor.CreateWithTraits(traits);
+ return UIFont.FromDescriptor(descriptor, size);
+ }
+ }
+
+ return UIFont.FromName(self.FontFamily, size);
+ }
+ catch
+ {
+ Debug.WriteLine("Could not load font named: {0}", self.FontFamily);
+ }
+ }
+ if (bold && italic)
+ {
+ if (!Forms.IsiOS7OrNewer)
+ {
+ // not sure how to make a font both bold and italic in iOS 6, default to bold
+ return UIFont.BoldSystemFontOfSize(size);
+ }
+
+ var defaultFont = UIFont.SystemFontOfSize(size);
+ var descriptor = defaultFont.FontDescriptor.CreateWithTraits(UIFontDescriptorSymbolicTraits.Bold | UIFontDescriptorSymbolicTraits.Italic);
+ return UIFont.FromDescriptor(descriptor, 0);
+ }
+ if (bold)
+ return UIFont.BoldSystemFontOfSize(size);
+ if (italic)
+ return UIFont.ItalicSystemFontOfSize(size);
+ return UIFont.SystemFontOfSize(size);
+ }
+
+ internal static bool IsDefault(this Span self)
+ {
+ return self.FontFamily == null && self.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(Label), true) && self.FontAttributes == FontAttributes.None;
+ }
+
+ internal static UIFont ToUIFont(this Label label)
+ {
+ var values = label.GetValues(Label.FontFamilyProperty, Label.FontSizeProperty, Label.FontAttributesProperty);
+ return ToUIFont((string)values[0], (float)(double)values[1], (FontAttributes)values[2]) ?? UIFont.SystemFontOfSize(UIFont.LabelFontSize);
+ }
+
+ internal static UIFont ToUIFont(this IFontElement element)
+ {
+ return ToUIFont(element.FontFamily, (float)element.FontSize, element.FontAttributes);
+ }
+
+ static UIFont _ToUIFont(string family, float size, FontAttributes attributes)
+ {
+ var bold = (attributes & FontAttributes.Bold) != 0;
+ var italic = (attributes & FontAttributes.Italic) != 0;
+
+ if (family != null)
+ {
+ try
+ {
+ UIFont result;
+ if (UIFont.FamilyNames.Contains(family) && Forms.IsiOS7OrNewer)
+ {
+ var descriptor = new UIFontDescriptor().CreateWithFamily(family);
+
+ if (bold || italic)
+ {
+ var traits = (UIFontDescriptorSymbolicTraits)0;
+ if (bold)
+ traits = traits | UIFontDescriptorSymbolicTraits.Bold;
+ if (italic)
+ traits = traits | UIFontDescriptorSymbolicTraits.Italic;
+
+ descriptor = descriptor.CreateWithTraits(traits);
+ result = UIFont.FromDescriptor(descriptor, size);
+ if (result != null)
+ return result;
+ }
+ }
+
+ result = UIFont.FromName(family, size);
+ if (result != null)
+ return result;
+ }
+ catch
+ {
+ Debug.WriteLine("Could not load font named: {0}", family);
+ }
+ }
+
+ if (bold && italic)
+ {
+ var defaultFont = UIFont.SystemFontOfSize(size);
+
+ if (!Forms.IsiOS7OrNewer)
+ {
+ // not sure how to make a font both bold and italic in iOS 6, default to bold
+ return UIFont.BoldSystemFontOfSize(size);
+ }
+
+ var descriptor = defaultFont.FontDescriptor.CreateWithTraits(UIFontDescriptorSymbolicTraits.Bold | UIFontDescriptorSymbolicTraits.Italic);
+ return UIFont.FromDescriptor(descriptor, 0);
+ }
+ if (bold)
+ return UIFont.BoldSystemFontOfSize(size);
+ if (italic)
+ return UIFont.ItalicSystemFontOfSize(size);
+
+ return UIFont.SystemFontOfSize(size);
+ }
+
+ static UIFont ToUIFont(string family, float size, FontAttributes attributes)
+ {
+ var key = new ToUIFontKey(family, size, attributes);
+
+ lock(ToUiFont)
+ {
+ UIFont value;
+ if (ToUiFont.TryGetValue(key, out value))
+ return value;
+ }
+
+ var generatedValue = _ToUIFont(family, size, attributes);
+
+ lock(ToUiFont)
+ {
+ UIFont value;
+ if (!ToUiFont.TryGetValue(key, out value))
+ ToUiFont.Add(key, value = generatedValue);
+ return value;
+ }
+ }
+
+ struct ToUIFontKey
+ {
+ internal ToUIFontKey(string family, float size, FontAttributes attributes)
+ {
+ _family = family;
+ _size = size;
+ _attributes = attributes;
+ }
+
+ string _family;
+ float _size;
+ FontAttributes _attributes;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/FormattedStringExtensions.cs b/Xamarin.Forms.Platform.iOS/Renderers/FormattedStringExtensions.cs
new file mode 100644
index 00000000..0dfa38cd
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/FormattedStringExtensions.cs
@@ -0,0 +1,82 @@
+#if __UNIFIED__
+using Foundation;
+using UIKit;
+
+#else
+using MonoTouch.Foundation;
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public static class FormattedStringExtensions
+ {
+ public static NSAttributedString ToAttributed(this Span span, Font defaultFont, Color defaultForegroundColor)
+ {
+ if (span == null)
+ return null;
+
+ var font = span.Font != Font.Default ? span.Font : defaultFont;
+
+ var fgcolor = span.ForegroundColor;
+ if (fgcolor.IsDefault)
+ fgcolor = defaultForegroundColor;
+ if (fgcolor.IsDefault)
+ fgcolor = Color.Black; // as defined by apple docs
+
+ return new NSAttributedString(span.Text, font == Font.Default ? null : font.ToUIFont(), fgcolor.ToUIColor(), span.BackgroundColor.ToUIColor());
+ }
+
+ public static NSAttributedString ToAttributed(this FormattedString formattedString, Font defaultFont, Color defaultForegroundColor)
+ {
+ if (formattedString == null)
+ return null;
+ var attributed = new NSMutableAttributedString();
+ foreach (var span in formattedString.Spans)
+ {
+ if (span.Text == null)
+ continue;
+
+ attributed.Append(span.ToAttributed(defaultFont, defaultForegroundColor));
+ }
+
+ return attributed;
+ }
+
+ internal static NSAttributedString ToAttributed(this Span span, Element owner, Color defaultForegroundColor)
+ {
+ if (span == null)
+ return null;
+
+ UIFont targetFont;
+ if (span.IsDefault())
+ targetFont = ((IFontElement)owner).ToUIFont();
+ else
+ targetFont = span.ToUIFont();
+
+ var fgcolor = span.ForegroundColor;
+ if (fgcolor.IsDefault)
+ fgcolor = defaultForegroundColor;
+ if (fgcolor.IsDefault)
+ fgcolor = Color.Black; // as defined by apple docs
+
+ return new NSAttributedString(span.Text, targetFont, fgcolor.ToUIColor(), span.BackgroundColor.ToUIColor());
+ }
+
+ internal static NSAttributedString ToAttributed(this FormattedString formattedString, Element owner, Color defaultForegroundColor)
+ {
+ if (formattedString == null)
+ return null;
+ var attributed = new NSMutableAttributedString();
+ foreach (var span in formattedString.Spans)
+ {
+ if (span.Text == null)
+ continue;
+
+ attributed.Append(span.ToAttributed(owner, defaultForegroundColor));
+ }
+
+ return attributed;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/FrameRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/FrameRenderer.cs
new file mode 100644
index 00000000..3f2f1ccb
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/FrameRenderer.cs
@@ -0,0 +1,61 @@
+using System.ComponentModel;
+using System.Drawing;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class FrameRenderer : VisualElementRenderer<Frame>
+ {
+ protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.NewElement != null)
+ SetupLayer();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName || e.PropertyName == Xamarin.Forms.Frame.OutlineColorProperty.PropertyName ||
+ e.PropertyName == Xamarin.Forms.Frame.HasShadowProperty.PropertyName)
+ SetupLayer();
+ }
+
+ void SetupLayer()
+ {
+ Layer.CornerRadius = 5;
+ if (Element.BackgroundColor == Color.Default)
+ Layer.BackgroundColor = UIColor.White.CGColor;
+ else
+ Layer.BackgroundColor = Element.BackgroundColor.ToCGColor();
+
+ if (Element.HasShadow)
+ {
+ Layer.ShadowRadius = 5;
+ Layer.ShadowColor = UIColor.Black.CGColor;
+ Layer.ShadowOpacity = 0.8f;
+ Layer.ShadowOffset = new SizeF();
+ }
+ else
+ Layer.ShadowOpacity = 0;
+
+ if (Element.OutlineColor == Color.Default)
+ Layer.BorderColor = UIColor.Clear.CGColor;
+ else
+ {
+ Layer.BorderColor = Element.OutlineColor.ToCGColor();
+ Layer.BorderWidth = 1;
+ }
+
+ Layer.RasterizationScale = UIScreen.MainScreen.Scale;
+ Layer.ShouldRasterize = true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/ImageRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/ImageRenderer.cs
new file mode 100644
index 00000000..f227f9a5
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/ImageRenderer.cs
@@ -0,0 +1,209 @@
+using System.Drawing;
+using System.ComponentModel;
+using System.IO;
+using System.Threading.Tasks;
+using System.Threading;
+using System;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public static class ImageExtensions
+ {
+ public static UIViewContentMode ToUIViewContentMode(this Aspect aspect)
+ {
+ switch (aspect)
+ {
+ case Aspect.AspectFill:
+ return UIViewContentMode.ScaleAspectFill;
+ case Aspect.Fill:
+ return UIViewContentMode.ScaleToFill;
+ case Aspect.AspectFit:
+ default:
+ return UIViewContentMode.ScaleAspectFit;
+ }
+ }
+ }
+
+ public class ImageRenderer : ViewRenderer<Image, UIImageView>
+ {
+ bool _isDisposed;
+
+ protected override void Dispose(bool disposing)
+ {
+ if (_isDisposed)
+ return;
+
+ if (disposing)
+ {
+ UIImage oldUIImage;
+ if (Control != null && (oldUIImage = Control.Image) != null)
+ {
+ oldUIImage.Dispose();
+ oldUIImage = null;
+ }
+ }
+
+ _isDisposed = true;
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
+ {
+ if (Control == null)
+ {
+ var imageView = new UIImageView(RectangleF.Empty);
+ imageView.ContentMode = UIViewContentMode.ScaleAspectFit;
+ imageView.ClipsToBounds = true;
+ SetNativeControl(imageView);
+ }
+
+ if (e.NewElement != null)
+ {
+ SetAspect();
+ SetImage(e.OldElement);
+ SetOpacity();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+ if (e.PropertyName == Image.SourceProperty.PropertyName)
+ SetImage();
+ else if (e.PropertyName == Image.IsOpaqueProperty.PropertyName)
+ SetOpacity();
+ else if (e.PropertyName == Image.AspectProperty.PropertyName)
+ SetAspect();
+ }
+
+ void SetAspect()
+ {
+ Control.ContentMode = Element.Aspect.ToUIViewContentMode();
+ }
+
+ async void SetImage(Image oldElement = null)
+ {
+ var source = Element.Source;
+
+ if (oldElement != null)
+ {
+ var oldSource = oldElement.Source;
+ if (Equals(oldSource, source))
+ return;
+
+ if (oldSource is FileImageSource && source is FileImageSource && ((FileImageSource)oldSource).File == ((FileImageSource)source).File)
+ return;
+
+ Control.Image = null;
+ }
+
+ IImageSourceHandler handler;
+ ((IElementController)Element).SetValueFromRenderer(Image.IsLoadingPropertyKey, true);
+
+ if (source != null && (handler = Registrar.Registered.GetHandler<IImageSourceHandler>(source.GetType())) != null)
+ {
+ UIImage uiimage;
+ try
+ {
+ uiimage = await handler.LoadImageAsync(source, scale: (float)UIScreen.MainScreen.Scale);
+ }
+ catch (OperationCanceledException)
+ {
+ uiimage = null;
+ }
+
+ var imageView = Control;
+ if (imageView != null)
+ imageView.Image = uiimage;
+
+ if (!_isDisposed)
+ ((IVisualElementController)Element).NativeSizeChanged();
+ }
+ else
+ Control.Image = null;
+
+ if (!_isDisposed)
+ ((IElementController)Element).SetValueFromRenderer(Image.IsLoadingPropertyKey, false);
+ }
+
+ void SetOpacity()
+ {
+ Control.Opaque = Element.IsOpaque;
+ }
+ }
+
+ public interface IImageSourceHandler : IRegisterable
+ {
+ Task<UIImage> LoadImageAsync(ImageSource imagesource, CancellationToken cancelationToken = default(CancellationToken), float scale = 1);
+ }
+
+ public sealed class FileImageSourceHandler : IImageSourceHandler
+ {
+ public Task<UIImage> LoadImageAsync(ImageSource imagesource, CancellationToken cancelationToken = default(CancellationToken), float scale = 1f)
+ {
+ UIImage image = null;
+ var filesource = imagesource as FileImageSource;
+ if (filesource != null)
+ {
+ var file = filesource.File;
+ if (!string.IsNullOrEmpty(file))
+ image = File.Exists(file) ? new UIImage(file) : UIImage.FromBundle(file);
+ }
+ return Task.FromResult(image);
+ }
+ }
+
+ public sealed class StreamImagesourceHandler : IImageSourceHandler
+ {
+ public async Task<UIImage> LoadImageAsync(ImageSource imagesource, CancellationToken cancelationToken = default(CancellationToken), float scale = 1f)
+ {
+ UIImage image = null;
+ var streamsource = imagesource as StreamImageSource;
+ if (streamsource != null && streamsource.Stream != null)
+ {
+ var streamImage = await streamsource.GetStreamAsync(cancelationToken).ConfigureAwait(false);
+ if (streamImage != null)
+ image = UIImage.LoadFromData(NSData.FromStream(streamImage), scale);
+ }
+ return image;
+ }
+ }
+
+ public sealed class ImageLoaderSourceHandler : IImageSourceHandler
+ {
+ public async Task<UIImage> LoadImageAsync(ImageSource imagesource, CancellationToken cancelationToken = default(CancellationToken), float scale = 1f)
+ {
+ UIImage image = null;
+ var imageLoader = imagesource as UriImageSource;
+ if (imageLoader != null && imageLoader.Uri != null)
+ {
+ using(var streamImage = await imageLoader.GetStreamAsync(cancelationToken).ConfigureAwait(false))
+ {
+ if (streamImage != null)
+ image = UIImage.LoadFromData(NSData.FromStream(streamImage), scale);
+ }
+ }
+ return image;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/KeyboardInsetTracker.cs b/Xamarin.Forms.Platform.iOS/Renderers/KeyboardInsetTracker.cs
new file mode 100644
index 00000000..d5759947
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/KeyboardInsetTracker.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Drawing;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ internal class KeyboardInsetTracker : IDisposable
+ {
+ readonly Func<UIWindow> _fetchWindow;
+ readonly Action<PointF> _setContentOffset;
+ readonly Action<UIEdgeInsets> _setInsetAction;
+ readonly UIView _targetView;
+ bool _disposed;
+
+ RectangleF _lastKeyboardRect;
+
+ public KeyboardInsetTracker(UIView targetView, Func<UIWindow> fetchWindow, Action<UIEdgeInsets> setInsetAction) : this(targetView, fetchWindow, setInsetAction, null)
+ {
+ }
+
+ public KeyboardInsetTracker(UIView targetView, Func<UIWindow> fetchWindow, Action<UIEdgeInsets> setInsetAction, Action<PointF> setContentOffset)
+ {
+ _setContentOffset = setContentOffset;
+ _targetView = targetView;
+ _fetchWindow = fetchWindow;
+ _setInsetAction = setInsetAction;
+ KeyboardObserver.KeyboardWillShow += OnKeyboardShown;
+ KeyboardObserver.KeyboardWillHide += OnKeyboardHidden;
+ }
+
+ public void Dispose()
+ {
+ if (_disposed)
+ return;
+ _disposed = true;
+
+ KeyboardObserver.KeyboardWillShow -= OnKeyboardShown;
+ KeyboardObserver.KeyboardWillHide -= OnKeyboardHidden;
+ }
+
+ //This method allows us to update the insets if the Frame changes
+ internal void UpdateInsets()
+ {
+ //being called from LayoutSubviews but keyboard wasn't shown yet
+ if (_lastKeyboardRect.IsEmpty)
+ return;
+
+ var window = _fetchWindow();
+ // Code left verbose to make its operation more obvious
+ if (window == null)
+ {
+ // we are not currently displayed and can safely ignore this
+ // most likely this renderer is on a page which is currently not displayed (e.g. in NavController)
+ return;
+ }
+
+ var field = _targetView.FindFirstResponder();
+
+ //the view that is triggering the keyboard is not inside our UITableView?
+ //if (field == null)
+ // return;
+
+ var boundsSize = _targetView.Frame.Size;
+
+ //since our keyboard frame is RVC CoordinateSpace, lets convert it to our targetView CoordinateSpace
+ var rect = _targetView.Superview.ConvertRectFromView(_lastKeyboardRect, null);
+ //let's see how much does it cover our target view
+ var overlay = RectangleF.Intersect(rect, _targetView.Frame);
+
+ _setInsetAction(new UIEdgeInsets(0, 0, overlay.Height, 0));
+
+ if (field is UITextView && _setContentOffset != null)
+ {
+ var keyboardTop = boundsSize.Height - overlay.Height;
+ var fieldPosition = field.ConvertPointToView(field.Frame.Location, _targetView.Superview);
+ var fieldBottom = fieldPosition.Y + field.Frame.Height;
+ var offset = fieldBottom - keyboardTop;
+ if (offset > 0)
+ _setContentOffset(new PointF(0, offset));
+ }
+ }
+
+ void OnKeyboardHidden(object sender, UIKeyboardEventArgs args)
+ {
+ _setInsetAction(new UIEdgeInsets(0, 0, 0, 0));
+ _lastKeyboardRect = RectangleF.Empty;
+ }
+
+ void OnKeyboardShown(object sender, UIKeyboardEventArgs args)
+ {
+ _lastKeyboardRect = args.FrameEnd;
+ UpdateInsets();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/KeyboardObserver.cs b/Xamarin.Forms.Platform.iOS/Renderers/KeyboardObserver.cs
new file mode 100644
index 00000000..4ebb75d7
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/KeyboardObserver.cs
@@ -0,0 +1,37 @@
+using System;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ internal static class KeyboardObserver
+ {
+ static KeyboardObserver()
+ {
+ UIKeyboard.Notifications.ObserveWillShow(OnKeyboardShown);
+ UIKeyboard.Notifications.ObserveWillHide(OnKeyboardHidden);
+ }
+
+ public static event EventHandler<UIKeyboardEventArgs> KeyboardWillHide;
+
+ public static event EventHandler<UIKeyboardEventArgs> KeyboardWillShow;
+
+ static void OnKeyboardHidden(object sender, UIKeyboardEventArgs args)
+ {
+ var handler = KeyboardWillHide;
+ if (handler != null)
+ handler(sender, args);
+ }
+
+ static void OnKeyboardShown(object sender, UIKeyboardEventArgs args)
+ {
+ var handler = KeyboardWillShow;
+ if (handler != null)
+ handler(sender, args);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/LabelRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/LabelRenderer.cs
new file mode 100644
index 00000000..f886cb35
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/LabelRenderer.cs
@@ -0,0 +1,183 @@
+using System;
+using System.Drawing;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+using CoreText;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.CoreText;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class LabelRenderer : ViewRenderer<Label, UILabel>
+ {
+ SizeRequest _perfectSize;
+
+ bool _perfectSizeValid;
+
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ if (!_perfectSizeValid)
+ {
+ _perfectSize = base.GetDesiredSize(double.PositiveInfinity, double.PositiveInfinity);
+ _perfectSize.Minimum = new Size(Math.Min(10, _perfectSize.Request.Width), _perfectSize.Request.Height);
+ _perfectSizeValid = true;
+ }
+
+ if (widthConstraint >= _perfectSize.Request.Width && heightConstraint >= _perfectSize.Request.Height)
+ return _perfectSize;
+
+ var result = base.GetDesiredSize(widthConstraint, heightConstraint);
+ result.Minimum = new Size(Math.Min(10, result.Request.Width), result.Request.Height);
+ if ((Element.LineBreakMode & (LineBreakMode.TailTruncation | LineBreakMode.HeadTruncation | LineBreakMode.MiddleTruncation)) != 0)
+ {
+ if (result.Request.Width > widthConstraint)
+ result.Request = new Size(Math.Max(result.Minimum.Width, widthConstraint), result.Request.Height);
+ }
+
+ return result;
+ }
+
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+ if (Control == null)
+ return;
+
+ SizeF fitSize;
+ nfloat labelHeight;
+ switch (Element.VerticalTextAlignment)
+ {
+ case TextAlignment.Start:
+ fitSize = Control.SizeThatFits(Element.Bounds.Size.ToSizeF());
+ labelHeight = (nfloat)Math.Min(Bounds.Height, fitSize.Height);
+ Control.Frame = new RectangleF(0, 0, (nfloat)Element.Width, labelHeight);
+ break;
+ case TextAlignment.Center:
+ Control.Frame = new RectangleF(0, 0, (nfloat)Element.Width, (nfloat)Element.Height);
+ break;
+ case TextAlignment.End:
+ nfloat yOffset = 0;
+ fitSize = Control.SizeThatFits(Element.Bounds.Size.ToSizeF());
+ labelHeight = (nfloat)Math.Min(Bounds.Height, fitSize.Height);
+ yOffset = (nfloat)(Element.Height - labelHeight);
+ Control.Frame = new RectangleF(0, yOffset, (nfloat)Element.Width, labelHeight);
+ break;
+ }
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
+ {
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new UILabel(RectangleF.Empty) { BackgroundColor = UIColor.Clear });
+ }
+
+ UpdateText();
+ UpdateLineBreakMode();
+ UpdateAlignment();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Label.HorizontalTextAlignmentProperty.PropertyName)
+ UpdateAlignment();
+ else if (e.PropertyName == Label.VerticalTextAlignmentProperty.PropertyName)
+ LayoutSubviews();
+ else if (e.PropertyName == Label.TextColorProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Label.FontProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Label.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Label.FormattedTextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Label.LineBreakModeProperty.PropertyName)
+ UpdateLineBreakMode();
+ }
+
+ protected override void SetBackgroundColor(Color color)
+ {
+ if (color == Color.Default)
+ BackgroundColor = UIColor.Clear;
+ else
+ BackgroundColor = color.ToUIColor();
+ }
+
+ void UpdateAlignment()
+ {
+ Control.TextAlignment = Element.HorizontalTextAlignment.ToNativeTextAlignment();
+ }
+
+ void UpdateLineBreakMode()
+ {
+ _perfectSizeValid = false;
+
+ switch (Element.LineBreakMode)
+ {
+ case LineBreakMode.NoWrap:
+ Control.LineBreakMode = UILineBreakMode.Clip;
+ Control.Lines = 1;
+ break;
+ case LineBreakMode.WordWrap:
+ Control.LineBreakMode = UILineBreakMode.WordWrap;
+ Control.Lines = 0;
+ break;
+ case LineBreakMode.CharacterWrap:
+ Control.LineBreakMode = UILineBreakMode.CharacterWrap;
+ Control.Lines = 0;
+ break;
+ case LineBreakMode.HeadTruncation:
+ Control.LineBreakMode = UILineBreakMode.HeadTruncation;
+ Control.Lines = 1;
+ break;
+ case LineBreakMode.MiddleTruncation:
+ Control.LineBreakMode = UILineBreakMode.MiddleTruncation;
+ Control.Lines = 1;
+ break;
+ case LineBreakMode.TailTruncation:
+ Control.LineBreakMode = UILineBreakMode.TailTruncation;
+ Control.Lines = 1;
+ break;
+ }
+ }
+
+ void UpdateText()
+ {
+ _perfectSizeValid = false;
+
+ var values = Element.GetValues(Label.FormattedTextProperty, Label.TextProperty, Label.TextColorProperty);
+ var formatted = (FormattedString)values[0];
+ if (formatted != null)
+ Control.AttributedText = formatted.ToAttributed(Element, (Color)values[2]);
+ else
+ {
+ Control.Text = (string)values[1];
+ // default value of color documented to be black in iOS docs
+ Control.Font = Element.ToUIFont();
+ Control.TextColor = ((Color)values[2]).ToUIColor(ColorExtensions.Black);
+ }
+
+ LayoutSubviews();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs
new file mode 100644
index 00000000..2151d446
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs
@@ -0,0 +1,1119 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class ListViewRenderer : ViewRenderer<ListView, UITableView>
+ {
+ const int DefaultRowHeight = 44;
+ ListViewDataSource _dataSource;
+ bool _estimatedRowHeight;
+ IVisualElementRenderer _headerRenderer;
+ IVisualElementRenderer _footerRenderer;
+
+ KeyboardInsetTracker _insetTracker;
+ RectangleF _previousFrame;
+ ScrollToRequestedEventArgs _requestedScroll;
+ bool _shouldEstimateRowHeight = true;
+ FormsUITableViewController _tableViewController;
+
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return Control.GetSizeRequest(widthConstraint, heightConstraint, 44, 44);
+ }
+
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+
+ double height = Bounds.Height;
+ double width = Bounds.Width;
+ if (_headerRenderer != null)
+ {
+ var e = _headerRenderer.Element;
+ var request = e.Measure(width, double.PositiveInfinity, MeasureFlags.IncludeMargins);
+
+ // Time for another story with Jason. Gather round children because the following Math.Ceiling will look like it's completely useless.
+ // You will remove it and test and find everything is fiiiiiine, but it is not fine, no it is far from fine. See iOS, or at least iOS 8
+ // has an issue where-by if the TableHeaderView happens to NOT be an integer height, it will add padding to the space between the content
+ // of the UITableView and the TableHeaderView to the tune of the difference between Math.Ceiling (height) - height. Now this seems fine
+ // and when you test it will be, EXCEPT that it does this every time you toggle the visibility of the UITableView causing the spacing to
+ // grow a little each time, which you weren't testing at all were you? So there you have it, the stupid reason we integer align here.
+ //
+ // The same technically applies to the footer, though that could hardly matter less. We just do it for fun.
+ Layout.LayoutChildIntoBoundingRegion(e, new Rectangle(0, 0, width, Math.Ceiling(request.Request.Height)));
+
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ if (_headerRenderer != null)
+ Control.TableHeaderView = _headerRenderer.NativeView;
+ });
+ }
+
+ if (_footerRenderer != null)
+ {
+ var e = _footerRenderer.Element;
+ var request = e.Measure(width, height, MeasureFlags.IncludeMargins);
+ Layout.LayoutChildIntoBoundingRegion(e, new Rectangle(0, 0, width, Math.Ceiling(request.Request.Height)));
+
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ if (_footerRenderer != null)
+ Control.TableFooterView = _footerRenderer.NativeView;
+ });
+ }
+
+ if (_requestedScroll != null && Superview != null)
+ {
+ var request = _requestedScroll;
+ _requestedScroll = null;
+ OnScrollToRequested(this, request);
+ }
+
+ if (_previousFrame != Frame)
+ {
+ _previousFrame = Frame;
+ _insetTracker?.UpdateInsets();
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ // check inset tracker for null to
+ if (disposing && _insetTracker != null)
+ {
+ _insetTracker.Dispose();
+ _insetTracker = null;
+
+ var viewsToLookAt = new Stack<UIView>(Subviews);
+ while (viewsToLookAt.Count > 0)
+ {
+ var view = viewsToLookAt.Pop();
+ var viewCellRenderer = view as ViewCellRenderer.ViewTableCell;
+ if (viewCellRenderer != null)
+ viewCellRenderer.Dispose();
+ else
+ {
+ foreach (var child in view.Subviews)
+ viewsToLookAt.Push(child);
+ }
+ }
+
+ if (Element != null)
+ {
+ Element.TemplatedItems.CollectionChanged -= OnCollectionChanged;
+ Element.TemplatedItems.GroupedCollectionChanged -= OnGroupedCollectionChanged;
+ }
+
+ if (_tableViewController != null)
+ {
+ _tableViewController.Dispose();
+ _tableViewController = null;
+ }
+ }
+
+ if (disposing)
+ {
+ if (_headerRenderer != null)
+ {
+ var platform = _headerRenderer.Element.Platform as Platform;
+ if (platform != null)
+ platform.DisposeModelAndChildrenRenderers(_headerRenderer.Element);
+ _headerRenderer = null;
+ }
+ if (_footerRenderer != null)
+ {
+ var platform = _footerRenderer.Element.Platform as Platform;
+ if (platform != null)
+ platform.DisposeModelAndChildrenRenderers(_footerRenderer.Element);
+ _footerRenderer = null;
+ }
+
+ var controller = Element as IListViewController;
+
+ var headerView = controller?.HeaderElement as VisualElement;
+ if (headerView != null)
+ headerView.MeasureInvalidated -= OnHeaderMeasureInvalidated;
+ Control?.TableHeaderView?.Dispose();
+
+ var footerView = controller?.FooterElement as VisualElement;
+ if (footerView != null)
+ footerView.MeasureInvalidated -= OnFooterMeasureInvalidated;
+ Control?.TableFooterView?.Dispose();
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
+ {
+ _requestedScroll = null;
+
+ if (e.OldElement != null)
+ {
+ var controller = (IListViewController)e.OldElement;
+ var headerView = (VisualElement)controller.HeaderElement;
+ if (headerView != null)
+ headerView.MeasureInvalidated -= OnHeaderMeasureInvalidated;
+
+ var footerView = (VisualElement)controller.FooterElement;
+ if (footerView != null)
+ footerView.MeasureInvalidated -= OnFooterMeasureInvalidated;
+
+ e.OldElement.ScrollToRequested -= OnScrollToRequested;
+ e.OldElement.TemplatedItems.CollectionChanged -= OnCollectionChanged;
+ e.OldElement.TemplatedItems.GroupedCollectionChanged -= OnGroupedCollectionChanged;
+ }
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ _tableViewController = new FormsUITableViewController(e.NewElement);
+ SetNativeControl(_tableViewController.TableView);
+ if (Forms.IsiOS9OrNewer)
+ Control.CellLayoutMarginsFollowReadableWidth = false;
+
+ _insetTracker = new KeyboardInsetTracker(_tableViewController.TableView, () => Control.Window, insets => Control.ContentInset = Control.ScrollIndicatorInsets = insets, point =>
+ {
+ var offset = Control.ContentOffset;
+ offset.Y += point.Y;
+ Control.SetContentOffset(offset, true);
+ });
+ }
+ _shouldEstimateRowHeight = true;
+ //if the user specifies he wants to sacrifice performance we will do things like:
+ // - don't EstimateRowHeight anymore
+ if (e.NewElement.TakePerformanceHit)
+ _shouldEstimateRowHeight = false;
+
+ e.NewElement.ScrollToRequested += OnScrollToRequested;
+ e.NewElement.TemplatedItems.CollectionChanged += OnCollectionChanged;
+ e.NewElement.TemplatedItems.GroupedCollectionChanged += OnGroupedCollectionChanged;
+
+ UpdateRowHeight();
+
+ Control.Source = _dataSource = e.NewElement.HasUnevenRows ? new UnevenListViewDataSource(e.NewElement, _tableViewController) : new ListViewDataSource(e.NewElement, _tableViewController);
+
+ UpdateEstimatedRowHeight();
+ UpdateHeader();
+ UpdateFooter();
+ UpdatePullToRefreshEnabled();
+ UpdateIsRefreshing();
+ UpdateSeparatorColor();
+ UpdateSeparatorVisibility();
+
+ var selected = e.NewElement.SelectedItem;
+ if (selected != null)
+ _dataSource.OnItemSelected(null, new SelectedItemChangedEventArgs(selected));
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+ if (e.PropertyName == ListView.RowHeightProperty.PropertyName)
+ UpdateRowHeight();
+ else if (e.PropertyName == ListView.IsGroupingEnabledProperty.PropertyName)
+ _dataSource.UpdateGrouping();
+ else if (e.PropertyName == ListView.HasUnevenRowsProperty.PropertyName)
+ {
+ _estimatedRowHeight = false;
+ Control.Source = _dataSource = Element.HasUnevenRows ? new UnevenListViewDataSource(_dataSource) : new ListViewDataSource(_dataSource);
+ }
+ else if (e.PropertyName == ListView.IsPullToRefreshEnabledProperty.PropertyName)
+ UpdatePullToRefreshEnabled();
+ else if (e.PropertyName == ListView.IsRefreshingProperty.PropertyName)
+ UpdateIsRefreshing();
+ else if (e.PropertyName == ListView.SeparatorColorProperty.PropertyName)
+ UpdateSeparatorColor();
+ else if (e.PropertyName == ListView.SeparatorVisibilityProperty.PropertyName)
+ UpdateSeparatorVisibility();
+ else if (e.PropertyName == "HeaderElement")
+ UpdateHeader();
+ else if (e.PropertyName == "FooterElement")
+ UpdateFooter();
+ else if (e.PropertyName == "RefreshAllowed")
+ UpdatePullToRefreshEnabled();
+ }
+
+ NSIndexPath[] GetPaths(int section, int index, int count)
+ {
+ var paths = new NSIndexPath[count];
+ for (var i = 0; i < paths.Length; i++)
+ paths[i] = NSIndexPath.FromRowSection(index + i, section);
+
+ return paths;
+ }
+
+ UITableViewScrollPosition GetScrollPosition(ScrollToPosition position)
+ {
+ switch (position)
+ {
+ case ScrollToPosition.Center:
+ return UITableViewScrollPosition.Middle;
+ case ScrollToPosition.End:
+ return UITableViewScrollPosition.Bottom;
+ case ScrollToPosition.Start:
+ return UITableViewScrollPosition.Top;
+ case ScrollToPosition.MakeVisible:
+ default:
+ return UITableViewScrollPosition.None;
+ }
+ }
+
+ void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ UpdateItems(e, 0, true);
+ }
+
+ void OnFooterMeasureInvalidated(object sender, EventArgs eventArgs)
+ {
+ double width = Bounds.Width;
+ if (width == 0)
+ return;
+
+ var footerView = (VisualElement)sender;
+ var request = footerView.Measure(width, double.PositiveInfinity, MeasureFlags.IncludeMargins);
+ Layout.LayoutChildIntoBoundingRegion(footerView, new Rectangle(0, 0, width, request.Request.Height));
+
+ Control.TableFooterView = _footerRenderer.NativeView;
+ }
+
+ void OnGroupedCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ var til = (TemplatedItemsList<ItemsView<Cell>, Cell>)sender;
+
+ var groupIndex = Element.TemplatedItems.IndexOf(til.HeaderContent);
+ UpdateItems(e, groupIndex, false);
+ }
+
+ void OnHeaderMeasureInvalidated(object sender, EventArgs eventArgs)
+ {
+ double width = Bounds.Width;
+ if (width == 0)
+ return;
+
+ var headerView = (VisualElement)sender;
+ var request = headerView.Measure(width, double.PositiveInfinity, MeasureFlags.IncludeMargins);
+ Layout.LayoutChildIntoBoundingRegion(headerView, new Rectangle(0, 0, width, request.Request.Height));
+
+ Control.TableHeaderView = _headerRenderer.NativeView;
+ }
+
+ void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
+ {
+ if (Superview == null)
+ {
+ _requestedScroll = e;
+ return;
+ }
+
+ var position = GetScrollPosition(e.Position);
+
+ if (Element.IsGroupingEnabled)
+ {
+ var result = Element.TemplatedItems.GetGroupAndIndexOfItem(e.Group, e.Item);
+ if (result.Item1 != -1 && result.Item2 != -1)
+ Control.ScrollToRow(NSIndexPath.FromRowSection(result.Item2, result.Item1), position, e.ShouldAnimate);
+ }
+ else
+ {
+ var index = Element.TemplatedItems.GetGlobalIndexOfItem(e.Item);
+ if (index != -1)
+ Control.ScrollToRow(NSIndexPath.FromRowSection(index, 0), position, e.ShouldAnimate);
+ }
+ }
+
+ void UpdateEstimatedRowHeight()
+ {
+ if (_estimatedRowHeight)
+ return;
+
+ var rowHeight = Element.RowHeight;
+ if (Element.HasUnevenRows && rowHeight == -1)
+ {
+ var source = _dataSource as UnevenListViewDataSource;
+ if (_shouldEstimateRowHeight)
+ {
+ if (Element.TemplatedItems.Count > 0 && source != null)
+ {
+ var estimatedHeightFromFirstCell = source.CalculateHeightForCell(Control, Element.TemplatedItems.First());
+ Control.EstimatedRowHeight = estimatedHeightFromFirstCell;
+ _estimatedRowHeight = true;
+ }
+ else
+ {
+ //We need to set a default estimated row height, because re-setting it later(when we have items on the TIL)
+ //will cause the UITableView to reload, and throw a Excepetion
+ Control.EstimatedRowHeight = DefaultRowHeight;
+ }
+ }
+ }
+ else
+ {
+ if (Forms.IsiOS7OrNewer)
+ Control.EstimatedRowHeight = 0;
+ _estimatedRowHeight = true;
+ }
+ }
+
+ void UpdateFooter()
+ {
+ var footer = ((IListViewController)Element).FooterElement;
+ var footerView = (View)footer;
+
+ if (footerView != null)
+ {
+ if (_footerRenderer != null)
+ {
+ _footerRenderer.Element.MeasureInvalidated -= OnFooterMeasureInvalidated;
+ if (footer != null && _footerRenderer.GetType() == Registrar.Registered.GetHandlerType(footer.GetType()))
+ {
+ _footerRenderer.SetElement(footerView);
+ return;
+ }
+ Control.TableFooterView = null;
+ var platform = _footerRenderer.Element.Platform as Platform;
+ if (platform != null)
+ platform.DisposeModelAndChildrenRenderers(_footerRenderer.Element);
+ _footerRenderer.Dispose();
+ _footerRenderer = null;
+ }
+
+ _footerRenderer = Platform.CreateRenderer(footerView);
+ Platform.SetRenderer(footerView, _footerRenderer);
+
+ double width = Bounds.Width;
+ var request = footerView.Measure(width, double.PositiveInfinity, MeasureFlags.IncludeMargins);
+ Layout.LayoutChildIntoBoundingRegion(footerView, new Rectangle(0, 0, width, request.Request.Height));
+
+ Control.TableFooterView = _footerRenderer.NativeView;
+ footerView.MeasureInvalidated += OnFooterMeasureInvalidated;
+ }
+ else if (_footerRenderer != null)
+ {
+ Control.TableFooterView = null;
+ var platform = _footerRenderer.Element.Platform as Platform;
+ if (platform != null)
+ platform.DisposeModelAndChildrenRenderers(_footerRenderer.Element);
+ _footerRenderer.Dispose();
+ _footerRenderer = null;
+ }
+ }
+
+ void UpdateHeader()
+ {
+ var header = ((IListViewController)Element).HeaderElement;
+ var headerView = (View)header;
+
+ if (headerView != null)
+ {
+ if (_headerRenderer != null)
+ {
+ _headerRenderer.Element.MeasureInvalidated -= OnHeaderMeasureInvalidated;
+ if (header != null && _headerRenderer.GetType() == Registrar.Registered.GetHandlerType(header.GetType()))
+ {
+ _headerRenderer.SetElement(headerView);
+ return;
+ }
+ Control.TableHeaderView = null;
+ var platform = _headerRenderer.Element.Platform as Platform;
+ if (platform != null)
+ platform.DisposeModelAndChildrenRenderers(_headerRenderer.Element);
+ _headerRenderer = null;
+ }
+
+ _headerRenderer = Platform.CreateRenderer(headerView);
+ // This will force measure to invalidate, which we haven't hooked up to yet because we are smarter!
+ Platform.SetRenderer(headerView, _headerRenderer);
+
+ double width = Bounds.Width;
+ var request = headerView.Measure(width, double.PositiveInfinity, MeasureFlags.IncludeMargins);
+ Layout.LayoutChildIntoBoundingRegion(headerView, new Rectangle(0, 0, width, request.Request.Height));
+
+ Control.TableHeaderView = _headerRenderer.NativeView;
+ headerView.MeasureInvalidated += OnHeaderMeasureInvalidated;
+ }
+ else if (_headerRenderer != null)
+ {
+ Control.TableHeaderView = null;
+ var platform = _headerRenderer.Element.Platform as Platform;
+ if (platform != null)
+ platform.DisposeModelAndChildrenRenderers(_headerRenderer.Element);
+ _headerRenderer.Dispose();
+ _headerRenderer = null;
+ }
+ }
+
+ void UpdateIsRefreshing()
+ {
+ var refreshing = Element.IsRefreshing;
+ if (_tableViewController != null)
+ _tableViewController.UpdateIsRefreshing(refreshing);
+ }
+
+ void UpdateItems(NotifyCollectionChangedEventArgs e, int section, bool resetWhenGrouped)
+ {
+ var exArgs = e as NotifyCollectionChangedEventArgsEx;
+ if (exArgs != null)
+ _dataSource.Counts[section] = exArgs.Count;
+
+ var groupReset = resetWhenGrouped && Element.IsGroupingEnabled;
+
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ UpdateEstimatedRowHeight();
+ if (e.NewStartingIndex == -1 || groupReset)
+ goto case NotifyCollectionChangedAction.Reset;
+ Control.BeginUpdates();
+ Control.InsertRows(GetPaths(section, e.NewStartingIndex, e.NewItems.Count), UITableViewRowAnimation.Automatic);
+
+ Control.EndUpdates();
+
+ break;
+
+ case NotifyCollectionChangedAction.Remove:
+ if (e.OldStartingIndex == -1 || groupReset)
+ goto case NotifyCollectionChangedAction.Reset;
+ Control.BeginUpdates();
+ Control.DeleteRows(GetPaths(section, e.OldStartingIndex, e.OldItems.Count), UITableViewRowAnimation.Automatic);
+
+ Control.EndUpdates();
+
+ if (_estimatedRowHeight && Element.TemplatedItems.Count == 0)
+ _estimatedRowHeight = false;
+
+ break;
+
+ case NotifyCollectionChangedAction.Move:
+ if (e.OldStartingIndex == -1 || e.NewStartingIndex == -1 || groupReset)
+ goto case NotifyCollectionChangedAction.Reset;
+ Control.BeginUpdates();
+ for (var i = 0; i < e.OldItems.Count; i++)
+ {
+ var oldi = e.OldStartingIndex;
+ var newi = e.NewStartingIndex;
+
+ if (e.NewStartingIndex < e.OldStartingIndex)
+ {
+ oldi += i;
+ newi += i;
+ }
+
+ Control.MoveRow(NSIndexPath.FromRowSection(oldi, section), NSIndexPath.FromRowSection(newi, section));
+ }
+ Control.EndUpdates();
+
+ if (_estimatedRowHeight && e.OldStartingIndex == 0)
+ _estimatedRowHeight = false;
+
+ break;
+
+ case NotifyCollectionChangedAction.Replace:
+ if (e.OldStartingIndex == -1 || groupReset)
+ goto case NotifyCollectionChangedAction.Reset;
+ Control.BeginUpdates();
+ Control.ReloadRows(GetPaths(section, e.OldStartingIndex, e.OldItems.Count), UITableViewRowAnimation.Automatic);
+ Control.EndUpdates();
+
+ if (_estimatedRowHeight && e.OldStartingIndex == 0)
+ _estimatedRowHeight = false;
+
+ break;
+
+ case NotifyCollectionChangedAction.Reset:
+ _estimatedRowHeight = false;
+ Control.ReloadData();
+ return;
+ }
+ }
+
+ void UpdatePullToRefreshEnabled()
+ {
+ if (_tableViewController != null)
+ {
+ var isPullToRequestEnabled = Element.IsPullToRefreshEnabled && (Element as IListViewController).RefreshAllowed;
+ _tableViewController.UpdatePullToRefreshEnabled(isPullToRequestEnabled);
+ }
+ }
+
+ void UpdateRowHeight()
+ {
+ var rowHeight = Element.RowHeight;
+ if (Element.HasUnevenRows && rowHeight == -1 && Forms.IsiOS7OrNewer)
+ {
+ if (Forms.IsiOS8OrNewer)
+ Control.RowHeight = UITableView.AutomaticDimension;
+ }
+ else
+ Control.RowHeight = rowHeight <= 0 ? DefaultRowHeight : rowHeight;
+ }
+
+ void UpdateSeparatorColor()
+ {
+ var color = Element.SeparatorColor;
+ // ...and Steve said to the unbelievers the separator shall be gray, and gray it was. The unbelievers looked on, and saw that it was good, and
+ // they went forth and documented the default color. The holy scripture still reflects this default.
+ // Defined here: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/#//apple_ref/occ/instp/UITableView/separatorColor
+ Control.SeparatorColor = color.ToUIColor(UIColor.Gray);
+ }
+
+ void UpdateSeparatorVisibility()
+ {
+ var visibility = Element.SeparatorVisibility;
+ switch (visibility)
+ {
+ case SeparatorVisibility.Default:
+ Control.SeparatorStyle = UITableViewCellSeparatorStyle.SingleLine;
+ break;
+ case SeparatorVisibility.None:
+ Control.SeparatorStyle = UITableViewCellSeparatorStyle.None;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ internal class UnevenListViewDataSource : ListViewDataSource
+ {
+ IVisualElementRenderer _prototype;
+
+ public UnevenListViewDataSource(ListView list, FormsUITableViewController uiTableViewController) : base(list, uiTableViewController)
+ {
+ }
+
+ public UnevenListViewDataSource(ListViewDataSource source) : base(source)
+ {
+ }
+
+ public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
+ {
+ var cell = GetCellForPath(indexPath);
+
+ if (List.RowHeight == -1 && cell.Height == -1 && cell is ViewCell)
+ {
+ // only doing ViewCell because its the only one that matters (the others dont adjust ANYWAY)
+ if (Forms.IsiOS8OrNewer)
+ return UITableView.AutomaticDimension;
+ return CalculateHeightForCell(tableView, cell);
+ }
+
+ var renderHeight = cell.RenderHeight;
+ return renderHeight > 0 ? (nfloat)renderHeight : DefaultRowHeight;
+ }
+
+ internal nfloat CalculateHeightForCell(UITableView tableView, Cell cell)
+ {
+ var viewCell = cell as ViewCell;
+ if (viewCell != null && viewCell.View != null)
+ {
+ var target = viewCell.View;
+ if (_prototype == null)
+ {
+ _prototype = Platform.CreateRenderer(target);
+ Platform.SetRenderer(target, _prototype);
+ }
+ else
+ {
+ _prototype.SetElement(target);
+ Platform.SetRenderer(target, _prototype);
+ }
+
+ var req = target.Measure(tableView.Frame.Width, double.PositiveInfinity, MeasureFlags.IncludeMargins);
+
+ target.ClearValue(Platform.RendererProperty);
+ foreach (var descendant in target.Descendants())
+ descendant.ClearValue(Platform.RendererProperty);
+
+ return (nfloat)req.Request.Height;
+ }
+ var renderHeight = cell.RenderHeight;
+ return renderHeight > 0 ? (nfloat)renderHeight : DefaultRowHeight;
+ }
+ }
+
+ internal class ListViewDataSource : UITableViewSource
+ {
+ const int DefaultItemTemplateId = 1;
+ static int s_dataTemplateIncrementer = 2; // lets start at not 0 because
+ readonly nfloat _defaultSectionHeight;
+ readonly Dictionary<DataTemplate, int> _templateToId = new Dictionary<DataTemplate, int>();
+ readonly UITableView _uiTableView;
+ readonly FormsUITableViewController _uiTableViewController;
+ protected readonly ListView List;
+ bool _isDragging;
+ bool _selectionFromNative;
+
+ public ListViewDataSource(ListViewDataSource source)
+ {
+ _uiTableViewController = source._uiTableViewController;
+ List = source.List;
+ _uiTableView = source._uiTableView;
+ _defaultSectionHeight = source._defaultSectionHeight;
+ _selectionFromNative = source._selectionFromNative;
+
+ Counts = new Dictionary<int, int>();
+ }
+
+ public ListViewDataSource(ListView list, FormsUITableViewController uiTableViewController)
+ {
+ _uiTableViewController = uiTableViewController;
+ _uiTableView = uiTableViewController.TableView;
+ _defaultSectionHeight = Forms.IsiOS8OrNewer ? DefaultRowHeight : _uiTableView.SectionHeaderHeight;
+ List = list;
+ List.ItemSelected += OnItemSelected;
+ UpdateShortNameListener();
+
+ Counts = new Dictionary<int, int>();
+ }
+
+ public Dictionary<int, int> Counts { get; set; }
+
+ UIColor DefaultBackgroundColor
+ {
+ get { return UIColor.Clear; }
+ }
+
+ public override void DraggingEnded(UIScrollView scrollView, bool willDecelerate)
+ {
+ _isDragging = false;
+ _uiTableViewController.UpdateShowHideRefresh(false);
+ }
+
+ public override void DraggingStarted(UIScrollView scrollView)
+ {
+ _isDragging = true;
+ }
+
+ public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
+ {
+ UITableViewCell nativeCell = null;
+
+ var cachingStrategy = List.CachingStrategy;
+ if (cachingStrategy == ListViewCachingStrategy.RetainElement)
+ {
+ var cell = GetCellForPath(indexPath);
+ nativeCell = CellTableViewCell.GetNativeCell(tableView, cell);
+ }
+ else if (cachingStrategy == ListViewCachingStrategy.RecycleElement)
+ {
+ var id = TemplateIdForPath(indexPath);
+ nativeCell = tableView.DequeueReusableCell(ContextActionsCell.Key + id);
+ if (nativeCell == null)
+ {
+ var cell = GetCellForPath(indexPath);
+ nativeCell = CellTableViewCell.GetNativeCell(tableView, cell, true, id.ToString());
+ }
+ else
+ {
+ var templatedList = List.TemplatedItems.GetGroup(indexPath.Section);
+ var cell = (Cell)((INativeElementView)nativeCell).Element;
+ cell.SendDisappearing();
+ templatedList.UpdateContent(cell, indexPath.Row);
+ cell.SendAppearing();
+ }
+ }
+ else
+ throw new NotSupportedException();
+
+ var bgColor = tableView.IndexPathForSelectedRow != null && tableView.IndexPathForSelectedRow.Equals(indexPath) ? UIColor.Clear : DefaultBackgroundColor;
+
+ SetCellBackgroundColor(nativeCell, bgColor);
+
+ return nativeCell;
+ }
+
+ public override nfloat GetHeightForHeader(UITableView tableView, nint section)
+ {
+ if (List.IsGroupingEnabled)
+ {
+ var cell = List.TemplatedItems[(int)section];
+ nfloat height = (float)cell.RenderHeight;
+ if (height == -1)
+ height = _defaultSectionHeight;
+
+ return height;
+ }
+
+ return 0;
+ }
+
+ public override UIView GetViewForHeader(UITableView tableView, nint section)
+ {
+ if (List.IsGroupingEnabled && List.GroupHeaderTemplate != null)
+ {
+ var cell = List.TemplatedItems[(int)section];
+ if (cell.HasContextActions)
+ throw new NotSupportedException("Header cells do not support context actions");
+
+ var renderer = (CellRenderer)Registrar.Registered.GetHandler(cell.GetType());
+
+ var view = new HeaderWrapperView();
+ view.AddSubview(renderer.GetCell(cell, null, tableView));
+
+ return view;
+ }
+
+ return null;
+ }
+
+ public override nint NumberOfSections(UITableView tableView)
+ {
+ if (List.IsGroupingEnabled)
+ return List.TemplatedItems.Count;
+
+ return 1;
+ }
+
+ public void OnItemSelected(object sender, SelectedItemChangedEventArgs eventArg)
+ {
+ if (_selectionFromNative)
+ {
+ _selectionFromNative = false;
+ return;
+ }
+
+ var location = List.TemplatedItems.GetGroupAndIndexOfItem(eventArg.SelectedItem);
+ if (location.Item1 == -1 || location.Item2 == -1)
+ {
+ var selectedIndexPath = _uiTableView.IndexPathForSelectedRow;
+
+ var animate = true;
+
+ if (selectedIndexPath != null)
+ {
+ var cell = _uiTableView.CellAt(selectedIndexPath) as ContextActionsCell;
+ if (cell != null)
+ {
+ cell.PrepareForDeselect();
+ if (cell.IsOpen)
+ animate = false;
+ }
+ }
+
+ if (selectedIndexPath != null)
+ _uiTableView.DeselectRow(selectedIndexPath, animate);
+ return;
+ }
+
+ _uiTableView.SelectRow(NSIndexPath.FromRowSection(location.Item2, location.Item1), true, UITableViewScrollPosition.Middle);
+ }
+
+ public override void RowDeselected(UITableView tableView, NSIndexPath indexPath)
+ {
+ var cell = tableView.CellAt(indexPath);
+ if (cell == null)
+ return;
+
+ SetCellBackgroundColor(cell, DefaultBackgroundColor);
+ }
+
+ public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
+ {
+ var cell = tableView.CellAt(indexPath);
+
+ if (cell == null)
+ return;
+
+ Cell formsCell = null;
+ if (List.CachingStrategy == ListViewCachingStrategy.RecycleElement)
+ formsCell = (Cell)((INativeElementView)cell).Element;
+
+ SetCellBackgroundColor(cell, UIColor.Clear);
+
+ _selectionFromNative = true;
+
+ tableView.EndEditing(true);
+ List.NotifyRowTapped(indexPath.Section, indexPath.Row, formsCell);
+ }
+
+ public override nint RowsInSection(UITableView tableview, nint section)
+ {
+ int countOverride;
+ if (Counts.TryGetValue((int)section, out countOverride))
+ {
+ Counts.Remove((int)section);
+ return countOverride;
+ }
+
+ if (List.IsGroupingEnabled)
+ {
+ var group = (IList)((IList)List.TemplatedItems)[(int)section];
+ return group.Count;
+ }
+
+ return List.TemplatedItems.Count;
+ }
+
+ public override void Scrolled(UIScrollView scrollView)
+ {
+ if (_isDragging && scrollView.ContentOffset.Y < 0)
+ _uiTableViewController.UpdateShowHideRefresh(true);
+ }
+
+ public override string[] SectionIndexTitles(UITableView tableView)
+ {
+ if (List.TemplatedItems.ShortNames == null)
+ return null;
+
+ return List.TemplatedItems.ShortNames.ToArray();
+ }
+
+ public override string TitleForHeader(UITableView tableView, nint section)
+ {
+ if (!List.IsGroupingEnabled)
+ return null;
+
+ var sl = GetSectionList((int)section);
+ sl.PropertyChanged -= OnSectionPropertyChanged;
+ sl.PropertyChanged += OnSectionPropertyChanged;
+
+ return sl.Name;
+ }
+
+ public void UpdateGrouping()
+ {
+ UpdateShortNameListener();
+ _uiTableView.ReloadData();
+ }
+
+ protected Cell GetCellForPath(NSIndexPath indexPath)
+ {
+ var templatedList = List.TemplatedItems;
+ if (List.IsGroupingEnabled)
+ templatedList = (TemplatedItemsList<ItemsView<Cell>, Cell>)((IList)templatedList)[indexPath.Section];
+
+ var cell = templatedList[indexPath.Row];
+ return cell;
+ }
+
+ TemplatedItemsList<ItemsView<Cell>, Cell> GetSectionList(int section)
+ {
+ return (TemplatedItemsList<ItemsView<Cell>, Cell>)((IList)List.TemplatedItems)[section];
+ }
+
+ void OnSectionPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ var currentSelected = _uiTableView.IndexPathForSelectedRow;
+
+ var til = (TemplatedItemsList<ItemsView<Cell>, Cell>)sender;
+ var groupIndex = ((IList)List.TemplatedItems).IndexOf(til);
+ if (groupIndex == -1)
+ {
+ til.PropertyChanged -= OnSectionPropertyChanged;
+ return;
+ }
+
+ _uiTableView.ReloadSections(NSIndexSet.FromIndex(groupIndex), UITableViewRowAnimation.Automatic);
+ _uiTableView.SelectRow(currentSelected, false, UITableViewScrollPosition.None);
+ }
+
+ void OnShortNamesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ _uiTableView.ReloadSectionIndexTitles();
+ }
+
+ static void SetCellBackgroundColor(UITableViewCell cell, UIColor color)
+ {
+ var contextCell = cell as ContextActionsCell;
+ cell.BackgroundColor = color;
+ if (contextCell != null)
+ contextCell.ContentCell.BackgroundColor = color;
+ }
+
+ int TemplateIdForPath(NSIndexPath indexPath)
+ {
+ var itemTemplate = List.ItemTemplate;
+ var selector = itemTemplate as DataTemplateSelector;
+ if (selector == null)
+ return DefaultItemTemplateId;
+
+ var templatedList = List.TemplatedItems;
+ if (List.IsGroupingEnabled)
+ templatedList = (TemplatedItemsList<ItemsView<Cell>, Cell>)((IList)templatedList)[indexPath.Section];
+
+ var item = templatedList.ListProxy[indexPath.Row];
+
+ itemTemplate = selector.SelectTemplate(item, List);
+ int key;
+ if (!_templateToId.TryGetValue(itemTemplate, out key))
+ {
+ s_dataTemplateIncrementer++;
+ key = s_dataTemplateIncrementer;
+ _templateToId[itemTemplate] = key;
+ }
+ return key;
+ }
+
+ void UpdateShortNameListener()
+ {
+ if (List.IsGroupingEnabled)
+ {
+ if (List.TemplatedItems.ShortNames != null)
+ ((INotifyCollectionChanged)List.TemplatedItems.ShortNames).CollectionChanged += OnShortNamesCollectionChanged;
+ }
+ else
+ {
+ if (List.TemplatedItems.ShortNames != null)
+ ((INotifyCollectionChanged)List.TemplatedItems.ShortNames).CollectionChanged -= OnShortNamesCollectionChanged;
+ }
+ }
+ }
+ }
+
+ internal class HeaderWrapperView : UIView
+ {
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+ foreach (var item in Subviews)
+ item.Frame = Bounds;
+ }
+ }
+
+ internal class FormsUITableViewController : UITableViewController
+ {
+ readonly ListView _list;
+ UIRefreshControl _refresh;
+
+ bool _refreshAdded;
+
+ public FormsUITableViewController(ListView element)
+ {
+ if (Forms.IsiOS9OrNewer)
+ TableView.CellLayoutMarginsFollowReadableWidth = false;
+ _refresh = new UIRefreshControl();
+ _refresh.ValueChanged += OnRefreshingChanged;
+ _list = element;
+ }
+
+ public void UpdateIsRefreshing(bool refreshing)
+ {
+ if (refreshing)
+ {
+ if (!_refreshAdded)
+ {
+ RefreshControl = _refresh;
+ _refreshAdded = true;
+ }
+
+ if (!_refresh.Refreshing)
+ {
+ _refresh.BeginRefreshing();
+
+ //hack: when we don't have cells in our UITableView the spinner fails to appear
+ CheckContentSize();
+
+ TableView.ScrollRectToVisible(new RectangleF(0, 0, _refresh.Bounds.Width, _refresh.Bounds.Height), true);
+ }
+ }
+ else
+ {
+ _refresh.EndRefreshing();
+
+ if (!_list.IsPullToRefreshEnabled)
+ RemoveRefresh();
+ }
+ }
+
+ public void UpdatePullToRefreshEnabled(bool pullToRefreshEnabled)
+ {
+ if (pullToRefreshEnabled)
+ {
+ if (!_refreshAdded)
+ {
+ _refreshAdded = true;
+ RefreshControl = _refresh;
+ }
+ }
+ else if (_refreshAdded)
+ {
+ if (_refresh.Refreshing)
+ _refresh.EndRefreshing();
+
+ RefreshControl = null;
+ _refreshAdded = false;
+ }
+ }
+
+ public void UpdateShowHideRefresh(bool shouldHide)
+ {
+ if (_list.IsPullToRefreshEnabled)
+ return;
+
+ if (shouldHide)
+ RemoveRefresh();
+ else
+ UpdateIsRefreshing(_list.IsRefreshing);
+ }
+
+ public override void ViewWillAppear(bool animated)
+ {
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (disposing && _refresh != null)
+ {
+ _refresh.ValueChanged -= OnRefreshingChanged;
+ _refresh.EndRefreshing();
+ _refresh.Dispose();
+ _refresh = null;
+ }
+ }
+
+ void CheckContentSize()
+ {
+ //adding a default height of at least 1 pixel tricks iOS to show the spinner
+ var contentSize = TableView.ContentSize;
+ if (contentSize.Height == 0)
+ TableView.ContentSize = new SizeF(contentSize.Width, 1);
+ }
+
+ void OnRefreshingChanged(object sender, EventArgs eventArgs)
+ {
+ if (_refresh.Refreshing)
+ (_list as IListViewController).SendRefreshing();
+ }
+
+ void RemoveRefresh()
+ {
+ if (!_refreshAdded)
+ return;
+
+ if (_refresh.Refreshing)
+ _refresh.EndRefreshing();
+
+ RefreshControl = null;
+ _refreshAdded = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/NavigationMenuRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/NavigationMenuRenderer.cs
new file mode 100644
index 00000000..7136a61d
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/NavigationMenuRenderer.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Drawing;
+using System.Linq;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class NavigationMenuRenderer : ViewRenderer
+ {
+ UICollectionView _collectionView;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<View> e)
+ {
+ base.OnElementChanged(e);
+ var pad = UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad;
+ var size = pad ? 220 : 142;
+ var margin = pad ? 27 : 12;
+ var bottomMargin = (int)(margin * 0.8);
+
+ _collectionView = new UICollectionView(new RectangleF(0, 0, 100, 100),
+ new UICollectionViewFlowLayout
+ {
+ ItemSize = new SizeF(size, size + 30),
+ ScrollDirection = UICollectionViewScrollDirection.Vertical,
+ SectionInset = new UIEdgeInsets(margin, margin, bottomMargin, margin),
+ MinimumInteritemSpacing = margin,
+ MinimumLineSpacing = margin
+ }) { DataSource = new DataSource((NavigationMenu)Element), BackgroundColor = UIColor.White };
+
+ using(var navigationCellId = new NSString("NavigationCell"))
+ _collectionView.RegisterClassForCell(typeof(NavigationCell), navigationCellId);
+
+ SetNativeControl(_collectionView);
+ }
+
+ sealed class NavigationCell : UICollectionViewCell
+ {
+ readonly UIButton _image = new UIButton(RectangleF.Empty);
+
+ readonly UILabel _nameLabel = new UILabel(RectangleF.Empty) { BackgroundColor = UIColor.Clear, TextAlignment = UITextAlignment.Center, Font = UIFont.SystemFontOfSize(14) };
+
+ string _icon;
+
+ [Export("initWithFrame:")]
+ public NavigationCell(RectangleF frame) : base(frame)
+ {
+ SetupLayer();
+ _image.TouchUpInside += (object sender, EventArgs e) =>
+ {
+ if (Selected != null)
+ Selected();
+ };
+ _image.ContentMode = UIViewContentMode.ScaleAspectFit;
+ _image.Center = ContentView.Center;
+
+ ContentView.AddSubview(_image);
+ ContentView.AddSubview(_nameLabel);
+ }
+
+ public string Icon
+ {
+ get { return _icon; }
+ set
+ {
+ _icon = value;
+ _image.SetImage(new UIImage(_icon), UIControlState.Normal);
+ }
+ }
+
+ public string Name
+ {
+ get { return _nameLabel.Text; }
+ set { _nameLabel.Text = value; }
+ }
+
+ public Action Selected { get; set; }
+
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+ _image.Frame = new RectangleF(0, 0, ContentView.Frame.Width, ContentView.Frame.Height - 30);
+ var sizeThatFits = _nameLabel.SizeThatFits(ContentView.Frame.Size);
+ _nameLabel.Frame = new RectangleF(0, ContentView.Frame.Height - 15 - sizeThatFits.Height / 2, ContentView.Frame.Width, sizeThatFits.Height);
+ }
+
+ void SetupLayer()
+ {
+ var layer = _image.Layer;
+
+ layer.ShadowRadius = 6;
+ layer.ShadowColor = UIColor.Black.CGColor;
+ layer.ShadowOpacity = 0.2f;
+ layer.ShadowOffset = new SizeF();
+
+ layer.RasterizationScale = UIScreen.MainScreen.Scale;
+ layer.ShouldRasterize = true;
+ }
+ }
+
+ class DataSource : UICollectionViewDataSource
+ {
+ readonly NavigationMenu _menu;
+
+ public DataSource(NavigationMenu menu)
+ {
+ _menu = menu;
+ }
+
+ public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
+ {
+ var cell = (NavigationCell)collectionView.DequeueReusableCell(new NSString("NavigationCell"), indexPath);
+ var target = _menu.Targets.Skip(indexPath.Row).FirstOrDefault();
+
+ if (target != null)
+ {
+ cell.Name = target.Title;
+ cell.Icon = target.Icon;
+ cell.Selected = () => _menu.SendTargetSelected(target);
+ }
+ else
+ {
+ cell.Selected = null;
+ cell.Icon = "";
+ cell.Name = "";
+ }
+
+ return cell;
+ }
+
+ public override nint GetItemsCount(UICollectionView collectionView, nint section)
+ {
+ return _menu.Targets.Count();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/NavigationRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/NavigationRenderer.cs
new file mode 100644
index 00000000..63330564
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/NavigationRenderer.cs
@@ -0,0 +1,918 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+#if __UNIFIED__
+using UIKit;
+using CoreGraphics;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.CoreGraphics;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class NavigationRenderer : UINavigationController, IVisualElementRenderer
+ {
+ internal const string UpdateToolbarButtons = "Xamarin.UpdateToolbarButtons";
+ bool _appeared;
+ bool _ignorePopCall;
+ bool _loaded;
+ MasterDetailPage _parentMasterDetailPage;
+ Size _queuedSize;
+ UIViewController[] _removeControllers;
+ UIToolbar _secondaryToolbar;
+
+ VisualElementTracker _tracker;
+
+ public NavigationRenderer()
+ {
+ MessagingCenter.Subscribe<IVisualElementRenderer>(this, UpdateToolbarButtons, sender =>
+ {
+ if (!ViewControllers.Any())
+ return;
+ var parentingViewController = (ParentingViewController)ViewControllers.Last();
+ UpdateLeftBarButtonItem(parentingViewController);
+ });
+ }
+
+ Page Current { get; set; }
+
+ public VisualElement Element { get; private set; }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return NativeView.GetSizeRequest(widthConstraint, heightConstraint);
+ }
+
+ public UIView NativeView
+ {
+ get { return View; }
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ var oldElement = Element;
+ Element = (NavigationPage)element;
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+
+ if (element != null)
+ element.SendViewInitialized(NativeView);
+ }
+
+ public void SetElementSize(Size size)
+ {
+ if (_loaded)
+ Element.Layout(new Rectangle(Element.X, Element.Y, size.Width, size.Height));
+ else
+ _queuedSize = size;
+ }
+
+ public UIViewController ViewController
+ {
+ get { return this; }
+ }
+
+ public override void DidRotate(UIInterfaceOrientation fromInterfaceOrientation)
+ {
+ base.DidRotate(fromInterfaceOrientation);
+
+ View.SetNeedsLayout();
+
+ var parentingViewController = (ParentingViewController)ViewControllers.Last();
+ UpdateLeftBarButtonItem(parentingViewController);
+ }
+
+ public Task<bool> PopToRootAsync(Page page, bool animated = true)
+ {
+ return OnPopToRoot(page, animated);
+ }
+
+ public override UIViewController[] PopToRootViewController(bool animated)
+ {
+ if (!_ignorePopCall && ViewControllers.Length > 1)
+ RemoveViewControllers(animated);
+
+ return base.PopToRootViewController(animated);
+ }
+
+ public Task<bool> PopViewAsync(Page page, bool animated = true)
+ {
+ return OnPopViewAsync(page, animated);
+ }
+
+#if __UNIFIED__
+ public override UIViewController PopViewController(bool animated)
+#else
+ public override UIViewController PopViewControllerAnimated (bool animated)
+ #endif
+ {
+ RemoveViewControllers(animated);
+#if __UNIFIED__
+ return base.PopViewController(animated);
+#else
+ return base.PopViewControllerAnimated (animated);
+ #endif
+ }
+
+ public Task<bool> PushPageAsync(Page page, bool animated = true)
+ {
+ return OnPushAsync(page, animated);
+ }
+
+ public override void ViewDidAppear(bool animated)
+ {
+ if (!_appeared)
+ {
+ _appeared = true;
+ ((NavigationPage)Element)?.SendAppearing();
+ }
+
+ base.ViewDidAppear(animated);
+
+ View.SetNeedsLayout();
+ }
+
+ public override void ViewDidDisappear(bool animated)
+ {
+ base.ViewDidDisappear(animated);
+
+ if (!_appeared || Element == null)
+ return;
+
+ _appeared = false;
+ ((NavigationPage)Element).SendDisappearing();
+ }
+
+ public override void ViewDidLayoutSubviews()
+ {
+ base.ViewDidLayoutSubviews();
+ UpdateToolBarVisible();
+
+ var navBarFrame = NavigationBar.Frame;
+
+ var toolbar = _secondaryToolbar;
+ // Use 0 if the NavBar is hidden or will be hidden
+ var toolbarY = NavigationBarHidden || !NavigationPage.GetHasNavigationBar(Current) ? 0 : navBarFrame.Bottom;
+ toolbar.Frame = new RectangleF(0, toolbarY, View.Frame.Width, toolbar.Frame.Height);
+
+ double trueBottom = toolbar.Hidden ? toolbarY : toolbar.Frame.Bottom;
+ var modelSize = _queuedSize.IsZero ? Element.Bounds.Size : _queuedSize;
+ ((NavigationPage)Element).ContainerArea = new Rectangle(0, toolbar.Hidden ? 0 : toolbar.Frame.Height, modelSize.Width, modelSize.Height - trueBottom);
+
+ if (!_queuedSize.IsZero)
+ {
+ Element.Layout(new Rectangle(Element.X, Element.Y, _queuedSize.Width, _queuedSize.Height));
+ _queuedSize = Size.Zero;
+ }
+
+ _loaded = true;
+
+ foreach (var view in View.Subviews)
+ {
+ if (view == NavigationBar || view == _secondaryToolbar)
+ continue;
+ view.Frame = View.Bounds;
+ }
+ }
+
+ public override void ViewDidLoad()
+ {
+ base.ViewDidLoad();
+
+ if (Forms.IsiOS7OrNewer)
+ NavigationBar.Translucent = false;
+ else
+ WantsFullScreenLayout = false;
+
+ _secondaryToolbar = new SecondaryToolbar { Frame = new RectangleF(0, 0, 320, 44) };
+ View.Add(_secondaryToolbar);
+ _secondaryToolbar.Hidden = true;
+
+ FindParentMasterDetail();
+
+ var navPage = (NavigationPage)Element;
+
+ if (navPage.CurrentPage == null)
+ {
+ throw new InvalidOperationException("NavigationPage must have a root Page before being used. Either call PushAsync with a valid Page, or pass a Page to the constructor before usage.");
+ }
+
+ navPage.PushRequested += OnPushRequested;
+ navPage.PopRequested += OnPopRequested;
+ navPage.PopToRootRequested += OnPopToRootRequested;
+ navPage.RemovePageRequested += OnRemovedPageRequested;
+ navPage.InsertPageBeforeRequested += OnInsertPageBeforeRequested;
+
+ UpdateTint();
+ UpdateBarBackgroundColor();
+ UpdateBarTextColor();
+
+ // If there is already stuff on the stack we need to push it
+ navPage.StackCopy.Reverse().ForEach(async p => await PushPageAsync(p, false));
+
+ _tracker = new VisualElementTracker(this);
+
+ Element.PropertyChanged += HandlePropertyChanged;
+
+ UpdateToolBarVisible();
+ UpdateBackgroundColor();
+ Current = navPage.CurrentPage;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ MessagingCenter.Unsubscribe<IVisualElementRenderer>(this, UpdateToolbarButtons);
+
+ foreach (var childViewController in ViewControllers)
+ childViewController.Dispose();
+
+ if (_tracker != null)
+ _tracker.Dispose();
+
+ _secondaryToolbar.RemoveFromSuperview();
+ _secondaryToolbar.Dispose();
+ _secondaryToolbar = null;
+
+ _parentMasterDetailPage = null;
+ Current = null; // unhooks events
+
+ var navPage = (NavigationPage)Element;
+ navPage.PropertyChanged -= HandlePropertyChanged;
+ navPage.PushRequested -= OnPushRequested;
+ navPage.PopRequested -= OnPopRequested;
+ navPage.PopToRootRequested -= OnPopToRootRequested;
+ navPage.RemovePageRequested -= OnRemovedPageRequested;
+ navPage.InsertPageBeforeRequested -= OnInsertPageBeforeRequested;
+ }
+
+ base.Dispose(disposing);
+ if (_appeared)
+ {
+ ((Page)Element).SendDisappearing();
+
+ _appeared = false;
+ }
+ }
+
+ protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ var changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ protected virtual async Task<bool> OnPopToRoot(Page page, bool animated)
+ {
+ _ignorePopCall = true;
+ var renderer = Platform.GetRenderer(page);
+ if (renderer == null || renderer.ViewController == null)
+ return false;
+
+ var task = GetAppearedOrDisappearedTask(page);
+
+ PopToRootViewController(animated);
+
+ _ignorePopCall = false;
+ var success = !await task;
+
+ UpdateToolBarVisible();
+ return success;
+ }
+
+ protected virtual async Task<bool> OnPopViewAsync(Page page, bool animated)
+ {
+ if (_ignorePopCall)
+ return true;
+
+ var renderer = Platform.GetRenderer(page);
+ if (renderer == null || renderer.ViewController == null)
+ return false;
+
+ var actuallyRemoved = false;
+
+ if (page != ((ParentingViewController)TopViewController).Child)
+ throw new NotSupportedException("Popped page does not appear on top of current navigation stack, please file a bug.");
+
+ var task = GetAppearedOrDisappearedTask(page);
+
+ UIViewController poppedViewController;
+#if __UNIFIED__
+ poppedViewController = base.PopViewController(animated);
+#else
+ poppedViewController = base.PopViewControllerAnimated (animated);
+ #endif
+
+ if (poppedViewController == null)
+ {
+ // this happens only when the user does something REALLY dumb like pop right after putting the page as visible.
+ poppedViewController = TopViewController;
+ var newControllers = ViewControllers.Remove(poppedViewController);
+ ViewControllers = newControllers;
+ actuallyRemoved = true;
+ }
+ else
+ actuallyRemoved = !await task;
+
+ poppedViewController.Dispose();
+
+ UpdateToolBarVisible();
+ return actuallyRemoved;
+ }
+
+ protected virtual async Task<bool> OnPushAsync(Page page, bool animated)
+ {
+ var pack = CreateViewControllerForPage(page);
+ var task = GetAppearedOrDisappearedTask(page);
+
+ PushViewController(pack, animated);
+
+ var shown = await task;
+ UpdateToolBarVisible();
+ return shown;
+ }
+
+ ParentingViewController CreateViewControllerForPage(Page page)
+ {
+ if (Platform.GetRenderer(page) == null)
+ Platform.SetRenderer(page, Platform.CreateRenderer(page));
+
+ // must pack into container so padding can work
+ // otherwise the view controller is forced to 0,0
+ var pack = new ParentingViewController(this) { Child = page };
+ if (!string.IsNullOrWhiteSpace(page.Title))
+ pack.NavigationItem.Title = page.Title;
+
+ // First page and we have a master detail to contend with
+ UpdateLeftBarButtonItem(pack);
+
+ //var pack = Platform.GetRenderer (view).ViewController;
+
+ var titleIcon = NavigationPage.GetTitleIcon(page);
+ if (!string.IsNullOrEmpty(titleIcon))
+ {
+ try
+ {
+ //UIImage ctor throws on file not found if MonoTouch.ObjCRuntime.Class.ThrowOnInitFailure is true;
+ pack.NavigationItem.TitleView = new UIImageView(new UIImage(titleIcon));
+ }
+ catch
+ {
+ }
+ }
+
+ var titleText = NavigationPage.GetBackButtonTitle(page);
+ if (titleText != null)
+ {
+ pack.NavigationItem.BackBarButtonItem = new UIBarButtonItem(titleText, UIBarButtonItemStyle.Plain, async (o, e) => await PopViewAsync(page));
+ }
+
+ var pageRenderer = Platform.GetRenderer(page);
+ pack.View.AddSubview(pageRenderer.ViewController.View);
+ pack.AddChildViewController(pageRenderer.ViewController);
+ pageRenderer.ViewController.DidMoveToParentViewController(pack);
+
+ return pack;
+ }
+
+ void FindParentMasterDetail()
+ {
+ var parentPages = ((Page)Element).GetParentPages();
+ var masterDetail = parentPages.OfType<MasterDetailPage>().FirstOrDefault();
+
+ if (masterDetail != null && parentPages.Append((Page)Element).Contains(masterDetail.Detail))
+ _parentMasterDetailPage = masterDetail;
+ }
+
+ Task<bool> GetAppearedOrDisappearedTask(Page page)
+ {
+ var tcs = new TaskCompletionSource<bool>();
+
+ var parentViewController = Platform.GetRenderer(page).ViewController.ParentViewController as ParentingViewController;
+ if (parentViewController == null)
+ throw new NotSupportedException("ParentingViewController parent could not be found. Please file a bug.");
+
+ EventHandler appearing = null, disappearing = null;
+ appearing = (s, e) =>
+ {
+ parentViewController.Appearing -= appearing;
+ parentViewController.Disappearing -= disappearing;
+
+ Device.BeginInvokeOnMainThread(() => { tcs.SetResult(true); });
+ };
+
+ disappearing = (s, e) =>
+ {
+ parentViewController.Appearing -= appearing;
+ parentViewController.Disappearing -= disappearing;
+
+ Device.BeginInvokeOnMainThread(() => { tcs.SetResult(false); });
+ };
+
+ parentViewController.Appearing += appearing;
+ parentViewController.Disappearing += disappearing;
+
+ return tcs.Task;
+ }
+
+ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == NavigationPage.TintProperty.PropertyName)
+ UpdateTint();
+ if (e.PropertyName == NavigationPage.BarBackgroundColorProperty.PropertyName)
+ UpdateBarBackgroundColor();
+ else if (e.PropertyName == NavigationPage.BarTextColorProperty.PropertyName)
+ UpdateBarTextColor();
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackgroundColor();
+ else if (e.PropertyName == NavigationPage.CurrentPageProperty.PropertyName)
+ Current = ((NavigationPage)Element).CurrentPage;
+ }
+
+ void InsertPageBefore(Page page, Page before)
+ {
+ if (before == null)
+ throw new ArgumentNullException("before");
+ if (page == null)
+ throw new ArgumentNullException("page");
+
+ var pageContainer = CreateViewControllerForPage(page);
+ var target = Platform.GetRenderer(before).ViewController.ParentViewController;
+ ViewControllers = ViewControllers.Insert(ViewControllers.IndexOf(target), pageContainer);
+ }
+
+ void OnInsertPageBeforeRequested(object sender, NavigationRequestedEventArgs e)
+ {
+ InsertPageBefore(e.Page, e.BeforePage);
+ }
+
+ void OnPopRequested(object sender, NavigationRequestedEventArgs e)
+ {
+ e.Task = PopViewAsync(e.Page, e.Animated);
+ }
+
+ void OnPopToRootRequested(object sender, NavigationRequestedEventArgs e)
+ {
+ e.Task = PopToRootAsync(e.Page, e.Animated);
+ }
+
+ void OnPushRequested(object sender, NavigationRequestedEventArgs e)
+ {
+ e.Task = PushPageAsync(e.Page, e.Animated);
+ }
+
+ void OnRemovedPageRequested(object sender, NavigationRequestedEventArgs e)
+ {
+ RemovePage(e.Page);
+ }
+
+ void RemovePage(Page page)
+ {
+ if (page == null)
+ throw new ArgumentNullException("page");
+ if (page == Current)
+ throw new NotSupportedException(); // should never happen as NavPage protecs against this
+
+ var target = Platform.GetRenderer(page).ViewController.ParentViewController;
+
+ // So the ViewControllers property is not very property like on iOS. Assigning to it doesn't cause it to be
+ // immediately reflected into the property. The change will not be reflected until there has been sufficient time
+ // to process it (it ends up on the event queue). So to resolve this issue we keep our own stack until we
+ // know iOS has processed it, and make sure any updates use that.
+
+ // In the future we may want to make RemovePageAsync and deprecate RemovePage to handle cases where Push/Pop is called
+ // during a remove cycle.
+
+ if (_removeControllers == null)
+ {
+ _removeControllers = ViewControllers.Remove(target);
+ ViewControllers = _removeControllers;
+ Device.BeginInvokeOnMainThread(() => { _removeControllers = null; });
+ }
+ else
+ {
+ _removeControllers = _removeControllers.Remove(target);
+ ViewControllers = _removeControllers;
+ }
+ }
+
+ void RemoveViewControllers(bool animated)
+ {
+ var controller = TopViewController as ParentingViewController;
+ if (controller == null || controller.Child == null)
+ return;
+
+ // Gesture in progress, lets not be proactive and just wait for it to finish
+ var count = ViewControllers.Length;
+ var task = GetAppearedOrDisappearedTask(controller.Child);
+ task.ContinueWith(async t =>
+ {
+ // task returns true if the user lets go of the page and is not popped
+ // however at this point the renderer is already off the visual stack so we just need to update the NavigationPage
+ // Also worth noting this task returns on the main thread
+ if (t.Result)
+ return;
+ _ignorePopCall = true;
+ // because iOS will just chain multiple animations together...
+ var removed = count - ViewControllers.Length;
+ for (var i = 0; i < removed; i++)
+ {
+ // lets just pop these suckers off, do not await, the true is there to make this fast
+ await ((NavigationPage)Element).PopAsyncInner(animated, true);
+ }
+ // because we skip the normal pop process we need to dispose ourselves
+ controller.Dispose();
+ _ignorePopCall = false;
+ }, TaskScheduler.FromCurrentSynchronizationContext());
+ }
+
+ void UpdateBackgroundColor()
+ {
+ var color = Element.BackgroundColor == Color.Default ? Color.White : Element.BackgroundColor;
+ View.BackgroundColor = color.ToUIColor();
+ }
+
+ void UpdateBarBackgroundColor()
+ {
+ var barBackgroundColor = ((NavigationPage)Element).BarBackgroundColor;
+ // Set navigation bar background color
+ if (Forms.IsiOS7OrNewer)
+ {
+ NavigationBar.BarTintColor = barBackgroundColor == Color.Default ? UINavigationBar.Appearance.BarTintColor : barBackgroundColor.ToUIColor();
+ }
+ else
+ {
+ NavigationBar.TintColor = barBackgroundColor == Color.Default ? UINavigationBar.Appearance.TintColor : barBackgroundColor.ToUIColor();
+ }
+ }
+
+ void UpdateBarTextColor()
+ {
+ var barTextColor = ((NavigationPage)Element).BarTextColor;
+
+ var globalAttributes = UINavigationBar.Appearance.GetTitleTextAttributes();
+
+ if (barTextColor == Color.Default)
+ {
+ if (NavigationBar.TitleTextAttributes != null)
+ {
+ var attributes = new UIStringAttributes();
+ attributes.ForegroundColor = globalAttributes.TextColor;
+ attributes.Font = globalAttributes.Font;
+ NavigationBar.TitleTextAttributes = attributes;
+ }
+ }
+ else
+ {
+ var titleAttributes = new UIStringAttributes();
+ titleAttributes.Font = globalAttributes.Font;
+ titleAttributes.ForegroundColor = barTextColor == Color.Default ? titleAttributes.ForegroundColor ?? UINavigationBar.Appearance.TintColor : barTextColor.ToUIColor();
+ NavigationBar.TitleTextAttributes = titleAttributes;
+ }
+
+ // set Tint color (i. e. Back Button arrow and Text)
+ if (Forms.IsiOS7OrNewer)
+ {
+ NavigationBar.TintColor = barTextColor == Color.Default ? UINavigationBar.Appearance.TintColor : barTextColor.ToUIColor();
+ }
+
+ if (barTextColor.Luminosity > 0.5)
+ {
+ // Use light text color for status bar
+ UIApplication.SharedApplication.StatusBarStyle = UIStatusBarStyle.LightContent;
+ }
+ else
+ {
+ // Use dark text color for status bar
+ UIApplication.SharedApplication.StatusBarStyle = UIStatusBarStyle.Default;
+ }
+ }
+
+ void UpdateLeftBarButtonItem(ParentingViewController containerController)
+ {
+ var currentChild = containerController.Child;
+ var firstPage = ((NavigationPage)Element).StackCopy.LastOrDefault();
+ if ((currentChild != firstPage && NavigationPage.GetHasBackButton(currentChild)) || _parentMasterDetailPage == null)
+ return;
+
+ if (!_parentMasterDetailPage.ShouldShowToolbarButton())
+ {
+ containerController.NavigationItem.LeftBarButtonItem = null;
+ return;
+ }
+
+ var shouldUseIcon = _parentMasterDetailPage.Master.Icon != null;
+ if (shouldUseIcon)
+ {
+ try
+ {
+ containerController.NavigationItem.LeftBarButtonItem = new UIBarButtonItem(new UIImage(_parentMasterDetailPage.Master.Icon), UIBarButtonItemStyle.Plain,
+ (o, e) => _parentMasterDetailPage.IsPresented = !_parentMasterDetailPage.IsPresented);
+ }
+ catch (Exception)
+ {
+ // Throws Exception otherwise would catch more specific exception type
+ shouldUseIcon = false;
+ }
+ }
+
+ if (!shouldUseIcon)
+ {
+ containerController.NavigationItem.LeftBarButtonItem = new UIBarButtonItem(_parentMasterDetailPage.Master.Title, UIBarButtonItemStyle.Plain,
+ (o, e) => _parentMasterDetailPage.IsPresented = !_parentMasterDetailPage.IsPresented);
+ }
+ }
+
+ void UpdateTint()
+ {
+ var tintColor = ((NavigationPage)Element).Tint;
+
+ if (Forms.IsiOS7OrNewer)
+ {
+ NavigationBar.BarTintColor = tintColor == Color.Default ? UINavigationBar.Appearance.BarTintColor : tintColor.ToUIColor();
+ if (tintColor == Color.Default)
+ NavigationBar.TintColor = UINavigationBar.Appearance.TintColor;
+ else
+ NavigationBar.TintColor = tintColor.Luminosity > 0.5 ? UIColor.Black : UIColor.White;
+ }
+ else
+ NavigationBar.TintColor = tintColor == Color.Default ? null : tintColor.ToUIColor();
+ }
+
+ void UpdateToolBarVisible()
+ {
+ if (_secondaryToolbar == null)
+ return;
+ if (TopViewController != null && TopViewController.ToolbarItems != null && TopViewController.ToolbarItems.Any())
+ {
+ _secondaryToolbar.Hidden = false;
+ _secondaryToolbar.Items = TopViewController.ToolbarItems;
+ }
+ else
+ {
+ _secondaryToolbar.Hidden = true;
+ //secondaryToolbar.Items = null;
+ }
+ }
+
+ class SecondaryToolbar : UIToolbar
+ {
+ readonly List<UIView> _lines = new List<UIView>();
+
+ public SecondaryToolbar()
+ {
+ TintColor = UIColor.White;
+ }
+
+ public override UIBarButtonItem[] Items
+ {
+ get { return base.Items; }
+ set
+ {
+ base.Items = value;
+ SetupLines();
+ }
+ }
+
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+ if (Items == null || Items.Length == 0)
+ return;
+ nfloat padding = 11f;
+ var itemWidth = (Bounds.Width - padding) / Items.Length - padding;
+ var x = padding;
+ var itemH = Bounds.Height - 10;
+ foreach (var item in Items)
+ {
+ var frame = new RectangleF(x, 5, itemWidth, itemH);
+ item.CustomView.Frame = frame;
+ x += itemWidth + padding;
+ }
+ x = itemWidth + padding * 1.5f;
+ var y = Bounds.GetMidY();
+ foreach (var l in _lines)
+ {
+ l.Center = new PointF(x, y);
+ x += itemWidth + padding;
+ }
+ }
+
+ void SetupLines()
+ {
+ _lines.ForEach(l => l.RemoveFromSuperview());
+ _lines.Clear();
+ if (Items == null)
+ return;
+ for (var i = 1; i < Items.Length; i++)
+ {
+ var l = new UIView(new RectangleF(0, 0, 1, 24)) { BackgroundColor = new UIColor(0, 0, 0, 0.2f) };
+ AddSubview(l);
+ _lines.Add(l);
+ }
+ }
+ }
+
+ class ParentingViewController : UIViewController
+ {
+ readonly WeakReference<NavigationRenderer> _navigation;
+
+ Page _child;
+ ToolbarTracker _tracker = new ToolbarTracker();
+
+ public ParentingViewController(NavigationRenderer navigation)
+ {
+ if (Forms.IsiOS7OrNewer)
+ AutomaticallyAdjustsScrollViewInsets = false;
+
+ _navigation = new WeakReference<NavigationRenderer>(navigation);
+ }
+
+ public Page Child
+ {
+ get { return _child; }
+ set
+ {
+ if (_child == value)
+ return;
+
+ if (_child != null)
+ _child.PropertyChanged -= HandleChildPropertyChanged;
+
+ _child = value;
+
+ if (_child != null)
+ _child.PropertyChanged += HandleChildPropertyChanged;
+
+ UpdateHasBackButton();
+ }
+ }
+
+ public event EventHandler Appearing;
+
+ public override void DidRotate(UIInterfaceOrientation fromInterfaceOrientation)
+ {
+ base.DidRotate(fromInterfaceOrientation);
+
+ View.SetNeedsLayout();
+ }
+
+ public event EventHandler Disappearing;
+
+ public override void ViewDidAppear(bool animated)
+ {
+ base.ViewDidAppear(animated);
+
+ var handler = Appearing;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+
+ public override void ViewDidDisappear(bool animated)
+ {
+ base.ViewDidDisappear(animated);
+
+ var handler = Disappearing;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+
+ public override void ViewDidLayoutSubviews()
+ {
+ IVisualElementRenderer childRenderer;
+ if (Child != null && (childRenderer = Platform.GetRenderer(Child)) != null)
+ childRenderer.NativeView.Frame = Child.Bounds.ToRectangleF();
+ base.ViewDidLayoutSubviews();
+ }
+
+ public override void ViewDidLoad()
+ {
+ base.ViewDidLoad();
+
+ _tracker.Target = Child;
+ _tracker.AdditionalTargets = Child.GetParentPages();
+ _tracker.CollectionChanged += TrackerOnCollectionChanged;
+
+ UpdateToolbarItems();
+ }
+
+ public override void ViewWillAppear(bool animated)
+ {
+ UpdateNavigationBarVisibility(animated);
+ base.ViewWillAppear(animated);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ Child.SendDisappearing();
+ Child = null;
+ _tracker.Target = null;
+ _tracker.CollectionChanged -= TrackerOnCollectionChanged;
+ _tracker = null;
+
+ if (NavigationItem.RightBarButtonItems != null)
+ {
+ for (var i = 0; i < NavigationItem.RightBarButtonItems.Length; i++)
+ NavigationItem.RightBarButtonItems[i].Dispose();
+ }
+
+ if (ToolbarItems != null)
+ {
+ for (var i = 0; i < ToolbarItems.Length; i++)
+ ToolbarItems[i].Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ void HandleChildPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == NavigationPage.HasNavigationBarProperty.PropertyName)
+ UpdateNavigationBarVisibility(true);
+ else if (e.PropertyName == Page.TitleProperty.PropertyName)
+ NavigationItem.Title = Child.Title;
+ else if (e.PropertyName == NavigationPage.HasBackButtonProperty.PropertyName)
+ UpdateHasBackButton();
+ }
+
+ void TrackerOnCollectionChanged(object sender, EventArgs eventArgs)
+ {
+ UpdateToolbarItems();
+ }
+
+ void UpdateHasBackButton()
+ {
+ if (Child == null)
+ return;
+
+ NavigationItem.HidesBackButton = !NavigationPage.GetHasBackButton(Child);
+ }
+
+ void UpdateNavigationBarVisibility(bool animated)
+ {
+ var current = Child;
+
+ if (current == null || NavigationController == null)
+ return;
+
+ var hasNavBar = NavigationPage.GetHasNavigationBar(current);
+
+ if (NavigationController.NavigationBarHidden == hasNavBar)
+ NavigationController.SetNavigationBarHidden(!hasNavBar, animated);
+ }
+
+ void UpdateToolbarItems()
+ {
+ if (NavigationItem.RightBarButtonItems != null)
+ {
+ for (var i = 0; i < NavigationItem.RightBarButtonItems.Length; i++)
+ NavigationItem.RightBarButtonItems[i].Dispose();
+ }
+ if (ToolbarItems != null)
+ {
+ for (var i = 0; i < ToolbarItems.Length; i++)
+ ToolbarItems[i].Dispose();
+ }
+
+ List<UIBarButtonItem> primaries = null;
+ List<UIBarButtonItem> secondaries = null;
+ foreach (var item in _tracker.ToolbarItems)
+ {
+ if (item.Order == ToolbarItemOrder.Secondary)
+ (secondaries = secondaries ?? new List<UIBarButtonItem>()).Add(item.ToUIBarButtonItem(true));
+ else
+ (primaries = primaries ?? new List<UIBarButtonItem>()).Add(item.ToUIBarButtonItem());
+ }
+
+ if (primaries != null)
+ primaries.Reverse();
+ NavigationItem.SetRightBarButtonItems(primaries == null ? new UIBarButtonItem[0] : primaries.ToArray(), false);
+ ToolbarItems = secondaries == null ? new UIBarButtonItem[0] : secondaries.ToArray();
+
+ NavigationRenderer n;
+ if (_navigation.TryGetTarget(out n))
+ n.UpdateToolBarVisible();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/OpenGLViewRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/OpenGLViewRenderer.cs
new file mode 100644
index 00000000..84c67744
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/OpenGLViewRenderer.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Drawing;
+using System.ComponentModel;
+#if __UNIFIED__
+using GLKit;
+using OpenGLES;
+using Foundation;
+using CoreAnimation;
+#else
+using MonoTouch.GLKit;
+using MonoTouch.OpenGLES;
+using MonoTouch.Foundation;
+using MonoTouch.CoreAnimation;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ internal class OpenGLViewRenderer : ViewRenderer<OpenGLView, GLKView>
+ {
+ CADisplayLink _displayLink;
+
+ public void Display(object sender, EventArgs eventArgs)
+ {
+ if (Element.HasRenderLoop)
+ return;
+ SetupRenderLoop(true);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (_displayLink != null)
+ {
+ _displayLink.Invalidate();
+ _displayLink.Dispose();
+ _displayLink = null;
+
+ if (Element != null)
+ ((IOpenGlViewController)Element).DisplayRequested -= Display;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<OpenGLView> e)
+ {
+ if (e.OldElement != null)
+ ((IOpenGlViewController)e.OldElement).DisplayRequested -= Display;
+
+ if (e.NewElement != null)
+ {
+ var context = new EAGLContext(EAGLRenderingAPI.OpenGLES2);
+ var glkView = new GLKView(RectangleF.Empty) { Context = context, DrawableDepthFormat = GLKViewDrawableDepthFormat.Format24, Delegate = new Delegate(e.NewElement) };
+ SetNativeControl(glkView);
+
+ ((IOpenGlViewController)e.NewElement).DisplayRequested += Display;
+
+ SetupRenderLoop(false);
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == OpenGLView.HasRenderLoopProperty.PropertyName)
+ SetupRenderLoop(false);
+ }
+
+ void SetupRenderLoop(bool oneShot)
+ {
+ if (_displayLink != null)
+ return;
+ if (!oneShot && !Element.HasRenderLoop)
+ return;
+
+ _displayLink = CADisplayLink.Create(() =>
+ {
+ var control = Control;
+ var model = Element;
+ if (control != null)
+ control.Display();
+ if (control == null || model == null || !model.HasRenderLoop)
+ {
+ _displayLink.Invalidate();
+ _displayLink.Dispose();
+ _displayLink = null;
+ }
+ });
+ _displayLink.AddToRunLoop(NSRunLoop.Current, NSRunLoop.NSDefaultRunLoopMode);
+ }
+
+ class Delegate : GLKViewDelegate
+ {
+ readonly OpenGLView _model;
+
+ public Delegate(OpenGLView model)
+ {
+ _model = model;
+ }
+
+ public override void DrawInRect(GLKView view, RectangleF rect)
+ {
+ var onDisplay = _model.OnDisplay;
+ if (onDisplay == null)
+ return;
+ onDisplay(rect.ToRectangle());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/PageRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/PageRenderer.cs
new file mode 100644
index 00000000..ddc0d39e
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/PageRenderer.cs
@@ -0,0 +1,218 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class PageRenderer : UIViewController, IVisualElementRenderer
+ {
+ bool _appeared;
+ bool _disposed;
+ EventTracker _events;
+ VisualElementPackager _packager;
+ VisualElementTracker _tracker;
+
+ public PageRenderer()
+ {
+ if (!Forms.IsiOS7OrNewer)
+ WantsFullScreenLayout = true;
+ }
+
+ public VisualElement Element { get; private set; }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return NativeView.GetSizeRequest(widthConstraint, heightConstraint);
+ }
+
+ public UIView NativeView
+ {
+ get { return _disposed ? null : View; }
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ var oldElement = Element;
+ Element = element;
+ UpdateTitle();
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+
+ if (Element != null && !string.IsNullOrEmpty(Element.AutomationId))
+ SetAutomationId(Element.AutomationId);
+
+ if (element != null)
+ element.SendViewInitialized(NativeView);
+ }
+
+ public void SetElementSize(Size size)
+ {
+ Element.Layout(new Rectangle(Element.X, Element.Y, size.Width, size.Height));
+ }
+
+ public UIViewController ViewController
+ {
+ get { return _disposed ? null : this; }
+ }
+
+ public override void ViewDidAppear(bool animated)
+ {
+ base.ViewDidAppear(animated);
+
+ if (_appeared || _disposed)
+ return;
+
+ _appeared = true;
+ ((Page)Element).SendAppearing();
+ }
+
+ public override void ViewDidDisappear(bool animated)
+ {
+ base.ViewDidDisappear(animated);
+
+ if (!_appeared || _disposed)
+ return;
+
+ _appeared = false;
+ ((Page)Element).SendDisappearing();
+ }
+
+ public override void ViewDidLoad()
+ {
+ base.ViewDidLoad();
+
+ var uiTapGestureRecognizer = new UITapGestureRecognizer(a => View.EndEditing(true));
+
+ uiTapGestureRecognizer.ShouldRecognizeSimultaneously = (recognizer, gestureRecognizer) => true;
+ uiTapGestureRecognizer.ShouldReceiveTouch = OnShouldReceiveTouch;
+ uiTapGestureRecognizer.DelaysTouchesBegan = uiTapGestureRecognizer.DelaysTouchesEnded = false;
+ View.AddGestureRecognizer(uiTapGestureRecognizer);
+
+ UpdateBackground();
+
+ _packager = new VisualElementPackager(this);
+ _packager.Load();
+
+ Element.PropertyChanged += OnHandlePropertyChanged;
+ _tracker = new VisualElementTracker(this);
+
+ _events = new EventTracker(this);
+ _events.LoadEvents(View);
+
+ Element.SendViewInitialized(View);
+ }
+
+ public override void ViewWillDisappear(bool animated)
+ {
+ base.ViewWillDisappear(animated);
+
+ if (View.Window != null)
+ View.Window.EndEditing(true);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ Element.PropertyChanged -= OnHandlePropertyChanged;
+ Platform.SetRenderer(Element, null);
+ if (_appeared)
+ ((Page)Element).SendDisappearing();
+
+ _appeared = false;
+
+ if (_events != null)
+ {
+ _events.Dispose();
+ _events = null;
+ }
+
+ if (_packager != null)
+ {
+ _packager.Dispose();
+ _packager = null;
+ }
+
+ if (_tracker != null)
+ {
+ _tracker.Dispose();
+ _tracker = null;
+ }
+
+ Element = null;
+ _disposed = true;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ var changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ protected virtual void SetAutomationId(string id)
+ {
+ if (NativeView != null)
+ NativeView.AccessibilityIdentifier = id;
+ }
+
+ void OnHandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackground();
+ else if (e.PropertyName == Page.BackgroundImageProperty.PropertyName)
+ UpdateBackground();
+ else if (e.PropertyName == Page.TitleProperty.PropertyName)
+ UpdateTitle();
+ }
+
+ bool OnShouldReceiveTouch(UIGestureRecognizer recognizer, UITouch touch)
+ {
+ if (ViewAndSuperviewsOfView(touch.View).Any(v => v is UITableView || v is UITableViewCell || v.CanBecomeFirstResponder))
+ return false;
+ return true;
+ }
+
+ void UpdateBackground()
+ {
+ var bgImage = ((Page)Element).BackgroundImage;
+ if (!string.IsNullOrEmpty(bgImage))
+ {
+ View.BackgroundColor = UIColor.FromPatternImage(UIImage.FromBundle(bgImage));
+ return;
+ }
+ var bgColor = Element.BackgroundColor;
+ if (bgColor.IsDefault)
+ View.BackgroundColor = UIColor.White;
+ else
+ View.BackgroundColor = bgColor.ToUIColor();
+ }
+
+ void UpdateTitle()
+ {
+ if (!string.IsNullOrWhiteSpace(((Page)Element).Title))
+ Title = ((Page)Element).Title;
+ }
+
+ IEnumerable<UIView> ViewAndSuperviewsOfView(UIView view)
+ {
+ while (view != null)
+ {
+ yield return view;
+ view = view.Superview;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/PhoneMasterDetailRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/PhoneMasterDetailRenderer.cs
new file mode 100644
index 00000000..070a0389
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/PhoneMasterDetailRenderer.cs
@@ -0,0 +1,401 @@
+using System;
+using System.Linq;
+using System.Drawing;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class PhoneMasterDetailRenderer : UIViewController, IVisualElementRenderer
+ {
+ UIView _clickOffView;
+ UIViewController _detailController;
+
+ bool _disposed;
+ EventTracker _events;
+
+ UIViewController _masterController;
+
+ UIPanGestureRecognizer _panGesture;
+
+ bool _presented;
+ UIGestureRecognizer _tapGesture;
+
+ VisualElementTracker _tracker;
+
+ public PhoneMasterDetailRenderer()
+ {
+ if (!Forms.IsiOS7OrNewer)
+ WantsFullScreenLayout = true;
+ }
+
+ bool Presented
+ {
+ get { return _presented; }
+ set
+ {
+ if (_presented == value)
+ return;
+ _presented = value;
+ LayoutChildren(true);
+ if (value)
+ AddClickOffView();
+ else
+ RemoveClickOffView();
+
+ ((IElementController)Element).SetValueFromRenderer(MasterDetailPage.IsPresentedProperty, value);
+ }
+ }
+
+ public VisualElement Element { get; private set; }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return NativeView.GetSizeRequest(widthConstraint, heightConstraint);
+ }
+
+ public UIView NativeView
+ {
+ get { return View; }
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ var oldElement = Element;
+ Element = element;
+ Element.SizeChanged += PageOnSizeChanged;
+
+ _masterController = new ChildViewController();
+ _detailController = new ChildViewController();
+
+ _clickOffView = new UIView();
+ _clickOffView.BackgroundColor = new Color(0, 0, 0, 0).ToUIColor();
+
+ Presented = ((MasterDetailPage)Element).IsPresented;
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+
+ if (element != null)
+ element.SendViewInitialized(NativeView);
+ }
+
+ public void SetElementSize(Size size)
+ {
+ Element.Layout(new Rectangle(Element.X, Element.Y, size.Width, size.Height));
+ }
+
+ public UIViewController ViewController
+ {
+ get { return this; }
+ }
+
+ public override void ViewDidAppear(bool animated)
+ {
+ base.ViewDidAppear(animated);
+ ((Page)Element).SendAppearing();
+ }
+
+ public override void ViewDidDisappear(bool animated)
+ {
+ base.ViewDidDisappear(animated);
+ ((Page)Element).SendDisappearing();
+ }
+
+ public override void ViewDidLayoutSubviews()
+ {
+ base.ViewDidLayoutSubviews();
+
+ LayoutChildren(false);
+ }
+
+ public override void ViewDidLoad()
+ {
+ base.ViewDidLoad();
+
+ _tracker = new VisualElementTracker(this);
+ _events = new EventTracker(this);
+ _events.LoadEvents(View);
+
+ ((MasterDetailPage)Element).PropertyChanged += HandlePropertyChanged;
+
+ _tapGesture = new UITapGestureRecognizer(() =>
+ {
+ if (Presented)
+ Presented = false;
+ });
+ _clickOffView.AddGestureRecognizer(_tapGesture);
+
+ PackContainers();
+ UpdateMasterDetailContainers();
+
+ UpdateBackground();
+
+ UpdatePanGesture();
+ }
+
+ public override void WillRotate(UIInterfaceOrientation toInterfaceOrientation, double duration)
+ {
+ if (!((MasterDetailPage)Element).ShouldShowSplitMode && _presented)
+ Presented = false;
+
+ base.WillRotate(toInterfaceOrientation, duration);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ Element.SizeChanged -= PageOnSizeChanged;
+ Element.PropertyChanged -= HandlePropertyChanged;
+
+ if (_tracker != null)
+ {
+ _tracker.Dispose();
+ _tracker = null;
+ }
+
+ if (_events != null)
+ {
+ _events.Dispose();
+ _events = null;
+ }
+
+ if (_tapGesture != null)
+ {
+ if (_clickOffView != null && _clickOffView.GestureRecognizers.Contains(_panGesture))
+ {
+ _clickOffView.GestureRecognizers.Remove(_tapGesture);
+ _clickOffView.Dispose();
+ }
+ _tapGesture.Dispose();
+ }
+ if (_panGesture != null)
+ {
+ if (View != null && View.GestureRecognizers.Contains(_panGesture))
+ View.GestureRecognizers.Remove(_panGesture);
+ _panGesture.Dispose();
+ }
+
+ EmptyContainers();
+
+ ((Page)Element).SendDisappearing();
+
+ _disposed = true;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ var changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ void AddClickOffView()
+ {
+ View.Add(_clickOffView);
+ _clickOffView.Frame = _detailController.View.Frame;
+ }
+
+ void EmptyContainers()
+ {
+ foreach (var child in _detailController.View.Subviews.Concat(_masterController.View.Subviews))
+ child.RemoveFromSuperview();
+
+ foreach (var vc in _detailController.ChildViewControllers.Concat(_masterController.ChildViewControllers))
+ vc.RemoveFromParentViewController();
+ }
+
+ void HandleMasterPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Page.IconProperty.PropertyName || e.PropertyName == Page.TitleProperty.PropertyName)
+ MessagingCenter.Send<IVisualElementRenderer>(this, NavigationRenderer.UpdateToolbarButtons);
+ }
+
+ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "Master" || e.PropertyName == "Detail")
+ UpdateMasterDetailContainers();
+ else if (e.PropertyName == MasterDetailPage.IsPresentedProperty.PropertyName)
+ Presented = ((MasterDetailPage)Element).IsPresented;
+ else if (e.PropertyName == MasterDetailPage.IsGestureEnabledProperty.PropertyName)
+ UpdatePanGesture();
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackground();
+ else if (e.PropertyName == Page.BackgroundImageProperty.PropertyName)
+ UpdateBackground();
+ }
+
+ void LayoutChildren(bool animated)
+ {
+ var frame = Element.Bounds.ToRectangleF();
+ var masterFrame = frame;
+ masterFrame.Width = (int)(Math.Min(masterFrame.Width, masterFrame.Height) * 0.8);
+
+ _masterController.View.Frame = masterFrame;
+
+ var target = frame;
+ if (Presented)
+ target.X += masterFrame.Width;
+
+ if (animated)
+ {
+ UIView.BeginAnimations("Flyout");
+ var view = _detailController.View;
+ view.Frame = target;
+ UIView.SetAnimationCurve(UIViewAnimationCurve.EaseOut);
+ UIView.SetAnimationDuration(250);
+ UIView.CommitAnimations();
+ }
+ else
+ _detailController.View.Frame = target;
+
+ ((MasterDetailPage)Element).MasterBounds = new Rectangle(0, 0, masterFrame.Width, masterFrame.Height);
+ ((MasterDetailPage)Element).DetailBounds = new Rectangle(0, 0, frame.Width, frame.Height);
+
+ if (Presented)
+ _clickOffView.Frame = _detailController.View.Frame;
+ }
+
+ void PackContainers()
+ {
+ _detailController.View.BackgroundColor = new UIColor(1, 1, 1, 1);
+ View.AddSubview(_masterController.View);
+ View.AddSubview(_detailController.View);
+
+ AddChildViewController(_masterController);
+ AddChildViewController(_detailController);
+ }
+
+ void PageOnSizeChanged(object sender, EventArgs eventArgs)
+ {
+ LayoutChildren(false);
+ }
+
+ void RemoveClickOffView()
+ {
+ _clickOffView.RemoveFromSuperview();
+ }
+
+ void UpdateBackground()
+ {
+ if (!string.IsNullOrEmpty(((Page)Element).BackgroundImage))
+ View.BackgroundColor = UIColor.FromPatternImage(UIImage.FromBundle(((Page)Element).BackgroundImage));
+ else if (Element.BackgroundColor == Color.Default)
+ View.BackgroundColor = UIColor.White;
+ else
+ View.BackgroundColor = Element.BackgroundColor.ToUIColor();
+ }
+
+ void UpdateMasterDetailContainers()
+ {
+ ((MasterDetailPage)Element).Master.PropertyChanged -= HandleMasterPropertyChanged;
+
+ EmptyContainers();
+
+ if (Platform.GetRenderer(((MasterDetailPage)Element).Master) == null)
+ Platform.SetRenderer(((MasterDetailPage)Element).Master, Platform.CreateRenderer(((MasterDetailPage)Element).Master));
+ if (Platform.GetRenderer(((MasterDetailPage)Element).Detail) == null)
+ Platform.SetRenderer(((MasterDetailPage)Element).Detail, Platform.CreateRenderer(((MasterDetailPage)Element).Detail));
+
+ var masterRenderer = Platform.GetRenderer(((MasterDetailPage)Element).Master);
+ var detailRenderer = Platform.GetRenderer(((MasterDetailPage)Element).Detail);
+
+ ((MasterDetailPage)Element).Master.PropertyChanged += HandleMasterPropertyChanged;
+
+ _masterController.View.AddSubview(masterRenderer.NativeView);
+ _masterController.AddChildViewController(masterRenderer.ViewController);
+
+ _detailController.View.AddSubview(detailRenderer.NativeView);
+ _detailController.AddChildViewController(detailRenderer.ViewController);
+ }
+
+ void UpdatePanGesture()
+ {
+ var model = (MasterDetailPage)Element;
+ if (!model.IsGestureEnabled)
+ {
+ if (_panGesture != null)
+ View.RemoveGestureRecognizer(_panGesture);
+ return;
+ }
+
+ if (_panGesture != null)
+ {
+ View.AddGestureRecognizer(_panGesture);
+ return;
+ }
+
+ UITouchEventArgs shouldRecieve = (g, t) => !(t.View is UISlider);
+ var center = new PointF();
+ _panGesture = new UIPanGestureRecognizer(g =>
+ {
+ switch (g.State)
+ {
+ case UIGestureRecognizerState.Began:
+ center = g.LocationInView(g.View);
+ break;
+ case UIGestureRecognizerState.Changed:
+ var currentPosition = g.LocationInView(g.View);
+ var motion = currentPosition.X - center.X;
+ var detailView = _detailController.View;
+ var targetFrame = detailView.Frame;
+ if (Presented)
+ targetFrame.X = (nfloat)Math.Max(0, _masterController.View.Frame.Width + Math.Min(0, motion));
+ else
+ targetFrame.X = (nfloat)Math.Min(_masterController.View.Frame.Width, Math.Max(0, motion));
+ detailView.Frame = targetFrame;
+ break;
+ case UIGestureRecognizerState.Ended:
+ var detailFrame = _detailController.View.Frame;
+ var masterFrame = _masterController.View.Frame;
+ if (Presented)
+ {
+ if (detailFrame.X < masterFrame.Width * .75)
+ Presented = false;
+ else
+ LayoutChildren(true);
+ }
+ else
+ {
+ if (detailFrame.X > masterFrame.Width * .25)
+ Presented = true;
+ else
+ LayoutChildren(true);
+ }
+ break;
+ }
+ });
+ _panGesture.ShouldReceiveTouch = shouldRecieve;
+ _panGesture.MaximumNumberOfTouches = 2;
+ View.AddGestureRecognizer(_panGesture);
+ }
+
+ class ChildViewController : UIViewController
+ {
+ public override void ViewDidLayoutSubviews()
+ {
+ foreach (var vc in ChildViewControllers)
+ vc.View.Frame = View.Bounds;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/PickerRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/PickerRenderer.cs
new file mode 100644
index 00000000..e47d2fa4
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/PickerRenderer.cs
@@ -0,0 +1,180 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class PickerRenderer : ViewRenderer<Picker, UITextField>
+ {
+ UIPickerView _picker;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
+ {
+ if (e.OldElement != null)
+ ((ObservableList<string>)e.OldElement.Items).CollectionChanged -= RowsCollectionChanged;
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var entry = new NoCaretField { BorderStyle = UITextBorderStyle.RoundedRect };
+
+ entry.Started += OnStarted;
+ entry.Ended += OnEnded;
+
+ _picker = new UIPickerView();
+
+ var width = UIScreen.MainScreen.Bounds.Width;
+ var toolbar = new UIToolbar(new RectangleF(0, 0, width, 44)) { BarStyle = UIBarStyle.Default, Translucent = true };
+ var spacer = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);
+ var doneButton = new UIBarButtonItem(UIBarButtonSystemItem.Done, (o, a) =>
+ {
+ var s = (PickerSource)_picker.Model;
+ if (s.SelectedIndex == -1 && Element.Items != null && Element.Items.Count > 0)
+ UpdatePickerSelectedIndex(0);
+ UpdatePickerFromModel(s);
+ entry.ResignFirstResponder();
+ });
+
+ toolbar.SetItems(new[] { spacer, doneButton }, false);
+
+ entry.InputView = _picker;
+ entry.InputAccessoryView = toolbar;
+
+ SetNativeControl(entry);
+ }
+
+ _picker.Model = new PickerSource(this);
+
+ UpdatePicker();
+
+ ((ObservableList<string>)e.NewElement.Items).CollectionChanged += RowsCollectionChanged;
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+ if (e.PropertyName == Picker.TitleProperty.PropertyName)
+ UpdatePicker();
+ if (e.PropertyName == Picker.SelectedIndexProperty.PropertyName)
+ UpdatePicker();
+ }
+
+ void OnEnded(object sender, EventArgs eventArgs)
+ {
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ }
+
+ void OnStarted(object sender, EventArgs eventArgs)
+ {
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
+ }
+
+ void RowsCollectionChanged(object sender, EventArgs e)
+ {
+ UpdatePicker();
+ }
+
+ void UpdatePicker()
+ {
+ var selectedIndex = Element.SelectedIndex;
+ var items = Element.Items;
+ Control.Placeholder = Element.Title;
+ var oldText = Control.Text;
+ Control.Text = selectedIndex == -1 || items == null ? "" : items[selectedIndex];
+ UpdatePickerNativeSize(oldText);
+ _picker.ReloadAllComponents();
+ if (items == null || items.Count == 0)
+ return;
+
+ UpdatePickerSelectedIndex(selectedIndex);
+ }
+
+ void UpdatePickerFromModel(PickerSource s)
+ {
+ if (Element != null)
+ {
+ var oldText = Control.Text;
+ ((IElementController)Element).SetValueFromRenderer(Picker.SelectedIndexProperty, s.SelectedIndex);
+ Control.Text = s.SelectedItem;
+ UpdatePickerNativeSize(oldText);
+ }
+ }
+
+ void UpdatePickerNativeSize(string oldText)
+ {
+ if (oldText != Control.Text)
+ ((IVisualElementController)Element).NativeSizeChanged();
+ }
+
+ void UpdatePickerSelectedIndex(int formsIndex)
+ {
+ var source = (PickerSource)_picker.Model;
+ source.SelectedIndex = formsIndex;
+ source.SelectedItem = formsIndex >= 0 ? Element.Items[formsIndex] : null;
+ _picker.Select(Math.Max(formsIndex, 0), 0, true);
+ }
+
+ class PickerSource : UIPickerViewModel
+ {
+ readonly PickerRenderer _renderer;
+
+ public PickerSource(PickerRenderer model)
+ {
+ _renderer = model;
+ }
+
+ public int SelectedIndex { get; internal set; }
+
+ public string SelectedItem { get; internal set; }
+
+ public override nint GetComponentCount(UIPickerView picker)
+ {
+ return 1;
+ }
+
+ public override nint GetRowsInComponent(UIPickerView pickerView, nint component)
+ {
+ return _renderer.Element.Items != null ? _renderer.Element.Items.Count : 0;
+ }
+
+ public override string GetTitle(UIPickerView picker, nint row, nint component)
+ {
+ return _renderer.Element.Items[(int)row];
+ }
+
+ public override void Selected(UIPickerView picker, nint row, nint component)
+ {
+ if (_renderer.Element.Items.Count == 0)
+ {
+ SelectedItem = null;
+ SelectedIndex = -1;
+ }
+ else
+ {
+ SelectedItem = _renderer.Element.Items[(int)row];
+ SelectedIndex = (int)row;
+ }
+ _renderer.UpdatePickerFromModel(this);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/ProgressBarRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/ProgressBarRenderer.cs
new file mode 100644
index 00000000..37091720
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/ProgressBarRenderer.cs
@@ -0,0 +1,67 @@
+using System.Drawing;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class ProgressBarRenderer : ViewRenderer<ProgressBar, UIProgressView>
+ {
+ public override SizeF SizeThatFits(SizeF size)
+ {
+ // progress bar will size itself to be as wide as the request, even if its inifinite
+ // we want the minimum need size
+ var result = base.SizeThatFits(size);
+ return new SizeF(10, result.Height);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<ProgressBar> e)
+ {
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ SetNativeControl(new UIProgressView(UIProgressViewStyle.Default));
+
+ UpdateProgress();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == ProgressBar.ProgressProperty.PropertyName)
+ UpdateProgress();
+ }
+
+ protected override void SetBackgroundColor(Color color)
+ {
+ base.SetBackgroundColor(color);
+
+ if (Control == null)
+ return;
+
+ Control.TrackTintColor = color != Color.Default ? color.ToUIColor() : null;
+ }
+
+ void UpdateProgress()
+ {
+ Control.Progress = (float)Element.Progress;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/ScrollViewRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/ScrollViewRenderer.cs
new file mode 100644
index 00000000..1e8ea1fc
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/ScrollViewRenderer.cs
@@ -0,0 +1,246 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+using ObjCRuntime;
+using PointF = CoreGraphics.CGPoint;
+using RectangleF = CoreGraphics.CGRect;
+
+#else
+using MonoTouch.Foundation;
+using MonoTouch.ObjCRuntime;
+using MonoTouch.UIKit;
+using nfloat=System.Single;
+
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class ScrollViewRenderer : UIScrollView, IVisualElementRenderer
+ {
+ EventTracker _events;
+ KeyboardInsetTracker _insetTracker;
+
+ VisualElementPackager _packager;
+
+ RectangleF _previousFrame;
+ ScrollToRequestedEventArgs _requestedScroll;
+ VisualElementTracker _tracker;
+
+ public ScrollViewRenderer() : base(RectangleF.Empty)
+ {
+ ScrollAnimationEnded += HandleScrollAnimationEnded;
+ Scrolled += HandleScrolled;
+ }
+
+ protected IScrollViewController Controller
+ {
+ get { return (IScrollViewController)Element; }
+ }
+
+ ScrollView ScrollView
+ {
+ get { return Element as ScrollView; }
+ }
+
+ public VisualElement Element { get; private set; }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return NativeView.GetSizeRequest(widthConstraint, heightConstraint, 44, 44);
+ }
+
+ public UIView NativeView
+ {
+ get { return this; }
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ _requestedScroll = null;
+ var oldElement = Element;
+ Element = element;
+
+ if (oldElement != null)
+ {
+ oldElement.PropertyChanged -= HandlePropertyChanged;
+ ((IScrollViewController)oldElement).ScrollToRequested -= OnScrollToRequested;
+ }
+
+ if (element != null)
+ {
+ element.PropertyChanged += HandlePropertyChanged;
+ ((IScrollViewController)element).ScrollToRequested += OnScrollToRequested;
+ if (_packager == null)
+ {
+ DelaysContentTouches = true;
+
+ _packager = new VisualElementPackager(this);
+ _packager.Load();
+
+ _tracker = new VisualElementTracker(this);
+ _tracker.NativeControlUpdated += OnNativeControlUpdated;
+ _events = new EventTracker(this);
+ _events.LoadEvents(this);
+
+ _insetTracker = new KeyboardInsetTracker(this, () => Window, insets => ContentInset = ScrollIndicatorInsets = insets, point =>
+ {
+ var offset = ContentOffset;
+ offset.Y += point.Y;
+ SetContentOffset(offset, true);
+ });
+ }
+
+ UpdateContentSize();
+ UpdateBackgroundColor();
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+
+ if (element != null)
+ element.SendViewInitialized(this);
+
+ if (!string.IsNullOrEmpty(element.AutomationId))
+ AccessibilityIdentifier = element.AutomationId;
+ }
+ }
+
+ public void SetElementSize(Size size)
+ {
+ Layout.LayoutChildIntoBoundingRegion(Element, new Rectangle(Element.X, Element.Y, size.Width, size.Height));
+ }
+
+ public UIViewController ViewController
+ {
+ get { return null; }
+ }
+
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+
+ if (_requestedScroll != null && Superview != null)
+ {
+ var request = _requestedScroll;
+ _requestedScroll = null;
+ OnScrollToRequested(this, request);
+ }
+
+ if (_previousFrame != Frame)
+ {
+ _previousFrame = Frame;
+ _insetTracker?.UpdateInsets();
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (_packager == null)
+ return;
+
+ SetElement(null);
+
+ _packager.Dispose();
+ _packager = null;
+
+ _tracker.NativeControlUpdated -= OnNativeControlUpdated;
+ _tracker.Dispose();
+ _tracker = null;
+
+ _events.Dispose();
+ _events = null;
+
+ _insetTracker.Dispose();
+ _insetTracker = null;
+
+ ScrollAnimationEnded -= HandleScrollAnimationEnded;
+ Scrolled -= HandleScrolled;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ var changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == ScrollView.ContentSizeProperty.PropertyName)
+ UpdateContentSize();
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackgroundColor();
+ }
+
+ void HandleScrollAnimationEnded(object sender, EventArgs e)
+ {
+ Controller.SendScrollFinished();
+ }
+
+ void HandleScrolled(object sender, EventArgs e)
+ {
+ UpdateScrollPosition();
+ }
+
+ void OnNativeControlUpdated(object sender, EventArgs eventArgs)
+ {
+ ContentSize = Bounds.Size;
+ UpdateContentSize();
+ }
+
+ void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
+ {
+ if (Superview == null)
+ {
+ _requestedScroll = e;
+ return;
+ }
+ if (e.Mode == ScrollToMode.Position)
+ SetContentOffset(new PointF((nfloat)e.ScrollX, (nfloat)e.ScrollY), e.ShouldAnimate);
+ else
+ {
+ var positionOnScroll = Controller.GetScrollPositionForElement(e.Element as VisualElement, e.Position);
+ switch (ScrollView.Orientation)
+ {
+ case ScrollOrientation.Horizontal:
+ SetContentOffset(new PointF((nfloat)positionOnScroll.X, ContentOffset.Y), e.ShouldAnimate);
+ break;
+ case ScrollOrientation.Vertical:
+ SetContentOffset(new PointF(ContentOffset.X, (nfloat)positionOnScroll.Y), e.ShouldAnimate);
+ break;
+ case ScrollOrientation.Both:
+ SetContentOffset(new PointF((nfloat)positionOnScroll.X, (nfloat)positionOnScroll.Y), e.ShouldAnimate);
+ break;
+ }
+ }
+ if (!e.ShouldAnimate)
+ Controller.SendScrollFinished();
+ }
+
+ void UpdateBackgroundColor()
+ {
+ BackgroundColor = Element.BackgroundColor.ToUIColor(Color.Transparent);
+ }
+
+ void UpdateContentSize()
+ {
+ var contentSize = ((ScrollView)Element).ContentSize.ToSizeF();
+ if (!contentSize.IsEmpty)
+ ContentSize = contentSize;
+ }
+
+ void UpdateScrollPosition()
+ {
+ if (ScrollView != null)
+ Controller.SetScrolledPosition(ContentOffset.X, ContentOffset.Y);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/SearchBarRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/SearchBarRenderer.cs
new file mode 100644
index 00000000..e5e156c4
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/SearchBarRenderer.cs
@@ -0,0 +1,249 @@
+using System;
+using System.Drawing;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class SearchBarRenderer : ViewRenderer<SearchBar, UISearchBar>
+ {
+ UIColor _cancelButtonTextColorDefaultDisabled;
+ UIColor _cancelButtonTextColorDefaultHighlighted;
+ UIColor _cancelButtonTextColorDefaultNormal;
+
+ UIColor _defaultTextColor;
+ UIColor _defaultTintColor;
+ UITextField _textField;
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (Control != null)
+ {
+ Control.CancelButtonClicked -= OnCancelClicked;
+ Control.SearchButtonClicked -= OnSearchButtonClicked;
+ Control.TextChanged -= OnTextChanged;
+
+ Control.OnEditingStarted -= OnEditingEnded;
+ Control.OnEditingStopped -= OnEditingStarted;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
+ {
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var searchBar = new UISearchBar(RectangleF.Empty) { ShowsCancelButton = true, BarStyle = UIBarStyle.Default };
+
+ var cancelButton = searchBar.FindDescendantView<UIButton>();
+ _cancelButtonTextColorDefaultNormal = cancelButton.TitleColor(UIControlState.Normal);
+ _cancelButtonTextColorDefaultHighlighted = cancelButton.TitleColor(UIControlState.Highlighted);
+ _cancelButtonTextColorDefaultDisabled = cancelButton.TitleColor(UIControlState.Disabled);
+
+ SetNativeControl(searchBar);
+
+ Control.CancelButtonClicked += OnCancelClicked;
+ Control.SearchButtonClicked += OnSearchButtonClicked;
+ Control.TextChanged += OnTextChanged;
+
+ Control.OnEditingStarted += OnEditingStarted;
+ Control.OnEditingStopped += OnEditingEnded;
+ }
+
+ UpdatePlaceholder();
+ UpdateText();
+ UpdateFont();
+ UpdateIsEnabled();
+ UpdateCancelButton();
+ UpdateAlignment();
+ UpdateTextColor();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == SearchBar.PlaceholderProperty.PropertyName || e.PropertyName == SearchBar.PlaceholderColorProperty.PropertyName)
+ UpdatePlaceholder();
+ else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ {
+ UpdateIsEnabled();
+ UpdateTextColor();
+ UpdatePlaceholder();
+ }
+ else if (e.PropertyName == SearchBar.TextColorProperty.PropertyName)
+ UpdateTextColor();
+ else if (e.PropertyName == SearchBar.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == SearchBar.CancelButtonColorProperty.PropertyName)
+ UpdateCancelButton();
+ else if (e.PropertyName == SearchBar.FontAttributesProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == SearchBar.FontFamilyProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == SearchBar.FontSizeProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == SearchBar.HorizontalTextAlignmentProperty.PropertyName)
+ UpdateAlignment();
+ }
+
+ protected override void SetBackgroundColor(Color color)
+ {
+ base.SetBackgroundColor(color);
+
+ if (Control == null)
+ return;
+
+ if (_defaultTintColor == null)
+ {
+ if (Forms.IsiOS7OrNewer)
+ _defaultTintColor = Control.BarTintColor;
+ else
+ _defaultTintColor = Control.TintColor;
+ }
+
+ if (Forms.IsiOS7OrNewer)
+ Control.BarTintColor = color.ToUIColor(_defaultTintColor);
+ else
+ Control.TintColor = color.ToUIColor(_defaultTintColor);
+
+ if (color.A < 1)
+ Control.SetBackgroundImage(new UIImage(), UIBarPosition.Any, UIBarMetrics.Default);
+
+ // updating BarTintColor resets the button color so we need to update the button color again
+ UpdateCancelButton();
+ }
+
+ void OnCancelClicked(object sender, EventArgs args)
+ {
+ ((IElementController)Element).SetValueFromRenderer(SearchBar.TextProperty, null);
+ Control.ResignFirstResponder();
+ }
+
+ void OnEditingEnded(object sender, EventArgs e)
+ {
+ if (Element != null)
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ }
+
+ void OnEditingStarted(object sender, EventArgs e)
+ {
+ if (Element != null)
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
+ }
+
+ void OnSearchButtonClicked(object sender, EventArgs e)
+ {
+ Element.OnSearchButtonPressed();
+ Control.ResignFirstResponder();
+ }
+
+ void OnTextChanged(object sender, UISearchBarTextChangedEventArgs a)
+ {
+ ((IElementController)Element).SetValueFromRenderer(SearchBar.TextProperty, Control.Text);
+ }
+
+ void UpdateAlignment()
+ {
+ _textField = _textField ?? Control.FindDescendantView<UITextField>();
+
+ if (_textField == null)
+ return;
+
+ _textField.TextAlignment = Element.HorizontalTextAlignment.ToNativeTextAlignment();
+ }
+
+ void UpdateCancelButton()
+ {
+ Control.ShowsCancelButton = !string.IsNullOrEmpty(Control.Text);
+
+ // We can't cache the cancel button reference because iOS drops it when it's not displayed
+ // and creates a brand new one when necessary, so we have to look for it each time
+ var cancelButton = Control.FindDescendantView<UIButton>();
+
+ if (cancelButton == null)
+ return;
+
+ if (Element.CancelButtonColor == Color.Default)
+ {
+ cancelButton.SetTitleColor(_cancelButtonTextColorDefaultNormal, UIControlState.Normal);
+ cancelButton.SetTitleColor(_cancelButtonTextColorDefaultHighlighted, UIControlState.Highlighted);
+ cancelButton.SetTitleColor(_cancelButtonTextColorDefaultDisabled, UIControlState.Disabled);
+ }
+ else
+ {
+ cancelButton.SetTitleColor(Element.CancelButtonColor.ToUIColor(), UIControlState.Normal);
+ cancelButton.SetTitleColor(Element.CancelButtonColor.ToUIColor(), UIControlState.Highlighted);
+ cancelButton.SetTitleColor(_cancelButtonTextColorDefaultDisabled, UIControlState.Disabled);
+ }
+ }
+
+ void UpdateFont()
+ {
+ _textField = _textField ?? Control.FindDescendantView<UITextField>();
+
+ if (_textField == null)
+ return;
+
+ _textField.Font = Element.ToUIFont();
+ }
+
+ void UpdateIsEnabled()
+ {
+ Control.UserInteractionEnabled = Element.IsEnabled;
+ }
+
+ void UpdatePlaceholder()
+ {
+ _textField = _textField ?? Control.FindDescendantView<UITextField>();
+
+ if (_textField == null)
+ return;
+
+ var formatted = (FormattedString)Element.Placeholder ?? string.Empty;
+ var targetColor = Element.PlaceholderColor;
+
+ // Placeholder default color is 70% gray
+ // https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITextField_Class/index.html#//apple_ref/occ/instp/UITextField/placeholder
+
+ var color = Element.IsEnabled && !targetColor.IsDefault ? targetColor : ColorExtensions.SeventyPercentGrey.ToColor();
+
+ _textField.AttributedPlaceholder = formatted.ToAttributed(Element, color);
+ }
+
+ void UpdateText()
+ {
+ Control.Text = Element.Text;
+ UpdateCancelButton();
+ }
+
+ void UpdateTextColor()
+ {
+ _textField = _textField ?? Control.FindDescendantView<UITextField>();
+
+ if (_textField == null)
+ return;
+
+ _defaultTextColor = _defaultTextColor ?? _textField.TextColor;
+ var targetColor = Element.TextColor;
+
+ var color = Element.IsEnabled && !targetColor.IsDefault ? targetColor : _defaultTextColor.ToColor();
+
+ _textField.TextColor = color.ToUIColor();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/SliderRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/SliderRenderer.cs
new file mode 100644
index 00000000..2df61f2f
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/SliderRenderer.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Drawing;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class SliderRenderer : ViewRenderer<Slider, UISlider>
+ {
+ SizeF _fitSize;
+
+ public override SizeF SizeThatFits(SizeF size)
+ {
+ return _fitSize;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (Control != null)
+ Control.ValueChanged -= OnControlValueChanged;
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Slider> e)
+ {
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new UISlider { Continuous = true });
+ Control.ValueChanged += OnControlValueChanged;
+
+ // sliders SizeThatFits method returns non-useful answers
+ // this however gives a very useful answer
+ Control.SizeToFit();
+ _fitSize = Control.Bounds.Size;
+
+ // except if your not running iOS 7... then it fails...
+ if (_fitSize.Width <= 0 || _fitSize.Height <= 0)
+ _fitSize = new SizeF(22, 22); // Per the glorious documentation known as the SDK docs
+ }
+
+ UpdateMaximum();
+ UpdateMinimum();
+ UpdateValue();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Slider.MaximumProperty.PropertyName)
+ UpdateMaximum();
+ else if (e.PropertyName == Slider.MinimumProperty.PropertyName)
+ UpdateMinimum();
+ else if (e.PropertyName == Slider.ValueProperty.PropertyName)
+ UpdateValue();
+ }
+
+ void OnControlValueChanged(object sender, EventArgs eventArgs)
+ {
+ ((IElementController)Element).SetValueFromRenderer(Slider.ValueProperty, Control.Value);
+ }
+
+ void UpdateMaximum()
+ {
+ Control.MaxValue = (float)Element.Maximum;
+ }
+
+ void UpdateMinimum()
+ {
+ Control.MinValue = (float)Element.Minimum;
+ }
+
+ void UpdateValue()
+ {
+ if ((float)Element.Value != Control.Value)
+ Control.Value = (float)Element.Value;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/StepperRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/StepperRenderer.cs
new file mode 100644
index 00000000..0cb0fcb7
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/StepperRenderer.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Drawing;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class StepperRenderer : ViewRenderer<Stepper, UIStepper>
+ {
+ protected override void Dispose(bool disposing)
+ {
+ if (Control != null)
+ Control.ValueChanged -= OnValueChanged;
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
+ {
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new UIStepper(RectangleF.Empty));
+ Control.ValueChanged += OnValueChanged;
+ }
+
+ UpdateMinimum();
+ UpdateMaximum();
+ UpdateValue();
+ UpdateIncrement();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Stepper.MinimumProperty.PropertyName)
+ UpdateMinimum();
+ else if (e.PropertyName == Stepper.MaximumProperty.PropertyName)
+ UpdateMaximum();
+ else if (e.PropertyName == Stepper.ValueProperty.PropertyName)
+ UpdateValue();
+ else if (e.PropertyName == Stepper.IncrementProperty.PropertyName)
+ UpdateIncrement();
+ }
+
+ void OnValueChanged(object sender, EventArgs e)
+ {
+ ((IElementController)Element).SetValueFromRenderer(Stepper.ValueProperty, Control.Value);
+ }
+
+ void UpdateIncrement()
+ {
+ Control.StepValue = Element.Increment;
+ }
+
+ void UpdateMaximum()
+ {
+ Control.MaximumValue = Element.Maximum;
+ }
+
+ void UpdateMinimum()
+ {
+ Control.MinimumValue = Element.Minimum;
+ }
+
+ void UpdateValue()
+ {
+ if (Control.Value != Element.Value)
+ Control.Value = Element.Value;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/SwitchRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/SwitchRenderer.cs
new file mode 100644
index 00000000..0bb7fbef
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/SwitchRenderer.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Drawing;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class SwitchRenderer : ViewRenderer<Switch, UISwitch>
+ {
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ Control.ValueChanged -= OnControlValueChanged;
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Switch> e)
+ {
+ if (e.OldElement != null)
+ e.OldElement.Toggled -= OnElementToggled;
+
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ SetNativeControl(new UISwitch(RectangleF.Empty));
+ Control.ValueChanged += OnControlValueChanged;
+ }
+
+ Control.On = Element.IsToggled;
+ e.NewElement.Toggled += OnElementToggled;
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ void OnControlValueChanged(object sender, EventArgs e)
+ {
+ ((IElementController)Element).SetValueFromRenderer(Switch.IsToggledProperty, Control.On);
+ }
+
+ void OnElementToggled(object sender, EventArgs e)
+ {
+ Control.SetState(Element.IsToggled, true);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/TabbedRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/TabbedRenderer.cs
new file mode 100644
index 00000000..7e5121fd
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/TabbedRenderer.cs
@@ -0,0 +1,311 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using System.Collections.Generic;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class TabbedRenderer : UITabBarController, IVisualElementRenderer
+ {
+ bool _loaded;
+ Size _queuedSize;
+
+ public override UIViewController SelectedViewController
+ {
+ get { return base.SelectedViewController; }
+ set
+ {
+ base.SelectedViewController = value;
+ UpdateCurrentPage();
+ }
+ }
+
+ protected TabbedPage Tabbed
+ {
+ get { return (TabbedPage)Element; }
+ }
+
+ public VisualElement Element { get; private set; }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return NativeView.GetSizeRequest(widthConstraint, heightConstraint);
+ }
+
+ public UIView NativeView
+ {
+ get { return View; }
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ var oldElement = Element;
+ Element = element;
+
+ FinishedCustomizingViewControllers += HandleFinishedCustomizingViewControllers;
+ Tabbed.PropertyChanged += OnPropertyChanged;
+ Tabbed.PagesChanged += OnPagesChanged;
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+
+ OnPagesChanged(null, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+
+ if (element != null)
+ element.SendViewInitialized(NativeView);
+
+ //disable edit/reorder of tabs
+ CustomizableViewControllers = null;
+ }
+
+ public void SetElementSize(Size size)
+ {
+ if (_loaded)
+ Element.Layout(new Rectangle(Element.X, Element.Y, size.Width, size.Height));
+ else
+ _queuedSize = size;
+ }
+
+ public UIViewController ViewController
+ {
+ get { return this; }
+ }
+
+ public override void DidRotate(UIInterfaceOrientation fromInterfaceOrientation)
+ {
+ base.DidRotate(fromInterfaceOrientation);
+
+ View.SetNeedsLayout();
+ }
+
+ public override void ViewDidAppear(bool animated)
+ {
+ ((TabbedPage)Element).SendAppearing();
+ base.ViewDidAppear(animated);
+ }
+
+ public override void ViewDidDisappear(bool animated)
+ {
+ base.ViewDidDisappear(animated);
+ ((TabbedPage)Element).SendDisappearing();
+ }
+
+ public override void ViewDidLayoutSubviews()
+ {
+ base.ViewDidLayoutSubviews();
+
+ if (Element == null)
+ return;
+
+ if (!Element.Bounds.IsEmpty)
+ {
+ View.Frame = new System.Drawing.RectangleF((float)Element.X, (float)Element.Y, (float)Element.Width, (float)Element.Height);
+ }
+
+ var frame = View.Frame;
+ var tabBarFrame = TabBar.Frame;
+ ((TabbedPage)Element).ContainerArea = new Rectangle(0, 0, frame.Width, frame.Height - tabBarFrame.Height);
+
+ if (!_queuedSize.IsZero)
+ {
+ Element.Layout(new Rectangle(Element.X, Element.Y, _queuedSize.Width, _queuedSize.Height));
+ _queuedSize = Size.Zero;
+ }
+
+ _loaded = true;
+ }
+
+ public override void ViewDidLoad()
+ {
+ base.ViewDidLoad();
+
+ if (!Forms.IsiOS7OrNewer)
+ WantsFullScreenLayout = false;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ ((TabbedPage)Element).SendDisappearing();
+ Tabbed.PropertyChanged -= OnPropertyChanged;
+ Tabbed.PagesChanged -= OnPagesChanged;
+ FinishedCustomizingViewControllers -= HandleFinishedCustomizingViewControllers;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ var changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ UIViewController GetViewController(Page page)
+ {
+ var renderer = Platform.GetRenderer(page);
+ if (renderer == null)
+ return null;
+
+ return renderer.ViewController;
+ }
+
+ void HandleFinishedCustomizingViewControllers(object sender, UITabBarCustomizeChangeEventArgs e)
+ {
+ if (e.Changed)
+ UpdateChildrenOrderIndex(e.ViewControllers);
+ }
+
+ void OnPagePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Page.TitleProperty.PropertyName)
+ {
+ var page = (Page)sender;
+ var renderer = Platform.GetRenderer(page);
+ if (renderer == null)
+ return;
+
+ if (renderer.ViewController.TabBarItem != null)
+ renderer.ViewController.TabBarItem.Title = page.Title;
+ }
+ else if (e.PropertyName == Page.IconProperty.PropertyName)
+ {
+ var page = (Page)sender;
+
+ var renderer = Platform.GetRenderer(page);
+ if (renderer == null)
+ return;
+
+ if (renderer.ViewController.TabBarItem == null)
+ return;
+
+ UIImage image = null;
+ if (!string.IsNullOrEmpty(page.Icon))
+ image = new UIImage(page.Icon);
+
+ // the new UITabBarItem forces redraw, setting the UITabBarItem.Image does not
+ renderer.ViewController.TabBarItem = new UITabBarItem(page.Title, image, 0);
+
+ if (image != null)
+ image.Dispose();
+ }
+ }
+
+ void OnPagesChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ e.Apply((o, i, c) => SetupPage((Page)o, i), (o, i) => TeardownPage((Page)o, i), Reset);
+
+ SetControllers();
+
+ UIViewController controller = null;
+ if (Tabbed.CurrentPage != null)
+ controller = GetViewController(Tabbed.CurrentPage);
+ if (controller != null && controller != base.SelectedViewController)
+ base.SelectedViewController = controller;
+ }
+
+ void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "CurrentPage")
+ {
+ var current = Tabbed.CurrentPage;
+ if (current == null)
+ return;
+
+ var controller = GetViewController(current);
+ if (controller == null)
+ return;
+
+ SelectedViewController = controller;
+ }
+ }
+
+ void Reset()
+ {
+ var i = 0;
+ foreach (var page in Tabbed.Children)
+ SetupPage(page, i++);
+ }
+
+ void SetControllers()
+ {
+ var list = new List<UIViewController>();
+ for (var i = 0; i < Element.LogicalChildren.Count; i++)
+ {
+ var child = Element.LogicalChildren[i];
+ var v = child as VisualElement;
+ if (v == null)
+ continue;
+ if (Platform.GetRenderer(v) != null)
+ list.Add(Platform.GetRenderer(v).ViewController);
+ }
+ ViewControllers = list.ToArray();
+ }
+
+ void SetupPage(Page page, int index)
+ {
+ var renderer = Platform.GetRenderer(page);
+ if (renderer == null)
+ {
+ renderer = Platform.CreateRenderer(page);
+ Platform.SetRenderer(page, renderer);
+ }
+
+ page.PropertyChanged += OnPagePropertyChanged;
+
+ UIImage icon = null;
+ if (page.Icon != null)
+ icon = new UIImage(page.Icon);
+
+ renderer.ViewController.TabBarItem = new UITabBarItem(page.Title, icon, 0);
+ if (icon != null)
+ icon.Dispose();
+
+ renderer.ViewController.TabBarItem.Tag = index;
+ }
+
+ void TeardownPage(Page page, int index)
+ {
+ page.PropertyChanged -= OnPagePropertyChanged;
+
+ Platform.SetRenderer(page, null);
+ }
+
+ void UpdateChildrenOrderIndex(UIViewController[] viewControllers)
+ {
+ for (var i = 0; i < viewControllers.Length; i++)
+ {
+ var originalIndex = -1;
+ if (int.TryParse(viewControllers[i].TabBarItem.Tag.ToString(), out originalIndex))
+ {
+ var page = (Page)Tabbed.InternalChildren[originalIndex];
+ TabbedPage.SetIndex(page, i);
+ }
+ }
+ }
+
+ void UpdateCurrentPage()
+ {
+ ((TabbedPage)Element).CurrentPage = SelectedIndex >= 0 && SelectedIndex < Tabbed.InternalChildren.Count ? Tabbed.GetPageByIndex((int)SelectedIndex) : null;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/TableViewModelRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/TableViewModelRenderer.cs
new file mode 100644
index 00000000..0e9e15f4
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/TableViewModelRenderer.cs
@@ -0,0 +1,157 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class TableViewModelRenderer : UITableViewSource
+ {
+ readonly Dictionary<nint, Cell> _headerCells = new Dictionary<nint, Cell>();
+
+ protected bool HasBoundGestures;
+ protected UITableView Table;
+
+ protected TableView View;
+
+ public TableViewModelRenderer(TableView model)
+ {
+ View = model;
+ View.ModelChanged += (s, e) =>
+ {
+ if (Table != null)
+ Table.ReloadData();
+ };
+ AutomaticallyDeselect = true;
+ }
+
+ public bool AutomaticallyDeselect { get; set; }
+
+ public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
+ {
+ var cell = View.Model.GetCell(indexPath.Section, indexPath.Row);
+
+ var nativeCell = CellTableViewCell.GetNativeCell(tableView, cell);
+ return nativeCell;
+ }
+
+ public override nfloat GetHeightForHeader(UITableView tableView, nint section)
+ {
+ if (!_headerCells.ContainsKey((int)section))
+ _headerCells[section] = View.Model.GetHeaderCell((int)section);
+
+ var result = _headerCells[section];
+
+ return result == null ? UITableView.AutomaticDimension : (nfloat)result.Height;
+ }
+
+ public override UIView GetViewForHeader(UITableView tableView, nint section)
+ {
+ if (!_headerCells.ContainsKey((int)section))
+ _headerCells[section] = View.Model.GetHeaderCell((int)section);
+
+ var result = _headerCells[section];
+
+ if (result != null)
+ {
+ var reusable = tableView.DequeueReusableCell(result.GetType().FullName);
+
+ var cellRenderer = Registrar.Registered.GetHandler<CellRenderer>(result.GetType());
+ return cellRenderer.GetCell(result, reusable, Table);
+ }
+ return null;
+ }
+
+ public void LongPress(UILongPressGestureRecognizer gesture)
+ {
+ var point = gesture.LocationInView(Table);
+ var indexPath = Table.IndexPathForRowAtPoint(point);
+ if (indexPath == null)
+ return;
+
+ View.Model.RowLongPressed(indexPath.Section, indexPath.Row);
+ }
+
+ public override nint NumberOfSections(UITableView tableView)
+ {
+ BindGestures(tableView);
+ return View.Model.GetSectionCount();
+ }
+
+ public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
+ {
+ View.Model.RowSelected(indexPath.Section, indexPath.Row);
+ if (AutomaticallyDeselect)
+ tableView.DeselectRow(indexPath, true);
+ }
+
+ public override nint RowsInSection(UITableView tableview, nint section)
+ {
+ return View.Model.GetRowCount((int)section);
+ }
+
+ public override string[] SectionIndexTitles(UITableView tableView)
+ {
+ return View.Model.GetSectionIndexTitles();
+ }
+
+ public override string TitleForHeader(UITableView tableView, nint section)
+ {
+ return View.Model.GetSectionTitle((int)section);
+ }
+
+ void BindGestures(UITableView tableview)
+ {
+ if (HasBoundGestures)
+ return;
+
+ HasBoundGestures = true;
+
+ var gesture = new UILongPressGestureRecognizer(LongPress);
+ gesture.MinimumPressDuration = 2;
+ tableview.AddGestureRecognizer(gesture);
+
+ var dismissGesture = new UITapGestureRecognizer(Tap);
+ dismissGesture.CancelsTouchesInView = false;
+ tableview.AddGestureRecognizer(dismissGesture);
+
+ Table = tableview;
+ }
+
+ void Tap(UITapGestureRecognizer gesture)
+ {
+ gesture.View.EndEditing(true);
+ }
+ }
+
+ public class UnEvenTableViewModelRenderer : TableViewModelRenderer
+ {
+ public UnEvenTableViewModelRenderer(TableView model) : base(model)
+ {
+ }
+
+ public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
+ {
+ var h = View.Model.GetCell(indexPath.Section, indexPath.Row).Height;
+ if (h == -1)
+ return tableView.RowHeight;
+ return (nfloat)h;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/TableViewRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/TableViewRenderer.cs
new file mode 100644
index 00000000..a77b32cc
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/TableViewRenderer.cs
@@ -0,0 +1,150 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Collections.Generic;
+#if __UNIFIED__
+using UIKit;
+using RectangleF = CoreGraphics.CGRect;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class TableViewRenderer : ViewRenderer<TableView, UITableView>
+ {
+ KeyboardInsetTracker _insetTracker;
+ UIView _originalBackgroundView;
+ RectangleF _previousFrame;
+
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return Control.GetSizeRequest(widthConstraint, heightConstraint, 44, 44);
+ }
+
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+
+ if (_previousFrame != Frame)
+ {
+ _previousFrame = Frame;
+ _insetTracker?.UpdateInsets();
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && _insetTracker != null)
+ {
+ _insetTracker.Dispose();
+ _insetTracker = null;
+
+ var viewsToLookAt = new Stack<UIView>(Subviews);
+ while (viewsToLookAt.Count > 0)
+ {
+ var view = viewsToLookAt.Pop();
+ var viewCellRenderer = view as ViewCellRenderer.ViewTableCell;
+ if (viewCellRenderer != null)
+ viewCellRenderer.Dispose();
+ else
+ {
+ foreach (var child in view.Subviews)
+ viewsToLookAt.Push(child);
+ }
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<TableView> e)
+ {
+ if (e.NewElement != null)
+ {
+ var style = UITableViewStyle.Plain;
+ if (e.NewElement.Intent != TableIntent.Data)
+ style = UITableViewStyle.Grouped;
+
+ if (Control == null || Control.Style != style)
+ {
+ if (Control != null)
+ {
+ _insetTracker.Dispose();
+ Control.Dispose();
+ }
+
+ var tv = new UITableView(RectangleF.Empty, style);
+ _originalBackgroundView = tv.BackgroundView;
+
+ SetNativeControl(tv);
+ if (Forms.IsiOS9OrNewer)
+ tv.CellLayoutMarginsFollowReadableWidth = false;
+
+ _insetTracker = new KeyboardInsetTracker(tv, () => Control.Window, insets => Control.ContentInset = Control.ScrollIndicatorInsets = insets, point =>
+ {
+ var offset = Control.ContentOffset;
+ offset.Y += point.Y;
+ Control.SetContentOffset(offset, true);
+ });
+ }
+
+ SetSource();
+ UpdateRowHeight();
+
+ UpdateBackgroundView();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == "RowHeight")
+ UpdateRowHeight();
+ else if (e.PropertyName == "HasUnevenRows")
+ SetSource();
+ else if (e.PropertyName == "BackgroundColor")
+ UpdateBackgroundView();
+ }
+
+ protected override void UpdateNativeWidget()
+ {
+ if (Element.Opacity < 1)
+ {
+ if (!Control.Layer.ShouldRasterize)
+ {
+ Control.Layer.RasterizationScale = UIScreen.MainScreen.Scale;
+ Control.Layer.ShouldRasterize = true;
+ }
+ }
+ else
+ Control.Layer.ShouldRasterize = false;
+ base.UpdateNativeWidget();
+ }
+
+ void SetSource()
+ {
+ var modeledView = Element;
+ Control.Source = modeledView.HasUnevenRows ? new UnEvenTableViewModelRenderer(modeledView) : new TableViewModelRenderer(modeledView);
+ }
+
+ void UpdateBackgroundView()
+ {
+ Control.BackgroundView = Element.BackgroundColor == Color.Default ? _originalBackgroundView : null;
+ }
+
+ void UpdateRowHeight()
+ {
+ var height = Element.RowHeight;
+
+ if (height <= 0)
+ height = 44;
+
+ Control.RowHeight = height;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/TabletMasterDetailRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/TabletMasterDetailRenderer.cs
new file mode 100644
index 00000000..3561322c
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/TabletMasterDetailRenderer.cs
@@ -0,0 +1,371 @@
+using System;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ internal class ChildViewController : UIViewController
+ {
+ public override void ViewDidLayoutSubviews()
+ {
+ foreach (var vc in ChildViewControllers)
+ vc.View.Frame = View.Bounds;
+ }
+ }
+
+ internal class EventedViewController : ChildViewController
+ {
+ public override void ViewWillAppear(bool animated)
+ {
+ base.ViewWillAppear(animated);
+
+ var eh = WillAppear;
+ if (eh != null)
+ eh(this, EventArgs.Empty);
+ }
+
+ public override void ViewWillDisappear(bool animated)
+ {
+ base.ViewWillDisappear(animated);
+
+ var eh = WillDisappear;
+ if (eh != null)
+ eh(this, EventArgs.Empty);
+ }
+
+ public event EventHandler WillAppear;
+
+ public event EventHandler WillDisappear;
+ }
+
+ public class TabletMasterDetailRenderer : UISplitViewController, IVisualElementRenderer
+ {
+ UIViewController _detailController;
+
+ bool _disposed;
+ EventTracker _events;
+ InnerDelegate _innerDelegate;
+
+ EventedViewController _masterController;
+
+ MasterDetailPage _masterDetailPage;
+
+ bool _masterVisible;
+
+ VisualElementTracker _tracker;
+
+ protected MasterDetailPage MasterDetailPage
+ {
+ get { return _masterDetailPage ?? (_masterDetailPage = (MasterDetailPage)Element); }
+ }
+
+ UIBarButtonItem PresentButton
+ {
+ get { return _innerDelegate == null ? null : _innerDelegate.PresentButton; }
+ }
+
+ public void Dispose()
+ {
+ if (_disposed)
+ return;
+
+ if (Element != null)
+ {
+ ((Page)Element).SendDisappearing();
+ Element.PropertyChanged -= HandlePropertyChanged;
+ Element = null;
+ }
+
+ if (_tracker != null)
+ {
+ _tracker.Dispose();
+ _tracker = null;
+ }
+
+ if (_events != null)
+ {
+ _events.Dispose();
+ _events = null;
+ }
+
+ if (_masterController != null)
+ {
+ _masterController.WillAppear -= MasterControllerWillAppear;
+ _masterController.WillDisappear -= MasterControllerWillDisappear;
+ }
+
+ _disposed = true;
+ }
+
+ public VisualElement Element { get; private set; }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return NativeView.GetSizeRequest(widthConstraint, heightConstraint);
+ }
+
+ public UIView NativeView
+ {
+ get { return View; }
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ var oldElement = Element;
+ Element = element;
+
+ ViewControllers = new[] { _masterController = new EventedViewController(), _detailController = new ChildViewController() };
+
+ Delegate = _innerDelegate = new InnerDelegate(MasterDetailPage.MasterBehavior);
+
+ UpdateControllers();
+
+ _masterController.WillAppear += MasterControllerWillAppear;
+ _masterController.WillDisappear += MasterControllerWillDisappear;
+
+ PresentsWithGesture = MasterDetailPage.IsGestureEnabled;
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+
+ if (element != null)
+ element.SendViewInitialized(NativeView);
+ }
+
+ public void SetElementSize(Size size)
+ {
+ Element.Layout(new Rectangle(Element.X, Element.Width, size.Width, size.Height));
+ }
+
+ public UIViewController ViewController
+ {
+ get { return this; }
+ }
+
+ public override void ViewDidAppear(bool animated)
+ {
+ ((Page)Element).SendAppearing();
+ base.ViewDidAppear(animated);
+ ToggleMaster();
+ }
+
+ public override void ViewDidDisappear(bool animated)
+ {
+ base.ViewDidDisappear(animated);
+ ((Page)Element).SendDisappearing();
+ }
+
+ public override void ViewDidLayoutSubviews()
+ {
+ base.ViewDidLayoutSubviews();
+
+ if (View.Subviews.Length < 2)
+ return;
+
+ var detailsBounds = _detailController.View.Frame;
+ var masterBounds = _masterController.View.Frame;
+
+ if (!masterBounds.IsEmpty)
+ MasterDetailPage.MasterBounds = new Rectangle(0, 0, masterBounds.Width, masterBounds.Height);
+
+ if (!detailsBounds.IsEmpty)
+ MasterDetailPage.DetailBounds = new Rectangle(0, 0, detailsBounds.Width, detailsBounds.Height);
+ }
+
+ public override void ViewDidLoad()
+ {
+ base.ViewDidLoad();
+ UpdateBackground();
+ _tracker = new VisualElementTracker(this);
+ _events = new EventTracker(this);
+ _events.LoadEvents(NativeView);
+ }
+
+ public override void ViewWillDisappear(bool animated)
+ {
+ if (_masterVisible)
+ PerformButtonSelector();
+
+ base.ViewWillDisappear(animated);
+ }
+
+ public override void ViewWillLayoutSubviews()
+ {
+ base.ViewWillLayoutSubviews();
+ _masterController.View.BackgroundColor = UIColor.White;
+ }
+
+ public override void WillRotate(UIInterfaceOrientation toInterfaceOrientation, double duration)
+ {
+ // On IOS8 the MasterViewController ViewAppear/Disappear weren't being called correctly after rotation
+ // We now close the Master by using the new SplitView API, basicly we set it to hidden and right back to the Normal/AutomaticMode
+ if (!MasterDetailPage.ShouldShowSplitMode && _masterVisible)
+ {
+ MasterDetailPage.CanChangeIsPresented = true;
+ if (Forms.IsiOS8OrNewer)
+ {
+ PreferredDisplayMode = UISplitViewControllerDisplayMode.PrimaryHidden;
+ PreferredDisplayMode = UISplitViewControllerDisplayMode.Automatic;
+ }
+ }
+ MasterDetailPage.UpdateMasterBehavior(MasterDetailPage);
+ MessagingCenter.Send<IVisualElementRenderer>(this, NavigationRenderer.UpdateToolbarButtons);
+ base.WillRotate(toInterfaceOrientation, duration);
+ }
+
+ protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ if (e.OldElement != null)
+ e.OldElement.PropertyChanged -= HandlePropertyChanged;
+
+ if (e.NewElement != null)
+ e.NewElement.PropertyChanged += HandlePropertyChanged;
+
+ var changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ void ClearControllers()
+ {
+ foreach (var controller in _masterController.ChildViewControllers)
+ {
+ controller.View.RemoveFromSuperview();
+ controller.RemoveFromParentViewController();
+ }
+
+ foreach (var controller in _detailController.ChildViewControllers)
+ {
+ controller.View.RemoveFromSuperview();
+ controller.RemoveFromParentViewController();
+ }
+ }
+
+ void HandleMasterPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Page.IconProperty.PropertyName || e.PropertyName == Page.TitleProperty.PropertyName)
+ MessagingCenter.Send<IVisualElementRenderer>(this, NavigationRenderer.UpdateToolbarButtons);
+ }
+
+ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (_tracker == null)
+ return;
+
+ if (e.PropertyName == "Master" || e.PropertyName == "Detail")
+ UpdateControllers();
+ else if (e.PropertyName == MasterDetailPage.IsPresentedProperty.PropertyName)
+ ToggleMaster();
+ else if (e.PropertyName == MasterDetailPage.IsGestureEnabledProperty.PropertyName)
+ PresentsWithGesture = MasterDetailPage.IsGestureEnabled;
+ MessagingCenter.Send<IVisualElementRenderer>(this, NavigationRenderer.UpdateToolbarButtons);
+ }
+
+ void MasterControllerWillAppear(object sender, EventArgs e)
+ {
+ _masterVisible = true;
+ if (MasterDetailPage.CanChangeIsPresented)
+ ((IElementController)Element).SetValueFromRenderer(MasterDetailPage.IsPresentedProperty, true);
+ }
+
+ void MasterControllerWillDisappear(object sender, EventArgs e)
+ {
+ _masterVisible = false;
+ if (MasterDetailPage.CanChangeIsPresented)
+ ((IElementController)Element).SetValueFromRenderer(MasterDetailPage.IsPresentedProperty, false);
+ }
+
+ void PerformButtonSelector()
+ {
+ if (Forms.IsiOS8OrNewer)
+ DisplayModeButtonItem.Target.PerformSelector(DisplayModeButtonItem.Action, DisplayModeButtonItem, 0);
+ else
+ PresentButton.Target.PerformSelector(PresentButton.Action, PresentButton, 0);
+ }
+
+ void ToggleMaster()
+ {
+ if (_masterVisible == MasterDetailPage.IsPresented || MasterDetailPage.ShouldShowSplitMode)
+ return;
+
+ PerformButtonSelector();
+ }
+
+ void UpdateBackground()
+ {
+ if (!string.IsNullOrEmpty(((Page)Element).BackgroundImage))
+ View.BackgroundColor = UIColor.FromPatternImage(UIImage.FromBundle(((Page)Element).BackgroundImage));
+ else if (Element.BackgroundColor == Color.Default)
+ View.BackgroundColor = UIColor.White;
+ else
+ View.BackgroundColor = Element.BackgroundColor.ToUIColor();
+ }
+
+ void UpdateControllers()
+ {
+ MasterDetailPage.Master.PropertyChanged -= HandleMasterPropertyChanged;
+
+ if (Platform.GetRenderer(MasterDetailPage.Master) == null)
+ Platform.SetRenderer(MasterDetailPage.Master, Platform.CreateRenderer(MasterDetailPage.Master));
+ if (Platform.GetRenderer(MasterDetailPage.Detail) == null)
+ Platform.SetRenderer(MasterDetailPage.Detail, Platform.CreateRenderer(MasterDetailPage.Detail));
+
+ ClearControllers();
+
+ MasterDetailPage.Master.PropertyChanged += HandleMasterPropertyChanged;
+
+ var master = Platform.GetRenderer(MasterDetailPage.Master).ViewController;
+ var detail = Platform.GetRenderer(MasterDetailPage.Detail).ViewController;
+
+ _masterController.View.AddSubview(master.View);
+ _masterController.AddChildViewController(master);
+
+ _detailController.View.AddSubview(detail.View);
+ _detailController.AddChildViewController(detail);
+ }
+
+ class InnerDelegate : UISplitViewControllerDelegate
+ {
+ readonly MasterBehavior _masterPresentedDefaultState;
+
+ public InnerDelegate(MasterBehavior masterPresentedDefaultState)
+ {
+ _masterPresentedDefaultState = masterPresentedDefaultState;
+ }
+
+ public UIBarButtonItem PresentButton { get; set; }
+
+ public override bool ShouldHideViewController(UISplitViewController svc, UIViewController viewController, UIInterfaceOrientation inOrientation)
+ {
+ bool willHideViewController;
+ switch (_masterPresentedDefaultState)
+ {
+ case MasterBehavior.Split:
+ willHideViewController = false;
+ break;
+ case MasterBehavior.Popover:
+ willHideViewController = true;
+ break;
+ case MasterBehavior.SplitOnPortrait:
+ willHideViewController = !(inOrientation == UIInterfaceOrientation.Portrait || inOrientation == UIInterfaceOrientation.PortraitUpsideDown);
+ break;
+ default:
+ willHideViewController = inOrientation == UIInterfaceOrientation.Portrait || inOrientation == UIInterfaceOrientation.PortraitUpsideDown;
+ break;
+ }
+ return willHideViewController;
+ }
+
+ public override void WillHideViewController(UISplitViewController svc, UIViewController aViewController, UIBarButtonItem barButtonItem, UIPopoverController pc)
+ {
+ PresentButton = barButtonItem;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/TimePickerRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/TimePickerRenderer.cs
new file mode 100644
index 00000000..85d3ad35
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/TimePickerRenderer.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Drawing;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class TimePickerRenderer : ViewRenderer<TimePicker, UITextField>
+ {
+ UIDatePicker _picker;
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ Control.Started -= OnStarted;
+ Control.Ended -= OnEnded;
+
+ _picker.ValueChanged -= OnValueChanged;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
+ {
+ if (e.NewElement != null)
+ {
+ if (Control == null)
+ {
+ var entry = new NoCaretField { BorderStyle = UITextBorderStyle.RoundedRect };
+
+ entry.Started += OnStarted;
+ entry.Ended += OnEnded;
+
+ _picker = new UIDatePicker { Mode = UIDatePickerMode.Time, TimeZone = new NSTimeZone("UTC") };
+
+ var width = UIScreen.MainScreen.Bounds.Width;
+ var toolbar = new UIToolbar(new RectangleF(0, 0, width, 44)) { BarStyle = UIBarStyle.Default, Translucent = true };
+ var spacer = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);
+ var doneButton = new UIBarButtonItem(UIBarButtonSystemItem.Done, (o, a) => entry.ResignFirstResponder());
+
+ toolbar.SetItems(new[] { spacer, doneButton }, false);
+
+ entry.InputView = _picker;
+ entry.InputAccessoryView = toolbar;
+
+ _picker.ValueChanged += OnValueChanged;
+
+ SetNativeControl(entry);
+ }
+
+ UpdateTime();
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == TimePicker.TimeProperty.PropertyName || e.PropertyName == TimePicker.FormatProperty.PropertyName)
+ UpdateTime();
+ }
+
+ void OnEnded(object sender, EventArgs eventArgs)
+ {
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
+ }
+
+ void OnStarted(object sender, EventArgs eventArgs)
+ {
+ ((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
+ }
+
+ void OnValueChanged(object sender, EventArgs e)
+ {
+ ((IElementController)Element).SetValueFromRenderer(TimePicker.TimeProperty, _picker.Date.ToDateTime() - new DateTime(1, 1, 1));
+ }
+
+ void UpdateTime()
+ {
+ _picker.Date = new DateTime(1, 1, 1).Add(Element.Time).ToNSDate();
+ Control.Text = DateTime.Today.Add(Element.Time).ToString(Element.Format);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/ToolbarRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/ToolbarRenderer.cs
new file mode 100644
index 00000000..705f95d8
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/ToolbarRenderer.cs
@@ -0,0 +1,66 @@
+using System.Linq;
+using System.Drawing;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class ToolbarRenderer : ViewRenderer
+ {
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ ((Toolbar)Element).ItemAdded -= OnItemAdded;
+ ((Toolbar)Element).ItemRemoved -= OnItemRemoved;
+
+ if (((UIToolbar)Control).Items != null)
+ {
+ foreach (var item in ((UIToolbar)Control).Items)
+ item.Dispose();
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<View> e)
+ {
+ base.OnElementChanged(e);
+
+ SetNativeControl(new UIToolbar(RectangleF.Empty));
+ UpdateItems(false);
+
+ ((Toolbar)Element).ItemAdded += OnItemAdded;
+ ((Toolbar)Element).ItemRemoved += OnItemRemoved;
+ }
+
+ void OnItemAdded(object sender, ToolbarItemEventArgs eventArg)
+ {
+ UpdateItems(true);
+ }
+
+ void OnItemRemoved(object sender, ToolbarItemEventArgs eventArg)
+ {
+ UpdateItems(true);
+ }
+
+ void UpdateItems(bool animated)
+ {
+ if (((UIToolbar)Control).Items != null)
+ {
+ for (var i = 0; i < ((UIToolbar)Control).Items.Length; i++)
+ ((UIToolbar)Control).Items[i].Dispose();
+ }
+ var items = new UIBarButtonItem[((Toolbar)Element).Items.Count];
+ for (var i = 0; i < ((Toolbar)Element).Items.Count; i++)
+ items[i] = ((Toolbar)Element).Items[i].ToUIBarButtonItem();
+
+ ((UIToolbar)Control).SetItems(items, animated);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/WebViewRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/WebViewRenderer.cs
new file mode 100644
index 00000000..538bc2d0
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/WebViewRenderer.cs
@@ -0,0 +1,270 @@
+using System;
+using System.Drawing;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class WebViewRenderer : UIWebView, IVisualElementRenderer, IWebViewRenderer
+ {
+ EventTracker _events;
+ bool _ignoreSourceChanges;
+ WebNavigationEvent _lastBackForwardEvent;
+ VisualElementPackager _packager;
+
+ VisualElementTracker _tracker;
+
+ public WebViewRenderer() : base(RectangleF.Empty)
+ {
+ }
+
+ public VisualElement Element { get; private set; }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return NativeView.GetSizeRequest(widthConstraint, heightConstraint, 44, 44);
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ var oldElement = Element;
+ Element = element;
+ Element.PropertyChanged += HandlePropertyChanged;
+ ((WebView)Element).EvalRequested += OnEvalRequested;
+ ((WebView)Element).GoBackRequested += OnGoBackRequested;
+ ((WebView)Element).GoForwardRequested += OnGoForwardRequested;
+ Delegate = new CustomWebViewDelegate(this);
+
+ BackgroundColor = UIColor.Clear;
+
+ AutosizesSubviews = true;
+ AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
+
+ _tracker = new VisualElementTracker(this);
+
+ _packager = new VisualElementPackager(this);
+ _packager.Load();
+
+ _events = new EventTracker(this);
+ _events.LoadEvents(this);
+
+ Load();
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+
+ if (Element != null && !string.IsNullOrEmpty(Element.AutomationId))
+ AccessibilityIdentifier = Element.AutomationId;
+
+ if (element != null)
+ element.SendViewInitialized(this);
+
+ if (Element != null && !string.IsNullOrEmpty(Element.AutomationId))
+ AccessibilityIdentifier = Element.AutomationId;
+ }
+
+ public void SetElementSize(Size size)
+ {
+ Layout.LayoutChildIntoBoundingRegion(Element, new Rectangle(Element.X, Element.Y, size.Width, size.Height));
+ }
+
+ public void LoadHtml(string html, string baseUrl)
+ {
+ if (html != null)
+ LoadHtmlString(html, baseUrl == null ? new NSUrl(NSBundle.MainBundle.BundlePath, true) : new NSUrl(baseUrl, true));
+ }
+
+ public void LoadUrl(string url)
+ {
+ LoadRequest(new NSUrlRequest(new NSUrl(url)));
+ }
+
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+
+ // ensure that inner scrollview properly resizes when frame of webview updated
+ ScrollView.Frame = Bounds;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (IsLoading)
+ StopLoading();
+
+ Element.PropertyChanged -= HandlePropertyChanged;
+ ((WebView)Element).EvalRequested -= OnEvalRequested;
+ ((WebView)Element).GoBackRequested -= OnGoBackRequested;
+ ((WebView)Element).GoForwardRequested -= OnGoForwardRequested;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ var changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == WebView.SourceProperty.PropertyName)
+ Load();
+ }
+
+ void Load()
+ {
+ if (_ignoreSourceChanges)
+ return;
+
+ if (((WebView)Element).Source != null)
+ ((WebView)Element).Source.Load(this);
+
+ UpdateCanGoBackForward();
+ }
+
+ void OnEvalRequested(object sender, EventArg<string> eventArg)
+ {
+ EvaluateJavascript(eventArg.Data);
+ }
+
+ void OnGoBackRequested(object sender, EventArgs eventArgs)
+ {
+ if (CanGoBack)
+ {
+ _lastBackForwardEvent = WebNavigationEvent.Back;
+ GoBack();
+ }
+
+ UpdateCanGoBackForward();
+ }
+
+ void OnGoForwardRequested(object sender, EventArgs eventArgs)
+ {
+ if (CanGoForward)
+ {
+ _lastBackForwardEvent = WebNavigationEvent.Forward;
+ GoForward();
+ }
+
+ UpdateCanGoBackForward();
+ }
+
+ void UpdateCanGoBackForward()
+ {
+ ((WebView)Element).CanGoBack = CanGoBack;
+ ((WebView)Element).CanGoForward = CanGoForward;
+ }
+
+ class CustomWebViewDelegate : UIWebViewDelegate
+ {
+ readonly WebViewRenderer _renderer;
+ WebNavigationEvent _lastEvent;
+
+ public CustomWebViewDelegate(WebViewRenderer renderer)
+ {
+ if (renderer == null)
+ throw new ArgumentNullException("renderer");
+ _renderer = renderer;
+ }
+
+ WebView WebView
+ {
+ get { return (WebView)_renderer.Element; }
+ }
+
+ public override void LoadFailed(UIWebView webView, NSError error)
+ {
+ var url = GetCurrentUrl();
+ WebView.SendNavigated(new WebNavigatedEventArgs(_lastEvent, new UrlWebViewSource { Url = url }, url, WebNavigationResult.Failure));
+
+ _renderer.UpdateCanGoBackForward();
+ }
+
+ public override void LoadingFinished(UIWebView webView)
+ {
+ if (webView.IsLoading)
+ return;
+
+ _renderer._ignoreSourceChanges = true;
+ var url = GetCurrentUrl();
+ ((IElementController)WebView).SetValueFromRenderer(WebView.SourceProperty, new UrlWebViewSource { Url = url });
+ _renderer._ignoreSourceChanges = false;
+
+ var args = new WebNavigatedEventArgs(_lastEvent, WebView.Source, url, WebNavigationResult.Success);
+ WebView.SendNavigated(args);
+
+ _renderer.UpdateCanGoBackForward();
+ }
+
+ public override void LoadStarted(UIWebView webView)
+ {
+ }
+
+ public override bool ShouldStartLoad(UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType)
+ {
+ var navEvent = WebNavigationEvent.NewPage;
+ switch (navigationType)
+ {
+ case UIWebViewNavigationType.LinkClicked:
+ navEvent = WebNavigationEvent.NewPage;
+ break;
+ case UIWebViewNavigationType.FormSubmitted:
+ navEvent = WebNavigationEvent.NewPage;
+ break;
+ case UIWebViewNavigationType.BackForward:
+ navEvent = _renderer._lastBackForwardEvent;
+ break;
+ case UIWebViewNavigationType.Reload:
+ navEvent = WebNavigationEvent.Refresh;
+ break;
+ case UIWebViewNavigationType.FormResubmitted:
+ navEvent = WebNavigationEvent.NewPage;
+ break;
+ case UIWebViewNavigationType.Other:
+ navEvent = WebNavigationEvent.NewPage;
+ break;
+ }
+
+ _lastEvent = navEvent;
+ var lastUrl = request.Url.ToString();
+ var args = new WebNavigatingEventArgs(navEvent, new UrlWebViewSource { Url = lastUrl }, lastUrl);
+
+ WebView.SendNavigating(args);
+ _renderer.UpdateCanGoBackForward();
+ return !args.Cancel;
+ }
+
+ string GetCurrentUrl()
+ {
+ return _renderer?.Request?.Url?.AbsoluteUrl?.ToString();
+ }
+ }
+
+ #region IPlatformRenderer implementation
+
+ public UIView NativeView
+ {
+ get { return this; }
+ }
+
+ public UIViewController ViewController
+ {
+ get { return null; }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.Designer.cs b/Xamarin.Forms.Platform.iOS/Resources/StringResources.Designer.cs
new file mode 100644
index 00000000..096da604
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.Designer.cs
@@ -0,0 +1,81 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Xamarin.Forms.Platform.iOS.Resources {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class StringResources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal StringResources() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Xamarin.Forms.Platform.iOS.Resources.StringResources", typeof(StringResources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Cancel.
+ /// </summary>
+ internal static string Cancel {
+ get {
+ return ResourceManager.GetString("Cancel", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to More.
+ /// </summary>
+ internal static string More {
+ get {
+ return ResourceManager.GetString("More", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.ar.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.ar.resx
new file mode 100644
index 00000000..2382ee59
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.ar.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>إلخاء</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>إضافي</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.ca.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.ca.resx
new file mode 100644
index 00000000..f8c683b4
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.ca.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Cancel·lar</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Més</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.cs.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.cs.resx
new file mode 100644
index 00000000..55c6946a
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.cs.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Zrušit</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Další</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.da.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.da.resx
new file mode 100644
index 00000000..0ff5a6fa
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.da.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Annuller</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Mere</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.de.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.de.resx
new file mode 100644
index 00000000..fa10a5a3
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.de.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Abbrechen</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Mehr</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.el.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.el.resx
new file mode 100644
index 00000000..d360a038
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.el.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Ακύρωση</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Λοιπά</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.es.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.es.resx
new file mode 100644
index 00000000..a8bc4fd8
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.es.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Cancelar</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Más</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.fi.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.fi.resx
new file mode 100644
index 00000000..0244fc71
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.fi.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Kumoa</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Muut</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.fr.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.fr.resx
new file mode 100644
index 00000000..819845a0
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.fr.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Annuler</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Options</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.he.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.he.resx
new file mode 100644
index 00000000..fe8724a3
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.he.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>ביטול</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>עוד</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.hi.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.hi.resx
new file mode 100644
index 00000000..5ad57b4c
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.hi.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>रद्द करें</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>अधिक</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.hr.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.hr.resx
new file mode 100644
index 00000000..c7e01f21
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.hr.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Poništi</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Više</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.hu.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.hu.resx
new file mode 100644
index 00000000..1942899b
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.hu.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Mégsem</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Továbbiak</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.id.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.id.resx
new file mode 100644
index 00000000..182b8e94
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.id.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Batalkan</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Lainnya</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.it.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.it.resx
new file mode 100644
index 00000000..e7b49e09
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.it.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Annulla</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Altro</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.ja.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.ja.resx
new file mode 100644
index 00000000..aa6ed1a4
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.ja.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>キャンセル</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>その他</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.ko.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.ko.resx
new file mode 100644
index 00000000..2a2de740
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.ko.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>취소</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>기타</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.ms.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.ms.resx
new file mode 100644
index 00000000..fd679653
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.ms.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Batal</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Lagi</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.nb.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.nb.resx
new file mode 100644
index 00000000..671f06f6
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.nb.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Avbryt</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Mer</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.nl.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.nl.resx
new file mode 100644
index 00000000..dd592bac
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.nl.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Annuleer</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Meer</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.pl.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.pl.resx
new file mode 100644
index 00000000..5a99c8e1
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.pl.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Anuluj</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Więcej</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.pt-BR.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.pt-BR.resx
new file mode 100644
index 00000000..38182acf
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.pt-BR.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Cancelar</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Mais</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.pt.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.pt.resx
new file mode 100644
index 00000000..38182acf
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.pt.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Cancelar</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Mais</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.resx
new file mode 100644
index 00000000..e96cccd2
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Cancel</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>More</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.ro.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.ro.resx
new file mode 100644
index 00000000..0135509d
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.ro.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Anulați</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Altele</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.ru.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.ru.resx
new file mode 100644
index 00000000..6789a97f
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.ru.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Oтменить</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Еще</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.sk.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.sk.resx
new file mode 100644
index 00000000..17dc74f4
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.sk.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Zrušiť</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Viac</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.sv.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.sv.resx
new file mode 100644
index 00000000..671f06f6
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.sv.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Avbryt</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Mer</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.th.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.th.resx
new file mode 100644
index 00000000..b9002921
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.th.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>ยกเลิก</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>เพิ่มเติม</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.tr.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.tr.resx
new file mode 100644
index 00000000..256919f4
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.tr.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Vazgeç</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Diğer</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.uk.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.uk.resx
new file mode 100644
index 00000000..c3a5aa44
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.uk.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Скасувати</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Щe</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.vi.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.vi.resx
new file mode 100644
index 00000000..f8f88e68
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.vi.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>Hủy</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>Thêm</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.zh-HK.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.zh-HK.resx
new file mode 100644
index 00000000..fff96457
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.zh-HK.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>取消</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>更多</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.zh-Hans.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.zh-Hans.resx
new file mode 100644
index 00000000..fff96457
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.zh-Hans.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>取消</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>更多</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Resources/StringResources.zh-Hant.resx b/Xamarin.Forms.Platform.iOS/Resources/StringResources.zh-Hant.resx
new file mode 100644
index 00000000..fff96457
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Resources/StringResources.zh-Hant.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="Cancel" xml:space="preserve">
+ <value>取消</value>
+ <comment>ContextActionCell Cancel button</comment>
+ </data>
+ <data name="More" xml:space="preserve">
+ <value>更多</value>
+ <comment>ContextActionCell More button</comment>
+ </data>
+</root> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/ResourcesProvider.cs b/Xamarin.Forms.Platform.iOS/ResourcesProvider.cs
new file mode 100644
index 00000000..847107d9
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/ResourcesProvider.cs
@@ -0,0 +1,72 @@
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ internal class ResourcesProvider : ISystemResourcesProvider
+ {
+ ResourceDictionary _dictionary;
+
+ public ResourcesProvider()
+ {
+ if (Forms.IsiOS7OrNewer)
+ UIApplication.Notifications.ObserveContentSizeCategoryChanged((sender, args) => UpdateStyles());
+ }
+
+ public IResourceDictionary GetSystemResources()
+ {
+ _dictionary = new ResourceDictionary();
+ UpdateStyles();
+
+ return _dictionary;
+ }
+
+ Style GenerateListItemDetailTextStyle()
+ {
+ var font = new UITableViewCell(UITableViewCellStyle.Subtitle, "Foobar").DetailTextLabel.Font;
+ return GenerateStyle(font);
+ }
+
+ Style GenerateListItemTextStyle()
+ {
+ var font = new UITableViewCell(UITableViewCellStyle.Subtitle, "Foobar").TextLabel.Font;
+ return GenerateStyle(font);
+ }
+
+ Style GenerateStyle(UIFont font)
+ {
+ var result = new Style(typeof(Label));
+
+ result.Setters.Add(new Setter { Property = Label.FontSizeProperty, Value = (double)font.PointSize });
+
+ result.Setters.Add(new Setter { Property = Label.FontFamilyProperty, Value = font.Name });
+
+ return result;
+ }
+
+ void UpdateStyles()
+ {
+ if (Forms.IsiOS7OrNewer)
+ {
+ _dictionary[Device.Styles.TitleStyleKey] = GenerateStyle(UIFont.PreferredHeadline);
+ _dictionary[Device.Styles.SubtitleStyleKey] = GenerateStyle(UIFont.PreferredSubheadline);
+ _dictionary[Device.Styles.BodyStyleKey] = GenerateStyle(UIFont.PreferredBody);
+ _dictionary[Device.Styles.CaptionStyleKey] = GenerateStyle(UIFont.PreferredCaption1);
+ }
+ else
+ {
+ _dictionary[Device.Styles.TitleStyleKey] = GenerateStyle(UIFont.BoldSystemFontOfSize(17));
+ _dictionary[Device.Styles.SubtitleStyleKey] = GenerateStyle(UIFont.SystemFontOfSize(15));
+ _dictionary[Device.Styles.BodyStyleKey] = GenerateStyle(UIFont.SystemFontOfSize(17));
+ _dictionary[Device.Styles.CaptionStyleKey] = GenerateStyle(UIFont.SystemFontOfSize(12));
+ }
+
+ _dictionary[Device.Styles.ListItemTextStyleKey] = GenerateListItemTextStyle();
+ _dictionary[Device.Styles.ListItemDetailTextStyleKey] = GenerateListItemDetailTextStyle();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/ViewInitializedEventArgs.cs b/Xamarin.Forms.Platform.iOS/ViewInitializedEventArgs.cs
new file mode 100644
index 00000000..e34a493e
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/ViewInitializedEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms
+{
+ public class ViewInitializedEventArgs : EventArgs
+ {
+ public UIView NativeView { get; internal set; }
+
+ public VisualElement View { get; internal set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/ViewRenderer.cs b/Xamarin.Forms.Platform.iOS/ViewRenderer.cs
new file mode 100644
index 00000000..5b3be1c3
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/ViewRenderer.cs
@@ -0,0 +1,151 @@
+using System;
+using System.Drawing;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public abstract class ViewRenderer : ViewRenderer<View, UIView>
+ {
+ }
+
+ public abstract class ViewRenderer<TView, TNativeView> : VisualElementRenderer<TView> where TView : View where TNativeView : UIView
+ {
+ UIColor _defaultColor;
+
+ public TNativeView Control { get; private set; }
+
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+ if (Control != null)
+ Control.Frame = new RectangleF(0, 0, (nfloat)Element.Width, (nfloat)Element.Height);
+ }
+
+ public override SizeF SizeThatFits(SizeF size)
+ {
+ return Control.SizeThatFits(size);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (disposing && Control != null)
+ {
+ Control.Dispose();
+ Control = null;
+ }
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<TView> e)
+ {
+ base.OnElementChanged(e);
+
+ if (e.OldElement != null)
+ e.OldElement.FocusChangeRequested -= ViewOnFocusChangeRequested;
+
+ if (e.NewElement != null)
+ {
+ if (Control != null && e.OldElement != null && e.OldElement.BackgroundColor != e.NewElement.BackgroundColor || e.NewElement.BackgroundColor != Color.Default)
+ SetBackgroundColor(e.NewElement.BackgroundColor);
+
+ e.NewElement.FocusChangeRequested += ViewOnFocusChangeRequested;
+ }
+
+ UpdateIsEnabled();
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (Control != null)
+ {
+ if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled();
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ SetBackgroundColor(Element.BackgroundColor);
+ }
+
+ base.OnElementPropertyChanged(sender, e);
+ }
+
+ protected override void OnRegisterEffect(PlatformEffect effect)
+ {
+ base.OnRegisterEffect(effect);
+ effect.Control = Control;
+ }
+
+ protected override void SetAutomationId(string id)
+ {
+ if (Control == null)
+ base.SetAutomationId(id);
+ else
+ {
+ AccessibilityIdentifier = id + "_Container";
+ Control.AccessibilityIdentifier = id;
+ }
+ }
+
+ protected override void SetBackgroundColor(Color color)
+ {
+ if (Control == null)
+ return;
+
+ if (color == Color.Default)
+ Control.BackgroundColor = _defaultColor;
+ else
+ Control.BackgroundColor = color.ToUIColor();
+ }
+
+ protected void SetNativeControl(TNativeView uiview)
+ {
+ _defaultColor = uiview.BackgroundColor;
+ Control = uiview;
+
+ if (Element.BackgroundColor != Color.Default)
+ SetBackgroundColor(Element.BackgroundColor);
+
+ UpdateIsEnabled();
+
+ AddSubview(uiview);
+ }
+
+ internal override void SendVisualElementInitialized(VisualElement element, UIView nativeView)
+ {
+ base.SendVisualElementInitialized(element, Control);
+ }
+
+ void UpdateIsEnabled()
+ {
+ if (Element == null || Control == null)
+ return;
+
+ var uiControl = Control as UIControl;
+ if (uiControl == null)
+ return;
+ uiControl.Enabled = Element.IsEnabled;
+ }
+
+ void ViewOnFocusChangeRequested(object sender, VisualElement.FocusRequestArgs focusRequestArgs)
+ {
+ if (Control == null)
+ return;
+
+ focusRequestArgs.Result = focusRequestArgs.Focus ? Control.BecomeFirstResponder() : Control.ResignFirstResponder();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/VisualElementPackager.cs b/Xamarin.Forms.Platform.iOS/VisualElementPackager.cs
new file mode 100644
index 00000000..7f511d9d
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/VisualElementPackager.cs
@@ -0,0 +1,179 @@
+using System;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class VisualElementPackager : IDisposable
+ {
+ VisualElement _element;
+
+ bool _isDisposed;
+
+ public VisualElementPackager(IVisualElementRenderer renderer)
+ {
+ if (renderer == null)
+ throw new ArgumentNullException("renderer");
+
+ Renderer = renderer;
+ renderer.ElementChanged += OnRendererElementChanged;
+ SetElement(null, renderer.Element);
+ }
+
+ protected IVisualElementRenderer Renderer { get; set; }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ public void Load()
+ {
+ for (var i = 0; i < Renderer.Element.LogicalChildren.Count; i++)
+ {
+ var child = Renderer.Element.LogicalChildren[i] as VisualElement;
+ if (child != null)
+ OnChildAdded(child);
+ }
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_isDisposed)
+ return;
+
+ if (disposing)
+ {
+ SetElement(_element, null);
+ if (Renderer != null)
+ {
+ Renderer.ElementChanged -= OnRendererElementChanged;
+ Renderer = null;
+ }
+ }
+
+ _isDisposed = true;
+ }
+
+ protected virtual void OnChildAdded(VisualElement view)
+ {
+ if (_isDisposed)
+ return;
+
+ var viewRenderer = Platform.CreateRenderer(view);
+ Platform.SetRenderer(view, viewRenderer);
+
+ var uiview = Renderer.NativeView;
+ uiview.AddSubview(viewRenderer.NativeView);
+
+ if (Renderer.ViewController != null && viewRenderer.ViewController != null)
+ Renderer.ViewController.AddChildViewController(viewRenderer.ViewController);
+
+ EnsureChildrenOrder();
+ }
+
+ protected virtual void OnChildRemoved(VisualElement view)
+ {
+ var viewRenderer = Platform.GetRenderer(view);
+ if (viewRenderer == null || viewRenderer.NativeView == null)
+ return;
+
+ viewRenderer.NativeView.RemoveFromSuperview();
+
+ if (Renderer.ViewController != null && viewRenderer.ViewController != null)
+ viewRenderer.ViewController.RemoveFromParentViewController();
+ }
+
+ void EnsureChildrenOrder()
+ {
+ if (Renderer.Element.LogicalChildren.Count == 0)
+ return;
+
+ for (var z = 0; z < Renderer.Element.LogicalChildren.Count; z++)
+ {
+ var child = Renderer.Element.LogicalChildren[z] as VisualElement;
+ if (child == null)
+ continue;
+ var childRenderer = Platform.GetRenderer(child);
+
+ if (childRenderer == null)
+ continue;
+
+ var nativeControl = childRenderer.NativeView;
+
+ Renderer.NativeView.BringSubviewToFront(nativeControl);
+ nativeControl.Layer.ZPosition = z * 1000;
+ }
+ }
+
+ void OnChildAdded(object sender, ElementEventArgs e)
+ {
+ var view = e.Element as VisualElement;
+ if (view != null)
+ OnChildAdded(view);
+ }
+
+ void OnChildRemoved(object sender, ElementEventArgs e)
+ {
+ var view = e.Element as VisualElement;
+ if (view != null)
+ OnChildRemoved(view);
+ }
+
+ void OnRendererElementChanged(object sender, VisualElementChangedEventArgs args)
+ {
+ if (args.NewElement == _element)
+ return;
+
+ SetElement(_element, args.NewElement);
+ }
+
+ void SetElement(VisualElement oldElement, VisualElement newElement)
+ {
+ if (oldElement == newElement)
+ return;
+
+ if (oldElement != null)
+ {
+ oldElement.ChildAdded -= OnChildAdded;
+ oldElement.ChildRemoved -= OnChildRemoved;
+ oldElement.ChildrenReordered -= UpdateChildrenOrder;
+
+ if (newElement != null)
+ {
+ var pool = new RendererPool(Renderer, oldElement);
+ pool.UpdateNewElement(newElement);
+
+ EnsureChildrenOrder();
+ }
+ else
+ {
+ for (var i = 0; i < oldElement.LogicalChildren.Count; i++)
+ {
+ var child = oldElement.LogicalChildren[i] as VisualElement;
+ if (child != null)
+ OnChildRemoved(child);
+ }
+ }
+ }
+
+ _element = newElement;
+
+ if (newElement != null)
+ {
+ newElement.ChildAdded += OnChildAdded;
+ newElement.ChildRemoved += OnChildRemoved;
+ newElement.ChildrenReordered += UpdateChildrenOrder;
+ }
+ }
+
+ void UpdateChildrenOrder(object sender, EventArgs e)
+ {
+ EnsureChildrenOrder();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/VisualElementRenderer.cs b/Xamarin.Forms.Platform.iOS/VisualElementRenderer.cs
new file mode 100644
index 00000000..d14c288c
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/VisualElementRenderer.cs
@@ -0,0 +1,273 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Drawing;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ [Flags]
+ public enum VisualElementRendererFlags
+ {
+ Disposed = 1 << 0,
+ AutoTrack = 1 << 1,
+ AutoPackage = 1 << 2
+ }
+
+ public class VisualElementRenderer<TElement> : UIView, IVisualElementRenderer, IEffectControlProvider where TElement : VisualElement
+ {
+ readonly UIColor _defaultColor = UIColor.Clear;
+
+ readonly List<EventHandler<VisualElementChangedEventArgs>> _elementChangedHandlers = new List<EventHandler<VisualElementChangedEventArgs>>();
+
+ readonly PropertyChangedEventHandler _propertyChangedHandler;
+ EventTracker _events;
+
+ VisualElementRendererFlags _flags = VisualElementRendererFlags.AutoPackage | VisualElementRendererFlags.AutoTrack;
+
+ VisualElementPackager _packager;
+ VisualElementTracker _tracker;
+
+ protected VisualElementRenderer() : base(RectangleF.Empty)
+ {
+ _propertyChangedHandler = OnElementPropertyChanged;
+ BackgroundColor = UIColor.Clear;
+ }
+
+ // prevent possible crashes in overrides
+ public sealed override UIColor BackgroundColor
+ {
+ get { return base.BackgroundColor; }
+ set { base.BackgroundColor = value; }
+ }
+
+ public TElement Element { get; private set; }
+
+ protected bool AutoPackage
+ {
+ get { return (_flags & VisualElementRendererFlags.AutoPackage) != 0; }
+ set
+ {
+ if (value)
+ _flags |= VisualElementRendererFlags.AutoPackage;
+ else
+ _flags &= ~VisualElementRendererFlags.AutoPackage;
+ }
+ }
+
+ protected bool AutoTrack
+ {
+ get { return (_flags & VisualElementRendererFlags.AutoTrack) != 0; }
+ set
+ {
+ if (value)
+ _flags |= VisualElementRendererFlags.AutoTrack;
+ else
+ _flags &= ~VisualElementRendererFlags.AutoTrack;
+ }
+ }
+
+ void IEffectControlProvider.RegisterEffect(Effect effect)
+ {
+ var platformEffect = effect as PlatformEffect;
+ if (platformEffect != null)
+ OnRegisterEffect(platformEffect);
+ }
+
+ VisualElement IVisualElementRenderer.Element
+ {
+ get { return Element; }
+ }
+
+ event EventHandler<VisualElementChangedEventArgs> IVisualElementRenderer.ElementChanged
+ {
+ add { _elementChangedHandlers.Add(value); }
+ remove { _elementChangedHandlers.Remove(value); }
+ }
+
+ public virtual SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return NativeView.GetSizeRequest(widthConstraint, heightConstraint);
+ }
+
+ public UIView NativeView
+ {
+ get { return this; }
+ }
+
+ void IVisualElementRenderer.SetElement(VisualElement element)
+ {
+ SetElement((TElement)element);
+ }
+
+ public void SetElementSize(Size size)
+ {
+ Layout.LayoutChildIntoBoundingRegion(Element, new Rectangle(Element.X, Element.Y, size.Width, size.Height));
+ }
+
+ public UIViewController ViewController
+ {
+ get { return null; }
+ }
+
+ public event EventHandler<ElementChangedEventArgs<TElement>> ElementChanged;
+
+ public void SetElement(TElement element)
+ {
+ var oldElement = Element;
+ Element = element;
+
+ if (oldElement != null)
+ oldElement.PropertyChanged -= _propertyChangedHandler;
+
+ if (element != null)
+ {
+ if (element.BackgroundColor != Color.Default || (oldElement != null && element.BackgroundColor != oldElement.BackgroundColor))
+ SetBackgroundColor(element.BackgroundColor);
+
+ UpdateClipToBounds();
+
+ if (_tracker == null)
+ {
+ _tracker = new VisualElementTracker(this);
+ _tracker.NativeControlUpdated += (sender, e) => UpdateNativeWidget();
+ }
+
+ if (AutoPackage && _packager == null)
+ {
+ _packager = new VisualElementPackager(this);
+ _packager.Load();
+ }
+
+ if (AutoTrack && _events == null)
+ {
+ _events = new EventTracker(this);
+ _events.LoadEvents(this);
+ }
+
+ element.PropertyChanged += _propertyChangedHandler;
+ }
+
+ OnElementChanged(new ElementChangedEventArgs<TElement>(oldElement, element));
+
+ if (element != null)
+ SendVisualElementInitialized(element, this);
+
+ var controller = (IElementController)oldElement;
+ if (controller != null && controller.EffectControlProvider == this)
+ controller.EffectControlProvider = null;
+
+ controller = element;
+ if (controller != null)
+ controller.EffectControlProvider = this;
+
+ if (Element != null && !string.IsNullOrEmpty(Element.AutomationId))
+ SetAutomationId(Element.AutomationId);
+ }
+
+ public override SizeF SizeThatFits(SizeF size)
+ {
+ return new SizeF(0, 0);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if ((_flags & VisualElementRendererFlags.Disposed) != 0)
+ return;
+ _flags |= VisualElementRendererFlags.Disposed;
+
+ if (disposing)
+ {
+ if (_events != null)
+ {
+ _events.Dispose();
+ _events = null;
+ }
+ if (_tracker != null)
+ {
+ _tracker.Dispose();
+ _tracker = null;
+ }
+ if (_packager != null)
+ {
+ _packager.Dispose();
+ _packager = null;
+ }
+
+ Platform.SetRenderer(Element, null);
+ SetElement(null);
+ Element = null;
+ }
+ base.Dispose(disposing);
+ }
+
+ protected virtual void OnElementChanged(ElementChangedEventArgs<TElement> e)
+ {
+ var args = new VisualElementChangedEventArgs(e.OldElement, e.NewElement);
+ for (var i = 0; i < _elementChangedHandlers.Count; i++)
+ _elementChangedHandlers[i](this, args);
+
+ var changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ SetBackgroundColor(Element.BackgroundColor);
+ else if (e.PropertyName == Layout.IsClippedToBoundsProperty.PropertyName)
+ UpdateClipToBounds();
+ }
+
+ protected virtual void OnRegisterEffect(PlatformEffect effect)
+ {
+ effect.Container = this;
+ }
+
+ protected virtual void SetAutomationId(string id)
+ {
+ AccessibilityIdentifier = id;
+ }
+
+ protected virtual void SetBackgroundColor(Color color)
+ {
+ if (color == Color.Default)
+ BackgroundColor = _defaultColor;
+ else
+ BackgroundColor = color.ToUIColor();
+ }
+
+ protected virtual void UpdateNativeWidget()
+ {
+ }
+
+ internal virtual void SendVisualElementInitialized(VisualElement element, UIView nativeView)
+ {
+ element.SendViewInitialized(nativeView);
+ }
+
+ void UpdateClipToBounds()
+ {
+ var clippableLayout = Element as Layout;
+ if (clippableLayout != null)
+ ClipsToBounds = clippableLayout.IsClippedToBounds;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/VisualElementTracker.cs b/Xamarin.Forms.Platform.iOS/VisualElementTracker.cs
new file mode 100644
index 00000000..0dbd7f9a
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/VisualElementTracker.cs
@@ -0,0 +1,259 @@
+using System;
+using System.Drawing;
+using System.ComponentModel;
+using System.Threading;
+#if __UNIFIED__
+using UIKit;
+using CoreAnimation;
+
+#else
+using MonoTouch.UIKit;
+using MonoTouch.CoreAnimation;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class VisualElementTracker : IDisposable
+ {
+ readonly EventHandler<EventArg<VisualElement>> _batchCommittedHandler;
+
+ readonly PropertyChangedEventHandler _propertyChangedHandler;
+ readonly EventHandler _sizeChangedEventHandler;
+ bool _disposed;
+ VisualElement _element;
+
+ // Track these by hand because the calls down into iOS are too expensive
+ bool _isInteractive;
+ Rectangle _lastBounds;
+
+ CALayer _layer;
+ int _updateCount;
+
+ public VisualElementTracker(IVisualElementRenderer renderer)
+ {
+ if (renderer == null)
+ throw new ArgumentNullException("renderer");
+
+ _propertyChangedHandler = HandlePropertyChanged;
+ _sizeChangedEventHandler = HandleSizeChanged;
+ _batchCommittedHandler = HandleRedrawNeeded;
+
+ Renderer = renderer;
+ renderer.ElementChanged += OnRendererElementChanged;
+ SetElement(null, renderer.Element);
+ }
+
+ IVisualElementRenderer Renderer { get; set; }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ public event EventHandler NativeControlUpdated;
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_disposed)
+ return;
+
+ _disposed = true;
+
+ if (disposing)
+ {
+ SetElement(_element, null);
+
+ if (_layer != null)
+ {
+ _layer.Dispose();
+ _layer = null;
+ }
+
+ Renderer.ElementChanged -= OnRendererElementChanged;
+ Renderer = null;
+ }
+ }
+
+ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == VisualElement.XProperty.PropertyName || e.PropertyName == VisualElement.YProperty.PropertyName || e.PropertyName == VisualElement.WidthProperty.PropertyName ||
+ e.PropertyName == VisualElement.HeightProperty.PropertyName || e.PropertyName == VisualElement.AnchorXProperty.PropertyName || e.PropertyName == VisualElement.AnchorYProperty.PropertyName ||
+ e.PropertyName == VisualElement.TranslationXProperty.PropertyName || e.PropertyName == VisualElement.TranslationYProperty.PropertyName || e.PropertyName == VisualElement.ScaleProperty.PropertyName ||
+ e.PropertyName == VisualElement.RotationProperty.PropertyName || e.PropertyName == VisualElement.RotationXProperty.PropertyName || e.PropertyName == VisualElement.RotationYProperty.PropertyName ||
+ e.PropertyName == VisualElement.IsVisibleProperty.PropertyName || e.PropertyName == VisualElement.IsEnabledProperty.PropertyName ||
+ e.PropertyName == VisualElement.InputTransparentProperty.PropertyName || e.PropertyName == VisualElement.OpacityProperty.PropertyName)
+ UpdateNativeControl(); // poorly optimized
+ }
+
+ void HandleRedrawNeeded(object sender, EventArgs e)
+ {
+ UpdateNativeControl();
+ }
+
+ void HandleSizeChanged(object sender, EventArgs e)
+ {
+ UpdateNativeControl();
+ }
+
+ void OnRendererElementChanged(object s, VisualElementChangedEventArgs e)
+ {
+ if (_element == e.NewElement)
+ return;
+
+ SetElement(_element, e.NewElement);
+ }
+
+ void OnUpdateNativeControl(CALayer caLayer)
+ {
+ var view = Renderer.Element;
+ var uiview = Renderer.NativeView;
+
+ if (view == null || view.Batched)
+ return;
+
+ var shouldInteract = !view.InputTransparent && view.IsEnabled;
+ if (_isInteractive != shouldInteract)
+ {
+ uiview.UserInteractionEnabled = shouldInteract;
+ _isInteractive = shouldInteract;
+ }
+
+ var boundsChanged = _lastBounds != view.Bounds;
+
+ var thread = !boundsChanged && !caLayer.Frame.IsEmpty;
+
+ var anchorX = (float)view.AnchorX;
+ var anchorY = (float)view.AnchorY;
+ var translationX = (float)view.TranslationX;
+ var translationY = (float)view.TranslationY;
+ var rotationX = (float)view.RotationX;
+ var rotationY = (float)view.RotationY;
+ var rotation = (float)view.Rotation;
+ var scale = (float)view.Scale;
+ var width = (float)view.Width;
+ var height = (float)view.Height;
+ var x = (float)view.X;
+ var y = (float)view.Y;
+ var opacity = (float)view.Opacity;
+ var isVisible = view.IsVisible;
+
+ var updateTarget = Interlocked.Increment(ref _updateCount);
+
+ Action update = () =>
+ {
+ if (updateTarget != _updateCount)
+ return;
+
+ var visualElement = view;
+ var parent = view.RealParent;
+
+ var shouldRelayoutSublayers = false;
+ if (isVisible && caLayer.Hidden)
+ {
+ caLayer.Hidden = false;
+ if (!caLayer.Frame.IsEmpty)
+ shouldRelayoutSublayers = true;
+ }
+
+ if (!isVisible && !caLayer.Hidden)
+ {
+ caLayer.Hidden = true;
+ shouldRelayoutSublayers = true;
+ }
+
+ // ripe for optimization
+ var transform = CATransform3D.Identity;
+
+ // Dont ever attempt to actually change the layout of a Page unless it is a ContentPage
+ // iOS is a really big fan of you not actually modifying the View's of the UIViewControllers
+ if ((!(visualElement is Page) || visualElement is ContentPage) && width > 0 && height > 0 && parent != null && boundsChanged)
+ {
+ var target = new RectangleF(x, y, width, height);
+ // must reset transform prior to setting frame...
+ caLayer.Transform = transform;
+ caLayer.Frame = target;
+ if (shouldRelayoutSublayers)
+ caLayer.LayoutSublayers();
+ }
+ else if (width <= 0 || height <= 0)
+ {
+ caLayer.Hidden = true;
+ return;
+ }
+
+ caLayer.AnchorPoint = new PointF(anchorX, anchorY);
+ caLayer.Opacity = opacity;
+ const double epsilon = 0.001;
+
+ // position is relative to anchor point
+ if (Math.Abs(anchorX - .5) > epsilon)
+ transform = transform.Translate((anchorX - .5f) * width, 0, 0);
+ if (Math.Abs(anchorY - .5) > epsilon)
+ transform = transform.Translate(0, (anchorY - .5f) * height, 0);
+
+ if (Math.Abs(translationX) > epsilon || Math.Abs(translationY) > epsilon)
+ transform = transform.Translate(translationX, translationY, 0);
+
+ if (Math.Abs(scale - 1) > epsilon)
+ transform = transform.Scale(scale);
+
+ // not just an optimization, iOS will not "pixel align" a view which has m34 set
+ if (Math.Abs(rotationY % 180) > epsilon || Math.Abs(rotationX % 180) > epsilon)
+ transform.m34 = 1.0f / -400f;
+
+ if (Math.Abs(rotationX % 360) > epsilon)
+ transform = transform.Rotate(rotationX * (float)Math.PI / 180.0f, 1.0f, 0.0f, 0.0f);
+ if (Math.Abs(rotationY % 360) > epsilon)
+ transform = transform.Rotate(rotationY * (float)Math.PI / 180.0f, 0.0f, 1.0f, 0.0f);
+
+ transform = transform.Rotate(rotation * (float)Math.PI / 180.0f, 0.0f, 0.0f, 1.0f);
+ caLayer.Transform = transform;
+ };
+
+ if (thread)
+ CADisplayLinkTicker.Default.Invoke(update);
+ else
+ update();
+
+ _lastBounds = view.Bounds;
+ }
+
+ void SetElement(VisualElement oldElement, VisualElement newElement)
+ {
+ if (oldElement != null)
+ {
+ oldElement.PropertyChanged -= _propertyChangedHandler;
+ oldElement.SizeChanged -= _sizeChangedEventHandler;
+ oldElement.BatchCommitted -= _batchCommittedHandler;
+ }
+
+ _element = newElement;
+
+ if (newElement != null)
+ {
+ newElement.BatchCommitted += _batchCommittedHandler;
+ newElement.SizeChanged += _sizeChangedEventHandler;
+ newElement.PropertyChanged += _propertyChangedHandler;
+
+ UpdateNativeControl();
+ }
+ }
+
+ void UpdateNativeControl()
+ {
+ if (_disposed)
+ return;
+
+ if (_layer == null)
+ {
+ _layer = Renderer.NativeView.Layer;
+ _isInteractive = Renderer.NativeView.UserInteractionEnabled;
+ }
+
+ OnUpdateNativeControl(_layer);
+
+ if (NativeControlUpdated != null)
+ NativeControlUpdated(this, EventArgs.Empty);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS.Classic.csproj b/Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS.Classic.csproj
new file mode 100644
index 00000000..7291c8f2
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS.Classic.csproj
@@ -0,0 +1,257 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}</ProjectGuid>
+ <ProjectTypeGuids>{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <RootNamespace>Xamarin.Forms.Platform.iOS</RootNamespace>
+ <IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
+ <AssemblyName>Xamarin.Forms.Platform.iOS.Classic</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>classic_bin\iPhoneSimulator\Debug\</OutputPath>
+ <BaseIntermediateOutputPath>classic_obj\</BaseIntermediateOutputPath>
+ <DefineConstants>TRACE;DEBUG;__MOBILE__;__IOS__</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <MtouchDebug>true</MtouchDebug>
+ <CodesignKey>iPhone Developer</CodesignKey>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>classic_bin\iPhoneSimulator\Release\</OutputPath>
+ <BaseIntermediateOutputPath>classic_obj\</BaseIntermediateOutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <CodesignKey>iPhone Developer</CodesignKey>
+ <DefineConstants>TRACE;__IOS__;__MOBILE__;</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>__MOBILE__;__IOS__;TRACE;DEBUG;__MOBILE__;__IOS__</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="CADisplayLinkTicker.cs" />
+ <Compile Include="ContextActionCell.cs" />
+ <Compile Include="ContextScrollViewDelegate.cs" />
+ <Compile Include="Extensions\CellExtensions.cs" />
+ <Compile Include="Forms.cs" />
+ <Compile Include="GlobalCloseContextGestureRecognizer.cs" />
+ <Compile Include="Extensions\ArrayExtensions.cs" />
+ <Compile Include="NativeViewWrapper.cs" />
+ <Compile Include="NativeViewWrapperRenderer.cs" />
+ <Compile Include="PlatformEffect.cs" />
+ <Compile Include="LayoutExtensions.cs" />
+ <Compile Include="Renderers\AlignmentExtensions.cs" />
+ <Compile Include="PageExtensions.cs" />
+ <Compile Include="Renderers\CarouselViewRenderer.cs" />
+ <Compile Include="Renderers\ExportCellAttribute.cs" />
+ <Compile Include="Renderers\ExportImageSourceHandlerAttribute.cs" />
+ <Compile Include="Renderers\ExportRendererAttribute.cs" />
+ <Compile Include="Resources\StringResources.Designer.cs" />
+ <Compile Include="ViewInitializedEventArgs.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="$(MSBuildThisFileDirectory)Deserializer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)ElementChangedEventArgs.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)EventTracker.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)FormsApplicationDelegate.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)IVisualElementRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Platform.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)PlatformRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)RendererFactory.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)RendererPool.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)ResourcesProvider.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)ViewRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)VisualElementPackager.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)VisualElementRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)VisualElementTracker.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Cells\CellRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Cells\CellTableViewCell.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Cells\EntryCellRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Cells\ImageCellRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Cells\SwitchCellRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Cells\TextCellRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Cells\ViewCellRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Extensions\ColorExtensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Extensions\DateExtensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Extensions\Extensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Extensions\ToolbarItemExtensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Extensions\UIViewExtensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Extensions\ViewExtensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\ActivityIndicatorRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\BoxRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\ButtonRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\CarouselPageRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\DatePickerRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\EditorRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\EntryRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\FontExtensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\FormattedStringExtensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\FrameRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\ImageRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\KeyboardInsetTracker.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\KeyboardObserver.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\LabelRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\ListViewRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\NavigationMenuRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\NavigationRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\OpenGLViewRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\PageRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\PhoneMasterDetailRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\PickerRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\ProgressBarRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\ScrollViewRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\SearchBarRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\SliderRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\StepperRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\SwitchRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\TabbedRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\TableViewModelRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\TableViewRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\TabletMasterDetailRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\TimePickerRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\ToolbarRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\WebViewRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.ar.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Runtime.Serialization" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Core" />
+ <Reference Include="monotouch" />
+ <Reference Include="System.Net.Http" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.MonoTouch.CSharp.targets" />
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.ca.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.cs.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.da.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.de.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.el.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.es.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.fi.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.fr.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.he.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.hi.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.hr.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.hu.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.id.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.it.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.ja.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.ko.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.ms.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.nb.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.nl.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.pl.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.pt-BR.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.pt.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.ro.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.ru.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.sk.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.sv.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.th.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.tr.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.uk.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.vi.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.zh-Hans.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.zh-Hant.resx" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.zh-HK.resx" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS.csproj b/Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS.csproj
new file mode 100644
index 00000000..5afb3b33
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS.csproj
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <ProjectGuid>{271193C1-6E7C-429C-A36D-3F1BE5267231}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <RootNamespace>Xamarin.Forms.Platform.iOS</RootNamespace>
+ <IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
+ <AssemblyName>Xamarin.Forms.Platform.iOS</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>full</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>__UNIFIED__;__MOBILE__;__IOS__;DEBUG;</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Runtime.Serialization" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Core" />
+ <Reference Include="Xamarin.iOS" />
+ <Reference Include="System.Net.Http" />
+ </ItemGroup>
+ <ItemGroup />
+ <ItemGroup>
+ <Compile Include="$(MSBuildThisFileDirectory)ContextActionCell.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)ContextScrollViewDelegate.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)GlobalCloseContextGestureRecognizer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Deserializer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)ElementChangedEventArgs.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)EventTracker.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)FormsApplicationDelegate.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)IVisualElementRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Platform.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)PlatformRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)RendererFactory.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)RendererPool.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)ResourcesProvider.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)ViewRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)VisualElementPackager.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)VisualElementRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)VisualElementTracker.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Cells\CellRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Cells\CellTableViewCell.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Cells\EntryCellRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Cells\ImageCellRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Cells\SwitchCellRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Cells\TextCellRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Cells\ViewCellRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Extensions\ColorExtensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Extensions\DateExtensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Extensions\Extensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Extensions\ToolbarItemExtensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Extensions\UIViewExtensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Extensions\ViewExtensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\ActivityIndicatorRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\BoxRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\ButtonRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\CarouselPageRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\DatePickerRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\EditorRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\EntryRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\FontExtensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\FormattedStringExtensions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\FrameRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\ImageRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\KeyboardInsetTracker.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\KeyboardObserver.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\LabelRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\ListViewRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\NavigationMenuRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\NavigationRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\OpenGLViewRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\PageRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\PhoneMasterDetailRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\PickerRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\ProgressBarRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\ScrollViewRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\SearchBarRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\SliderRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\StepperRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\SwitchRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\TabbedRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\TableViewModelRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\TableViewRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\TabletMasterDetailRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\TimePickerRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\ToolbarRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Renderers\WebViewRenderer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Properties\AssemblyInfo.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Extensions\CellExtensions.cs" />
+ <Compile Include="CADisplayLinkTicker.cs" />
+ <Compile Include="ExportCellAttribute.cs" />
+ <Compile Include="ExportImageSourceHandlerAttribute.cs" />
+ <Compile Include="ExportRendererAttribute.cs" />
+ <Compile Include="Extensions\ArrayExtensions.cs" />
+ <Compile Include="NativeViewWrapper.cs" />
+ <Compile Include="NativeViewWrapperRenderer.cs" />
+ <Compile Include="PlatformEffect.cs" />
+ <Compile Include="LayoutExtensions.cs" />
+ <Compile Include="Renderers\AlignmentExtensions.cs" />
+ <Compile Include="Forms.cs" />
+ <Compile Include="PageExtensions.cs" />
+ <Compile Include="Renderers\CarouselViewRenderer.cs" />
+ <Compile Include="Resources\StringResources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>StringResources.resx</DependentUpon>
+ </Compile>
+ <Compile Include="ViewInitializedEventArgs.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Resources\StringResources.ar.resx" />
+ <EmbeddedResource Include="Resources\StringResources.ca.resx" />
+ <EmbeddedResource Include="Resources\StringResources.cs.resx" />
+ <EmbeddedResource Include="Resources\StringResources.da.resx" />
+ <EmbeddedResource Include="Resources\StringResources.de.resx">
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Resources\StringResources.el.resx" />
+ <EmbeddedResource Include="Resources\StringResources.es.resx" />
+ <EmbeddedResource Include="Resources\StringResources.fi.resx" />
+ <EmbeddedResource Include="Resources\StringResources.fr.resx" />
+ <EmbeddedResource Include="Resources\StringResources.he.resx" />
+ <EmbeddedResource Include="Resources\StringResources.hi.resx" />
+ <EmbeddedResource Include="Resources\StringResources.hr.resx" />
+ <EmbeddedResource Include="Resources\StringResources.hu.resx" />
+ <EmbeddedResource Include="Resources\StringResources.id.resx" />
+ <EmbeddedResource Include="Resources\StringResources.it.resx" />
+ <EmbeddedResource Include="Resources\StringResources.ja.resx" />
+ <EmbeddedResource Include="Resources\StringResources.ko.resx" />
+ <EmbeddedResource Include="Resources\StringResources.ms.resx" />
+ <EmbeddedResource Include="Resources\StringResources.nb.resx" />
+ <EmbeddedResource Include="Resources\StringResources.nl.resx" />
+ <EmbeddedResource Include="Resources\StringResources.pl.resx" />
+ <EmbeddedResource Include="Resources\StringResources.pt-BR.resx" />
+ <EmbeddedResource Include="Resources\StringResources.pt.resx" />
+ <EmbeddedResource Include="Resources\StringResources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>StringResources.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Resources\StringResources.ro.resx" />
+ <EmbeddedResource Include="Resources\StringResources.ru.resx" />
+ <EmbeddedResource Include="Resources\StringResources.sk.resx" />
+ <EmbeddedResource Include="Resources\StringResources.sv.resx" />
+ <EmbeddedResource Include="Resources\StringResources.th.resx" />
+ <EmbeddedResource Include="Resources\StringResources.tr.resx" />
+ <EmbeddedResource Include="Resources\StringResources.uk.resx" />
+ <EmbeddedResource Include="Resources\StringResources.vi.resx" />
+ <EmbeddedResource Include="Resources\StringResources.zh-Hans.resx" />
+ <EmbeddedResource Include="Resources\StringResources.zh-Hant.resx" />
+ <EmbeddedResource Include="Resources\StringResources.zh-HK.resx" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS.nuspec b/Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS.nuspec
new file mode 100644
index 00000000..6ecf64c4
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Xamarin.Forms.Platform.iOS.nuspec
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<package >
+ <metadata>
+ <id>Xamarin.Forms.Platform.iOS</id>
+ <version>$version$</version>
+ <title>Xamarin.Forms iOS Platform Renderers</title>
+ <authors>Xamarin Inc.</authors>
+ <owners>Xamarin Inc.</owners>
+ <requireLicenseAcceptance>false</requireLicenseAcceptance>
+ <description>Xamarin.Forms platform abstruction library for mobile applications.</description>
+ <releaseNotes></releaseNotes>
+ <copyright>Copyright 2013</copyright>
+ </metadata>
+</package>
diff --git a/Xamarin.Forms.Platform/Properties/AssemblyInfo.cs b/Xamarin.Forms.Platform/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..6ca776be
--- /dev/null
+++ b/Xamarin.Forms.Platform/Properties/AssemblyInfo.cs
@@ -0,0 +1,32 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Xamarin.Forms.Platform")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Forms.Platform")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: NeutralResourcesLanguage("en")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Core")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file
diff --git a/Xamarin.Forms.Platform/Xamarin.Forms.Platform.cs b/Xamarin.Forms.Platform/Xamarin.Forms.Platform.cs
new file mode 100644
index 00000000..bdb66b86
--- /dev/null
+++ b/Xamarin.Forms.Platform/Xamarin.Forms.Platform.cs
@@ -0,0 +1,125 @@
+namespace Xamarin.Forms.Platform
+{
+ internal static class Loader
+ {
+ internal static void Load()
+ {
+ }
+ }
+
+ internal class _BoxViewRenderer
+ {
+ }
+
+ internal class _EntryRenderer
+ {
+ }
+
+ internal class _EditorRenderer
+ {
+ }
+
+ internal class _LabelRenderer
+ {
+ }
+
+ internal class _ImageRenderer
+ {
+ }
+
+ internal class _ButtonRenderer
+ {
+ }
+
+ internal class _TableViewRenderer
+ {
+ }
+
+ internal class _ListViewRenderer
+ {
+ }
+
+ internal class _CarouselViewRenderer
+ {
+ }
+
+ internal class _SliderRenderer
+ {
+ }
+
+ internal class _WebViewRenderer
+ {
+ }
+
+ internal class _SearchBarRenderer
+ {
+ }
+
+ internal class _SwitchRenderer
+ {
+ }
+
+ internal class _DatePickerRenderer
+ {
+ }
+
+ internal class _TimePickerRenderer
+ {
+ }
+
+ internal class _PickerRenderer
+ {
+ }
+
+ internal class _StepperRenderer
+ {
+ }
+
+ internal class _ProgressBarRenderer
+ {
+ }
+
+ internal class _ScrollViewRenderer
+ {
+ }
+
+ internal class _ToolbarRenderer
+ {
+ }
+
+ internal class _ActivityIndicatorRenderer
+ {
+ }
+
+ internal class _FrameRenderer
+ {
+ }
+
+ internal class _NavigationMenuRenderer
+ {
+ }
+
+ internal class _OpenGLViewRenderer
+ {
+ }
+
+ internal class _TabbedPageRenderer
+ {
+ }
+
+ internal class _NavigationPageRenderer
+ {
+ }
+
+ internal class _CarouselPageRenderer
+ {
+ }
+
+ internal class _PageRenderer
+ {
+ }
+
+ internal class _MasterDetailPageRenderer
+ {
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform/Xamarin.Forms.Platform.csproj b/Xamarin.Forms.Platform/Xamarin.Forms.Platform.csproj
new file mode 100644
index 00000000..3b4e32c5
--- /dev/null
+++ b/Xamarin.Forms.Platform/Xamarin.Forms.Platform.csproj
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{67F9D3A8-F71E-4428-913F-C37AE82CDB24}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Platform</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Platform</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ <NuGetPackageImportStamp>9af32e5a</NuGetPackageImportStamp>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="Xamarin.Forms.Platform.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+ </Target>
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/App.config b/Xamarin.Forms.UITest.TestCloud/App.config
new file mode 100644
index 00000000..8e156463
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/App.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <startup>
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
+ </startup>
+</configuration> \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/DeviceSet.cs b/Xamarin.Forms.UITest.TestCloud/DeviceSet.cs
new file mode 100644
index 00000000..3afa0959
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/DeviceSet.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.UITest.TestCloud
+{
+ internal class DeviceSet
+ {
+ public DeviceSet(List<Platform> deviceSetPlatform, string id, List<string> devices)
+ {
+ Id = id;
+ DeviceSetPlatform = deviceSetPlatform;
+ Devices = devices;
+ }
+
+ public string Id { get; private set; }
+
+ public List<Platform> DeviceSetPlatform { get; private set; }
+
+ public List<string> Devices { get; private set; }
+
+ internal enum Platform
+ {
+ None,
+ Android,
+ IOs,
+ IOsClassic
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/DeviceSets.cs b/Xamarin.Forms.UITest.TestCloud/DeviceSets.cs
new file mode 100644
index 00000000..508253bb
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/DeviceSets.cs
@@ -0,0 +1,154 @@
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.UITest.TestCloud
+{
+ internal static class DeviceSets
+ {
+ public static readonly DeviceSet AndroidMassiveSet =
+ new DeviceSet(new List<DeviceSet.Platform> { DeviceSet.Platform.Android }, "ddaf5646", new List<string>
+ {
+ "150+ devices!"
+ });
+
+ public static readonly DeviceSet IOsMassiveSet =
+ new DeviceSet(new List<DeviceSet.Platform> { DeviceSet.Platform.IOs, DeviceSet.Platform.IOsClassic }, "cc20a257",
+ new List<string>
+ {
+ "60+ devices!"
+ });
+
+ // Android
+ public static readonly DeviceSet AndroidFastParallel =
+ new DeviceSet(new List<DeviceSet.Platform> { DeviceSet.Platform.Android }, "7e376fe0", new List<string>
+ {
+ "LG Nexus 5 - Android 4.4.4"
+ });
+
+ public static readonly DeviceSet Android5 = new DeviceSet(
+ new List<DeviceSet.Platform> { DeviceSet.Platform.Android }, "f2d90195", new List<string>
+ {
+ "LG Nexus 5- Android 5.1.1"
+ });
+
+ public static readonly DeviceSet Android6 = new DeviceSet(
+ new List<DeviceSet.Platform> { DeviceSet.Platform.Android }, "012c8f06", new List<string>
+ {
+ "LG Nexus 5 - Android 6.0.1"
+ });
+
+ public static readonly DeviceSet SethLocalDeviceSetAndroid =
+ new DeviceSet(new List<DeviceSet.Platform> { DeviceSet.Platform.Android }, "9e76018b", new List<string>
+ {
+ "Google Nexus 7 - 4.4.2",
+ "Samsung Galaxy S4 (Google Play Edition GT-I9505G) - Seth -> 4.4, Test Cloud -> 4.4.2 (closest match)"
+ });
+
+ public static readonly DeviceSet IcsSmallSet =
+ new DeviceSet(new List<DeviceSet.Platform> { DeviceSet.Platform.Android }, "fc61dbe3", new List<string>
+ {
+ "Amazon Kindle Fire (2nd Gen) - 4.0.3",
+ "HTC Desire - 4.0.3",
+ "Samsung Galaxy Tab 2 - 4.0.4",
+ "Sony Xperia neo L - 4.0.3"
+ });
+
+ public static readonly DeviceSet AndroidAllApiSmallSet =
+ new DeviceSet(new List<DeviceSet.Platform> { DeviceSet.Platform.Android }, "4f912d99", new List<string>
+ {
+ "HTC Sensation XL - 4.0.3",
+ "Amazon Kindle Fire (2nd Generation) - 4.0.3",
+ "Samsung Galaxy Tab 2 - 4.0.4",
+ "Motorola ATRIX 2 - 4.0.4",
+ "Samsung Galaxy Note II - 4.1.1",
+ "HP Slate 7 - 4.1.1",
+ "Sony Xperia Z - 4.1.2",
+ "Samsung Galaxy Tab 3 7.0 - 4.1.2",
+ "Google Nexus 7 - 4.2",
+ "Oppo R819 - 4.2.1",
+ "Samsung Galaxy S4 Zoom - 4.2.2",
+ "Acer Iconia Tab A1 - 4.2.2",
+ "Samsung Galaxy S4 (Octo-core) - 4.3",
+ "Oppo N1 - 4.3",
+ "LG Nexus 5 - 4.4",
+ "Samsung Google Nexus 10 - 4.4",
+ "Samsung Galaxy S5 - 4.4.2",
+ "Samsung Galaxy Note - 3 (Octo-Core) - 4.4.2"
+ });
+
+ public static readonly DeviceSet IOsFastParallel =
+ new DeviceSet(new List<DeviceSet.Platform> { DeviceSet.Platform.IOs, DeviceSet.Platform.IOsClassic }, "7f2fa3ae",
+ new List<string>
+ {
+ "Apple iPad Mini Retina - iOS 7.1.2"
+ });
+
+ // iOS
+ public static readonly DeviceSet SethLocalDeviceSetiOs =
+ new DeviceSet(new List<DeviceSet.Platform> { DeviceSet.Platform.IOs, DeviceSet.Platform.IOsClassic }, "b417f165",
+ new List<string>
+ {
+ "Apple iPhone 5 - iOS 7.1.1",
+ "Apple iPad Air - iOS 7.1.1"
+ });
+
+ public static readonly DeviceSet IOsAllApiSmallSet =
+ new DeviceSet(new List<DeviceSet.Platform> { DeviceSet.Platform.IOs, DeviceSet.Platform.IOsClassic }, "d2d6440e",
+ new List<string>
+ {
+ "Apple iPod Touch 5th Gen - iOS 6.0.1",
+ "Apple iPad 2 - iOS 6.1.3",
+ "Apple iPhone 4 - iOS 6.1.3",
+ "Apple iPhone 5 - iOS 6.1.4",
+ "Apple iPhone 3GS - iOS 6.1.6",
+ "Apple iPod Touch 4th Gen - iOS 6.1.6",
+ "Apple iPhone 5C - iOS 7.0.2",
+ "Apple iPad Mini - iOS 7.0.3",
+ "Apple iPad 4 - iOS 7.0.4",
+ "Apple iPhone 5S - iOS 7.0.4",
+ "Apple iPad Air - iOS 7.1",
+ "Apple iPhone 5C - iOS 7.1",
+ "Apple iPad Air - iOS 7.1.1",
+ "Apple iPhone 4S - iOS 7.1.1",
+ "Apple iPhone 5 - iOS 7.1.1"
+ });
+
+ public static readonly DeviceSet IOs8 =
+ new DeviceSet(new List<DeviceSet.Platform> { DeviceSet.Platform.IOs, DeviceSet.Platform.IOsClassic }, "56293ce6",
+ new List<string>
+ {
+ "Apple iPhone 5S - iOS 8.1"
+ });
+
+ public static readonly DeviceSet IOs7AndiOs8 =
+ new DeviceSet(new List<DeviceSet.Platform> { DeviceSet.Platform.IOs, DeviceSet.Platform.IOsClassic }, "5190fc68",
+ new List<string>
+ {
+ "Apple Ipad Retina Mini - iOS 7.1.2",
+ "Apple Iphone 6 Plus - 8.1.3"
+ });
+
+ public static readonly DeviceSet IOs6PhoneTablet =
+ new DeviceSet(new List<DeviceSet.Platform> { DeviceSet.Platform.IOs, DeviceSet.Platform.IOsClassic }, "212c4682",
+ new List<string>
+ {
+ "Apple Ipad 4 - iOS 6.1.3",
+ "Apple Iphone 4 - iOS 6.1.3"
+ });
+
+ public static readonly DeviceSet IOs9 =
+ new DeviceSet(new List<DeviceSet.Platform> { DeviceSet.Platform.IOs, DeviceSet.Platform.IOsClassic }, "dc3140fd",
+ new List<string>
+ {
+ "Apple Iphone 6 - iOS 9.0",
+ "Apple Ipad Air - iOS 9.0"
+ });
+
+ public static readonly DeviceSet IOs91 =
+ new DeviceSet(new List<DeviceSet.Platform> { DeviceSet.Platform.IOs, DeviceSet.Platform.IOsClassic }, "7f4b13f8",
+ new List<string>
+ {
+ "Apple Iphone 6S - iOS 9.1",
+ "Apple Ipad Air 2 - iOS 9.1"
+ });
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/LoaderActions.cs b/Xamarin.Forms.UITest.TestCloud/LoaderActions.cs
new file mode 100644
index 00000000..93edee2b
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/LoaderActions.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Xamarin.Forms.Loader;
+
+namespace Xamarin.Forms.UITest.TestCloud
+{
+ internal class LoaderActions
+ {
+ readonly IEnumerable<string> _testCategories;
+
+ public LoaderActions()
+ {
+ var formsLoader = new FormsLoader();
+
+ var categoriesOnTypes =
+ from type in formsLoader.IOSTestTypes()
+ from categoryAttribute in type.Categories()
+ select categoryAttribute.Name;
+
+ var categoriesOnMembers =
+ from type in formsLoader.IOSTestTypes()
+ from members in type.Members()
+ from categoryAttribute in members.CategoryAttributes()
+ select categoryAttribute.Name;
+
+ _testCategories = categoriesOnTypes.Union(categoriesOnMembers);
+ }
+
+ public void ListCategories()
+ {
+ foreach (string category in _testCategories)
+ Console.WriteLine(category);
+ }
+
+ public bool ValidateCategory(string category)
+ {
+ return _testCategories.Any(k => k == category) || category == "All";
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/Mono.Options/ArgumentSource.cs b/Xamarin.Forms.UITest.TestCloud/Mono.Options/ArgumentSource.cs
new file mode 100644
index 00000000..da24d02b
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/Mono.Options/ArgumentSource.cs
@@ -0,0 +1,78 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Mono.Options
+{
+ public abstract class ArgumentSource
+ {
+ public abstract string Description { get; }
+
+ public abstract string[] GetNames();
+ public abstract bool GetArguments(string value, out IEnumerable<string> replacement);
+
+ public static IEnumerable<string> GetArgumentsFromFile(string file)
+ {
+ return GetArguments(File.OpenText(file), true);
+ }
+
+ public static IEnumerable<string> GetArguments(TextReader reader)
+ {
+ return GetArguments(reader, false);
+ }
+
+ // Cribbed from mcs/driver.cs:LoadArgs(string)
+ static IEnumerable<string> GetArguments(TextReader reader, bool close)
+ {
+ try
+ {
+ StringBuilder arg = new StringBuilder();
+
+ string line;
+ while ((line = reader.ReadLine()) != null)
+ {
+ int t = line.Length;
+
+ for (int i = 0; i < t; i++)
+ {
+ char c = line[i];
+
+ if (c == '"' || c == '\'')
+ {
+ char end = c;
+
+ for (i++; i < t; i++)
+ {
+ c = line[i];
+
+ if (c == end)
+ break;
+ arg.Append(c);
+ }
+ }
+ else if (c == ' ')
+ {
+ if (arg.Length > 0)
+ {
+ yield return arg.ToString();
+ arg.Length = 0;
+ }
+ }
+ else
+ arg.Append(c);
+ }
+ if (arg.Length > 0)
+ {
+ yield return arg.ToString();
+ arg.Length = 0;
+ }
+ }
+ }
+ finally
+ {
+ if (close)
+ reader.Close();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/Mono.Options/Option.cs b/Xamarin.Forms.UITest.TestCloud/Mono.Options/Option.cs
new file mode 100644
index 00000000..f91934c2
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/Mono.Options/Option.cs
@@ -0,0 +1,221 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+
+namespace Mono.Options
+{
+ public abstract class Option
+ {
+ static readonly char[] NameTerminator = { '=', ':' };
+
+ protected Option(string prototype, string description)
+ : this(prototype, description, 1, false)
+ {
+ }
+
+ protected Option(string prototype, string description, int maxValueCount)
+ : this(prototype, description, maxValueCount, false)
+ {
+ }
+
+ protected Option(string prototype, string description, int maxValueCount, bool hidden)
+ {
+ if (prototype == null)
+ throw new ArgumentNullException("prototype");
+ if (prototype.Length == 0)
+ throw new ArgumentException("Cannot be the empty string.", "prototype");
+ if (maxValueCount < 0)
+ throw new ArgumentOutOfRangeException("maxValueCount");
+
+ Prototype = prototype;
+ Description = description;
+ MaxValueCount = maxValueCount;
+ Names = (this is OptionSet.Category)
+ // append GetHashCode() so that "duplicate" categories have distinct
+ // names, e.g. adding multiple "" categories should be valid.
+ ? new[] { prototype + GetHashCode() }
+ : prototype.Split('|');
+
+ if (this is OptionSet.Category)
+ return;
+
+ OptionValueType = ParsePrototype();
+ Hidden = hidden;
+
+ if (MaxValueCount == 0 && OptionValueType != OptionValueType.None)
+ {
+ throw new ArgumentException(
+ "Cannot provide maxValueCount of 0 for OptionValueType.Required or " +
+ "OptionValueType.Optional.",
+ "maxValueCount");
+ }
+ if (OptionValueType == OptionValueType.None && maxValueCount > 1)
+ {
+ throw new ArgumentException(
+ string.Format("Cannot provide maxValueCount of {0} for OptionValueType.None.", maxValueCount),
+ "maxValueCount");
+ }
+ if (Array.IndexOf(Names, "<>") >= 0 &&
+ ((Names.Length == 1 && OptionValueType != OptionValueType.None) ||
+ (Names.Length > 1 && MaxValueCount > 1)))
+ {
+ throw new ArgumentException(
+ "The default option handler '<>' cannot require values.",
+ "prototype");
+ }
+ }
+
+ public string Prototype { get; }
+
+ public string Description { get; }
+
+ public OptionValueType OptionValueType { get; }
+
+ public int MaxValueCount { get; }
+
+ public bool Hidden { get; }
+
+ internal string[] Names { get; }
+
+ internal string[] ValueSeparators { get; private set; }
+
+ public string[] GetNames()
+ {
+ return (string[])Names.Clone();
+ }
+
+ public string[] GetValueSeparators()
+ {
+ if (ValueSeparators == null)
+ return new string[0];
+ return (string[])ValueSeparators.Clone();
+ }
+
+ protected static T Parse<T>(string value, OptionContext c)
+ {
+ Type tt = typeof (T);
+ bool nullable = tt.IsValueType && tt.IsGenericType &&
+ !tt.IsGenericTypeDefinition &&
+ tt.GetGenericTypeDefinition() == typeof (Nullable<>);
+ Type targetType = nullable ? tt.GetGenericArguments()[0] : typeof (T);
+ TypeConverter conv = TypeDescriptor.GetConverter(targetType);
+ T t = default(T);
+ try
+ {
+ if (value != null)
+ t = (T)conv.ConvertFromString(value);
+ }
+ catch (Exception e)
+ {
+ throw new OptionException(
+ string.Format(
+ c.OptionSet.MessageLocalizer("Could not convert string `{0}' to type {1} for option `{2}'."),
+ value, targetType.Name, c.OptionName),
+ c.OptionName, e);
+ }
+ return t;
+ }
+
+ OptionValueType ParsePrototype()
+ {
+ char type = '\0';
+ List<string> seps = new List<string>();
+ for (int i = 0; i < Names.Length; ++i)
+ {
+ string name = Names[i];
+ if (name.Length == 0)
+ throw new ArgumentException("Empty option names are not supported.", "prototype");
+
+ int end = name.IndexOfAny(NameTerminator);
+ if (end == -1)
+ continue;
+ Names[i] = name.Substring(0, end);
+ if (type == '\0' || type == name[end])
+ type = name[end];
+ else
+ {
+ throw new ArgumentException(
+ string.Format("Conflicting option types: '{0}' vs. '{1}'.", type, name[end]),
+ "prototype");
+ }
+ AddSeparators(name, end, seps);
+ }
+
+ if (type == '\0')
+ return OptionValueType.None;
+
+ if (MaxValueCount <= 1 && seps.Count != 0)
+ {
+ throw new ArgumentException(
+ string.Format("Cannot provide key/value separators for Options taking {0} value(s).", MaxValueCount),
+ "prototype");
+ }
+ if (MaxValueCount > 1)
+ {
+ if (seps.Count == 0)
+ ValueSeparators = new[] { ":", "=" };
+ else if (seps.Count == 1 && seps[0].Length == 0)
+ ValueSeparators = null;
+ else
+ ValueSeparators = seps.ToArray();
+ }
+
+ return type == '=' ? OptionValueType.Required : OptionValueType.Optional;
+ }
+
+ static void AddSeparators(string name, int end, ICollection<string> seps)
+ {
+ int start = -1;
+ for (int i = end + 1; i < name.Length; ++i)
+ {
+ switch (name[i])
+ {
+ case '{':
+ if (start != -1)
+ {
+ throw new ArgumentException(
+ string.Format("Ill-formed name/value separator found in \"{0}\".", name),
+ "prototype");
+ }
+ start = i + 1;
+ break;
+ case '}':
+ if (start == -1)
+ {
+ throw new ArgumentException(
+ string.Format("Ill-formed name/value separator found in \"{0}\".", name),
+ "prototype");
+ }
+ seps.Add(name.Substring(start, i - start));
+ start = -1;
+ break;
+ default:
+ if (start == -1)
+ seps.Add(name[i].ToString());
+ break;
+ }
+ }
+ if (start != -1)
+ {
+ throw new ArgumentException(
+ string.Format("Ill-formed name/value separator found in \"{0}\".", name),
+ "prototype");
+ }
+ }
+
+ public void Invoke(OptionContext c)
+ {
+ OnParseComplete(c);
+ c.OptionName = null;
+ c.Option = null;
+ c.OptionValues.Clear();
+ }
+
+ protected abstract void OnParseComplete(OptionContext c);
+
+ public override string ToString()
+ {
+ return Prototype;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionAction.cs b/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionAction.cs
new file mode 100644
index 00000000..2c8fd7b3
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionAction.cs
@@ -0,0 +1,4 @@
+namespace Mono.Options
+{
+ public delegate void OptionAction<TKey, TValue>(TKey key, TValue value);
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionContext.cs b/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionContext.cs
new file mode 100644
index 00000000..4a718360
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionContext.cs
@@ -0,0 +1,21 @@
+namespace Mono.Options
+{
+ public class OptionContext
+ {
+ public OptionContext(OptionSet set)
+ {
+ OptionSet = set;
+ OptionValues = new OptionValueCollection(this);
+ }
+
+ public Option Option { get; set; }
+
+ public string OptionName { get; set; }
+
+ public int OptionIndex { get; set; }
+
+ public OptionSet OptionSet { get; }
+
+ public OptionValueCollection OptionValues { get; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionException.cs b/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionException.cs
new file mode 100644
index 00000000..8a8229e7
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionException.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+
+namespace Mono.Options
+{
+ [Serializable]
+ public class OptionException : Exception
+ {
+ public OptionException()
+ {
+ }
+
+ public OptionException(string message, string optionName)
+ : base(message)
+ {
+ OptionName = optionName;
+ }
+
+ public OptionException(string message, string optionName, Exception innerException)
+ : base(message, innerException)
+ {
+ OptionName = optionName;
+ }
+
+ protected OptionException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ OptionName = info.GetString("OptionName");
+ }
+
+ public string OptionName { get; }
+
+ [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+ info.AddValue("OptionName", OptionName);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionSet.cs b/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionSet.cs
new file mode 100644
index 00000000..5d406705
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionSet.cs
@@ -0,0 +1,718 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Mono.Options
+{
+ public class OptionSet : KeyedCollection<string, Option>
+ {
+ const int OptionWidth = 29;
+ const int DescriptionFirstWidth = 80 - OptionWidth;
+ const int DescriptionRemWidth = 80 - OptionWidth - 2;
+
+ readonly Regex _valueOption = new Regex(
+ @"^(?<flag>--|-|/)(?<name>[^:=]+)((?<sep>[:=])(?<value>.*))?$");
+
+ readonly List<ArgumentSource> _sources = new List<ArgumentSource>();
+
+ public OptionSet()
+ : this(delegate(string f) { return f; })
+ {
+ }
+
+ public OptionSet(Converter<string, string> localizer)
+ {
+ MessageLocalizer = localizer;
+ ArgumentSources = new ReadOnlyCollection<ArgumentSource>(_sources);
+ }
+
+ public Converter<string, string> MessageLocalizer { get; }
+
+ public ReadOnlyCollection<ArgumentSource> ArgumentSources { get; }
+
+ protected override string GetKeyForItem(Option item)
+ {
+ if (item == null)
+ throw new ArgumentNullException("option");
+ if (item.Names != null && item.Names.Length > 0)
+ return item.Names[0];
+ // This should never happen, as it's invalid for Option to be
+ // constructed w/o any names.
+ throw new InvalidOperationException("Option has no names!");
+ }
+
+ [Obsolete("Use KeyedCollection.this[string]")]
+ protected Option GetOptionForName(string option)
+ {
+ if (option == null)
+ throw new ArgumentNullException("option");
+ try
+ {
+ return base[option];
+ }
+ catch (KeyNotFoundException)
+ {
+ return null;
+ }
+ }
+
+ protected override void InsertItem(int index, Option item)
+ {
+ base.InsertItem(index, item);
+ AddImpl(item);
+ }
+
+ protected override void RemoveItem(int index)
+ {
+ Option p = Items[index];
+ base.RemoveItem(index);
+ // KeyedCollection.RemoveItem() handles the 0th item
+ for (int i = 1; i < p.Names.Length; ++i)
+ Dictionary.Remove(p.Names[i]);
+ }
+
+ protected override void SetItem(int index, Option item)
+ {
+ base.SetItem(index, item);
+ AddImpl(item);
+ }
+
+ void AddImpl(Option option)
+ {
+ if (option == null)
+ throw new ArgumentNullException("option");
+ List<string> added = new List<string>(option.Names.Length);
+ try
+ {
+ // KeyedCollection.InsertItem/SetItem handle the 0th name.
+ for (int i = 1; i < option.Names.Length; ++i)
+ {
+ Dictionary.Add(option.Names[i], option);
+ added.Add(option.Names[i]);
+ }
+ }
+ catch (Exception)
+ {
+ foreach (string name in added)
+ Dictionary.Remove(name);
+ throw;
+ }
+ }
+
+ public OptionSet Add(string header)
+ {
+ if (header == null)
+ throw new ArgumentNullException("header");
+ Add(new Category(header));
+ return this;
+ }
+
+ public new OptionSet Add(Option option)
+ {
+ base.Add(option);
+ return this;
+ }
+
+ public OptionSet Add(string prototype, Action<string> action)
+ {
+ return Add(prototype, null, action);
+ }
+
+ public OptionSet Add(string prototype, string description, Action<string> action)
+ {
+ return Add(prototype, description, action, false);
+ }
+
+ public OptionSet Add(string prototype, string description, Action<string> action, bool hidden)
+ {
+ if (action == null)
+ throw new ArgumentNullException("action");
+ Option p = new ActionOption(prototype, description, 1,
+ delegate(OptionValueCollection v) { action(v[0]); }, hidden);
+ base.Add(p);
+ return this;
+ }
+
+ public OptionSet Add(string prototype, OptionAction<string, string> action)
+ {
+ return Add(prototype, null, action);
+ }
+
+ public OptionSet Add(string prototype, string description, OptionAction<string, string> action)
+ {
+ return Add(prototype, description, action, false);
+ }
+
+ public OptionSet Add(string prototype, string description, OptionAction<string, string> action, bool hidden)
+ {
+ if (action == null)
+ throw new ArgumentNullException("action");
+ Option p = new ActionOption(prototype, description, 2,
+ delegate(OptionValueCollection v) { action(v[0], v[1]); }, hidden);
+ base.Add(p);
+ return this;
+ }
+
+ public OptionSet Add<T>(string prototype, Action<T> action)
+ {
+ return Add(prototype, null, action);
+ }
+
+ public OptionSet Add<T>(string prototype, string description, Action<T> action)
+ {
+ return Add(new ActionOption<T>(prototype, description, action));
+ }
+
+ public OptionSet Add<TKey, TValue>(string prototype, OptionAction<TKey, TValue> action)
+ {
+ return Add(prototype, null, action);
+ }
+
+ public OptionSet Add<TKey, TValue>(string prototype, string description, OptionAction<TKey, TValue> action)
+ {
+ return Add(new ActionOption<TKey, TValue>(prototype, description, action));
+ }
+
+ public OptionSet Add(ArgumentSource source)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ _sources.Add(source);
+ return this;
+ }
+
+ protected virtual OptionContext CreateOptionContext()
+ {
+ return new OptionContext(this);
+ }
+
+ public List<string> Parse(IEnumerable<string> arguments)
+ {
+ if (arguments == null)
+ throw new ArgumentNullException("arguments");
+ OptionContext c = CreateOptionContext();
+ c.OptionIndex = -1;
+ bool process = true;
+ List<string> unprocessed = new List<string>();
+ Option def = Contains("<>") ? this["<>"] : null;
+ ArgumentEnumerator ae = new ArgumentEnumerator(arguments);
+ foreach (string argument in ae)
+ {
+ ++c.OptionIndex;
+ if (argument == "--")
+ {
+ process = false;
+ continue;
+ }
+ if (!process)
+ {
+ Unprocessed(unprocessed, def, c, argument);
+ continue;
+ }
+ if (AddSource(ae, argument))
+ continue;
+ if (!Parse(argument, c))
+ Unprocessed(unprocessed, def, c, argument);
+ }
+ if (c.Option != null)
+ c.Option.Invoke(c);
+ return unprocessed;
+ }
+
+ bool AddSource(ArgumentEnumerator ae, string argument)
+ {
+ foreach (ArgumentSource source in _sources)
+ {
+ IEnumerable<string> replacement;
+ if (!source.GetArguments(argument, out replacement))
+ continue;
+ ae.Add(replacement);
+ return true;
+ }
+ return false;
+ }
+
+ static bool Unprocessed(ICollection<string> extra, Option def, OptionContext c, string argument)
+ {
+ if (def == null)
+ {
+ extra.Add(argument);
+ return false;
+ }
+ c.OptionValues.Add(argument);
+ c.Option = def;
+ c.Option.Invoke(c);
+ return false;
+ }
+
+ protected bool GetOptionParts(string argument, out string flag, out string name, out string sep, out string value)
+ {
+ if (argument == null)
+ throw new ArgumentNullException("argument");
+
+ flag = name = sep = value = null;
+ Match m = _valueOption.Match(argument);
+ if (!m.Success)
+ return false;
+ flag = m.Groups["flag"].Value;
+ name = m.Groups["name"].Value;
+ if (m.Groups["sep"].Success && m.Groups["value"].Success)
+ {
+ sep = m.Groups["sep"].Value;
+ value = m.Groups["value"].Value;
+ }
+ return true;
+ }
+
+ protected virtual bool Parse(string argument, OptionContext c)
+ {
+ if (c.Option != null)
+ {
+ ParseValue(argument, c);
+ return true;
+ }
+
+ string f, n, s, v;
+ if (!GetOptionParts(argument, out f, out n, out s, out v))
+ return false;
+
+ Option p;
+ if (Contains(n))
+ {
+ p = this[n];
+ c.OptionName = f + n;
+ c.Option = p;
+ switch (p.OptionValueType)
+ {
+ case OptionValueType.None:
+ c.OptionValues.Add(n);
+ c.Option.Invoke(c);
+ break;
+ case OptionValueType.Optional:
+ case OptionValueType.Required:
+ ParseValue(v, c);
+ break;
+ }
+ return true;
+ }
+ // no match; is it a bool option?
+ if (ParseBool(argument, n, c))
+ return true;
+ // is it a bundled option?
+ if (ParseBundledValue(f, string.Concat(n + s + v), c))
+ return true;
+
+ return false;
+ }
+
+ void ParseValue(string option, OptionContext c)
+ {
+ if (option != null)
+ {
+ foreach (string o in c.Option.ValueSeparators != null
+ ? option.Split(c.Option.ValueSeparators, c.Option.MaxValueCount - c.OptionValues.Count, StringSplitOptions.None)
+ : new[] { option })
+ c.OptionValues.Add(o);
+ }
+ if (c.OptionValues.Count == c.Option.MaxValueCount ||
+ c.Option.OptionValueType == OptionValueType.Optional)
+ c.Option.Invoke(c);
+ else if (c.OptionValues.Count > c.Option.MaxValueCount)
+ {
+ throw new OptionException(MessageLocalizer(string.Format(
+ "Error: Found {0} option values when expecting {1}.",
+ c.OptionValues.Count, c.Option.MaxValueCount)),
+ c.OptionName);
+ }
+ }
+
+ bool ParseBool(string option, string n, OptionContext c)
+ {
+ Option p;
+ string rn;
+ if (n.Length >= 1 && (n[n.Length - 1] == '+' || n[n.Length - 1] == '-') &&
+ Contains((rn = n.Substring(0, n.Length - 1))))
+ {
+ p = this[rn];
+ string v = n[n.Length - 1] == '+' ? option : null;
+ c.OptionName = option;
+ c.Option = p;
+ c.OptionValues.Add(v);
+ p.Invoke(c);
+ return true;
+ }
+ return false;
+ }
+
+ bool ParseBundledValue(string f, string n, OptionContext c)
+ {
+ if (f != "-")
+ return false;
+ for (int i = 0; i < n.Length; ++i)
+ {
+ Option p;
+ string opt = f + n[i];
+ string rn = n[i].ToString();
+ if (!Contains(rn))
+ {
+ if (i == 0)
+ return false;
+ throw new OptionException(string.Format(MessageLocalizer(
+ "Cannot bundle unregistered option '{0}'."), opt), opt);
+ }
+ p = this[rn];
+ switch (p.OptionValueType)
+ {
+ case OptionValueType.None:
+ Invoke(c, opt, n, p);
+ break;
+ case OptionValueType.Optional:
+ case OptionValueType.Required:
+ {
+ string v = n.Substring(i + 1);
+ c.Option = p;
+ c.OptionName = opt;
+ ParseValue(v.Length != 0 ? v : null, c);
+ return true;
+ }
+ default:
+ throw new InvalidOperationException("Unknown OptionValueType: " + p.OptionValueType);
+ }
+ }
+ return true;
+ }
+
+ static void Invoke(OptionContext c, string name, string value, Option option)
+ {
+ c.OptionName = name;
+ c.Option = option;
+ c.OptionValues.Add(value);
+ option.Invoke(c);
+ }
+
+ public void WriteOptionDescriptions(TextWriter o)
+ {
+ foreach (Option p in this)
+ {
+ int written = 0;
+
+ if (p.Hidden)
+ continue;
+
+ Category c = p as Category;
+ if (c != null)
+ {
+ WriteDescription(o, p.Description, "", 80, 80);
+ continue;
+ }
+
+ if (!WriteOptionPrototype(o, p, ref written))
+ continue;
+
+ if (written < OptionWidth)
+ o.Write(new string(' ', OptionWidth - written));
+ else
+ {
+ o.WriteLine();
+ o.Write(new string(' ', OptionWidth));
+ }
+
+ WriteDescription(o, p.Description, new string(' ', OptionWidth + 2),
+ DescriptionFirstWidth, DescriptionRemWidth);
+ }
+
+ foreach (ArgumentSource s in _sources)
+ {
+ string[] names = s.GetNames();
+ if (names == null || names.Length == 0)
+ continue;
+
+ int written = 0;
+
+ Write(o, ref written, " ");
+ Write(o, ref written, names[0]);
+ for (int i = 1; i < names.Length; ++i)
+ {
+ Write(o, ref written, ", ");
+ Write(o, ref written, names[i]);
+ }
+
+ if (written < OptionWidth)
+ o.Write(new string(' ', OptionWidth - written));
+ else
+ {
+ o.WriteLine();
+ o.Write(new string(' ', OptionWidth));
+ }
+
+ WriteDescription(o, s.Description, new string(' ', OptionWidth + 2),
+ DescriptionFirstWidth, DescriptionRemWidth);
+ }
+ }
+
+ void WriteDescription(TextWriter o, string value, string prefix, int firstWidth, int remWidth)
+ {
+ bool indent = false;
+ foreach (string line in GetLines(MessageLocalizer(GetDescription(value)), firstWidth, remWidth))
+ {
+ if (indent)
+ o.Write(prefix);
+ o.WriteLine(line);
+ indent = true;
+ }
+ }
+
+ bool WriteOptionPrototype(TextWriter o, Option p, ref int written)
+ {
+ string[] names = p.Names;
+
+ int i = GetNextOptionIndex(names, 0);
+ if (i == names.Length)
+ return false;
+
+ if (names[i].Length == 1)
+ {
+ Write(o, ref written, " -");
+ Write(o, ref written, names[0]);
+ }
+ else
+ {
+ Write(o, ref written, " --");
+ Write(o, ref written, names[0]);
+ }
+
+ for (i = GetNextOptionIndex(names, i + 1);
+ i < names.Length;
+ i = GetNextOptionIndex(names, i + 1))
+ {
+ Write(o, ref written, ", ");
+ Write(o, ref written, names[i].Length == 1 ? "-" : "--");
+ Write(o, ref written, names[i]);
+ }
+
+ if (p.OptionValueType == OptionValueType.Optional ||
+ p.OptionValueType == OptionValueType.Required)
+ {
+ if (p.OptionValueType == OptionValueType.Optional)
+ Write(o, ref written, MessageLocalizer("["));
+ Write(o, ref written, MessageLocalizer("=" + GetArgumentName(0, p.MaxValueCount, p.Description)));
+ string sep = p.ValueSeparators != null && p.ValueSeparators.Length > 0
+ ? p.ValueSeparators[0]
+ : " ";
+ for (int c = 1; c < p.MaxValueCount; ++c)
+ Write(o, ref written, MessageLocalizer(sep + GetArgumentName(c, p.MaxValueCount, p.Description)));
+ if (p.OptionValueType == OptionValueType.Optional)
+ Write(o, ref written, MessageLocalizer("]"));
+ }
+ return true;
+ }
+
+ static int GetNextOptionIndex(string[] names, int i)
+ {
+ while (i < names.Length && names[i] == "<>")
+ ++i;
+ return i;
+ }
+
+ static void Write(TextWriter o, ref int n, string s)
+ {
+ n += s.Length;
+ o.Write(s);
+ }
+
+ static string GetArgumentName(int index, int maxIndex, string description)
+ {
+ if (description == null)
+ return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1);
+ string[] nameStart;
+ if (maxIndex == 1)
+ nameStart = new[] { "{0:", "{" };
+ else
+ nameStart = new[] { "{" + index + ":" };
+ for (int i = 0; i < nameStart.Length; ++i)
+ {
+ int start, j = 0;
+ do
+ {
+ start = description.IndexOf(nameStart[i], j);
+ } while (start >= 0 && j != 0 ? description[j++ - 1] == '{' : false);
+ if (start == -1)
+ continue;
+ int end = description.IndexOf("}", start);
+ if (end == -1)
+ continue;
+ return description.Substring(start + nameStart[i].Length, end - start - nameStart[i].Length);
+ }
+ return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1);
+ }
+
+ static string GetDescription(string description)
+ {
+ if (description == null)
+ return string.Empty;
+ StringBuilder sb = new StringBuilder(description.Length);
+ int start = -1;
+ for (int i = 0; i < description.Length; ++i)
+ {
+ switch (description[i])
+ {
+ case '{':
+ if (i == start)
+ {
+ sb.Append('{');
+ start = -1;
+ }
+ else if (start < 0)
+ start = i + 1;
+ break;
+ case '}':
+ if (start < 0)
+ {
+ if ((i + 1) == description.Length || description[i + 1] != '}')
+ throw new InvalidOperationException("Invalid option description: " + description);
+ ++i;
+ sb.Append("}");
+ }
+ else
+ {
+ sb.Append(description.Substring(start, i - start));
+ start = -1;
+ }
+ break;
+ case ':':
+ if (start < 0)
+ goto default;
+ start = i + 1;
+ break;
+ default:
+ if (start < 0)
+ sb.Append(description[i]);
+ break;
+ }
+ }
+ return sb.ToString();
+ }
+
+ static IEnumerable<string> GetLines(string description, int firstWidth, int remWidth)
+ {
+ return StringCoda.WrappedLines(description, firstWidth, remWidth);
+ }
+
+ internal sealed class Category : Option
+ {
+ // Prototype starts with '=' because this is an invalid prototype
+ // (see Option.ParsePrototype(), and thus it'll prevent Category
+ // instances from being accidentally used as normal options.
+ public Category(string description)
+ : base("=:Category:= " + description, description)
+ {
+ }
+
+ protected override void OnParseComplete(OptionContext c)
+ {
+ throw new NotSupportedException("Category.OnParseComplete should not be invoked.");
+ }
+ }
+
+ sealed class ActionOption : Option
+ {
+ readonly Action<OptionValueCollection> _action;
+
+ public ActionOption(string prototype, string description, int count, Action<OptionValueCollection> action)
+ : this(prototype, description, count, action, false)
+ {
+ }
+
+ public ActionOption(string prototype, string description, int count, Action<OptionValueCollection> action,
+ bool hidden)
+ : base(prototype, description, count, hidden)
+ {
+ if (action == null)
+ throw new ArgumentNullException("action");
+ _action = action;
+ }
+
+ protected override void OnParseComplete(OptionContext c)
+ {
+ _action(c.OptionValues);
+ }
+ }
+
+ sealed class ActionOption<T> : Option
+ {
+ readonly Action<T> _action;
+
+ public ActionOption(string prototype, string description, Action<T> action)
+ : base(prototype, description, 1)
+ {
+ if (action == null)
+ throw new ArgumentNullException("action");
+ _action = action;
+ }
+
+ protected override void OnParseComplete(OptionContext c)
+ {
+ _action(Parse<T>(c.OptionValues[0], c));
+ }
+ }
+
+ sealed class ActionOption<TKey, TValue> : Option
+ {
+ readonly OptionAction<TKey, TValue> _action;
+
+ public ActionOption(string prototype, string description, OptionAction<TKey, TValue> action)
+ : base(prototype, description, 2)
+ {
+ if (action == null)
+ throw new ArgumentNullException("action");
+ _action = action;
+ }
+
+ protected override void OnParseComplete(OptionContext c)
+ {
+ _action(
+ Parse<TKey>(c.OptionValues[0], c),
+ Parse<TValue>(c.OptionValues[1], c));
+ }
+ }
+
+ class ArgumentEnumerator : IEnumerable<string>
+ {
+ readonly List<IEnumerator<string>> _sources = new List<IEnumerator<string>>();
+
+ public ArgumentEnumerator(IEnumerable<string> arguments)
+ {
+ _sources.Add(arguments.GetEnumerator());
+ }
+
+ public IEnumerator<string> GetEnumerator()
+ {
+ do
+ {
+ IEnumerator<string> c = _sources[_sources.Count - 1];
+ if (c.MoveNext())
+ yield return c.Current;
+ else
+ {
+ c.Dispose();
+ _sources.RemoveAt(_sources.Count - 1);
+ }
+ } while (_sources.Count > 0);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public void Add(IEnumerable<string> arguments)
+ {
+ _sources.Add(arguments.GetEnumerator());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionValueCollection.cs b/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionValueCollection.cs
new file mode 100644
index 00000000..6ed60483
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionValueCollection.cs
@@ -0,0 +1,182 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Mono.Options
+{
+ public class OptionValueCollection : IList, IList<string>
+ {
+ readonly OptionContext _c;
+ readonly List<string> _values = new List<string>();
+
+ internal OptionValueCollection(OptionContext c)
+ {
+ _c = c;
+ }
+
+ #region IEnumerable
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return _values.GetEnumerator();
+ }
+
+ #endregion
+
+ #region IEnumerable<T>
+
+ public IEnumerator<string> GetEnumerator()
+ {
+ return _values.GetEnumerator();
+ }
+
+ #endregion
+
+ public List<string> ToList()
+ {
+ return new List<string>(_values);
+ }
+
+ public string[] ToArray()
+ {
+ return _values.ToArray();
+ }
+
+ public override string ToString()
+ {
+ return string.Join(", ", _values.ToArray());
+ }
+
+ #region ICollection
+
+ void ICollection.CopyTo(Array array, int index)
+ {
+ (_values as ICollection).CopyTo(array, index);
+ }
+
+ bool ICollection.IsSynchronized => (_values as ICollection).IsSynchronized;
+
+ object ICollection.SyncRoot => (_values as ICollection).SyncRoot;
+
+ #endregion
+
+ #region ICollection<T>
+
+ public void Add(string item)
+ {
+ _values.Add(item);
+ }
+
+ public void Clear()
+ {
+ _values.Clear();
+ }
+
+ public bool Contains(string item)
+ {
+ return _values.Contains(item);
+ }
+
+ public void CopyTo(string[] array, int arrayIndex)
+ {
+ _values.CopyTo(array, arrayIndex);
+ }
+
+ public bool Remove(string item)
+ {
+ return _values.Remove(item);
+ }
+
+ public int Count => _values.Count;
+
+ public bool IsReadOnly => false;
+
+ #endregion
+
+ #region IList
+
+ int IList.Add(object value)
+ {
+ return (_values as IList).Add(value);
+ }
+
+ bool IList.Contains(object value)
+ {
+ return (_values as IList).Contains(value);
+ }
+
+ int IList.IndexOf(object value)
+ {
+ return (_values as IList).IndexOf(value);
+ }
+
+ void IList.Insert(int index, object value)
+ {
+ (_values as IList).Insert(index, value);
+ }
+
+ void IList.Remove(object value)
+ {
+ (_values as IList).Remove(value);
+ }
+
+ void IList.RemoveAt(int index)
+ {
+ (_values as IList).RemoveAt(index);
+ }
+
+ bool IList.IsFixedSize => false;
+
+ object IList.this[int index]
+ {
+ get { return this[index]; }
+ set { (_values as IList)[index] = value; }
+ }
+
+ #endregion
+
+ #region IList<T>
+
+ public int IndexOf(string item)
+ {
+ return _values.IndexOf(item);
+ }
+
+ public void Insert(int index, string item)
+ {
+ _values.Insert(index, item);
+ }
+
+ public void RemoveAt(int index)
+ {
+ _values.RemoveAt(index);
+ }
+
+ void AssertValid(int index)
+ {
+ if (_c.Option == null)
+ throw new InvalidOperationException("OptionContext.Option is null.");
+ if (index >= _c.Option.MaxValueCount)
+ throw new ArgumentOutOfRangeException("index");
+ if (_c.Option.OptionValueType == OptionValueType.Required &&
+ index >= _values.Count)
+ {
+ throw new OptionException(string.Format(
+ _c.OptionSet.MessageLocalizer("Missing required value for option '{0}'."), _c.OptionName),
+ _c.OptionName);
+ }
+ }
+
+ public string this[int index]
+ {
+ get
+ {
+ AssertValid(index);
+ return index >= _values.Count ? null : _values[index];
+ }
+ set { _values[index] = value; }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionValueType.cs b/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionValueType.cs
new file mode 100644
index 00000000..97ac0e9b
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/Mono.Options/OptionValueType.cs
@@ -0,0 +1,9 @@
+namespace Mono.Options
+{
+ public enum OptionValueType
+ {
+ None,
+ Optional,
+ Required
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/Mono.Options/ResponseFileSource.cs b/Xamarin.Forms.UITest.TestCloud/Mono.Options/ResponseFileSource.cs
new file mode 100644
index 00000000..881a384e
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/Mono.Options/ResponseFileSource.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+
+namespace Mono.Options
+{
+ public class ResponseFileSource : ArgumentSource
+ {
+ public override string Description => "Read response file for more options.";
+
+ public override string[] GetNames()
+ {
+ return new[] { "@file" };
+ }
+
+ public override bool GetArguments(string value, out IEnumerable<string> replacement)
+ {
+ if (string.IsNullOrEmpty(value) || !value.StartsWith("@"))
+ {
+ replacement = null;
+ return false;
+ }
+ replacement = GetArgumentsFromFile(value.Substring(1));
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/Mono.Options/StringCoda.cs b/Xamarin.Forms.UITest.TestCloud/Mono.Options/StringCoda.cs
new file mode 100644
index 00000000..76eaf575
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/Mono.Options/StringCoda.cs
@@ -0,0 +1,237 @@
+//
+// Options.cs
+//
+// Authors:
+// Jonathan Pryor <jpryor@novell.com>
+// Federico Di Gregorio <fog@initd.org>
+// Rolf Bjarne Kvinge <rolf@xamarin.com>
+//
+// Copyright (C) 2008 Novell (http://www.novell.com)
+// Copyright (C) 2009 Federico Di Gregorio.
+// Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+// Compile With:
+// gmcs -debug+ -r:System.Core Options.cs -o:NDesk.Options.dll
+// gmcs -debug+ -d:LINQ -r:System.Core Options.cs -o:NDesk.Options.dll
+//
+// The LINQ version just changes the implementation of
+// OptionSet.Parse(IEnumerable<string>), and confers no semantic changes.
+
+//
+// A Getopt::Long-inspired option parsing library for C#.
+//
+// NDesk.Options.OptionSet is built upon a key/value table, where the
+// key is a option format string and the value is a delegate that is
+// invoked when the format string is matched.
+//
+// Option format strings:
+// Regex-like BNF Grammar:
+// name: .+
+// type: [=:]
+// sep: ( [^{}]+ | '{' .+ '}' )?
+// aliases: ( name type sep ) ( '|' name type sep )*
+//
+// Each '|'-delimited name is an alias for the associated action. If the
+// format string ends in a '=', it has a required value. If the format
+// string ends in a ':', it has an optional value. If neither '=' or ':'
+// is present, no value is supported. `=' or `:' need only be defined on one
+// alias, but if they are provided on more than one they must be consistent.
+//
+// Each alias portion may also end with a "key/value separator", which is used
+// to split option values if the option accepts > 1 value. If not specified,
+// it defaults to '=' and ':'. If specified, it can be any character except
+// '{' and '}' OR the *string* between '{' and '}'. If no separator should be
+// used (i.e. the separate values should be distinct arguments), then "{}"
+// should be used as the separator.
+//
+// Options are extracted either from the current option by looking for
+// the option name followed by an '=' or ':', or is taken from the
+// following option IFF:
+// - The current option does not contain a '=' or a ':'
+// - The current option requires a value (i.e. not a Option type of ':')
+//
+// The `name' used in the option format string does NOT include any leading
+// option indicator, such as '-', '--', or '/'. All three of these are
+// permitted/required on any named option.
+//
+// Option bundling is permitted so long as:
+// - '-' is used to start the option group
+// - all of the bundled options are a single character
+// - at most one of the bundled options accepts a value, and the value
+// provided starts from the next character to the end of the string.
+//
+// This allows specifying '-a -b -c' as '-abc', and specifying '-D name=value'
+// as '-Dname=value'.
+//
+// Option processing is disabled by specifying "--". All options after "--"
+// are returned by OptionSet.Parse() unchanged and unprocessed.
+//
+// Unprocessed options are returned from OptionSet.Parse().
+//
+// Examples:
+// int verbose = 0;
+// OptionSet p = new OptionSet ()
+// .Add ("v", v => ++verbose)
+// .Add ("name=|value=", v => Console.WriteLine (v));
+// p.Parse (new string[]{"-v", "--v", "/v", "-name=A", "/name", "B", "extra"});
+//
+// The above would parse the argument string array, and would invoke the
+// lambda expression three times, setting `verbose' to 3 when complete.
+// It would also print out "A" and "B" to standard output.
+// The returned array would contain the string "extra".
+//
+// C# 3.0 collection initializers are supported and encouraged:
+// var p = new OptionSet () {
+// { "h|?|help", v => ShowHelp () },
+// };
+//
+// System.ComponentModel.TypeConverter is also supported, allowing the use of
+// custom data types in the callback type; TypeConverter.ConvertFromString()
+// is used to convert the value option to an instance of the specified
+// type:
+//
+// var p = new OptionSet () {
+// { "foo=", (Foo f) => Console.WriteLine (f.ToString ()) },
+// };
+//
+// Random other tidbits:
+// - Boolean options (those w/o '=' or ':' in the option format string)
+// are explicitly enabled if they are followed with '+', and explicitly
+// disabled if they are followed with '-':
+// string a = null;
+// var p = new OptionSet () {
+// { "a", s => a = s },
+// };
+// p.Parse (new string[]{"-a"}); // sets v != null
+// p.Parse (new string[]{"-a+"}); // sets v != null
+// p.Parse (new string[]{"-a-"}); // sets v == null
+//
+
+using System;
+using System.Collections.Generic;
+
+#if LINQ
+using System.Linq;
+#endif
+
+#if TEST
+using NDesk.Options;
+#endif
+
+#if NDESK_OPTIONS
+namespace NDesk.Options
+#else
+
+namespace Mono.Options
+#endif
+{
+ internal static class StringCoda
+ {
+ public static IEnumerable<string> WrappedLines(string self, params int[] widths)
+ {
+ IEnumerable<int> w = widths;
+ return WrappedLines(self, w);
+ }
+
+ public static IEnumerable<string> WrappedLines(string self, IEnumerable<int> widths)
+ {
+ if (widths == null)
+ throw new ArgumentNullException("widths");
+ return CreateWrappedLinesIterator(self, widths);
+ }
+
+ static IEnumerable<string> CreateWrappedLinesIterator(string self, IEnumerable<int> widths)
+ {
+ if (string.IsNullOrEmpty(self))
+ {
+ yield return string.Empty;
+ yield break;
+ }
+ using(IEnumerator<int> ewidths = widths.GetEnumerator())
+ {
+ bool? hw = null;
+ int width = GetNextWidth(ewidths, int.MaxValue, ref hw);
+ int start = 0, end;
+ do
+ {
+ end = GetLineEnd(start, width, self);
+ char c = self[end - 1];
+ if (char.IsWhiteSpace(c))
+ --end;
+ bool needContinuation = end != self.Length && !IsEolChar(c);
+ string continuation = "";
+ if (needContinuation)
+ {
+ --end;
+ continuation = "-";
+ }
+ string line = self.Substring(start, end - start) + continuation;
+ yield return line;
+ start = end;
+ if (char.IsWhiteSpace(c))
+ ++start;
+ width = GetNextWidth(ewidths, width, ref hw);
+ } while (start < self.Length);
+ }
+ }
+
+ static int GetNextWidth(IEnumerator<int> ewidths, int curWidth, ref bool? eValid)
+ {
+ if (!eValid.HasValue || (eValid.HasValue && eValid.Value))
+ {
+ curWidth = (eValid = ewidths.MoveNext()).Value ? ewidths.Current : curWidth;
+ // '.' is any character, - is for a continuation
+ const string minWidth = ".-";
+ if (curWidth < minWidth.Length)
+ {
+ throw new ArgumentOutOfRangeException("widths",
+ string.Format("Element must be >= {0}, was {1}.", minWidth.Length, curWidth));
+ }
+ return curWidth;
+ }
+ // no more elements, use the last element.
+ return curWidth;
+ }
+
+ static bool IsEolChar(char c)
+ {
+ return !char.IsLetterOrDigit(c);
+ }
+
+ static int GetLineEnd(int start, int length, string description)
+ {
+ int end = System.Math.Min(start + length, description.Length);
+ int sep = -1;
+ for (int i = start; i < end; ++i)
+ {
+ if (description[i] == '\n')
+ return i + 1;
+ if (IsEolChar(description[i]))
+ sep = i + 1;
+ }
+ if (sep == -1 || end == description.Length)
+ return end;
+ return sep;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/Properties/AssemblyInfo.cs b/Xamarin.Forms.UITest.TestCloud/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..a88308b9
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/Properties/AssemblyInfo.cs
@@ -0,0 +1,39 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Xamarin.Forms.UITest.TestCloud")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Forms.UITest.TestCloud")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("461f48a4-9e1c-4146-aa4e-ddd85746afc7")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/TestCloudUtils.cs b/Xamarin.Forms.UITest.TestCloud/TestCloudUtils.cs
new file mode 100644
index 00000000..a554096f
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/TestCloudUtils.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Diagnostics;
+
+namespace Xamarin.Forms.UITest.TestCloud
+{
+ internal static class TestCloudUtils
+ {
+ public static bool IsRunningOnMono()
+ {
+ return Type.GetType("Mono.Runtime") != null;
+ }
+
+ public static Tuple<DeviceSet.Platform, string> ParseArgs(string input)
+ {
+ string[] deviceArgs = input.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
+ if (deviceArgs.Length != 2)
+ {
+ Console.WriteLine("!!! Invalid upload paramters, should be <Platform> <Category> : You entered : " + input);
+ return null;
+ }
+
+ DeviceSet.Platform platform = deviceArgs[0] == "Android" ? DeviceSet.Platform.Android : DeviceSet.Platform.IOs;
+ string category = deviceArgs[1];
+
+ return Tuple.Create(platform, category);
+ }
+
+ public static int UploadApp(string command)
+ {
+ Tuple<string, string> execArgsPair = IsRunningOnMono() ? MonoExecArgs(command) : WindowsExecArgs(command);
+
+ var process = new Process
+ {
+ StartInfo = new ProcessStartInfo
+ {
+ FileName = execArgsPair.Item1,
+ Arguments = execArgsPair.Item2,
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ CreateNoWindow = true
+ }
+ };
+
+ try
+ {
+ process.Start();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.Message);
+ return 1;
+ }
+
+ while (!process.StandardOutput.EndOfStream)
+ {
+ string line = process.StandardOutput.ReadLine();
+ Console.WriteLine(line);
+ }
+ while (!process.StandardError.EndOfStream)
+ {
+ string line = process.StandardError.ReadLine();
+ Console.WriteLine(line);
+ }
+ process.WaitForExit();
+ return process.ExitCode;
+ }
+
+ static Tuple<string, string> MonoExecArgs(string command)
+ {
+ return Tuple.Create("mono", command);
+ }
+
+ static Tuple<string, string> WindowsExecArgs(string command)
+ {
+ string[] commandArray = command.Split(' ');
+ string executable = commandArray[0];
+ string uploadCommand = string.Join(" ", commandArray, 1, commandArray.Length - 1);
+ return Tuple.Create(executable, uploadCommand);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/Uploader.cs b/Xamarin.Forms.UITest.TestCloud/Uploader.cs
new file mode 100644
index 00000000..b0cf299c
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/Uploader.cs
@@ -0,0 +1,409 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Security.Policy;
+using System.Text;
+using Mono.Options;
+using Xamarin.Forms.Core.UITests;
+using Xamarin.Forms.Loader;
+
+namespace Xamarin.Forms.UITest.TestCloud
+{
+ // TODO: Provide way to construct url for results easy access
+
+ static class Uploader
+ {
+ static LoaderActions loaderActions;
+
+ static int Main(string[] args)
+ {
+ loaderActions = new LoaderActions();
+
+ var categories = new List<string>();
+ string series = null;
+ var platform = DeviceSet.Platform.None;
+ DeviceSet deviceSet = null;
+ var validate = false;
+ string outputFile = null;
+ var account = "";
+ var user = "";
+
+ OptionSet optionSet = null;
+ optionSet = new OptionSet
+ {
+ {
+ "p|platform=", "specify the test platform, iOS or Android",
+ s => platform = (DeviceSet.Platform)Enum.Parse(typeof (DeviceSet.Platform), s)
+ },
+ { "d|deviceset=", "the device set to use for the test run", s => deviceSet = StringToDeviceSet(s) },
+ { "c|category=", "add a category to the test run", s => categories.Add(s) },
+ { "s|series=", "specify the series when uploaded to Test Cloud", s => series = s },
+ { "l|list", "list categories available in test suite", ListCategories },
+ { "sets", "list available device sets", ListDeviceSets },
+ { "i|interactive", "start uploader in interactive mode", InteractiveMode },
+ { "h|help", "show this message and exit", s => ShowHelp(optionSet) },
+ { "v|validate", "validate all tests or a specified category", s => validate = true },
+ { "o|output=", "output destination for NUnit XML", s => outputFile = s },
+ { "a|account=", "Test Cloud key", s => account = s },
+ { "u|user=", "Test Cloud user", s => user = s }
+ };
+
+ List<string> extra;
+ try
+ {
+ extra = optionSet.Parse(args);
+ }
+ catch (OptionException ex)
+ {
+ Console.Write("Uploader:");
+ Console.WriteLine(ex.Message);
+ Console.WriteLine("Try --help for more informaiton");
+ }
+
+ if (args.Length == 0)
+ ShowHelp(optionSet);
+
+ if (validate)
+ {
+ var category = categories.FirstOrDefault();
+ return loaderActions.ValidateCategory(category) ? 0 : 1;
+ }
+
+ if (platform == DeviceSet.Platform.None)
+ {
+ Console.WriteLine("Platform must be specified");
+ return 1;
+ }
+
+ if (deviceSet != null && !deviceSet.DeviceSetPlatform.Contains(platform))
+ {
+ Console.WriteLine("DeviceSet platform does not match specified platform");
+ return 1;
+ }
+
+ if (deviceSet == null)
+ {
+ if (platform == DeviceSet.Platform.Android)
+ deviceSet = DeviceSets.AndroidFastParallel;
+ else
+ deviceSet = DeviceSets.IOsFastParallel;
+ }
+
+ var execString = BuildExecutionString(platform, deviceSet, categories, series, account, user, outputFile);
+
+ Console.WriteLine(execString);
+
+ var processStatus = TestCloudUtils.UploadApp(execString);
+
+ Console.WriteLine("test-cloud.exe status: " + processStatus);
+ return processStatus;
+ }
+
+ static string BuildExecutionString(DeviceSet.Platform platform, DeviceSet deviceSet, IEnumerable<string> categories,
+ string series, string account, string user, string outputFile = null)
+ {
+ var stringBuilder = new StringBuilder();
+ stringBuilder.Append(ConsolePath);
+ stringBuilder.Append(" submit ");
+
+ switch (platform)
+ {
+ case DeviceSet.Platform.Android:
+ stringBuilder.Append(ApkPath);
+ break;
+ case DeviceSet.Platform.IOs:
+ stringBuilder.Append(IpaPath);
+ break;
+ case DeviceSet.Platform.IOsClassic:
+ stringBuilder.Append(IpaClassicPath);
+ break;
+ }
+
+ stringBuilder.Append(" ");
+ stringBuilder.Append(account);
+ stringBuilder.Append(" --user ");
+ stringBuilder.Append(user);
+ stringBuilder.Append(" --devices ");
+ stringBuilder.Append(deviceSet.Id);
+
+ foreach (var category in categories)
+ {
+ stringBuilder.Append(" --include ");
+ stringBuilder.Append(category);
+ }
+
+ if (!string.IsNullOrEmpty(series))
+ {
+ stringBuilder.Append(" --series ");
+ stringBuilder.Append(series);
+ }
+
+ stringBuilder.Append(" --locale \"en_US\"");
+
+ switch (platform)
+ {
+ case DeviceSet.Platform.Android:
+ stringBuilder.Append(" --app-name \"AndroidControlGallery\"");
+ break;
+ case DeviceSet.Platform.IOs:
+ case DeviceSet.Platform.IOsClassic:
+ stringBuilder.Append(" --app-name \"XamControl\"");
+ break;
+ }
+
+ stringBuilder.Append(" --assembly-dir ");
+
+ if (platform == DeviceSet.Platform.Android)
+ stringBuilder.Append(AndroidTestingDirectory);
+ else
+ stringBuilder.Append(iOSTestingDirectory);
+
+ stringBuilder.Append(" --fixture-chunk");
+
+ if (!string.IsNullOrEmpty(outputFile))
+ stringBuilder.Append($" --nunit-xml {outputFile}");
+
+ return stringBuilder.ToString();
+ }
+
+ static void InteractiveMode(string s)
+ {
+ Console.WriteLine("Interactive testcloud uploader. Type --help for help");
+ Console.WriteLine(
+ "Usage: >>> -d <deviceset> -c <category> -a <key> -u <user> [-c <category> -c <category> -c <category>]");
+
+ while (true)
+ {
+ Console.Write(">>> ");
+ var command = Console.ReadLine();
+ var commandList = command.Split(' ');
+
+ var platform = DeviceSet.Platform.None;
+ var deviceSet = "";
+ var categories = new List<string>();
+ var series = "";
+ var account = "";
+ var user = "";
+
+ OptionSet options = null;
+ options = new OptionSet
+ {
+ { "q|quit", "quit", Exit },
+ { "h|help", "show this message and exit", str => ShowInteractiveHelp(options) },
+ { "c|category=", "specify the category to run in Test cloud", str => categories.Add(str) },
+ { "d|deviceset=", "specify the device set to upload", str => deviceSet = str },
+ { "lc|listcategories", "Lists categories in uitests", ListCategories },
+ { "ld|listdevicesets", "Lists defined devices sets", ListDeviceSets },
+ { "a|account=", "Test Cloud key", str => account = str },
+ { "u|user=", "Test Cloud user", str => user = str }
+ };
+
+ List<string> extra;
+ try
+ {
+ extra = options.Parse(commandList);
+ }
+ catch (OptionException ex)
+ {
+ Console.Write("Uploader:");
+ Console.WriteLine(ex.Message);
+ Console.WriteLine("Try --help for more informaiton");
+ }
+
+ if (command.Length == 0)
+ ShowHelp(options);
+
+ // by default take the first category as the series name
+ if (categories.Count >= 1)
+ series = categories.First();
+
+ if (commandList.Length >= 4)
+ {
+ var validQuery = true;
+
+ if (!IsValidDeviceSet(deviceSet))
+ {
+ Console.WriteLine("Invalid DeviceSet: {0}", deviceSet);
+ validQuery = false;
+ }
+
+ if (!CategoriesValid(categories))
+ {
+ Console.Write("Invalid Category(s):");
+ foreach (var c in categories)
+ Console.Write(" {0} ", c);
+ Console.Write("\n");
+ validQuery = false;
+ }
+
+ if (validQuery)
+ {
+ var devSet = StringToDeviceSet(deviceSet);
+ var execString = BuildExecutionString(devSet.DeviceSetPlatform.First(), devSet, categories, series, account, user);
+ Console.WriteLine(execString);
+ TestCloudUtils.UploadApp(execString);
+ }
+ }
+ }
+ }
+
+ static void ShowInteractiveHelp(OptionSet options)
+ {
+ Console.WriteLine("Usage: [OPTIONS]");
+ Console.WriteLine();
+ Console.WriteLine("Options:");
+ options.WriteOptionDescriptions(Console.Out);
+ }
+
+ static void Exit(string s)
+ {
+ Environment.Exit(0);
+ }
+
+ static void ShowHelp(OptionSet options)
+ {
+ Console.WriteLine("Usage: Uploader [OPTIONS]");
+ Console.WriteLine();
+ Console.WriteLine("Options:");
+ options.WriteOptionDescriptions(Console.Out);
+
+ Environment.Exit(0);
+ }
+
+ static DeviceSet StringToDeviceSet(string s)
+ {
+ try
+ {
+ var device = (DeviceSet)typeof (DeviceSets).GetField(s).GetValue(null);
+ return device;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("DeviceSet not found");
+ return null;
+ }
+ }
+
+ static void ListDeviceSets(string s)
+ {
+ var deviceSetsType = typeof (DeviceSets);
+
+ var fields = deviceSetsType.GetFields();
+
+ foreach (var field in fields)
+ Console.WriteLine(field.Name);
+ }
+
+ static void ListCategories(string s)
+ {
+ loaderActions.ListCategories();
+ }
+
+ static bool CategoriesValid(List<string> categories)
+ {
+ var areValid = true;
+
+ if (categories.Count < 1)
+ return false;
+
+ foreach (var category in categories)
+ {
+ if (!loaderActions.ValidateCategory(category))
+ return false;
+ }
+
+ return areValid;
+ }
+
+ static bool IsValidDeviceSet(string deviceSet)
+ {
+ var deviceSetsType = typeof (DeviceSets);
+ var isValid = deviceSetsType.GetFields().Any(ds => ds.Name == deviceSet);
+ return isValid;
+ }
+
+ public static string ConsolePath
+ {
+ get
+ {
+ string[] consolePathElements = { "..", "..", "..", "packages", "Xamarin.UITest.1.3.3", "tools", "test-cloud.exe" };
+ return Path.Combine(consolePathElements);
+ }
+ }
+
+ public static string IpaPath
+ {
+ get
+ {
+ string[] ipaPathElements =
+ {
+ "..",
+ "..",
+ "..",
+ "Xamarin.Forms.ControlGallery.iOS",
+ "bin",
+ "iPhone",
+ "Debug",
+ "XamarinFormsControlGalleryiOS-1.0.ipa"
+ };
+ return Path.Combine(ipaPathElements);
+ }
+ }
+
+ public static string IpaClassicPath
+ {
+ get
+ {
+ string[] ipaPathElements =
+ {
+ "..",
+ "..",
+ "..",
+ "Xamarin.Forms.ControlGallery.iOS",
+ "classic_bin",
+ "iPhone",
+ "Debug",
+ "XamarinFormsControlGalleryiOS-1.0.ipa"
+ };
+ return Path.Combine(ipaPathElements);
+ }
+ }
+
+ public static string ApkPath
+ {
+ get
+ {
+ string[] apkPathElements =
+ {
+ "..",
+ "..",
+ "..",
+ "Xamarin.Forms.ControlGallery.Android",
+ "bin",
+ "Debug",
+ "AndroidControlGallery.AndroidControlGallery-Signed.apk"
+ };
+ return Path.Combine(apkPathElements);
+ }
+ }
+
+ public static string iOSTestingDirectory
+ {
+ get
+ {
+ string[] testDiriOSPathElements = { "..", "..", "..", "Xamarin.Forms.Core.iOS.UITests", "bin", "Debug" };
+ return Path.Combine(testDiriOSPathElements);
+ }
+ }
+
+ public static string AndroidTestingDirectory
+ {
+ get
+ {
+ string[] testDirAndroidPathElements = { "..", "..", "..", "Xamarin.Forms.Core.Android.UITests", "bin", "Debug" };
+ return Path.Combine(testDirAndroidPathElements);
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.UITest.TestCloud/Xamarin.Forms.UITest.TestCloud.csproj b/Xamarin.Forms.UITest.TestCloud/Xamarin.Forms.UITest.TestCloud.csproj
new file mode 100644
index 00000000..86f62324
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/Xamarin.Forms.UITest.TestCloud.csproj
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{1E238A01-B492-461F-BADE-415E8F9C5DFC}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.UITest.TestCloud</RootNamespace>
+ <AssemblyName>Xamarin.Forms.UITest.TestCloud</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ <Reference Include="nunit.framework">
+ <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="DeviceSet.cs" />
+ <Compile Include="DeviceSets.cs" />
+ <Compile Include="LoaderActions.cs" />
+ <Compile Include="Uploader.cs" />
+ <Compile Include="Mono.Options\ArgumentSource.cs" />
+ <Compile Include="Mono.Options\Option.cs" />
+ <Compile Include="Mono.Options\OptionAction.cs" />
+ <Compile Include="Mono.Options\OptionContext.cs" />
+ <Compile Include="Mono.Options\OptionException.cs" />
+ <Compile Include="Mono.Options\StringCoda.cs" />
+ <Compile Include="Mono.Options\OptionSet.cs" />
+ <Compile Include="Mono.Options\OptionValueCollection.cs" />
+ <Compile Include="Mono.Options\OptionValueType.cs" />
+ <Compile Include="Mono.Options\ResponseFileSource.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="TestCloudUtils.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core.Android.UITests\Xamarin.Forms.Core.Android.UITests.csproj">
+ <Project>{a34ebe01-25bf-4e69-a2dc-2288dc625541}</Project>
+ <Name>Xamarin.Forms.Core.Android.UITests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Core.iOS.UITests\Xamarin.Forms.Core.iOS.UITests.csproj">
+ <Project>{eadd8100-b3ae-4a31-92c4-267a64a1c6eb}</Project>
+ <Name>Xamarin.Forms.Core.iOS.UITests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.CustomAttributes\Xamarin.Forms.CustomAttributes.csproj">
+ <Project>{4dcd0420-1168-4b77-86db-6196ee4bd491}</Project>
+ <Name>Xamarin.Forms.CustomAttributes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Loader\Xamarin.Forms.Loader.csproj">
+ <Project>{00211725-2f89-4e2c-ac5a-38e5ff61be67}</Project>
+ <Name>Xamarin.Forms.Loader</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform\Xamarin.Forms.Platform.csproj">
+ <Project>{67f9d3a8-f71e-4428-913f-c37ae82cdb24}</Project>
+ <Name>Xamarin.Forms.Platform</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Logs\" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include=".NETFramework,Version=v4.5">
+ <Visible>False</Visible>
+ <ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+ </Target>
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.TestCloud/packages.config b/Xamarin.Forms.UITest.TestCloud/packages.config
new file mode 100644
index 00000000..d18b935f
--- /dev/null
+++ b/Xamarin.Forms.UITest.TestCloud/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Mono.Options" version="1.1" targetFramework="net45" />
+ <package id="NUnit" version="2.6.4" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.Validator/App.config b/Xamarin.Forms.UITest.Validator/App.config
new file mode 100644
index 00000000..8e156463
--- /dev/null
+++ b/Xamarin.Forms.UITest.Validator/App.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <startup>
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
+ </startup>
+</configuration> \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.Validator/DomMemberModel.cs b/Xamarin.Forms.UITest.Validator/DomMemberModel.cs
new file mode 100644
index 00000000..7f005405
--- /dev/null
+++ b/Xamarin.Forms.UITest.Validator/DomMemberModel.cs
@@ -0,0 +1,56 @@
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.UITest.Validator
+{
+ internal class DomMemberModel
+ {
+ readonly List<string> _androidtests;
+ readonly List<string> _iOStests;
+ readonly string _name;
+
+ public DomMemberModel(string memberName, List<string> iOsTestsForMember, List<string> androidTestsForMember)
+ {
+ _name = memberName;
+ _iOStests = iOsTestsForMember;
+ var isiOsTested = iOsTestsForMember.Count != 0;
+ NumberOfiOsTests = iOsTestsForMember.Count;
+
+ _androidtests = androidTestsForMember;
+ var isAndroidTested = androidTestsForMember.Count != 0;
+ NumberOfAndroidTests = androidTestsForMember.Count;
+
+ IsTested = isiOsTested && isAndroidTested;
+ }
+
+ public bool IsTested { get; }
+
+ public int NumberOfiOsTests { get; }
+
+ public int NumberOfAndroidTests { get; }
+
+ public string Html()
+ {
+ var html = "";
+
+ if (IsTested)
+ html += "<div class=\"testedMember\">" + _name + "</div>";
+ else
+ html += "<div class=\"unTestedMember\">" + _name + "</div>";
+
+ html += "<div class=\"platformTestContainer\">";
+ html += "<div class=\"iosColumn\">";
+ foreach (var test in _iOStests)
+ html += "<div class=\"test ios\">" + test + "</div>";
+ html += "</div>";
+
+ html += "<div class=\"androidColumn\">";
+ foreach (var test in _androidtests)
+ html += "<div class=\"test android\">" + test + "</div>";
+ html += "</div>";
+
+ html += "</div>";
+
+ return html;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.Validator/DomTypeModel.cs b/Xamarin.Forms.UITest.Validator/DomTypeModel.cs
new file mode 100644
index 00000000..16d70bd9
--- /dev/null
+++ b/Xamarin.Forms.UITest.Validator/DomTypeModel.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Xamarin.Forms.Loader;
+
+namespace Xamarin.Forms.UITest.Validator
+{
+ internal class DomTypeModel
+ {
+ readonly List<string> _androidTypeTests;
+ readonly List<string> _iosTypeTests;
+ public string TypeName;
+
+ public DomTypeModel(FormsType formsType, Dictionary<Type, List<FormsUiTest>> typeiOsuiTestDictionary,
+ Dictionary<Type, List<FormsUiTest>> typeAndroidUiTestDictionary)
+ {
+ TypeName = formsType.Type.Name;
+
+ var iOsTests = new List<FormsUiTest>();
+ var androidTests = new List<FormsUiTest>();
+
+ _iosTypeTests = new List<string>();
+ _androidTypeTests = new List<string>();
+
+ Rank = 0;
+
+ if (typeiOsuiTestDictionary.ContainsKey(formsType.Type))
+ {
+ iOsTests =
+ (from test in typeiOsuiTestDictionary[formsType.Type]
+ select test).ToList();
+ }
+
+ if (typeAndroidUiTestDictionary.ContainsKey(formsType.Type))
+ {
+ androidTests =
+ (from test in typeAndroidUiTestDictionary[formsType.Type]
+ select test).ToList();
+ }
+
+ _iosTypeTests =
+ (from test in iOsTests
+ where test.MemberName == ""
+ select test.TestName).ToList();
+
+ _androidTypeTests =
+ (from test in androidTests
+ where test.MemberName == ""
+ select test.TestName).ToList();
+
+ Rank -= _iosTypeTests.Count;
+ Rank -= _androidTypeTests.Count;
+
+ Children = new List<DomMemberModel>();
+
+ foreach (var formsMember in formsType.Members())
+ {
+ var iOsMemberTests =
+ (from test in iOsTests
+ where test.MemberName == formsMember.MemberInfo.Name
+ select test.TestName).ToList();
+
+ Rank -= iOsMemberTests.Count;
+
+ var androidMemberTests =
+ (from test in androidTests
+ where test.MemberName == formsMember.MemberInfo.Name
+ select test.TestName).ToList();
+
+ Rank -= androidMemberTests.Count;
+
+ Children.Add(new DomMemberModel(formsMember.MemberInfo.Name, iOsMemberTests, androidMemberTests));
+ }
+
+ Rank += Children.Count;
+ }
+
+ public List<DomMemberModel> Children { get; }
+
+ public int Rank { get; }
+
+ public string Html()
+ {
+ var html =
+ "<div class=\"type\" id=\"" + TypeName + "\">" +
+ "<div class=\"stats\">" +
+ "<h2>" + TypeName + "</h2>" +
+ "<h3>Number of tests: " + TotalTests() + "</h3>" +
+ string.Format("<h3>{0:N2}%</h3>", PercentageTested() * 100) +
+ "<div class=\"progressBar\">" +
+ "<div class=\"testedBox\" style=\"width:" + 290 * PercentageTested() + "px\"></div>" +
+ "</div>" +
+ "</div>" +
+ "<div class=\"platform\">" +
+ "<div class=\"ios\">iOS</div>" +
+ "<div class=\"android\">Android</div>" +
+ "</div>";
+
+ html +=
+ "<div class=\"testsForType\">" +
+ "<div class=\"platformTestContainer\">";
+ html += "<div class=\"iosColumn\">";
+ foreach (var iosTest in _iosTypeTests)
+ html += "<div class=\"test ios\">" + iosTest + "</div>";
+ html += "</div>";
+ html += "<div class=\"androidColumn\">";
+ foreach (var androidTest in _androidTypeTests)
+ html += "<div class=\"test android\">" + androidTest + "</div>";
+ html += "</div>" +
+ "</div>" +
+ "</div>";
+
+ html += "<div class=\"members\">";
+ foreach (var child in Children)
+ {
+ html += "<div class=\"member\">";
+ html += child.Html();
+ html += "</div>";
+ }
+
+ html += "</div>";
+
+ html += "</div>";
+ return html;
+ }
+
+ int TotalTests()
+ {
+ int result = _iosTypeTests.Count + _androidTypeTests.Count;
+ foreach (var child in Children)
+ result += child.NumberOfiOsTests + child.NumberOfAndroidTests;
+ return result;
+ }
+
+ int NumberOfTestedMembers()
+ {
+ int result = 0;
+ foreach (var child in Children)
+ {
+ if (child.IsTested)
+ result += 1;
+ }
+ return result;
+ }
+
+ double PercentageTested()
+ {
+ if (Children.Count > 0)
+ return (NumberOfTestedMembers() / (double)Children.Count);
+
+ return 0.0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.Validator/FormsUITest.cs b/Xamarin.Forms.UITest.Validator/FormsUITest.cs
new file mode 100644
index 00000000..508b1777
--- /dev/null
+++ b/Xamarin.Forms.UITest.Validator/FormsUITest.cs
@@ -0,0 +1,15 @@
+namespace Xamarin.Forms.UITest.Validator
+{
+ internal class FormsUiTest
+ {
+ public FormsUiTest(string memberName, string testName)
+ {
+ MemberName = memberName;
+ TestName = testName;
+ }
+
+ public string MemberName { get; private set; }
+
+ public string TestName { get; private set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.Validator/LoaderActions.cs b/Xamarin.Forms.UITest.Validator/LoaderActions.cs
new file mode 100644
index 00000000..9de39f21
--- /dev/null
+++ b/Xamarin.Forms.UITest.Validator/LoaderActions.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Loader;
+
+namespace Xamarin.Forms.UITest.Validator
+{
+ internal class LoaderActions
+ {
+ readonly IEnumerable<TestType> _androidTestTypes;
+ readonly IEnumerable<TestType> _iOsTestTypes;
+
+ public LoaderActions()
+ {
+ var formsLoader = new FormsLoader();
+ FormsTypes = formsLoader.FormsTypes();
+ _iOsTestTypes = formsLoader.IOSTestTypes();
+ _androidTestTypes = formsLoader.AndroidTestTypes();
+
+ TypeiOsuiTestDictionary = BuildTypeUiTestDictionary(_iOsTestTypes);
+ TypeAndroidUiTestDictionary = BuildTypeUiTestDictionary(_androidTestTypes);
+
+ Debug.WriteLine("HI");
+ }
+
+ internal IEnumerable<FormsType> FormsTypes { get; }
+
+ internal Dictionary<Type, List<FormsUiTest>> TypeiOsuiTestDictionary { get; }
+
+ internal Dictionary<Type, List<FormsUiTest>> TypeAndroidUiTestDictionary { get; }
+
+ Dictionary<Type, List<FormsUiTest>> BuildTypeUiTestDictionary(IEnumerable<TestType> testTypes)
+ {
+ var result = new Dictionary<Type, List<FormsUiTest>>();
+
+ foreach (TestType testType in testTypes)
+ {
+ foreach (TestMember testMember in testType.Members())
+ {
+ IEnumerable<UiTestAttribute> testAttrs = testMember.UiTestAttributes();
+ foreach (UiTestAttribute testAttr in testAttrs)
+ {
+ Type type = testAttr.Type;
+ string memberName = testAttr.MemberName;
+ string testName = testMember.MemberInfo.Name;
+
+ if (!result.ContainsKey(type))
+ result.Add(type, new List<FormsUiTest> { new FormsUiTest(memberName, testName) });
+ else
+ result[type].Add(new FormsUiTest(memberName, testName));
+ }
+ }
+ }
+
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.Validator/Properties/AssemblyInfo.cs b/Xamarin.Forms.UITest.Validator/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..00442570
--- /dev/null
+++ b/Xamarin.Forms.UITest.Validator/Properties/AssemblyInfo.cs
@@ -0,0 +1,39 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Xamarin.Forms.UITest.Validator")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Forms.UITest.Validator")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("e1948442-ac28-49be-ac46-8ceeff28e183")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.Validator/UITestCoverage/Css/styles.css b/Xamarin.Forms.UITest.Validator/UITestCoverage/Css/styles.css
new file mode 100644
index 00000000..d04f971b
--- /dev/null
+++ b/Xamarin.Forms.UITest.Validator/UITestCoverage/Css/styles.css
@@ -0,0 +1,206 @@
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+}
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+ display: block;
+}
+body {
+ line-height: 1;
+ font-family: sans-serif;
+ font-size: 14px;
+}
+ol, ul {
+ list-style: none;
+}
+blockquote, q {
+ quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+ content: '';
+ content: none;
+}
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+html {
+ padding: 50px;
+}
+
+#totalStats {
+ width: 1000px;
+ padding: 20px;
+}
+
+#totalStats #coverage {
+ float: left;
+ font-size:225%;
+ padding: 10px;
+}
+
+.totalStatsLarge {
+ padding : 15px 10px;
+ text-align: start;
+ width: 200px;
+ float: right;
+ color: #808080;
+ font-size: 18px;
+}
+
+.totalStatsSmall {
+ padding : 5px 10px;
+ text-align: start;
+ width: 200px;
+ float: right;
+ color: #808080;
+ font-size: 18px;
+}
+
+#totalStats .coverageDetail {
+ float: left;
+ font-size:150%;
+ padding: 20px;
+}
+
+.cell {
+ width: 200px;
+ border: 1px solid green;
+ float: left;
+}
+
+.test {
+ color: blue;
+}
+
+.type {
+ clear: both;
+ width: 1000px;
+ overflow: hidden;
+ border: 1px solid #bbb;
+ margin: 5px;
+}
+
+.stats {
+ height: 37px;
+ border-bottom: 1px solid #ddd;
+}
+
+.stats h2 {
+ cursor: pointer;
+ font-size: 115%;
+ float: left;
+ width: 300px;
+ padding: 7px 0px 10px 10px;
+}
+
+.stats h3 {
+ float: left;
+ width: 200px;
+ padding: 11px 0px 10px 0px;
+}
+
+.platform {
+ width: 500px;
+ padding: 20px 0px 20px 10px;
+ margin: 0px 0px 0px 300px;
+
+}
+
+.platform .ios {
+ font-size: 18px;
+ width: 200px;
+ float: left;
+}
+
+.platform .android {
+ font-size: 18px;
+}
+
+.type .testsForType, .type .members, .type .platform {
+ display: none;
+}
+
+.type.expanded .testsForType, .type.expanded .members, .type.expanded .platform {
+ display: block;
+}
+
+.testsForType {
+ padding: 0px 0px 20px 20px;
+}
+
+.members {
+ padding: 0px 0px 20px 20px;
+}
+
+.member {
+ clear: both;
+ padding: 3px;
+}
+
+.testedMember {
+ font-size: 100%;
+ color: green;
+}
+
+.unTestedMember {
+ height: 28px;
+ font-size: 100%;
+ color: red;
+}
+
+.test {
+ color: blue;
+ text-decoration: underline;
+}
+
+.platformTestContainer {
+ width: 400px;
+ margin-left: 290px;
+}
+
+.iosColumn {
+ float: left;
+ width: 180px;
+ margin-right: 20px;
+ overflow: hidden;
+}
+
+.androidColumn {
+ float: left;
+ width: 180px;
+ margin-right: 20px;
+ overflow: hidden;
+}
+
+.progressBar {
+ float: right;
+ background-color: #ee8888;
+ width: 290px;
+ height: 37px;
+}
+
+.testedBox {
+ background-color: #88cc88;
+ height: 37px;
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.Validator/UITestCoverage/Js/script.js b/Xamarin.Forms.UITest.Validator/UITestCoverage/Js/script.js
new file mode 100644
index 00000000..d204495f
--- /dev/null
+++ b/Xamarin.Forms.UITest.Validator/UITestCoverage/Js/script.js
@@ -0,0 +1,6 @@
+$(function () {
+ $('body').on('click', '.stats', function (e) {
+ e.preventDefault();
+ $(this).parents('.type').toggleClass('expanded');
+ });
+}); \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.Validator/Validator.cs b/Xamarin.Forms.UITest.Validator/Validator.cs
new file mode 100644
index 00000000..d384940f
--- /dev/null
+++ b/Xamarin.Forms.UITest.Validator/Validator.cs
@@ -0,0 +1,68 @@
+using System;
+using System.IO;
+using System.Linq;
+
+namespace Xamarin.Forms.UITest.Validator
+{
+ //[UITest (typeof(Button), "Clicked")]
+ internal class Validator
+ {
+ // TODO - Add support for muliple attributes (i.e. Fonts or Image.Aspect)
+ // TODO - Add analysis of test duplication using duplicated tags
+ // TODO - Support Single class analysis by passing a class name into the program
+ // TODO - Stats of public surface area coverage
+
+ static int Main(string[] args)
+ {
+ Console.WriteLine("Generating UITest code coverage");
+
+ // Currently scanning for public events, public properties and public methods.
+
+ var loaderActions = new LoaderActions();
+
+ var domTypes =
+ (from formsType in loaderActions.FormsTypes
+ where formsType.Members().Count() > 1
+ select
+ new DomTypeModel(formsType, loaderActions.TypeiOsuiTestDictionary, loaderActions.TypeAndroidUiTestDictionary))
+ .OrderByDescending(domType => domType.Rank);
+
+ var typeMemberHtml = "";
+ int numberOfTestedMembers = 0;
+ int numberOfMembers = 0;
+
+ foreach (var domType in domTypes)
+ {
+ numberOfTestedMembers += (from member in domType.Children where member.IsTested select member).Count();
+ numberOfMembers += domType.Children.Count;
+ typeMemberHtml += domType.Html();
+ }
+
+ var html =
+ "<html>" +
+ "<head>" +
+ "<link rel=\"stylesheet\" type=\"text/css\" href=\"Css/styles.css\">" +
+ "<script type=\"text/javascript\" src=\"https://code.jquery.com/jquery-2.1.3.min.js\"></script>" +
+ "<script type=\"text/javascript\" src=\"Js/script.js\"></script>" +
+ "</head>" +
+ "<body>" +
+ "<div id=\"totalStats\">" +
+ string.Format("<div id=\"coverage\">{0:N2}%<span class=\"totalStatsLarge\"> Covered!!</span></div>",
+ (numberOfTestedMembers / (double)numberOfMembers) * 100) +
+ string.Format("<div class=\"coverageDetail\">{0}<span class=\"totalStatsSmall\"> Members</span></div>",
+ numberOfMembers) +
+ string.Format("<div class=\"coverageDetail\">{0}<span class=\"totalStatsSmall\"> Tested Members</span></div>",
+ numberOfTestedMembers) +
+ "</div>" +
+ "<div id=\"container\">" +
+ typeMemberHtml +
+ "</div>" +
+ "</body>" +
+ "</html>";
+
+ File.WriteAllText("../../UITestCoverage/index.html", html);
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.Validator/Xamarin.Forms.UITest.Validator.csproj b/Xamarin.Forms.UITest.Validator/Xamarin.Forms.UITest.Validator.csproj
new file mode 100644
index 00000000..e41a33bb
--- /dev/null
+++ b/Xamarin.Forms.UITest.Validator/Xamarin.Forms.UITest.Validator.csproj
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{115C31B9-C1B2-4B00-BB0E-EA36F105903E}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.UITest.Validator</RootNamespace>
+ <AssemblyName>Xamarin.Forms.UITest.Validator</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Web" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ <Reference Include="nunit.framework">
+ <HintPath>..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="Xamarin.UITest, Version=1.3.3.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\packages\Xamarin.UITest.1.3.3\lib\Xamarin.UITest.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="DomMemberModel.cs" />
+ <Compile Include="DomTypeModel.cs" />
+ <Compile Include="FormsUITest.cs" />
+ <Compile Include="LoaderActions.cs" />
+ <Compile Include="Validator.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ <None Include="Logs\Xamarin.Forms.UITest.Validator.log" />
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.CustomAttributes\Xamarin.Forms.CustomAttributes.csproj">
+ <Project>{4dcd0420-1168-4b77-86db-6196ee4bd491}</Project>
+ <Name>Xamarin.Forms.CustomAttributes</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Loader\Xamarin.Forms.Loader.csproj">
+ <Project>{00211725-2f89-4e2c-ac5a-38e5ff61be67}</Project>
+ <Name>Xamarin.Forms.Loader</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Core.iOS.UITests\Xamarin.Forms.Core.iOS.UITests.csproj">
+ <Project>{EADD8100-B3AE-4A31-92C4-267A64A1C6EB}</Project>
+ <Name>Xamarin.Forms.Core.iOS.UITests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Core.Android.UITests\Xamarin.Forms.Core.Android.UITests.csproj">
+ <Project>{A34EBE01-25BF-4E69-A2DC-2288DC625541}</Project>
+ <Name>Xamarin.Forms.Core.Android.UITests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform\Xamarin.Forms.Platform.csproj">
+ <Project>{67f9d3a8-f71e-4428-913f-c37ae82cdb24}</Project>
+ <Name>Xamarin.Forms.Platform</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup />
+ <ItemGroup>
+ <Content Include="UITestCoverage\Css\styles.css" />
+ <Content Include="UITestCoverage\Js\script.js" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+ </Target>
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.UITest.Validator/packages.config b/Xamarin.Forms.UITest.Validator/packages.config
new file mode 100644
index 00000000..031fa54c
--- /dev/null
+++ b/Xamarin.Forms.UITest.Validator/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit" version="2.6.4" targetFramework="net45" />
+ <package id="Xamarin.UITest" version="1.3.3" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.Design/AttributeTableBuilder.cs b/Xamarin.Forms.Xaml.Design/AttributeTableBuilder.cs
new file mode 100644
index 00000000..4b3689b6
--- /dev/null
+++ b/Xamarin.Forms.Xaml.Design/AttributeTableBuilder.cs
@@ -0,0 +1,14 @@
+using Microsoft.Windows.Design;
+
+namespace Xamarin.Forms.Xaml.Design
+{
+ class AttributeTableBuilder : Microsoft.Windows.Design.Metadata.AttributeTableBuilder
+ {
+ public AttributeTableBuilder()
+ {
+ // Turn off validation of values, which doesn't work for OnPlatform/OnIdiom
+ AddCustomAttributes(typeof (ArrayExtension).Assembly,
+ new XmlnsSupportsValidationAttribute("http://xamarin.com/schemas/2014/forms", false));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.Design/Properties/AssemblyInfo.cs b/Xamarin.Forms.Xaml.Design/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..3b978884
--- /dev/null
+++ b/Xamarin.Forms.Xaml.Design/Properties/AssemblyInfo.cs
@@ -0,0 +1,7 @@
+using System.Reflection;
+using Microsoft.Windows.Design.Metadata;
+using Xamarin.Forms.Xaml.Design;
+
+[assembly: AssemblyTitle("Xamarin.Forms.Xaml.Design")]
+[assembly: AssemblyDescription("Provides the design-time metadata for the XAML language service.")]
+[assembly: ProvideMetadata(typeof (RegisterMetadata))] \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.Design/RegisterMetadata.cs b/Xamarin.Forms.Xaml.Design/RegisterMetadata.cs
new file mode 100644
index 00000000..be3b2b88
--- /dev/null
+++ b/Xamarin.Forms.Xaml.Design/RegisterMetadata.cs
@@ -0,0 +1,9 @@
+using Microsoft.Windows.Design.Metadata;
+
+namespace Xamarin.Forms.Xaml.Design
+{
+ class RegisterMetadata : IProvideAttributeTable
+ {
+ public AttributeTable AttributeTable => new AttributeTableBuilder().CreateTable();
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.Design/Xamarin.Forms.Xaml.Design.csproj b/Xamarin.Forms.Xaml.Design/Xamarin.Forms.Xaml.Design.csproj
new file mode 100644
index 00000000..de727cb0
--- /dev/null
+++ b/Xamarin.Forms.Xaml.Design/Xamarin.Forms.Xaml.Design.csproj
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{65BC4888-CC59-428A-9B75-540CF1C09480}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.Xaml.Design</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Xaml.Design</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <NuGetPackageImportStamp>
+ </NuGetPackageImportStamp>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup Condition=" '$(OS)' != 'Unix' ">
+ <Reference Include="Microsoft.Windows.Design.Extensibility, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\lib\Microsoft.Windows.Design.Extensibility.dll</HintPath>
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Xaml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup Condition=" '$(OS)' != 'Unix' ">
+ <Compile Include="AttributeTableBuilder.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="RegisterMetadata.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Xaml\Xamarin.Forms.Xaml.csproj">
+ <Project>{9db2f292-8034-4e06-89ad-98bbda4306b9}</Project>
+ <Name>Xamarin.Forms.Xaml</Name>
+ <GenerateDesignMetadata>true</GenerateDesignMetadata>
+ <Private>False</Private>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup Condition=" '$(OS)' != 'Unix' ">
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets') And '$(OS)' != 'Unix' " />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild" Condition=" '$(OS)' != 'Unix' ">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('..\packages\Xamarin.Forms.Design.1.0.14-pre\build\Xamarin.Forms.Design.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Forms.Design.1.0.14-pre\build\Xamarin.Forms.Design.targets'))" />
+ </Target>
+ <Import Project="..\packages\Xamarin.Forms.Design.1.0.14-pre\build\Xamarin.Forms.Design.targets" Condition="Exists('..\packages\Xamarin.Forms.Design.1.0.14-pre\build\Xamarin.Forms.Design.targets') And '$(OS)' != 'Unix' " />
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.Design/packages.config b/Xamarin.Forms.Xaml.Design/packages.config
new file mode 100644
index 00000000..6e99fb80
--- /dev/null
+++ b/Xamarin.Forms.Xaml.Design/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Xamarin.Forms.Design" version="1.0.14-pre" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Compiled/FindByName.xaml b/Xamarin.Forms.Xaml.UnitTests/Compiled/FindByName.xaml
new file mode 100644
index 00000000..c0b7afd7
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Compiled/FindByName.xaml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Compiled.FindByName"
+ x:Name="root">
+ <StackLayout>
+ <Label Text="Foo" x:Name="label0"/>
+ </StackLayout>
+</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/Compiled/FindByName.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Compiled/FindByName.xaml.cs
new file mode 100644
index 00000000..0ec198e8
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Compiled/FindByName.xaml.cs
@@ -0,0 +1,40 @@
+using NUnit.Framework;
+
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Xaml.UnitTests.Compiled
+{
+ public partial class FindByName : ContentPage
+ {
+ public FindByName ()
+ {
+ InitializeComponent ();
+ }
+
+ public FindByName (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class FindByNameTests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestRootName (bool useCompiledXaml)
+ {
+ var page = new FindByName (useCompiledXaml);
+ Assert.AreSame (page, ((Forms.Internals.INameScope)page).FindByName ("root"));
+ Assert.AreSame (page, page.FindByName<FindByName> ("root"));
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestName (bool useCompiledXaml)
+ {
+ var page = new FindByName (useCompiledXaml);
+ Assert.AreSame (page.label0, page.FindByName<Label> ("label0"));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Compiled/SetValue.xaml b/Xamarin.Forms.Xaml.UnitTests/Compiled/SetValue.xaml
new file mode 100644
index 00000000..e60cd6db
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Compiled/SetValue.xaml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Compiled.SetValue">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <Color x:Key="purple">Purple</Color>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ <StackLayout>
+ <Label x:Name="label0" Text="Foo"/>
+ <Label x:Name="label1" Text="{Binding Path=labeltext}"/>
+ <Button x:Name="button0" Clicked="onButtonClicked" />
+ <Image x:Name="image0" IsOpaque="true" />
+ <Label x:Name="label2" Grid.Column="1">
+ <Grid.Row>2</Grid.Row>
+ </Label>
+ <ContentView x:Name="contentview0">
+ <ContentView.Content>
+ <Label x:Name="label3"/>
+ </ContentView.Content>
+ </ContentView>
+ <ContentView x:Name="contentview1">
+ <Label x:Name="label4"/>
+ </ContentView>
+ <StackLayout x:Name="stack0">
+ <StackLayout.Children>
+ <Label x:Name="label5"/>
+ <Label x:Name="label6"/>
+ </StackLayout.Children>
+ </StackLayout>
+ <StackLayout x:Name="stack1">
+ <Label x:Name="label7"/>
+ <Label x:Name="label8"/>
+ </StackLayout>
+ <StackLayout x:Name="stack2">
+ <StackLayout.Children>
+ <Label x:Name="label9"/>
+ </StackLayout.Children>
+ </StackLayout>
+ <StackLayout x:Name="stack3">
+ <Label x:Name="label10"/>
+ </StackLayout>
+ <Label x:Name="label11" Text="{Binding labeltext}"/>
+ <ListView x:Name="listView">
+ <ListView.ItemsSource>
+ <x:Array Type="{x:Type x:String}" x:Key="array">
+ <x:String>foo</x:String>
+ <x:String>bar</x:String>
+ </x:Array>
+ </ListView.ItemsSource>
+ </ListView>
+ <Label x:Name="label12" TextColor="Red" />
+ <Label x:Name="label13">
+ <Label.TextColor>
+ <Color>Pink</Color>
+ </Label.TextColor>
+ </Label>
+ <Grid x:Name="grid0">
+ <Grid.RowDefinitions>
+ <RowDefinition/>
+ <RowDefinition/>
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition/>
+ </Grid.ColumnDefinitions>
+ </Grid>
+ <Label x:Name="label14" AbsoluteLayout.LayoutFlags="PositionProportional,WidthProportional" />
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Compiled/SetValue.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Compiled/SetValue.xaml.cs
new file mode 100644
index 00000000..f835d59f
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Compiled/SetValue.xaml.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Linq;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests.Compiled
+{
+ public partial class SetValue : ContentPage
+ {
+ public SetValue ()
+ {
+ InitializeComponent ();
+ }
+
+ public SetValue (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ bool fired;
+ void onButtonClicked (object sender, EventArgs args)
+ {
+ fired = true;
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetValueToBP (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.AreEqual ("Foo", page.label0.Text);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetBindingToBP (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.AreEqual (Label.TextProperty.DefaultValue, page.label1.Text);
+
+ page.label1.BindingContext = new {labeltext="Foo"};
+ Assert.AreEqual ("Foo", page.label1.Text);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetBindingWithImplicitPath (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.AreEqual (Label.TextProperty.DefaultValue, page.label11.Text);
+
+ page.label11.BindingContext = new {labeltext="Foo"};
+ Assert.AreEqual ("Foo", page.label11.Text);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetEvent (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.False (page.fired);
+ (page.button0 as IButtonController).SendClicked ();
+ Assert.True (page.fired);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetBoolValue (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.True (page.image0.IsOpaque);
+ }
+
+ //TODO test all value conversions
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetAttachedBP (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.AreEqual (1, Grid.GetColumn (page.label2));
+ Assert.AreEqual (2, Grid.GetRow (page.label2));
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetContent (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.AreSame (page.label3, page.contentview0.Content);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetImplicitContent (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.AreSame (page.label4, page.contentview1.Content);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetCollectionContent (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.True (page.stack0.Children.Contains(page.label5));
+ Assert.True (page.stack0.Children.Contains(page.label6));
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetImplicitCollectionContent (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.True (page.stack1.Children.Contains(page.label7));
+ Assert.True (page.stack1.Children.Contains(page.label8));
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetSingleCollectionContent (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.True (page.stack2.Children.Contains(page.label9));
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetImplicitSingleCollectionContent (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.True (page.stack3.Children.Contains(page.label10));
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetPropertyDefinedOnGenericType (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.AreEqual (2, page.listView.ItemsSource.Cast<object>().Count ());
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetConvertibleProperties (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.AreEqual (Color.Red, page.label12.TextColor);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetValueTypeProperties (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.AreEqual (Color.Pink, page.label13.TextColor);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void CreateValueTypes (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.AreEqual (Color.Purple, page.Resources ["purple"]);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void DefCollections (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.AreEqual (2, page.grid0.RowDefinitions.Count);
+ Assert.AreEqual (1, page.grid0.ColumnDefinitions.Count);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void FlagsAreApplied (bool useCompiledXaml)
+ {
+ var page = new SetValue (useCompiledXaml);
+ Assert.AreEqual (AbsoluteLayoutFlags.PositionProportional | AbsoluteLayoutFlags.WidthProportional, AbsoluteLayout.GetLayoutFlags (page.label14));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/ConstraintExpression.xaml b/Xamarin.Forms.Xaml.UnitTests/ConstraintExpression.xaml
new file mode 100644
index 00000000..0e71a7a0
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/ConstraintExpression.xaml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.ConstraintExpression" >
+ <RelativeLayout x:Name="relativeLayout">
+ <Label x:Name="constantConstraint"
+ RelativeLayout.WidthConstraint="{ConstraintExpression Type=Constant, Constant=42}" />
+ <Label x:Name="constraintRelativeToParent"
+ RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Constant=2, Factor=.5, Property=Width}" />
+ <Label x:Name="foo" />
+ <Label x:Name="constraintRelativeToView"
+ RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToView, Constant=2, Factor=.5, Property=Width, ElementName=foo}" />
+ </RelativeLayout>
+</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/ConstraintExpression.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/ConstraintExpression.xaml.cs
new file mode 100644
index 00000000..3786ccb5
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/ConstraintExpression.xaml.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using Xamarin.Forms.Core.UnitTests;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class ConstraintExpression : ContentPage
+ {
+ public ConstraintExpression ()
+ {
+ InitializeComponent ();
+ }
+
+ public ConstraintExpression (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [SetUp]
+ public void Setup ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void ConstantConstraint (bool useCompiledXaml)
+ {
+ var layout = new ConstraintExpression (useCompiledXaml);
+ var label = layout.constantConstraint;
+ var constraint = RelativeLayout.GetWidthConstraint (label);
+ Assert.NotNull (constraint);
+ Assert.AreEqual (42, constraint.Compute (null));
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void ConstraintRelativeToParent (bool useCompiledXaml)
+ {
+ var layout = new ConstraintExpression (useCompiledXaml);
+ layout.relativeLayout.Layout (new Rectangle (0, 0, 200, 200));
+ var label = layout.constraintRelativeToParent;
+ var constraint = RelativeLayout.GetWidthConstraint (label);
+ Assert.NotNull (constraint);
+ Assert.AreEqual (102, constraint.Compute (layout.relativeLayout));
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void ContraintRelativeToView (bool useCompiledXaml)
+ {
+ var layout = new ConstraintExpression (useCompiledXaml) {
+ IsPlatformEnabled = true
+ };
+ layout.relativeLayout.Layout (new Rectangle (0, 0, 200, 100));
+ layout.foo.Layout (new Rectangle (5, 5, 190, 25));
+
+ var label = layout.constraintRelativeToView;
+ var constraint = RelativeLayout.GetWidthConstraint (label);
+ Assert.NotNull (constraint);
+ Assert.AreEqual (97, constraint.Compute (layout.relativeLayout));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/CustomXamlView.xaml b/Xamarin.Forms.Xaml.UnitTests/CustomXamlView.xaml
new file mode 100644
index 00000000..67d92bef
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/CustomXamlView.xaml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<ContentView
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.CustomXamlView">
+ <Label x:Name="label0" Text="foobar"/>
+</ContentView> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/CustomXamlView.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/CustomXamlView.xaml.cs
new file mode 100644
index 00000000..6b0c862d
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/CustomXamlView.xaml.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class CustomXamlView : ContentView
+ {
+ public CustomXamlView ()
+ {
+ InitializeComponent ();
+ }
+ }
+}
diff --git a/Xamarin.Forms.Xaml.UnitTests/DataTemplate.xaml b/Xamarin.Forms.Xaml.UnitTests/DataTemplate.xaml
new file mode 100644
index 00000000..d1c233b7
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/DataTemplate.xaml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.DataTemplate"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <DataTemplate x:Key="celltemplate">
+ <TextCell Text="{Binding}"/>
+ </DataTemplate>
+ <local:ReverseConverter x:Key="reverseConverter"/>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ <StackLayout>
+ <ListView x:Name="emptyTextCell">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <TextCell />
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ <ListView x:Name="textCell">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <TextCell Text="{Binding}"/>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ <ListView x:Name="fromResource" ItemTemplate="{StaticResource celltemplate}" />
+ <ListView x:Name="textCellAccessResource">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <TextCell Text="{Binding Path=., Converter={StaticResource reverseConverter}}"/>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ <ListView x:Name="viewCellAccessResource">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell><Label Text="{Binding Path=., Converter={StaticResource reverseConverter}}"/></ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/DataTemplate.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/DataTemplate.xaml.cs
new file mode 100644
index 00000000..cfc5d1a1
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/DataTemplate.xaml.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class DataTemplate : ContentPage
+ {
+ public DataTemplate ()
+ {
+ InitializeComponent ();
+ }
+
+ public DataTemplate (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void EmptyTextCell (bool useCompiledXaml)
+ {
+ var layout = new DataTemplate (useCompiledXaml);
+
+ var cell0 = layout.emptyTextCell.ItemTemplate.CreateContent ();
+ Assert.NotNull (cell0);
+ Assert.That (cell0, Is.TypeOf<TextCell> ());
+
+ var cell1 = layout.emptyTextCell.ItemTemplate.CreateContent ();
+ Assert.NotNull (cell1);
+ Assert.That (cell1, Is.TypeOf<TextCell> ());
+
+ Assert.AreNotSame (cell0, cell1);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TextCell (bool useCompiledXaml)
+ {
+ var layout = new DataTemplate (useCompiledXaml);
+ var cell0 = layout.textCell.ItemTemplate.CreateContent ();
+ Assert.NotNull (cell0);
+ Assert.That (cell0, Is.TypeOf<TextCell> ());
+ ((TextCell)cell0).BindingContext = "Foo";
+ Assert.AreEqual ("Foo", ((TextCell)cell0).Text);
+
+ var cell1 = layout.textCell.ItemTemplate.CreateContent ();
+ Assert.NotNull (cell1);
+ Assert.That (cell1, Is.TypeOf<TextCell> ());
+ ((TextCell)cell1).BindingContext = "Bar";
+ Assert.AreEqual ("Bar", ((TextCell)cell1).Text);
+
+ Assert.AreNotSame (cell0, cell1);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void FromResource (bool useCompiledXaml)
+ {
+ var layout = new DataTemplate (useCompiledXaml);
+ var cell0 = layout.fromResource.ItemTemplate.CreateContent ();
+ Assert.NotNull (cell0);
+ Assert.That (cell0, Is.TypeOf<TextCell> ());
+ ((TextCell)cell0).BindingContext = "Foo";
+ Assert.AreEqual ("Foo", ((TextCell)cell0).Text);
+
+ var cell1 = layout.fromResource.ItemTemplate.CreateContent ();
+ Assert.NotNull (cell1);
+ Assert.That (cell1, Is.TypeOf<TextCell> ());
+ ((TextCell)cell1).BindingContext = "Bar";
+ Assert.AreEqual ("Bar", ((TextCell)cell1).Text);
+
+ Assert.AreNotSame (cell0, cell1);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TextCellAccessResources (bool useCompiledXaml)
+ {
+ var layout = new DataTemplate (useCompiledXaml);
+ var cell0 = layout.textCellAccessResource.ItemTemplate.CreateContent ();
+ Assert.NotNull (cell0);
+ Assert.That (cell0, Is.TypeOf<TextCell> ());
+ ((TextCell)cell0).BindingContext = "Foo";
+ Assert.AreEqual ("ooF", ((TextCell)cell0).Text);
+
+ var cell1 = layout.textCellAccessResource.ItemTemplate.CreateContent ();
+ Assert.NotNull (cell1);
+ Assert.That (cell1, Is.TypeOf<TextCell> ());
+ ((TextCell)cell1).BindingContext = "Bar";
+ Assert.AreEqual ("raB", ((TextCell)cell1).Text);
+
+ Assert.AreNotSame (cell0, cell1);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void ViewCellAccessResources (bool useCompiledXaml)
+ {
+ var layout = new DataTemplate (useCompiledXaml);
+ var cell0 = layout.viewCellAccessResource.ItemTemplate.CreateContent ();
+ Assert.NotNull (cell0);
+ Assert.That (cell0, Is.TypeOf<ViewCell> ());
+ ((ViewCell)cell0).BindingContext = "Foo";
+ Assert.AreEqual ("ooF", ((Label)((ViewCell)cell0).View).Text);
+
+ var cell1 = layout.viewCellAccessResource.ItemTemplate.CreateContent ();
+ Assert.NotNull (cell1);
+ Assert.That (cell1, Is.TypeOf<ViewCell> ());
+ ((ViewCell)cell1).BindingContext = "Bar";
+ Assert.AreEqual ("raB", ((Label)((ViewCell)cell1).View).Text);
+
+ Assert.AreNotSame (cell0, cell1);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/DummyBuildEngine.cs b/Xamarin.Forms.Xaml.UnitTests/DummyBuildEngine.cs
new file mode 100644
index 00000000..df76e13a
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/DummyBuildEngine.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections;
+using Microsoft.Build.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class DummyBuildEngine : IBuildEngine
+ {
+ public void LogErrorEvent (BuildErrorEventArgs e)
+ {
+ }
+
+ public void LogWarningEvent (BuildWarningEventArgs e)
+ {
+ }
+
+ public void LogMessageEvent (BuildMessageEventArgs e)
+ {
+ }
+
+ public void LogCustomEvent (CustomBuildEventArgs e)
+ {
+ }
+
+ public bool BuildProjectFile (string projectFileName, string[] targetNames, IDictionary globalProperties, IDictionary targetOutputs)
+ {
+ return false;
+ }
+
+ public bool ContinueOnError {
+ get { return false; }
+ }
+
+ public int LineNumberOfTaskNode {
+ get { return 1; }
+ }
+
+ public int ColumnNumberOfTaskNode {
+ get { return 1; }
+ }
+
+ public string ProjectFileOfTaskNode {
+ get { return String.Empty; }
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/DynamicResource.xaml b/Xamarin.Forms.Xaml.UnitTests/DynamicResource.xaml
new file mode 100644
index 00000000..3a90c26a
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/DynamicResource.xaml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.DynamicResource">
+ <Label Text="{DynamicResource FooBar}" x:Name="label0" />
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/DynamicResource.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/DynamicResource.xaml.cs
new file mode 100644
index 00000000..703313c4
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/DynamicResource.xaml.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+
+using NUnit.Framework;
+
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class DynamicResource : ContentPage
+ {
+ public DynamicResource ()
+ {
+ InitializeComponent ();
+ }
+
+ public DynamicResource (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestDynamicResources (bool useCompiledXaml)
+ {
+ var layout = new DynamicResource (useCompiledXaml);
+ var label = layout.label0;
+
+ Assert.Null (label.Text);
+
+ layout.Resources = new ResourceDictionary {
+ {"FooBar", "FOOBAR"},
+ };
+ Assert.AreEqual ("FOOBAR", label.Text);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml b/Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml
new file mode 100644
index 00000000..f9032089
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<local:BaseForEvents xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.EventsConnection">
+ <StackLayout>
+ <local:ElementWithEvent x:Name="elementWithEvent"
+ Clicked="HandleClicked" />
+ <local:ElementWithGenericEvent x:Name="elementWithGenericEvent"
+ Clicked="HandleGenericClicked"/>
+ <local:ElementWithEvent x:Name="eventHandlerOnBase"
+ Clicked="HandleClickedOnBase" />
+ <local:ElementWithEvent x:Name="elementwithAsyncprivateHandler"
+ Clicked="HandleClickedPrivateAsync" />
+ </StackLayout>
+</local:BaseForEvents> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml.cs
new file mode 100644
index 00000000..7bab5676
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class BaseForEvents : ContentView
+ {
+ protected int baseClicked;
+ protected void HandleClickedOnBase (object sender, EventArgs e)
+ {
+ baseClicked++;
+ }
+ }
+
+ public class ElementWithEvent : ContentView
+ {
+ public event EventHandler Clicked;
+
+ public void SendClicked ()
+ {
+ var eh = Clicked;
+ if (eh != null)
+ eh (this, EventArgs.Empty);
+ }
+ }
+
+ public class ElementWithGenericEvent : ContentView
+ {
+ public event EventHandler<ItemTappedEventArgs> Clicked;
+
+ public void SendClicked ()
+ {
+ var eh = Clicked;
+ if (eh != null)
+ eh (this, new ItemTappedEventArgs ("foo", "bar"));
+ }
+ }
+
+ public partial class EventsConnection : BaseForEvents
+ {
+ public EventsConnection ()
+ {
+ InitializeComponent ();
+ }
+
+ public EventsConnection (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ int clicked;
+ public void HandleClicked (object sender, EventArgs e)
+ {
+ clicked++;
+ }
+
+ int genericClicked;
+ public void HandleGenericClicked (object sender, ItemTappedEventArgs e)
+ {
+ genericClicked++;
+ }
+
+ int asyncPrivateClicked;
+ async void HandleClickedPrivateAsync (object sender, EventArgs e)
+ {
+ asyncPrivateClicked++;
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestClicked (bool useCompiledXaml)
+ {
+ var layout = new EventsConnection (useCompiledXaml);
+ Assert.AreEqual (0, layout.clicked);
+ layout.elementWithEvent.SendClicked ();
+ Assert.AreEqual (1, layout.clicked);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestGenericClicked (bool useCompiledXaml)
+ {
+ var layout = new EventsConnection (useCompiledXaml);
+ Assert.AreEqual (0, layout.genericClicked);
+ layout.elementWithGenericEvent.SendClicked ();
+ Assert.AreEqual (1, layout.genericClicked);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestHandlerOnBase (bool useCompiledXaml)
+ {
+ var layout = new EventsConnection (useCompiledXaml);
+ Assert.AreEqual (0, layout.baseClicked);
+ layout.eventHandlerOnBase.SendClicked ();
+ Assert.AreEqual (1, layout.baseClicked);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestAsyncPrivateHandler (bool useCompiledXaml)
+ {
+ var layout = new EventsConnection (useCompiledXaml);
+ Assert.AreEqual (0, layout.asyncPrivateClicked);
+ layout.elementwithAsyncprivateHandler.SendClicked ();
+ Assert.AreEqual (1, layout.asyncPrivateClicked);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/FactoryMethodTests.cs b/Xamarin.Forms.Xaml.UnitTests/FactoryMethodTests.cs
new file mode 100644
index 00000000..d6ee1886
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/FactoryMethodTests.cs
@@ -0,0 +1,53 @@
+using System;
+using NUnit.Framework;
+
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class FactoryMethodTests : BaseTestFixture
+ {
+ [Test]
+ public void ThrowOnMissingCtor ()
+ {
+ var xaml = @"
+ <local:MockView
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"" >
+ <local:MockView.Content>
+ <local:MockFactory>
+ <x:Arguments>
+ <x:Object/>
+ <x:String>bar</x:String>
+ <x:Int32>42</x:Int32>
+ </x:Arguments>
+ </local:MockFactory>
+ </local:MockView.Content>
+ </local:MockView>";
+ Assert.Throws<MissingMethodException> (()=>new MockView ().LoadFromXaml (xaml));
+ }
+
+ [Test]
+ public void ThrowOnMissingMethod ()
+ {
+ var xaml = @"
+ <local:MockView
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"" >
+ <local:MockView.Content>
+ <local:MockFactory x:FactoryMethod=""Factory"">
+ <x:Arguments>
+ <x:Object/>
+ <x:String>bar</x:String>
+ <x:Int32>42</x:Int32>
+ </x:Arguments>
+ </local:MockFactory>
+ </local:MockView.Content>
+ </local:MockView>";
+ Assert.Throws<MissingMemberException> (()=>new MockView ().LoadFromXaml (xaml));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Xaml.UnitTests/FactoryMethods.xaml b/Xamarin.Forms.Xaml.UnitTests/FactoryMethods.xaml
new file mode 100644
index 00000000..a90a0378
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/FactoryMethods.xaml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.FactoryMethods">
+ <StackLayout>
+ <local:MockView x:Name="v0">
+ <local:MockView.Content>
+ <local:MockFactory/>
+ </local:MockView.Content>
+ </local:MockView>
+ <local:MockView x:Name="v1">
+ <local:MockView.Content>
+ <local:MockFactory>
+ <x:Arguments>
+ <x:String>foo</x:String>
+ <x:String>bar</x:String>
+ </x:Arguments>
+ </local:MockFactory>
+ </local:MockView.Content>
+ </local:MockView>
+ <local:MockView x:Name="v2">
+ <local:MockView.Content>
+ <local:MockFactory>
+ <x:Arguments>
+ <x:Int32>42</x:Int32>
+ </x:Arguments>
+ </local:MockFactory>
+ </local:MockView.Content>
+ </local:MockView>
+ <local:MockView x:Name="v3">
+ <local:MockView.Content>
+ <local:MockFactory x:FactoryMethod="ParameterlessFactory">
+ </local:MockFactory>
+ </local:MockView.Content>
+ </local:MockView>
+ <local:MockView x:Name="v4">
+ <local:MockView.Content>
+ <local:MockFactory x:FactoryMethod="Factory">
+ <x:Arguments>
+ <x:String>foo</x:String>
+ <x:Int32>42</x:Int32>
+ </x:Arguments>
+ </local:MockFactory>
+ </local:MockView.Content>
+ </local:MockView>
+ <local:MockView x:Name="v5">
+ <local:MockView.Content>
+ <local:MockFactory x:FactoryMethod="Factory">
+ <x:Arguments>
+ <x:Int32>42</x:Int32>
+ <x:String>foo</x:String>
+ </x:Arguments>
+ </local:MockFactory>
+ </local:MockView.Content>
+ </local:MockView>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/FactoryMethods.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/FactoryMethods.xaml.cs
new file mode 100644
index 00000000..42f359b7
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/FactoryMethods.xaml.cs
@@ -0,0 +1,115 @@
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class MockView : View
+ {
+ public MockFactory Content { get; set; }
+ }
+
+ public class MockFactory
+ {
+ public string Content { get; set; }
+ public MockFactory ()
+ {
+ Content = "default ctor";
+ }
+
+ public MockFactory (string arg0, string arg1)
+ {
+ Content = "alternate ctor " + arg0 + arg1;
+ }
+
+ public MockFactory (int arg)
+ {
+ Content = "int ctor " + arg.ToString ();
+ }
+
+ public static MockFactory ParameterlessFactory ()
+ {
+ return new MockFactory {
+ Content = "parameterless factory",
+ };
+ }
+
+ public static MockFactory Factory (string arg0, int arg1)
+ {
+ return new MockFactory {
+ Content = "factory " + arg0 + arg1,
+ };
+ }
+
+ public static MockFactory Factory (int arg0, string arg1)
+ {
+ return new MockFactory {
+ Content = "factory " + arg0 + arg1,
+ };
+ }
+ }
+
+ public partial class FactoryMethods : ContentPage
+ {
+ public FactoryMethods ()
+ {
+ InitializeComponent ();
+ }
+
+ public FactoryMethods (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestDefaultCtor (bool useCompiledXaml)
+ {
+ var layout = new FactoryMethods (useCompiledXaml);
+ Assert.AreEqual ("default ctor", layout.v0.Content.Content);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestStringCtor (bool useCompiledXaml)
+ {
+ var layout = new FactoryMethods (useCompiledXaml);
+ Assert.AreEqual ("alternate ctor foobar", layout.v1.Content.Content);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestIntCtor (bool useCompiledXaml)
+ {
+ var layout = new FactoryMethods (useCompiledXaml);
+ Assert.AreEqual ("int ctor 42", layout.v2.Content.Content);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestArgumentlessFactoryMethod (bool useCompiledXaml)
+ {
+ var layout = new FactoryMethods (useCompiledXaml);
+ Assert.AreEqual ("parameterless factory", layout.v3.Content.Content);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestFactoryMethod (bool useCompiledXaml)
+ {
+ var layout = new FactoryMethods (useCompiledXaml);
+ Assert.AreEqual ("factory foo42", layout.v4.Content.Content);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestFactoryMethodParametersOrder (bool useCompiledXaml)
+ {
+ var layout = new FactoryMethods (useCompiledXaml);
+ Assert.AreEqual ("factory 42foo", layout.v5.Content.Content);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/FontConverterTests.cs b/Xamarin.Forms.Xaml.UnitTests/FontConverterTests.cs
new file mode 100644
index 00000000..fc5e25b0
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/FontConverterTests.cs
@@ -0,0 +1,27 @@
+using NUnit.Framework;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class FontConverterTests : BaseTestFixture
+ {
+ [TestCase ("Bold", Forms.FontAttributes.Bold)]
+ [TestCase ("Italic", Forms.FontAttributes.Italic)]
+ [TestCase ("Bold, Italic", Forms.FontAttributes.Bold | Forms.FontAttributes.Italic)]
+ public void FontAttributes (string attributeString, FontAttributes result)
+ {
+ var xaml = @"
+ <Label
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" FontAttributes=""" + result + @""" />";
+
+ Device.PlatformServices = new MockPlatformServices ();
+
+ var label = new Label ().LoadFromXaml (xaml);
+
+ Assert.AreEqual (result, label.FontAttributes);
+ Assert.AreEqual (result, label.Font.FontAttributes);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/GenericCollections.xaml b/Xamarin.Forms.Xaml.UnitTests/GenericCollections.xaml
new file mode 100644
index 00000000..79a38df9
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/GenericCollections.xaml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.GenericCollections">
+ <Label x:Name="label0">
+ <local:AttachedBP.AttachedBP>
+ <local:GenericCollection>
+ <x:String>Foo</x:String>
+ </local:GenericCollection>
+ </local:AttachedBP.AttachedBP>
+ </Label>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/GenericCollections.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/GenericCollections.xaml.cs
new file mode 100644
index 00000000..95c057b0
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/GenericCollections.xaml.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using System.Collections.ObjectModel;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class AttachedBP
+ {
+ public static readonly BindableProperty AttachedBPProperty = BindableProperty.CreateAttached (
+ "AttachedBP",
+ typeof(GenericCollection),
+ typeof(AttachedBP),
+ null);
+ }
+
+ public class GenericCollection : ObservableCollection<object>
+ {
+ }
+
+ public partial class GenericCollections : ContentPage
+ {
+ public GenericCollections ()
+ {
+ InitializeComponent ();
+ }
+
+ public GenericCollections (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SupportsCrookedGenericScenarios (bool useCompiledXaml)
+ {
+ var p = new GenericCollections ();
+ Assert.AreEqual ("Foo", (p.label0.GetValue (AttachedBP.AttachedBPProperty) as GenericCollection) [0]);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/GenericsTests.xaml b/Xamarin.Forms.Xaml.UnitTests/GenericsTests.xaml
new file mode 100644
index 00000000..da224282
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/GenericsTests.xaml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:sys="clr-namespace:System;assembly=mscorlib"
+ xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib"
+ xmlns:scgs="clr-namespace:System.Collections.Generic;assembly=System"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.GenericsTests">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <scg:List x:TypeArguments="Button" x:Key="genericButtonList">
+ <Button />
+ <Button />
+ </scg:List>
+ <scg:List x:TypeArguments="Button" x:Key="genericButtonList1" x:Name="myList"/>
+ <scg:List x:TypeArguments="sys:String" x:Key="list"/>
+ <scg:Dictionary x:TypeArguments="sys:String, sys:String" x:Key="dict"/>
+ <scgs:Queue x:TypeArguments="scg:KeyValuePair(sys:String,sys:String)" x:Key="queue"/>
+ <scg:List x:TypeArguments="x:String" x:Key="stringList"/>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/GenericsTests.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/GenericsTests.xaml.cs
new file mode 100644
index 00000000..5a62b9fa
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/GenericsTests.xaml.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class GenericsTests : ContentPage
+ {
+ public GenericsTests ()
+ {
+ InitializeComponent ();
+ }
+
+ public GenericsTests (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [Test]
+ public void NoGenericsOnXaml2006 ()
+ {
+ var xaml = @"
+ <ContentPage
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:scg=""clr-namespace:System.Collections.Generic;assembly=mscorlib"">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <scg:List x:TypeArguments=""Button"" x:Key=""genericList""/>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ </ContentPage>";
+ Assert.Throws (new XamlParseExceptionConstraint (8, 9), () => new ContentPage ().LoadFromXaml (xaml));
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void GenericSupportOnXaml2009 (bool useCompiledXaml)
+ {
+ var layout = new GenericsTests (useCompiledXaml);
+ Assert.True (layout.Resources.ContainsKey ("genericButtonList"));
+ var list = layout.Resources ["genericButtonList"];
+ Assert.That (list, Is.TypeOf<List<Button>> ());
+ Assert.AreEqual (2, ((List<Button>)list).Count);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void FindGenericByName (bool useCompiledXaml)
+ {
+ var layout = new GenericsTests (useCompiledXaml);
+ var list = layout.FindByName<List<Button>> ("myList");
+ Assert.NotNull (list);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestGenericParsing (bool useCompiledXaml)
+ {
+ var layout = new GenericsTests (useCompiledXaml);
+ var list = layout.Resources ["list"];
+ Assert.NotNull (list);
+ Assert.That (list, Is.TypeOf<List<String>> ());
+
+ var dict = layout.Resources ["dict"];
+ Assert.NotNull (dict);
+ Assert.That (dict, Is.TypeOf<Dictionary<string,string>> ());
+
+ var queue = layout.Resources ["queue"];
+ Assert.NotNull (dict);
+ Assert.That (queue, Is.TypeOf<Queue<KeyValuePair<string,string>>> ());
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestXamlPrimitives (bool useCompiledXaml)
+ {
+ var layout = new GenericsTests (useCompiledXaml);
+ var list = layout.Resources ["stringList"];
+ Assert.NotNull (list);
+ Assert.That (list, Is.TypeOf<List<String>> ());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/ImplicitConversions.xaml b/Xamarin.Forms.Xaml.UnitTests/ImplicitConversions.xaml
new file mode 100644
index 00000000..38d20e3e
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/ImplicitConversions.xaml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.ImplicitConversions">
+ <StackLayout>
+ <DatePicker x:Name="datetime0" Date="2015-01-16"/>
+ <DatePicker x:Name="datetime1">
+ <DatePicker.Date>2015-01-16</DatePicker.Date>
+ </DatePicker>
+ <Label x:Name="label0" Text="foobar"/>
+ <Label x:Name="label1">
+ <Label.Text>
+ foobar
+ </Label.Text>
+ </Label>
+ <Label x:Name="label2">
+ foobar
+ </Label>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/ImplicitConversions.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/ImplicitConversions.xaml.cs
new file mode 100644
index 00000000..5eae0299
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/ImplicitConversions.xaml.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class ImplicitConversions : ContentPage
+ {
+ public ImplicitConversions ()
+ {
+ InitializeComponent ();
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [Test]
+ public void Datetime ()
+ {
+ var layout = new ImplicitConversions ();
+
+ Assert.AreEqual (new DateTime (2015, 01, 16), layout.datetime0.Date);
+ Assert.AreEqual (new DateTime (2015, 01, 16), layout.datetime1.Date);
+ }
+
+ [Test]
+ public void String ()
+ {
+ var layout = new ImplicitConversions ();
+
+ Assert.AreEqual ("foobar", layout.label0.Text);
+ Assert.AreEqual ("foobar", layout.label1.Text);
+
+ //Issue #2122, implicit content property not trimmed
+ Assert.AreEqual ("foobar", layout.label2.Text);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/IsCompiledDefault.xaml b/Xamarin.Forms.Xaml.UnitTests/IsCompiledDefault.xaml
new file mode 100644
index 00000000..15033daf
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/IsCompiledDefault.xaml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Forms.Xaml.UnitTests.IsCompiledDefault">
+ <ContentPage.Content>
+ </ContentPage.Content>
+</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/IsCompiledDefault.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/IsCompiledDefault.xaml.cs
new file mode 100644
index 00000000..e07c00b1
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/IsCompiledDefault.xaml.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class IsCompiledDefault : ContentPage
+ {
+ public IsCompiledDefault ()
+ {
+ InitializeComponent ();
+ }
+
+ public IsCompiledDefault (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void IsCompiled (bool useCompiledXaml)
+ {
+ var layout = new IsCompiledDefault (useCompiledXaml);
+ Assert.AreEqual (true, typeof (IsCompiledDefault).IsCompiled ());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/IsCompiledSkip.xaml b/Xamarin.Forms.Xaml.UnitTests/IsCompiledSkip.xaml
new file mode 100644
index 00000000..05a2d9fc
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/IsCompiledSkip.xaml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Forms.Xaml.UnitTests.IsCompiledSkip">
+ <ContentPage.Content>
+ </ContentPage.Content>
+</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/IsCompiledSkip.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/IsCompiledSkip.xaml.cs
new file mode 100644
index 00000000..ca5b7cbd
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/IsCompiledSkip.xaml.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using NUnit.Framework;
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [XamlCompilation (XamlCompilationOptions.Skip)]
+ public partial class IsCompiledSkip : ContentPage
+ {
+ public IsCompiledSkip ()
+ {
+ InitializeComponent ();
+ }
+
+ public IsCompiledSkip (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void IsCompiled (bool useCompiledXaml)
+ {
+ var layout = new IsCompiledDefault (useCompiledXaml);
+ Assert.AreEqual (false, typeof (IsCompiledSkip).IsCompiled ());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/BPNotResolvedOnSubClass.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/BPNotResolvedOnSubClass.xaml
new file mode 100644
index 00000000..ea5204a3
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/BPNotResolvedOnSubClass.xaml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.BPNotResolvedOnSubClass">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <Style TargetType="Button">
+ <Style.Setters>
+ <Setter Property="local:BPNotResolvedOnSubClass.ShadowColor" Value="#dddddd" />
+ </Style.Setters>
+ </Style>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/BPNotResolvedOnSubClass.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/BPNotResolvedOnSubClass.xaml.cs
new file mode 100644
index 00000000..65bb73f1
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/BPNotResolvedOnSubClass.xaml.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class BPNotResolvedOnSubClass : ContentPage
+ {
+ public static readonly BindableProperty ShadowColorProperty =
+ BindableProperty.CreateAttached ("ShadowColor", typeof (Color), typeof (BPNotResolvedOnSubClass), Color.Default);
+
+ public static Color GetShadowColor (Element bindable) // Change to Element instead of BindableObject o make fail
+ {
+ return (Color)bindable.GetValue (ShadowColorProperty);
+ }
+
+ public BPNotResolvedOnSubClass ()
+ {
+ InitializeComponent ();
+ }
+
+ public BPNotResolvedOnSubClass (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void CorrectlyResolveBPOnSubClasses (bool useCompiledXaml)
+ {
+ var layout = new BPNotResolvedOnSubClass (useCompiledXaml);
+ var style = (Style)layout.Resources["Xamarin.Forms.Button"];
+ Assert.NotNull (style);
+
+ var button = new Button ();
+ button.Style = style;
+
+ Assert.AreEqual (Color.FromHex ("#dddddd"), button.GetValue (ShadowColorProperty));
+ }
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz24485.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz24485.xaml
new file mode 100644
index 00000000..ed7ec074
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz24485.xaml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz24485">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <local:Bz24485Converter x:Key="ToBasicItem" />
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ <Grid BindingContext="{Binding Data1, Converter={StaticResource ToBasicItem}">
+ <Label Text="{Binding FormattedDate}" />
+ <Label Text="{Binding Date}" />
+ </Grid>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz24485.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz24485.xaml.cs
new file mode 100644
index 00000000..8165e8f4
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz24485.xaml.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class Bz24485Converter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value == null)
+ return null;
+
+ return new {
+ Date = DateTime.Now.ToString("dd MMMM yyyy"),
+ Object = new object ()
+ };
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public partial class Bz24485 : ContentPage
+ {
+ public Bz24485 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Bz24485 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void BindingContextWithConverter (bool useCompiledXaml)
+ {
+ var layout = new Bz24485 (useCompiledXaml);
+ layout.BindingContext = new { Data1 = new object ()};
+ Assert.Pass ();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz24910.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz24910.xaml
new file mode 100644
index 00000000..6031212c
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz24910.xaml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz24910" >
+ <StackLayout>
+ <local:Bz24910Control x:Name="control0" Text="CustomButton" NullableInt="1" NullableDouble="2.2" />
+ <local:Bz24910Control x:Name="control1" Text="CustomButton" NullableDouble="2" />
+ <local:Bz24910Control x:Name="control2" Text="CustomButton" NullableInt="{x:Null}" />
+ <local:Bz24910Control x:Name="control3" Text="CustomButton" NullableInt="{Binding .}" />
+ <Label x:Name="control4" local:Bz24910Control.AttachedNullableInt="3" />
+ <local:Bz24910Control x:Name="control5" Text="CustomButton" NullableIntProp="5" />
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz24910.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz24910.xaml.cs
new file mode 100644
index 00000000..50dad4f7
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz24910.xaml.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Bz24910 : ContentPage
+ {
+ public Bz24910 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Bz24910 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true), TestCase(false)]
+ public void AllowNullableIntProperties (bool useCompiledXaml)
+ {
+ var page = new Bz24910 (useCompiledXaml);
+ var control = page.control0;
+ Assert.AreEqual (1, control.NullableInt);
+ }
+
+ [TestCase(true), TestCase(false)]
+ public void AllowNullableDoubleProperties (bool useCompiledXaml)
+ {
+ var page = new Bz24910 (useCompiledXaml);
+ var control = page.control0;
+ Assert.AreEqual (2.2d, control.NullableDouble);
+ }
+
+ [TestCase(true), TestCase(false)]
+ public void ConversionForNullable (bool useCompiledXaml)
+ {
+ var page = new Bz24910 (useCompiledXaml);
+ var control = page.control1;
+ Assert.AreEqual (2d, control.NullableDouble);
+ }
+
+ [TestCase(true), TestCase(false)]
+ public void AllowNull (bool useCompiledXaml)
+ {
+ var page = new Bz24910 (useCompiledXaml);
+ var control = page.control2;
+ Assert.Null (control.NullableInt);
+ }
+
+ [TestCase(true), TestCase(false)]
+ public void AllowBindingToNullable (bool useCompiledXaml)
+ {
+ var page = new Bz24910 (useCompiledXaml);
+ var control = page.control3;
+ Assert.Null (control.NullableInt);
+
+ page.BindingContext = 2;
+ Assert.AreEqual (2, control.NullableInt);
+ }
+
+ [TestCase(true), TestCase(false)]
+ public void NullableAttachedBPs (bool useCompiledXaml)
+ {
+ var page = new Bz24910 (useCompiledXaml);
+ var control = page.control4;
+ Assert.AreEqual (3, Bz24910Control.GetAttachedNullableInt (control));
+ }
+
+ [TestCase(true), TestCase(false)]
+ public void AllowNonBindableNullable (bool useCompiledXaml)
+ {
+ var page = new Bz24910 (useCompiledXaml);
+ var control = page.control5;
+
+ Assert.AreEqual (5, control.NullableIntProp);
+ }
+ }
+ }
+
+ public class Bz24910Control : Button
+ {
+ public static readonly BindableProperty NullableIntProperty =
+ BindableProperty.Create ("NullableInt", typeof(int?), typeof(Bz24910Control), default(int?));
+
+ public int? NullableInt {
+ get { return (int?)GetValue (NullableIntProperty); }
+ set { SetValue (NullableIntProperty, value); }
+ }
+
+ public static readonly BindableProperty NullableDoubleProperty =
+ BindableProperty.Create ("NullableDouble", typeof(double?), typeof(Bz24910Control), default(double?));
+
+ public double? NullableDouble {
+ get { return (double?)GetValue (NullableDoubleProperty); }
+ set { SetValue (NullableDoubleProperty, value); }
+ }
+
+ public static readonly BindableProperty AttachedNullableIntProperty =
+ BindableProperty.CreateAttached<Bz24910Control, int?> (bindable => GetAttachedNullableInt (bindable), default(int?));
+
+ public static int? GetAttachedNullableInt (BindableObject bindable)
+ {
+ return (int?)bindable.GetValue (AttachedNullableIntProperty);
+ }
+
+ public static void SetAttachedNullableInt (BindableObject bindable, int? value)
+ {
+ bindable.SetValue (AttachedNullableIntProperty, value);
+ }
+
+ public int? NullableIntProp { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27299.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27299.xaml
new file mode 100644
index 00000000..fd149013
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27299.xaml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz27299"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ BindingContext="{Binding Bz27299, Source={StaticResource ViewModelLocator}}">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <local:Bz27299ViewModelLocator x:Key="ViewModelLocator" />
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ <Label x:Name="label"
+ Text="{Binding Text}" />
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27299.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27299.xaml.cs
new file mode 100644
index 00000000..35211a1b
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27299.xaml.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class Bz27299ViewModel
+ {
+ public string Text {
+ get { return "Foo"; }
+ }
+ }
+ public class Bz27299ViewModelLocator
+ {
+ public static int Count { get; set; }
+ public object Bz27299 {
+ get {
+ Count++;
+ return new Bz27299ViewModel ();
+ }
+ }
+ }
+
+ public partial class Bz27299 : ContentPage
+ {
+ public Bz27299 ()
+ {
+ InitializeComponent ();
+ }
+ public Bz27299 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [SetUp]
+ public void SetUp ()
+ {
+ Bz27299ViewModelLocator.Count = 0;
+ }
+
+ [TestCase(true)]
+ [TestCase(false)]
+ public void ViewModelLocatorOnlyCalledOnce (bool useCompiledXaml)
+ {
+ Assert.AreEqual (0, Bz27299ViewModelLocator.Count);
+ var layout = new Bz27299 (useCompiledXaml);
+ Assert.AreEqual (1, Bz27299ViewModelLocator.Count);
+ Assert.AreEqual ("Foo", layout.label.Text);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27863.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27863.xaml
new file mode 100644
index 00000000..962ede6d
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27863.xaml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz27863">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <local:ReverseConverter x:Key="reverseConverter"/>
+ <DataTemplate x:Key="SimpleMessageTemplate">
+ <ViewCell>
+ <StackLayout >
+ <Label Text="{Binding Converter={StaticResource reverseConverter}}" />
+ </StackLayout>
+ </ViewCell>
+ </DataTemplate>
+ <ListView x:Key="listview"
+ ItemTemplate="{StaticResource SimpleMessageTemplate}" />
+ </ResourceDictionary>
+ </ContentPage.Resources>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27863.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27863.xaml.cs
new file mode 100644
index 00000000..03ebaaf9
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27863.xaml.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Bz27863 : ContentPage
+ {
+ public Bz27863 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Bz27863 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void DataTemplateInResourceDictionaries (bool useCompiledXaml)
+ {
+ var layout = new Bz27863 (useCompiledXaml);
+ var listview = layout.Resources ["listview"] as ListView;
+ Assert.NotNull (listview.ItemTemplate);
+ var template = listview.ItemTemplate;
+ var cell = template.CreateContent () as ViewCell;
+ cell.BindingContext = "Foo";
+ Assert.AreEqual ("ooF", ((Label)((StackLayout)cell.View).Children [0]).Text);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27968.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27968.xaml
new file mode 100644
index 00000000..98121ab3
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27968.xaml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<local:Bz27968Page xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz27968">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <DataTemplate x:Key="template">
+ <ViewCell />
+ </DataTemplate>
+ <ListView x:Key="listView" ItemTemplate="{StaticResource template}" />
+ </ResourceDictionary>
+ </ContentPage.Resources>
+</local:Bz27968Page> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27968.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27968.xaml.cs
new file mode 100644
index 00000000..2482e9f0
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27968.xaml.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class Bz27968Page : ContentPage
+ {
+ }
+
+ public partial class Bz27968 : Bz27968Page
+ {
+ public Bz27968 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Bz27968 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void BaseClassIdentifiersAreValidForResources (bool useCompiledXaml)
+ {
+ var layout = new Bz27968 (useCompiledXaml);
+ Assert.That (layout.Resources ["listView"], Is.TypeOf<ListView> ());
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28545.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28545.xaml
new file mode 100644
index 00000000..66664011
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28545.xaml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz28545">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <Style x:Key="TitleLabel" TargetType="Label">
+ <Setter Property="AbsoluteLayout.LayoutBounds" Value="1,1,AutoSize,AutoSize" />
+ <Setter Property="AbsoluteLayout.LayoutFlags" Value="PositionProportional" />
+ <Setter Property="TextColor" Value="Pink" />
+ </Style>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ <AbsoluteLayout>
+ <Label x:Name="label"
+ Style="{StaticResource TitleLabel}" />
+ </AbsoluteLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28545.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28545.xaml.cs
new file mode 100644
index 00000000..794e7ce1
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28545.xaml.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Bz28545 : ContentPage
+ {
+ public Bz28545 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Bz28545 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void TypeConverterAreAppliedForSettersToAttachedBP (bool useCompiledXaml)
+ {
+ var layout = new Bz28545 (useCompiledXaml);
+ Assert.AreEqual (Color.Pink, layout.label.TextColor);
+ Assert.AreEqual (AbsoluteLayoutFlags.PositionProportional, AbsoluteLayout.GetLayoutFlags (layout.label));
+ Assert.AreEqual (new Rectangle (1, 1, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize), AbsoluteLayout.GetLayoutBounds (layout.label));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28556.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28556.xaml
new file mode 100644
index 00000000..4780ee23
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28556.xaml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz28556">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <Style TargetType="Entry">
+ <Setter Property="TextColor" Value="Yellow" />
+ <Setter Property="BackgroundColor" Value="Green" />
+ <Style.Triggers>
+ <Trigger TargetType="Entry" Property="IsEnabled" Value="False">
+ <Setter Property="TextColor" Value="Red" />
+ <Setter Property="BackgroundColor" Value="Purple" />
+ </Trigger>
+<!-- <Trigger TargetType="Entry" Property="IsEnabled" Value="True">
+ <Setter Property="TextColor" Value="Yellow" />
+ <Setter Property="BackgroundColor" Value="Green" />
+ </Trigger>-->
+ </Style.Triggers>
+ </Style>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ <StackLayout>
+ <Entry x:Name="entry" Text="Sample Text" />
+ <Entry x:Name="disableEntry" Text="Sample Text" IsEnabled="false" />
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28556.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28556.xaml.cs
new file mode 100644
index 00000000..dd5bb317
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28556.xaml.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Bz28556 : ContentPage
+ {
+ public Bz28556 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Bz28556 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void SettersAppliedBeforeTriggers (bool useCompiledXaml)
+ {
+ var layout = new Bz28556 (useCompiledXaml);
+
+ Assert.AreEqual (Color.Yellow, layout.entry.TextColor);
+ Assert.AreEqual (Color.Green, layout.entry.BackgroundColor);
+
+ Assert.AreEqual (Color.Red, layout.disableEntry.TextColor);
+ Assert.AreEqual (Color.Purple, layout.disableEntry.BackgroundColor);
+
+ layout.entry.IsEnabled = false;
+ layout.disableEntry.IsEnabled = true;
+
+ Assert.AreEqual (Color.Yellow, layout.disableEntry.TextColor);
+ Assert.AreEqual (Color.Green, layout.disableEntry.BackgroundColor);
+
+ Assert.AreEqual (Color.Red, layout.entry.TextColor);
+ Assert.AreEqual (Color.Purple, layout.entry.BackgroundColor);
+
+ layout.entry.IsEnabled = true;
+ layout.disableEntry.IsEnabled = false;
+
+ Assert.AreEqual (Color.Yellow, layout.entry.TextColor);
+ Assert.AreEqual (Color.Green, layout.entry.BackgroundColor);
+
+ Assert.AreEqual (Color.Red, layout.disableEntry.TextColor);
+ Assert.AreEqual (Color.Purple, layout.disableEntry.BackgroundColor);
+ }
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28689.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28689.xaml
new file mode 100644
index 00000000..e2d10dab
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28689.xaml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz28689">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <x:Array x:Key="stringArray" Type="{x:Type x:String}">
+ <x:String>Test1</x:String>
+ <x:String>Test2</x:String>
+ </x:Array>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28689.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28689.xaml.cs
new file mode 100644
index 00000000..41a8280c
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28689.xaml.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Bz28689 : ContentPage
+ {
+ public Bz28689 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Bz28689 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void XArrayInResources (bool useCompiledXaml)
+ {
+ var layout = new Bz28689 (useCompiledXaml);
+ var array = layout.Resources ["stringArray"];
+ Assert.That (array, Is.TypeOf<string[]> ());
+ var stringarray = (string[])array;
+ Assert.AreEqual (2, stringarray.Length);
+ Assert.AreEqual ("Test1", stringarray [0]);
+ Assert.AreEqual ("Test2", stringarray [1]);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28719.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28719.xaml
new file mode 100644
index 00000000..54a8b9a0
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28719.xaml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz28719">
+ <ListView x:Name="listView">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <Image Grid.Row="0" Grid.Column="0">
+ <Image.Triggers>
+ <DataTrigger TargetType="Image" Binding="{Binding IsSelected}" Value="False">
+ <Setter Property="Source" Value="Add.png" />
+ </DataTrigger>
+ <DataTrigger TargetType="Image" Binding="{Binding IsSelected}" Value="True">
+ <Setter Property="Source" Value="Remove.png" />
+ </DataTrigger>
+ </Image.Triggers>
+ </Image>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28719.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28719.xaml.cs
new file mode 100644
index 00000000..5cd1f9cb
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz28719.xaml.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Bz28719 : ContentPage
+ {
+ public Bz28719 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Bz28719 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void DataTriggerInTemplates (bool useCompiledXaml)
+ {
+ var layout = new Bz28719 (useCompiledXaml);
+ var template = layout.listView.ItemTemplate;
+ Assert.NotNull (template);
+ var cell0 = template.CreateContent () as ViewCell;
+ Assert.NotNull (cell0);
+ var image0 = cell0.View as Image;
+ Assert.NotNull (image0);
+
+ cell0.BindingContext = new {IsSelected = true};
+ Assert.AreEqual ("Remove.png", (image0.Source as FileImageSource).File);
+
+ cell0.BindingContext = new {IsSelected = false};
+ Assert.AreEqual ("Add.png", (image0.Source as FileImageSource).File);
+
+ var cell1 = template.CreateContent () as ViewCell;
+ Assert.NotNull (cell1);
+ var image1 = cell1.View as Image;
+ Assert.NotNull (image1);
+
+ cell1.BindingContext = new {IsSelected = true};
+ Assert.AreEqual ("Remove.png", (image1.Source as FileImageSource).File);
+
+ cell1.BindingContext = new {IsSelected = false};
+ Assert.AreEqual ("Add.png", (image1.Source as FileImageSource).File);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz29300.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz29300.xaml
new file mode 100644
index 00000000..39b961dc
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz29300.xaml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz29300">
+ <local:Bz29300DummyView x:Name="dummy"
+ Text="Test"
+ NumOfRepeat="4" />
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz29300.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz29300.xaml.cs
new file mode 100644
index 00000000..3548fc14
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz29300.xaml.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class Bz29300DummyView : StackLayout
+ {
+ public static readonly BindableProperty NumOfRepeatProperty =
+ BindableProperty.Create<Bz29300DummyView, int> (p => p.NumOfRepeat, 1, BindingMode.OneWay, null, UpdateTexts);
+
+ public static readonly BindableProperty TextProperty =
+ BindableProperty.Create<Bz29300DummyView, string> (p => p.Text, string.Empty, BindingMode.OneWay, null, UpdateTexts);
+
+ public int NumOfRepeat
+ {
+ get { return (int)GetValue(NumOfRepeatProperty); }
+ set { SetValue(NumOfRepeatProperty, value); }
+ }
+
+ public string Text
+ {
+ get { return (string)GetValue(TextProperty); }
+ set { SetValue(TextProperty, value); }
+ }
+
+ public Bz29300DummyView()
+ {
+ }
+
+ static void UpdateTexts(BindableObject bindable, string oldValue, string newValue)
+ {
+ var instance = bindable as Bz29300DummyView;
+ instance.Children.Clear();
+ for (int i = 0; i < instance.NumOfRepeat; i++)
+ instance.Children.Add(new Label() {Text = newValue });
+ }
+
+ static void UpdateTexts(BindableObject bindable, int oldValue, int newValue)
+ {
+ var instance = bindable as Bz29300DummyView;
+ if (oldValue == newValue)
+ return;
+ if (oldValue > newValue) {
+ for (int i = newValue; i > oldValue; i--)
+ instance.Children.RemoveAt(0);
+ } else {
+ for (int i = oldValue; i < newValue; i++)
+ instance.Children.Add(new Label() { Text = instance.Text });
+ }
+ }
+ }
+
+ public partial class Bz29300 : ContentPage
+ {
+ public Bz29300 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Bz29300 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void AccessUserDefinedBindableProperties (bool useCompiledXaml)
+ {
+ var layout = new Bz29300 (useCompiledXaml);
+ Assert.AreEqual (4, layout.dummy.NumOfRepeat);
+ Assert.AreEqual ("Test", layout.dummy.Text);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz30074.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz30074.xaml
new file mode 100644
index 00000000..85604a82
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz30074.xaml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz30074">
+ <Image x:Name="image">
+ <Image.Triggers>
+ <DataTrigger TargetType="Image" Binding="{Binding IsSelected}" Value="True">
+ <Setter Property="Source" Value="Add.png" />
+ </DataTrigger>
+ </Image.Triggers>
+ </Image>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz30074.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz30074.xaml.cs
new file mode 100644
index 00000000..e1c60feb
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz30074.xaml.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Bz30074 : ContentPage
+ {
+ public Bz30074 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Bz30074 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void DataTriggerInTemplates (bool useCompiledXaml)
+ {
+ var layout = new Bz30074 (useCompiledXaml);
+ Assert.Null (layout.image.Source);
+
+ layout.BindingContext = new {IsSelected = true};
+ Assert.AreEqual ("Add.png", ((FileImageSource)layout.image.Source).File);
+
+ layout.BindingContext = new {IsSelected = false};
+ Assert.Null (layout.image.Source);
+ }
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz30684.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz30684.xaml
new file mode 100644
index 00000000..0dff72c2
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz30684.xaml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz30684">
+ <StackLayout>
+ <Label Text="Foo" x:Name="foo" />
+ <ListView x:Name="listView">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <TextCell Text="{Binding Text, Source={x:Reference foo}}" />
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz30684.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz30684.xaml.cs
new file mode 100644
index 00000000..2b0ca827
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz30684.xaml.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Bz30684 : ContentPage
+ {
+ public Bz30684 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Bz30684 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void XReferenceFindObjectsInParentNamescopes (bool useCompiledXaml)
+ {
+ var layout = new Bz30684 (useCompiledXaml);
+ var cell = (TextCell)layout.listView.TemplatedItems.GetOrCreateContent (0, null);
+ Assert.AreEqual ("Foo", cell.Text);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/A/Bz31234.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/A/Bz31234.xaml
new file mode 100644
index 00000000..57f780a6
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/A/Bz31234.xaml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.A.Bz31234">
+ <ContentPage.Content>
+ </ContentPage.Content>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/A/Bz31234.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/A/Bz31234.xaml.cs
new file mode 100644
index 00000000..a2c1a62c
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/A/Bz31234.xaml.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests.A
+{
+ public partial class Bz31234 : ContentPage
+ {
+ public Bz31234 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Bz31234 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase(true), TestCase(false)]
+ public void ShouldPass (bool useCompiledXaml)
+ {
+ new Bz31234 (useCompiledXaml);
+ Assert.Pass ();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/B/Bz31234.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/B/Bz31234.xaml
new file mode 100644
index 00000000..4be6af22
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/B/Bz31234.xaml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.B.Bz31234">
+ <ContentPage.Content>
+ </ContentPage.Content>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/B/Bz31234.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/B/Bz31234.xaml.cs
new file mode 100644
index 00000000..b7b12be8
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31234/B/Bz31234.xaml.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Xaml.UnitTests.B
+{
+ public partial class Bz31234 : ContentPage
+ {
+ public Bz31234 ()
+ {
+ InitializeComponent ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31529.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31529.xaml
new file mode 100644
index 00000000..ebe69f8c
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31529.xaml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz31529">
+ <StackLayout>
+ <Label x:Name="label" Text="Foo" />
+ <Button x:Name="button"
+ CommandParameter = "{Binding Text, Source= {x:Reference label}}" />
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31529.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31529.xaml.cs
new file mode 100644
index 00000000..7edf9ad2
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz31529.xaml.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Bz31529 : ContentPage
+ {
+ public Bz31529 ()
+ {
+ InitializeComponent ();
+ }
+ public Bz31529 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void AllowWhiteSpacesInMarkups (bool useCompiledXaml)
+ {
+ var layout = new Bz31529 (useCompiledXaml);
+ Assert.AreEqual ("Foo", layout.button.CommandParameter);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz34037.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz34037.xaml
new file mode 100644
index 00000000..b5c36482
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz34037.xaml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz34037"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Name="PageRoot">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <local:Bz34037Converter0 x:Key="MyConverter0" />
+ <local:Bz34037Converter1 x:Key="MyConverter1" />
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ <StackLayout>
+ <Switch x:Name="s0">
+ <Switch.Triggers>
+ <MultiTrigger TargetType="Switch">
+ <MultiTrigger.Conditions>
+ <BindingCondition Value="True"
+ Binding="{Binding Property, Source={x:Reference PageRoot}, Converter={local:Bz34037Converter0}, ConverterParameter={x:Type x:String}}" />
+ </MultiTrigger.Conditions>
+ <Setter Property="Switch.IsToggled" Value="True" />
+ </MultiTrigger>
+ </Switch.Triggers>
+ </Switch>
+ <Switch x:Name="s1">
+ <Switch.Triggers>
+ <MultiTrigger TargetType="Switch">
+ <MultiTrigger.Conditions>
+ <BindingCondition Value="True"
+ Binding="{Binding Property, ConverterParameter={x:Type x:String}, Source={x:Reference PageRoot}, Converter={local:Bz34037Converter1}}" />
+ </MultiTrigger.Conditions>
+ <Setter Property="Switch.IsToggled" Value="True" />
+ </MultiTrigger>
+ </Switch.Triggers>
+ </Switch>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz34037.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz34037.xaml.cs
new file mode 100644
index 00000000..ee300cb0
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz34037.xaml.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class Bz34037Converter0 : IValueConverter, IMarkupExtension
+ {
+ public static int Invoked { get; set; }
+ public static object Parameter { get; set; }
+ public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ Invoked++;
+ Parameter = parameter;
+ return true;
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public object ProvideValue (IServiceProvider serviceProvider)
+ {
+ return new Bz34037Converter0 ();
+ }
+ }
+
+ public class Bz34037Converter1 : IValueConverter, IMarkupExtension
+ {
+ public static int Invoked { get; set; }
+ public static object Parameter { get; set; }
+ public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ Invoked++;
+ Parameter = parameter;
+ return true;
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public object ProvideValue (IServiceProvider serviceProvider)
+ {
+ return new Bz34037Converter1 ();
+ }
+ }
+
+ public partial class Bz34037 : ContentPage
+ {
+ public Bz34037 ()
+ {
+ InitializeComponent ();
+ }
+
+ public string Property {
+ get { return "FooBar"; }
+ }
+
+ public Bz34037 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [SetUp]
+ public void Setup ()
+ {
+ Bz34037Converter0.Invoked = 0;
+ Bz34037Converter1.Invoked = 0;
+ }
+
+ [TestCase(true)]
+ [TestCase(false)]
+ public void ConverterParameterOrderDoesNotMatters (bool useCompiledXaml)
+ {
+ var layout = new Bz34037 (useCompiledXaml);
+ Assert.AreEqual (2, Bz34037Converter0.Invoked);
+// Assert.AreEqual (2, Bz34037Converter1.Invoked);
+ Assert.AreEqual (typeof(string), Bz34037Converter0.Parameter);
+// Assert.AreEqual (typeof(string), Bz34037Converter1.Parameter);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz36422.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz36422.xaml
new file mode 100644
index 00000000..4a467eab
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz36422.xaml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz36422">
+ <local:Bz36422Control x:Name="control">
+ <local:Bz36422Control.Views>
+ <x:Array Type="{x:Type ContentView}">
+ <ContentView>
+ <Label Text="Page 1"/>
+ </ContentView>
+ <ContentView>
+ <Label Text="Page 2"/>
+ </ContentView>
+ <ContentView>
+ <Label Text="Page 3"/>
+ </ContentView>
+ </x:Array>
+ </local:Bz36422Control.Views>
+ </local:Bz36422Control>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz36422.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz36422.xaml.cs
new file mode 100644
index 00000000..4728068f
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz36422.xaml.cs
@@ -0,0 +1,37 @@
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class Bz36422Control : ContentView
+ {
+ public IList<ContentView> Views { get; set; }
+ }
+
+ public partial class Bz36422 : ContentPage
+ {
+ public Bz36422 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Bz36422 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void xArrayCanBeAssignedToIListT (bool useCompiledXaml)
+ {
+ var layout = new Bz36422 (useCompiledXaml);
+ Assert.AreEqual (3, layout.control.Views.Count);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz37306.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz37306.xaml
new file mode 100644
index 00000000..bfd5b732
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz37306.xaml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:sys="clr-namespace:System;assembly=mscorlib"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz37306">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <x:String x:Key="AppName">Mobile App</x:String>
+ <sys:String x:Key="ApplicationName">Mobile App</sys:String>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz37306.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz37306.xaml.cs
new file mode 100644
index 00000000..6e0d39e2
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz37306.xaml.cs
@@ -0,0 +1,31 @@
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Bz37306 : ContentPage
+ {
+ public Bz37306 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Bz37306 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void xStringInResourcesDictionaries (bool useCompiledXaml)
+ {
+ var layout = new Bz37306 (useCompiledXaml);
+ Assert.AreEqual ("Mobile App", layout.Resources ["AppName"]);
+ Assert.AreEqual ("Mobile App", layout.Resources ["ApplicationName"]);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz37524.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz37524.xaml
new file mode 100644
index 00000000..df2736a8
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz37524.xaml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz37524">
+ <StackLayout>
+ <Entry x:Name="TheEntry"
+ Text="This simulates an error"
+ TextColor="Red"/>
+ <Button x:Name="TheButton"
+ Text="Should be disabled">
+ <Button.Triggers>
+ <MultiTrigger TargetType="Button">
+ <MultiTrigger.Conditions>
+ <BindingCondition Binding="{Binding Source={x:Reference TheEntry}, Path=TextColor}"
+ Value="Red" />
+ </MultiTrigger.Conditions>
+ <Setter Property="IsEnabled" Value="False" />
+ </MultiTrigger>
+ </Button.Triggers>
+ </Button>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz37524.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz37524.xaml.cs
new file mode 100644
index 00000000..d979755d
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz37524.xaml.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Bz37524 : ContentPage
+ {
+ public Bz37524 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Bz37524 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void MultiTriggerConditionNotApplied (bool useCompiledXaml)
+ {
+ var layout = new Bz37524 (useCompiledXaml);
+ Assert.AreEqual (false, layout.TheButton.IsEnabled);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue01.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue01.xaml
new file mode 100644
index 00000000..ea92c61e
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue01.xaml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.GrialIssue01">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <FileImageSource x:Key="image">path.png</FileImageSource>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue01.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue01.xaml.cs
new file mode 100644
index 00000000..7cf20f42
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue01.xaml.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class GrialIssue01 : ContentPage
+ {
+ public GrialIssue01 ()
+ {
+ InitializeComponent ();
+ }
+
+ public GrialIssue01 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void ImplicitCastIsUsedOnFileImageSource (bool useCompiledXaml)
+ {
+ var layout = new GrialIssue01 (useCompiledXaml);
+ var res = (FileImageSource)layout.Resources ["image"];
+
+ Assert.AreEqual ("path.png", res.File);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue02.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue02.xaml
new file mode 100644
index 00000000..d623607b
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue02.xaml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.GrialIssue02">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <local:GrialIssue02Converter x:Key="converter">
+ <local:GrialIssue02Converter.TrueValue>
+ <FontAttributes>None</FontAttributes>
+ </local:GrialIssue02Converter.TrueValue>
+ <local:GrialIssue02Converter.FalseValue>
+ <FontAttributes>Bold</FontAttributes>
+ </local:GrialIssue02Converter.FalseValue>
+ </local:GrialIssue02Converter>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue02.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue02.xaml.cs
new file mode 100644
index 00000000..ca239af7
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/GrialIssue02.xaml.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using System.Globalization;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class GrialIssue02Converter : IValueConverter
+ {
+ public object FalseValue {
+ get;
+ set;
+ }
+
+ public object TrueValue {
+ get;
+ set;
+ }
+
+ public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (!(value is bool)) {
+ return null;
+ }
+ bool flag = (bool)value;
+ return (!flag) ? FalseValue : TrueValue;
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ public partial class GrialIssue02 : ContentPage
+ {
+ public GrialIssue02 ()
+ {
+ InitializeComponent ();
+ }
+ public GrialIssue02 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void BoxValueTypes (bool useCompiledXaml)
+ {
+ var layout = new GrialIssue02 (useCompiledXaml);
+ var res = (GrialIssue02Converter)layout.Resources ["converter"];
+
+ Assert.AreEqual (FontAttributes.None, res.TrueValue);
+ Assert.AreEqual (FontAttributes.Bold, res.FalseValue);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1199.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1199.xaml
new file mode 100644
index 00000000..7d6abe90
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1199.xaml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue1199">
+<ContentPage.Resources>
+ <ResourceDictionary>
+ <Color x:Key="AlmostSilver">#FFCCCCCC</Color>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1199.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1199.xaml.cs
new file mode 100644
index 00000000..18ae8731
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1199.xaml.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue1199 : ContentPage
+ {
+ public Issue1199 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue1199 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void AllowCreationOfTypesFromString (bool useCompiledXaml)
+ {
+ var layout = new Issue1199 (useCompiledXaml);
+ var res = (Color)layout.Resources ["AlmostSilver"];
+
+ Assert.AreEqual (Color.FromHex ("#FFCCCCCC"), res);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1213.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1213.xaml
new file mode 100644
index 00000000..ec149423
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1213.xaml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue1213">
+ <ContentPage Title="page 1">
+ <Label Text="page 1"
+ VerticalOptions = "LayoutOptions.CenterAndExpand"
+ HorizontalOptions = "LayoutOptions.CenterAndExpand"/>
+ </ContentPage>
+ <ContentPage Title="page 2">
+ <Label Text="page 2"
+ VerticalOptions = "LayoutOptions.CenterAndExpand"
+ HorizontalOptions = "LayoutOptions.CenterAndExpand"/>
+ </ContentPage>
+</TabbedPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1213.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1213.xaml.cs
new file mode 100644
index 00000000..d89203b7
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1213.xaml.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue1213 : TabbedPage
+ {
+ public Issue1213 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue1213 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase(false)]
+ [TestCase(true)]
+ public void MultiPageAsContentPropertyAttribute (bool useCompiledXaml)
+ {
+ var page = new Issue1213 (useCompiledXaml);
+ Assert.AreEqual (2, page.Children.Count);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1250.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1250.xaml
new file mode 100644
index 00000000..ad06901c
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1250.xaml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue1250">
+ <StackLayout x:Name="stack">
+ <Label Text="{Binding Header}" />
+ <local:Issue1250AspectRatioContainer AspectRatio="0.5">
+ <Image Source="{Binding Image}" Aspect="Fill" />
+ </local:Issue1250AspectRatioContainer>
+ <Label Text="{Binding Footer}" />
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1250.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1250.xaml.cs
new file mode 100644
index 00000000..8f4cdb7d
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1250.xaml.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class Issue1250AspectRatioContainer : ContentView
+ {
+ protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
+ {
+ return new SizeRequest(new Size(widthConstraint, widthConstraint * AspectRatio));
+ }
+
+ public double AspectRatio { get; set; }
+ }
+
+ public partial class Issue1250 : ContentPage
+ {
+ public Issue1250 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue1250 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void AddCustomElementInCollection (bool useCompiledXaml)
+ {
+ var page = new Issue1250 (useCompiledXaml);
+ var stack = page.stack;
+
+ Assert.AreEqual (3, stack.Children.Count);
+ Assert.That (stack.Children [0], Is.TypeOf<Label> ());
+ Assert.That (stack.Children [1], Is.TypeOf<Issue1250AspectRatioContainer> ());
+ Assert.That (stack.Children [2], Is.TypeOf<Label> ());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1306.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1306.xaml
new file mode 100644
index 00000000..e77a2d95
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1306.xaml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ListView xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue1306"
+ GroupDisplayBinding="{Binding Key}"
+ GroupShortNameBinding="{Binding Key}"/> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1306.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1306.xaml.cs
new file mode 100644
index 00000000..582ce102
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1306.xaml.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue1306 : ListView
+ {
+ public Issue1306 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue1306 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void AssignBindingMarkupToBindingBase (bool useCompiledXaml)
+ {
+ var listView = new Issue1306 (useCompiledXaml);
+
+ Assert.NotNull (listView.GroupDisplayBinding);
+ Assert.NotNull (listView.GroupShortNameBinding);
+ Assert.That (listView.GroupDisplayBinding, Is.TypeOf<Binding> ());
+ Assert.That (listView.GroupShortNameBinding, Is.TypeOf<Binding> ());
+ Assert.AreEqual ("Key", (listView.GroupDisplayBinding as Binding).Path);
+ Assert.AreEqual ("Key", (listView.GroupShortNameBinding as Binding).Path);
+ }
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1415.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1415.xaml
new file mode 100644
index 00000000..148704ea
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1415.xaml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue1415"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests">
+ <Label x:Name="label" Text="{Binding Converter={x:Static local:ReverseConverter.Instance}, Mode=TwoWay}"/>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1415.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1415.xaml.cs
new file mode 100644
index 00000000..b23fdb92
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1415.xaml.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue1415 : ContentPage
+ {
+ public Issue1415 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue1415 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void NestedMarkupExtension (bool useCompiledXaml)
+ {
+ var page = new Issue1415 (useCompiledXaml);
+ var label = page.FindByName<Label> ("label");
+ Assert.NotNull (label);
+ label.BindingContext = "foo";
+ Assert.AreEqual ("oof", label.Text);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1438.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1438.xaml
new file mode 100644
index 00000000..f31c52ab
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1438.xaml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue1438">
+ <StackLayout>
+ <Label BindingContext="{x:Reference slider}"
+ x:Name="label"
+ Text="{Binding Value, StringFormat='Slider value is {0:F3}'}"
+ Font="Large"
+ HorizontalOptions="Center"
+ VerticalOptions="CenterAndExpand" />
+ <Slider x:Name="slider"
+ VerticalOptions="CenterAndExpand" />
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1438.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1438.xaml.cs
new file mode 100644
index 00000000..26ee3d0b
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1438.xaml.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+using System.Diagnostics;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue1438 : ContentPage
+ {
+ public Issue1438 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue1438 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [SetUp]
+ public void Setup ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void XNameForwardDeclaration (bool useCompiledXaml)
+ {
+ var page = new Issue1438 (useCompiledXaml);
+
+ var slider = page.FindByName<Slider> ("slider");
+ var label = page.FindByName<Label> ("label");
+ Assert.AreSame (slider, label.BindingContext);
+ Assert.That (slider.Parent, Is.TypeOf<StackLayout> ());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1493.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1493.cs
new file mode 100644
index 00000000..41f00ab8
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1493.cs
@@ -0,0 +1,26 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class Issue1493
+ {
+ [Test]
+ //mostly happens in european cultures
+ [SetCulture ("fr-FR")]
+ public void CultureInvariantNumberParsing ()
+ {
+ var xaml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
+ <View
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ RelativeLayout.HeightConstraint=""{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.25}""
+ RelativeLayout.WidthConstraint=""{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.6}""/>";
+ View view = new View ();
+ view.LoadFromXaml (xaml);
+ Assert.DoesNotThrow (() => view.LoadFromXaml (xaml));
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1497.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1497.cs
new file mode 100644
index 00000000..3813f73a
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1497.cs
@@ -0,0 +1,27 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class Issue1497
+ {
+ [Test]
+ public void BPCollectionsWithSingleElement ()
+ {
+ var xaml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
+ <Grid
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml"">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width=""*""/>
+ </Grid.ColumnDefinitions>
+ </Grid>";
+
+ var grid = new Grid ().LoadFromXaml (xaml);
+ Assert.AreEqual (1, grid.ColumnDefinitions.Count);
+ Assert.True (grid.ColumnDefinitions [0].Width.IsStar);
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1501.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1501.cs
new file mode 100644
index 00000000..d4a5e761
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1501.cs
@@ -0,0 +1,41 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class BoxView1501 : BoxView
+ {
+ public bool Fired { get; set;}
+
+ public void OnBoxViewTapped (object sender, EventArgs e)
+ {
+ Fired = true;
+ }
+ }
+
+ [TestFixture]
+ public class Issue1501
+ {
+ [Test]
+ public void ConnectEventsInGestureRecognizers ()
+ {
+ var xaml = @"
+ <BoxView
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ x:Class=""Xamarin.Forms.Xaml.UnitTests.BoxView1501"" >
+ <BoxView.GestureRecognizers>
+ <TapGestureRecognizer Tapped=""OnBoxViewTapped"" />
+ </BoxView.GestureRecognizers>
+ </BoxView>";
+
+ BoxView1501 layout = null;
+ Assert.DoesNotThrow (() => {layout = new BoxView1501 ().LoadFromXaml (xaml);});
+
+ Assert.False (layout.Fired);
+ var tgr = layout.GestureRecognizers [0] as TapGestureRecognizer;
+ tgr.SendTapped (layout);
+ Assert.True (layout.Fired);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1545.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1545.cs
new file mode 100644
index 00000000..00747db4
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1545.cs
@@ -0,0 +1,174 @@
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class Issue1545
+ {
+ [Test]
+ public void BindingCanNotBeReused()
+ {
+ string xaml = @"<ContentPage xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ x:Class=""Xamarin.Forms.Controls.Issue1545"">
+ <ListView x:Name=""List"" ItemsSource=""{Binding}"">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <TextCell Text=""{Binding}"" />
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </ContentPage>";
+
+ ContentPage page = new ContentPage().LoadFromXaml (xaml);
+
+ var items = new[] { "Fu", "Bar" };
+ page.BindingContext = items;
+
+ ListView lv = page.FindByName<ListView> ("List");
+
+ TextCell cell = (TextCell)lv.TemplatedItems.GetOrCreateContent (0, items[0]);
+ Assert.That (cell.Text, Is.EqualTo ("Fu"));
+
+ cell = (TextCell)lv.TemplatedItems.GetOrCreateContent (1, items[1]);
+ Assert.That (cell.Text, Is.EqualTo ("Bar"));
+ }
+
+ [Test]
+ public void ElementsCanNotBeReused()
+ {
+ string xaml = @"<ContentPage xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ x:Class=""Xamarin.Forms.Controls.Issue1545"">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <Color x:Key=""color"">#ff00aa</Color>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+
+ <ListView x:Name=""List"" ItemsSource=""{Binding}"">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <StackLayout>
+ <Label Text=""{Binding}"" BackgroundColor=""{StaticResource color}""/>
+ </StackLayout>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </ContentPage>";
+
+ ContentPage page = new ContentPage().LoadFromXaml (xaml);
+
+ var items = new[] { "Fu", "Bar" };
+ page.BindingContext = items;
+
+ ListView lv = page.FindByName<ListView> ("List");
+
+ ViewCell cell0 = (ViewCell)lv.TemplatedItems.GetOrCreateContent (0, items[0]);
+
+
+ Assert.That (((Label)((StackLayout)cell0.View).Children[0]).Text, Is.EqualTo ("Fu"));
+
+ ViewCell cell1 = (ViewCell)lv.TemplatedItems.GetOrCreateContent (1, items[1]);
+ Assert.That (((Label)((StackLayout)cell1.View).Children[0]).Text, Is.EqualTo ("Bar"));
+
+ Assert.AreNotSame (cell0, cell1);
+ Assert.AreNotSame (cell0.View, cell1.View);
+ Assert.AreNotSame (((StackLayout)cell0.View).Children [0], ((StackLayout)cell1.View).Children [0]);
+ Assert.AreEqual (Color.FromHex ("ff00aa"), ((StackLayout)cell1.View).Children [0].BackgroundColor);
+ }
+
+ [Test]
+ public void ElementsFromCollectionsAreNotReused ()
+ {
+ var xaml = @"<ListView
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests""
+ ItemsSource=""{Binding}"">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <local:ViewCellWithCollection>
+ <local:ViewCellWithCollection.Children>
+ <local:ViewList>
+ <Label />
+ <Label />
+ </local:ViewList>
+ </local:ViewCellWithCollection.Children>
+ </local:ViewCellWithCollection>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>";
+
+ var listview = new ListView ();
+ var items = new [] { "Foo", "Bar", "Baz" };
+ listview.BindingContext = items;
+ listview.LoadFromXaml (xaml);
+ var cell0 = (ViewCellWithCollection)listview.TemplatedItems.GetOrCreateContent (0, items[0]);
+ var cell1 = (ViewCellWithCollection)listview.TemplatedItems.GetOrCreateContent (1, items[1]);
+
+ Assert.AreNotSame (cell0, cell1);
+ Assert.AreNotSame (cell0.Children, cell1.Children);
+ Assert.AreNotSame (cell0.Children[0], cell1.Children[0]);
+
+ }
+
+ [Test]
+ public void ResourcesDeclaredInDataTemplatesAreNotShared ()
+ {
+ var xaml = @"<ListView
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ xmlns:sys=""clr-namespace:System;assembly=mscorlib""
+ ItemsSource=""{Binding}"">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <Label Text=""{Binding}"">
+ <Label.Resources>
+ <ResourceDictionary>
+ <sys:Object x:Key=""object""/>
+ </ResourceDictionary>
+ </Label.Resources>
+ </Label>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>";
+
+ var listview = new ListView ();
+ var items = new [] { "Foo", "Bar", "Baz" };
+ listview.BindingContext = items;
+
+ listview.LoadFromXaml (xaml);
+ var cell0 = (ViewCell)listview.TemplatedItems.GetOrCreateContent (0, items[0]);
+ var cell1 = (ViewCell)listview.TemplatedItems.GetOrCreateContent (1, items[1]);
+ Assert.AreNotSame (cell0, cell1);
+
+ var label0 = (Label)cell0.View;
+ var label1 = (Label)cell1.View;
+ Assert.AreNotSame (label0, label1);
+ Assert.AreEqual ("Foo", label0.Text);
+ Assert.AreEqual ("Bar", label1.Text);
+
+ var res0 = label0.Resources;
+ var res1 = label1.Resources;
+ Assert.AreNotSame (res0, res1);
+
+ var obj0 = res0 ["object"];
+ var obj1 = res1 ["object"];
+
+ Assert.NotNull (obj0);
+ Assert.NotNull (obj1);
+
+ Assert.AreNotSame (obj0, obj1);
+ }
+ }
+
+ public class ViewCellWithCollection : ViewCell
+ {
+ public ViewList Children { get; set; }
+ }
+}
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1549.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1549.cs
new file mode 100644
index 00000000..c1253040
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1549.cs
@@ -0,0 +1,166 @@
+using System;
+using NUnit.Framework;
+using System.Collections.ObjectModel;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+
+ public class SeverityColorConverter : IValueConverter
+ {
+
+ public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ count++;
+ return Color.Blue;
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException ();
+ }
+
+
+ public static int count=0;
+ }
+
+ public class InvertBoolenConverter : IValueConverter
+ {
+ public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ count++;
+ if (value is bool) {
+
+ return !(bool)value;
+ }
+ return value;
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException ();
+ }
+ public static int count=0;
+ }
+
+ public class Item
+ {
+ public bool IsLocked {
+ get;
+ set;
+ }
+ }
+
+ [TestFixture]
+ public class Issue1549
+ {
+ [SetUp]
+ public void Setup ()
+ {
+ SeverityColorConverter.count = 0;
+ InvertBoolenConverter.count = 0;
+ }
+
+ [Test]
+ public void ConverterIsInvoked ()
+ {
+ var xaml = @"
+<ContentPage
+xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"">
+
+<ContentPage.Resources>
+<ResourceDictionary>
+<local:SeverityColorConverter x:Key=""SeverityColorConverter"" />
+</ResourceDictionary>
+</ContentPage.Resources>
+ <Label Text=""{Binding value, StringFormat='{0}'}""
+ WidthRequest=""50""
+ TextColor=""Black""
+ x:Name=""label""
+ BackgroundColor=""{Binding Severity, Converter={StaticResource SeverityColorConverter}}""
+ XAlign=""Center"" YAlign=""Center""/>
+</ContentPage>";
+
+ var layout = new ContentPage ().LoadFromXaml (xaml);
+ layout.BindingContext = new {Value = "Foo", Severity = "Bar"};
+ var label = layout.FindByName<Label> ("label");
+ Assert.AreEqual (Color.Blue, label.BackgroundColor);
+ Assert.AreEqual (1, SeverityColorConverter.count);
+ }
+
+ [Test]
+ public void ResourcesInNonXFBaseClassesAreFound ()
+ {
+ var xaml = @"<local:BaseView
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests""
+ Padding=""0,40,0,0"">
+ <local:BaseView.Resources>
+ <ResourceDictionary>
+ <local:InvertBoolenConverter x:Key=""cnvInvert""></local:InvertBoolenConverter>
+ </ResourceDictionary>
+ </local:BaseView.Resources>
+ <local:BaseView.Content>
+ <ListView x:Name=""lst"" VerticalOptions=""FillAndExpand""
+ HorizontalOptions=""FillAndExpand""
+
+ ItemsSource=""{Binding Items}""
+
+ >
+ <ListView.ItemTemplate >
+ <DataTemplate>
+ <ViewCell >
+ <ViewCell.View>
+ <Grid VerticalOptions=""FillAndExpand"" HorizontalOptions=""FillAndExpand"" >
+ <Label IsVisible=""{Binding IsLocked}"" Text=""Show Is Locked"" />
+ <Label IsVisible=""{Binding IsLocked, Converter={StaticResource cnvInvert}}"" Text=""Show Is Not locked"" />
+ </Grid>
+ </ViewCell.View>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </local:BaseView.Content>
+</local:BaseView>";
+ var page = new Issue1549Page ().LoadFromXaml (xaml);
+ var lst = page.FindByName<ListView> ("lst");
+ ObservableCollection<Item> items;
+ lst.BindingContext = new {
+ Items = items = new ObservableCollection<Item> {
+ new Item { IsLocked = true},
+ new Item { IsLocked = false},
+ new Item { IsLocked = true},
+ new Item { IsLocked = true},
+ },
+ };
+
+ var cell0 = (ViewCell)lst.TemplatedItems.GetOrCreateContent (0, items [0]);
+ var cell1 = (ViewCell)lst.TemplatedItems.GetOrCreateContent (1, items [1]);
+ var cell2 = (ViewCell)lst.TemplatedItems.GetOrCreateContent (2, items [2]);
+ var cell3 = (ViewCell)lst.TemplatedItems.GetOrCreateContent (3, items [3]);
+
+ var label00 = (cell0.View as Grid).Children [0] as Label;
+ var label01 = (cell0.View as Grid).Children [1] as Label;
+
+ Assert.AreEqual ("Show Is Locked", label00.Text);
+ Assert.AreEqual ("Show Is Not locked", label01.Text);
+
+ Assert.AreEqual (true, label00.IsVisible);
+ Assert.AreEqual (false, label01.IsVisible);
+
+ Assert.AreEqual (4, InvertBoolenConverter.count);
+
+ }
+ }
+
+ public class BaseView : ContentPage
+ {
+ }
+
+ public partial class Issue1549Page : BaseView
+ {
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1554.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1554.cs
new file mode 100644
index 00000000..2e7bfa91
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1554.cs
@@ -0,0 +1,53 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class Issue1554
+ {
+ [Test]
+ public void CollectionItemsInDataTemplate ()
+ {
+ var xaml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
+ <ListView
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ ItemsSource=""{Binding}"">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <ViewCell.View>
+ <StackLayout>
+ <Label Text=""{Binding}""></Label>
+ <Label Text=""{Binding}""></Label>
+ </StackLayout>
+ </ViewCell.View>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>";
+ var listview = new ListView ();
+ var items = new [] { "Foo", "Bar", "Baz" };
+ listview.BindingContext = items;
+
+ listview.LoadFromXaml (xaml);
+
+ ViewCell cell0 = null;
+ Assert.DoesNotThrow (() => {
+ cell0 = (ViewCell)listview.TemplatedItems.GetOrCreateContent (0, items [0]);
+ });
+ ViewCell cell1 = null;
+ Assert.DoesNotThrow (() => {
+ cell1 = (ViewCell)listview.TemplatedItems.GetOrCreateContent (1, items [1]);
+ });
+
+ Assert.AreNotSame (cell0, cell1);
+ Assert.AreNotSame (cell0.View, cell1.View);
+ Assert.AreNotSame (((StackLayout)cell0.View).Children [0], ((StackLayout)cell1.View).Children [0]);
+ Assert.AreNotSame (((StackLayout)cell0.View).Children [1], ((StackLayout)cell1.View).Children [1]);
+
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1564.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1564.cs
new file mode 100644
index 00000000..895eb900
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1564.cs
@@ -0,0 +1,29 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class Issue1564
+ {
+ [Test]
+ public void ViewCellAsXamlRoot ()
+ {
+ var xaml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
+ <ViewCell
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ x:Class=""m.transport.VehicleCell"">
+ <ViewCell.View>
+ <StackLayout>
+ <Label Text=""This is my label""></Label>
+ </StackLayout>
+ </ViewCell.View>
+ </ViewCell>";
+ var cell = new ViewCell ().LoadFromXaml (xaml);
+ Assert.NotNull (cell);
+ Assert.AreEqual ("This is my label", ((cell.View as StackLayout).Children [0] as Label).Text);
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1594.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1594.cs
new file mode 100644
index 00000000..cd942319
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1594.cs
@@ -0,0 +1,43 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class Issue1594
+ {
+ [Test]
+ public void OnPlatformForButtonHeight ()
+ {
+ var xaml = @"
+ <Button
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ xmlns:sys=""clr-namespace:System;assembly=mscorlib""
+ x:Name=""activateButton"" Text=""ACTIVATE NOW"" TextColor=""White"" BackgroundColor=""#00A0FF"">
+ <Button.HeightRequest>
+ <OnPlatform x:TypeArguments=""sys:Double""
+ iOS=""33""
+ Android=""44""
+ WinPhone=""44"" />
+ </Button.HeightRequest>
+ </Button>";
+
+ Device.OS = TargetPlatform.iOS;
+ var button = new Button ().LoadFromXaml (xaml);
+ Assert.AreEqual (33, button.HeightRequest);
+
+ Device.OS = TargetPlatform.Android;
+ button = new Button ().LoadFromXaml (xaml);
+ Assert.AreEqual (44, button.HeightRequest);
+
+ Device.OS = TargetPlatform.WinPhone;
+ button = new Button ().LoadFromXaml (xaml);
+ Assert.AreEqual (44, button.HeightRequest);
+
+
+ }
+
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1637.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1637.cs
new file mode 100644
index 00000000..f6083fb1
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1637.cs
@@ -0,0 +1,25 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class Issue1637
+ {
+ [Test]
+ public void ImplicitCollectionWithSingleElement ()
+ {
+ var xaml = @"
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height=""*"" />
+ </Grid.RowDefinitions>
+ </Grid>";
+ var grid = new Grid ();
+ Assert.DoesNotThrow(()=> grid.LoadFromXaml<Grid> (xaml));
+ Assert.AreEqual (1, grid.RowDefinitions.Count);
+ Assert.IsTrue (grid.RowDefinitions [0].Height.IsStar);
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1641.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1641.cs
new file mode 100644
index 00000000..3809c16d
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1641.cs
@@ -0,0 +1,38 @@
+using System;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class Issue1641
+ {
+ [Test]
+ public void StaticResourceInTableView ()
+ {
+ var xaml = @"
+ <ContentPage
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml"">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <x:String x:Key=""caption"" >Hello there!</x:String>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+
+ <TableView>
+ <TableRoot Title=""x"">
+ <TableSection Title=""y"">
+ <TextCell Text=""{StaticResource caption}"" />
+ </TableSection>
+ </TableRoot>
+ </TableView>
+ </ContentPage>";
+ var page = new ContentPage ().LoadFromXaml (xaml);
+ var table = page.Content as TableView;
+ Assert.AreEqual ("Hello there!", page.Resources ["caption"] as string);
+ Assert.AreEqual ("Hello there!", (table.Root [0] [0] as TextCell).Text);
+
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1794.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1794.cs
new file mode 100644
index 00000000..d0b6eb96
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue1794.cs
@@ -0,0 +1,58 @@
+using System;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class Issue1794
+ {
+ [Test]
+ public void FindNameInDT ()
+ {
+ var xaml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
+ <ContentPage xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ xmlns:local=""clr-namespace:XamarinFormsXamlSample;assembly=XamarinFormsXamlSample""
+ xmlns:constants=""clr-namespace:XamarinFormsSample;assembly=XamarinFormsXamlSample""
+ x:Class=""UxDemoAppXF.Layouts.Menu""
+ Title=""Employee List"">
+
+ <ListView x:Name=""listView""
+ IsVisible=""true""
+ ItemsSource=""{Binding MenuItems}""
+ SelectedItem=""{Binding ListItemSelected}"">
+
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <RelativeLayout>
+ <Label x:Name=""LinkText""
+ Text=""{Binding Name}""
+ RelativeLayout.XConstraint=
+ ""{ConstraintExpression Type=RelativeToParent,
+ Property=Width,
+ Factor=0.5}""/>
+ <Image x:Name=""LinkImage""
+ Source=""{Binding ImageSource}""
+ RelativeLayout.XConstraint=
+ ""{ConstraintExpression Type=RelativeToView,
+ Property=Width,
+ ElementName=LinkText,
+ Constant=5}""/>
+
+
+ </RelativeLayout>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </ContentPage>";
+ var layout = new ContentPage ().LoadFromXaml (xaml);
+ var list = layout.FindByName<ListView> ("listView");
+ var item0 = list.TemplatedItems.GetOrCreateContent (0, null);
+ var item1 = list.TemplatedItems.GetOrCreateContent (1, null);
+ Assert.Pass ();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2016.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2016.xaml
new file mode 100644
index 00000000..012427cd
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2016.xaml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Forms.Xaml.UnitTests.Issue2016">
+ <StackLayout>
+ <Switch x:Name="a0" />
+ <Switch x:Name="b0" />
+ <Switch x:Name="s0">
+ <Switch.Triggers>
+ <MultiTrigger TargetType="Switch">
+ <MultiTrigger.Conditions>
+ <BindingCondition Binding="{Binding Source={x:Reference a0}, Path=IsToggled}" Value="True" />
+ <BindingCondition Binding="{Binding Source={x:Reference b0}, Path=IsToggled}" Value="True" />
+ </MultiTrigger.Conditions>
+ <Setter Property="Switch.IsToggled" Value="True" />
+ </MultiTrigger>
+ </Switch.Triggers>
+ </Switch>
+ <Switch x:Name="t0">
+ <Switch.Triggers>
+ <DataTrigger TargetType="Switch" Binding="{Binding Source={x:Reference a0}, Path=IsToggled}" Value="True">
+ <Setter Property="Switch.IsToggled" Value="True" />
+ </DataTrigger>
+ </Switch.Triggers>
+ </Switch>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2016.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2016.xaml.cs
new file mode 100644
index 00000000..89c6964f
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2016.xaml.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue2016 : ContentPage
+ {
+ public Issue2016 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue2016 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [SetUp]
+ public void Setup ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestSwitches (bool useCompiledXaml)
+ {
+ var page = new Issue2016 (useCompiledXaml);
+ Assert.AreEqual (false, page.a0.IsToggled);
+ Assert.AreEqual (false, page.b0.IsToggled);
+ Assert.AreEqual (false, page.s0.IsToggled);
+ Assert.AreEqual (false, page.t0.IsToggled);
+
+ page.a0.IsToggled = true;
+ page.b0.IsToggled = true;
+
+ Assert.AreEqual (true, page.s0.IsToggled);
+ Assert.AreEqual (true, page.t0.IsToggled);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2062.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2062.xaml
new file mode 100644
index 00000000..e756d4a5
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2062.xaml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue2062">
+ <StackLayout>
+ <Label x:Name="label1">
+ <Label.Text>text explicitly set to Label.Text</Label.Text>
+ </Label>
+ <Label x:Name="label2">text implicitly set to Text property of Label</Label>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2062.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2062.xaml.cs
new file mode 100644
index 00000000..ff756756
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2062.xaml.cs
@@ -0,0 +1,32 @@
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue2062 : ContentPage
+ {
+ public Issue2062 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue2062 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void LabelWithoutExplicitPropertyElement (bool useCompiledXaml)
+ {
+ var layout = new Issue2062 (useCompiledXaml);
+ Assert.AreEqual ("text explicitly set to Label.Text", layout.label1.Text);
+ Assert.AreEqual ("text implicitly set to Text property of Label", layout.label2.Text);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2114.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2114.xaml
new file mode 100644
index 00000000..8a6917dc
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2114.xaml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Application
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue2114"
+ >
+ <Application.Resources>
+ <ResourceDictionary>
+ <!-- buttons -->
+ <Style x:Key="ButtonStyle" TargetType="Button">
+ <Setter Property="BorderRadius" Value="0"/>
+ <Setter Property="HeightRequest" Value="42"/>
+ </Style>
+ <Style x:Key="NavButtonBlueStyle" BasedOn="{StaticResource ButtonStyle}" TargetType="Button">
+ </Style>
+ <Style x:Key="NavButtonGrayStyle" BasedOn="{StaticResource ButtonStyle}" TargetType="Button">
+ </Style>
+ </ResourceDictionary>
+ </Application.Resources>
+</Application> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2114.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2114.xaml.cs
new file mode 100644
index 00000000..66aeac54
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2114.xaml.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms;
+
+using NUnit.Framework;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue2114 : Application
+ {
+ public Issue2114 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue2114 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [SetUp]
+ public void SetUp ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+
+ Current = null;
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void StaticResourceOnApplication (bool useCompiledXaml)
+ {
+ Issue2114 app;
+ Assert.DoesNotThrow (() => app = new Issue2114 (useCompiledXaml));
+
+ Assert.True (Current.Resources.ContainsKey ("ButtonStyle"));
+ Assert.True (Current.Resources.ContainsKey ("NavButtonBlueStyle"));
+ Assert.True (Current.Resources.ContainsKey ("NavButtonGrayStyle"));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2125.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2125.xaml
new file mode 100644
index 00000000..c2bc239c
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2125.xaml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Forms.Xaml.UnitTests.Issue2125">
+ <StackLayout>
+ <Label x:Name="label"/>
+ <Label x:Name="label"/>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2125.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2125.xaml.cs
new file mode 100644
index 00000000..8c4dcf80
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2125.xaml.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue2125 : ContentPage
+ {
+ public Issue2125 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue2125 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void DuplicatexName (bool useCompiledXaml)
+ {
+ Assert.Throws (new XamlParseExceptionConstraint (5, 10), () => new Issue2125 (useCompiledXaml));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2152.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2152.xaml
new file mode 100644
index 00000000..4614fafb
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2152.xaml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Forms.Xaml.UnitTests.Issue2152">
+ <ListView ItemsSource="{Binding MyItems}" x:Name="listview">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <StackLayout Orientation="Horizontal">
+ <Label Text="{Binding Reference}"/>
+ <Button Clicked="OnButtonClicked" Text=">>>" IsVisible="{Binding ShowButton}" x:Name="btn" />
+ </StackLayout>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2152.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2152.xaml.cs
new file mode 100644
index 00000000..7062074a
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2152.xaml.cs
@@ -0,0 +1,52 @@
+using System;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue2152 : ContentPage
+ {
+ public Issue2152 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue2152 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ int clickcount;
+ public void OnButtonClicked(object sender, EventArgs e)
+ {
+ clickcount++;
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [SetUp]
+ public void Setup ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestEventConnection (bool useCompiledXaml)
+ {
+ Issue2152 layout = null;
+ Assert.DoesNotThrow (() => layout = new Issue2152 (useCompiledXaml));
+ Cell cell = null;
+ Assert.DoesNotThrow (() => cell = layout.listview.TemplatedItems.GetOrCreateContent (0, null));
+ var button = cell.FindByName<Button> ("btn") as IButtonController;
+ Assert.AreEqual (0, layout.clickcount);
+ button.SendClicked ();
+ Assert.AreEqual (1, layout.clickcount);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml
new file mode 100644
index 00000000..385619e5
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue2450">
+ <StackLayout>
+ <Label x:Name="label0"/>
+ <Label x:Name="label0"/>
+ </StackLayout>
+</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml.cs
new file mode 100644
index 00000000..0cf6f56c
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml.cs
@@ -0,0 +1,37 @@
+using Xamarin.Forms;
+
+using NUnit.Framework;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue2450 : ContentPage
+ {
+ public Issue2450 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue2450 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [SetUp]
+ public void Setup ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void ThrowMeaningfulExceptionOnDuplicateXName (bool useCompiledXaml)
+ {
+ Assert.Throws (new XamlParseExceptionConstraint (8, 10, m => m == "An element with the name \"label0\" already exists in this NameScope"), () => new Issue2450 (useCompiledXaml));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2489.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2489.xaml
new file mode 100644
index 00000000..58629e6e
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2489.xaml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue2489">
+ <local:WImage Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" HeightRequest="150" x:Name="wimage">
+ <local:WImage.Source>
+ <UriImageSource Uri="{Binding ImageUrl}" />
+ </local:WImage.Source>
+ <local:WImage.Triggers>
+ <DataTrigger TargetType="{x:Type local:WImage}" Binding="{Binding ImageUrl}" Value="{x:Null}" >
+ <Setter Property="IsVisible" Value="False" />
+ </DataTrigger>
+ </local:WImage.Triggers>
+ </local:WImage>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2489.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2489.xaml.cs
new file mode 100644
index 00000000..ad79298e
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2489.xaml.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Linq;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue2489 : ContentPage
+ {
+ public Issue2489 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue2489 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [SetUp]
+ public void SetUp ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void DataTriggerTargetType (bool useCompiledXaml)
+ {
+ var layout = new Issue2489 (useCompiledXaml);
+ Assert.NotNull (layout.wimage);
+ Assert.NotNull (layout.wimage.Triggers);
+ Assert.True (layout.wimage.Triggers.Any ());
+ Assert.That (layout.wimage.Triggers [0], Is.TypeOf<DataTrigger> ());
+ var trigger = (DataTrigger)layout.wimage.Triggers [0];
+ Assert.AreEqual (typeof(WImage), trigger.TargetType);
+ }
+ }
+ }
+
+ public class WImage: View
+ {
+ public ImageSource Source { get; set; }
+ public Aspect Aspect { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2578.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2578.xaml
new file mode 100644
index 00000000..cedfbc83
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2578.xaml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue2578">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <Style x:Key="labelStyle" TargetType="Label">
+ <Style.Triggers>
+ <Trigger Property="Text" TargetType="Label" Value="Foo">
+ <Setter Property="BackgroundColor" Value="Red" />
+ </Trigger>
+ <Trigger Property="Font" TargetType="Label" Value="Small">
+ <Setter Property="TextColor" Value="Olive" />
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ <Label x:Name="label" Font="Small" Style="{StaticResource labelStyle}" />
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2578.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2578.xaml.cs
new file mode 100644
index 00000000..62e54cd7
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2578.xaml.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue2578 : ContentPage
+ {
+ public Issue2578 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue2578 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [SetUp]
+ public void Setup ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void MultipleTriggers (bool useCompiledXaml)
+ {
+ Issue2578 layout = null;
+ Assert.DoesNotThrow (() => layout = new Issue2578 (useCompiledXaml));
+
+ Assert.AreEqual (null, layout.label.Text);
+ Assert.AreEqual (Color.Default, layout.label.BackgroundColor);
+ Assert.AreEqual (Color.Olive, layout.label.TextColor);
+ layout.label.Text = "Foo";
+ Assert.AreEqual (Color.Red, layout.label.BackgroundColor);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2659.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2659.xaml
new file mode 100644
index 00000000..6e292469
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2659.xaml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue2659">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <Style x:Key="buttonStyle" TargetType="Button">
+ <Setter Property="HorizontalOptions" Value="Center" />
+ <Setter Property="VerticalOptions" Value="CenterAndExpand" />
+ <Setter Property="FontSize" Value="Large" />
+ <Setter Property="TextColor" Value="Blue" />
+ <Setter Property="FontAttributes" Value="Italic" />
+ </Style>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+
+ <StackLayout x:Name="stackLayout">
+ <Button Text="Set Style from Resource"
+ Clicked="OnSetStyleButtonClicked"
+ x:Name="button0"/>
+
+ <Button Text="Set Style to null"
+ Clicked="OnUnsetStyleButtonClicked"
+ x:Name="button1"/>
+
+ <Button Text="Set Local Properties"
+ Clicked="OnSetLocalButtonClicked"
+ x:Name="button2"/>
+
+ <Button Text="Clear Local Properties"
+ Clicked="OnClearLocalButtonClicked"
+ x:Name="button3"/>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2659.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2659.xaml.cs
new file mode 100644
index 00000000..8372c50d
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2659.xaml.cs
@@ -0,0 +1,131 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue2659 : ContentPage
+ {
+ public Issue2659 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue2659 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ void OnSetStyleButtonClicked(object sender, EventArgs args)
+ {
+ Style style = (Style)Resources["buttonStyle"];
+ SetButtonStyle(style);
+ }
+
+ void OnUnsetStyleButtonClicked(object sender, EventArgs args)
+ {
+ SetButtonStyle (null);
+ }
+
+ void OnSetLocalButtonClicked(object sender, EventArgs args)
+ {
+ EnumerateButtons ((Button button) => {
+ button.TextColor = Color.Red;
+ button.FontAttributes = FontAttributes.Bold;
+ });
+ }
+
+ void OnClearLocalButtonClicked(object sender, EventArgs args)
+ {
+ EnumerateButtons ((Button button) => {
+ button.ClearValue (Button.TextColorProperty);
+ button.ClearValue (Button.FontAttributesProperty);
+ });
+ }
+
+ void SetButtonStyle(Style style)
+ {
+ EnumerateButtons (button => {
+ button.Style = style;
+ });
+ }
+
+ void EnumerateButtons(Action<Button> action)
+ {
+ foreach (View view in stackLayout.Children)
+ action ((Button)view);
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [SetUp]
+ public void SetUp ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ void AssertStyleApplied (Button button)
+ {
+ Assert.AreEqual (LayoutOptions.Center, button.HorizontalOptions);
+ Assert.AreEqual (LayoutOptions.CenterAndExpand, button.VerticalOptions);
+ Assert.AreEqual (16, button.FontSize);
+ Assert.AreEqual (Color.Blue, button.TextColor);
+ Assert.AreEqual (FontAttributes.Italic, button.FontAttributes);
+ }
+
+ void AssertStyleUnApplied (Button button)
+ {
+ Assert.AreEqual (View.HorizontalOptionsProperty.DefaultValue, button.HorizontalOptions);
+ Assert.AreEqual (View.VerticalOptionsProperty.DefaultValue, button.VerticalOptions);
+ Assert.AreEqual (10, button.FontSize);
+ Assert.AreEqual (Button.TextColorProperty.DefaultValue, button.TextColor);
+ Assert.AreEqual (Button.FontAttributesProperty.DefaultValue, button.FontAttributes);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetUnsetStyleFromResource (bool useCompiledXaml)
+ {
+ var layout = new Issue2659 (useCompiledXaml);
+ layout.EnumerateButtons (AssertStyleUnApplied);
+
+ ((IButtonController)layout.button0).SendClicked ();
+ layout.EnumerateButtons (AssertStyleApplied);
+
+ ((IButtonController)layout.button1).SendClicked ();
+ layout.EnumerateButtons (AssertStyleUnApplied);
+ }
+
+ void AssertPropertiesApplied (Button button)
+ {
+ Assert.AreEqual (Color.Red, button.TextColor);
+ Assert.AreEqual (FontAttributes.Bold, button.FontAttributes);
+ }
+
+ void AssertPropertiesUnApplied (Button button)
+ {
+ Assert.AreEqual (Button.TextColorProperty.DefaultValue, button.TextColor);
+ Assert.AreEqual (Button.FontAttributesProperty.DefaultValue, button.FontAttributes);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SetUnsetLocalProperties (bool useCompiledXaml)
+ {
+ var layout = new Issue2659 (useCompiledXaml);
+ layout.EnumerateButtons (AssertPropertiesUnApplied);
+
+ ((IButtonController)layout.button2).SendClicked ();
+ layout.EnumerateButtons (AssertPropertiesApplied);
+
+ ((IButtonController)layout.button3).SendClicked ();
+ layout.EnumerateButtons (AssertPropertiesUnApplied);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2742.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2742.xaml
new file mode 100644
index 00000000..d4dc6fc6
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2742.xaml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<local:Issue2742BasePage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue2742">
+ <ContentPage.ToolbarItems>
+ <ToolbarItem Name="One"></ToolbarItem>
+ <ToolbarItem Name="Two"></ToolbarItem>
+ </ContentPage.ToolbarItems>
+ <ContentPage.Content>
+ <Label Text="test"></Label>
+ </ContentPage.Content>
+</local:Issue2742BasePage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2742.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2742.xaml.cs
new file mode 100644
index 00000000..ba69280d
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2742.xaml.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class Issue2742BasePage : ContentPage
+ {
+
+ }
+
+ public partial class Issue2742 : Issue2742BasePage
+ {
+ public Issue2742 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue2742 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void ToolBarItemsOnContentPageInheritors (bool useCompiledXaml)
+ {
+ var layout = new Issue2742 (useCompiledXaml);
+ Assert.That (layout.Content, Is.TypeOf<Label> ());
+ Assert.AreEqual ("test", ((Label)layout.Content).Text);
+
+ Assert.NotNull (layout.ToolbarItems);
+ Assert.AreEqual (2, layout.ToolbarItems.Count);
+ Assert.AreEqual ("One", layout.ToolbarItems [0].Name);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3076.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3076.xaml
new file mode 100644
index 00000000..61e25f04
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3076.xaml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ xmlns:controls="clr-namespace:Xamarin.Forms.Controls;assembly=Xamarin.Forms.Controls"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue3076">
+ <StackLayout>
+ <local:Issue3076Button VerticalContentAlignment="Start" x:Name="local"/>
+ <controls:Issue3076Button HorizontalContentAlignment="Start" x:Name="controls" />
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3076.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3076.xaml.cs
new file mode 100644
index 00000000..e44a1349
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3076.xaml.cs
@@ -0,0 +1,55 @@
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class Issue3076Button : Button
+ {
+ public static readonly BindableProperty VerticalContentAlignmentProperty =
+ BindableProperty.Create ("VerticalContentAlignemnt", typeof(TextAlignment), typeof(Issue3076Button), TextAlignment.Center);
+
+ public TextAlignment VerticalContentAlignment
+ {
+ get { return (TextAlignment)GetValue (VerticalContentAlignmentProperty); }
+ set { SetValue (VerticalContentAlignmentProperty, value); }
+ }
+ }
+
+ public partial class Issue3076 : ContentPage
+ {
+ public Issue3076 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue3076 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void CanUseBindableObjectDefinedInThisAssembly (bool useCompiledXaml)
+ {
+ var layout = new Issue3076 (useCompiledXaml);
+
+ Assert.That (layout.local, Is.TypeOf<Issue3076Button> ());
+ Assert.AreEqual (TextAlignment.Start, layout.local.VerticalContentAlignment);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void CanUseBindableObjectDefinedInOtherAssembly (bool useCompiledXaml)
+ {
+ var layout = new Issue3076 (useCompiledXaml);
+
+ Assert.That (layout.controls, Is.TypeOf<Controls.Issue3076Button> ());
+ Assert.AreEqual (TextAlignment.Start, layout.controls.HorizontalContentAlignment);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3090.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3090.xaml
new file mode 100644
index 00000000..4a171913
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3090.xaml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue3090">
+ <AbsoluteLayout >
+ <Label AbsoluteLayout.LayoutBounds="0, 0, 1, 1" />
+ </AbsoluteLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3090.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3090.xaml.cs
new file mode 100644
index 00000000..8fc37994
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3090.xaml.cs
@@ -0,0 +1,30 @@
+using NUnit.Framework;
+
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue3090 : ContentPage
+ {
+ public Issue3090 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Issue3090 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void NewDoesNotThrow (bool useCompiledXaml)
+ {
+ var p = new Issue3090 (useCompiledXaml);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3106.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3106.xaml
new file mode 100644
index 00000000..fe48c730
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3106.xaml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Issue3106">
+ <ContentPage.Content>
+ <TableView HasUnevenRows="true">
+ <TableView.Root>
+ <TableSection Title="TextCell Disable">
+ <TextCell Text="txtCellDisable1" Detail="test" IsEnabled="false" />
+ <TextCell Text="txtCellDisable2" Height="25" IsEnabled="false" />
+ </TableSection>
+ <TableSection Title="TextCell Enable">
+ <TextCell Text="txtCellEnable1" Detail="test" IsEnabled="true" />
+ <TextCell Text="txtCellEnable2" Height="25" IsEnabled="true" />
+ </TableSection>
+ <TableSection Title="TextCell ContextActions Disable">
+ <TextCell Text="txtCellDisableContextActions1" Detail="test" IsEnabled="false">
+ <TextCell.ContextActions>
+ <MenuItem Command="{Binding MoreCommand}" Text="More" />
+ <MenuItem Command="{Binding DeleteCommand}" Text="Delete" />
+ </TextCell.ContextActions>
+ </TextCell>
+ </TableSection>
+ <TableSection Title="TextCell ContextActions Enable">
+ <TextCell Text="txtCellEnabledContextActions1" Detail="test" IsEnabled="true">
+ <TextCell.ContextActions>
+ <MenuItem Command="{Binding MoreCommand}" Text="More" />
+ <MenuItem Command="{Binding DeleteCommand}" Text="Delete" IsDestructive="true" />
+ </TextCell.ContextActions>
+ </TextCell>
+ </TableSection>
+ </TableView.Root>
+ </TableView>
+ </ContentPage.Content>
+</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3106.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3106.xaml.cs
new file mode 100644
index 00000000..f2e8a641
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue3106.xaml.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Issue3106 : ContentPage
+ {
+ public Issue3106 ()
+ {
+ InitializeComponent ();
+ }
+ public Issue3106 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void NewDoesNotThrow (bool useCompiledXaml)
+ {
+ var p = new Issue3106 (useCompiledXaml);
+ }
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Pr3384.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Pr3384.xaml
new file mode 100644
index 00000000..24d0842b
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Pr3384.xaml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Pr3384">
+ <ListView x:Name="listView"
+ CachingStrategy="RecycleElement" />
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Pr3384.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Pr3384.xaml.cs
new file mode 100644
index 00000000..ebf3fe18
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Pr3384.xaml.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Pr3384 : ContentPage
+ {
+ public Pr3384 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Pr3384 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [SetUp]
+ public void SetUp ()
+ {
+ Device.OS = TargetPlatform.iOS;
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void RecyclingStrategyIsHandled (bool useCompiledXaml)
+ {
+ var p = new Pr3384 (useCompiledXaml);
+ Assert.AreEqual (ListViewCachingStrategy.RecycleElement, p.listView.CachingStrategy);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/TestCases.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/TestCases.cs
new file mode 100644
index 00000000..ba3c2c2f
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/TestCases.cs
@@ -0,0 +1,212 @@
+using System;
+using System.Linq;
+using NUnit.Framework;
+using System.Collections.Generic;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class BasePage : ContentPage
+ {
+
+ }
+
+ [TestFixture]
+ public class TestCases
+ {
+ [SetUp]
+ public void Setup ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public void Teardown ()
+ {
+ Device.PlatformServices = null;
+ }
+
+ public static readonly BindableProperty InnerViewProperty =
+ BindableProperty.CreateAttached<TestCases, View> (bindable => GetInnerView (bindable), default(View));
+
+ public static View GetInnerView (BindableObject bindable)
+ {
+ return (View)bindable.GetValue (InnerViewProperty);
+ }
+
+ public static void SetInnerView (BindableObject bindable, View value)
+ {
+ bindable.SetValue (InnerViewProperty, value);
+ }
+
+ [Test]
+ public void TestCase001 ()
+ {
+ var xaml = @"<?xml version=""1.0"" encoding=""UTF-8"" ?>
+ <ContentPage
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests""
+ Title=""Home"">
+ <local:TestCases.InnerView>
+ <Label x:Name=""innerView""/>
+ </local:TestCases.InnerView>
+ <ContentPage.Content>
+ <Grid RowSpacing=""9"" ColumnSpacing=""6"" Padding=""6,9"" VerticalOptions=""Fill"" HorizontalOptions=""Fill"" BackgroundColor=""Red"">
+ <Grid.Children>
+ <Label x:Name=""label0""/>
+ <Label x:Name=""label1""/>
+ <Label x:Name=""label2""/>
+ <Label x:Name=""label3""/>
+ </Grid.Children>
+ </Grid>
+ </ContentPage.Content>
+ </ContentPage>";
+ var contentPage = new ContentPage ().LoadFromXaml (xaml);
+ var label0 = contentPage.FindByName<Label> ("label0");
+ var label1 = contentPage.FindByName<Label> ("label1");
+
+ Assert.NotNull (GetInnerView (contentPage));
+// Assert.AreEqual ("innerView", GetInnerView (contentPage).Name);
+ Assert.AreEqual (GetInnerView (contentPage), ((Forms.Internals.INameScope)contentPage).FindByName ("innerView"));
+ Assert.NotNull (label0);
+ Assert.NotNull (label1);
+ Assert.AreEqual (4, contentPage.Content.Descendants ().Count ());
+ }
+
+
+ [Test]
+ public void TestCase002 ()
+ {
+ var xaml = @"<?xml version=""1.0"" encoding=""UTF-8"" ?>
+ <local:BasePage
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests""
+ x:Class=""Tramchester.App.Views.HomeView"">
+ <local:BasePage.Content>
+ <Label Text=""Hi There!"" />
+ </local:BasePage.Content>
+ </local:BasePage>";
+ var contentPage = new ContentPage ().LoadFromXaml (xaml);
+ Assert.That (contentPage.Content, Is.InstanceOf<Label> ());
+ }
+
+ [Test]
+ public void TestCase003 ()
+ {
+ var xaml = @"<?xml version=""1.0"" encoding=""UTF-8"" ?>
+ <ContentPage
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ Title=""People"">
+
+ <StackLayout Spacing=""0"">
+ <SearchBar x:Name=""searchBar""/>
+ <ListView ItemsSource=""{Binding Path=.}"" RowHeight=""42"" x:Name=""listview"">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <ViewCell.View>
+ <StackLayout Orientation=""Horizontal"" HorizontalOptions=""FillAndExpand"" VerticalOptions=""CenterAndExpand"" BackgroundColor=""#fff4f4f4"">
+ <BoxView WidthRequest=""10""/>
+ <Grid WidthRequest=""42"" HeightRequest=""32"" VerticalOptions=""CenterAndExpand"" HorizontalOptions=""Start"">
+ <Image WidthRequest=""32"" HeightRequest=""32"" Aspect=""AspectFill"" HorizontalOptions=""FillAndExpand"" Source=""Images/icone_nopic_members_42.png""/>
+ <!--<Image WidthRequest=""32"" HeightRequest=""32"" Aspect=""AspectFill"" HorizontalOptions=""FillAndExpand"">
+ <Image.Source>
+ <UriImageSource Uri=""{Binding Picture}"" CacheValidity=""30""/>
+ </Image.Source>
+ </Image>-->
+ <Image Source=""Images/cropcircle.png"" HorizontalOptions=""FillAndExpand"" VerticalOptions=""FillAndExpand"" WidthRequest=""32"" HeightRequest=""32"" Aspect=""Fill""/>
+ </Grid>
+ <Label Text=""{Binding FirstName}"" VerticalOptions=""CenterAndExpand""/>
+ <Label Text=""{Binding LastName}"" Font=""HelveticaNeue-Bold, Medium"" VerticalOptions=""CenterAndExpand"" />
+ </StackLayout>
+ </ViewCell.View>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </StackLayout>
+ </ContentPage>";
+ var page = new ContentPage ().LoadFromXaml (xaml);
+ var model = new List<object> {
+ new {FirstName = "John", LastName="Lennon", Picture="http://www.johnlennon.com/wp-content/themes/jl/images/home-gallery/2.jpg"},
+ new {FirstName = "Paul", LastName="McCartney", Picture="http://t0.gstatic.com/images?q=tbn:ANd9GcRjNUGJ00Mt85n2XDu8CZM0w1em0Wv4ZaemLuIVmLCMwPMOLUO1SQ"},
+ new {FirstName = "George", LastName="Harisson", Picture="http://cdn.riffraf.net/wp-content/uploads/2013/02/george-harrison-living.jpg"},
+ new {FirstName = "Ringo", LastName="Starr", Picture="http://www.biography.com/imported/images/Biography/Images/Profiles/S/Ringo-Starr-306872-1-402.jpg"},
+ };
+ page.BindingContext = model;
+
+ var listview = page.FindByName<ListView> ("listview");
+ Cell cell = null;
+ Assert.DoesNotThrow(() => { cell = listview.TemplatedItems[0]; });
+ Assert.NotNull (cell);
+ Assert.That (cell, Is.TypeOf<ViewCell> ());
+ Assert.AreSame (model [0], cell.BindingContext);
+ }
+
+ [Test]
+ public void TestCase004 ()
+ {
+ var xaml = @"<?xml version=""1.0"" encoding=""UTF-8"" ?>
+ <ContentPage
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
+ <ContentPage.Content>
+ <ScrollView Orientation=""Horizontal"">
+ <ScrollView.Content>
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition />
+ <ColumnDefinition />
+ </Grid.ColumnDefinitions>
+ <Image Grid.Column=""0"" Grid.Row=""0"" Aspect=""AspectFill"">
+ <Image.Source>
+ <StreamImageSource Stream=""{Binding HeroPicture.Stream}"" />
+ </Image.Source>
+ </Image>
+ </Grid>
+ </ScrollView.Content>
+ </ScrollView>
+ </ContentPage.Content>
+ </ContentPage>";
+
+ var page = new ContentPage ();
+ Assert.DoesNotThrow (()=> page.LoadFromXaml (xaml));
+ }
+
+ [Test]
+ public void Issue1415 ()
+ {
+ var xaml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
+ <ContentPage
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"">
+ <Label x:Name=""label"" Text=""{Binding Converter={x:Static local:ReverseConverter.Instance}, Mode=TwoWay}""/>
+ </ContentPage>";
+ var page = new ContentPage ().LoadFromXaml (xaml);
+ var label = page.FindByName<Label> ("label");
+ Assert.NotNull (label);
+ label.BindingContext = "foo";
+ Assert.AreEqual ("oof", label.Text);
+ }
+
+ [Test]
+ //only happens in european cultures
+ [SetCulture ("fr-FR")]
+ public void Issue1493 ()
+ {
+ var xaml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
+ <View
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ RelativeLayout.HeightConstraint=""{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.25}""
+ RelativeLayout.WidthConstraint=""{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.6}""/>";
+ View view = new View ();
+ view.LoadFromXaml (xaml);
+ Assert.DoesNotThrow (() => view.LoadFromXaml (xaml));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported001.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported001.xaml
new file mode 100644
index 00000000..a039f7f6
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported001.xaml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Unreported001">
+ <NavigationPage Title="Test" x:Name="navpage">
+ <x:Arguments>
+ <local:U001Page />
+ </x:Arguments>
+ </NavigationPage>
+</TabbedPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported001.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported001.xaml.cs
new file mode 100644
index 00000000..d04ad467
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported001.xaml.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class U001Page : ContentPage
+ {
+ public U001Page ()
+ {
+ ;
+ }
+
+ }
+
+ public partial class Unreported001 : TabbedPage
+ {
+ public Unreported001 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Unreported001 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void DoesNotThrow (bool useCompiledXaml)
+ {
+ var p = new Unreported001 (useCompiledXaml);
+ Assert.That (p.navpage.CurrentPage, Is.TypeOf<U001Page> ());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported002.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported002.xaml
new file mode 100644
index 00000000..7785ae8c
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported002.xaml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Unreported002">
+ <Label x:Name="label"
+ AbsoluteLayout.LayoutBounds="0.5,0.5,1,AutoSize" />
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported002.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported002.xaml.cs
new file mode 100644
index 00000000..23f24044
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported002.xaml.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Unreported002 : ContentPage
+ {
+ public Unreported002 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Unreported002 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TypeConvertersOnAttachedBP (bool useCompiledXaml)
+ {
+ var p = new Unreported002 (useCompiledXaml);
+ Assert.AreEqual (new Rectangle (0.5, 0.5, 1, -1), AbsoluteLayout.GetLayoutBounds (p.label));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported003.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported003.xaml
new file mode 100644
index 00000000..b8db54b3
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported003.xaml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Unreported003" >
+ <maps:Map x:Name="map">
+ <x:Arguments>
+ <maps:MapSpan>
+ <x:Arguments>
+ <!-- These coordinates land near Red Deer at a fairly high altitude (birds eye view). -->
+ <maps:Position>
+ <x:Arguments>
+ <!-- Latitude-->
+ <x:Double>52.325</x:Double>
+ <!-- Longitude-->
+ <x:Double>-113.9</x:Double>
+ </x:Arguments>
+ </maps:Position>
+ <!-- Elevation lat/long-->
+ <x:Double>.8</x:Double>
+ <x:Double>.8</x:Double>
+ </x:Arguments>
+ </maps:MapSpan>
+ </x:Arguments>
+ </maps:Map>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported003.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported003.xaml.cs
new file mode 100644
index 00000000..ebe78bc4
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported003.xaml.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Unreported003 : ContentPage
+ {
+ public Unreported003 ()
+ {
+ InitializeComponent ();
+ }
+
+ public Unreported003 (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true), TestCase(false)]
+ public void AllowCtorArgsForValueTypes (bool useCompiledXaml)
+ {
+ var page = new Unreported003 (useCompiledXaml);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/LoaderTests.cs b/Xamarin.Forms.Xaml.UnitTests/LoaderTests.cs
new file mode 100644
index 00000000..76817335
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/LoaderTests.cs
@@ -0,0 +1,808 @@
+using NUnit.Framework;
+using System.Linq;
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [ContentProperty ("Content")]
+ public class CustomView : View
+ {
+ public string NotBindable { get; set; }
+
+ public View Content { get; set; }
+
+ public MockFlags MockFlags { get; set; }
+ }
+
+ [ContentProperty ("Children")]
+ public class ViewWithChildrenContent : View
+ {
+ public ViewWithChildrenContent ()
+ {
+ Children = DefaultChildren = new ViewList ();
+ }
+ public ViewList DefaultChildren;
+ public ViewList Children { get; set; }
+ }
+
+ public class ViewList : List<View>
+ {
+
+ }
+
+ public class ReverseConverter : IValueConverter
+ {
+ public static ReverseConverter Instance = new ReverseConverter ();
+
+ public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ var s = value as string;
+ if (s == null)
+ return value;
+ return new string (s.Reverse ().ToArray ());
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ var s = value as string;
+ if (s == null)
+ return value;
+ return new string (s.Reverse ().ToArray ());
+ }
+ }
+
+ public class Catalog
+ {
+ public static readonly BindableProperty MessageProperty =
+ BindableProperty.CreateAttached<Catalog, string> (bindable => GetMessage (bindable), default(string),
+ propertyChanged: (bindable, oldvalue, newvalue) => {
+ var label = bindable as Label;
+ if (label != null)
+ label.SetValue (Label.TextProperty, new string (newvalue.Reverse ().ToArray ()));
+ });
+
+ public static string GetMessage (BindableObject bindable)
+ {
+ return (string)bindable.GetValue (MessageProperty);
+ }
+
+ public static void SetMessage (BindableObject bindable, string value)
+ {
+ bindable.SetValue (MessageProperty, value);
+ }
+ }
+
+ [Flags]
+ public enum MockFlags
+ {
+ Foo = 1<<0,
+ Bar = 1<<1,
+ Baz = 1<<2,
+ Qux = 1<<3,
+ }
+
+
+ [TestFixture]
+ public class LoaderTests : BaseTestFixture
+ {
+ [Test]
+ public void TestRootName ()
+ {
+ var xaml = @"
+ <View
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ x:Class=""Xamarin.Forms.Xaml.UnitTests.CustomView""
+ x:Name=""customView""
+ />";
+
+ var view = new CustomView ();
+ view.LoadFromXaml (xaml);
+
+ Assert.AreSame (view, ((Forms.Internals.INameScope)view).FindByName("customView"));
+ }
+
+ [Test]
+ public void TestFindByXName ()
+ {
+ var xaml = @"
+ <StackLayout
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
+ <StackLayout.Children>
+ <Label x:Name=""label0"" Text=""Foo""/>
+ </StackLayout.Children>
+ </StackLayout>";
+
+ var stacklayout = new StackLayout ();
+ stacklayout.LoadFromXaml (xaml);
+
+ var label = stacklayout.FindByName<Label> ("label0");
+ Assert.NotNull (label);
+ Assert.AreEqual ("Foo", label.Text);
+ }
+
+ [Test]
+ public void TestUnknownPropertyShouldThrow ()
+ {
+ var xaml = @"
+ <Label
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ Text=""Foo""
+ UnknownProperty=""Bar""
+ />";
+
+ var label = new Label ();
+ Assert.Throws (new XamlParseExceptionConstraint (5, 5), () => label.LoadFromXaml (xaml));
+ }
+
+ [Test]
+ public void TestSetValueToBindableProperty ()
+ {
+ var xaml = @"
+ <Label
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ Text=""Foo""
+ />";
+
+ var label = new Label ();
+
+ label.LoadFromXaml (xaml);
+ Assert.AreEqual ("Foo", label.Text);
+
+ }
+
+ [Test]
+ public void TestSetBindingToBindableProperty ()
+ {
+ var xaml = @"
+ <Label
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ Text=""{Binding Path=labeltext}""
+ />";
+
+ var label = new Label ();
+ label.LoadFromXaml (xaml);
+
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label.Text);
+
+ label.BindingContext = new {labeltext="Foo"};
+ Assert.AreEqual ("Foo", label.Text);
+ }
+
+ [Test]
+ public void TestBindingAsElement ()
+ {
+ var xaml = @"
+ <Label
+ xmlns=""http://xamarin.com/schemas/2014/forms"">
+ <Label.Text>
+ <Binding Path=""labeltext""/>
+ </Label.Text>
+ </Label>";
+
+ var label = new Label ();
+ label.LoadFromXaml (xaml);
+
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label.Text);
+
+ label.BindingContext = new {labeltext="Foo"};
+ Assert.AreEqual ("Foo", label.Text);
+
+ }
+
+ [Test]
+ public void TestSetBindingToNonBindablePropertyShouldThrow ()
+ {
+ var xaml = @"
+ <View
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ x:Class=""Xamarin.Forms.Xaml.UnitTests.CustomView""
+ Name=""customView""
+ NotBindable=""{Binding text}""
+ />";
+
+ var view = new CustomView ();
+ Assert.Throws (new XamlParseExceptionConstraint (6, 5), () => view.LoadFromXaml (xaml));
+ }
+
+ [Test]
+ public void TestBindingPath ()
+ {
+ var xaml = @"
+ <StackLayout
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
+ <StackLayout.Children>
+ <Label x:Name=""label0"" Text=""{Binding text}""/>
+ <Label x:Name=""label1"" Text=""{Binding Path=text}""/>
+ </StackLayout.Children>
+ </StackLayout>";
+
+ var stacklayout = new StackLayout ();
+ stacklayout.LoadFromXaml (xaml);
+
+ var label0 = stacklayout.FindByName<Label> ("label0");
+ var label1 = stacklayout.FindByName<Label> ("label1");
+
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label0.Text);
+ Assert.AreEqual (Label.TextProperty.DefaultValue, label1.Text);
+
+ stacklayout.BindingContext = new {text = "Foo"};
+ Assert.AreEqual ("Foo", label0.Text);
+ Assert.AreEqual ("Foo", label1.Text);
+ }
+
+
+ class ViewModel
+ {
+ public string Text { get; set; }
+ }
+
+ [Test]
+ public void TestBindingModeAndConverter ()
+ {
+ var xaml = @"
+ <ContentPage
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <local:ReverseConverter x:Key=""reverseConverter""/>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ <ContentPage.Content>
+ <StackLayout Orientation=""Vertical"">
+ <StackLayout.Children>
+ <Label x:Name=""label0"" Text=""{Binding Text, Converter={StaticResource reverseConverter}}""/>
+ <Label x:Name=""label1"" Text=""{Binding Text, Mode=TwoWay}""/>
+ </StackLayout.Children>
+ </StackLayout>
+ </ContentPage.Content>
+ </ContentPage>";
+
+ var contentPage = new ContentPage ();
+ contentPage.LoadFromXaml (xaml);
+ contentPage.BindingContext = new ViewModel { Text = "foobar" };
+ var label0 = contentPage.FindByName<Label> ("label0");
+ var label1 = contentPage.FindByName<Label> ("label1");
+ Assert.AreEqual ("raboof", label0.Text);
+
+ label1.Text = "baz";
+ Assert.AreEqual ("baz", ((ViewModel)(contentPage.BindingContext)).Text);
+ }
+
+ [Test]
+ public void TestNonEmptyCollectionMembers ()
+ {
+ var xaml = @"
+ <StackLayout
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
+ <StackLayout.Children>
+ <Grid x:Name=""grid0"">
+ </Grid>
+ <Grid x:Name=""grid1"">
+ </Grid>
+ </StackLayout.Children>
+ </StackLayout>";
+
+ var stacklayout = new StackLayout ();
+ stacklayout.LoadFromXaml (xaml);
+ var grid0 = stacklayout.FindByName<Grid> ("grid0");
+ var grid1 = stacklayout.FindByName<Grid> ("grid1");
+ Assert.NotNull (grid0);
+ Assert.NotNull (grid1);
+ }
+
+ [Test]
+ public void TestUnknownType ()
+ {
+ var xaml = @"
+ <StackLayout
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
+ <StackLayout.Children>
+ <CustomView />
+ </StackLayout.Children>
+ </StackLayout>";
+
+ var stacklayout = new StackLayout ();
+ Assert.Throws (new XamlParseExceptionConstraint (6, 8), () => stacklayout.LoadFromXaml (xaml));
+ }
+
+ [Test]
+ public void TestResources ()
+ {
+ var xaml = @"
+ <Label
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"">
+ <Label.Resources>
+ <ResourceDictionary>
+ <local:ReverseConverter x:Key=""reverseConverter""/>
+ </ResourceDictionary>
+ </Label.Resources>
+ </Label>";
+
+ var label = new Label ().LoadFromXaml (xaml);
+ Assert.NotNull (label.Resources);
+ Assert.True (label.Resources.ContainsKey ("reverseConverter"));
+ Assert.True (label.Resources ["reverseConverter"] is ReverseConverter);
+ }
+
+ [Test]
+ public void TestResourceDoesRequireKey ()
+ {
+ var xaml = @"
+ <Label
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"">
+ <Label.Resources>
+ <ResourceDictionary>
+ <local:ReverseConverter />
+ </ResourceDictionary>
+ </Label.Resources>
+ </Label>";
+ var label = new Label ();
+ Assert.Throws (new XamlParseExceptionConstraint (8, 9), () => label.LoadFromXaml (xaml));
+ }
+
+ [Test]
+ public void UseResourcesOutsideOfBinding ()
+ {
+ var xaml = @"
+ <ContentView
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
+ <ContentView.Resources>
+ <ResourceDictionary>
+ <Label Text=""Foo"" x:Key=""bar""/>
+ </ResourceDictionary>
+ </ContentView.Resources>
+ <ContentView.Content>
+ <ContentView Content=""{StaticResource bar}""/>
+ </ContentView.Content>
+ </ContentView>";
+
+ var contentView = new ContentView ().LoadFromXaml (xaml);
+ Assert.AreEqual ("Foo", (((ContentView)(contentView.Content)).Content as Label).Text);
+ }
+
+ [Test]
+ public void MissingStaticResourceShouldThrow ()
+ {
+ var xaml = @"<Label Text=""{StaticResource foo}""/>";
+ var label = new Label ();
+ Assert.Throws (new XamlParseExceptionConstraint (1, 8), () => label.LoadFromXaml (xaml));
+ }
+
+ public class CustView : Button
+ {
+ public bool fired = false;
+ public void onButtonClicked (object sender, EventArgs e)
+ {
+ fired = true;
+ }
+
+ public void wrongSignature (bool a, string b)
+ {
+ }
+ }
+
+ class MyApp : Application
+ {
+ public MyApp ()
+ {
+ Resources = new ResourceDictionary {
+ {"foo", "FOO"},
+ {"bar", "BAR"}
+ };
+ }
+ }
+
+ [Test]
+ public void StaticResourceLookForApplicationResources ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ Application.Current = null;
+
+ Application.Current = new MyApp ();
+ var xaml = @"
+ <ContentView
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
+ <ContentView.Resources>
+ <ResourceDictionary>
+ <x:String x:Key=""bar"">BAZ</x:String>
+ </ResourceDictionary>
+ </ContentView.Resources>
+ <StackLayout>
+ <Label x:Name=""label0"" Text=""{StaticResource foo}""/>
+ <Label x:Name=""label1"" Text=""{StaticResource bar}""/>
+ </StackLayout>
+ </ContentView>";
+ var layout = new ContentView ().LoadFromXaml (xaml);
+ var label0 = layout.FindByName<Label> ("label0");
+ var label1 = layout.FindByName<Label> ("label1");
+
+ //resource from App.Resources
+ Assert.AreEqual ("FOO", label0.Text);
+
+ //local resources have precedence
+ Assert.AreEqual ("BAZ", label1.Text);
+ }
+
+ [Test]
+ public void TestEvent ()
+ {
+ var xaml = @"
+ <Button
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ x:Class=""Xamarin.Forms.Xaml.UnitTests.CustView"" Clicked=""onButtonClicked"" />
+ </Button>";
+ var view = new CustView ();
+ view.LoadFromXaml (xaml);
+ Assert.False (view.fired);
+ ((IButtonController) view).SendClicked ();
+ Assert.True (view.fired);
+ }
+
+ [Test]
+ public void TestFailingEvent ()
+ {
+ var xaml = @"
+ <View
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ x:Class=""Xamarin.Forms.Xaml.UnitTests.CustView"" Activated=""missingMethod"" />
+ </View>";
+ var view = new CustView ();
+ Assert.Throws (new XamlParseExceptionConstraint (5, 53), () => view.LoadFromXaml (xaml));
+ }
+
+ [Test]
+ public void TestConnectingEventOnMethodWithWrongSignature ()
+ {
+ var xaml = @"
+ <View
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ x:Class=""Xamarin.Forms.Xaml.UnitTests.CustView"" Activated=""wrongSignature"" />
+ </View>";
+ var view = new CustView ();
+
+ Assert.Throws (new XamlParseExceptionConstraint (5, 53), () => view.LoadFromXaml (xaml));
+ }
+
+
+ public class CustEntry : Entry
+ {
+ public bool fired = false;
+ public void onValueChanged (object sender, TextChangedEventArgs e)
+ {
+ fired = true;
+ }
+
+ }
+
+ [Test]
+ public void TestEventWithCustomEventArgs ()
+ {
+ var xaml = @"
+ <Entry
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ x:Class=""Xamarin.Forms.Xaml.UnitTests.CustEntry"" TextChanged=""onValueChanged"" />
+ </Entry>";
+ var view = new CustEntry ().LoadFromXaml (xaml);
+ }
+
+ [Test]
+ public void TestEmptyTemplate ()
+ {
+ var xaml = @"
+ <ContentPage
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <DataTemplate x:Key=""datatemplate""/>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ </ContentPage>";
+ var page = new ContentPage ();
+ page.LoadFromXaml (xaml);
+ var template = page.Resources["datatemplate"]as Forms.DataTemplate;
+ Assert.Throws<InvalidOperationException>(() => template.CreateContent());
+ }
+
+ [Test]
+ public void TestBoolValue ()
+ {
+ var xaml = @"
+ <Image
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ IsOpaque=""true""/>";
+
+ var image = new Image ();
+ Assert.AreEqual (Image.IsOpaqueProperty.DefaultValue, image.IsOpaque);
+ image.LoadFromXaml (xaml);
+ Assert.AreEqual (true, image.IsOpaque);
+ }
+
+ [Test]
+ public void TestAttachedBP ()
+ {
+ var xaml = @"
+ <View
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ Grid.Column=""1"">
+ <Grid.Row>2</Grid.Row>
+ </View>";
+ var view = new View ().LoadFromXaml (xaml);
+ Assert.AreEqual (1, Grid.GetColumn (view));
+ Assert.AreEqual (2, Grid.GetRow (view));
+ }
+
+ [Test]
+ public void TestAttachedBPWithDifferentNS ()
+ {
+ //If this looks very similar to Vernacular, well... it's on purpose :)
+ var xaml = @"
+ <Label
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests""
+ local:Catalog.Message=""foobar""/>";
+ var label = new Label ().LoadFromXaml (xaml);
+ Assert.AreEqual ("raboof", label.Text);
+ }
+
+ [Test]
+ public void TestBindOnAttachedBP ()
+ {
+ var xaml = @"
+ <Label
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests""
+ local:Catalog.Message=""{Binding .}""/>";
+ var label = new Label ().LoadFromXaml (xaml);
+ label.BindingContext = "foobar";
+ Assert.AreEqual ("raboof", label.Text);
+ }
+
+ [Test]
+ public void TestContentProperties ()
+ {
+ var xaml = @"
+ <local:CustomView
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"" >
+ <Label x:Name=""contentview""/>
+ </local:CustomView>";
+ CustomView customView = null;
+ Assert.DoesNotThrow(()=> customView = new CustomView ().LoadFromXaml (xaml));
+ Assert.NotNull (customView.Content);
+ Assert.AreSame (customView.Content, ((Forms.Internals.INameScope)customView).FindByName("contentview"));
+ }
+
+ [Test]
+ public void TestCollectionContentProperties ()
+ {
+ var xaml = @"
+ <StackLayout>
+ <Label Text=""Foo""/>
+ <Label Text=""Bar""/>
+ </StackLayout>";
+ var layout = new StackLayout ().LoadFromXaml (xaml);
+ Assert.AreEqual (2, layout.Children.Count);
+ Assert.AreEqual ("Foo", ((Label)(layout.Children [0])).Text);
+ Assert.AreEqual ("Bar", ((Label)(layout.Children [1])).Text);
+ }
+
+ [Test]
+ public void TestCollectionContentPropertiesWithSingleElement ()
+ {
+ var xaml = @"
+ <StackLayout>
+ <Label Text=""Foo""/>
+ </StackLayout>";
+ var layout = new StackLayout ().LoadFromXaml (xaml);
+ Assert.AreEqual (1, layout.Children.Count);
+ Assert.AreEqual ("Foo", ((Label)(layout.Children [0])).Text);
+ }
+
+ [Test]
+ public void TestPropertiesWithContentProperties ()
+ {
+ var xaml = @"
+ <ContentPage
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
+ <Grid.Row>1</Grid.Row>
+ <Label Text=""foo""></Label>
+ </ContentPage>";
+ var contentPage = new ContentPage ().LoadFromXaml (xaml);
+ Assert.AreEqual (1, Grid.GetRow (contentPage));
+ Assert.NotNull (contentPage.Content);
+ }
+
+ [Test]
+ public void LoadFromXamlResource ()
+ {
+ ContentView view = null;
+ Assert.DoesNotThrow (() => view = new CustomXamlView ());
+ Assert.NotNull (view);
+ Assert.That (view.Content, Is.TypeOf<Label> ());
+ Assert.AreEqual ("foobar", ((Label)view.Content).Text);
+ }
+
+ [Test]
+ public void ThrowOnMissingXamlResource ()
+ {
+ var view = new CustomView ();
+ Assert.Throws (new XamlParseExceptionConstraint (), () => view.LoadFromXaml (typeof(CustomView)));
+ }
+
+ [Test]
+ public void CreateNewChildrenCollection ()
+ {
+ var xaml = @"
+ <local:ViewWithChildrenContent
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"" >
+ <local:ViewWithChildrenContent.Children>
+ <local:ViewList>
+ <Label x:Name=""child0""/>
+ <Label x:Name=""child1""/>
+ </local:ViewList>
+ </local:ViewWithChildrenContent.Children>
+ </local:ViewWithChildrenContent>";
+ ViewWithChildrenContent layout = null;
+ Assert.DoesNotThrow (() => layout = new ViewWithChildrenContent ().LoadFromXaml (xaml));
+ Assert.IsNotNull (layout);
+ Assert.AreNotSame (layout.DefaultChildren, layout.Children);
+ Assert.Contains (((Forms.Internals.INameScope)layout).FindByName ("child0"), layout.Children);
+ Assert.Contains (((Forms.Internals.INameScope)layout).FindByName ("child1"), layout.Children);
+ }
+
+ [Test]
+ public void AddChildrenToCollectionContentProperty ()
+ {
+ var xaml = @"
+ <local:ViewWithChildrenContent
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"" >
+ <Label x:Name=""child0""/>
+ <Label x:Name=""child1""/>
+ </local:ViewWithChildrenContent>";
+ ViewWithChildrenContent layout = null;
+ Assert.DoesNotThrow (() => layout = new ViewWithChildrenContent ().LoadFromXaml (xaml));
+ Assert.IsNotNull (layout);
+ Assert.AreSame (layout.DefaultChildren, layout.Children);
+ Assert.Contains (((Forms.Internals.INameScope)layout).FindByName ("child0"), layout.Children);
+ Assert.Contains (((Forms.Internals.INameScope)layout).FindByName ("child1"), layout.Children);
+ }
+
+ [Test]
+ public void AddChildrenToExistingCollection ()
+ {
+ var xaml = @"
+ <local:ViewWithChildrenContent
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"" >
+ <local:ViewWithChildrenContent.Children>
+ <Label x:Name=""child0""/>
+ <Label x:Name=""child1""/>
+ </local:ViewWithChildrenContent.Children>
+ </local:ViewWithChildrenContent>";
+ ViewWithChildrenContent layout = null;
+ Assert.DoesNotThrow (() => layout = new ViewWithChildrenContent ().LoadFromXaml (xaml));
+ Assert.IsNotNull (layout);
+ Assert.AreSame (layout.DefaultChildren, layout.Children);
+ Assert.Contains (((Forms.Internals.INameScope)layout).FindByName ("child0"), layout.Children);
+ Assert.Contains (((Forms.Internals.INameScope)layout).FindByName ("child1"), layout.Children);
+
+ }
+
+ [Test]
+ public void AddSingleChildToCollectionContentProperty ()
+ {
+ var xaml = @"
+ <local:ViewWithChildrenContent
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"" >
+ <Label x:Name=""child0""/>
+ </local:ViewWithChildrenContent>";
+ ViewWithChildrenContent layout = null;
+ Assert.DoesNotThrow (() => layout = new ViewWithChildrenContent ().LoadFromXaml (xaml));
+ Assert.IsNotNull (layout);
+ Assert.AreSame (layout.DefaultChildren, layout.Children);
+ Assert.Contains (((Forms.Internals.INameScope)layout).FindByName ("child0"), layout.Children);
+ }
+
+ [Test]
+ public void FindResourceByName ()
+ {
+ var xaml = @"
+ <ContentPage
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ x:Class=""Resources"">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <Button x:Key=""buttonKey"" x:Name=""buttonName""/>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ <Label x:Name=""label""/>
+ </ContentPage>";
+
+ var layout = new ContentPage ().LoadFromXaml (xaml);
+ Assert.True (layout.Resources.ContainsKey ("buttonKey"));
+ var resource = layout.FindByName<Button> ("buttonName");
+ Assert.NotNull (resource);
+ Assert.That (resource, Is.TypeOf<Button> ());
+ }
+
+ [Test]
+ public void ParseEnum ()
+ {
+ var xaml = @"
+ <local:CustomView
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests""
+ MockFlags=""Bar""
+ />";
+ var view = new CustomView ().LoadFromXaml (xaml);
+ Assert.AreEqual (MockFlags.Bar, view.MockFlags);
+
+ }
+
+ [Test]
+ public void ParseFlags ()
+ {
+ var xaml = @"
+ <local:CustomView
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests""
+ MockFlags=""Baz,Bar""
+ />";
+ var view = new CustomView ().LoadFromXaml (xaml);
+ Assert.AreEqual (MockFlags.Bar | MockFlags.Baz, view.MockFlags);
+ }
+
+ [Test]
+ public void StyleWithoutTargetTypeThrows ()
+ {
+ var xaml = @"
+ <Label>
+ <Label.Style>
+ <Style>
+ <Setter Property=""Text"" Value=""Foo"" />
+ </Style>
+ </Label.Style>
+ </Label>";
+ var label = new Label ();
+ Assert.Throws (new XamlParseExceptionConstraint (4, 8), () => label.LoadFromXaml (xaml));
+ }
+ }
+}
diff --git a/Xamarin.Forms.Xaml.UnitTests/MarkupExpressionParserTests.cs b/Xamarin.Forms.Xaml.UnitTests/MarkupExpressionParserTests.cs
new file mode 100644
index 00000000..63493030
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/MarkupExpressionParserTests.cs
@@ -0,0 +1,326 @@
+using System;
+using NUnit.Framework;
+using System.Xml;
+using System.Collections.Generic;
+
+using Xamarin.Forms.Core.UnitTests;
+using System.Reflection;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class MarkupExpressionParserTests : BaseTestFixture
+ {
+ IXamlTypeResolver typeResolver;
+
+ class MockElementNode : IElementNode, IValueNode, IXmlLineInfo
+ {
+ public bool HasLineInfo () { return false; }
+
+ public int LineNumber {
+ get { return -1; }
+ }
+
+ public int LinePosition {
+ get { return -1; }
+ }
+
+
+ public IXmlNamespaceResolver NamespaceResolver {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+
+ public object Value {get;set;}
+ public Dictionary<XmlName, INode> Properties { get; set; }
+
+ public List<XmlName> SkipProperties { get; set; }
+
+ public Forms.Internals.INameScope Namescope {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+
+ public XmlType XmlType {
+ get;
+ set;
+ }
+
+ public string NamespaceURI {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+
+ public INode Parent {
+ get {
+ throw new NotImplementedException ();
+ }
+ set { throw new NotImplementedException (); }
+ }
+
+ public List<INode> CollectionItems { get; set; }
+
+ public void Accept (IXamlNodeVisitor visitor, INode parentNode)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public List<string> IgnorablePrefixes { get; set; }
+ }
+
+ [SetUp]
+ public override void Setup ()
+ {
+ base.Setup ();
+ var nsManager = new XmlNamespaceManager (new NameTable ());
+ nsManager.AddNamespace ("local", "clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests");
+ nsManager.AddNamespace ("x", "http://schemas.microsoft.com/winfx/2009/xaml");
+ typeResolver = new Internals.XamlTypeResolver (nsManager, XamlParser.GetElementType, Assembly.GetCallingAssembly ());
+ }
+
+ [Test]
+ public void BindingOnSelf ()
+ {
+ var bindingString = "{Binding}";
+ var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ });
+ Assert.That (binding, Is.InstanceOf<Binding> ());
+ Assert.AreEqual (Binding.SelfPath, ((Binding)binding).Path);
+ }
+
+ [Test]
+ public void BindingWithImplicitPath ()
+ {
+ var bindingString = "{Binding Foo}";
+
+ var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ });
+
+ Assert.That (binding, Is.InstanceOf<Binding> ());
+ Assert.AreEqual ("Foo", ((Binding)binding).Path);
+ }
+
+ [Test]
+ public void BindingWithPath ()
+ {
+ var bindingString = "{Binding Path=Foo}";
+
+ var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ });
+
+ Assert.That (binding, Is.InstanceOf<Binding> ());
+ Assert.AreEqual ("Foo", ((Binding)binding).Path);
+ }
+
+ [Test]
+ public void BindingWithComposedPath ()
+ {
+ var bindingString = "{Binding Path=Foo.Bar}";
+
+ var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ });
+
+ Assert.That (binding, Is.InstanceOf<Binding> ());
+ Assert.AreEqual ("Foo.Bar", ((Binding)binding).Path);
+ }
+
+ [Test]
+ public void BindingWithImplicitComposedPath ()
+ {
+ var bindingString = "{Binding Path=Foo.Bar}";
+
+ var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ });
+
+ Assert.That (binding, Is.InstanceOf<Binding> ());
+ Assert.AreEqual ("Foo.Bar", ((Binding)binding).Path);
+ }
+
+ class MockValueProvider : IProvideParentValues, IProvideValueTarget
+ {
+ public MockValueProvider (string key, object resource)
+ {
+ var rd = new ResourceDictionary {
+ {key, resource}
+ };
+
+ ve = new VisualElement {
+ Resources = rd,
+ };
+ }
+
+
+ VisualElement ve;
+ public IEnumerable<object> ParentObjects {
+ get {
+ yield return ve;
+ }
+ }
+
+ public object TargetObject {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+
+ public object TargetProperty {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+ }
+
+ [Test]
+ public void BindingWithImplicitPathAndConverter ()
+ {
+ var bindingString = "{Binding Foo, Converter={StaticResource Bar}}";
+ var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ IProvideValueTarget = new MockValueProvider ("Bar", new ReverseConverter()),
+ });
+
+ Assert.That (binding, Is.InstanceOf<Binding> ());
+ Assert.AreEqual ("Foo", ((Binding)binding).Path);
+ Assert.NotNull (((Binding)binding).Converter);
+ Assert.That (((Binding)binding).Converter, Is.InstanceOf<ReverseConverter> ());
+ }
+
+ [Test]
+ public void BindingWithPathAndConverter ()
+ {
+ var bindingString = "{Binding Path=Foo, Converter={StaticResource Bar}}";
+ var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ IProvideValueTarget = new MockValueProvider ("Bar", new ReverseConverter()),
+ });
+
+ Assert.That (binding, Is.InstanceOf<Binding> ());
+ Assert.AreEqual ("Foo", ((Binding)binding).Path);
+ Assert.NotNull (((Binding)binding).Converter);
+ Assert.That (((Binding)binding).Converter, Is.InstanceOf<ReverseConverter> ());
+ }
+
+
+ [Test]
+ public void TestBindingMode ()
+ {
+ var bindingString = "{Binding Foo, Mode=TwoWay}";
+
+ var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ });
+
+ Assert.That (binding, Is.InstanceOf<Binding> ());
+ Assert.AreEqual ("Foo", ((Binding)binding).Path);
+ Assert.AreEqual (BindingMode.TwoWay, ((Binding)binding).Mode);
+ }
+
+ [Test]
+ public void BindingStringFormat ()
+ {
+ var bindingString = "{Binding Foo, StringFormat=Bar}";
+
+ var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ });
+ Assert.That (binding, Is.InstanceOf<Binding> ());
+ Assert.AreEqual ("Foo", ((Binding)binding).Path);
+ Assert.AreEqual ("Bar", ((Binding)binding).StringFormat);
+ }
+
+ [Test]
+ public void BindingStringFormatWithEscapes ()
+ {
+ var bindingString = "{Binding Foo, StringFormat='{}Hello {0}'}";
+
+ var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ });
+
+ Assert.That (binding, Is.InstanceOf<Binding> ());
+ Assert.AreEqual ("Foo", ((Binding)binding).Path);
+ Assert.AreEqual ("Hello {0}", ((Binding)binding).StringFormat);
+ }
+
+ [Test]
+ public void BindingStringFormatWithoutEscaping ()
+ {
+ var bindingString = "{Binding Foo, StringFormat='{0,20}'}";
+
+ var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ });
+
+ Assert.That (binding, Is.InstanceOf<Binding> ());
+ Assert.AreEqual ("Foo", ((Binding)binding).Path);
+ Assert.AreEqual ("{0,20}", ((Binding)binding).StringFormat);
+ }
+
+ [Test]
+ public void BindingStringFormatNumeric ()
+ {
+ var bindingString = "{Binding Foo, StringFormat=P2}";
+
+ var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ });
+
+ Assert.That (binding, Is.InstanceOf<Binding> ());
+ Assert.AreEqual ("Foo", ((Binding)binding).Path);
+ Assert.AreEqual ("P2", ((Binding)binding).StringFormat);
+ }
+
+ [Test]
+ public void BindingConverterParameter ()
+ {
+ var bindingString = "{Binding Foo, ConverterParameter='Bar'}";
+
+ var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ });
+
+ Assert.That (binding, Is.InstanceOf<Binding> ());
+ Assert.AreEqual ("Foo", ((Binding)binding).Path);
+ Assert.AreEqual ("Bar", ((Binding)binding).ConverterParameter);
+ }
+
+ [Test]
+ public void BindingsCompleteString ()
+ {
+ var bindingString = "{Binding Path=Foo.Bar, StringFormat='{}Qux, {0}', Converter={StaticResource Baz}, Mode=OneWayToSource}";
+ var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ IProvideValueTarget = new MockValueProvider ("Baz", new ReverseConverter()),
+ });
+
+ Assert.That (binding, Is.InstanceOf<Binding> ());
+ Assert.AreEqual ("Foo.Bar", ((Binding)binding).Path);
+ Assert.NotNull (((Binding)binding).Converter);
+ Assert.That (((Binding)binding).Converter, Is.InstanceOf<ReverseConverter> ());
+ Assert.AreEqual (BindingMode.OneWayToSource, ((Binding)binding).Mode);
+ Assert.AreEqual ("Qux, {0}", ((Binding)binding).StringFormat);
+ }
+
+ [Test]
+ public void BindingWithStaticConverter ()
+ {
+ var bindingString = "{Binding Converter={x:Static local:ReverseConverter.Instance}}";
+
+ var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ }) as Binding;
+
+ Assert.NotNull (binding);
+ Assert.AreEqual(".", binding.Path);
+ Assert.That (binding.Converter, Is.TypeOf<ReverseConverter> ());
+ }
+ }
+}
diff --git a/Xamarin.Forms.Xaml.UnitTests/MarkupExtensionTests.cs b/Xamarin.Forms.Xaml.UnitTests/MarkupExtensionTests.cs
new file mode 100644
index 00000000..ebc32f4a
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/MarkupExtensionTests.cs
@@ -0,0 +1,211 @@
+using System;
+using NUnit.Framework;
+using System.Xml;
+
+using Xamarin.Forms.Core.UnitTests;
+using System.Reflection;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class FooMarkupExtension : IMarkupExtension
+ {
+ public object ProvideValue (IServiceProvider serviceProvider)
+ {
+ return "Foo";
+ }
+ }
+
+ public class AppendMarkupExtension : IMarkupExtension
+ {
+ public object Value0 { get; set; }
+ public object Value1 { get; set; }
+
+ public object ProvideValue (IServiceProvider serviceProvider)
+ {
+ return Value0.ToString () + Value1.ToString ();
+ }
+ }
+
+ public class AccessServiceProviderExtension : IMarkupExtension
+ {
+ public object ProvideValue (IServiceProvider serviceProvider)
+ {
+ var result = "";
+ if (serviceProvider != null) {
+ var targetValueProvider = serviceProvider.GetService (typeof(IProvideValueTarget));
+ result += targetValueProvider != null;
+ var xamlType = serviceProvider.GetService (typeof(IXamlTypeResolver));
+ result += xamlType != null;
+ var rootObject = serviceProvider.GetService (typeof(IRootObjectProvider));
+ result += rootObject != null;
+ }
+ return result;
+ }
+ }
+
+ public class ColorMarkup : IMarkupExtension
+ {
+ public int R { get; set; }
+ public int G { get; set; }
+ public int B { get; set; }
+
+ public ColorMarkup ()
+ {
+ }
+
+ public object ProvideValue (IServiceProvider serviceProvider)
+ {
+ return Color.FromRgb (R, G, B);
+ }
+ }
+
+ public class FuuExtension : IMarkupExtension
+ {
+ public object ProvideValue (IServiceProvider serviceProvider)
+ {
+ return "FuuExtension";
+ }
+ }
+
+ public class Fuu : IMarkupExtension
+ {
+ public object ProvideValue (IServiceProvider serviceProvider)
+ {
+ return "Fuu";
+ }
+ }
+
+ public class BaaExtension : IMarkupExtension
+ {
+ public object ProvideValue (IServiceProvider serviceProvider)
+ {
+ return "BaaExtension";
+ }
+ }
+
+ [TestFixture]
+ public class MarkupExtensionTests : BaseTestFixture
+ {
+ IXamlTypeResolver typeResolver;
+
+ [SetUp]
+ public override void Setup ()
+ {
+ base.Setup ();
+ var nsManager = new XmlNamespaceManager (new NameTable ());
+ nsManager.AddNamespace ("local", "clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests");
+ nsManager.AddNamespace ("x", "http://schemas.microsoft.com/winfx/2006/xaml");
+
+ typeResolver = new Internals.XamlTypeResolver (nsManager, XamlParser.GetElementType, Assembly.GetCallingAssembly ());
+ }
+
+ [Test]
+ public void TestSimpleExtension ()
+ {
+ var markupString = "{local:FooMarkupExtension}";
+ var serviceProvider = new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ };
+ var result = (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider);
+
+ Assert.That (result, Is.InstanceOf<string> ());
+ Assert.AreEqual ("Foo", result);
+ }
+
+ [Test]
+ public void TestExtensionWithParameters ()
+ {
+ var markupString = "{local:AppendMarkupExtension Value0=Foo, Value1=Bar}";
+ var serviceProvider = new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ };
+ var result = (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider);
+
+ Assert.That (result, Is.InstanceOf<string> ());
+ Assert.AreEqual ("FooBar", result);
+ }
+
+ [Test]
+ public void TestServiceProvider ()
+ {
+ var markupString = "{local:AccessServiceProviderExtension}";
+ var serviceProvider = new Internals.XamlServiceProvider (null, null) {
+ IProvideValueTarget = new Internals.XamlValueTargetProvider (null, null, null, null),
+ IXamlTypeResolver = typeResolver,
+ IRootObjectProvider = new Internals.XamlRootObjectProvider(null),
+ };
+
+ var result = (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider);
+
+ Assert.That (result, Is.InstanceOf<string> ());
+ Assert.AreEqual ("TrueTrueTrue", result);
+ }
+
+ [Test]
+ public void TestInXaml ()
+ {
+ var xaml = @"
+ <Label
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests""
+ Text=""{local:AppendMarkupExtension Value0=Foo, Value1=Bar}""
+ />";
+
+ var label = new Label ();
+ label.LoadFromXaml (xaml);
+ Assert.AreEqual ("FooBar", label.Text.ToString ());
+ }
+
+ [Test]
+ public void TestDocumentationCode ()
+ {
+ var xaml =@"
+ <Label
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests""
+ TextColor=""{local:ColorMarkup R=100, G=80, B=60}""/>";
+
+ var label = new Label ().LoadFromXaml (xaml);
+ Assert.AreEqual (Color.FromRgb (100, 80, 60), label.TextColor);
+ }
+
+ [Test]
+ public void TestLookupWithSuffix ()
+ {
+ var markupString = "{local:Baa}";
+ var serviceProvider = new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ };
+ var result = (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider);
+
+ Assert.That (result, Is.InstanceOf<string> ());
+ Assert.AreEqual ("BaaExtension", result);
+ }
+
+ [Test]
+ public void TestLookupOrder ()
+ {
+ //The order of lookup is to look for the Extension-suffixed class name first and then look for the class name without the Extension suffix.
+ var markupString = "{local:Fuu}";
+ var serviceProvider = new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ };
+ var result = (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider);
+
+ Assert.That (result, Is.InstanceOf<string> ());
+ Assert.AreEqual ("FuuExtension", result);
+ }
+
+ [Test]
+ public void ThrowOnMarkupExtensionNotFound ()
+ {
+ var markupString = "{local:Missing}";
+ var serviceProvider = new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ };
+ Assert.Throws<XamlParseException> (()=> (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/McIgnorable.xaml b/Xamarin.Forms.Xaml.UnitTests/McIgnorable.xaml
new file mode 100644
index 00000000..7cbd4aa5
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/McIgnorable.xaml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:d="ignoreme"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ mc:Ignorable="d"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.McIgnorable"
+ d:DesignWidth="320"
+ d:DesignHeight="800">
+ <ContentPage.BindingContext>
+ <d:FooBar />
+ </ContentPage.BindingContext>
+</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/McIgnorable.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/McIgnorable.xaml.cs
new file mode 100644
index 00000000..f1c4aa6f
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/McIgnorable.xaml.cs
@@ -0,0 +1,29 @@
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class McIgnorable : ContentPage
+ {
+ public McIgnorable ()
+ {
+ InitializeComponent ();
+ }
+
+ public McIgnorable (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void DoesNotThrow (bool useCompiledXaml)
+ {
+ var layout = new McIgnorable (useCompiledXaml);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/NameScopeTests.cs b/Xamarin.Forms.Xaml.UnitTests/NameScopeTests.cs
new file mode 100644
index 00000000..b622da27
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/NameScopeTests.cs
@@ -0,0 +1,110 @@
+using NUnit.Framework;
+
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+
+ [TestFixture]
+ public class NameScopeTests : BaseTestFixture
+ {
+ [Test]
+ public void TopLevelObjectsHaveANameScope ()
+ {
+ var xaml = @"
+ <View
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" />";
+
+ var view = new CustomView ().LoadFromXaml (xaml);
+
+ Assert.IsNotNull (Forms.Internals.NameScope.GetNameScope (view));
+ Assert.That (Forms.Internals.NameScope.GetNameScope (view), Is.TypeOf<Forms.Internals.NameScope> ());
+ }
+
+ [Test]
+ public void NameScopeAreSharedWithChildren ()
+ {
+ var xaml = @"
+ <StackLayout
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" >
+ <Label />
+ <Label />
+ </StackLayout>";
+
+ var layout = new StackLayout ().LoadFromXaml (xaml);
+
+ Assert.IsNotNull (Forms.Internals.NameScope.GetNameScope (layout));
+ Assert.That (Forms.Internals.NameScope.GetNameScope (layout), Is.TypeOf<Forms.Internals.NameScope> ());
+
+ foreach (var child in layout.Children) {
+ Assert.IsNotNull (Forms.Internals.NameScope.GetNameScope (child));
+ Assert.That (Forms.Internals.NameScope.GetNameScope (child), Is.TypeOf<Forms.Internals.NameScope> ());
+ Assert.AreSame (Forms.Internals.NameScope.GetNameScope (layout), Forms.Internals.NameScope.GetNameScope (child));
+ }
+ }
+
+ [Test]
+ public void DataTemplateChildrenDoesNotParticipateToParentNameScope ()
+ {
+ var xaml = @"
+ <ListView
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ x:Name=""listview"">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <TextCell Text=""{Binding name}"" x:Name=""textcell""/>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>";
+
+ var listview = new ListView ();
+ listview.LoadFromXaml (xaml);
+
+ Assert.AreSame (listview, ((Forms.Internals.INameScope)listview).FindByName ("listview"));
+ Assert.IsNull (((Forms.Internals.INameScope)listview).FindByName ("textcell"));
+ }
+
+ [Test]
+ public void ElementsCreatedFromDataTemplateHaveTheirOwnNameScope ()
+ {
+ var xaml = @"
+ <ListView
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ x:Name=""listview"">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <TextCell Text=""{Binding name}"" x:Name=""textcell""/>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>";
+
+ var listview = new ListView ();
+ listview.LoadFromXaml (xaml);
+ Assert.IsNotNull (Forms.Internals.NameScope.GetNameScope (listview));
+ Assert.That (Forms.Internals.NameScope.GetNameScope (listview), Is.TypeOf<Forms.Internals.NameScope> ());
+
+ var cell0 = listview.ItemTemplate.CreateContent () as Element;
+ var cell1 = listview.ItemTemplate.CreateContent () as Element;
+
+ Assert.IsNotNull (Forms.Internals.NameScope.GetNameScope (cell0));
+ Assert.That (Forms.Internals.NameScope.GetNameScope (cell0), Is.TypeOf<Forms.Internals.NameScope> ());
+ Assert.IsNotNull (Forms.Internals.NameScope.GetNameScope (cell1));
+ Assert.That (Forms.Internals.NameScope.GetNameScope (cell1), Is.TypeOf<Forms.Internals.NameScope> ());
+
+ Assert.AreNotSame (Forms.Internals.NameScope.GetNameScope (listview), Forms.Internals.NameScope.GetNameScope (cell0));
+ Assert.AreNotSame (Forms.Internals.NameScope.GetNameScope (listview), Forms.Internals.NameScope.GetNameScope (cell1));
+ Assert.AreNotSame (Forms.Internals.NameScope.GetNameScope (cell0), Forms.Internals.NameScope.GetNameScope (cell1));
+
+ Assert.IsNull (((Forms.Internals.INameScope)listview).FindByName ("textcell"));
+ Assert.NotNull (((Forms.Internals.INameScope)cell0).FindByName ("textcell"));
+ Assert.NotNull (((Forms.Internals.INameScope)cell1).FindByName ("textcell"));
+
+ Assert.AreNotSame (((Forms.Internals.INameScope)cell0).FindByName ("textcell"), ((Forms.Internals.INameScope)cell1).FindByName ("textcell"));
+
+ }
+ }
+}
diff --git a/Xamarin.Forms.Xaml.UnitTests/NullExtensionTests.cs b/Xamarin.Forms.Xaml.UnitTests/NullExtensionTests.cs
new file mode 100644
index 00000000..1831cdce
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/NullExtensionTests.cs
@@ -0,0 +1,21 @@
+using System;
+using NUnit.Framework;
+
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class NullExtensionTests : BaseTestFixture
+ {
+ [Test]
+ public void TestxNull ()
+ {
+ var markupString = "{x:Null}";
+ var serviceProvider = new Internals.XamlServiceProvider (null, null);
+ var result = (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider);
+
+ Assert.IsNull (result);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Xaml.UnitTests/OnPlatform.xaml b/Xamarin.Forms.Xaml.UnitTests/OnPlatform.xaml
new file mode 100644
index 00000000..bf44299b
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/OnPlatform.xaml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.OnPlatform">
+ <StackLayout>
+ <Label x:Name="label0">
+ <Label.IsVisible>
+ <OnPlatform x:TypeArguments="x:Boolean">
+ <OnPlatform.iOS>true</OnPlatform.iOS>
+ <OnPlatform.Android>false</OnPlatform.Android>
+ </OnPlatform>
+ </Label.IsVisible>
+ <Label.WidthRequest>
+ <OnPlatform x:TypeArguments="x:Double">
+ <OnPlatform.iOS>20</OnPlatform.iOS>
+ <OnPlatform.Android>30</OnPlatform.Android>
+ </OnPlatform>
+ </Label.WidthRequest>
+ <Label.Text>
+ <OnPlatform x:TypeArguments="x:String">
+ <OnPlatform.iOS>Foo</OnPlatform.iOS>
+ <OnPlatform.Android>Bar</OnPlatform.Android>
+ </OnPlatform>
+ </Label.Text>
+ </Label>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/OnPlatform.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/OnPlatform.xaml.cs
new file mode 100644
index 00000000..2c2c6482
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/OnPlatform.xaml.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class OnPlatform : ContentPage
+ {
+ public OnPlatform ()
+ {
+ InitializeComponent ();
+ }
+
+ public OnPlatform (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void BoolToVisibility (bool useCompiledXaml)
+ {
+ Device.OS = TargetPlatform.iOS;
+ var layout = new OnPlatform (useCompiledXaml);
+ Assert.AreEqual (true, layout.label0.IsVisible);
+
+ Device.OS = TargetPlatform.Android;
+ layout = new OnPlatform (useCompiledXaml);
+ Assert.AreEqual (false, layout.label0.IsVisible);
+ }
+ }
+
+ public void T ()
+ {
+ var onplat = new OnPlatform<bool> ();
+ var label = new Label ();
+ label.IsVisible = onplat;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/OnPlatformTests.cs b/Xamarin.Forms.Xaml.UnitTests/OnPlatformTests.cs
new file mode 100644
index 00000000..fc7283ad
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/OnPlatformTests.cs
@@ -0,0 +1,118 @@
+using NUnit.Framework;
+using System;
+
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class OnPlatformTests : BaseTestFixture
+ {
+ [Test]
+ public void ApplyToProperty ()
+ {
+ var xaml = @"
+ <ContentPage
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ xmlns:scg=""clr-namespace:System.Collections.Generic;assembly=mscorlib"">
+ <OnPlatform x:TypeArguments=""View"">
+ <OnPlatform.iOS><Button Text=""iOS""/></OnPlatform.iOS>
+ <OnPlatform.Android><Button Text=""Android""/></OnPlatform.Android>
+ <OnPlatform.WinPhone><Button Text=""WinPhone""/></OnPlatform.WinPhone>
+ </OnPlatform>
+ </ContentPage>";
+ var layout = new ContentPage ().LoadFromXaml (xaml);
+ Assert.NotNull (layout.Content);
+ }
+
+ [Test]
+ public void UseTypeConverters ()
+ {
+ var xaml = @"
+ <ContentPage xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ Title=""Grid Demo Page"">
+ <ContentPage.Padding>
+ <OnPlatform x:TypeArguments=""Thickness"">
+ <OnPlatform.iOS>
+ 0, 20, 0, 0
+ </OnPlatform.iOS>
+ <OnPlatform.Android>
+ 0, 0, 10, 0
+ </OnPlatform.Android>
+ <OnPlatform.WinPhone>
+ 0, 20, 0, 20
+ </OnPlatform.WinPhone>
+ </OnPlatform>
+ </ContentPage.Padding>
+ </ContentPage>";
+
+ ContentPage layout;
+
+ Device.OS = TargetPlatform.iOS;
+ layout = new ContentPage ().LoadFromXaml (xaml);
+ Assert.AreEqual (new Thickness (0, 20, 0, 0), layout.Padding);
+
+ Device.OS = TargetPlatform.Android;
+ layout = new ContentPage ().LoadFromXaml (xaml);
+ Assert.AreEqual (new Thickness (0, 0, 10, 0), layout.Padding);
+
+ Device.OS = TargetPlatform.WinPhone;
+ layout = new ContentPage ().LoadFromXaml (xaml);
+ Assert.AreEqual (new Thickness (0, 20, 0, 20), layout.Padding);
+ }
+
+ [Test]
+ //Issue 1480
+ public void TypeConverterAndDerivedTypes ()
+ {
+ var xaml = @"
+ <Image xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml"">
+ <Image.Source>
+ <OnPlatform x:TypeArguments=""ImageSource"">
+ <OnPlatform.iOS>icon_twitter.png</OnPlatform.iOS>
+ <OnPlatform.Android>icon_twitter.png</OnPlatform.Android>
+ <OnPlatform.WinPhone>Images/icon_twitter.png</OnPlatform.WinPhone>
+ </OnPlatform>
+ </Image.Source>
+ </Image>";
+
+ Image image;
+
+ Device.OS = TargetPlatform.iOS;
+ image = new Image ().LoadFromXaml (xaml);
+ Assert.AreEqual ("icon_twitter.png", (image.Source as FileImageSource).File);
+ }
+ }
+
+ [TestFixture]
+ public class OnIdiomTests : BaseTestFixture
+ {
+ [Test]
+ public void StackLayoutOrientation ()
+ {
+ var xaml = @"
+ <StackLayout
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml"">
+ <StackLayout.Orientation>
+ <OnIdiom x:TypeArguments=""StackOrientation"">
+ <OnIdiom.Phone>Vertical</OnIdiom.Phone>
+ <OnIdiom.Tablet>Horizontal</OnIdiom.Tablet>
+ </OnIdiom>
+ </StackLayout.Orientation>
+ <Label Text=""child0""/>
+ <Label Text=""child1""/>
+ </StackLayout>";
+ Device.Idiom = TargetIdiom.Phone;
+ var layout = new StackLayout ().LoadFromXaml (xaml);
+ Assert.AreEqual (StackOrientation.Vertical, layout.Orientation);
+
+ Device.Idiom = TargetIdiom.Tablet;
+ layout = new StackLayout ().LoadFromXaml (xaml);
+ Assert.AreEqual (StackOrientation.Horizontal, layout.Orientation);
+ }
+ }
+}
diff --git a/Xamarin.Forms.Xaml.UnitTests/Properties/AssemblyInfo.cs b/Xamarin.Forms.Xaml.UnitTests/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..894b3ecd
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Properties/AssemblyInfo.cs
@@ -0,0 +1,3 @@
+using Xamarin.Forms.Xaml;
+
+[assembly:XamlCompilationAttribute (XamlCompilationOptions.Compile)] \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Speed/SimpleContentPage.xaml b/Xamarin.Forms.Xaml.UnitTests/Speed/SimpleContentPage.xaml
new file mode 100644
index 00000000..688d998e
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Speed/SimpleContentPage.xaml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.SimpleContentPage">
+ <Label Text="Hello, Xamarin.Forms!"
+ VerticalOptions="CenterAndExpand"
+ HorizontalOptions="CenterAndExpand" />
+</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/Speed/SimpleContentPage.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Speed/SimpleContentPage.xaml.cs
new file mode 100644
index 00000000..bdf291e7
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Speed/SimpleContentPage.xaml.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+using Xamarin.Forms.Core.UnitTests;
+
+using NUnit.Framework;
+using System.Diagnostics;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class SimpleContentPageCode : ContentPage
+ {
+ public SimpleContentPageCode ()
+ {
+ Content = new Label {
+ Text="Hello, Xamarin.Forms!",
+ VerticalOptions=LayoutOptions.CenterAndExpand,
+ HorizontalOptions=LayoutOptions.CenterAndExpand
+ };
+ }
+
+ public SimpleContentPageCode (bool useCompiledXaml) : this ()
+ {
+ }
+ }
+ public partial class SimpleContentPage : ContentPage
+ {
+ public SimpleContentPage ()
+ {
+ InitializeComponent ();
+ }
+
+ public SimpleContentPage (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [SetUp]
+ public void Setup ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [Test]
+ [Ignore]
+ public void XamlCIs20TimesFasterThanXaml ()
+ {
+ var swXamlC = new Stopwatch ();
+ var swXaml = new Stopwatch ();
+
+ swXamlC.Start ();
+ for (var i = 0; i < 1000; i++)
+ new SimpleContentPage (true);
+ swXamlC.Stop ();
+
+ swXaml.Start ();
+ for (var i = 0; i < 1000; i++)
+ new SimpleContentPage (false);
+ swXaml.Stop ();
+
+ Assert.Less (swXamlC.ElapsedMilliseconds * 20, swXaml.ElapsedMilliseconds);
+ }
+
+ [Test]
+ [Ignore]
+ public void XamlCIsNotMuchSlowerThanCode ()
+ {
+ var swXamlC = new Stopwatch ();
+ var swCode = new Stopwatch ();
+
+ swXamlC.Start ();
+ for (var i = 0; i < 1000; i++)
+ new SimpleContentPage (true);
+ swXamlC.Stop ();
+
+ swCode.Start ();
+ for (var i = 0; i < 1000; i++)
+ new SimpleContentPageCode (false);
+ swCode.Stop ();
+
+ Assert.LessOrEqual (swXamlC.ElapsedMilliseconds*.2, swCode.ElapsedMilliseconds);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/StaticExtensionTests.cs b/Xamarin.Forms.Xaml.UnitTests/StaticExtensionTests.cs
new file mode 100644
index 00000000..86e02fe7
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/StaticExtensionTests.cs
@@ -0,0 +1,72 @@
+using System;
+using NUnit.Framework;
+using System.Xml;
+
+using Xamarin.Forms.Core.UnitTests;
+using System.Reflection;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class StaticExtensionTests : BaseTestFixture
+ {
+ IXamlTypeResolver typeResolver;
+
+ [SetUp]
+ public override void Setup ()
+ {
+ base.Setup ();
+ var nsManager = new XmlNamespaceManager (new NameTable ());
+ nsManager.AddNamespace ("local", "clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests");
+ nsManager.AddNamespace ("x", "http://schemas.microsoft.com/winfx/2006/xaml");
+
+ typeResolver = new Internals.XamlTypeResolver (nsManager, XamlParser.GetElementType, Assembly.GetCallingAssembly ());
+ }
+
+ [Test]
+ public void TestxStatic ()
+ {
+ //{x:Static Member=prefix:typeName.staticMemberName}
+ //{x:Static prefix:typeName.staticMemberName}
+
+ //The code entity that is referenced must be one of the following:
+ // - A constant
+ // - A static property
+ // - A field
+ // - An enumeration value
+ // All other cases should throw
+
+ var serviceProvider = new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ };
+
+ //Static property
+ var markupString = @"{x:Static Member=""local:MockxStatic.MockStaticProperty""}";
+ Assert.AreEqual ("Property", (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider));
+
+ //constant
+ markupString = @"{x:Static Member=""local:MockxStatic.MockConstant""}";
+ Assert.AreEqual ("Constant", (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider));
+
+ //field
+ markupString = @"{x:Static Member=""local:MockxStatic.MockField""}";
+ Assert.AreEqual ("Field", (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider));
+
+ //enum
+ markupString = @"{x:Static Member=""local:MockEnum.Second""}";
+ Assert.AreEqual (MockEnum.Second, (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider));
+
+ //throw on InstanceProperty
+ markupString = @"{x:Static Member=""local:MockxStatic.InstanceProperty""}";
+ Assert.Throws<XamlParseException> (()=> (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider));
+
+ //quotes are optional
+ markupString = @"{x:Static Member=local:MockxStatic.MockStaticProperty}";
+ Assert.AreEqual ("Property", (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider));
+
+ //Member is optional
+ markupString = @"{x:Static local:MockxStatic.MockStaticProperty}";
+ Assert.AreEqual ("Property", (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/StringLiterals.xaml b/Xamarin.Forms.Xaml.UnitTests/StringLiterals.xaml
new file mode 100644
index 00000000..cd40b053
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/StringLiterals.xaml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.StringLiterals">
+ <Label x:Name="label0" Text="{}Foo" />
+ <Label x:Name="label1" Text="{}{Foo}" />
+ <Label x:Name="label2">
+ {}Foo
+ </Label>
+ <Label x:Name="label3">
+ <Label.Text>
+ {}Foo
+ </Label.Text>
+ </Label>
+</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/StringLiterals.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/StringLiterals.xaml.cs
new file mode 100644
index 00000000..256ee5f9
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/StringLiterals.xaml.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class StringLiterals : ContentPage
+ {
+ public StringLiterals ()
+ {
+ InitializeComponent ();
+ }
+
+ public StringLiterals (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase(false)]
+ [TestCase(true)]
+ public void EscapedStringsAreTreatedAsLiterals (bool useCompiledXaml)
+ {
+ var layout = new StringLiterals (useCompiledXaml);
+ Assert.AreEqual ("Foo", layout.label0.Text);
+ Assert.AreEqual ("{Foo}", layout.label1.Text);
+ Assert.AreEqual ("Foo", layout.label2.Text);
+ Assert.AreEqual ("Foo", layout.label3.Text);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/StyleTests.xaml b/Xamarin.Forms.Xaml.UnitTests/StyleTests.xaml
new file mode 100644
index 00000000..8b875510
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/StyleTests.xaml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.StyleTests">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <Style TargetType="Label">
+ <Setter Property="Label.TextColor" Value="Red"/>
+ </Style>
+ <Style x:Key="styleKey0" x:Name="style0" TargetType="Label">
+ <Setter Property="Label.Text" Value="FooBar"/>
+ <Setter Property="Label.BackgroundColor" Value="Pink"/>
+ </Style>
+ <Style x:Key="styleKey1" x:Name="style1" TargetType="Label">
+ <Setter Property="Label.Height" Value="42"/>
+ <Setter Property="Label.BackgroundColor" Value="Pink"/>
+ <Setter Property="Image.Source" Value="foo.png"/>
+ </Style>
+ <Style TargetType="Label" x:Key="style0" x:Name="style2">
+ <Setter Property="Text" Value="foo"/>
+ <Setter Property="BackgroundColor" Value="Red"/>
+ </Style>
+ <Style x:Key="labelStyle" TargetType="Label"
+ BaseResourceKey="TitleStyle">
+ <Setter Property="TextColor" Value="Red" />
+ </Style>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ <StackLayout>
+ <Label x:Name="label0" Style="{StaticResource styleKey0}"/>
+ <Label x:Name="label1" />
+ <Label x:Name="labelWithStyleDerivedFromDynamic_StaticResource" Style="{StaticResource labelStyle}"/>
+ <Label x:Name="labelWithStyleDerivedFromDynamic_DynamicResource" Style="{DynamicResource labelStyle}"/>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/StyleTests.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/StyleTests.xaml.cs
new file mode 100644
index 00000000..7041ff77
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/StyleTests.xaml.cs
@@ -0,0 +1,117 @@
+using System.Linq;
+
+using NUnit.Framework;
+
+using Xamarin.Forms;
+using Xamarin.Forms.Xaml.UnitTests;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class StyleTests : ContentPage
+ {
+ public StyleTests ()
+ {
+ InitializeComponent ();
+ }
+
+ public StyleTests (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [SetUp]
+ public void SetUp ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ Application.Current = new MockApplication ();
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestStyle (bool useCompiledXaml)
+ {
+ var layout = new StyleTests (useCompiledXaml);
+ Assert.That (layout.style0, Is.InstanceOf<Style> ());
+ Assert.AreSame (layout.style0, layout.label0.Style);
+ Assert.AreEqual ("FooBar", layout.label0.Text);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void TestConversionOnSetters (bool useCompiledXaml)
+ {
+ var layout = new StyleTests (useCompiledXaml);
+ Style style = layout.style1;
+ Setter setter;
+
+ //Test built-in conversions
+ setter = style.Setters.Single (s => s.Property == HeightProperty);
+ Assert.That (setter.Value, Is.TypeOf<double> ());
+ Assert.AreEqual (42d, (double)setter.Value);
+
+ //Test TypeConverters
+ setter = style.Setters.Single (s => s.Property == BackgroundColorProperty);
+ Assert.That (setter.Value, Is.TypeOf<Color> ());
+ Assert.AreEqual (Color.Pink, (Color)setter.Value);
+
+ //Test implicit cast operator
+ setter = style.Setters.Single (s => s.Property == Image.SourceProperty);
+ Assert.That (setter.Value, Is.TypeOf<FileImageSource> ());
+ Assert.AreEqual ("foo.png", ((FileImageSource)setter.Value).File);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void ImplicitStyleAreApplied (bool useCompiledXaml)
+ {
+ var layout = new StyleTests (useCompiledXaml);
+ Assert.AreEqual (Color.Red, layout.label1.TextColor);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void PropertyDoesNotNeedTypes (bool useCompiledXaml)
+ {
+ var layout = new StyleTests (useCompiledXaml);
+ Style style2 = layout.style2;
+ var s0 = style2.Setters [0];
+ var s1 = style2.Setters [1];
+ Assert.AreEqual (Label.TextProperty, s0.Property);
+ Assert.AreEqual (BackgroundColorProperty, s1.Property);
+ Assert.AreEqual (Color.Red, s1.Value);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ //issue #2406
+ public void StylesDerivedFromDynamicStylesThroughStaticResource (bool useCompiledXaml)
+ {
+ var layout = new StyleTests (useCompiledXaml);
+ Application.Current.MainPage = layout;
+
+ var label = layout.labelWithStyleDerivedFromDynamic_StaticResource;
+
+ Assert.AreEqual (50, label.FontSize);
+ Assert.AreEqual (Color.Red, label.TextColor);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ //issue #2406
+ public void StylesDerivedFromDynamicStylesThroughDynamicResource (bool useCompiledXaml)
+ {
+ var layout = new StyleTests (useCompiledXaml);
+ Application.Current.MainPage = layout;
+
+ var label = layout.labelWithStyleDerivedFromDynamic_DynamicResource;
+
+ Assert.AreEqual (50, label.FontSize);
+ Assert.AreEqual (Color.Red, label.TextColor);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/TriggerTests.xaml b/Xamarin.Forms.Xaml.UnitTests/TriggerTests.xaml
new file mode 100644
index 00000000..8d78ba93
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/TriggerTests.xaml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Forms.Xaml.UnitTests.TriggerTests">
+ <ContentPage.Content>
+ <Entry x:Name="entry">
+ <Entry.Triggers>
+ <Trigger Property="IsPassword" Value="true" TargetType="Entry">
+ <Setter Property="Scale" Value="1.2" />
+ </Trigger>
+ </Entry.Triggers>
+ </Entry>
+ </ContentPage.Content>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/TriggerTests.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/TriggerTests.xaml.cs
new file mode 100644
index 00000000..5fe61bee
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/TriggerTests.xaml.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class TriggerTests : ContentPage
+ {
+ public TriggerTests ()
+ {
+ InitializeComponent ();
+ }
+
+ public TriggerTests (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void ValueIsConverted (bool useCompiledXaml)
+ {
+ var layout = new TriggerTests (useCompiledXaml);
+ Entry entry = layout.entry;
+ Assert.NotNull (entry);
+
+ var triggers = entry.Triggers;
+ Assert.IsNotEmpty (triggers);
+ var pwTrigger = triggers [0] as Trigger;
+ Assert.AreEqual (Entry.IsPasswordProperty, pwTrigger.Property);
+ Assert.AreEqual (true, pwTrigger.Value);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/TypeConverterTests.xaml b/Xamarin.Forms.Xaml.UnitTests/TypeConverterTests.xaml
new file mode 100644
index 00000000..10cae044
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/TypeConverterTests.xaml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.TypeConverterTests">
+ <StackLayout>
+ <Image>
+ <Image.Source>
+ <UriImageSource Uri="https://xamarin.com/content/images/pages/branding/assets/xamagon.png" x:Name="imageSource"/>
+ </Image.Source>
+ </Image>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/TypeConverterTests.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/TypeConverterTests.xaml.cs
new file mode 100644
index 00000000..5125ce74
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/TypeConverterTests.xaml.cs
@@ -0,0 +1,39 @@
+using Xamarin.Forms;
+using NUnit.Framework;
+using System;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class TypeConverterTests : ContentPage
+ {
+ public TypeConverterTests ()
+ {
+ InitializeComponent ();
+ }
+
+ public TypeConverterTests (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [SetUp]
+ public void Setup ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void UriAreConverted (bool useCompiledXaml)
+ {
+ var layout = new TypeConverterTests (useCompiledXaml);
+ Assert.That (layout.imageSource.Uri, Is.TypeOf<Uri> ());
+ Assert.AreEqual ("https://xamarin.com/content/images/pages/branding/assets/xamagon.png", layout.imageSource.Uri.ToString ());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/TypeConverterTestsLegacy.cs b/Xamarin.Forms.Xaml.UnitTests/TypeConverterTestsLegacy.cs
new file mode 100644
index 00000000..c9f3a382
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/TypeConverterTestsLegacy.cs
@@ -0,0 +1,258 @@
+using System;
+using NUnit.Framework;
+using System.Xml;
+using System.Globalization;
+
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class FooConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString (string value)
+ {
+ return new Foo { Value = value };
+ }
+ }
+
+ public class BarConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString (string value)
+ {
+ return new Bar { Value = (string)value };
+ }
+ }
+
+ public class QuxConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString (string value)
+ {
+ return new Qux { Value = (string)value };
+ }
+ }
+
+ public class FooBarConverter : TypeConverter
+ {
+ public override object ConvertFromInvariantString (string value)
+ {
+ return new FooBar { Value = (string)value };
+ }
+ }
+
+ public class Foo {
+ public string Value { get; set; }
+ }
+ public class Bar {
+ public string Value { get; set; }
+ }
+ public class Baz {
+ public string Value { get; set; }
+ }
+ public class Qux {
+ public string Value { get; set; }
+ }
+
+ [TypeConverter (typeof(FooBarConverter))]
+ public class FooBar {
+ public string Value { get; set; }
+ }
+
+ public class Bindable : BindableObject
+ {
+ [TypeConverter (typeof(FooConverter))]
+ public Foo Foo { get; set; }
+
+ public static readonly BindableProperty BarProperty =
+ BindableProperty.Create<Bindable, Bar> (w => w.Bar, default(Bar));
+
+ [TypeConverter (typeof(BarConverter))]
+ public Bar Bar {
+ get { return (Bar)GetValue (BarProperty); }
+ set { SetValue (BarProperty, value); }
+ }
+
+ public Baz Baz { get; set; }
+
+ public static readonly BindableProperty QuxProperty =
+ BindableProperty.CreateAttached<Bindable, Qux> (bindable => GetQux (bindable), default(Qux));
+
+ [TypeConverter (typeof(QuxConverter))]
+ public static Qux GetQux (BindableObject bindable)
+ {
+ return (Qux)bindable.GetValue (QuxProperty);
+ }
+
+ public static void SetQux (BindableObject bindable, Qux value)
+ {
+ bindable.SetValue (QuxProperty, value);
+ }
+
+ public FooBar FooBar { get; set; }
+ }
+
+ internal class MockNameSpaceResolver : IXmlNamespaceResolver
+ {
+ public System.Collections.Generic.IDictionary<string, string> GetNamespacesInScope (XmlNamespaceScope scope)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public string LookupNamespace (string prefix)
+ {
+ return "";
+ }
+
+ public string LookupPrefix (string namespaceName)
+ {
+ return "";
+ }
+ }
+
+ [TestFixture]
+ public class TypeConverterTestsLegacy : BaseTestFixture
+ {
+ [Test]
+ public void TestSetPropertyWithoutConverter ()
+ {
+ var baz = new Baz ();
+ var node = new ValueNode (baz, new MockNameSpaceResolver());
+ var bindable = new Bindable ();
+
+ Assert.IsNull (bindable.Baz);
+ var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable) {
+ Properties = {
+ { new XmlName (null, "Baz"), node },
+ }
+ };
+ var context = new HydratationContext { RootElement = new Label () };
+ rootNode.Accept (new CreateValuesVisitor(context), null);
+ node.Accept (new ApplyPropertiesVisitor (context), rootNode);
+ Assert.AreEqual (baz, bindable.Baz);
+
+ }
+
+ [Test]
+ public void TestFailOnMissingOrWrongConverter ()
+ {
+ var node = new ValueNode ("baz", new MockNameSpaceResolver());
+ var bindable = new Bindable ();
+
+ Assert.IsNull (bindable.Baz);
+ var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable) {
+ Properties = {
+ { new XmlName (null, "Baz"), node },
+ }
+ };
+ var context = new HydratationContext { RootElement = new Label () };
+ rootNode.Accept (new CreateValuesVisitor (context), null);
+ Assert.Throws<XamlParseException>(()=> node.Accept (new ApplyPropertiesVisitor (context), rootNode));
+ }
+
+ [Test]
+ public void TestConvertNonBindableProperty ()
+ {
+ var node = new ValueNode ("foo", new MockNameSpaceResolver());
+ var bindable = new Bindable ();
+
+ Assert.IsNull (bindable.Foo);
+ var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable) {
+ Properties = {
+ { new XmlName (null, "Foo"), node },
+ }
+ };
+
+ var context = new HydratationContext { RootElement = new Label () };
+ rootNode.Accept (new CreateValuesVisitor(context), null);
+ node.Accept (new ApplyPropertiesVisitor (context), rootNode);
+ Assert.IsNotNull (bindable.Foo);
+ Assert.That (bindable.Foo, Is.TypeOf<Foo> ());
+ Assert.AreEqual ("foo", bindable.Foo.Value);
+ }
+
+ [Test]
+ public void TestConvertBindableProperty ()
+ {
+ var node = new ValueNode ("bar", new MockNameSpaceResolver());
+ var bindable = new Bindable ();
+
+ Assert.IsNull (bindable.Bar);
+ var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable) {
+ Properties = {
+ { new XmlName (null, "Bar"), node },
+ }
+ };
+ var context = new HydratationContext { RootElement = new Label () };
+ rootNode.Accept (new CreateValuesVisitor(context), null);
+ node.Accept (new ApplyPropertiesVisitor (context), rootNode);
+ Assert.IsNotNull (bindable.Bar);
+ Assert.That (bindable.Bar, Is.TypeOf<Bar> ());
+ Assert.AreEqual ("bar", bindable.Bar.Value);
+ }
+
+ [Test]
+ public void TestConvertAttachedBindableProperty ()
+ {
+ var node = new ValueNode ("qux", new MockNameSpaceResolver());
+ var bindable = new Bindable ();
+
+ Assert.IsNull (Bindable.GetQux (bindable));
+ var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable) {
+ Properties = {
+ { new XmlName ("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests", "Bindable.Qux"), node },
+ }
+ };
+ var context = new HydratationContext { RootElement = new Label () };
+ rootNode.Accept (new CreateValuesVisitor (context), null);
+ node.Accept (new ApplyPropertiesVisitor (context), rootNode);
+ Assert.IsNotNull (Bindable.GetQux (bindable));
+ Assert.That (Bindable.GetQux (bindable), Is.TypeOf<Qux> ());
+ Assert.AreEqual ("qux", Bindable.GetQux (bindable).Value);
+ }
+
+ [Test]
+ public void TestConvertWithAttributeOnType ()
+ {
+ var node = new ValueNode ("foobar", new MockNameSpaceResolver());
+ var bindable = new Bindable ();
+
+ Assert.IsNull (bindable.FooBar);
+ var rootNode = new XamlLoader.RuntimeRootNode (new XmlType("clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests","Bindable",null), bindable) {
+ Properties = {
+ { new XmlName (null, "FooBar"), node },
+ }
+ };
+ var context = new HydratationContext { RootElement = new Label () };
+ rootNode.Accept (new CreateValuesVisitor (context), null);
+ node.Accept (new ApplyPropertiesVisitor (context), rootNode);
+
+ Assert.IsNotNull (bindable.FooBar);
+ Assert.That (bindable.FooBar, Is.TypeOf<FooBar> ());
+ Assert.AreEqual ("foobar", bindable.FooBar.Value);
+ }
+
+ #if !WINDOWS_PHONE
+ [Test]
+ [SetCulture ("fr-FR")]
+ public void TestCultureOnThicknessFR ()
+ {
+ TestCultureOnThickness ();
+ }
+ #endif
+
+ [Test]
+ #if !WINDOWS_PHONE
+ [SetCulture ("en-GB")]
+ #endif
+ public void TestCultureOnThicknessEN ()
+ {
+ TestCultureOnThickness ();
+ }
+
+ public void TestCultureOnThickness ()
+ {
+ var xaml = @"<Page Padding=""1.1, 2""/>";
+ var page = new Page ().LoadFromXaml (xaml);
+ Assert.AreEqual (new Thickness (1.1, 2), page.Padding);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/TypeExtensionTests.cs b/Xamarin.Forms.Xaml.UnitTests/TypeExtensionTests.cs
new file mode 100644
index 00000000..49c4bb49
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/TypeExtensionTests.cs
@@ -0,0 +1,54 @@
+using System;
+using NUnit.Framework;
+using System.Xml;
+
+using Xamarin.Forms.Core.UnitTests;
+using System.Reflection;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+
+ [TestFixture]
+ public class TypeExtensionTests : BaseTestFixture
+ {
+ IXamlTypeResolver typeResolver;
+ Internals.XamlServiceProvider serviceProvider;
+
+ [SetUp]
+ public override void Setup ()
+ {
+ base.Setup ();
+ var nsManager = new XmlNamespaceManager (new NameTable ());
+ nsManager.AddNamespace ("local", "clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests");
+ nsManager.AddNamespace ("sys", "clr-namespace:System;assembly=mscorlib");
+ nsManager.AddNamespace ("x", "http://schemas.microsoft.com/winfx/2006/xaml");
+
+ typeResolver = new Internals.XamlTypeResolver (nsManager, XamlParser.GetElementType, Assembly.GetCallingAssembly ());
+
+ serviceProvider = new Internals.XamlServiceProvider (null, null) {
+ IXamlTypeResolver = typeResolver,
+ };
+ }
+
+ [Test]
+ public void TestxType ()
+ {
+ var markupString = @"{x:Type sys:String}";
+ Assert.AreEqual (typeof(string), (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider));
+ }
+
+ [Test]
+ public void TestWithoutPrefix ()
+ {
+ var markupString = @"{x:Type Grid}";
+ Assert.AreEqual (typeof(Grid), (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider));
+ }
+
+ [Test]
+ public void TestWithExplicitTypeName ()
+ {
+ var markupString = @"{x:Type TypeName=sys:String}";
+ Assert.AreEqual (typeof(string), (new MarkupExtensionParser ()).ParseExpression (ref markupString, serviceProvider));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/TypeLoader.xaml b/Xamarin.Forms.Xaml.UnitTests/TypeLoader.xaml
new file mode 100644
index 00000000..d99f03e8
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/TypeLoader.xaml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"
+ xmlns:this="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.TypeLoader">
+ <StackLayout>
+ <local:CustomView x:Name="customview0" />
+ <this:CustomView x:Name="customview1" />
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/TypeLoader.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/TypeLoader.xaml.cs
new file mode 100644
index 00000000..62b4cb4c
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/TypeLoader.xaml.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class TypeLoader : ContentPage
+ {
+ public TypeLoader ()
+ {
+ InitializeComponent ();
+ }
+
+ public TypeLoader (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [SetUp]
+ public void SetUp ()
+ {
+ Device.PlatformServices = new MockPlatformServices ();
+ Application.Current = new MockApplication ();
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void LoadTypeFromXmlns (bool useCompiledXaml)
+ {
+ TypeLoader layout = null;
+ Assert.DoesNotThrow (() => layout = new TypeLoader (useCompiledXaml));
+ Assert.NotNull (layout.customview0);
+ Assert.That (layout.customview0, Is.TypeOf<CustomView> ());
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void LoadTypeFromXmlnsWithoutAssembly (bool useCompiledXaml)
+ {
+ TypeLoader layout = null;
+ Assert.DoesNotThrow (() => layout = new TypeLoader (useCompiledXaml));
+ Assert.NotNull (layout.customview1);
+ Assert.That (layout.customview1, Is.TypeOf<CustomView> ());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Validation/SetterOnNonBP.xaml b/Xamarin.Forms.Xaml.UnitTests/Validation/SetterOnNonBP.xaml
new file mode 100644
index 00000000..87252208
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Validation/SetterOnNonBP.xaml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.SetterOnNonBP"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests">
+ <local:FakeVisualElement>
+ <local:FakeVisualElement.Style>
+ <Style TargetType="local:FakeVisualElement">
+ <Setter Property="NonBindable" Value="Should Fail"/>
+ </Style>
+ </local:FakeVisualElement.Style>
+ </local:FakeVisualElement>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Validation/SetterOnNonBP.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Validation/SetterOnNonBP.xaml.cs
new file mode 100644
index 00000000..f6d8ffea
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Validation/SetterOnNonBP.xaml.cs
@@ -0,0 +1,34 @@
+using NUnit.Framework;
+
+using Xamarin.Forms;
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class FakeVisualElement : VisualElement
+ {
+ public string NonBindable { get; set; }
+ }
+
+ public partial class SetterOnNonBP : ContentPage
+ {
+ public SetterOnNonBP ()
+ {
+ InitializeComponent ();
+ }
+
+ public SetterOnNonBP (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class SetterOnNonBPTests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void ShouldThrow (bool useCompiledXaml)
+ {
+ Assert.Throws (new XamlParseExceptionConstraint (10, 13), () => new SetterOnNonBP (useCompiledXaml));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Validation/StaticExtensionException.xaml b/Xamarin.Forms.Xaml.UnitTests/Validation/StaticExtensionException.xaml
new file mode 100644
index 00000000..b8dc5b5d
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Validation/StaticExtensionException.xaml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Forms.Xaml.UnitTests.StaticExtensionException">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <Style TargetType="Label" x:Key="foo">
+ <Setter Property="TextColor" Value="{x:Static local:Colors.ButtonText}"/>
+ </Style>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Validation/StaticExtensionException.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Validation/StaticExtensionException.xaml.cs
new file mode 100644
index 00000000..d7476b74
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Validation/StaticExtensionException.xaml.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class StaticExtensionException : ContentPage
+ {
+ public StaticExtensionException ()
+ {
+ InitializeComponent ();
+ }
+
+ public StaticExtensionException (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Issue2115
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void xStaticThrowsMeaningfullException (bool useCompiledXaml)
+ {
+ Assert.Throws (new XamlParseExceptionConstraint (6, 34), () => new StaticExtensionException (useCompiledXaml));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Validation/TypeMismatch.xaml b/Xamarin.Forms.Xaml.UnitTests/Validation/TypeMismatch.xaml
new file mode 100644
index 00000000..6b994bba
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Validation/TypeMismatch.xaml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.TypeMismatch">
+ <StackLayout>
+ <ContentView Content="foobar"/>
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Validation/TypeMismatch.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Validation/TypeMismatch.xaml.cs
new file mode 100644
index 00000000..43a4459c
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Validation/TypeMismatch.xaml.cs
@@ -0,0 +1,32 @@
+using System;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class TypeMismatch : ContentPage
+ {
+ public TypeMismatch ()
+ {
+ InitializeComponent ();
+ }
+
+ public TypeMismatch (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+// [TestCase (true)]
+ public void ThrowsOnMismatchingType (bool useCompiledXaml)
+ {
+ Assert.Throws (new XamlParseExceptionConstraint (7, 16, m => m.StartsWith ("Cannot assign property", StringComparison.Ordinal)), () => new TypeMismatch (useCompiledXaml));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/ViewExtensionsTest.cs b/Xamarin.Forms.Xaml.UnitTests/ViewExtensionsTest.cs
new file mode 100644
index 00000000..57c6e353
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/ViewExtensionsTest.cs
@@ -0,0 +1,59 @@
+using NUnit.Framework;
+using System;
+
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class ViewExtensionsTest : BaseTestFixture
+ {
+ [Test]
+ public void TestGetResource ()
+ {
+ var resource = new object ();
+ var view = new View {
+ Resources = new ResourceDictionary {
+ { "foo", resource }
+ },
+ };
+ var found = view.Resources ["foo"];
+ Assert.AreSame (resource, found);
+ }
+
+ [Test]
+ public void TestResourceNotFound ()
+ {
+ var view = new View ();
+ var resource = view.Resources!= null ? view.Resources ["foo"] : null;
+ Assert.Null (resource);
+ }
+
+ [Test]
+ public void TestGetResourceInParents ()
+ {
+ var resource = new object ();
+ var nestedView = new View ();
+ var stack = new StackLayout {
+ Children = {
+ new StackLayout {
+ Children = {
+ new StackLayout {
+ Children = {
+ nestedView
+ }
+ }
+ }
+ }
+ }
+ };
+ stack.Resources = new ResourceDictionary {
+ { "foo", resource }
+ };
+
+ var found = stack.Resources ["foo"];
+ Assert.AreSame (resource, found);
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/X2009Primitives.xaml b/Xamarin.Forms.Xaml.UnitTests/X2009Primitives.xaml
new file mode 100644
index 00000000..a7a91edc
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/X2009Primitives.xaml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.X2009Primitives">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <x:String x:Key="aString">foobar</x:String>
+ <x:String x:Key="defaultString"/>
+
+ <x:Object x:Key="syncHandle"/>
+
+ <x:Boolean x:Key="falsebool">false</x:Boolean>
+ <x:Boolean x:Key="truebool">true</x:Boolean>
+ <x:Boolean x:Key="defaultbool"/>
+
+ <x:Char x:Key="singleChar">f</x:Char>
+ <x:Char x:Key="multipleChar">foo</x:Char>
+ <x:Char x:Key="defaultChar"/>
+
+ <x:Decimal x:Key="aDecimal">1000.0</x:Decimal>
+ <x:Decimal x:Key="defaultDecimal"/>
+ <x:Single x:Key="aSingle">42.2</x:Single>
+ <x:Single x:Key="defaultSingle"/>
+ <x:Double x:Key="aDouble">42.3</x:Double>
+ <x:Double x:Key="aNegativeDouble">-42.3</x:Double>
+ <x:Double x:Key="defaultDouble"/>
+ <x:Byte x:Key="aByte">54</x:Byte>
+ <x:Byte x:Key="defaultByte"/>
+ <x:Int16 x:Key="anInt16">43</x:Int16>
+ <x:Int16 x:Key="defaultInt16"/>
+ <x:Int32 x:Key="anInt32">44</x:Int32>
+ <x:Int32 x:Key="defaultInt32"/>
+ <x:Int64 x:Key="anInt64">45</x:Int64>
+ <x:Int64 x:Key="defaultInt64"/>
+ <x:TimeSpan x:Key="aTimeSpan">6.12:14:45.3448000</x:TimeSpan>
+ <x:TimeSpan x:Key="defaultTimeSpan"/>
+ <x:Uri x:Key="anUri">http://xamarin.com/forms</x:Uri>
+ <x:Uri x:Key="defaultUri"/>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/X2009Primitives.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/X2009Primitives.xaml.cs
new file mode 100644
index 00000000..60ead7ca
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/X2009Primitives.xaml.cs
@@ -0,0 +1,233 @@
+using System;
+using System.Collections.Generic;
+
+using NUnit.Framework;
+
+using Xamarin.Forms;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class X2009Primitives : ContentPage
+ {
+ public X2009Primitives ()
+ {
+ InitializeComponent ();
+ }
+
+ public X2009Primitives (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SupportsXString (bool useCompiledXaml)
+ {
+ var layout = new X2009Primitives (useCompiledXaml);
+ Assert.True (layout.Resources.ContainsKey ("aString"));
+ Assert.AreEqual ("foobar", layout.Resources ["aString"]);
+
+ Assert.True (layout.Resources.ContainsKey ("defaultString"));
+ Assert.AreEqual (String.Empty, layout.Resources ["defaultString"]);
+
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SupportsXObject (bool useCompiledXaml)
+ {
+ var layout = new X2009Primitives (useCompiledXaml);
+ Assert.True (layout.Resources.ContainsKey ("syncHandle"));
+ var value = layout.Resources ["syncHandle"];
+ Assert.NotNull (value);
+ Assert.That (value, Is.TypeOf<object> ());
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SupportsXBoolean (bool useCompiledXaml)
+ {
+ var layout = new X2009Primitives (useCompiledXaml);
+
+ Assert.True (layout.Resources.ContainsKey ("falsebool"));
+ var falsebool = layout.Resources ["falsebool"];
+ Assert.NotNull (falsebool);
+ Assert.That (falsebool, Is.TypeOf<bool> ());
+ Assert.AreEqual (false, (bool)falsebool);
+
+ Assert.True (layout.Resources.ContainsKey ("truebool"));
+ var truebool = layout.Resources ["truebool"];
+ Assert.NotNull (truebool);
+ Assert.That (truebool, Is.TypeOf<bool> ());
+ Assert.AreEqual (true, (bool)truebool);
+
+ Assert.True (layout.Resources.ContainsKey ("defaultbool"));
+ var defaultbool = layout.Resources ["defaultbool"];
+ Assert.NotNull (defaultbool);
+ Assert.That (defaultbool, Is.TypeOf<bool> ());
+ Assert.AreEqual (default(bool), (bool)defaultbool);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SupportsXChar (bool useCompiledXaml)
+ {
+ var layout = new X2009Primitives (useCompiledXaml);
+
+ Assert.True (layout.Resources.ContainsKey ("singleChar"));
+ var singleChar = layout.Resources ["singleChar"];
+ Assert.NotNull (singleChar);
+ Assert.That (singleChar, Is.TypeOf<char> ());
+ Assert.AreEqual ('f', (char)singleChar);
+
+ Assert.True (layout.Resources.ContainsKey ("multipleChar"));
+ var multipleChar = layout.Resources ["multipleChar"];
+ Assert.NotNull (multipleChar);
+ Assert.That (multipleChar, Is.TypeOf<char> ());
+ Assert.AreEqual (default(char), (char)multipleChar);
+
+ Assert.True (layout.Resources.ContainsKey ("defaultChar"));
+ var defaultChar = layout.Resources ["defaultChar"];
+ Assert.NotNull (defaultChar);
+ Assert.That (defaultChar, Is.TypeOf<char> ());
+ Assert.AreEqual (default(char), (char)defaultChar);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SupportsXNumbers (bool useCompiledXaml)
+ {
+ var layout = new X2009Primitives (useCompiledXaml);
+
+ Assert.True (layout.Resources.ContainsKey ("aDecimal"));
+ var aDecimal = layout.Resources ["aDecimal"];
+ Assert.NotNull (aDecimal);
+ Assert.That (aDecimal, Is.TypeOf<decimal> ());
+ Assert.AreEqual (1000, (decimal)aDecimal);
+
+ Assert.True (layout.Resources.ContainsKey ("defaultDecimal"));
+ var defaultDecimal = layout.Resources ["defaultDecimal"];
+ Assert.NotNull (defaultDecimal);
+ Assert.That (defaultDecimal, Is.TypeOf<decimal> ());
+ Assert.AreEqual (default(decimal), (decimal)defaultDecimal);
+
+ Assert.True (layout.Resources.ContainsKey ("aSingle"));
+ var aSingle = layout.Resources ["aSingle"];
+ Assert.NotNull (aSingle);
+ Assert.That (aSingle, Is.TypeOf<float> ());
+ Assert.AreEqual (42.2f, (float)aSingle, .0001f);
+
+ Assert.True (layout.Resources.ContainsKey ("defaultSingle"));
+ var defaultSingle = layout.Resources ["defaultSingle"];
+ Assert.NotNull (defaultSingle);
+ Assert.That (defaultSingle, Is.TypeOf<Single> ());
+ Assert.AreEqual (default(float), (float)defaultSingle, .0001f);
+
+ Assert.True (layout.Resources.ContainsKey ("aDouble"));
+ var aDouble = layout.Resources ["aDouble"];
+ Assert.NotNull (aDouble);
+ Assert.That (aDouble, Is.TypeOf<double> ());
+ Assert.AreEqual (42.3d, (double)aDouble, .0001d);
+
+ Assert.True (layout.Resources.ContainsKey ("aNegativeDouble"));
+ var aNegativeDouble = layout.Resources ["aNegativeDouble"];
+ Assert.NotNull (aNegativeDouble);
+ Assert.That (aNegativeDouble, Is.TypeOf<double> ());
+ Assert.AreEqual (-42.3d, (double)aNegativeDouble, .0001d);
+
+ Assert.True (layout.Resources.ContainsKey ("defaultDouble"));
+ var defaultDouble = layout.Resources ["defaultDouble"];
+ Assert.NotNull (defaultDouble);
+ Assert.That (defaultDouble, Is.TypeOf<double> ());
+ Assert.AreEqual (default(double), (double)defaultDouble, .0001d);
+
+ Assert.True (layout.Resources.ContainsKey ("aByte"));
+ var aByte = layout.Resources ["aByte"];
+ Assert.NotNull (aByte);
+ Assert.That (aByte, Is.TypeOf<byte> ());
+ Assert.AreEqual (54, (byte)aByte);
+
+ Assert.True (layout.Resources.ContainsKey ("defaultByte"));
+ var defaultByte = layout.Resources ["defaultByte"];
+ Assert.NotNull (defaultByte);
+ Assert.That (defaultByte, Is.TypeOf<byte> ());
+ Assert.AreEqual (default(byte), (byte)defaultByte);
+
+ Assert.True (layout.Resources.ContainsKey ("anInt16"));
+ var anInt16 = layout.Resources ["anInt16"];
+ Assert.NotNull (anInt16);
+ Assert.That (anInt16, Is.TypeOf<short> ());
+ Assert.AreEqual (43, (short)anInt16);
+
+ Assert.True (layout.Resources.ContainsKey ("defaultInt16"));
+ var defaultInt16 = layout.Resources ["defaultInt16"];
+ Assert.NotNull (defaultInt16);
+ Assert.That (defaultInt16, Is.TypeOf<short> ());
+ Assert.AreEqual (default(short), (short)defaultInt16);
+
+ Assert.True (layout.Resources.ContainsKey ("anInt32"));
+ var anInt32 = layout.Resources ["anInt32"];
+ Assert.NotNull (anInt32);
+ Assert.That (anInt32, Is.TypeOf<int> ());
+ Assert.AreEqual (44, (int)anInt32);
+
+ Assert.True (layout.Resources.ContainsKey ("defaultInt32"));
+ var defaultInt32 = layout.Resources ["defaultInt32"];
+ Assert.NotNull (defaultInt32);
+ Assert.That (defaultInt32, Is.TypeOf<int> ());
+ Assert.AreEqual (default(int), (int)defaultInt32);
+
+ Assert.True (layout.Resources.ContainsKey ("anInt64"));
+ var anInt64 = layout.Resources ["anInt64"];
+ Assert.NotNull (anInt64);
+ Assert.That (anInt64, Is.TypeOf<long> ());
+ Assert.AreEqual (45, (long)anInt64);
+
+ Assert.True (layout.Resources.ContainsKey ("defaultInt64"));
+ var defaultInt64 = layout.Resources ["defaultInt64"];
+ Assert.NotNull (defaultInt64);
+ Assert.That (defaultInt64, Is.TypeOf<long> ());
+ Assert.AreEqual (default(long), (long)defaultInt64);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SupportsXTimeSpan (bool useCompiledXaml)
+ {
+ var layout = new X2009Primitives (useCompiledXaml);
+
+ Assert.True (layout.Resources.ContainsKey ("aTimeSpan"));
+ var aTimeSpan = layout.Resources ["aTimeSpan"];
+ Assert.NotNull (aTimeSpan);
+ Assert.That (aTimeSpan, Is.TypeOf<TimeSpan> ());
+ Assert.AreEqual (new TimeSpan (6, 12, 14, 45, 344).Add (TimeSpan.FromTicks (8000)), (TimeSpan)aTimeSpan);
+
+ Assert.True (layout.Resources.ContainsKey ("defaultTimeSpan"));
+ var defaultTimeSpan = layout.Resources ["defaultTimeSpan"];
+ Assert.NotNull (defaultTimeSpan);
+ Assert.That (defaultTimeSpan, Is.TypeOf<TimeSpan> ());
+ Assert.AreEqual (default(TimeSpan), (TimeSpan)defaultTimeSpan);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SupportsXUri (bool useCompiledXaml)
+ {
+ var layout = new X2009Primitives (useCompiledXaml);
+
+ Assert.True (layout.Resources.ContainsKey ("anUri"));
+ var anUri = layout.Resources ["anUri"];
+ Assert.NotNull (anUri);
+ Assert.That (anUri, Is.TypeOf<Uri> ());
+ Assert.AreEqual (new Uri ("http://xamarin.com/forms"), (Uri)anUri);
+
+ Assert.True (layout.Resources.ContainsKey ("defaultUri"));
+ var defaultUri = layout.Resources ["defaultUri"];
+ Assert.Null (defaultUri);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/XArray.xaml b/Xamarin.Forms.Xaml.UnitTests/XArray.xaml
new file mode 100644
index 00000000..efd878c0
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/XArray.xaml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<local:MockBindableForArray
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:sys="clr-namespace:System;assembly=mscorlib"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests;assembly=Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.XArray">
+ <x:Array Type="{x:Type sys:String}" x:Key="array">
+ <x:String>Hello</x:String>
+ <x:String>World</x:String>
+ </x:Array>
+</local:MockBindableForArray> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/XArray.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/XArray.xaml.cs
new file mode 100644
index 00000000..52327f25
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/XArray.xaml.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [ContentProperty ("Content")]
+ public class MockBindableForArray : View
+ {
+ public object Content { get; set; }
+ }
+
+ public partial class XArray : MockBindableForArray
+ {
+ public XArray ()
+ {
+ InitializeComponent ();
+ }
+
+ public XArray (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SupportsXArray (bool useCompiledXaml)
+ {
+ var layout = new XArray (useCompiledXaml);
+ var array = layout.Content;
+ Assert.NotNull (array);
+ Assert.That (array, Is.TypeOf<string[]> ());
+ Assert.AreEqual (2, ((string[])layout.Content).Length);
+ Assert.AreEqual ("Hello", ((string[])layout.Content) [0]);
+ Assert.AreEqual ("World", ((string[])layout.Content) [1]);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/XNull.xaml b/Xamarin.Forms.Xaml.UnitTests/XNull.xaml
new file mode 100644
index 00000000..4670e30b
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/XNull.xaml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.XNull">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <x:Null x:Key="null"/>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/XNull.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/XNull.xaml.cs
new file mode 100644
index 00000000..60ec785d
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/XNull.xaml.cs
@@ -0,0 +1,32 @@
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class XNull : ContentPage
+ {
+ public XNull ()
+ {
+ InitializeComponent ();
+ }
+
+ public XNull (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase(false)]
+ [TestCase(true)]
+ public void SupportsXNull (bool useCompiledXaml)
+ {
+ var layout = new XNull (useCompiledXaml);
+ Assert.True (layout.Resources.ContainsKey ("null"));
+ Assert.Null (layout.Resources ["null"]);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/XReference.xaml b/Xamarin.Forms.Xaml.UnitTests/XReference.xaml
new file mode 100644
index 00000000..f09af13e
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/XReference.xaml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.XReference">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <Image x:Name="image" x:Key="imageKey"/>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+ <StackLayout>
+ <ContentView x:Name="imageView" Content="{x:Reference image}"/>
+ <Button
+ x:Name="aButton"
+ Text="My Button"
+ Command="{Binding ButtonClickCommand}"
+ CommandParameter="{x:Reference aButton}"/>
+ <StackLayout>
+ <Label x:Name="label0" Text="foo" BindingContext="{x:Reference label1}"/>
+ <Label x:Name="label1" Text="bar" BindingContext="{x:Reference label0}"/>
+ <Entry x:Name="entry" Text="{Binding Text, Source={x:Reference label0}}" Placeholder="{Binding Text, Source={x:Reference label1}}"/>
+ </StackLayout>
+
+<!-- <ListView x:Name="listView">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <StackLayout>
+ <Label x:Name="foo" BindingContext="{x:Reference bar}"/>
+ <Label x:Name="bar" BindingContext="{x:Reference foo}"/>
+ </StackLayout>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>-->
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/XReference.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/XReference.xaml.cs
new file mode 100644
index 00000000..e3ad9e75
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/XReference.xaml.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class XReference : ContentPage
+ {
+ public XReference ()
+ {
+ InitializeComponent ();
+ }
+
+ public XReference (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void SupportsXReference (bool useCompiledXaml)
+ {
+ var layout = new XReference (useCompiledXaml);
+ Assert.AreSame (layout.image, layout.imageView.Content);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void XReferenceAsCommandParameterToSelf (bool useCompiledXaml)
+ {
+ var layout = new XReference (useCompiledXaml);
+
+ var button = layout.aButton;
+ button.BindingContext = new {
+ ButtonClickCommand = new Command (o => {
+ if (o == button)
+ Assert.Pass ();
+ })
+ };
+ ((IButtonController) button).SendClicked ();
+ Assert.Fail ();
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void XReferenceAsBindingSource (bool useCompiledXaml)
+ {
+ var layout = new XReference (useCompiledXaml);
+
+ Assert.AreEqual ("foo", layout.entry.Text);
+ Assert.AreEqual ("bar", layout.entry.Placeholder);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void CrossXReference (bool useCompiledXaml)
+ {
+ var layout = new XReference (useCompiledXaml);
+
+ Assert.AreSame (layout.label0, layout.label1.BindingContext);
+ Assert.AreSame (layout.label1, layout.label0.BindingContext);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/XStatic.xaml b/Xamarin.Forms.Xaml.UnitTests/XStatic.xaml
new file mode 100644
index 00000000..7c2910cd
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/XStatic.xaml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.XStatic">
+ <StackLayout>
+ <Label x:Name="staticproperty"
+ Text="{x:Static Member=local:MockxStatic.MockStaticProperty}" />
+ <Label x:Name="memberisoptional"
+ Text="{x:Static local:MockxStatic.MockStaticProperty}" />
+ <Label x:Name="color"
+ TextColor="{x:Static local:MockxStatic.BackgroundColor}" />
+ </StackLayout>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/XStatic.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/XStatic.xaml.cs
new file mode 100644
index 00000000..ff1f0199
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/XStatic.xaml.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+
+using Xamarin.Forms;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class MockxStatic
+ {
+ public static string MockStaticProperty { get { return "Property"; } }
+ public const string MockConstant = "Constant";
+ public static string MockField = "Field";
+ public string InstanceProperty { get { return "InstanceProperty"; } }
+ public static readonly Color BackgroundColor = Color.Fuchsia;
+ }
+
+ public enum MockEnum
+ {
+ First,
+ Second,
+ Third,
+ }
+
+ public partial class XStatic : ContentPage
+ {
+ public XStatic ()
+ {
+ InitializeComponent ();
+ }
+ public XStatic (bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ public class Tests
+ {
+ [TestCase (false)]
+ [TestCase (true)]
+ public void StaticProperty (bool useCompiledXaml)
+ {
+ var layout = new XStatic (useCompiledXaml);
+ Assert.AreEqual ("Property", layout.staticproperty.Text);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void MemberOptional (bool useCompiledXaml)
+ {
+ var layout = new XStatic (useCompiledXaml);
+ Assert.AreEqual ("Property", layout.memberisoptional.Text);
+ }
+
+ [TestCase (false)]
+ [TestCase (true)]
+ public void FieldColor (bool useCompiledXaml)
+ {
+ var layout = new XStatic (useCompiledXaml);
+ Assert.AreEqual (Color.Fuchsia, layout.color.TextColor);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj b/Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj
new file mode 100644
index 00000000..114b8df1
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj
@@ -0,0 +1,608 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{4B14D295-C09B-4C38-B880-7CC768E50585}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <RootNamespace>Xamarin.Forms.Xaml.UnitTests</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Xaml.UnitTests</AssemblyName>
+ <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>full</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;TURKEY</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Mono.Cecil.Mdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Mdb.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Mono.Cecil.Pdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Pdb.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Mono.Cecil.Rocks, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+ <HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+ <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Xml" />
+ <Reference Include="Microsoft.Build.Utilities.v4.0" />
+ <Reference Include="Microsoft.Build.Framework" />
+ <Reference Include="Microsoft.Build.Tasks.v4.0" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core.UnitTests\BaseTestFixture.cs">
+ <Link>BaseTestFixture.cs</Link>
+ </Compile>
+ <Compile Include="..\Xamarin.Forms.Core.UnitTests\MockPlatformServices.cs">
+ <Link>MockPlatformServices.cs</Link>
+ </Compile>
+ <Compile Include="FontConverterTests.cs" />
+ <Compile Include="LoaderTests.cs" />
+ <Compile Include="ViewExtensionsTest.cs" />
+ <Compile Include="MarkupExpressionParserTests.cs" />
+ <Compile Include="MarkupExtensionTests.cs" />
+ <Compile Include="NameScopeTests.cs" />
+ <Compile Include="OnPlatformTests.cs" />
+ <Compile Include="StaticExtensionTests.cs" />
+ <Compile Include="NullExtensionTests.cs" />
+ <Compile Include="TypeExtensionTests.cs" />
+ <Compile Include="FactoryMethodTests.cs" />
+ <Compile Include="XamlgTests.cs" />
+ <Compile Include="Issues\TestCases.cs" />
+ <Compile Include="Issues\Issue1493.cs" />
+ <Compile Include="Issues\Issue1501.cs" />
+ <Compile Include="Issues\Issue1497.cs" />
+ <Compile Include="Issues\Issue1545.cs" />
+ <Compile Include="Issues\Issue1554.cs" />
+ <Compile Include="Issues\Issue1549.cs" />
+ <Compile Include="Issues\Issue1637.cs" />
+ <Compile Include="Issues\Issue1564.cs" />
+ <Compile Include="Issues\Issue1641.cs" />
+ <Compile Include="Issues\Issue1594.cs" />
+ <Compile Include="XamlgFileLockTests.cs" />
+ <Compile Include="DummyBuildEngine.cs" />
+ <Compile Include="Issues\Issue1794.cs" />
+ <Compile Include="StyleTests.xaml.cs">
+ <DependentUpon>StyleTests.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="CustomXamlView.xaml.cs">
+ <DependentUpon>CustomXamlView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="TriggerTests.xaml.cs">
+ <DependentUpon>TriggerTests.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue2016.xaml.cs">
+ <DependentUpon>Issue2016.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Compiled\FindByName.xaml.cs">
+ <DependentUpon>FindByName.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Validation\SetterOnNonBP.xaml.cs">
+ <DependentUpon>SetterOnNonBP.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="XamlParseExceptionConstraint.cs" />
+ <Compile Include="Issues\Issue2062.xaml.cs">
+ <DependentUpon>Issue2062.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue2114.xaml.cs">
+ <DependentUpon>Issue2114.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue2125.xaml.cs">
+ <DependentUpon>Issue2125.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Validation\StaticExtensionException.xaml.cs">
+ <DependentUpon>StaticExtensionException.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue2152.xaml.cs">
+ <DependentUpon>Issue2152.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="ImplicitConversions.xaml.cs">
+ <DependentUpon>ImplicitConversions.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue2450.xaml.cs">
+ <DependentUpon>Issue2450.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Validation\TypeMismatch.xaml.cs">
+ <DependentUpon>TypeMismatch.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue2578.xaml.cs">
+ <DependentUpon>Issue2578.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue2489.xaml.cs">
+ <DependentUpon>Issue2489.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue2659.xaml.cs">
+ <DependentUpon>Issue2659.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="TypeLoader.xaml.cs">
+ <DependentUpon>TypeLoader.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="StringLiterals.xaml.cs">
+ <DependentUpon>StringLiterals.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue2742.xaml.cs">
+ <DependentUpon>Issue2742.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Compiled\SetValue.xaml.cs">
+ <DependentUpon>SetValue.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="X2009Primitives.xaml.cs">
+ <DependentUpon>X2009Primitives.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="XArray.xaml.cs">
+ <DependentUpon>XArray.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="XReference.xaml.cs">
+ <DependentUpon>XReference.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="DataTemplate.xaml.cs">
+ <DependentUpon>DataTemplate.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="XNull.xaml.cs">
+ <DependentUpon>XNull.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="OnPlatform.xaml.cs">
+ <DependentUpon>OnPlatform.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="XStatic.xaml.cs">
+ <DependentUpon>XStatic.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="XamlC\FieldReferenceExtensionsTests.cs" />
+ <Compile Include="XamlC\PropertyDefinitionExtensionsTests.cs" />
+ <Compile Include="XamlC\MethodReferenceExtensionsTests.cs" />
+ <Compile Include="DynamicResource.xaml.cs">
+ <DependentUpon>DynamicResource.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue1199.xaml.cs">
+ <DependentUpon>Issue1199.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue1213.xaml.cs">
+ <DependentUpon>Issue1213.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue1250.xaml.cs">
+ <DependentUpon>Issue1250.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue1306.xaml.cs">
+ <DependentUpon>Issue1306.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue1415.xaml.cs">
+ <DependentUpon>Issue1415.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue1438.xaml.cs">
+ <DependentUpon>Issue1438.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Speed\SimpleContentPage.xaml.cs">
+ <DependentUpon>SimpleContentPage.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue3076.xaml.cs">
+ <DependentUpon>Issue3076.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="ConstraintExpression.xaml.cs">
+ <DependentUpon>ConstraintExpression.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue3090.xaml.cs">
+ <DependentUpon>Issue3090.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Issue3106.xaml.cs">
+ <DependentUpon>Issue3106.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz28689.xaml.cs">
+ <DependentUpon>Bz28689.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz27863.xaml.cs">
+ <DependentUpon>Bz27863.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz24910.xaml.cs">
+ <DependentUpon>Bz24910.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz28719.xaml.cs">
+ <DependentUpon>Bz28719.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz30074.xaml.cs">
+ <DependentUpon>Bz30074.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz29300.xaml.cs">
+ <DependentUpon>Bz29300.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="GenericsTests.xaml.cs">
+ <DependentUpon>GenericsTests.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz27968.xaml.cs">
+ <DependentUpon>Bz27968.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz28545.xaml.cs">
+ <DependentUpon>Bz28545.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz27299.xaml.cs">
+ <DependentUpon>Bz27299.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz24485.xaml.cs">
+ <DependentUpon>Bz24485.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz30684.xaml.cs">
+ <DependentUpon>Bz30684.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz28556.xaml.cs">
+ <DependentUpon>Bz28556.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz31234\A\Bz31234.xaml.cs">
+ <DependentUpon>Bz31234.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz31234\B\Bz31234.xaml.cs">
+ <DependentUpon>Bz31234.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz31529.xaml.cs">
+ <DependentUpon>Bz31529.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz34037.xaml.cs">
+ <DependentUpon>Bz34037.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="EventsConnection.xaml.cs">
+ <DependentUpon>EventsConnection.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="GenericCollections.xaml.cs">
+ <DependentUpon>GenericCollections.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Pr3384.xaml.cs">
+ <DependentUpon>Pr3384.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="FactoryMethods.xaml.cs">
+ <DependentUpon>FactoryMethods.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Unreported002.xaml.cs">
+ <DependentUpon>Unreported002.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Unreported001.xaml.cs">
+ <DependentUpon>Unreported001.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz36422.xaml.cs">
+ <DependentUpon>Bz36422.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz37306.xaml.cs">
+ <DependentUpon>Bz37306.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\BPNotResolvedOnSubClass.xaml.cs">
+ <DependentUpon>BPNotResolvedOnSubClass.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Bz37524.xaml.cs">
+ <DependentUpon>Bz37524.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\Unreported003.xaml.cs">
+ <DependentUpon>Unreported003.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\GrialIssue01.xaml.cs">
+ <DependentUpon>GrialIssue01.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Issues\GrialIssue02.xaml.cs">
+ <DependentUpon>GrialIssue02.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="TypeConverterTestsLegacy.cs" />
+ <Compile Include="TypeConverterTests.xaml.cs">
+ <DependentUpon>TypeConverterTests.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="IsCompiledDefault.xaml.cs">
+ <DependentUpon>IsCompiledDefault.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="IsCompiledSkip.xaml.cs">
+ <DependentUpon>IsCompiledSkip.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="McIgnorable.xaml.cs">
+ <DependentUpon>McIgnorable.xaml</DependentUpon>
+ </Compile>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <Import Project="..\.nuspec\Xamarin.Forms.Debug.targets" />
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Platform\Xamarin.Forms.Platform.csproj">
+ <Project>{67F9D3A8-F71E-4428-913F-C37AE82CDB24}</Project>
+ <Name>Xamarin.Forms.Platform</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Xaml\Xamarin.Forms.Xaml.csproj">
+ <Project>{9DB2F292-8034-4E06-89AD-98BBDA4306B9}</Project>
+ <Name>Xamarin.Forms.Xaml</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Build.Tasks\Xamarin.Forms.Build.Tasks.csproj">
+ <Project>{96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}</Project>
+ <Name>Xamarin.Forms.Build.Tasks</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Controls\Xamarin.Forms.Controls.csproj">
+ <Project>{CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}</Project>
+ <Name>Xamarin.Forms.Controls</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+ <Project>{7D13BAC2-C6A4-416A-B07E-C169B199E52B}</Project>
+ <Name>Xamarin.Forms.Maps</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ProjectExtensions>
+ <MonoDevelop>
+ <Properties>
+ <Policies>
+ <StandardHeader Text="" IncludeInNewFiles="True" />
+ </Policies>
+ </Properties>
+ </MonoDevelop>
+ </ProjectExtensions>
+ <ItemGroup>
+ <EmbeddedResource Include="CustomXamlView.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="StyleTests.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="TriggerTests.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue2016.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Validation\SetterOnNonBP.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue2062.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue2114.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue2125.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Validation\StaticExtensionException.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue2152.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="ImplicitConversions.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue2450.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Validation\TypeMismatch.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue2578.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue2489.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue2659.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="TypeLoader.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="StringLiterals.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue2742.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Compiled\FindByName.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Compiled\SetValue.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="X2009Primitives.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="XArray.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="XReference.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="DataTemplate.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="XNull.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="OnPlatform.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="XStatic.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="DynamicResource.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue1199.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue1213.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue1250.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue1306.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue1415.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue1438.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Speed\SimpleContentPage.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue3076.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="ConstraintExpression.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue3090.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Issue3106.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz28689.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz27863.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz24910.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz28719.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz30074.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz29300.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="GenericsTests.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz27968.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz28545.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz27299.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz24485.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz30684.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz28556.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz31234\A\Bz31234.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz31234\B\Bz31234.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz31529.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz34037.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="EventsConnection.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="GenericCollections.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Pr3384.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="FactoryMethods.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Unreported002.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Unreported001.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz36422.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz37306.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\BPNotResolvedOnSubClass.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Bz37524.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\Unreported003.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\GrialIssue01.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Issues\GrialIssue02.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="TypeConverterTests.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="IsCompiledDefault.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="IsCompiledSkip.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ <EmbeddedResource Include="McIgnorable.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.config" />
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+ </Target>
+ <ItemGroup />
+</Project>
diff --git a/Xamarin.Forms.Xaml.UnitTests/XamlC/FieldReferenceExtensionsTests.cs b/Xamarin.Forms.Xaml.UnitTests/XamlC/FieldReferenceExtensionsTests.cs
new file mode 100644
index 00000000..79144f98
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/XamlC/FieldReferenceExtensionsTests.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Linq;
+
+using Mono.Cecil;
+
+using Xamarin.Forms.Build.Tasks;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.XamlcUnitTests
+{
+ [TestFixture]
+ public class FieldReferenceExtensionsTests
+ {
+ public class NonGenericClass {
+ public object Field;
+ }
+
+ public class GenericClass<T1,T2> {
+ public object NonGenericField;
+ public T1 GenericField1;
+ public T2 GenericField2;
+ }
+
+ public class Inheritor : GenericClass<string,double>
+ {
+ }
+
+ ModuleDefinition module;
+
+ [SetUp]
+ public void SetUp ()
+ {
+ module = ModuleDefinition.CreateModule ("foo", ModuleKind.Dll);
+ }
+
+ [Test]
+ public void ResolveGenericsOnNonGenericDoesNotThrow ()
+ {
+ var type = module.Import (typeof (NonGenericClass));
+ TypeReference declaringTypeReference;
+ FieldDefinition field = type.GetField (fd => fd.Name == "Field", out declaringTypeReference);
+ Assert.DoesNotThrow (() => field.ResolveGenericParameters (declaringTypeReference));
+ }
+
+ [Test]
+ public void NonGenericFieldOnGenericType ()
+ {
+ var type = module.Import (typeof (Inheritor));
+ TypeReference declaringTypeReference;
+ FieldDefinition field = type.GetField (fd => fd.Name == "NonGenericField", out declaringTypeReference);
+ Assert.AreEqual ("NonGenericField", field.Name);
+ Assert.AreEqual ("Xamarin.Forms.Xaml.XamlcUnitTests.FieldReferenceExtensionsTests/GenericClass`2", field.DeclaringType.FullName);
+ Assert.False (field.DeclaringType.IsGenericInstance);
+ var genericField = field.ResolveGenericParameters (declaringTypeReference);
+ Assert.AreEqual ("NonGenericField", genericField.Name);
+ Assert.AreEqual ("Xamarin.Forms.Xaml.XamlcUnitTests.FieldReferenceExtensionsTests/GenericClass`2<System.String,System.Double>", genericField.DeclaringType.FullName);
+ Assert.True (genericField.DeclaringType.IsGenericInstance);
+ }
+
+ [Test]
+ public void GenericFieldOnGenericType ()
+ {
+ var type = module.Import (typeof (Inheritor));
+ TypeReference declaringTypeReference;
+
+ FieldDefinition field1 = type.GetField (fd => fd.Name == "GenericField1", out declaringTypeReference);
+ Assert.AreEqual ("GenericField1", field1.Name);
+ Assert.AreEqual ("Xamarin.Forms.Xaml.XamlcUnitTests.FieldReferenceExtensionsTests/GenericClass`2", field1.DeclaringType.FullName);
+ Assert.False (field1.DeclaringType.IsGenericInstance);
+ Assert.True (field1.FieldType.IsGenericParameter);
+ Assert.AreEqual ("T1", field1.FieldType.FullName);
+
+ var genericField1 = field1.ResolveGenericParameters (declaringTypeReference);
+ Assert.AreEqual ("GenericField1", genericField1.Name);
+ Assert.AreEqual ("Xamarin.Forms.Xaml.XamlcUnitTests.FieldReferenceExtensionsTests/GenericClass`2<System.String,System.Double>", genericField1.DeclaringType.FullName);
+ Assert.True (genericField1.DeclaringType.IsGenericInstance);
+ Assert.False (genericField1.FieldType.IsGenericParameter);
+ Assert.AreEqual ("System.String", genericField1.FieldType.FullName);
+
+ FieldDefinition field2 = type.GetField (fd => fd.Name == "GenericField2", out declaringTypeReference);
+ Assert.AreEqual ("GenericField2", field2.Name);
+ Assert.AreEqual ("Xamarin.Forms.Xaml.XamlcUnitTests.FieldReferenceExtensionsTests/GenericClass`2", field2.DeclaringType.FullName);
+ Assert.False (field2.DeclaringType.IsGenericInstance);
+ Assert.True (field2.FieldType.IsGenericParameter);
+ Assert.AreEqual ("T2", field2.FieldType.FullName);
+
+ var genericField2 = field2.ResolveGenericParameters (declaringTypeReference);
+ Assert.AreEqual ("GenericField2", genericField2.Name);
+ Assert.AreEqual ("Xamarin.Forms.Xaml.XamlcUnitTests.FieldReferenceExtensionsTests/GenericClass`2<System.String,System.Double>", genericField2.DeclaringType.FullName);
+ Assert.True (genericField2.DeclaringType.IsGenericInstance);
+ Assert.False (genericField2.FieldType.IsGenericParameter);
+ Assert.AreEqual ("System.Double", genericField2.FieldType.FullName);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/XamlC/MethodReferenceExtensionsTests.cs b/Xamarin.Forms.Xaml.UnitTests/XamlC/MethodReferenceExtensionsTests.cs
new file mode 100644
index 00000000..ab7925ac
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/XamlC/MethodReferenceExtensionsTests.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Linq;
+
+using Mono.Cecil;
+
+using Xamarin.Forms.Build.Tasks;
+
+using NUnit.Framework;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Xaml.XamlcUnitTests
+{
+ [TestFixture]
+ public class MethodReferenceExtensionsTests
+ {
+ ModuleDefinition module;
+
+ [SetUp]
+ public void SetUp ()
+ {
+ module = ModuleDefinition.CreateModule ("foo", ModuleKind.Dll);
+ }
+
+ [Test]
+ public void ResolveRowDefAdder ()
+ {
+ var propertyType = module.Import(typeof (RowDefinitionCollection));
+ var adderT = propertyType.GetMethods ((md, tr) => md.Name == "Add", module).Single ();
+ var adder = adderT.Item1;
+ var ptype = adderT.Item2;
+ Assert.AreEqual ("System.Void Xamarin.Forms.DefinitionCollection`1::Add(T)", adder.FullName);
+ Assert.AreEqual ("Xamarin.Forms.DefinitionCollection`1<Xamarin.Forms.RowDefinition>", ptype.FullName);
+ var adderRef = module.Import (adder);
+ Assert.AreEqual ("System.Void Xamarin.Forms.DefinitionCollection`1::Add(T)", adderRef.FullName);
+ adderRef = adderRef.ResolveGenericParameters (ptype, module);
+ Assert.AreEqual ("System.Void Xamarin.Forms.DefinitionCollection`1<Xamarin.Forms.RowDefinition>::Add(T)", adderRef.FullName);
+ }
+
+ [Test]
+ public void GenericGetter ()
+ {
+ TypeReference declaringTypeReference;
+ var type = module.Import (typeof (StackLayout));
+ var property = type.GetProperty (pd => pd.Name == "Children", out declaringTypeReference);
+ Assert.AreEqual ("System.Collections.Generic.IList`1<T> Xamarin.Forms.Layout`1::Children()", property.FullName);
+ Assert.AreEqual ("Xamarin.Forms.Layout`1<Xamarin.Forms.View>", declaringTypeReference.FullName);
+ var propertyGetter = property.GetMethod;
+ Assert.AreEqual ("System.Collections.Generic.IList`1<T> Xamarin.Forms.Layout`1::get_Children()", propertyGetter.FullName);
+ var propertyGetterRef = module.Import (propertyGetter);
+ Assert.AreEqual ("System.Collections.Generic.IList`1<T> Xamarin.Forms.Layout`1::get_Children()", propertyGetterRef.FullName);
+
+ propertyGetterRef = module.Import (propertyGetterRef.ResolveGenericParameters (declaringTypeReference, module));
+ Assert.AreEqual ("System.Collections.Generic.IList`1<T> Xamarin.Forms.Layout`1<Xamarin.Forms.View>::get_Children()", propertyGetterRef.FullName);
+ var returnType = propertyGetterRef.ReturnType.ResolveGenericParameters (declaringTypeReference);
+ Assert.AreEqual ("System.Collections.Generic.IList`1<Xamarin.Forms.View>", returnType.FullName);
+ }
+
+ [Test]
+ public void GetterWithGenericReturnType ()
+ {
+ TypeReference declaringTypeReference;
+ var type = module.Import (typeof (Style));
+ var property = type.GetProperty (pd => pd.Name == "Setters", out declaringTypeReference);
+ Assert.AreEqual ("System.Collections.Generic.IList`1<Xamarin.Forms.Setter> Xamarin.Forms.Style::Setters()", property.FullName);
+ Assert.AreEqual ("Xamarin.Forms.Style", declaringTypeReference.FullName);
+ var propertyGetter = property.GetMethod;
+ Assert.AreEqual ("System.Collections.Generic.IList`1<Xamarin.Forms.Setter> Xamarin.Forms.Style::get_Setters()", propertyGetter.FullName);
+
+ var propertyGetterRef = module.Import (propertyGetter);
+ Assert.AreEqual ("System.Collections.Generic.IList`1<Xamarin.Forms.Setter> Xamarin.Forms.Style::get_Setters()", propertyGetterRef.FullName);
+ propertyGetterRef = module.Import (propertyGetterRef.ResolveGenericParameters (declaringTypeReference, module));
+ Assert.AreEqual ("System.Collections.Generic.IList`1<Xamarin.Forms.Setter> Xamarin.Forms.Style::get_Setters()", propertyGetterRef.FullName);
+ var returnType = propertyGetterRef.ReturnType.ResolveGenericParameters (declaringTypeReference);
+ Assert.AreEqual ("System.Collections.Generic.IList`1<Xamarin.Forms.Setter>", returnType.FullName);
+ }
+
+ [Test]
+ public void ResolveChildren ()
+ {
+ var propertyType = module.Import (typeof (IList<View>));
+ var adderT = propertyType.GetMethods (md => md.Name == "Add" && md.Parameters.Count == 1, module).Single ();
+ var adder = adderT.Item1;
+ var ptype = adderT.Item2;
+ Assert.AreEqual ("System.Void System.Collections.Generic.ICollection`1::Add(T)", adder.FullName);
+ Assert.AreEqual ("System.Collections.Generic.ICollection`1<Xamarin.Forms.View>", ptype.FullName);
+ var adderRef = module.Import (adder);
+ Assert.AreEqual ("System.Void System.Collections.Generic.ICollection`1::Add(T)", adderRef.FullName);
+ adderRef = adderRef.ResolveGenericParameters (ptype, module);
+ Assert.AreEqual ("System.Void System.Collections.Generic.ICollection`1<Xamarin.Forms.View>::Add(T)", adderRef.FullName);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/XamlC/PropertyDefinitionExtensionsTests.cs b/Xamarin.Forms.Xaml.UnitTests/XamlC/PropertyDefinitionExtensionsTests.cs
new file mode 100644
index 00000000..b43e4c9d
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/XamlC/PropertyDefinitionExtensionsTests.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Linq;
+
+using Mono.Cecil;
+
+using Xamarin.Forms.Build.Tasks;
+
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.XamlcUnitTests
+{
+ [TestFixture]
+ public class PropertyDefinitionExtensionsTests
+ {
+ public class NonGenericClass
+ {
+ public object Property { get; set; }
+ }
+
+ public class GenericClass<T>
+ {
+ public object Property { get; set; }
+ public T GenericProperty { get; set; }
+ }
+
+ ModuleDefinition module;
+
+ [SetUp]
+ public void SetUp ()
+ {
+ module = ModuleDefinition.CreateModule ("foo", ModuleKind.Dll);
+ }
+
+// [Test]
+// public void ResolveGenericsOnNonGenericPreserveAccessors ()
+// {
+// var type = module.Import (typeof (NonGenericClass));
+// TypeReference declaringTypeReference;
+// PropertyDefinition prop = type.GetProperty (fd => fd.Name == "Property", out declaringTypeReference);
+// Assert.AreEqual ("System.Object", prop.PropertyType.FullName);
+// Assert.AreEqual ("System.Void Xamarin.Forms.Xaml.XamlcUnitTests.PropertyDefinitionExtensionsTests/NonGenericClass::set_Property(System.Object)", prop.SetMethod.FullName);
+// Assert.AreEqual ("System.Object Xamarin.Forms.Xaml.XamlcUnitTests.PropertyDefinitionExtensionsTests/NonGenericClass::get_Property()", prop.GetMethod.FullName);
+// Assert.AreEqual ("Xamarin.Forms.Xaml.XamlcUnitTests.PropertyDefinitionExtensionsTests/NonGenericClass", prop.DeclaringType.FullName);
+//
+// prop.ResolveGenericParameters (declaringTypeReference);
+//
+// Assert.AreEqual ("System.Object", prop.PropertyType.FullName);
+// Assert.AreEqual ("System.Void Xamarin.Forms.Xaml.XamlcUnitTests.PropertyDefinitionExtensionsTests/NonGenericClass::set_Property(System.Object)", prop.SetMethod.FullName);
+// Assert.AreEqual ("System.Object Xamarin.Forms.Xaml.XamlcUnitTests.PropertyDefinitionExtensionsTests/NonGenericClass::get_Property()", prop.GetMethod.FullName);
+// Assert.AreEqual ("Xamarin.Forms.Xaml.XamlcUnitTests.PropertyDefinitionExtensionsTests/NonGenericClass", prop.DeclaringType.FullName);
+//
+// }
+//
+// [Test]
+// public void NonGenericPropertyOnGenericType ()
+// {
+// var type = module.Import (typeof (GenericClass<bool>));
+// TypeReference declaringTypeReference;
+// PropertyDefinition prop = type.GetProperty (fd => fd.Name == "Property", out declaringTypeReference);
+// Assert.AreEqual ("System.Object", prop.PropertyType.FullName);
+// Assert.AreEqual ("System.Void Xamarin.Forms.Xaml.XamlcUnitTests.PropertyDefinitionExtensionsTests/GenericClass`1::set_Property(System.Object)", prop.SetMethod.FullName);
+// Assert.AreEqual ("System.Object Xamarin.Forms.Xaml.XamlcUnitTests.PropertyDefinitionExtensionsTests/GenericClass`1::get_Property()", prop.GetMethod.FullName);
+// Assert.AreEqual ("Xamarin.Forms.Xaml.XamlcUnitTests.PropertyDefinitionExtensionsTests/GenericClass`1", prop.DeclaringType.FullName);
+// Assert.False (prop.DeclaringType.IsGenericInstance);
+//
+// prop.ResolveGenericParameters (declaringTypeReference);
+// Assert.AreEqual ("System.Object", prop.PropertyType.FullName);
+// Assert.AreEqual ("System.Void Xamarin.Forms.Xaml.XamlcUnitTests.PropertyDefinitionExtensionsTests/GenericClass`1::set_Property(System.Object)", prop.SetMethod.FullName);
+// Assert.AreEqual ("System.Object Xamarin.Forms.Xaml.XamlcUnitTests.PropertyDefinitionExtensionsTests/GenericClass`1::get_Property()", prop.GetMethod.FullName);
+// Assert.AreEqual ("Xamarin.Forms.Xaml.XamlcUnitTests.PropertyDefinitionExtensionsTests/GenericClass`1", prop.DeclaringType.FullName);
+// Assert.True (prop.DeclaringType.IsGenericInstance);
+//
+// }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/XamlParseExceptionConstraint.cs b/Xamarin.Forms.Xaml.UnitTests/XamlParseExceptionConstraint.cs
new file mode 100644
index 00000000..cdff5ca8
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/XamlParseExceptionConstraint.cs
@@ -0,0 +1,67 @@
+using System;
+using NUnit.Framework.Constraints;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class XamlParseExceptionConstraint : ExceptionTypeConstraint
+ {
+ bool haslineinfo;
+ int linenumber;
+ int lineposition;
+ Func<string, bool> messagePredicate;
+
+ XamlParseExceptionConstraint (bool haslineinfo) : base (typeof (XamlParseException))
+ {
+ this.haslineinfo = haslineinfo;
+ DisplayName = "xamlparse";
+ }
+
+ public XamlParseExceptionConstraint () : this (false)
+ {
+ }
+
+ public XamlParseExceptionConstraint (int linenumber, int lineposition, Func<string, bool> messagePredicate = null) : this (true)
+ {
+ this.linenumber = linenumber;
+ this.lineposition = lineposition;
+ this.messagePredicate = messagePredicate;
+ }
+
+ public override bool Matches (object actual)
+ {
+ this.actual = actual;
+ if (!base.Matches (actual))
+ return false;
+ var xmlInfo = ((XamlParseException)actual).XmlInfo;
+ if (!haslineinfo)
+ return true;
+ if (xmlInfo == null || !xmlInfo.HasLineInfo ())
+ return false;
+ if (messagePredicate != null)
+ if (!messagePredicate (((XamlParseException)actual).UnformattedMessage))
+ return false;
+ return xmlInfo.LineNumber == linenumber && xmlInfo.LinePosition == lineposition;
+ }
+
+ public override void WriteDescriptionTo (MessageWriter writer)
+ {
+ base.WriteDescriptionTo (writer);
+ if (haslineinfo)
+ writer.Write (string.Format (" line {0}, position {1}", linenumber, lineposition));
+ }
+
+ public override void WriteActualValueTo (MessageWriter writer)
+ {
+ var ex = actual as XamlParseException;
+ writer.WriteActualValue ((actual == null) ? null : actual.GetType ());
+ if (ex != null) {
+ if (ex.XmlInfo != null && ex.XmlInfo.HasLineInfo ())
+ writer.Write (" line {0}, position {1}", ex.XmlInfo.LineNumber, ex.XmlInfo.LinePosition);
+ else
+ writer.Write (" no line info");
+ writer.WriteLine (" ({0})", ex.Message);
+ writer.Write (ex.StackTrace);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/XamlgFileLockTests.cs b/Xamarin.Forms.Xaml.UnitTests/XamlgFileLockTests.cs
new file mode 100644
index 00000000..4034ef5b
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/XamlgFileLockTests.cs
@@ -0,0 +1,43 @@
+using System;
+using System.IO;
+using NUnit.Framework;
+using Xamarin.Forms.Build.Tasks;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class XamlgFileLockTests : BaseTestFixture
+ {
+ string CreateXamlInputFile ()
+ {
+ string xaml =
+ @"<ContentPage xmlns='http://xamarin.com/schemas/2014/forms' xmlns:x='http://schemas.microsoft.com/winfx/2009/xaml' x:Class='Test.MyPage'>
+ <ContentPage.Content></ContentPage.Content>
+ </ContentPage>";
+
+ string fileName = Path.GetTempFileName ();
+ File.WriteAllText (fileName, xaml);
+
+ return fileName;
+ }
+
+ [Test]
+ public void XamlFileShouldNotBeLockedAfterFileIsGenerated ()
+ {
+ string xamlInputFile = CreateXamlInputFile ();
+ string xamlOutputFile = Path.ChangeExtension (xamlInputFile, ".xaml.g.cs");
+ var generator = new XamlGTask ();
+ generator.BuildEngine = new DummyBuildEngine ();
+ generator.AssemblyName = "Test";
+ generator.Source = xamlInputFile;
+ generator.OutputFile = xamlOutputFile;
+ generator.Language = "C#";
+
+ generator.Execute();
+ File.Delete (xamlOutputFile);
+
+ Assert.DoesNotThrow (() => File.Delete (xamlInputFile));
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/XamlgTests.cs b/Xamarin.Forms.Xaml.UnitTests/XamlgTests.cs
new file mode 100644
index 00000000..9303539e
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/XamlgTests.cs
@@ -0,0 +1,300 @@
+using System;
+using NUnit.Framework;
+using System.IO;
+using System.CodeDom;
+using Xamarin.Forms.Build.Tasks;
+using System.Collections.Generic;
+using System.Linq;
+
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [TestFixture]
+ public class XamlgTests : BaseTestFixture
+ {
+ [Test]
+ public void LoadXaml2006 ()
+ {
+ var xaml = @"<View
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
+ x:Class=""Xamarin.Forms.Xaml.UnitTests.CustomView"" >
+ <Label x:Name=""label0""/>
+ </View>";
+
+ var reader = new StringReader (xaml);
+ string rootType, rootNs;
+ CodeTypeReference baseType;
+ IDictionary<string,CodeTypeReference> namesAndTypes;
+
+ XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes);
+ Assert.NotNull (rootType);
+ Assert.NotNull (rootNs);
+ Assert.NotNull (baseType);
+ Assert.NotNull (namesAndTypes);
+
+ Assert.AreEqual ("CustomView", rootType);
+ Assert.AreEqual ("Xamarin.Forms.Xaml.UnitTests", rootNs);
+ Assert.AreEqual ("Xamarin.Forms.View", baseType.BaseType);
+ Assert.AreEqual (1, namesAndTypes.Count);
+ Assert.AreEqual ("label0", namesAndTypes.First().Key);
+ Assert.AreEqual ("Xamarin.Forms.Label", namesAndTypes.First().Value.BaseType);
+ }
+
+ [Test]
+ public void LoadXaml2009 ()
+ {
+ var xaml = @"<View
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ x:Class=""Xamarin.Forms.Xaml.UnitTests.CustomView"" >
+ <Label x:Name=""label0""/>
+ </View>";
+
+ var reader = new StringReader (xaml);
+ string rootType, rootNs;
+ CodeTypeReference baseType;
+ IDictionary<string,CodeTypeReference> namesAndTypes;
+
+ XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes);
+ Assert.NotNull (rootType);
+ Assert.NotNull (rootNs);
+ Assert.NotNull (baseType);
+ Assert.NotNull (namesAndTypes);
+
+ Assert.AreEqual ("CustomView", rootType);
+ Assert.AreEqual ("Xamarin.Forms.Xaml.UnitTests", rootNs);
+ Assert.AreEqual ("Xamarin.Forms.View", baseType.BaseType);
+ Assert.AreEqual (1, namesAndTypes.Count);
+ Assert.AreEqual ("label0", namesAndTypes.First().Key);
+ Assert.AreEqual ("Xamarin.Forms.Label", namesAndTypes.First().Value.BaseType);
+ }
+
+ [Test]
+ //https://github.com/xamarin/Duplo/issues/1207#issuecomment-47159917
+ public void xNameInCustomTypes ()
+ {
+ var xaml = @"<ContentPage
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ xmlns:local=""clr-namespace:CustomListViewSample;assembly=CustomListViewSample""
+ x:Class=""CustomListViewSample.TestPage"">
+ <StackLayout
+ VerticalOptions=""CenterAndExpand""
+ HorizontalOptions=""CenterAndExpand"">
+ <Label Text=""Hello, Custom Renderer!"" />
+ <local:CustomListView x:Name=""listView""
+ WidthRequest=""960"" CornerRadius=""50"" OutlineColor=""Blue"" />
+ </StackLayout>
+</ContentPage>";
+
+ var reader = new StringReader (xaml);
+ string rootType, rootNs;
+ CodeTypeReference baseType;
+ IDictionary<string,CodeTypeReference> namesAndTypes;
+
+ XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes);
+ Assert.AreEqual (1, namesAndTypes.Count);
+ Assert.AreEqual ("listView", namesAndTypes.First ().Key);
+ Assert.AreEqual ("CustomListViewSample.CustomListView", namesAndTypes.First ().Value.BaseType);
+
+ }
+
+ [Test]
+ public void xNameInDataTemplates ()
+ {
+ var xaml = @"<StackLayout
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ x:Class=""FooBar"" >
+ <ListView>
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <Label x:Name=""notincluded""/>
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ <Label x:Name=""included""/>
+ </StackLayout>";
+ var reader = new StringReader (xaml);
+ string rootType, rootNs;
+ CodeTypeReference baseType;
+ IDictionary<string,CodeTypeReference> namesAndTypes;
+
+ XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes);
+ Assert.Contains ("included", namesAndTypes.Keys.ToList());
+ Assert.False (namesAndTypes.Keys.Contains ("notincluded"));
+ Assert.AreEqual (1, namesAndTypes.Count);
+ }
+
+ [Test]
+ public void xNameInStyles ()
+ {
+ var xaml = @"<StackLayout
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ x:Class=""FooBar"" >
+ <StackLayout.Resources>
+ <ResourceDictionary>
+ <Style TargetType=""Label"" >
+ <Setter Property=""Text"">
+ <Setter.Value>
+ <Label x:Name=""notincluded"" />
+ </Setter.Value>
+ </Setter>
+ </Style>
+ </ResourceDictionary>
+ </StackLayout.Resources>
+ </StackLayout>";
+ var reader = new StringReader (xaml);
+ string rootType, rootNs;
+ CodeTypeReference baseType;
+ IDictionary<string,CodeTypeReference> namesAndTypes;
+
+ XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes);
+ Assert.False (namesAndTypes.Keys.Contains ("notincluded"));
+ Assert.AreEqual (0, namesAndTypes.Count);
+ }
+
+ [Test]
+ public void xTypeArgumentsOnRootElement ()
+ {
+ var xaml = @"<Foo
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ x:Class=""FooBar""
+ x:TypeArguments=""x:String""
+ />";
+ var reader = new StringReader (xaml);
+ string rootType, rootNs;
+ CodeTypeReference baseType;
+ IDictionary<string,CodeTypeReference> namesAndTypes;
+
+ XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes);
+ Assert.AreEqual ("FooBar", rootType);
+ Assert.AreEqual ("Xamarin.Forms.Foo`1", baseType.BaseType);
+ Assert.AreEqual (1, baseType.TypeArguments.Count);
+ Assert.AreEqual ("System.String", baseType.TypeArguments [0].BaseType);
+ }
+
+ [Test]
+ public void MulipleXTypeArgumentsOnRootElement ()
+ {
+ var xaml = @"<Foo
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ x:Class=""FooBar""
+ x:TypeArguments=""x:String,x:Int32""
+ />";
+ var reader = new StringReader (xaml);
+ string rootType, rootNs;
+ CodeTypeReference baseType;
+ IDictionary<string,CodeTypeReference> namesAndTypes;
+
+ XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes);
+ Assert.AreEqual ("FooBar", rootType);
+ Assert.AreEqual ("Xamarin.Forms.Foo`2", baseType.BaseType);
+ Assert.AreEqual (2, baseType.TypeArguments.Count);
+ Assert.AreEqual ("System.String", baseType.TypeArguments [0].BaseType);
+ Assert.AreEqual ("System.Int32", baseType.TypeArguments [1].BaseType);
+ }
+
+ [Test]
+ public void MulipleXTypeArgumentsOnRootElementWithWhitespace ()
+ {
+ var xaml = @"<Foo
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ x:Class=""FooBar""
+ x:TypeArguments=""x:String, x:Int32""
+ />";
+ var reader = new StringReader (xaml);
+ string rootType, rootNs;
+ CodeTypeReference baseType;
+ IDictionary<string,CodeTypeReference> namesAndTypes;
+
+ XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes);
+ Assert.AreEqual ("FooBar", rootType);
+ Assert.AreEqual ("Xamarin.Forms.Foo`2", baseType.BaseType);
+ Assert.AreEqual (2, baseType.TypeArguments.Count);
+ Assert.AreEqual ("System.String", baseType.TypeArguments [0].BaseType);
+ Assert.AreEqual ("System.Int32", baseType.TypeArguments [1].BaseType);
+ }
+
+ [Test]
+ public void MulipleXTypeArgumentsMulitpleNamespacesOnRootElement ()
+ {
+ var xaml = @"<Foo
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ x:Class=""FooBar""
+ x:TypeArguments=""nsone:IDummyInterface,nstwo:IDummyInterfaceTwo""
+ xmlns:nsone=""clr-namespace:Xamarin.Forms.Xaml.UnitTests.Bugzilla24258.Interfaces""
+ xmlns:nstwo=""clr-namespace:Xamarin.Forms.Xaml.UnitTests.Bugzilla24258.InterfacesTwo""
+
+ />";
+ var reader = new StringReader (xaml);
+ string rootType, rootNs;
+ CodeTypeReference baseType;
+ IDictionary<string,CodeTypeReference> namesAndTypes;
+
+ XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes);
+ Assert.AreEqual ("FooBar", rootType);
+ Assert.AreEqual ("Xamarin.Forms.Foo`2", baseType.BaseType);
+ Assert.AreEqual (2, baseType.TypeArguments.Count);
+ Assert.AreEqual ("Xamarin.Forms.Xaml.UnitTests.Bugzilla24258.Interfaces.IDummyInterface", baseType.TypeArguments [0].BaseType);
+ Assert.AreEqual ("Xamarin.Forms.Xaml.UnitTests.Bugzilla24258.InterfacesTwo.IDummyInterfaceTwo", baseType.TypeArguments [1].BaseType);
+ }
+
+ [Test]
+ public void MulipleXTypeArgumentsMulitpleNamespacesOnRootElementWithWhitespace ()
+ {
+ var xaml = @"<Foo
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ x:Class=""FooBar""
+ x:TypeArguments=""nsone:IDummyInterface, nstwo:IDummyInterfaceTwo""
+ xmlns:nsone=""clr-namespace:Xamarin.Forms.Xaml.UnitTests.Bugzilla24258.Interfaces""
+ xmlns:nstwo=""clr-namespace:Xamarin.Forms.Xaml.UnitTests.Bugzilla24258.InterfacesTwo""
+
+ />";
+ var reader = new StringReader (xaml);
+ string rootType, rootNs;
+ CodeTypeReference baseType;
+ IDictionary<string,CodeTypeReference> namesAndTypes;
+
+ XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes);
+ Assert.AreEqual ("FooBar", rootType);
+ Assert.AreEqual ("Xamarin.Forms.Foo`2", baseType.BaseType);
+ Assert.AreEqual (2, baseType.TypeArguments.Count);
+ Assert.AreEqual ("Xamarin.Forms.Xaml.UnitTests.Bugzilla24258.Interfaces.IDummyInterface", baseType.TypeArguments [0].BaseType);
+ Assert.AreEqual ("Xamarin.Forms.Xaml.UnitTests.Bugzilla24258.InterfacesTwo.IDummyInterfaceTwo", baseType.TypeArguments [1].BaseType);
+ }
+
+ [Test]
+ //https://bugzilla.xamarin.com/show_bug.cgi?id=33256
+ public void AlwaysUseGlobalReference ()
+ {
+ var xaml = @"
+ <ContentPage
+ xmlns=""http://xamarin.com/schemas/2014/forms""
+ xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
+ x:Class=""FooBar"" >
+ <Label x:Name=""label0""/>
+ </ContentPage>";
+ using (var reader = new StringReader (xaml)) {
+ string rootType, rootNs;
+ CodeTypeReference baseType;
+ IDictionary<string,CodeTypeReference> namesAndTypes;
+
+ XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes);
+ Assert.IsTrue (baseType.Options.HasFlag (CodeTypeReferenceOptions.GlobalReference));
+ Assert.IsTrue (namesAndTypes.Values.First ().Options.HasFlag (CodeTypeReferenceOptions.GlobalReference));
+ }
+ }
+ }
+}
+
diff --git a/Xamarin.Forms.Xaml.UnitTests/app.config b/Xamarin.Forms.Xaml.UnitTests/app.config
new file mode 100644
index 00000000..b1d2a5a3
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/app.config
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="Mono.Cecil" publicKeyToken="0738eb9f132ed756" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-0.9.6.0" newVersion="0.9.6.0" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/packages.config b/Xamarin.Forms.Xaml.UnitTests/packages.config
new file mode 100644
index 00000000..86bf3eaa
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Mono.Cecil" version="0.9.6.1" targetFramework="net451" />
+ <package id="NUnit" version="2.6.4" targetFramework="net451" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.Xamlc/Xamarin.Forms.Xaml.Xamlc.csproj b/Xamarin.Forms.Xaml.Xamlc/Xamarin.Forms.Xaml.Xamlc.csproj
new file mode 100644
index 00000000..653f812b
--- /dev/null
+++ b/Xamarin.Forms.Xaml.Xamlc/Xamarin.Forms.Xaml.Xamlc.csproj
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <RootNamespace>Xamarin.Forms.Xaml</RootNamespace>
+ <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <Externalconsole>true</Externalconsole>
+ <Commandlineparameters>-r "../../../Xamarin.Forms.Controls/bin/Debug/" -p "../../../Xamarin.Forms.Xaml.UnitTest/bin/Debug/;/Library/Frameworks/Mono.framework/Versions/3.12.1/lib/mono/4.5;/Library/Frameworks/Mono.framework/Versions/3.12.1/lib/mono/4.5/Facades/" --keep -v 4 -d ../../../Xamarin.Forms.Xaml.UnitTests/bin/Debug/Xamarin.Forms.Xaml.UnitTests.dll</Commandlineparameters>
+ <AssemblyName>xamlc</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>full</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <Externalconsole>true</Externalconsole>
+ <AssemblyName>xamlc</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Turkey|AnyCPU' ">
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Turkey</OutputPath>
+ <WarningLevel>4</WarningLevel>
+ <AssemblyName>Xamarin.Forms.Xaml.Xamlc</AssemblyName>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="Microsoft.Build.Utilities.v4.0" />
+ <Reference Include="Microsoft.Build.Framework" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Xaml.Xamlg\Mono.Options\Options.cs">
+ <Link>Mono.Options\Options.cs</Link>
+ </Compile>
+ <Compile Include="Xamlc.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <ItemGroup>
+ <Folder Include="Mono.Options\" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Build.Tasks\Xamarin.Forms.Build.Tasks.csproj">
+ <Project>{96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}</Project>
+ <Name>Xamarin.Forms.Build.Tasks</Name>
+ </ProjectReference>
+ </ItemGroup>
+</Project>
diff --git a/Xamarin.Forms.Xaml.Xamlc/Xamlc.cs b/Xamarin.Forms.Xaml.Xamlc/Xamlc.cs
new file mode 100644
index 00000000..b2fa172b
--- /dev/null
+++ b/Xamarin.Forms.Xaml.Xamlc/Xamlc.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using Mono.Options;
+using Xamarin.Forms.Build.Tasks;
+
+namespace Xamarin.Forms.Xaml
+{
+ class Xamlc
+ {
+ static readonly string help_string = "xamlc.exe - a utility for compiling XAML into IL.\n" +
+ "xamlc.exe assembly\n\n";
+
+ public static void Main(string[] args)
+ {
+ bool help = false;
+ int verbosity = 1;
+ bool keep = false;
+ bool optimize = false;
+ bool decompile = false;
+ string paths = null;
+ string refs = null;
+ var p = new OptionSet
+ {
+ { "h|?|help", "Print this help message", v => help = true },
+ { "v=|verbosity=", "0 is quiet, 1 is normal, 2 is verbose", v => verbosity = Int32.Parse(v) },
+ { "o|optimize", "Optimize generated IL", v => optimize = true },
+ { "keep", "do not strip compiled embedded xaml", v => keep = true },
+ { "p=|paths=|dependencypaths=", "look for dependencies in (comma separated) list of paths", v => paths = v },
+ { "r=", "referencepath", v => refs = v },
+ { "d|decompile", v => decompile = true }
+ };
+
+ if (help || args.Length < 1)
+ {
+ ShowHelp(p);
+ Environment.Exit(0);
+ }
+ List<string> extra = null;
+ try
+ {
+ extra = p.Parse(args);
+ }
+ catch (OptionException)
+ {
+ Console.WriteLine("Type `xamlc --help' for more information.");
+ return;
+ }
+
+ if (extra.Count == 0)
+ {
+ if (verbosity > 0)
+ {
+ Console.WriteLine("assembly missing");
+ ShowHelp(p);
+ }
+ Environment.Exit(0);
+ }
+
+ var assembly = extra[0];
+ XamlCTask.Compile(assembly, verbosity, keep, optimize, paths, refs, decompile);
+ }
+
+ static void ShowHelp(OptionSet ops)
+ {
+ Console.WriteLine(help_string);
+ ops.WriteOptionDescriptions(Console.Out);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.Xamlg/Mono.Options/Options.cs b/Xamarin.Forms.Xaml.Xamlg/Mono.Options/Options.cs
new file mode 100644
index 00000000..d74ebf64
--- /dev/null
+++ b/Xamarin.Forms.Xaml.Xamlg/Mono.Options/Options.cs
@@ -0,0 +1,1490 @@
+//
+// Options.cs
+//
+// Authors:
+// Jonathan Pryor <jpryor@novell.com>
+// Federico Di Gregorio <fog@initd.org>
+//
+// Copyright (C) 2008 Novell (http://www.novell.com)
+// Copyright (C) 2009 Federico Di Gregorio.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+// Compile With:
+// gmcs -debug+ -r:System.Core Options.cs -o:NDesk.Options.dll
+// gmcs -debug+ -d:LINQ -r:System.Core Options.cs -o:NDesk.Options.dll
+//
+// The LINQ version just changes the implementation of
+// OptionSet.Parse(IEnumerable<string>), and confers no semantic changes.
+
+//
+// A Getopt::Long-inspired option parsing library for C#.
+//
+// NDesk.Options.OptionSet is built upon a key/value table, where the
+// key is a option format string and the value is a delegate that is
+// invoked when the format string is matched.
+//
+// Option format strings:
+// Regex-like BNF Grammar:
+// name: .+
+// type: [=:]
+// sep: ( [^{}]+ | '{' .+ '}' )?
+// aliases: ( name type sep ) ( '|' name type sep )*
+//
+// Each '|'-delimited name is an alias for the associated action. If the
+// format string ends in a '=', it has a required value. If the format
+// string ends in a ':', it has an optional value. If neither '=' or ':'
+// is present, no value is supported. `=' or `:' need only be defined on one
+// alias, but if they are provided on more than one they must be consistent.
+//
+// Each alias portion may also end with a "key/value separator", which is used
+// to split option values if the option accepts > 1 value. If not specified,
+// it defaults to '=' and ':'. If specified, it can be any character except
+// '{' and '}' OR the *string* between '{' and '}'. If no separator should be
+// used (i.e. the separate values should be distinct arguments), then "{}"
+// should be used as the separator.
+//
+// Options are extracted either from the current option by looking for
+// the option name followed by an '=' or ':', or is taken from the
+// following option IFF:
+// - The current option does not contain a '=' or a ':'
+// - The current option requires a value (i.e. not a Option type of ':')
+//
+// The `name' used in the option format string does NOT include any leading
+// option indicator, such as '-', '--', or '/'. All three of these are
+// permitted/required on any named option.
+//
+// Option bundling is permitted so long as:
+// - '-' is used to start the option group
+// - all of the bundled options are a single character
+// - at most one of the bundled options accepts a value, and the value
+// provided starts from the next character to the end of the string.
+//
+// This allows specifying '-a -b -c' as '-abc', and specifying '-D name=value'
+// as '-Dname=value'.
+//
+// Option processing is disabled by specifying "--". All options after "--"
+// are returned by OptionSet.Parse() unchanged and unprocessed.
+//
+// Unprocessed options are returned from OptionSet.Parse().
+//
+// Examples:
+// int verbose = 0;
+// OptionSet p = new OptionSet ()
+// .Add ("v", v => ++verbose)
+// .Add ("name=|value=", v => Console.WriteLine (v));
+// p.Parse (new string[]{"-v", "--v", "/v", "-name=A", "/name", "B", "extra"});
+//
+// The above would parse the argument string array, and would invoke the
+// lambda expression three times, setting `verbose' to 3 when complete.
+// It would also print out "A" and "B" to standard output.
+// The returned array would contain the string "extra".
+//
+// C# 3.0 collection initializers are supported and encouraged:
+// var p = new OptionSet () {
+// { "h|?|help", v => ShowHelp () },
+// };
+//
+// System.ComponentModel.TypeConverter is also supported, allowing the use of
+// custom data types in the callback type; TypeConverter.ConvertFromString()
+// is used to convert the value option to an instance of the specified
+// type:
+//
+// var p = new OptionSet () {
+// { "foo=", (Foo f) => Console.WriteLine (f.ToString ()) },
+// };
+//
+// Random other tidbits:
+// - Boolean options (those w/o '=' or ':' in the option format string)
+// are explicitly enabled if they are followed with '+', and explicitly
+// disabled if they are followed with '-':
+// string a = null;
+// var p = new OptionSet () {
+// { "a", s => a = s },
+// };
+// p.Parse (new string[]{"-a"}); // sets v != null
+// p.Parse (new string[]{"-a+"}); // sets v != null
+// p.Parse (new string[]{"-a-"}); // sets v == null
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+using System.Text;
+using System.Text.RegularExpressions;
+
+#if LINQ
+using System.Linq;
+#endif
+
+#if TEST
+using NDesk.Options;
+#endif
+
+#if NDESK_OPTIONS
+namespace NDesk.Options
+#else
+
+namespace Mono.Options
+#endif
+{
+ internal static class StringCoda
+ {
+ public static IEnumerable<string> WrappedLines(string self, params int[] widths)
+ {
+ IEnumerable<int> w = widths;
+ return WrappedLines(self, w);
+ }
+
+ public static IEnumerable<string> WrappedLines(string self, IEnumerable<int> widths)
+ {
+ if (widths == null)
+ throw new ArgumentNullException("widths");
+ return CreateWrappedLinesIterator(self, widths);
+ }
+
+ static IEnumerable<string> CreateWrappedLinesIterator(string self, IEnumerable<int> widths)
+ {
+ if (string.IsNullOrEmpty(self))
+ {
+ yield return string.Empty;
+ yield break;
+ }
+ using(IEnumerator<int> ewidths = widths.GetEnumerator())
+ {
+ bool? hw = null;
+ int width = GetNextWidth(ewidths, int.MaxValue, ref hw);
+ int start = 0, end;
+ do
+ {
+ end = GetLineEnd(start, width, self);
+ char c = self[end - 1];
+ if (char.IsWhiteSpace(c))
+ --end;
+ bool needContinuation = end != self.Length && !IsEolChar(c);
+ string continuation = "";
+ if (needContinuation)
+ {
+ --end;
+ continuation = "-";
+ }
+ string line = self.Substring(start, end - start) + continuation;
+ yield return line;
+ start = end;
+ if (char.IsWhiteSpace(c))
+ ++start;
+ width = GetNextWidth(ewidths, width, ref hw);
+ } while (start < self.Length);
+ }
+ }
+
+ static int GetNextWidth(IEnumerator<int> ewidths, int curWidth, ref bool? eValid)
+ {
+ if (!eValid.HasValue || (eValid.HasValue && eValid.Value))
+ {
+ curWidth = (eValid = ewidths.MoveNext()).Value ? ewidths.Current : curWidth;
+ // '.' is any character, - is for a continuation
+ const string minWidth = ".-";
+ if (curWidth < minWidth.Length)
+ {
+ throw new ArgumentOutOfRangeException("widths",
+ string.Format("Element must be >= {0}, was {1}.", minWidth.Length, curWidth));
+ }
+ return curWidth;
+ }
+ // no more elements, use the last element.
+ return curWidth;
+ }
+
+ static bool IsEolChar(char c)
+ {
+ return !char.IsLetterOrDigit(c);
+ }
+
+ static int GetLineEnd(int start, int length, string description)
+ {
+ int end = System.Math.Min(start + length, description.Length);
+ int sep = -1;
+ for (int i = start; i < end; ++i)
+ {
+ if (description[i] == '\n')
+ return i + 1;
+ if (IsEolChar(description[i]))
+ sep = i + 1;
+ }
+ if (sep == -1 || end == description.Length)
+ return end;
+ return sep;
+ }
+ }
+
+ public class OptionValueCollection : IList, IList<string>
+ {
+ readonly OptionContext _c;
+
+ readonly List<string> _values = new List<string>();
+
+ internal OptionValueCollection(OptionContext c)
+ {
+ _c = c;
+ }
+
+ #region IEnumerable
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return _values.GetEnumerator();
+ }
+
+ #endregion
+
+ #region IEnumerable<T>
+
+ public IEnumerator<string> GetEnumerator()
+ {
+ return _values.GetEnumerator();
+ }
+
+ #endregion
+
+ public List<string> ToList()
+ {
+ return new List<string>(_values);
+ }
+
+ public string[] ToArray()
+ {
+ return _values.ToArray();
+ }
+
+ public override string ToString()
+ {
+ return string.Join(", ", _values.ToArray());
+ }
+
+ #region ICollection
+
+ void ICollection.CopyTo(Array array, int index)
+ {
+ (_values as ICollection).CopyTo(array, index);
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ get { return (_values as ICollection).IsSynchronized; }
+ }
+
+ object ICollection.SyncRoot
+ {
+ get { return (_values as ICollection).SyncRoot; }
+ }
+
+ #endregion
+
+ #region ICollection<T>
+
+ public void Add(string item)
+ {
+ _values.Add(item);
+ }
+
+ public void Clear()
+ {
+ _values.Clear();
+ }
+
+ public bool Contains(string item)
+ {
+ return _values.Contains(item);
+ }
+
+ public void CopyTo(string[] array, int arrayIndex)
+ {
+ _values.CopyTo(array, arrayIndex);
+ }
+
+ public bool Remove(string item)
+ {
+ return _values.Remove(item);
+ }
+
+ public int Count
+ {
+ get { return _values.Count; }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ #endregion
+
+ #region IList
+
+ int IList.Add(object value)
+ {
+ return (_values as IList).Add(value);
+ }
+
+ bool IList.Contains(object value)
+ {
+ return (_values as IList).Contains(value);
+ }
+
+ int IList.IndexOf(object value)
+ {
+ return (_values as IList).IndexOf(value);
+ }
+
+ void IList.Insert(int index, object value)
+ {
+ (_values as IList).Insert(index, value);
+ }
+
+ void IList.Remove(object value)
+ {
+ (_values as IList).Remove(value);
+ }
+
+ void IList.RemoveAt(int index)
+ {
+ (_values as IList).RemoveAt(index);
+ }
+
+ bool IList.IsFixedSize
+ {
+ get { return false; }
+ }
+
+ object IList.this[int index]
+ {
+ get { return this[index]; }
+ set { (_values as IList)[index] = value; }
+ }
+
+ #endregion
+
+ #region IList<T>
+
+ public int IndexOf(string item)
+ {
+ return _values.IndexOf(item);
+ }
+
+ public void Insert(int index, string item)
+ {
+ _values.Insert(index, item);
+ }
+
+ public void RemoveAt(int index)
+ {
+ _values.RemoveAt(index);
+ }
+
+ void AssertValid(int index)
+ {
+ if (_c.Option == null)
+ throw new InvalidOperationException("OptionContext.Option is null.");
+ if (index >= _c.Option.MaxValueCount)
+ throw new ArgumentOutOfRangeException("index");
+ if (_c.Option.OptionValueType == OptionValueType.Required &&
+ index >= _values.Count)
+ {
+ throw new OptionException(string.Format(
+ _c.OptionSet.MessageLocalizer("Missing required value for option '{0}'."), _c.OptionName),
+ _c.OptionName);
+ }
+ }
+
+ public string this[int index]
+ {
+ get
+ {
+ AssertValid(index);
+ return index >= _values.Count ? null : _values[index];
+ }
+ set { _values[index] = value; }
+ }
+
+ #endregion
+ }
+
+ public class OptionContext
+ {
+ public OptionContext(OptionSet set)
+ {
+ OptionSet = set;
+ OptionValues = new OptionValueCollection(this);
+ }
+
+ public Option Option { get; set; }
+
+ public string OptionName { get; set; }
+
+ public int OptionIndex { get; set; }
+
+ public OptionSet OptionSet { get; }
+
+ public OptionValueCollection OptionValues { get; }
+ }
+
+ public enum OptionValueType
+ {
+ None,
+ Optional,
+ Required
+ }
+
+ public abstract class Option
+ {
+ static readonly char[] NameTerminator = { '=', ':' };
+
+ protected Option(string prototype, string description)
+ : this(prototype, description, 1)
+ {
+ }
+
+ protected Option(string prototype, string description, int maxValueCount)
+ {
+ if (prototype == null)
+ throw new ArgumentNullException("prototype");
+ if (prototype.Length == 0)
+ throw new ArgumentException("Cannot be the empty string.", "prototype");
+ if (maxValueCount < 0)
+ throw new ArgumentOutOfRangeException("maxValueCount");
+
+ Prototype = prototype;
+ Description = description;
+ MaxValueCount = maxValueCount;
+ Names = (this is OptionSet.Category)
+ // append GetHashCode() so that "duplicate" categories have distinct
+ // names, e.g. adding multiple "" categories should be valid.
+ ? new[] { prototype + GetHashCode() }
+ : prototype.Split('|');
+
+ if (this is OptionSet.Category)
+ return;
+
+ OptionValueType = ParsePrototype();
+
+ if (MaxValueCount == 0 && OptionValueType != OptionValueType.None)
+ {
+ throw new ArgumentException(
+ "Cannot provide maxValueCount of 0 for OptionValueType.Required or " +
+ "OptionValueType.Optional.",
+ "maxValueCount");
+ }
+ if (OptionValueType == OptionValueType.None && maxValueCount > 1)
+ {
+ throw new ArgumentException(
+ string.Format("Cannot provide maxValueCount of {0} for OptionValueType.None.", maxValueCount),
+ "maxValueCount");
+ }
+ if (Array.IndexOf(Names, "<>") >= 0 &&
+ ((Names.Length == 1 && OptionValueType != OptionValueType.None) ||
+ (Names.Length > 1 && MaxValueCount > 1)))
+ {
+ throw new ArgumentException(
+ "The default option handler '<>' cannot require values.",
+ "prototype");
+ }
+ }
+
+ public string Prototype { get; }
+
+ public string Description { get; }
+
+ public OptionValueType OptionValueType { get; }
+
+ public int MaxValueCount { get; }
+
+ internal string[] Names { get; }
+
+ internal string[] ValueSeparators { get; private set; }
+
+ public string[] GetNames()
+ {
+ return (string[])Names.Clone();
+ }
+
+ public string[] GetValueSeparators()
+ {
+ if (ValueSeparators == null)
+ return new string[0];
+ return (string[])ValueSeparators.Clone();
+ }
+
+ protected static T Parse<T>(string value, OptionContext c)
+ {
+ Type tt = typeof (T);
+ bool nullable = tt.IsValueType && tt.IsGenericType &&
+ !tt.IsGenericTypeDefinition &&
+ tt.GetGenericTypeDefinition() == typeof (Nullable<>);
+ Type targetType = nullable ? tt.GetGenericArguments()[0] : typeof (T);
+ TypeConverter conv = TypeDescriptor.GetConverter(targetType);
+ T t = default(T);
+ try
+ {
+ if (value != null)
+ t = (T)conv.ConvertFromString(value);
+ }
+ catch (Exception e)
+ {
+ throw new OptionException(
+ string.Format(
+ c.OptionSet.MessageLocalizer("Could not convert string `{0}' to type {1} for option `{2}'."),
+ value, targetType.Name, c.OptionName),
+ c.OptionName, e);
+ }
+ return t;
+ }
+
+ OptionValueType ParsePrototype()
+ {
+ char type = '\0';
+ List<string> seps = new List<string>();
+ for (int i = 0; i < Names.Length; ++i)
+ {
+ string name = Names[i];
+ if (name.Length == 0)
+ throw new ArgumentException("Empty option names are not supported.", "prototype");
+
+ int end = name.IndexOfAny(NameTerminator);
+ if (end == -1)
+ continue;
+ Names[i] = name.Substring(0, end);
+ if (type == '\0' || type == name[end])
+ type = name[end];
+ else
+ {
+ throw new ArgumentException(
+ string.Format("Conflicting option types: '{0}' vs. '{1}'.", type, name[end]),
+ "prototype");
+ }
+ AddSeparators(name, end, seps);
+ }
+
+ if (type == '\0')
+ return OptionValueType.None;
+
+ if (MaxValueCount <= 1 && seps.Count != 0)
+ {
+ throw new ArgumentException(
+ string.Format("Cannot provide key/value separators for Options taking {0} value(s).", MaxValueCount),
+ "prototype");
+ }
+ if (MaxValueCount > 1)
+ {
+ if (seps.Count == 0)
+ ValueSeparators = new[] { ":", "=" };
+ else if (seps.Count == 1 && seps[0].Length == 0)
+ ValueSeparators = null;
+ else
+ ValueSeparators = seps.ToArray();
+ }
+
+ return type == '=' ? OptionValueType.Required : OptionValueType.Optional;
+ }
+
+ static void AddSeparators(string name, int end, ICollection<string> seps)
+ {
+ int start = -1;
+ for (int i = end + 1; i < name.Length; ++i)
+ {
+ switch (name[i])
+ {
+ case '{':
+ if (start != -1)
+ {
+ throw new ArgumentException(
+ string.Format("Ill-formed name/value separator found in \"{0}\".", name),
+ "prototype");
+ }
+ start = i + 1;
+ break;
+ case '}':
+ if (start == -1)
+ {
+ throw new ArgumentException(
+ string.Format("Ill-formed name/value separator found in \"{0}\".", name),
+ "prototype");
+ }
+ seps.Add(name.Substring(start, i - start));
+ start = -1;
+ break;
+ default:
+ if (start == -1)
+ seps.Add(name[i].ToString());
+ break;
+ }
+ }
+ if (start != -1)
+ {
+ throw new ArgumentException(
+ string.Format("Ill-formed name/value separator found in \"{0}\".", name),
+ "prototype");
+ }
+ }
+
+ public void Invoke(OptionContext c)
+ {
+ OnParseComplete(c);
+ c.OptionName = null;
+ c.Option = null;
+ c.OptionValues.Clear();
+ }
+
+ protected abstract void OnParseComplete(OptionContext c);
+
+ public override string ToString()
+ {
+ return Prototype;
+ }
+ }
+
+ public abstract class ArgumentSource
+ {
+ public abstract string Description { get; }
+
+ public abstract string[] GetNames();
+ public abstract bool GetArguments(string value, out IEnumerable<string> replacement);
+
+ public static IEnumerable<string> GetArgumentsFromFile(string file)
+ {
+ return GetArguments(File.OpenText(file), true);
+ }
+
+ public static IEnumerable<string> GetArguments(TextReader reader)
+ {
+ return GetArguments(reader, false);
+ }
+
+ // Cribbed from mcs/driver.cs:LoadArgs(string)
+ static IEnumerable<string> GetArguments(TextReader reader, bool close)
+ {
+ try
+ {
+ StringBuilder arg = new StringBuilder();
+
+ string line;
+ while ((line = reader.ReadLine()) != null)
+ {
+ int t = line.Length;
+
+ for (int i = 0; i < t; i++)
+ {
+ char c = line[i];
+
+ if (c == '"' || c == '\'')
+ {
+ char end = c;
+
+ for (i++; i < t; i++)
+ {
+ c = line[i];
+
+ if (c == end)
+ break;
+ arg.Append(c);
+ }
+ }
+ else if (c == ' ')
+ {
+ if (arg.Length > 0)
+ {
+ yield return arg.ToString();
+ arg.Length = 0;
+ }
+ }
+ else
+ arg.Append(c);
+ }
+ if (arg.Length > 0)
+ {
+ yield return arg.ToString();
+ arg.Length = 0;
+ }
+ }
+ }
+ finally
+ {
+ if (close)
+ reader.Close();
+ }
+ }
+ }
+
+ public class ResponseFileSource : ArgumentSource
+ {
+ public override string Description
+ {
+ get { return "Read response file for more options."; }
+ }
+
+ public override string[] GetNames()
+ {
+ return new[] { "@file" };
+ }
+
+ public override bool GetArguments(string value, out IEnumerable<string> replacement)
+ {
+ if (string.IsNullOrEmpty(value) || !value.StartsWith("@"))
+ {
+ replacement = null;
+ return false;
+ }
+ replacement = GetArgumentsFromFile(value.Substring(1));
+ return true;
+ }
+ }
+
+ [Serializable]
+ public class OptionException : Exception
+ {
+ public OptionException()
+ {
+ }
+
+ public OptionException(string message, string optionName)
+ : base(message)
+ {
+ OptionName = optionName;
+ }
+
+ public OptionException(string message, string optionName, Exception innerException)
+ : base(message, innerException)
+ {
+ OptionName = optionName;
+ }
+
+ protected OptionException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ OptionName = info.GetString("OptionName");
+ }
+
+ public string OptionName { get; }
+
+ [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+ info.AddValue("OptionName", OptionName);
+ }
+ }
+
+ public delegate void OptionAction<TKey, TValue>(TKey key, TValue value);
+
+ public class OptionSet : KeyedCollection<string, Option>
+ {
+ const int OptionWidth = 29;
+ const int DescriptionFirstWidth = 80 - OptionWidth;
+ const int DescriptionRemWidth = 80 - OptionWidth - 2;
+
+ readonly List<ArgumentSource> _sources = new List<ArgumentSource>();
+
+ readonly Regex _valueOption = new Regex(
+ @"^(?<flag>--|-|/)(?<name>[^:=]+)((?<sep>[:=])(?<value>.*))?$");
+
+ public OptionSet()
+ : this(delegate(string f) { return f; })
+ {
+ }
+
+ public OptionSet(Converter<string, string> localizer)
+ {
+ MessageLocalizer = localizer;
+ ArgumentSources = new ReadOnlyCollection<ArgumentSource>(_sources);
+ }
+
+ public Converter<string, string> MessageLocalizer { get; }
+
+ public ReadOnlyCollection<ArgumentSource> ArgumentSources { get; }
+
+ protected override string GetKeyForItem(Option item)
+ {
+ if (item == null)
+ throw new ArgumentNullException("option");
+ if (item.Names != null && item.Names.Length > 0)
+ return item.Names[0];
+ // This should never happen, as it's invalid for Option to be
+ // constructed w/o any names.
+ throw new InvalidOperationException("Option has no names!");
+ }
+
+ [Obsolete("Use KeyedCollection.this[string]")]
+ protected Option GetOptionForName(string option)
+ {
+ if (option == null)
+ throw new ArgumentNullException("option");
+ try
+ {
+ return base[option];
+ }
+ catch (KeyNotFoundException)
+ {
+ return null;
+ }
+ }
+
+ protected override void InsertItem(int index, Option item)
+ {
+ base.InsertItem(index, item);
+ AddImpl(item);
+ }
+
+ protected override void RemoveItem(int index)
+ {
+ Option p = Items[index];
+ base.RemoveItem(index);
+ // KeyedCollection.RemoveItem() handles the 0th item
+ for (int i = 1; i < p.Names.Length; ++i)
+ Dictionary.Remove(p.Names[i]);
+ }
+
+ protected override void SetItem(int index, Option item)
+ {
+ base.SetItem(index, item);
+ AddImpl(item);
+ }
+
+ void AddImpl(Option option)
+ {
+ if (option == null)
+ throw new ArgumentNullException("option");
+ List<string> added = new List<string>(option.Names.Length);
+ try
+ {
+ // KeyedCollection.InsertItem/SetItem handle the 0th name.
+ for (int i = 1; i < option.Names.Length; ++i)
+ {
+ Dictionary.Add(option.Names[i], option);
+ added.Add(option.Names[i]);
+ }
+ }
+ catch (Exception)
+ {
+ foreach (string name in added)
+ Dictionary.Remove(name);
+ throw;
+ }
+ }
+
+ public OptionSet Add(string header)
+ {
+ if (header == null)
+ throw new ArgumentNullException("header");
+ Add(new Category(header));
+ return this;
+ }
+
+ public new OptionSet Add(Option option)
+ {
+ base.Add(option);
+ return this;
+ }
+
+ public OptionSet Add(string prototype, Action<string> action)
+ {
+ return Add(prototype, null, action);
+ }
+
+ public OptionSet Add(string prototype, string description, Action<string> action)
+ {
+ if (action == null)
+ throw new ArgumentNullException("action");
+ Option p = new ActionOption(prototype, description, 1,
+ delegate(OptionValueCollection v) { action(v[0]); });
+ base.Add(p);
+ return this;
+ }
+
+ public OptionSet Add(string prototype, OptionAction<string, string> action)
+ {
+ return Add(prototype, null, action);
+ }
+
+ public OptionSet Add(string prototype, string description, OptionAction<string, string> action)
+ {
+ if (action == null)
+ throw new ArgumentNullException("action");
+ Option p = new ActionOption(prototype, description, 2,
+ delegate(OptionValueCollection v) { action(v[0], v[1]); });
+ base.Add(p);
+ return this;
+ }
+
+ public OptionSet Add<T>(string prototype, Action<T> action)
+ {
+ return Add(prototype, null, action);
+ }
+
+ public OptionSet Add<T>(string prototype, string description, Action<T> action)
+ {
+ return Add(new ActionOption<T>(prototype, description, action));
+ }
+
+ public OptionSet Add<TKey, TValue>(string prototype, OptionAction<TKey, TValue> action)
+ {
+ return Add(prototype, null, action);
+ }
+
+ public OptionSet Add<TKey, TValue>(string prototype, string description, OptionAction<TKey, TValue> action)
+ {
+ return Add(new ActionOption<TKey, TValue>(prototype, description, action));
+ }
+
+ public OptionSet Add(ArgumentSource source)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ _sources.Add(source);
+ return this;
+ }
+
+ protected virtual OptionContext CreateOptionContext()
+ {
+ return new OptionContext(this);
+ }
+
+ public List<string> Parse(IEnumerable<string> arguments)
+ {
+ if (arguments == null)
+ throw new ArgumentNullException("arguments");
+ OptionContext c = CreateOptionContext();
+ c.OptionIndex = -1;
+ bool process = true;
+ List<string> unprocessed = new List<string>();
+ Option def = Contains("<>") ? this["<>"] : null;
+ ArgumentEnumerator ae = new ArgumentEnumerator(arguments);
+ foreach (string argument in ae)
+ {
+ ++c.OptionIndex;
+ if (argument == "--")
+ {
+ process = false;
+ continue;
+ }
+ if (!process)
+ {
+ Unprocessed(unprocessed, def, c, argument);
+ continue;
+ }
+ if (AddSource(ae, argument))
+ continue;
+ if (!Parse(argument, c))
+ Unprocessed(unprocessed, def, c, argument);
+ }
+ if (c.Option != null)
+ c.Option.Invoke(c);
+ return unprocessed;
+ }
+
+ bool AddSource(ArgumentEnumerator ae, string argument)
+ {
+ foreach (ArgumentSource source in _sources)
+ {
+ IEnumerable<string> replacement;
+ if (!source.GetArguments(argument, out replacement))
+ continue;
+ ae.Add(replacement);
+ return true;
+ }
+ return false;
+ }
+
+ static bool Unprocessed(ICollection<string> extra, Option def, OptionContext c, string argument)
+ {
+ if (def == null)
+ {
+ extra.Add(argument);
+ return false;
+ }
+ c.OptionValues.Add(argument);
+ c.Option = def;
+ c.Option.Invoke(c);
+ return false;
+ }
+
+ protected bool GetOptionParts(string argument, out string flag, out string name, out string sep, out string value)
+ {
+ if (argument == null)
+ throw new ArgumentNullException("argument");
+
+ flag = name = sep = value = null;
+ Match m = _valueOption.Match(argument);
+ if (!m.Success)
+ return false;
+ flag = m.Groups["flag"].Value;
+ name = m.Groups["name"].Value;
+ if (m.Groups["sep"].Success && m.Groups["value"].Success)
+ {
+ sep = m.Groups["sep"].Value;
+ value = m.Groups["value"].Value;
+ }
+ return true;
+ }
+
+ protected virtual bool Parse(string argument, OptionContext c)
+ {
+ if (c.Option != null)
+ {
+ ParseValue(argument, c);
+ return true;
+ }
+
+ string f, n, s, v;
+ if (!GetOptionParts(argument, out f, out n, out s, out v))
+ return false;
+
+ Option p;
+ if (Contains(n))
+ {
+ p = this[n];
+ c.OptionName = f + n;
+ c.Option = p;
+ switch (p.OptionValueType)
+ {
+ case OptionValueType.None:
+ c.OptionValues.Add(n);
+ c.Option.Invoke(c);
+ break;
+ case OptionValueType.Optional:
+ case OptionValueType.Required:
+ ParseValue(v, c);
+ break;
+ }
+ return true;
+ }
+ // no match; is it a bool option?
+ if (ParseBool(argument, n, c))
+ return true;
+ // is it a bundled option?
+ if (ParseBundledValue(f, string.Concat(n + s + v), c))
+ return true;
+
+ return false;
+ }
+
+ void ParseValue(string option, OptionContext c)
+ {
+ if (option != null)
+ {
+ foreach (string o in c.Option.ValueSeparators != null
+ ? option.Split(c.Option.ValueSeparators, c.Option.MaxValueCount - c.OptionValues.Count, StringSplitOptions.None)
+ : new[] { option })
+ c.OptionValues.Add(o);
+ }
+ if (c.OptionValues.Count == c.Option.MaxValueCount ||
+ c.Option.OptionValueType == OptionValueType.Optional)
+ c.Option.Invoke(c);
+ else if (c.OptionValues.Count > c.Option.MaxValueCount)
+ {
+ throw new OptionException(MessageLocalizer(string.Format(
+ "Error: Found {0} option values when expecting {1}.",
+ c.OptionValues.Count, c.Option.MaxValueCount)),
+ c.OptionName);
+ }
+ }
+
+ bool ParseBool(string option, string n, OptionContext c)
+ {
+ Option p;
+ string rn;
+ if (n.Length >= 1 && (n[n.Length - 1] == '+' || n[n.Length - 1] == '-') &&
+ Contains((rn = n.Substring(0, n.Length - 1))))
+ {
+ p = this[rn];
+ string v = n[n.Length - 1] == '+' ? option : null;
+ c.OptionName = option;
+ c.Option = p;
+ c.OptionValues.Add(v);
+ p.Invoke(c);
+ return true;
+ }
+ return false;
+ }
+
+ bool ParseBundledValue(string f, string n, OptionContext c)
+ {
+ if (f != "-")
+ return false;
+ for (int i = 0; i < n.Length; ++i)
+ {
+ Option p;
+ string opt = f + n[i];
+ string rn = n[i].ToString();
+ if (!Contains(rn))
+ {
+ if (i == 0)
+ return false;
+ throw new OptionException(string.Format(MessageLocalizer(
+ "Cannot bundle unregistered option '{0}'."), opt), opt);
+ }
+ p = this[rn];
+ switch (p.OptionValueType)
+ {
+ case OptionValueType.None:
+ Invoke(c, opt, n, p);
+ break;
+ case OptionValueType.Optional:
+ case OptionValueType.Required:
+ {
+ string v = n.Substring(i + 1);
+ c.Option = p;
+ c.OptionName = opt;
+ ParseValue(v.Length != 0 ? v : null, c);
+ return true;
+ }
+ default:
+ throw new InvalidOperationException("Unknown OptionValueType: " + p.OptionValueType);
+ }
+ }
+ return true;
+ }
+
+ static void Invoke(OptionContext c, string name, string value, Option option)
+ {
+ c.OptionName = name;
+ c.Option = option;
+ c.OptionValues.Add(value);
+ option.Invoke(c);
+ }
+
+ public void WriteOptionDescriptions(TextWriter o)
+ {
+ foreach (Option p in this)
+ {
+ int written = 0;
+
+ Category c = p as Category;
+ if (c != null)
+ {
+ WriteDescription(o, p.Description, "", 80, 80);
+ continue;
+ }
+
+ if (!WriteOptionPrototype(o, p, ref written))
+ continue;
+
+ if (written < OptionWidth)
+ o.Write(new string(' ', OptionWidth - written));
+ else
+ {
+ o.WriteLine();
+ o.Write(new string(' ', OptionWidth));
+ }
+
+ WriteDescription(o, p.Description, new string(' ', OptionWidth + 2),
+ DescriptionFirstWidth, DescriptionRemWidth);
+ }
+
+ foreach (ArgumentSource s in _sources)
+ {
+ string[] names = s.GetNames();
+ if (names == null || names.Length == 0)
+ continue;
+
+ int written = 0;
+
+ Write(o, ref written, " ");
+ Write(o, ref written, names[0]);
+ for (int i = 1; i < names.Length; ++i)
+ {
+ Write(o, ref written, ", ");
+ Write(o, ref written, names[i]);
+ }
+
+ if (written < OptionWidth)
+ o.Write(new string(' ', OptionWidth - written));
+ else
+ {
+ o.WriteLine();
+ o.Write(new string(' ', OptionWidth));
+ }
+
+ WriteDescription(o, s.Description, new string(' ', OptionWidth + 2),
+ DescriptionFirstWidth, DescriptionRemWidth);
+ }
+ }
+
+ void WriteDescription(TextWriter o, string value, string prefix, int firstWidth, int remWidth)
+ {
+ bool indent = false;
+ foreach (string line in GetLines(MessageLocalizer(GetDescription(value)), firstWidth, remWidth))
+ {
+ if (indent)
+ o.Write(prefix);
+ o.WriteLine(line);
+ indent = true;
+ }
+ }
+
+ bool WriteOptionPrototype(TextWriter o, Option p, ref int written)
+ {
+ string[] names = p.Names;
+
+ int i = GetNextOptionIndex(names, 0);
+ if (i == names.Length)
+ return false;
+
+ if (names[i].Length == 1)
+ {
+ Write(o, ref written, " -");
+ Write(o, ref written, names[0]);
+ }
+ else
+ {
+ Write(o, ref written, " --");
+ Write(o, ref written, names[0]);
+ }
+
+ for (i = GetNextOptionIndex(names, i + 1);
+ i < names.Length;
+ i = GetNextOptionIndex(names, i + 1))
+ {
+ Write(o, ref written, ", ");
+ Write(o, ref written, names[i].Length == 1 ? "-" : "--");
+ Write(o, ref written, names[i]);
+ }
+
+ if (p.OptionValueType == OptionValueType.Optional ||
+ p.OptionValueType == OptionValueType.Required)
+ {
+ if (p.OptionValueType == OptionValueType.Optional)
+ Write(o, ref written, MessageLocalizer("["));
+ Write(o, ref written, MessageLocalizer("=" + GetArgumentName(0, p.MaxValueCount, p.Description)));
+ string sep = p.ValueSeparators != null && p.ValueSeparators.Length > 0
+ ? p.ValueSeparators[0]
+ : " ";
+ for (int c = 1; c < p.MaxValueCount; ++c)
+ Write(o, ref written, MessageLocalizer(sep + GetArgumentName(c, p.MaxValueCount, p.Description)));
+ if (p.OptionValueType == OptionValueType.Optional)
+ Write(o, ref written, MessageLocalizer("]"));
+ }
+ return true;
+ }
+
+ static int GetNextOptionIndex(string[] names, int i)
+ {
+ while (i < names.Length && names[i] == "<>")
+ ++i;
+ return i;
+ }
+
+ static void Write(TextWriter o, ref int n, string s)
+ {
+ n += s.Length;
+ o.Write(s);
+ }
+
+ static string GetArgumentName(int index, int maxIndex, string description)
+ {
+ if (description == null)
+ return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1);
+ string[] nameStart;
+ if (maxIndex == 1)
+ nameStart = new[] { "{0:", "{" };
+ else
+ nameStart = new[] { "{" + index + ":" };
+ for (int i = 0; i < nameStart.Length; ++i)
+ {
+ int start, j = 0;
+ do
+ {
+ start = description.IndexOf(nameStart[i], j);
+ } while (start >= 0 && j != 0 ? description[j++ - 1] == '{' : false);
+ if (start == -1)
+ continue;
+ int end = description.IndexOf("}", start);
+ if (end == -1)
+ continue;
+ return description.Substring(start + nameStart[i].Length, end - start - nameStart[i].Length);
+ }
+ return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1);
+ }
+
+ static string GetDescription(string description)
+ {
+ if (description == null)
+ return string.Empty;
+ StringBuilder sb = new StringBuilder(description.Length);
+ int start = -1;
+ for (int i = 0; i < description.Length; ++i)
+ {
+ switch (description[i])
+ {
+ case '{':
+ if (i == start)
+ {
+ sb.Append('{');
+ start = -1;
+ }
+ else if (start < 0)
+ start = i + 1;
+ break;
+ case '}':
+ if (start < 0)
+ {
+ if ((i + 1) == description.Length || description[i + 1] != '}')
+ throw new InvalidOperationException("Invalid option description: " + description);
+ ++i;
+ sb.Append("}");
+ }
+ else
+ {
+ sb.Append(description.Substring(start, i - start));
+ start = -1;
+ }
+ break;
+ case ':':
+ if (start < 0)
+ goto default;
+ start = i + 1;
+ break;
+ default:
+ if (start < 0)
+ sb.Append(description[i]);
+ break;
+ }
+ }
+ return sb.ToString();
+ }
+
+ static IEnumerable<string> GetLines(string description, int firstWidth, int remWidth)
+ {
+ return StringCoda.WrappedLines(description, firstWidth, remWidth);
+ }
+
+ internal sealed class Category : Option
+ {
+ // Prototype starts with '=' because this is an invalid prototype
+ // (see Option.ParsePrototype(), and thus it'll prevent Category
+ // instances from being accidentally used as normal options.
+ public Category(string description)
+ : base("=:Category:= " + description, description)
+ {
+ }
+
+ protected override void OnParseComplete(OptionContext c)
+ {
+ throw new NotSupportedException("Category.OnParseComplete should not be invoked.");
+ }
+ }
+
+ sealed class ActionOption : Option
+ {
+ readonly Action<OptionValueCollection> _action;
+
+ public ActionOption(string prototype, string description, int count, Action<OptionValueCollection> action)
+ : base(prototype, description, count)
+ {
+ if (action == null)
+ throw new ArgumentNullException("action");
+ _action = action;
+ }
+
+ protected override void OnParseComplete(OptionContext c)
+ {
+ _action(c.OptionValues);
+ }
+ }
+
+ sealed class ActionOption<T> : Option
+ {
+ readonly Action<T> _action;
+
+ public ActionOption(string prototype, string description, Action<T> action)
+ : base(prototype, description, 1)
+ {
+ if (action == null)
+ throw new ArgumentNullException("action");
+ _action = action;
+ }
+
+ protected override void OnParseComplete(OptionContext c)
+ {
+ _action(Parse<T>(c.OptionValues[0], c));
+ }
+ }
+
+ sealed class ActionOption<TKey, TValue> : Option
+ {
+ readonly OptionAction<TKey, TValue> _action;
+
+ public ActionOption(string prototype, string description, OptionAction<TKey, TValue> action)
+ : base(prototype, description, 2)
+ {
+ if (action == null)
+ throw new ArgumentNullException("action");
+ _action = action;
+ }
+
+ protected override void OnParseComplete(OptionContext c)
+ {
+ _action(
+ Parse<TKey>(c.OptionValues[0], c),
+ Parse<TValue>(c.OptionValues[1], c));
+ }
+ }
+
+ class ArgumentEnumerator : IEnumerable<string>
+ {
+ readonly List<IEnumerator<string>> _sources = new List<IEnumerator<string>>();
+
+ public ArgumentEnumerator(IEnumerable<string> arguments)
+ {
+ _sources.Add(arguments.GetEnumerator());
+ }
+
+ public IEnumerator<string> GetEnumerator()
+ {
+ do
+ {
+ IEnumerator<string> c = _sources[_sources.Count - 1];
+ if (c.MoveNext())
+ yield return c.Current;
+ else
+ {
+ c.Dispose();
+ _sources.RemoveAt(_sources.Count - 1);
+ }
+ } while (_sources.Count > 0);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public void Add(IEnumerable<string> arguments)
+ {
+ _sources.Add(arguments.GetEnumerator());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.Xamlg/Program.cs b/Xamarin.Forms.Xaml.Xamlg/Program.cs
new file mode 100644
index 00000000..27508541
--- /dev/null
+++ b/Xamarin.Forms.Xaml.Xamlg/Program.cs
@@ -0,0 +1,20 @@
+//
+// Program.cs
+//
+// Author:
+// Stephane Delcroix <stephane@delcroix.org>
+//
+// Copyright (c) 2013 S. Delcroix
+//
+using System;
+
+namespace Xamarin.Forms.Xaml.Xamlg
+{
+ class MainClass
+ {
+ public static void Main (string[] args)
+ {
+ Console.WriteLine ("Hello World!");
+ }
+ }
+}
diff --git a/Xamarin.Forms.Xaml.Xamlg/Properties/AssemblyInfo.cs b/Xamarin.Forms.Xaml.Xamlg/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..9070b661
--- /dev/null
+++ b/Xamarin.Forms.Xaml.Xamlg/Properties/AssemblyInfo.cs
@@ -0,0 +1,31 @@
+//
+// AssemblyInfo.cs
+//
+// Author:
+// Stephane Delcroix <stephane@delcroix.org>
+//
+// Copyright (c) 2013 S. Delcroix
+//
+
+using System.Reflection;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("Xamarin.Forms.Xaml.Xamlg")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("mobileInception")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("S. Delcroix")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion("1.0.*")]
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")] \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.Xamlg/Xamarin.Forms.Xaml.Xamlg.csproj b/Xamarin.Forms.Xaml.Xamlg/Xamarin.Forms.Xaml.Xamlg.csproj
new file mode 100644
index 00000000..660c024d
--- /dev/null
+++ b/Xamarin.Forms.Xaml.Xamlg/Xamarin.Forms.Xaml.Xamlg.csproj
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>12.0.0</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{D597E3C6-1A50-4042-99FA-3E7CE28E4819}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <RootNamespace>Xamarin.Forms.Xaml</RootNamespace>
+ <AssemblyName>xamlg</AssemblyName>
+ <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <Externalconsole>true</Externalconsole>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>full</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <Externalconsole>true</Externalconsole>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>true</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Microsoft.Build" />
+ <Reference Include="Microsoft.Build.Framework" />
+ <Reference Include="Microsoft.Build.Utilities.v4.0" />
+ <Reference Include="System" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Xamlg.cs" />
+ <Compile Include="Mono.Options\Options.cs" />
+ <Compile Include="..\Xamarin.Forms.Xaml\XmlnsHelper.cs">
+ <Link>XmlnsHelper.cs</Link>
+ </Compile>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <ItemGroup />
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Build.Tasks\Xamarin.Forms.Build.Tasks.csproj">
+ <Project>{96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}</Project>
+ <Name>Xamarin.Forms.Build.Tasks</Name>
+ </ProjectReference>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.Xamlg/Xamlg.cs b/Xamarin.Forms.Xaml.Xamlg/Xamlg.cs
new file mode 100644
index 00000000..d66b6ce7
--- /dev/null
+++ b/Xamarin.Forms.Xaml.Xamlg/Xamlg.cs
@@ -0,0 +1,93 @@
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Original Author for Moonlight:
+// Jackson Harper (jackson@ximian.com)
+//
+// Copyright 2007 Novell, Inc.
+//
+// Author:
+// Stephane Delcroix (stephane@mi8.be)
+//
+// Copyright 2013 Mobile Inception
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Mono.Options;
+using Xamarin.Forms.Build.Tasks;
+
+namespace Xamarin.Forms.Xaml
+{
+ public class Xamlg
+ {
+ static readonly string HelpString = "xamlg.exe - a utility for generating partial classes from XAML.\n" +
+ "xamlg.exe xamlfile[,outputfile]...\n\n" +
+ "If an outputfile is not specified one will be created using the format <xamlfile>.g.cs\n\n";
+
+ public static void Main(string[] args)
+ {
+ bool help = false;
+ var p = new OptionSet
+ {
+ { "h|?|help", "Print this help message", v => help = true }
+ };
+
+ if (help || args.Length < 1)
+ {
+ ShowHelp(p);
+ Environment.Exit(0);
+ }
+ List<string> extra = null;
+ try
+ {
+ extra = p.Parse(args);
+ }
+ catch (OptionException)
+ {
+ Console.WriteLine("Type `xamlg --help' for more information.");
+ return;
+ }
+
+ foreach (var file in extra)
+ {
+ var f = file;
+ var n = "";
+
+ var sub = file.IndexOf(",", StringComparison.InvariantCulture);
+ if (sub > 0)
+ {
+ n = f.Substring(sub + 1);
+ f = f.Substring(0, sub);
+ }
+ else
+ n = string.Concat(Path.GetFileName(f), ".g.", XamlGTask.Provider.FileExtension);
+
+ XamlGTask.GenerateFile(f, n);
+ }
+ }
+
+ static void ShowHelp(OptionSet ops)
+ {
+ Console.WriteLine(HelpString);
+ ops.WriteOptionDescriptions(Console.Out);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs b/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs
new file mode 100644
index 00000000..e013a742
--- /dev/null
+++ b/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs
@@ -0,0 +1,439 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Xml;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Xaml.Internals;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal class ApplyPropertiesVisitor : IXamlNodeVisitor
+ {
+ public static readonly IList<XmlName> Skips = new List<XmlName>
+ {
+ XmlName.xKey,
+ XmlName.xTypeArguments,
+ XmlName.xArguments,
+ XmlName.xFactoryMethod,
+ XmlName.xName
+ };
+
+ public ApplyPropertiesVisitor(HydratationContext context, bool stopOnResourceDictionary = false)
+ {
+ Context = context;
+ StopOnResourceDictionary = stopOnResourceDictionary;
+ }
+
+ Dictionary<INode, object> Values
+ {
+ get { return Context.Values; }
+ }
+
+ HydratationContext Context { get; }
+
+ public bool VisitChildrenFirst
+ {
+ get { return true; }
+ }
+
+ public bool StopOnDataTemplate
+ {
+ get { return true; }
+ }
+
+ public bool StopOnResourceDictionary { get; }
+
+ public void Visit(ValueNode node, INode parentNode)
+ {
+ var parentElement = parentNode as IElementNode;
+ var value = Values[node];
+ var source = Values[parentNode];
+
+ XmlName propertyName;
+ if (TryGetPropertyName(node, parentNode, out propertyName))
+ {
+ if (Skips.Contains(propertyName))
+ return;
+ if (parentElement.SkipProperties.Contains(propertyName))
+ return;
+ if (parentElement.SkipPrefix(node.NamespaceResolver.LookupPrefix(propertyName.NamespaceURI)))
+ return;
+ if (propertyName.NamespaceURI == "http://schemas.openxmlformats.org/markup-compatibility/2006" &&
+ propertyName.LocalName == "Ignorable")
+ {
+ (parentNode.IgnorablePrefixes ?? (parentNode.IgnorablePrefixes = new List<string>())).AddRange(
+ (value as string).Split(','));
+ return;
+ }
+ SetPropertyValue(source, propertyName, value, Context.RootElement, node, Context, node);
+ }
+ else if (IsCollectionItem(node, parentNode) && parentNode is IElementNode)
+ {
+ // Collection element, implicit content, or implicit collection element.
+ var contentProperty = GetContentPropertyName(Context.Types[parentElement].GetTypeInfo());
+ if (contentProperty != null)
+ {
+ var name = new XmlName(((ElementNode)parentNode).NamespaceURI, contentProperty);
+ if (Skips.Contains(name))
+ return;
+ if (parentElement.SkipProperties.Contains(propertyName))
+ return;
+ SetPropertyValue(source, name, value, Context.RootElement, node, Context, node);
+ }
+ }
+ }
+
+ public void Visit(MarkupNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(ElementNode node, INode parentNode)
+ {
+ if (node.SkipPrefix(node.NamespaceResolver.LookupPrefix(node.NamespaceURI)))
+ return;
+
+ var value = Values[node];
+ var parentElement = parentNode as IElementNode;
+ var markupExtension = value as IMarkupExtension;
+ var valueProvider = value as IValueProvider;
+
+ if (markupExtension != null)
+ {
+ var serviceProvider = new XamlServiceProvider(node, Context);
+ value = markupExtension.ProvideValue(serviceProvider);
+ }
+
+ if (valueProvider != null)
+ {
+ var serviceProvider = new XamlServiceProvider(node, Context);
+ value = valueProvider.ProvideValue(serviceProvider);
+ }
+
+ XmlName propertyName;
+ if (TryGetPropertyName(node, parentNode, out propertyName))
+ {
+ if (Skips.Contains(propertyName))
+ return;
+ if (parentElement.SkipProperties.Contains(propertyName))
+ return;
+
+ var source = Values[parentNode];
+
+ if (propertyName == XmlName._CreateContent && source is ElementTemplate)
+ SetTemplate(source as ElementTemplate, node);
+ else
+ SetPropertyValue(source, propertyName, value, Context.RootElement, node, Context, node);
+ }
+ else if (IsCollectionItem(node, parentNode) && parentNode is IElementNode)
+ {
+ // Collection element, implicit content, or implicit collection element.
+ string contentProperty;
+ if (typeof (IEnumerable).GetTypeInfo().IsAssignableFrom(Context.Types[parentElement].GetTypeInfo()))
+ {
+ var source = Values[parentNode];
+ if (Context.Types[parentElement] != typeof (ResourceDictionary))
+ {
+ var addMethod =
+ Context.Types[parentElement].GetRuntimeMethods().First(mi => mi.Name == "Add" && mi.GetParameters().Length == 1);
+ addMethod.Invoke(source, new[] { value });
+ }
+ }
+ else if ((contentProperty = GetContentPropertyName(Context.Types[parentElement].GetTypeInfo())) != null)
+ {
+ var name = new XmlName(node.NamespaceURI, contentProperty);
+ if (Skips.Contains(name))
+ return;
+ if (parentElement.SkipProperties.Contains(propertyName))
+ return;
+
+ var source = Values[parentNode];
+ SetPropertyValue(source, name, value, Context.RootElement, node, Context, node);
+ }
+ }
+ else if (IsCollectionItem(node, parentNode) && parentNode is ListNode)
+ {
+ var parentList = (ListNode)parentNode;
+ var source = Values[parentNode.Parent];
+
+ if (Skips.Contains(parentList.XmlName))
+ return;
+
+ var elementType = source.GetType();
+ var localname = parentList.XmlName.LocalName;
+
+ GetRealNameAndType(ref elementType, parentList.XmlName.NamespaceURI, ref localname, Context, node);
+
+ PropertyInfo propertyInfo = null;
+ try
+ {
+ propertyInfo = elementType.GetRuntimeProperty(localname);
+ }
+ catch (AmbiguousMatchException)
+ {
+ // Get most derived instance of property
+ foreach (var property in elementType.GetRuntimeProperties().Where(prop => prop.Name == localname))
+ {
+ if (propertyInfo == null || propertyInfo.DeclaringType.IsAssignableFrom(property.DeclaringType))
+ propertyInfo = property;
+ }
+ }
+ if (propertyInfo == null)
+ throw new XamlParseException(string.Format("Property {0} not found", localname), node);
+ MethodInfo getter;
+ if (!propertyInfo.CanRead || (getter = propertyInfo.GetMethod) == null)
+ throw new XamlParseException(string.Format("Property {0} does not have an accessible getter", localname), node);
+ IEnumerable collection;
+ if ((collection = getter.Invoke(source, new object[] { }) as IEnumerable) == null)
+ throw new XamlParseException(string.Format("Property {0} is null or is not IEnumerable", localname), node);
+ MethodInfo addMethod;
+ if (
+ (addMethod =
+ collection.GetType().GetRuntimeMethods().First(mi => mi.Name == "Add" && mi.GetParameters().Length == 1)) == null)
+ throw new XamlParseException(string.Format("Value of {0} does not have a Add() method", localname), node);
+
+ addMethod.Invoke(collection, new[] { Values[node] });
+ }
+ }
+
+ public void Visit(RootNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(ListNode node, INode parentNode)
+ {
+ }
+
+ public static bool TryGetPropertyName(INode node, INode parentNode, out XmlName name)
+ {
+ name = default(XmlName);
+ var parentElement = parentNode as IElementNode;
+ if (parentElement == null)
+ return false;
+ foreach (var kvp in parentElement.Properties)
+ {
+ if (kvp.Value != node)
+ continue;
+ name = kvp.Key;
+ return true;
+ }
+ return false;
+ }
+
+ static bool IsCollectionItem(INode node, INode parentNode)
+ {
+ var parentList = parentNode as IListNode;
+ if (parentList == null)
+ return false;
+ return parentList.CollectionItems.Contains(node);
+ }
+
+ internal static string GetContentPropertyName(TypeInfo typeInfo)
+ {
+ while (typeInfo != null)
+ {
+ var propName = GetContentPropertyName(typeInfo.CustomAttributes);
+ if (propName != null)
+ return propName;
+ typeInfo = typeInfo?.BaseType?.GetTypeInfo();
+ }
+ return null;
+ }
+
+ static string GetContentPropertyName(IEnumerable<CustomAttributeData> attributes)
+ {
+ var contentAttribute =
+ attributes.FirstOrDefault(cad => ContentPropertyAttribute.ContentPropertyTypes.Contains(cad.AttributeType.FullName));
+ if (contentAttribute == null || contentAttribute.ConstructorArguments.Count != 1)
+ return null;
+ if (contentAttribute.ConstructorArguments[0].ArgumentType == typeof (string))
+ return (string)contentAttribute.ConstructorArguments[0].Value;
+ return null;
+ }
+
+ static bool GetRealNameAndType(ref Type elementType, string namespaceURI, ref string localname,
+ HydratationContext context, IXmlLineInfo lineInfo)
+ {
+ var dotIdx = localname.IndexOf('.');
+ if (dotIdx > 0)
+ {
+ var typename = localname.Substring(0, dotIdx);
+ localname = localname.Substring(dotIdx + 1);
+ XamlParseException xpe;
+ elementType = XamlParser.GetElementType(new XmlType(namespaceURI, typename, null), lineInfo,
+ context.RootElement.GetType().GetTypeInfo().Assembly, out xpe);
+ if (xpe != null)
+ throw xpe;
+ return true;
+ }
+ return false;
+ }
+
+ static BindableProperty GetBindableProperty(Type elementType, string localName, IXmlLineInfo lineInfo,
+ bool throwOnError = false)
+ {
+ var bindableFieldInfo =
+ elementType.GetFields().FirstOrDefault(fi => fi.Name == localName + "Property" && fi.IsStatic && fi.IsPublic);
+
+ Exception exception = null;
+ if (exception == null && bindableFieldInfo == null)
+ {
+ exception =
+ new XamlParseException(
+ string.Format("BindableProperty {0} not found on {1}", localName + "Property", elementType.Name), lineInfo);
+ }
+
+ if (exception == null)
+ return bindableFieldInfo.GetValue(null) as BindableProperty;
+ if (throwOnError)
+ throw exception;
+ return null;
+ }
+
+ public static void SetPropertyValue(object xamlelement, XmlName propertyName, object value, BindableObject rootElement,
+ INode node, HydratationContext context, IXmlLineInfo lineInfo)
+ {
+ var elementType = xamlelement.GetType();
+ var localname = propertyName.LocalName;
+
+ var serviceProvider = new XamlServiceProvider(node, context);
+
+ //If it's an attached BP, update elementType and propertyName
+ var attached = GetRealNameAndType(ref elementType, propertyName.NamespaceURI, ref localname, context, lineInfo);
+
+ //If the target is an event, connect
+ var eventInfo = elementType.GetRuntimeEvent(localname);
+ if (eventInfo != null && value is string)
+ {
+ var methodInfo = rootElement.GetType().GetRuntimeMethods().FirstOrDefault(mi => mi.Name == (string)value);
+ if (methodInfo == null)
+ {
+ throw new XamlParseException(string.Format("No method {0} found on type {1}", value, rootElement.GetType()),
+ lineInfo);
+ }
+
+ try
+ {
+ eventInfo.AddEventHandler(xamlelement, methodInfo.CreateDelegate(eventInfo.EventHandlerType, rootElement));
+ }
+ catch (ArgumentException)
+ {
+ throw new XamlParseException(string.Format("Method {0} does not have the correct signature", value), lineInfo);
+ }
+
+ return;
+ }
+
+ var property = GetBindableProperty(elementType, localname, lineInfo, false);
+
+ //If Value is DynamicResource and it's a BP, SetDynamicResource
+ if (value is DynamicResource && property != null)
+ {
+ if (!(xamlelement.GetType()).GetTypeInfo().IsSubclassOf(typeof (BindableObject)))
+ throw new XamlParseException(string.Format("{0} is not a BindableObject", xamlelement.GetType().Name), lineInfo);
+ ((BindableObject)xamlelement).SetDynamicResource(property, ((DynamicResource)value).Key);
+ return;
+ }
+
+ //If value is BindingBase, and target is a BindableProperty, SetBinding
+ if (value is BindingBase && property != null)
+ {
+ if (!(xamlelement.GetType()).GetTypeInfo().IsSubclassOf(typeof (BindableObject)))
+ throw new XamlParseException(string.Format("{0} is not a BindableObject", xamlelement.GetType().Name), lineInfo);
+
+ ((BindableObject)xamlelement).SetBinding(property, value as BindingBase);
+ return;
+ }
+
+ //If it's a BindableProberty, SetValue
+ if (property != null)
+ {
+ if (!(xamlelement.GetType()).GetTypeInfo().IsSubclassOf(typeof (BindableObject)))
+ throw new XamlParseException(string.Format("{0} is not a BindableObject", xamlelement.GetType().Name), lineInfo);
+ Func<MemberInfo> minforetriever;
+ if (attached)
+ minforetriever = () => elementType.GetRuntimeMethod("Get" + localname, new[] { typeof (BindableObject) });
+ else
+ minforetriever = () => elementType.GetRuntimeProperty(localname);
+
+ var convertedValue = value.ConvertTo(property.ReturnType, minforetriever, serviceProvider);
+
+ //SetValue doesn't throw on mismatching type, so check before to get a chance to try the property setting or the collection adding
+ var nullable = property.ReturnTypeInfo.IsGenericType &&
+ property.ReturnTypeInfo.GetGenericTypeDefinition() == typeof (Nullable<>);
+ if ((convertedValue == null && (!property.ReturnTypeInfo.IsValueType || nullable)) ||
+ (property.ReturnType.IsInstanceOfType(convertedValue)))
+ {
+ ((BindableObject)xamlelement).SetValue(property, convertedValue);
+ return;
+ }
+ }
+
+ var exception = new XamlParseException(
+ String.Format("No Property of name {0} found", propertyName.LocalName), lineInfo);
+
+ //If we can assign that value to a normal property, let's do it
+ var propertyInfo = elementType.GetRuntimeProperties().FirstOrDefault(p => p.Name == localname);
+ MethodInfo setter;
+ if (propertyInfo != null && propertyInfo.CanWrite && (setter = propertyInfo.SetMethod) != null)
+ {
+ object convertedValue = value.ConvertTo(propertyInfo.PropertyType, () => propertyInfo, serviceProvider);
+ if (convertedValue == null || propertyInfo.PropertyType.IsInstanceOfType(convertedValue))
+ {
+ try
+ {
+ setter.Invoke(xamlelement, new[] { convertedValue });
+ return;
+ }
+ catch (ArgumentException)
+ {
+ }
+ }
+ else
+ {
+ exception = new XamlParseException(
+ String.Format("Cannot assign property \"{0}\": type mismatch between \"{1}\" and \"{2}\"", propertyName.LocalName,
+ value.GetType(), propertyInfo.PropertyType), lineInfo);
+ }
+ }
+
+ //If it's an already initialized property, add to it
+ MethodInfo getter;
+ if (propertyInfo != null && propertyInfo.CanRead && (getter = propertyInfo.GetMethod) != null)
+ {
+ IEnumerable collection;
+ MethodInfo addMethod;
+ if ((collection = getter.Invoke(xamlelement, new object[] { }) as IEnumerable) != null
+ &&
+ (addMethod =
+ collection.GetType().GetRuntimeMethods().First(mi => mi.Name == "Add" && mi.GetParameters().Length == 1)) !=
+ null)
+ {
+ addMethod.Invoke(collection,
+ new[] { value.ConvertTo(propertyInfo.PropertyType, (Func<TypeConverter>)null, serviceProvider) });
+ return;
+ }
+ }
+
+ throw exception;
+ }
+
+ void SetTemplate(ElementTemplate dt, INode node)
+ {
+#pragma warning disable 0612
+ ((IDataTemplate)dt).LoadTemplate = () =>
+ {
+#pragma warning restore 0612
+ var context = new HydratationContext { ParentContext = Context, RootElement = Context.RootElement };
+ node.Accept(new ExpandMarkupsVisitor(context), null);
+ node.Accept(new NamescopingVisitor(context), null);
+ node.Accept(new CreateValuesVisitor(context), null);
+ node.Accept(new RegisterXNamesVisitor(context), null);
+ node.Accept(new FillResourceDictionariesVisitor(context), null);
+ node.Accept(new ApplyPropertiesVisitor(context, true), null);
+ return context.Values[node];
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/CreateValuesVisitor.cs b/Xamarin.Forms.Xaml/CreateValuesVisitor.cs
new file mode 100644
index 00000000..96af9189
--- /dev/null
+++ b/Xamarin.Forms.Xaml/CreateValuesVisitor.cs
@@ -0,0 +1,369 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+using System.Xml;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Xaml.Internals;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal class CreateValuesVisitor : IXamlNodeVisitor
+ {
+ public CreateValuesVisitor(HydratationContext context)
+ {
+ Context = context;
+ }
+
+ Dictionary<INode, object> Values
+ {
+ get { return Context.Values; }
+ }
+
+ HydratationContext Context { get; }
+
+ public bool VisitChildrenFirst
+ {
+ get { return true; }
+ }
+
+ public bool StopOnDataTemplate
+ {
+ get { return true; }
+ }
+
+ public bool StopOnResourceDictionary
+ {
+ get { return false; }
+ }
+
+ public void Visit(ValueNode node, INode parentNode)
+ {
+ Values[node] = node.Value;
+
+ XmlName propertyName;
+ if (ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out propertyName))
+ {
+ if (propertyName.NamespaceURI == "http://schemas.openxmlformats.org/markup-compatibility/2006" &&
+ propertyName.LocalName == "Ignorable")
+ {
+ (parentNode.IgnorablePrefixes ?? (parentNode.IgnorablePrefixes = new List<string>())).AddRange(
+ (node.Value as string).Split(','));
+ }
+ }
+ }
+
+ public void Visit(MarkupNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(ElementNode node, INode parentNode)
+ {
+ object value = null;
+
+ if (node.SkipPrefix(node.NamespaceResolver.LookupPrefix(node.NamespaceURI)))
+ return;
+
+ XamlParseException xpe;
+ var type = XamlParser.GetElementType(node.XmlType, node, Context.RootElement.GetType().GetTypeInfo().Assembly,
+ out xpe);
+ if (xpe != null)
+ throw xpe;
+
+ Context.Types[node] = type;
+ string ctorargname;
+ if (IsXaml2009LanguagePrimitive(node))
+ value = CreateLanguagePrimitive(type, node);
+ else if (node.Properties.ContainsKey(XmlName.xArguments) || node.Properties.ContainsKey(XmlName.xFactoryMethod))
+ value = CreateFromFactory(type, node);
+ else if (
+ type.GetTypeInfo()
+ .DeclaredConstructors.Any(
+ ci =>
+ ci.IsPublic && ci.GetParameters().Length != 0 &&
+ ci.GetParameters().All(pi => pi.CustomAttributes.Any(attr => attr.AttributeType == typeof (ParameterAttribute)))) &&
+ ValidateCtorArguments(type, node, out ctorargname))
+ value = CreateFromParameterizedConstructor(type, node);
+ else if (!type.GetTypeInfo().DeclaredConstructors.Any(ci => ci.IsPublic && ci.GetParameters().Length == 0) &&
+ !ValidateCtorArguments(type, node, out ctorargname))
+ {
+ throw new XamlParseException(
+ String.Format("The Property {0} is required to create a {1} object.", ctorargname, type.FullName), node);
+ }
+ else
+ {
+ //this is a trick as the DataTemplate parameterless ctor is internal, and we can't CreateInstance(..., false) on WP7
+ try
+ {
+ if (type == typeof (DataTemplate))
+ value = new DataTemplate();
+ if (type == typeof (ControlTemplate))
+ value = new ControlTemplate();
+ if (value == null && node.CollectionItems.Any() && node.CollectionItems.First() is ValueNode)
+ {
+ var serviceProvider = new XamlServiceProvider(node, Context);
+ var converted = ((ValueNode)node.CollectionItems.First()).Value.ConvertTo(type, () => type.GetTypeInfo(),
+ serviceProvider);
+ if (converted != null && converted.GetType() == type)
+ value = converted;
+ }
+ if (value == null)
+ value = Activator.CreateInstance(type);
+ }
+ catch (TargetInvocationException e)
+ {
+ if (e.InnerException is XamlParseException || e.InnerException is XmlException)
+ throw e.InnerException;
+ throw;
+ }
+ }
+
+ Values[node] = value;
+
+ var typeExtension = value as TypeExtension;
+ if (typeExtension != null)
+ {
+ var serviceProvider = new XamlServiceProvider(node, Context);
+
+ var visitor = new ApplyPropertiesVisitor(Context);
+ foreach (var cnode in node.Properties.Values.ToList())
+ cnode.Accept(visitor, node);
+ foreach (var cnode in node.CollectionItems)
+ cnode.Accept(visitor, node);
+
+ value = typeExtension.ProvideValue(serviceProvider);
+
+ node.Properties.Clear();
+ node.CollectionItems.Clear();
+
+ Values[node] = value;
+ }
+
+ if (value is BindableObject)
+ NameScope.SetNameScope(value as BindableObject, node.Namescope);
+ }
+
+ public void Visit(RootNode node, INode parentNode)
+ {
+ var rnode = (XamlLoader.RuntimeRootNode)node;
+ Values[node] = rnode.Root;
+ Context.Types[node] = rnode.Root.GetType();
+ NameScope.SetNameScope(rnode.Root as BindableObject, node.Namescope);
+ }
+
+ public void Visit(ListNode node, INode parentNode)
+ {
+ //this is a gross hack to keep ListNode alive. ListNode must go in favor of Properties
+ XmlName name;
+ if (ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out name))
+ node.XmlName = name;
+ }
+
+ bool ValidateCtorArguments(Type nodeType, IElementNode node, out string missingArgName)
+ {
+ missingArgName = null;
+ var ctorInfo =
+ nodeType.GetTypeInfo()
+ .DeclaredConstructors.FirstOrDefault(
+ ci =>
+ ci.GetParameters().Length != 0 && ci.IsPublic &&
+ ci.GetParameters().All(pi => pi.CustomAttributes.Any(attr => attr.AttributeType == typeof (ParameterAttribute))));
+ if (ctorInfo == null)
+ return true;
+ foreach (var parameter in ctorInfo.GetParameters())
+ {
+ var propname =
+ parameter.CustomAttributes.First(ca => ca.AttributeType.FullName == "Xamarin.Forms.ParameterAttribute")
+ .ConstructorArguments.First()
+ .Value as string;
+ if (!node.Properties.ContainsKey(new XmlName("", propname)))
+ {
+ missingArgName = propname;
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public object CreateFromParameterizedConstructor(Type nodeType, IElementNode node)
+ {
+ var ctorInfo =
+ nodeType.GetTypeInfo()
+ .DeclaredConstructors.FirstOrDefault(
+ ci =>
+ ci.GetParameters().Length != 0 && ci.IsPublic &&
+ ci.GetParameters().All(pi => pi.CustomAttributes.Any(attr => attr.AttributeType == typeof (ParameterAttribute))));
+ object[] arguments = CreateArgumentsArray(node, ctorInfo);
+ return ctorInfo.Invoke(arguments);
+ }
+
+ public object CreateFromFactory(Type nodeType, IElementNode node)
+ {
+ object[] arguments = CreateArgumentsArray(node);
+
+ if (!node.Properties.ContainsKey(XmlName.xFactoryMethod))
+ {
+ //non-default ctor
+ return Activator.CreateInstance(nodeType, arguments);
+ }
+
+ var factoryMethod = ((string)((ValueNode)node.Properties[XmlName.xFactoryMethod]).Value);
+ Type[] types = arguments == null ? new Type[0] : arguments.Select(a => a.GetType()).ToArray();
+ var mi = nodeType.GetRuntimeMethod(factoryMethod, types);
+ if (mi == null || !mi.IsStatic)
+ {
+ throw new MissingMemberException(String.Format("No static method found for {0}::{1} ({2})", nodeType.FullName,
+ factoryMethod, string.Join(", ", types.Select(t => t.FullName))));
+ }
+ return mi.Invoke(null, arguments);
+ }
+
+ public object[] CreateArgumentsArray(IElementNode enode)
+ {
+ if (!enode.Properties.ContainsKey(XmlName.xArguments))
+ return null;
+ var node = enode.Properties[XmlName.xArguments];
+ var elementNode = node as ElementNode;
+ if (elementNode != null)
+ {
+ var array = new object[1];
+ array[0] = Values[elementNode];
+ return array;
+ }
+
+ var listnode = node as ListNode;
+ if (listnode != null)
+ {
+ var array = new object[listnode.CollectionItems.Count];
+ for (var i = 0; i < listnode.CollectionItems.Count; i++)
+ array[i] = Values[(ElementNode)listnode.CollectionItems[i]];
+ return array;
+ }
+ return null;
+ }
+
+ public object[] CreateArgumentsArray(IElementNode enode, ConstructorInfo ctorInfo)
+ {
+ var n = ctorInfo.GetParameters().Length;
+ var array = new object[n];
+ for (var i = 0; i < n; i++)
+ {
+ var parameter = ctorInfo.GetParameters()[i];
+ var propname =
+ parameter.CustomAttributes.First(attr => attr.AttributeType == typeof (ParameterAttribute))
+ .ConstructorArguments.First()
+ .Value as string;
+ var name = new XmlName("", propname);
+ INode node;
+ if (!enode.Properties.TryGetValue(name, out node))
+ {
+ throw new XamlParseException(
+ String.Format("The Property {0} is required to create a {1} object.", propname, ctorInfo.DeclaringType.FullName),
+ enode as IXmlLineInfo);
+ }
+ if (!enode.SkipProperties.Contains(name))
+ enode.SkipProperties.Add(name);
+ var value = Context.Values[node];
+ var serviceProvider = new XamlServiceProvider(enode, Context);
+ var convertedValue = value.ConvertTo(parameter.ParameterType, () => parameter, serviceProvider);
+ array[i] = convertedValue;
+ }
+
+ return array;
+ }
+
+ static bool IsXaml2009LanguagePrimitive(IElementNode node)
+ {
+ return node.NamespaceURI == "http://schemas.microsoft.com/winfx/2009/xaml";
+ }
+
+ static object CreateLanguagePrimitive(Type nodeType, IElementNode node)
+ {
+ object value = null;
+ if (nodeType == typeof (string))
+ value = String.Empty;
+ else if (nodeType == typeof (Uri))
+ value = null;
+ else
+ value = Activator.CreateInstance(nodeType);
+
+ if (node.CollectionItems.Count == 1 && node.CollectionItems[0] is ValueNode &&
+ ((ValueNode)node.CollectionItems[0]).Value is string)
+ {
+ var valuestring = ((ValueNode)node.CollectionItems[0]).Value as string;
+
+ if (nodeType == typeof (bool))
+ {
+ bool outbool;
+ if (bool.TryParse(valuestring, out outbool))
+ value = outbool;
+ }
+ else if (nodeType == typeof (char))
+ {
+ char retval;
+ if (char.TryParse(valuestring, out retval))
+ value = retval;
+ }
+ else if (nodeType == typeof (string))
+ value = valuestring;
+ else if (nodeType == typeof (decimal))
+ {
+ decimal retval;
+ if (decimal.TryParse(valuestring, NumberStyles.Number, CultureInfo.InvariantCulture, out retval))
+ value = retval;
+ }
+ else if (nodeType == typeof (float))
+ {
+ float retval;
+ if (float.TryParse(valuestring, NumberStyles.Number, CultureInfo.InvariantCulture, out retval))
+ value = retval;
+ }
+ else if (nodeType == typeof (double))
+ {
+ double retval;
+ if (double.TryParse(valuestring, NumberStyles.Number, CultureInfo.InvariantCulture, out retval))
+ value = retval;
+ }
+ else if (nodeType == typeof (byte))
+ {
+ byte retval;
+ if (byte.TryParse(valuestring, NumberStyles.Number, CultureInfo.InvariantCulture, out retval))
+ value = retval;
+ }
+ else if (nodeType == typeof (short))
+ {
+ short retval;
+ if (short.TryParse(valuestring, NumberStyles.Number, CultureInfo.InvariantCulture, out retval))
+ value = retval;
+ }
+ else if (nodeType == typeof (int))
+ {
+ int retval;
+ if (int.TryParse(valuestring, NumberStyles.Number, CultureInfo.InvariantCulture, out retval))
+ value = retval;
+ }
+ else if (nodeType == typeof (long))
+ {
+ long retval;
+ if (long.TryParse(valuestring, NumberStyles.Number, CultureInfo.InvariantCulture, out retval))
+ value = retval;
+ }
+ else if (nodeType == typeof (TimeSpan))
+ {
+ TimeSpan retval;
+ if (TimeSpan.TryParse(valuestring, CultureInfo.InvariantCulture, out retval))
+ value = retval;
+ }
+ else if (nodeType == typeof (Uri))
+ {
+ Uri retval;
+ if (Uri.TryCreate(valuestring, UriKind.RelativeOrAbsolute, out retval))
+ value = retval;
+ }
+ }
+ return value;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/ExpandMarkupsVisitor.cs b/Xamarin.Forms.Xaml/ExpandMarkupsVisitor.cs
new file mode 100644
index 00000000..0d5e9ee6
--- /dev/null
+++ b/Xamarin.Forms.Xaml/ExpandMarkupsVisitor.cs
@@ -0,0 +1,187 @@
+using System;
+using System.Collections.Generic;
+using System.Xml;
+using Xamarin.Forms.Xaml.Internals;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal class ExpandMarkupsVisitor : IXamlNodeVisitor
+ {
+ public ExpandMarkupsVisitor(HydratationContext context)
+ {
+ Context = context;
+ }
+
+ Dictionary<INode, object> Values
+ {
+ get { return Context.Values; }
+ }
+
+ HydratationContext Context { get; }
+
+ public bool VisitChildrenFirst
+ {
+ get { return true; }
+ }
+
+ public bool StopOnDataTemplate
+ {
+ get { return false; }
+ }
+
+ public bool StopOnResourceDictionary
+ {
+ get { return false; }
+ }
+
+ public void Visit(ValueNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(MarkupNode markupnode, INode parentNode)
+ {
+ var parentElement = parentNode as IElementNode;
+ XmlName propertyName;
+ if (!ApplyPropertiesVisitor.TryGetPropertyName(markupnode, parentNode, out propertyName))
+ return;
+ if (ApplyPropertiesVisitor.Skips.Contains(propertyName))
+ return;
+ if (parentElement.SkipProperties.Contains(propertyName))
+ return;
+
+ var markupString = markupnode.MarkupString;
+ var node =
+ ParseExpression(ref markupString, markupnode.NamespaceResolver, markupnode, markupnode, parentNode) as IElementNode;
+ if (node != null)
+ {
+ ((IElementNode)parentNode).Properties[propertyName] = node;
+ node.Parent = parentNode;
+ }
+ }
+
+ public void Visit(ElementNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(RootNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(ListNode node, INode parentNode)
+ {
+ }
+
+ INode ParseExpression(ref string expression, IXmlNamespaceResolver nsResolver, IXmlLineInfo xmlLineInfo, INode node,
+ INode parentNode)
+ {
+ if (expression.StartsWith("{}", StringComparison.Ordinal))
+ return new ValueNode(expression.Substring(2), null);
+
+ if (expression[expression.Length - 1] != '}')
+ throw new Exception("Expression must end with '}'");
+
+ int len;
+ string match;
+ if (!MarkupExpressionParser.MatchMarkup(out match, expression, out len))
+ throw new Exception();
+ expression = expression.Substring(len).TrimStart();
+ if (expression.Length == 0)
+ throw new Exception("Expression did not end in '}'");
+
+ var serviceProvider = new XamlServiceProvider(node, Context);
+ serviceProvider.Add(typeof (IXmlNamespaceResolver), nsResolver);
+
+ return new MarkupExpansionParser().Parse(match, ref expression, serviceProvider);
+ }
+
+ public class MarkupExpansionParser : MarkupExpressionParser, IExpressionParser<INode>
+ {
+ IElementNode node;
+
+ object IExpressionParser.Parse(string match, ref string remaining, IServiceProvider serviceProvider)
+ {
+ return Parse(match, ref remaining, serviceProvider);
+ }
+
+ public INode Parse(string match, ref string remaining, IServiceProvider serviceProvider)
+ {
+ var nsResolver = serviceProvider.GetService(typeof (IXmlNamespaceResolver)) as IXmlNamespaceResolver;
+ if (nsResolver == null)
+ throw new ArgumentException();
+ IXmlLineInfo xmlLineInfo = null;
+ var xmlLineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
+ if (xmlLineInfoProvider != null)
+ xmlLineInfo = xmlLineInfoProvider.XmlLineInfo;
+
+ var split = match.Split(':');
+ if (split.Length > 2)
+ throw new ArgumentException();
+
+ string prefix; //, name;
+ if (split.Length == 2)
+ {
+ prefix = split[0];
+ // name = split [1];
+ }
+ else
+ {
+ prefix = "";
+ // name = split [0];
+ }
+
+ Type type;
+ var typeResolver = serviceProvider.GetService(typeof (IXamlTypeResolver)) as IXamlTypeResolver;
+ if (typeResolver == null)
+ type = null;
+ else
+ {
+ //The order of lookup is to look for the Extension-suffixed class name first and then look for the class name without the Extension suffix.
+ if (!typeResolver.TryResolve(match + "Extension", out type) && !typeResolver.TryResolve(match, out type))
+ {
+ var lineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
+ var lineInfo = (lineInfoProvider != null) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+ throw new XamlParseException(String.Format("MarkupExtension not found for {0}", match), lineInfo);
+ }
+ }
+
+ var namespaceuri = nsResolver.LookupNamespace(prefix) ?? "";
+ var xmltype = new XmlType(namespaceuri, type.Name, null);
+
+ if (type == null)
+ throw new NotSupportedException();
+
+ node = xmlLineInfo == null
+ ? new ElementNode(xmltype, null, nsResolver)
+ : new ElementNode(xmltype, null, nsResolver, xmlLineInfo.LineNumber, xmlLineInfo.LinePosition);
+
+ if (remaining.StartsWith("}", StringComparison.Ordinal))
+ {
+ remaining = remaining.Substring(1);
+ return node;
+ }
+
+ char next;
+ string piece;
+ while ((piece = GetNextPiece(ref remaining, out next)) != null)
+ HandleProperty(piece, serviceProvider, ref remaining, next != '=');
+
+ return node;
+ }
+
+ protected override void SetPropertyValue(string prop, string strValue, object value, IServiceProvider serviceProvider)
+ {
+ var nsResolver = serviceProvider.GetService(typeof (IXmlNamespaceResolver)) as IXmlNamespaceResolver;
+
+ var childnode = value as INode ?? new ValueNode(strValue, nsResolver);
+ childnode.Parent = node;
+ if (prop != null)
+ {
+ var name = new XmlName(node.NamespaceURI, prop);
+ node.Properties[name] = childnode;
+ }
+ else //ContentProperty
+ node.CollectionItems.Add(childnode);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/FillResourceDictionariesVisitor.cs b/Xamarin.Forms.Xaml/FillResourceDictionariesVisitor.cs
new file mode 100644
index 00000000..5eb47887
--- /dev/null
+++ b/Xamarin.Forms.Xaml/FillResourceDictionariesVisitor.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using Xamarin.Forms.Xaml.Internals;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal class FillResourceDictionariesVisitor : IXamlNodeVisitor
+ {
+ public FillResourceDictionariesVisitor(HydratationContext context)
+ {
+ Context = context;
+ }
+
+ HydratationContext Context { get; }
+
+ Dictionary<INode, object> Values
+ {
+ get { return Context.Values; }
+ }
+
+ public bool VisitChildrenFirst
+ {
+ get { return false; }
+ }
+
+ public bool StopOnDataTemplate
+ {
+ get { return true; }
+ }
+
+ public bool StopOnResourceDictionary
+ {
+ get { return false; }
+ }
+
+ public void Visit(ValueNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(MarkupNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(ElementNode node, INode parentNode)
+ {
+ if (node.SkipPrefix(node.NamespaceResolver.LookupPrefix(node.NamespaceURI)))
+ return;
+
+ var value = Values[node];
+ var parentElement = parentNode as IElementNode;
+ var markupExtension = value as IMarkupExtension;
+ var valueProvider = value as IValueProvider;
+
+ //Set Resources in ResourcesDictionaries
+ if (IsCollectionItem(node, parentNode) && parentNode is IElementNode)
+ {
+ if (typeof (IEnumerable).GetTypeInfo().IsAssignableFrom(Context.Types[parentElement].GetTypeInfo()))
+ {
+ var source = Values[parentNode];
+ if (Context.Types[parentElement] == typeof (ResourceDictionary) && value is Style &&
+ !node.Properties.ContainsKey(XmlName.xKey))
+ {
+ node.Accept(new ApplyPropertiesVisitor(Context), parentNode);
+ if (markupExtension != null)
+ {
+ var serviceProvider = new XamlServiceProvider(node, Context);
+ value = markupExtension.ProvideValue(serviceProvider);
+ }
+ if (valueProvider != null)
+ {
+ var serviceProvider = new XamlServiceProvider(node, Context);
+ value = valueProvider.ProvideValue(serviceProvider);
+ }
+ ((ResourceDictionary)source).Add(value as Style);
+ }
+ else if (Context.Types[parentElement] == typeof (ResourceDictionary) && !node.Properties.ContainsKey(XmlName.xKey))
+ throw new XamlParseException("resources in ResourceDictionary require a x:Key attribute", node);
+ else if (Context.Types[parentElement] == typeof (ResourceDictionary) && node.Properties.ContainsKey(XmlName.xKey))
+ {
+ node.Accept(new ApplyPropertiesVisitor(Context), parentNode);
+ if (markupExtension != null)
+ {
+ var serviceProvider = new XamlServiceProvider(node, Context);
+ value = markupExtension.ProvideValue(serviceProvider);
+ }
+ if (valueProvider != null)
+ {
+ var serviceProvider = new XamlServiceProvider(node, Context);
+ value = valueProvider.ProvideValue(serviceProvider);
+ }
+ ((ResourceDictionary)source).Add((string)(((ValueNode)node.Properties[XmlName.xKey]).Value), value);
+ }
+ }
+ }
+
+ //Set RD to VE
+ XmlName propertyName;
+ if (ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out propertyName))
+ {
+ if ((propertyName.LocalName == "Resources" ||
+ propertyName.LocalName.EndsWith(".Resources", StringComparison.Ordinal)) && value is ResourceDictionary)
+ {
+ var source = Values[parentNode];
+ ApplyPropertiesVisitor.SetPropertyValue(source, propertyName, value, Context.RootElement, node, Context, node);
+ }
+ }
+ }
+
+ public void Visit(RootNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(ListNode node, INode parentNode)
+ {
+ }
+
+ static bool IsCollectionItem(INode node, INode parentNode)
+ {
+ var parentList = parentNode as IListNode;
+ if (parentList == null)
+ return false;
+ return parentList.CollectionItems.Contains(node);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/HydratationContext.cs b/Xamarin.Forms.Xaml/HydratationContext.cs
new file mode 100644
index 00000000..befb9095
--- /dev/null
+++ b/Xamarin.Forms.Xaml/HydratationContext.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal class HydratationContext
+ {
+ public HydratationContext()
+ {
+ Values = new Dictionary<INode, object>();
+ Types = new Dictionary<IElementNode, Type>();
+ }
+
+ public Dictionary<INode, object> Values { get; private set; }
+
+ public Dictionary<IElementNode, Type> Types { get; private set; }
+
+ public HydratationContext ParentContext { get; set; }
+
+ public BindableObject RootElement { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/IDictionaryExtensions.cs b/Xamarin.Forms.Xaml/IDictionaryExtensions.cs
new file mode 100644
index 00000000..2cbb0376
--- /dev/null
+++ b/Xamarin.Forms.Xaml/IDictionaryExtensions.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal static class IDictionaryExtensions
+ {
+ public static void AddRange<TKey, TValue>(this IDictionary<TKey, TValue> dictionary,
+ IEnumerable<KeyValuePair<TKey, TValue>> collection)
+ {
+ foreach (var kvp in collection)
+ dictionary.Add(kvp);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/IExpressionParser.cs b/Xamarin.Forms.Xaml/IExpressionParser.cs
new file mode 100644
index 00000000..39b92273
--- /dev/null
+++ b/Xamarin.Forms.Xaml/IExpressionParser.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal interface IExpressionParser
+ {
+ object Parse(string match, ref string expression, IServiceProvider serviceProvider);
+ }
+
+ internal interface IExpressionParser<out T> : IExpressionParser
+ where T : class
+ {
+ new T Parse(string match, ref string expression, IServiceProvider serviceProvider);
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/MarkupExpressionParser.cs b/Xamarin.Forms.Xaml/MarkupExpressionParser.cs
new file mode 100644
index 00000000..db97d320
--- /dev/null
+++ b/Xamarin.Forms.Xaml/MarkupExpressionParser.cs
@@ -0,0 +1,227 @@
+//
+// MarkupExpressionParser.cs
+//
+// This code is partly salvaged from moonlight. Following licence apply.
+//
+//
+// Author(s):
+// Moonlight List (moonlight-list@lists.ximian.com)
+// Stephane Delcroix (stephane@mi8.be)
+//
+// Copyright 2009 Novell, Inc.
+// Copyright 2013 Xamarin, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Text;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal abstract class MarkupExpressionParser
+ {
+ public object ParseExpression(ref string expression, IServiceProvider serviceProvider)
+ {
+ if (serviceProvider == null)
+ throw new ArgumentNullException("serviceProvider");
+ if (expression.StartsWith("{}", StringComparison.Ordinal))
+ return expression.Substring(2);
+
+ if (expression[expression.Length - 1] != '}')
+ throw new Exception("Expression must end with '}'");
+
+ int len;
+ string match;
+ if (!MatchMarkup(out match, expression, out len))
+ return false;
+ expression = expression.Substring(len).TrimStart();
+ if (expression.Length == 0)
+ throw new Exception("Expression did not end in '}'");
+
+ var parser = Activator.CreateInstance(GetType()) as IExpressionParser;
+ return parser.Parse(match, ref expression, serviceProvider);
+ }
+
+ internal static bool MatchMarkup(out string match, string expression, out int end)
+ {
+ if (expression.Length < 2)
+ {
+ end = 1;
+ match = null;
+ return false;
+ }
+
+ if (expression[0] != '{')
+ {
+ end = 2;
+ match = null;
+ return false;
+ }
+
+ int i;
+ bool found = false;
+ for (i = 1; i < expression.Length; i++)
+ {
+ if (expression[i] == ' ')
+ continue;
+ found = true;
+ break;
+ }
+
+ if (!found)
+ {
+ end = 3;
+ match = null;
+ return false;
+ }
+
+ int c;
+ for (c = 0; c + i < expression.Length; c++)
+ {
+ if (expression[i + c] == ' ' || expression[i + c] == '}')
+ break;
+ }
+
+ if (i + c == expression.Length)
+ {
+ end = 6;
+ match = null;
+ return false;
+ }
+
+ end = i + c;
+ match = expression.Substring(i, c);
+ return true;
+ }
+
+ protected void HandleProperty(string prop, IServiceProvider serviceProvider, ref string remaining, bool isImplicit)
+ {
+ char next;
+ object value = null;
+ string str_value;
+
+ if (isImplicit)
+ {
+ SetPropertyValue(null, prop, null, serviceProvider);
+ return;
+ }
+ remaining = remaining.TrimStart();
+ if (remaining.StartsWith("{", StringComparison.Ordinal))
+ {
+ value = ParseExpression(ref remaining, serviceProvider);
+ remaining = remaining.TrimStart();
+
+ if (remaining.Length > 0 && remaining[0] == ',')
+ remaining = remaining.Substring(1);
+
+ str_value = value as string;
+ }
+ else
+ str_value = GetNextPiece(ref remaining, out next);
+
+ SetPropertyValue(prop, str_value, value, serviceProvider);
+ }
+
+ protected abstract void SetPropertyValue(string prop, string strValue, object value, IServiceProvider serviceProvider);
+
+ protected string GetNextPiece(ref string remaining, out char next)
+ {
+ bool inString = false;
+ int end = 0;
+ char stringTerminator = '\0';
+ remaining = remaining.TrimStart();
+ if (remaining.Length == 0)
+ {
+ next = Char.MaxValue;
+ return null;
+ }
+
+ var piece = new StringBuilder();
+ // If we're inside a quoted string we append all chars to our piece until we hit the ending quote.
+ while (end < remaining.Length &&
+ (inString || (remaining[end] != '}' && remaining[end] != ',' && remaining[end] != '=')))
+ {
+ if (inString)
+ {
+ if (remaining[end] == stringTerminator)
+ {
+ inString = false;
+ end ++;
+ break;
+ }
+ }
+ else
+ {
+ if (remaining[end] == '\'' || remaining[end] == '"')
+ {
+ inString = true;
+ stringTerminator = remaining[end];
+ end ++;
+ continue;
+ }
+ }
+
+ // If this is an escape char, consume it and append the next char to our piece.
+ if (remaining[end] == '\\')
+ {
+ end ++;
+ if (end == remaining.Length)
+ break;
+ }
+ piece.Append(remaining[end]);
+ end++;
+ }
+
+ if (inString && end == remaining.Length)
+ throw new Exception("Unterminated quoted string");
+
+ if (end == remaining.Length && !remaining.EndsWith("}", StringComparison.Ordinal))
+ throw new Exception("Expression did not end with '}'");
+
+ if (end == 0)
+ {
+ next = Char.MaxValue;
+ return null;
+ }
+
+ next = remaining[end];
+ remaining = remaining.Substring(end + 1);
+
+ // Whitespace is trimmed from the end of the piece before stripping
+ // quote chars from the start/end of the string.
+ while (piece.Length > 0 && char.IsWhiteSpace(piece[piece.Length - 1]))
+ piece.Length --;
+
+ if (piece.Length >= 2)
+ {
+ char first = piece[0];
+ char last = piece[piece.Length - 1];
+ if ((first == '\'' && last == '\'') || (first == '"' && last == '"'))
+ {
+ piece.Remove(piece.Length - 1, 1);
+ piece.Remove(0, 1);
+ }
+ }
+
+ return piece.ToString();
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/MarkupExtensionParser.cs b/Xamarin.Forms.Xaml/MarkupExtensionParser.cs
new file mode 100644
index 00000000..cb62e1d1
--- /dev/null
+++ b/Xamarin.Forms.Xaml/MarkupExtensionParser.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Reflection;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal sealed class MarkupExtensionParser : MarkupExpressionParser, IExpressionParser<object>
+ {
+ IMarkupExtension markupExtension;
+
+ public object Parse(string match, ref string remaining, IServiceProvider serviceProvider)
+ {
+ var typeResolver = serviceProvider.GetService(typeof (IXamlTypeResolver)) as IXamlTypeResolver;
+
+ //shortcut for Binding and StaticResource, to avoid too many reflection calls.
+ if (match == "Binding")
+ markupExtension = new BindingExtension();
+ else if (match == "TemplateBinding")
+ markupExtension = new TemplateBindingExtension();
+ else if (match == "StaticResource")
+ markupExtension = new StaticResourceExtension();
+ else
+ {
+ if (typeResolver == null)
+ return null;
+ Type type;
+
+ //The order of lookup is to look for the Extension-suffixed class name first and then look for the class name without the Extension suffix.
+ if (!typeResolver.TryResolve(match + "Extension", out type) && !typeResolver.TryResolve(match, out type))
+ {
+ var lineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
+ var lineInfo = (lineInfoProvider != null) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+ throw new XamlParseException(String.Format("MarkupExtension not found for {0}", match), lineInfo);
+ }
+ markupExtension = Activator.CreateInstance(type) as IMarkupExtension;
+ }
+
+ if (markupExtension == null)
+ {
+ var lineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
+ var lineInfo = (lineInfoProvider != null) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+ throw new XamlParseException(String.Format("Missing public default constructor for MarkupExtension {0}", match),
+ lineInfo);
+ }
+
+ char next;
+ if (remaining == "}")
+ return markupExtension.ProvideValue(serviceProvider);
+
+ string piece;
+ while ((piece = GetNextPiece(ref remaining, out next)) != null)
+ HandleProperty(piece, serviceProvider, ref remaining, next != '=');
+
+ return markupExtension.ProvideValue(serviceProvider);
+ }
+
+ protected override void SetPropertyValue(string prop, string strValue, object value, IServiceProvider serviceProvider)
+ {
+ MethodInfo setter;
+ if (prop == null)
+ {
+ //implicit property
+ var t = markupExtension.GetType();
+ prop = ApplyPropertiesVisitor.GetContentPropertyName(t.GetTypeInfo());
+ if (prop == null)
+ return;
+ setter = t.GetRuntimeProperty(prop).SetMethod;
+ }
+ else
+ setter = markupExtension.GetType().GetRuntimeProperty(prop).SetMethod;
+
+ if (value == null && strValue != null)
+ {
+ value = strValue.ConvertTo(markupExtension.GetType().GetRuntimeProperty(prop).PropertyType,
+ (Func<TypeConverter>)null, serviceProvider);
+ }
+
+ setter.Invoke(markupExtension, new[] { value });
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/MarkupExtensions/ArrayExtension.cs b/Xamarin.Forms.Xaml/MarkupExtensions/ArrayExtension.cs
new file mode 100644
index 00000000..9f594132
--- /dev/null
+++ b/Xamarin.Forms.Xaml/MarkupExtensions/ArrayExtension.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Xaml
+{
+ [ContentProperty("Items")]
+ public class ArrayExtension : IMarkupExtension<Array>
+ {
+ public ArrayExtension()
+ {
+ Items = new List<object>();
+ }
+
+ public IList Items { get; }
+
+ public Type Type { get; set; }
+
+ public Array ProvideValue(IServiceProvider serviceProvider)
+ {
+ if (Type == null)
+ throw new InvalidOperationException("Type argument mandatory for x:Array extension");
+
+ if (Items == null)
+ return null;
+
+ var array = Array.CreateInstance(Type, Items.Count);
+ for (var i = 0; i < Items.Count; i++)
+ ((IList)array)[i] = Items[i];
+
+ return array;
+ }
+
+ object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
+ {
+ return (this as IMarkupExtension<Array>).ProvideValue(serviceProvider);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/MarkupExtensions/BindingExtension.cs b/Xamarin.Forms.Xaml/MarkupExtensions/BindingExtension.cs
new file mode 100644
index 00000000..f9af72a4
--- /dev/null
+++ b/Xamarin.Forms.Xaml/MarkupExtensions/BindingExtension.cs
@@ -0,0 +1,36 @@
+using System;
+
+namespace Xamarin.Forms.Xaml
+{
+ [ContentProperty("Path")]
+ public sealed class BindingExtension : IMarkupExtension<BindingBase>
+ {
+ public BindingExtension()
+ {
+ Mode = BindingMode.Default;
+ Path = Binding.SelfPath;
+ }
+
+ public string Path { get; set; }
+
+ public BindingMode Mode { get; set; }
+
+ public IValueConverter Converter { get; set; }
+
+ public object ConverterParameter { get; set; }
+
+ public string StringFormat { get; set; }
+
+ public object Source { get; set; }
+
+ BindingBase IMarkupExtension<BindingBase>.ProvideValue(IServiceProvider serviceProvider)
+ {
+ return new Binding(Path, Mode, Converter, ConverterParameter, StringFormat, Source);
+ }
+
+ object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
+ {
+ return (this as IMarkupExtension<BindingBase>).ProvideValue(serviceProvider);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/MarkupExtensions/DynamicResourceExtension.cs b/Xamarin.Forms.Xaml/MarkupExtensions/DynamicResourceExtension.cs
new file mode 100644
index 00000000..a15b2ca4
--- /dev/null
+++ b/Xamarin.Forms.Xaml/MarkupExtensions/DynamicResourceExtension.cs
@@ -0,0 +1,27 @@
+using System;
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms.Xaml
+{
+ [ContentProperty("Key")]
+ public sealed class DynamicResourceExtension : IMarkupExtension<DynamicResource>
+ {
+ public string Key { get; set; }
+
+ public object ProvideValue(IServiceProvider serviceProvider)
+ {
+ return ((IMarkupExtension<DynamicResource>)this).ProvideValue(serviceProvider);
+ }
+
+ DynamicResource IMarkupExtension<DynamicResource>.ProvideValue(IServiceProvider serviceProvider)
+ {
+ if (Key == null)
+ {
+ var lineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
+ var lineInfo = (lineInfoProvider != null) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+ throw new XamlParseException("DynamicResource markup require a Key", lineInfo);
+ }
+ return new DynamicResource(Key);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/MarkupExtensions/NullExtension.cs b/Xamarin.Forms.Xaml/MarkupExtensions/NullExtension.cs
new file mode 100644
index 00000000..7872a1c4
--- /dev/null
+++ b/Xamarin.Forms.Xaml/MarkupExtensions/NullExtension.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Xamarin.Forms.Xaml
+{
+ public class NullExtension : IMarkupExtension
+ {
+ public object ProvideValue(IServiceProvider serviceProvider)
+ {
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/MarkupExtensions/ReferenceExtension.cs b/Xamarin.Forms.Xaml/MarkupExtensions/ReferenceExtension.cs
new file mode 100644
index 00000000..6dc8280d
--- /dev/null
+++ b/Xamarin.Forms.Xaml/MarkupExtensions/ReferenceExtension.cs
@@ -0,0 +1,39 @@
+using System;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Xaml.Internals;
+
+namespace Xamarin.Forms.Xaml
+{
+ [ContentProperty("Name")]
+ public class ReferenceExtension : IMarkupExtension
+ {
+ public string Name { get; set; }
+
+ public object ProvideValue(IServiceProvider serviceProvider)
+ {
+ if (serviceProvider == null)
+ throw new ArgumentNullException("serviceProvider");
+ var valueProvider = serviceProvider.GetService(typeof (IProvideValueTarget)) as IProvideParentValues;
+ if (valueProvider == null)
+ throw new ArgumentException("serviceProvider does not provide an IProvideValueTarget");
+ var namescopeprovider = serviceProvider.GetService(typeof (INameScopeProvider)) as INameScopeProvider;
+ if (namescopeprovider != null && namescopeprovider.NameScope != null)
+ {
+ var value = namescopeprovider.NameScope.FindByName(Name);
+ if (value != null)
+ return value;
+ }
+
+ foreach (var target in valueProvider.ParentObjects)
+ {
+ var ns = target as INameScope;
+ if (ns == null)
+ continue;
+ var value = ns.FindByName(Name);
+ if (value != null)
+ return value;
+ }
+ throw new Exception("Can't resolve name on Element");
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/MarkupExtensions/StaticExtension.cs b/Xamarin.Forms.Xaml/MarkupExtensions/StaticExtension.cs
new file mode 100644
index 00000000..7585eb6e
--- /dev/null
+++ b/Xamarin.Forms.Xaml/MarkupExtensions/StaticExtension.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using System.Xml;
+
+namespace Xamarin.Forms.Xaml
+{
+ [ContentProperty("Member")]
+ public class StaticExtension : IMarkupExtension
+ {
+ public string Member { get; set; }
+
+ public object ProvideValue(IServiceProvider serviceProvider)
+ {
+ IXmlLineInfoProvider lineInfoProvider;
+ IXmlLineInfo lineInfo;
+
+ if (serviceProvider == null)
+ throw new ArgumentNullException("serviceProvider");
+ var typeResolver = serviceProvider.GetService(typeof (IXamlTypeResolver)) as IXamlTypeResolver;
+ if (typeResolver == null)
+ throw new ArgumentException("No IXamlTypeResolver in IServiceProvider");
+
+ if (string.IsNullOrEmpty(Member) || !Member.Contains("."))
+ {
+ lineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
+ lineInfo = (lineInfoProvider != null) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+ throw new XamlParseException("Syntax for x:Static is [Member=][prefix:]typeName.staticMemberName", lineInfo);
+ }
+
+ var dotIdx = Member.LastIndexOf('.');
+ var typename = Member.Substring(0, dotIdx);
+ var membername = Member.Substring(dotIdx + 1);
+
+ var type = typeResolver.Resolve(typename, serviceProvider);
+
+ var pinfo = type.GetRuntimeProperties().FirstOrDefault(pi => pi.Name == membername && pi.GetMethod.IsStatic);
+ if (pinfo != null)
+ return pinfo.GetMethod.Invoke(null, new object[] { });
+
+ var finfo = type.GetRuntimeFields().FirstOrDefault(fi => fi.Name == membername && fi.IsStatic);
+ if (finfo != null)
+ return finfo.GetValue(null);
+
+ lineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
+ lineInfo = (lineInfoProvider != null) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+ throw new XamlParseException(String.Format("No static member found for {0}", Member), lineInfo);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/MarkupExtensions/StaticResourceExtension.cs b/Xamarin.Forms.Xaml/MarkupExtensions/StaticResourceExtension.cs
new file mode 100644
index 00000000..e5a7aef7
--- /dev/null
+++ b/Xamarin.Forms.Xaml/MarkupExtensions/StaticResourceExtension.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace Xamarin.Forms.Xaml
+{
+ [ContentProperty("Key")]
+ public sealed class StaticResourceExtension : IMarkupExtension
+ {
+ public string Key { get; set; }
+
+ public object ProvideValue(IServiceProvider serviceProvider)
+ {
+ if (serviceProvider == null)
+ throw new ArgumentNullException("serviceProvider");
+ if (Key == null)
+ {
+ var lineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
+ var lineInfo = (lineInfoProvider != null) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
+ throw new XamlParseException("you must specify a key in {StaticResource}", lineInfo);
+ }
+ var valueProvider = serviceProvider.GetService(typeof (IProvideValueTarget)) as IProvideParentValues;
+ if (valueProvider == null)
+ throw new ArgumentException();
+ var xmlLineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
+ var xmlLineInfo = xmlLineInfoProvider != null ? xmlLineInfoProvider.XmlLineInfo : null;
+
+ foreach (var p in valueProvider.ParentObjects)
+ {
+ var ve = p as VisualElement;
+ if (ve == null)
+ continue;
+ if (ve.Resources == null)
+ continue;
+ object res;
+ if (ve.Resources.TryGetValue(Key, out res))
+ return res;
+ }
+ if (Application.Current != null && Application.Current.Resources != null &&
+ Application.Current.Resources.ContainsKey(Key))
+ return Application.Current.Resources[Key];
+
+ throw new XamlParseException(string.Format("StaticResource not found for key {0}", Key), xmlLineInfo);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/MarkupExtensions/TemplateBindingExtension.cs b/Xamarin.Forms.Xaml/MarkupExtensions/TemplateBindingExtension.cs
new file mode 100644
index 00000000..c14f9f94
--- /dev/null
+++ b/Xamarin.Forms.Xaml/MarkupExtensions/TemplateBindingExtension.cs
@@ -0,0 +1,34 @@
+using System;
+
+namespace Xamarin.Forms.Xaml
+{
+ [ContentProperty("Path")]
+ public sealed class TemplateBindingExtension : IMarkupExtension<BindingBase>
+ {
+ public TemplateBindingExtension()
+ {
+ Mode = BindingMode.Default;
+ Path = Binding.SelfPath;
+ }
+
+ public string Path { get; set; }
+
+ public BindingMode Mode { get; set; }
+
+ public IValueConverter Converter { get; set; }
+
+ public object ConverterParameter { get; set; }
+
+ public string StringFormat { get; set; }
+
+ BindingBase IMarkupExtension<BindingBase>.ProvideValue(IServiceProvider serviceProvider)
+ {
+ return new TemplateBinding(Path, Mode, Converter, ConverterParameter, StringFormat);
+ }
+
+ object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
+ {
+ return (this as IMarkupExtension<BindingBase>).ProvideValue(serviceProvider);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/MarkupExtensions/TypeExtension.cs b/Xamarin.Forms.Xaml/MarkupExtensions/TypeExtension.cs
new file mode 100644
index 00000000..f4bbf842
--- /dev/null
+++ b/Xamarin.Forms.Xaml/MarkupExtensions/TypeExtension.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace Xamarin.Forms.Xaml
+{
+ [ContentProperty("TypeName")]
+ public class TypeExtension : IMarkupExtension<Type>
+ {
+ public string TypeName { get; set; }
+
+ public Type ProvideValue(IServiceProvider serviceProvider)
+ {
+ if (serviceProvider == null)
+ throw new ArgumentNullException("serviceProvider");
+ var typeResolver = serviceProvider.GetService(typeof (IXamlTypeResolver)) as IXamlTypeResolver;
+ if (typeResolver == null)
+ throw new ArgumentException("No IXamlTypeResolver in IServiceProvider");
+
+ return typeResolver.Resolve(TypeName, serviceProvider);
+ }
+
+ object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
+ {
+ return (this as IMarkupExtension<Type>).ProvideValue(serviceProvider);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/NamescopingVisitor.cs b/Xamarin.Forms.Xaml/NamescopingVisitor.cs
new file mode 100644
index 00000000..0651d045
--- /dev/null
+++ b/Xamarin.Forms.Xaml/NamescopingVisitor.cs
@@ -0,0 +1,79 @@
+using System.Collections.Generic;
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal class NamescopingVisitor : IXamlNodeVisitor
+ {
+ readonly Dictionary<INode, INameScope> scopes = new Dictionary<INode, INameScope>();
+
+ public NamescopingVisitor(HydratationContext context)
+ {
+ Values = context.Values;
+ }
+
+ Dictionary<INode, object> Values { get; set; }
+
+ public bool VisitChildrenFirst
+ {
+ get { return false; }
+ }
+
+ public bool StopOnDataTemplate
+ {
+ get { return false; }
+ }
+
+ public bool StopOnResourceDictionary
+ {
+ get { return false; }
+ }
+
+ public void Visit(ValueNode node, INode parentNode)
+ {
+ scopes[node] = scopes[parentNode];
+ }
+
+ public void Visit(MarkupNode node, INode parentNode)
+ {
+ scopes[node] = scopes[parentNode];
+ }
+
+ public void Visit(ElementNode node, INode parentNode)
+ {
+ var ns = parentNode == null || IsDataTemplate(node, parentNode) || IsStyle(node, parentNode)
+ ? new NameScope()
+ : scopes[parentNode];
+ node.Namescope = ns;
+ scopes[node] = ns;
+ }
+
+ public void Visit(RootNode node, INode parentNode)
+ {
+ var ns = new NameScope();
+ node.Namescope = ns;
+ scopes[node] = ns;
+ }
+
+ public void Visit(ListNode node, INode parentNode)
+ {
+ scopes[node] = scopes[parentNode];
+ }
+
+ static bool IsDataTemplate(INode node, INode parentNode)
+ {
+ var parentElement = parentNode as IElementNode;
+ INode createContent;
+ if (parentElement != null && parentElement.Properties.TryGetValue(XmlName._CreateContent, out createContent) &&
+ createContent == node)
+ return true;
+ return false;
+ }
+
+ static bool IsStyle(INode node, INode parentNode)
+ {
+ var pnode = parentNode as ElementNode;
+ return pnode != null && pnode.XmlType.Name == "Style";
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/Properties/AssemblyInfo.cs b/Xamarin.Forms.Xaml/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..03b4fb12
--- /dev/null
+++ b/Xamarin.Forms.Xaml/Properties/AssemblyInfo.cs
@@ -0,0 +1,25 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Xamarin.Forms;
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("Xamarin.Forms.Xaml")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCulture("")]
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+//[assembly: AssemblyVersion ("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
+[assembly: InternalsVisibleTo("Xamarin.Forms.Xaml.UnitTests")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Build.Tasks")]
+[assembly: InternalsVisibleTo("Xamarin.Forms.Xaml.Design")]
+[assembly: Preserve] \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/RegisterXNamesVisitor.cs b/Xamarin.Forms.Xaml/RegisterXNamesVisitor.cs
new file mode 100644
index 00000000..7985cff1
--- /dev/null
+++ b/Xamarin.Forms.Xaml/RegisterXNamesVisitor.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal class RegisterXNamesVisitor : IXamlNodeVisitor
+ {
+ public RegisterXNamesVisitor(HydratationContext context)
+ {
+ Values = context.Values;
+ }
+
+ Dictionary<INode, object> Values { get; }
+
+ public bool VisitChildrenFirst
+ {
+ get { return false; }
+ }
+
+ public bool StopOnDataTemplate
+ {
+ get { return true; }
+ }
+
+ public bool StopOnResourceDictionary
+ {
+ get { return false; }
+ }
+
+ public void Visit(ValueNode node, INode parentNode)
+ {
+ if (!IsXNameProperty(node, parentNode))
+ return;
+ try
+ {
+ ((IElementNode)parentNode).Namescope.RegisterName((string)node.Value, Values[parentNode]);
+ }
+ catch (ArgumentException ae)
+ {
+ if (ae.ParamName != "name")
+ throw ae;
+ throw new XamlParseException(
+ string.Format("An element with the name \"{0}\" already exists in this NameScope", (string)node.Value), node);
+ }
+ }
+
+ public void Visit(MarkupNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(ElementNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(RootNode node, INode parentNode)
+ {
+ }
+
+ public void Visit(ListNode node, INode parentNode)
+ {
+ }
+
+ static bool IsXNameProperty(ValueNode node, INode parentNode)
+ {
+ var parentElement = parentNode as IElementNode;
+ INode xNameNode;
+ if (parentElement != null && parentElement.Properties.TryGetValue(XmlName.xName, out xNameNode) && xNameNode == node)
+ return true;
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/TypeArgumentsParser.cs b/Xamarin.Forms.Xaml/TypeArgumentsParser.cs
new file mode 100644
index 00000000..59b2dd0a
--- /dev/null
+++ b/Xamarin.Forms.Xaml/TypeArgumentsParser.cs
@@ -0,0 +1,54 @@
+using System.Collections.Generic;
+using System.Xml;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal static class TypeArgumentsParser
+ {
+ public static IList<XmlType> ParseExpression(string expression, IXmlNamespaceResolver resolver, IXmlLineInfo lineInfo)
+ {
+ var typeList = new List<XmlType>();
+ while (!string.IsNullOrWhiteSpace(expression))
+ {
+ var match = expression;
+ typeList.Add(Parse(match, ref expression, resolver, lineInfo));
+ }
+ return typeList;
+ }
+
+ static XmlType Parse(string match, ref string remaining, IXmlNamespaceResolver resolver, IXmlLineInfo lineinfo)
+ {
+ remaining = null;
+ int parensCount = 0;
+ int pos = 0;
+ bool isGeneric = false;
+
+ for (pos = 0; pos < match.Length; pos++)
+ {
+ if (match[pos] == '(')
+ {
+ parensCount++;
+ isGeneric = true;
+ }
+ else if (match[pos] == ')')
+ parensCount--;
+ else if (match[pos] == ',' && parensCount == 0)
+ {
+ remaining = match.Substring(pos + 1);
+ break;
+ }
+ }
+ var type = match.Substring(0, pos).Trim();
+
+ IList<XmlType> typeArguments = null;
+ if (isGeneric)
+ {
+ typeArguments = ParseExpression(
+ type.Substring(type.IndexOf('(') + 1, type.LastIndexOf(')') - type.IndexOf('(') - 1), resolver, lineinfo);
+ type = type.Substring(0, type.IndexOf('('));
+ }
+ var namespaceuri = type.Contains(":") ? resolver.LookupNamespace(type.Split(':')[0].Trim()) : "";
+ return new XmlType(namespaceuri, type, typeArguments);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/TypeConversionExtensions.cs b/Xamarin.Forms.Xaml/TypeConversionExtensions.cs
new file mode 100644
index 00000000..a81ed11d
--- /dev/null
+++ b/Xamarin.Forms.Xaml/TypeConversionExtensions.cs
@@ -0,0 +1,162 @@
+//
+// InternalExtensions.cs
+//
+// Author:
+// Stephane Delcroix <stephane@mi8.be>
+//
+// Copyright (c) 2013 Mobile Inception
+// Copyright (c) 2014 Xamarin, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal static class TypeConversionExtensions
+ {
+ internal static object ConvertTo(this object value, Type toType, Func<ParameterInfo> pinfoRetriever,
+ IServiceProvider serviceProvider)
+ {
+ Func<TypeConverter> getConverter = () =>
+ {
+ ParameterInfo pInfo;
+ if (pinfoRetriever == null || (pInfo = pinfoRetriever()) == null)
+ return null;
+
+ var converterTypeName = pInfo.CustomAttributes.GetTypeConverterTypeName();
+ if (converterTypeName == null)
+ return null;
+ var convertertype = Type.GetType(converterTypeName);
+ return (TypeConverter)Activator.CreateInstance(convertertype);
+ };
+
+ return ConvertTo(value, toType, getConverter, serviceProvider);
+ }
+
+ internal static object ConvertTo(this object value, Type toType, Func<MemberInfo> minfoRetriever,
+ IServiceProvider serviceProvider)
+ {
+ Func<object> getConverter = () =>
+ {
+ MemberInfo memberInfo;
+
+ var converterTypeName = toType.GetTypeInfo().CustomAttributes.GetTypeConverterTypeName();
+ if (minfoRetriever != null && (memberInfo = minfoRetriever()) != null)
+ converterTypeName = memberInfo.CustomAttributes.GetTypeConverterTypeName() ?? converterTypeName;
+ if (converterTypeName == null)
+ return null;
+
+ var convertertype = Type.GetType(converterTypeName);
+ return Activator.CreateInstance(convertertype);
+ };
+
+ return ConvertTo(value, toType, getConverter, serviceProvider);
+ }
+
+ static string GetTypeConverterTypeName(this IEnumerable<CustomAttributeData> attributes)
+ {
+ var converterAttribute =
+ attributes.FirstOrDefault(cad => TypeConverterAttribute.TypeConvertersType.Contains(cad.AttributeType.FullName));
+ if (converterAttribute == null)
+ return null;
+ if (converterAttribute.ConstructorArguments[0].ArgumentType == typeof (string))
+ return (string)converterAttribute.ConstructorArguments[0].Value;
+ if (converterAttribute.ConstructorArguments[0].ArgumentType == typeof (Type))
+ return ((Type)converterAttribute.ConstructorArguments[0].Value).AssemblyQualifiedName;
+ return null;
+ }
+
+ //Don't change the name or the signature of this, it's used by XamlC
+ public static object ConvertTo(this object value, Type toType, Type convertertype, IServiceProvider serviceProvider)
+ {
+ if (convertertype == null)
+ return value.ConvertTo(toType, (Func<object>)null, serviceProvider);
+ Func<object> getConverter = () => Activator.CreateInstance(convertertype);
+ ;
+ return value.ConvertTo(toType, getConverter, serviceProvider);
+ }
+
+ internal static object ConvertTo(this object value, Type toType, Func<object> getConverter,
+ IServiceProvider serviceProvider)
+ {
+ if (value == null)
+ return null;
+
+ var str = value as string;
+ if (str != null)
+ {
+ //If there's a [TypeConverter], use it
+ object converter = getConverter?.Invoke();
+ var xfTypeConverter = converter as TypeConverter;
+ var xfExtendedTypeConverter = xfTypeConverter as IExtendedTypeConverter;
+ if (xfExtendedTypeConverter != null)
+ return value = xfExtendedTypeConverter.ConvertFromInvariantString(str, serviceProvider);
+ if (xfTypeConverter != null)
+ return value = xfTypeConverter.ConvertFromInvariantString(str);
+ var converterType = converter?.GetType();
+ if (converterType != null)
+ {
+ var convertFromStringInvariant = converterType.GetRuntimeMethod("ConvertFromInvariantString",
+ new[] { typeof (string) });
+ if (convertFromStringInvariant != null)
+ return value = convertFromStringInvariant.Invoke(converter, new object[] { str });
+ }
+
+ //If the type is nullable, as the value is not null, it's safe to assume we want the built-in conversion
+ if (toType.GetTypeInfo().IsGenericType && toType.GetGenericTypeDefinition() == typeof (Nullable<>))
+ toType = Nullable.GetUnderlyingType(toType);
+
+ //Obvious Built-in conversions
+ if (toType.GetTypeInfo().IsEnum)
+ return Enum.Parse(toType, str);
+ //TODO supports Int16, 64, Byte, Char, ...
+ if (toType == typeof (Int32))
+ return Int32.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof (float))
+ return Single.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof (double))
+ return Double.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof (bool))
+ return Boolean.Parse(str);
+ if (toType == typeof (TimeSpan))
+ return TimeSpan.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof (DateTime))
+ return DateTime.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof (string) && str.StartsWith("{}", StringComparison.Ordinal))
+ return str.Substring(2);
+ if (toType == typeof (string))
+ return value;
+ }
+
+ //if there's an implicit conversion, convert
+ if (value != null)
+ {
+ var cast = value.GetType().GetRuntimeMethod("op_Implicit", new[] { value.GetType() });
+ if (cast != null && cast.ReturnType == toType)
+ value = cast.Invoke(null, new[] { value });
+ }
+ return value;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/ValueConverterProvider.cs b/Xamarin.Forms.Xaml/ValueConverterProvider.cs
new file mode 100644
index 00000000..f7859e0c
--- /dev/null
+++ b/Xamarin.Forms.Xaml/ValueConverterProvider.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Reflection;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal class ValueConverterProvider : IValueConverterProvider
+ {
+ public object Convert(object value, Type toType, Func<MemberInfo> minfoRetriever, IServiceProvider serviceProvider)
+ {
+ return value.ConvertTo(toType, minfoRetriever, serviceProvider);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/ViewExtensions.cs b/Xamarin.Forms.Xaml/ViewExtensions.cs
new file mode 100644
index 00000000..fb8a612a
--- /dev/null
+++ b/Xamarin.Forms.Xaml/ViewExtensions.cs
@@ -0,0 +1,46 @@
+//
+// ViewExtensions.cs
+//
+// Author:
+// Stephane Delcroix <stephane@mi8.be>
+//
+// Copyright (c) 2013 Mobile Inception
+// Copyright (c) 2013 Xamarin, Inc
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace Xamarin.Forms.Xaml
+{
+ public static class Extensions
+ {
+ public static TView LoadFromXaml<TView>(this TView view, Type callingType) where TView : BindableObject
+ {
+ XamlLoader.Load(view, callingType);
+ return view;
+ }
+
+ internal static TView LoadFromXaml<TView>(this TView view, string xaml) where TView : BindableObject
+ {
+ XamlLoader.Load(view, xaml);
+ return view;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.csproj b/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.csproj
new file mode 100644
index 00000000..9c60ec98
--- /dev/null
+++ b/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.csproj
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>12.0.0</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{9DB2F292-8034-4E06-89AD-98BBDA4306B9}</ProjectGuid>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <RootNamespace>Xamarin.Forms.Xaml</RootNamespace>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>full</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Turkey|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Turkey\</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="..\Xamarin.Forms.Core\Properties\GlobalAssemblyInfo.cs">
+ <Link>Properties\GlobalAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="MarkupExtensions\TemplateBindingExtension.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="MarkupExpressionParser.cs" />
+ <Compile Include="ViewExtensions.cs" />
+ <Compile Include="XamlLoader.cs" />
+ <Compile Include="XamlNode.cs" />
+ <Compile Include="XamlServiceProvider.cs" />
+ <Compile Include="XmlnsHelper.cs" />
+ <Compile Include="IExpressionParser.cs" />
+ <Compile Include="MarkupExtensionParser.cs" />
+ <Compile Include="TypeConversionExtensions.cs" />
+ <Compile Include="IDictionaryExtensions.cs" />
+ <Compile Include="MarkupExtensions\NullExtension.cs" />
+ <Compile Include="MarkupExtensions\ReferenceExtension.cs" />
+ <Compile Include="MarkupExtensions\StaticExtension.cs" />
+ <Compile Include="MarkupExtensions\TypeExtension.cs" />
+ <Compile Include="MarkupExtensions\ArrayExtension.cs" />
+ <Compile Include="XmlName.cs" />
+ <Compile Include="XamlNodeVisitor.cs" />
+ <Compile Include="NamescopingVisitor.cs" />
+ <Compile Include="CreateValuesVisitor.cs" />
+ <Compile Include="ApplyPropertiesVisitor.cs" />
+ <Compile Include="HydratationContext.cs" />
+ <Compile Include="RegisterXNamesVisitor.cs" />
+ <Compile Include="XamlParser.cs" />
+ <Compile Include="MarkupExtensions\BindingExtension.cs" />
+ <Compile Include="MarkupExtensions\StaticResourceExtension.cs" />
+ <Compile Include="MarkupExtensions\DynamicResourceExtension.cs" />
+ <Compile Include="ValueConverterProvider.cs" />
+ <Compile Include="FillResourceDictionariesVisitor.cs" />
+ <Compile Include="ExpandMarkupsVisitor.cs" />
+ <Compile Include="XamlCompilationAttribute.cs" />
+ <Compile Include="TypeArgumentsParser.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup />
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/XamlCompilationAttribute.cs b/Xamarin.Forms.Xaml/XamlCompilationAttribute.cs
new file mode 100644
index 00000000..76199039
--- /dev/null
+++ b/Xamarin.Forms.Xaml/XamlCompilationAttribute.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Reflection;
+
+namespace Xamarin.Forms.Xaml
+{
+ [Flags]
+ public enum XamlCompilationOptions
+ {
+ Skip = 1 << 0,
+ Compile = 1 << 1
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class, Inherited = false)]
+ public sealed class XamlCompilationAttribute : Attribute
+ {
+ public XamlCompilationAttribute(XamlCompilationOptions xamlCompilationOptions)
+ {
+ XamlCompilationOptions = xamlCompilationOptions;
+ }
+
+ public XamlCompilationOptions XamlCompilationOptions { get; set; }
+ }
+
+ internal static class XamlCExtensions
+ {
+ public static bool IsCompiled(this Type type)
+ {
+ var attr = type.GetTypeInfo().GetCustomAttribute<XamlCompilationAttribute>();
+ if (attr != null)
+ return attr.XamlCompilationOptions == XamlCompilationOptions.Compile;
+ attr = type.GetTypeInfo().Module.GetCustomAttribute<XamlCompilationAttribute>();
+ if (attr != null)
+ return attr.XamlCompilationOptions == XamlCompilationOptions.Compile;
+ attr = type.GetTypeInfo().Assembly.GetCustomAttribute<XamlCompilationAttribute>();
+ if (attr != null)
+ return attr.XamlCompilationOptions == XamlCompilationOptions.Compile;
+
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/XamlLoader.cs b/Xamarin.Forms.Xaml/XamlLoader.cs
new file mode 100644
index 00000000..6d7674b9
--- /dev/null
+++ b/Xamarin.Forms.Xaml/XamlLoader.cs
@@ -0,0 +1,208 @@
+//
+// XamlLoader.cs
+//
+// Author:
+// Stephane Delcroix <stephane@mi8.be>
+//
+// Copyright (c) 2013 Mobile Inception
+// Copyright (c) 2013-2014 Xamarin, Inc
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Xml;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal static class XamlLoader
+ {
+ static readonly Dictionary<Type, string> XamlResources = new Dictionary<Type, string>();
+
+ public static void Load(BindableObject view, Type callingType)
+ {
+ var xaml = GetXamlForType(callingType);
+ if (string.IsNullOrEmpty(xaml))
+ throw new XamlParseException(string.Format("No embeddedresources found for {0}", callingType), new XmlLineInfo());
+ Load(view, xaml);
+ }
+
+ public static void Load(BindableObject view, string xaml)
+ {
+ using(var reader = XmlReader.Create(new StringReader(xaml)))
+ {
+ while (reader.Read())
+ {
+ //Skip until element
+ if (reader.NodeType == XmlNodeType.Whitespace)
+ continue;
+ if (reader.NodeType != XmlNodeType.Element)
+ {
+ Debug.WriteLine("Unhandled node {0} {1} {2}", reader.NodeType, reader.Name, reader.Value);
+ continue;
+ }
+
+ var rootnode = new RuntimeRootNode(new XmlType(reader.NamespaceURI, reader.Name, null), view);
+
+ XamlParser.ParseXaml(rootnode, reader);
+
+ var visitorContext = new HydratationContext { RootElement = view };
+
+ rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null);
+ //set parents for {StaticResource}
+ rootnode.Accept(new ExpandMarkupsVisitor(visitorContext), null);
+ rootnode.Accept(new NamescopingVisitor(visitorContext), null); //set namescopes for {x:Reference}
+ rootnode.Accept(new CreateValuesVisitor(visitorContext), null);
+ rootnode.Accept(new RegisterXNamesVisitor(visitorContext), null);
+ rootnode.Accept(new FillResourceDictionariesVisitor(visitorContext), null);
+ rootnode.Accept(new ApplyPropertiesVisitor(visitorContext, true), null);
+ break;
+ }
+ }
+ }
+
+ static string GetXamlForType(Type type)
+ {
+ var assembly = type.GetTypeInfo().Assembly;
+
+ string resourceId;
+ if (XamlResources.TryGetValue(type, out resourceId))
+ {
+ var result = ReadResourceAsXaml(type, assembly, resourceId);
+ if (result != null)
+ return result;
+ }
+
+ var likelyResourceName = type.Name + ".xaml";
+ var resourceNames = assembly.GetManifestResourceNames();
+ string resourceName = null;
+
+ // first pass, pray to find it because the user named it correctly
+
+ string xaml = null;
+ foreach (var resource in resourceNames)
+ {
+ if (ResourceMatchesFilename(assembly, resource, likelyResourceName))
+ {
+ resourceName = resource;
+ xaml = ReadResourceAsXaml(type, assembly, resource);
+ if (xaml != null)
+ goto end;
+ }
+ }
+
+ // okay maybe they at least named it .xaml
+
+ foreach (var resource in resourceNames)
+ {
+ if (!resource.EndsWith(".xaml", StringComparison.OrdinalIgnoreCase))
+ continue;
+
+ resourceName = resource;
+ xaml = ReadResourceAsXaml(type, assembly, resource);
+ if (xaml != null)
+ goto end;
+ }
+
+ foreach (var resource in resourceNames)
+ {
+ if (resource.EndsWith(".xaml", StringComparison.OrdinalIgnoreCase))
+ continue;
+
+ resourceName = resource;
+ xaml = ReadResourceAsXaml(type, assembly, resource, true);
+ if (xaml != null)
+ goto end;
+ }
+
+ end:
+ if (xaml == null)
+ return null;
+
+ XamlResources[type] = resourceName;
+ return xaml;
+ }
+
+ static bool ResourceMatchesFilename(Assembly assembly, string resource, string filename)
+ {
+ try
+ {
+ var info = assembly.GetManifestResourceInfo(resource);
+
+ if (!string.IsNullOrEmpty(info.FileName) &&
+ string.Compare(info.FileName, filename, StringComparison.OrdinalIgnoreCase) == 0)
+ return true;
+ }
+ catch (PlatformNotSupportedException)
+ {
+ // Because Win10 + .NET Native
+ }
+
+ if (resource.EndsWith("." + filename, StringComparison.OrdinalIgnoreCase) ||
+ string.Compare(resource, filename, StringComparison.OrdinalIgnoreCase) == 0)
+ return true;
+
+ return false;
+ }
+
+ static string ReadResourceAsXaml(Type type, Assembly assembly, string likelyTargetName, bool validate = false)
+ {
+ using(var stream = assembly.GetManifestResourceStream(likelyTargetName))
+ using(var reader = new StreamReader(stream))
+ {
+ if (validate)
+ {
+ // terrible validation of XML. Unfortunately it will probably work most of the time since comments
+ // also start with a <. We can't bring in any real deps.
+
+ var firstNonWhitespace = (char)reader.Read();
+ while (char.IsWhiteSpace(firstNonWhitespace))
+ firstNonWhitespace = (char)reader.Read();
+
+ if (firstNonWhitespace != '<')
+ return null;
+
+ stream.Seek(0, SeekOrigin.Begin);
+ }
+
+ var xaml = reader.ReadToEnd();
+
+ var pattern = String.Format("x:Class *= *\"{0}\"", type.FullName);
+ var regex = new Regex(pattern, RegexOptions.ECMAScript);
+ if (regex.IsMatch(xaml) || xaml.Contains(String.Format("x:Class=\"{0}\"", type.FullName)))
+ return xaml;
+ }
+ return null;
+ }
+
+ public class RuntimeRootNode : RootNode
+ {
+ public RuntimeRootNode(XmlType xmlType, object root) : base(xmlType)
+ {
+ Root = root;
+ }
+
+ public object Root { get; private set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/XamlNode.cs b/Xamarin.Forms.Xaml/XamlNode.cs
new file mode 100644
index 00000000..2ef87c13
--- /dev/null
+++ b/Xamarin.Forms.Xaml/XamlNode.cs
@@ -0,0 +1,234 @@
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Xml;
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal interface INode
+ {
+ List<string> IgnorablePrefixes { get; set; }
+
+ IXmlNamespaceResolver NamespaceResolver { get; }
+
+ INode Parent { get; set; }
+
+ void Accept(IXamlNodeVisitor visitor, INode parentNode);
+ }
+
+ internal interface IValueNode : INode
+ {
+ }
+
+ internal interface IElementNode : INode, IListNode
+ {
+ Dictionary<XmlName, INode> Properties { get; }
+
+ List<XmlName> SkipProperties { get; }
+
+ INameScope Namescope { get; }
+
+ XmlType XmlType { get; }
+
+ string NamespaceURI { get; }
+ }
+
+ internal interface IListNode : INode
+ {
+ List<INode> CollectionItems { get; }
+ }
+
+ [DebuggerDisplay("{NamespaceUri}:{Name}")]
+ internal class XmlType
+ {
+ public XmlType(string namespaceUri, string name, IList<XmlType> typeArguments)
+ {
+ NamespaceUri = namespaceUri;
+ Name = name;
+ TypeArguments = typeArguments;
+ }
+
+ public string NamespaceUri { get; }
+
+ public string Name { get; }
+
+ public IList<XmlType> TypeArguments { get; private set; }
+ }
+
+ internal abstract class BaseNode : IXmlLineInfo, INode
+ {
+ protected BaseNode(IXmlNamespaceResolver namespaceResolver, int linenumber = -1, int lineposition = -1)
+ {
+ NamespaceResolver = namespaceResolver;
+ LineNumber = linenumber;
+ LinePosition = lineposition;
+ }
+
+ public IXmlNamespaceResolver NamespaceResolver { get; }
+
+ public abstract void Accept(IXamlNodeVisitor visitor, INode parentNode);
+
+ public INode Parent { get; set; }
+
+ public List<string> IgnorablePrefixes { get; set; }
+
+ public bool HasLineInfo()
+ {
+ return LineNumber >= 0 && LinePosition >= 0;
+ }
+
+ public int LineNumber { get; set; }
+
+ public int LinePosition { get; set; }
+ }
+
+ [DebuggerDisplay("{Value}")]
+ internal class ValueNode : BaseNode, IValueNode
+ {
+ public ValueNode(object value, IXmlNamespaceResolver namespaceResolver, int linenumber = -1, int lineposition = -1)
+ : base(namespaceResolver, linenumber, lineposition)
+ {
+ Value = value;
+ }
+
+ public object Value { get; set; }
+
+ public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
+ {
+ visitor.Visit(this, parentNode);
+ }
+ }
+
+ [DebuggerDisplay("{MarkupString}")]
+ internal class MarkupNode : BaseNode, IValueNode
+ {
+ public MarkupNode(string markupString, IXmlNamespaceResolver namespaceResolver, int linenumber = -1,
+ int lineposition = -1)
+ : base(namespaceResolver, linenumber, lineposition)
+ {
+ MarkupString = markupString;
+ }
+
+ public string MarkupString { get; }
+
+ public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
+ {
+ visitor.Visit(this, parentNode);
+ }
+ }
+
+ internal class ElementNode : BaseNode, IValueNode, IElementNode
+ {
+ public ElementNode(XmlType type, string namespaceURI, IXmlNamespaceResolver namespaceResolver, int linenumber = -1,
+ int lineposition = -1)
+ : base(namespaceResolver, linenumber, lineposition)
+ {
+ Properties = new Dictionary<XmlName, INode>();
+ SkipProperties = new List<XmlName>();
+ CollectionItems = new List<INode>();
+ XmlType = type;
+ NamespaceURI = namespaceURI;
+ }
+
+ public Dictionary<XmlName, INode> Properties { get; }
+
+ public List<XmlName> SkipProperties { get; }
+
+ public List<INode> CollectionItems { get; }
+
+ public XmlType XmlType { get; }
+
+ public string NamespaceURI { get; }
+
+ public INameScope Namescope { get; set; }
+
+ public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
+ {
+ if (!visitor.VisitChildrenFirst)
+ visitor.Visit(this, parentNode);
+ if ((!visitor.StopOnDataTemplate || !IsDataTemplate(this, parentNode)) &&
+ (!visitor.StopOnResourceDictionary || !IsResourceDictionary(this, parentNode)))
+ {
+ foreach (var node in Properties.Values.ToList())
+ node.Accept(visitor, this);
+ foreach (var node in CollectionItems)
+ node.Accept(visitor, this);
+ }
+ if (visitor.VisitChildrenFirst)
+ visitor.Visit(this, parentNode);
+ }
+
+ static bool IsDataTemplate(INode node, INode parentNode)
+ {
+ var parentElement = parentNode as IElementNode;
+ INode createContent;
+ if (parentElement != null && parentElement.Properties.TryGetValue(XmlName._CreateContent, out createContent) &&
+ createContent == node)
+ return true;
+ return false;
+ }
+
+ static bool IsResourceDictionary(INode node, INode parentNode)
+ {
+ var enode = node as ElementNode;
+ return enode.XmlType.Name == "ResourceDictionary";
+ }
+ }
+
+ internal abstract class RootNode : ElementNode
+ {
+ protected RootNode(XmlType xmlType) : base(xmlType, xmlType.NamespaceUri, null)
+ {
+ }
+
+ public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
+ {
+ if (!visitor.VisitChildrenFirst)
+ visitor.Visit(this, parentNode);
+ foreach (var node in Properties.Values.ToList())
+ node.Accept(visitor, this);
+ foreach (var node in CollectionItems)
+ node.Accept(visitor, this);
+ if (visitor.VisitChildrenFirst)
+ visitor.Visit(this, parentNode);
+ }
+ }
+
+ internal class ListNode : BaseNode, IListNode, IValueNode
+ {
+ public ListNode(IList<INode> nodes, IXmlNamespaceResolver namespaceResolver, int linenumber = -1,
+ int lineposition = -1) : base(namespaceResolver, linenumber, lineposition)
+ {
+ CollectionItems = nodes.ToList();
+ }
+
+ public XmlName XmlName { get; set; }
+
+ public List<INode> CollectionItems { get; set; }
+
+ public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
+ {
+ if (!visitor.VisitChildrenFirst)
+ visitor.Visit(this, parentNode);
+ foreach (var node in CollectionItems)
+ node.Accept(visitor, this);
+ if (visitor.VisitChildrenFirst)
+ visitor.Visit(this, parentNode);
+ }
+ }
+
+ internal static class INodeExtensions
+ {
+ public static bool SkipPrefix(this INode node, string prefix)
+ {
+ do
+ {
+ if (node.IgnorablePrefixes != null && node.IgnorablePrefixes.Contains(prefix))
+ return true;
+ node = node.Parent;
+ } while (node != null);
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/XamlNodeVisitor.cs b/Xamarin.Forms.Xaml/XamlNodeVisitor.cs
new file mode 100644
index 00000000..e0b1db32
--- /dev/null
+++ b/Xamarin.Forms.Xaml/XamlNodeVisitor.cs
@@ -0,0 +1,62 @@
+using System;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal interface IXamlNodeVisitor
+ {
+ bool VisitChildrenFirst { get; }
+
+ bool StopOnDataTemplate { get; }
+
+ bool StopOnResourceDictionary { get; }
+
+ void Visit(ValueNode node, INode parentNode);
+ void Visit(MarkupNode node, INode parentNode);
+ void Visit(ElementNode node, INode parentNode);
+ void Visit(RootNode node, INode parentNode);
+ void Visit(ListNode node, INode parentNode);
+ }
+
+ internal class XamlNodeVisitor : IXamlNodeVisitor
+ {
+ readonly Action<INode, INode> action;
+
+ public XamlNodeVisitor(Action<INode, INode> action, bool visitChildrenFirst = false, bool stopOnDataTemplate = false)
+ {
+ this.action = action;
+ VisitChildrenFirst = visitChildrenFirst;
+ StopOnDataTemplate = stopOnDataTemplate;
+ }
+
+ public bool VisitChildrenFirst { get; }
+
+ public bool StopOnDataTemplate { get; }
+
+ public bool StopOnResourceDictionary { get; private set; }
+
+ public void Visit(ValueNode node, INode parentNode)
+ {
+ action(node, parentNode);
+ }
+
+ public void Visit(MarkupNode node, INode parentNode)
+ {
+ action(node, parentNode);
+ }
+
+ public void Visit(ElementNode node, INode parentNode)
+ {
+ action(node, parentNode);
+ }
+
+ public void Visit(RootNode node, INode parentNode)
+ {
+ action(node, parentNode);
+ }
+
+ public void Visit(ListNode node, INode parentNode)
+ {
+ action(node, parentNode);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/XamlParser.cs b/Xamarin.Forms.Xaml/XamlParser.cs
new file mode 100644
index 00000000..730c1624
--- /dev/null
+++ b/Xamarin.Forms.Xaml/XamlParser.cs
@@ -0,0 +1,349 @@
+//
+// XamlParser.cs
+//
+// Author:
+// Stephane Delcroix <stephane@mi8.be>
+//
+// Copyright (c) 2013 Mobile Inception
+// Copyright (c) 2013-2014 Xamarin, Inc
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Xml;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal static class XamlParser
+ {
+ public static void ParseXaml(RootNode rootNode, XmlReader reader)
+ {
+ var attributes = ParseXamlAttributes(reader);
+ rootNode.Properties.AddRange(attributes);
+ ParseXamlElementFor(rootNode, reader);
+ }
+
+ static void ParseXamlElementFor(IElementNode node, XmlReader reader)
+ {
+ Debug.Assert(reader.NodeType == XmlNodeType.Element);
+
+ var elementName = reader.Name;
+ var isEmpty = reader.IsEmptyElement;
+
+ if (isEmpty)
+ return;
+
+ while (reader.Read())
+ {
+ switch (reader.NodeType)
+ {
+ case XmlNodeType.EndElement:
+ Debug.Assert(reader.Name == elementName); //make sure we close the right element
+ return;
+ case XmlNodeType.Element:
+ // 1. Property Element.
+ if (reader.Name.Contains("."))
+ {
+ XmlName name;
+ if (reader.Name.StartsWith(elementName + ".", StringComparison.Ordinal))
+ name = new XmlName(reader.NamespaceURI, reader.Name.Substring(elementName.Length + 1));
+ else //Attached DP
+ name = new XmlName(reader.NamespaceURI, reader.LocalName);
+
+ var prop = ReadNode(reader);
+ if (prop != null)
+ node.Properties.Add(name, prop);
+ }
+ // 2. Xaml2009 primitives, x:Arguments, ...
+ else if (reader.NamespaceURI == "http://schemas.microsoft.com/winfx/2009/xaml" && reader.LocalName == "Arguments")
+ {
+ var prop = ReadNode(reader);
+ if (prop != null)
+ node.Properties.Add(XmlName.xArguments, prop);
+ // 3. DataTemplate (should be handled by 4.)
+ }
+ else if (node.XmlType.NamespaceUri == "http://xamarin.com/schemas/2014/forms" &&
+ (node.XmlType.Name == "DataTemplate" || node.XmlType.Name == "ControlTemplate"))
+ {
+ var prop = ReadNode(reader, true);
+ if (prop != null)
+ node.Properties.Add(XmlName._CreateContent, prop);
+ // 4. Implicit content, implicit collection, or collection syntax. Add to CollectionItems, resolve case later.
+ }
+ else
+ {
+ var item = ReadNode(reader, true);
+ if (item != null)
+ node.CollectionItems.Add(item);
+ }
+ break;
+ case XmlNodeType.Whitespace:
+ break;
+ case XmlNodeType.Text:
+ node.CollectionItems.Add(new ValueNode(reader.Value.Trim(), (IXmlNamespaceResolver)reader));
+ break;
+ default:
+ Debug.WriteLine("Unhandled node {0} {1} {2}", reader.NodeType, reader.Name, reader.Value);
+ break;
+ }
+ }
+ }
+
+ static INode ReadNode(XmlReader reader, bool nested = false)
+ {
+ var skipFirstRead = nested;
+ Debug.Assert(reader.NodeType == XmlNodeType.Element);
+ var name = reader.Name;
+ List<INode> nodes = new List<INode>();
+ INode node = null;
+
+ while (skipFirstRead || reader.Read())
+ {
+ skipFirstRead = false;
+
+ switch (reader.NodeType)
+ {
+ case XmlNodeType.EndElement:
+ Debug.Assert(reader.Name == name);
+ if (nodes.Count == 0) //Empty element
+ return null;
+ if (nodes.Count == 1)
+ return nodes[0];
+ return new ListNode(nodes, (IXmlNamespaceResolver)reader, ((IXmlLineInfo)reader).LineNumber,
+ ((IXmlLineInfo)reader).LinePosition);
+ case XmlNodeType.Element:
+ var isEmpty = reader.IsEmptyElement && reader.Name == name;
+ var elementName = reader.Name;
+ var elementNsUri = reader.NamespaceURI;
+ var elementXmlInfo = (IXmlLineInfo)reader;
+
+ var attributes = ParseXamlAttributes(reader);
+
+ IList<XmlType> typeArguments = null;
+ if (attributes.Any(kvp => kvp.Key == XmlName.xTypeArguments))
+ {
+ typeArguments =
+ ((ValueNode)attributes.First(kvp => kvp.Key == XmlName.xTypeArguments).Value).Value as IList<XmlType>;
+ }
+
+ node = new ElementNode(new XmlType(elementNsUri, elementName, typeArguments), elementNsUri,
+ reader as IXmlNamespaceResolver, elementXmlInfo.LineNumber, elementXmlInfo.LinePosition);
+ ((IElementNode)node).Properties.AddRange(attributes);
+
+ ParseXamlElementFor((IElementNode)node, reader);
+ nodes.Add(node);
+ if (isEmpty || nested)
+ return node;
+ break;
+ case XmlNodeType.Text:
+ node = new ValueNode(reader.Value.Trim(), (IXmlNamespaceResolver)reader, ((IXmlLineInfo)reader).LineNumber,
+ ((IXmlLineInfo)reader).LinePosition);
+ nodes.Add(node);
+ break;
+ case XmlNodeType.Whitespace:
+ break;
+ default:
+ Debug.WriteLine("Unhandled node {0} {1} {2}", reader.NodeType, reader.Name, reader.Value);
+ break;
+ }
+ }
+ throw new XamlParseException("Closing PropertyElement expected", (IXmlLineInfo)reader);
+ }
+
+ static IList<KeyValuePair<XmlName, INode>> ParseXamlAttributes(XmlReader reader)
+ {
+ Debug.Assert(reader.NodeType == XmlNodeType.Element);
+ var attributes = new List<KeyValuePair<XmlName, INode>>();
+ for (var i = 0; i < reader.AttributeCount; i++)
+ {
+ reader.MoveToAttribute(i);
+
+ //skip xmlns
+ if (reader.NamespaceURI == "http://www.w3.org/2000/xmlns/")
+ continue;
+
+ var propertyName = new XmlName(reader.NamespaceURI, reader.LocalName);
+
+ object value = reader.Value;
+
+ if (reader.NamespaceURI == "http://schemas.microsoft.com/winfx/2006/xaml")
+ {
+ switch (reader.Name)
+ {
+ case "x:Key":
+ propertyName = XmlName.xKey;
+ break;
+ case "x:Name":
+ propertyName = XmlName.xName;
+ break;
+ case "x:Class":
+ continue;
+ default:
+ Debug.WriteLine("Unhandled {0}", reader.Name);
+ continue;
+ }
+ }
+
+ if (reader.NamespaceURI == "http://schemas.microsoft.com/winfx/2009/xaml")
+ {
+ switch (reader.Name)
+ {
+ case "x:Key":
+ propertyName = XmlName.xKey;
+ break;
+ case "x:Name":
+ propertyName = XmlName.xName;
+ break;
+ case "x:TypeArguments":
+ propertyName = XmlName.xTypeArguments;
+ value = TypeArgumentsParser.ParseExpression((string)value, (IXmlNamespaceResolver)reader, (IXmlLineInfo)reader);
+ break;
+ case "x:Class":
+ continue;
+ case "x:FactoryMethod":
+ propertyName = XmlName.xFactoryMethod;
+ break;
+ default:
+ Debug.WriteLine("Unhandled {0}", reader.Name);
+ continue;
+ }
+ }
+
+ var propertyNode = GetValueNode(value, reader);
+ attributes.Add(new KeyValuePair<XmlName, INode>(propertyName, propertyNode));
+ }
+ reader.MoveToElement();
+ return attributes;
+ }
+
+ static IValueNode GetValueNode(object value, XmlReader reader)
+ {
+ var valueString = value as string;
+ if (valueString != null && valueString.Trim().StartsWith("{}", StringComparison.Ordinal))
+ {
+ return new ValueNode(valueString.Substring(2), (IXmlNamespaceResolver)reader, ((IXmlLineInfo)reader).LineNumber,
+ ((IXmlLineInfo)reader).LinePosition);
+ }
+ if (valueString != null && valueString.Trim().StartsWith("{", StringComparison.Ordinal))
+ {
+ return new MarkupNode(valueString.Trim(), reader as IXmlNamespaceResolver, ((IXmlLineInfo)reader).LineNumber,
+ ((IXmlLineInfo)reader).LinePosition);
+ }
+ return new ValueNode(value, (IXmlNamespaceResolver)reader, ((IXmlLineInfo)reader).LineNumber,
+ ((IXmlLineInfo)reader).LinePosition);
+ }
+
+ public static Type GetElementType(XmlType xmlType, IXmlLineInfo xmlInfo, Assembly currentAssembly,
+ out XamlParseException exception)
+ {
+ var namespaceURI = xmlType.NamespaceUri;
+ var elementName = xmlType.Name;
+ var typeArguments = xmlType.TypeArguments;
+ exception = null;
+
+ List<Tuple<string, Assembly>> lookupAssemblies = new List<Tuple<string, Assembly>>();
+ List<string> lookupNames = new List<string>();
+
+ if (!XmlnsHelper.IsCustom(namespaceURI))
+ {
+ lookupAssemblies.Add(new Tuple<string, Assembly>("Xamarin.Forms", typeof (View).GetTypeInfo().Assembly));
+ lookupAssemblies.Add(new Tuple<string, Assembly>("Xamarin.Forms.Xaml", typeof (XamlLoader).GetTypeInfo().Assembly));
+ }
+ else if (namespaceURI == "http://schemas.microsoft.com/winfx/2009/xaml" ||
+ namespaceURI == "http://schemas.microsoft.com/winfx/2006/xaml")
+ {
+ lookupAssemblies.Add(new Tuple<string, Assembly>("Xamarin.Forms.Xaml", typeof (XamlLoader).GetTypeInfo().Assembly));
+ lookupAssemblies.Add(new Tuple<string, Assembly>("System", typeof (object).GetTypeInfo().Assembly));
+ lookupAssemblies.Add(new Tuple<string, Assembly>("System", typeof (Uri).GetTypeInfo().Assembly)); //System.dll
+ }
+ else
+ {
+ string ns;
+ string typename;
+ string asmstring;
+ Assembly asm;
+
+ XmlnsHelper.ParseXmlns(namespaceURI, out typename, out ns, out asmstring);
+ asm = asmstring == null ? currentAssembly : Assembly.Load(new AssemblyName(asmstring));
+ lookupAssemblies.Add(new Tuple<string, Assembly>(ns, asm));
+ }
+
+ lookupNames.Add(elementName);
+ if (namespaceURI == "http://schemas.microsoft.com/winfx/2009/xaml")
+ lookupNames.Add(elementName + "Extension");
+ for (var i = 0; i < lookupNames.Count; i++)
+ {
+ var name = lookupNames[i];
+ if (name.Contains(":"))
+ name = name.Substring(name.LastIndexOf(':') + 1);
+ if (typeArguments != null)
+ name += "`" + typeArguments.Count; //this will return an open generic Type
+ lookupNames[i] = name;
+ }
+
+ Type type = null;
+ foreach (var asm in lookupAssemblies)
+ {
+ if (type != null)
+ break;
+ foreach (var name in lookupNames)
+ {
+ if (type != null)
+ break;
+ type = asm.Item2.GetType(asm.Item1 + "." + name);
+ }
+ }
+
+ if (type != null && typeArguments != null)
+ {
+ XamlParseException innerexception = null;
+ var args = typeArguments.Select(delegate(XmlType xmltype)
+ {
+ XamlParseException xpe;
+ var t = GetElementType(xmltype, xmlInfo, currentAssembly, out xpe);
+ if (xpe != null)
+ {
+ innerexception = xpe;
+ return null;
+ }
+ return t;
+ }).ToArray();
+ if (innerexception != null)
+ {
+ exception = innerexception;
+ return null;
+ }
+ type = type.MakeGenericType(args);
+ }
+
+ if (type == null)
+ {
+ exception = new XamlParseException(string.Format("Type {0} not found in xmlns {1}", elementName, namespaceURI),
+ xmlInfo);
+ return null;
+ }
+
+ return type;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/XamlServiceProvider.cs b/Xamarin.Forms.Xaml/XamlServiceProvider.cs
new file mode 100644
index 00000000..8998e6f5
--- /dev/null
+++ b/Xamarin.Forms.Xaml/XamlServiceProvider.cs
@@ -0,0 +1,309 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Xml;
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms.Xaml.Internals
+{
+ public class XamlServiceProvider : IServiceProvider
+ {
+ readonly Dictionary<Type, object> services = new Dictionary<Type, object>();
+
+ internal XamlServiceProvider(INode node, HydratationContext context)
+ {
+ object targetObject;
+ if (node != null && node.Parent != null && context.Values.TryGetValue(node.Parent, out targetObject))
+ IProvideValueTarget = new XamlValueTargetProvider(targetObject, node, context, null);
+ if (context != null)
+ IRootObjectProvider = new XamlRootObjectProvider(context.RootElement);
+ if (node != null)
+ {
+ IXamlTypeResolver = new XamlTypeResolver(node.NamespaceResolver, XamlParser.GetElementType,
+ context.RootElement.GetType().GetTypeInfo().Assembly);
+
+ var enode = node;
+ while (enode != null && !(enode is IElementNode))
+ enode = enode.Parent;
+ if (enode != null)
+ INameScopeProvider = new NameScopeProvider { NameScope = (enode as IElementNode).Namescope };
+ }
+
+ var xmlLineInfo = node as IXmlLineInfo;
+ if (xmlLineInfo != null)
+ IXmlLineInfoProvider = new XmlLineInfoProvider(xmlLineInfo);
+
+ IValueConverterProvider = new ValueConverterProvider();
+ }
+
+ public XamlServiceProvider()
+ {
+ IValueConverterProvider = new ValueConverterProvider();
+ }
+
+ internal IProvideValueTarget IProvideValueTarget
+ {
+ get { return (IProvideValueTarget)GetService(typeof (IProvideValueTarget)); }
+ set { services[typeof (IProvideValueTarget)] = value; }
+ }
+
+ internal IXamlTypeResolver IXamlTypeResolver
+ {
+ get { return (IXamlTypeResolver)GetService(typeof (IXamlTypeResolver)); }
+ set { services[typeof (IXamlTypeResolver)] = value; }
+ }
+
+ internal IRootObjectProvider IRootObjectProvider
+ {
+ get { return (IRootObjectProvider)GetService(typeof (IRootObjectProvider)); }
+ set { services[typeof (IRootObjectProvider)] = value; }
+ }
+
+ internal IXmlLineInfoProvider IXmlLineInfoProvider
+ {
+ get { return (IXmlLineInfoProvider)GetService(typeof (IXmlLineInfoProvider)); }
+ set { services[typeof (IXmlLineInfoProvider)] = value; }
+ }
+
+ internal INameScopeProvider INameScopeProvider
+ {
+ get { return (INameScopeProvider)GetService(typeof (INameScopeProvider)); }
+ set { services[typeof (INameScopeProvider)] = value; }
+ }
+
+ internal IValueConverterProvider IValueConverterProvider
+ {
+ get { return (IValueConverterProvider)GetService(typeof (IValueConverterProvider)); }
+ set { services[typeof (IValueConverterProvider)] = value; }
+ }
+
+ public object GetService(Type serviceType)
+ {
+ object service;
+ return services.TryGetValue(serviceType, out service) ? service : null;
+ }
+
+ public void Add(Type type, object service)
+ {
+ services.Add(type, service);
+ }
+ }
+
+ internal class XamlValueTargetProvider : IProvideParentValues, IProvideValueTarget
+ {
+ public XamlValueTargetProvider(object targetObject, INode node, HydratationContext context, object targetProperty)
+ {
+ Context = context;
+ Node = node;
+ TargetObject = targetObject;
+ TargetProperty = targetProperty;
+ }
+
+ INode Node { get; }
+
+ HydratationContext Context { get; }
+
+ public object TargetObject { get; }
+
+ public object TargetProperty
+ {
+ get { throw new NotImplementedException(); }
+ private set { }
+ }
+
+ IEnumerable<object> IProvideParentValues.ParentObjects
+ {
+ get
+ {
+ if (Node == null || Context == null)
+ yield break;
+ var n = Node;
+ object obj = null;
+ var context = Context;
+ while (n.Parent != null && context != null)
+ {
+ if (n.Parent is IElementNode)
+ {
+ if (context.Values.TryGetValue(n.Parent, out obj))
+ yield return obj;
+ else
+ {
+ context = context.ParentContext;
+ continue;
+ }
+ }
+ n = n.Parent;
+ }
+ }
+ }
+ }
+
+ public class SimpleValueTargetProvider : IProvideParentValues, IProvideValueTarget
+ {
+ readonly object[] objectAndParents;
+
+ public SimpleValueTargetProvider(object[] objectAndParents)
+ {
+ if (objectAndParents == null)
+ throw new ArgumentNullException("objectAndParents");
+ if (objectAndParents.Length == 0)
+ throw new ArgumentException();
+
+ this.objectAndParents = objectAndParents;
+ }
+
+ IEnumerable<object> IProvideParentValues.ParentObjects
+ {
+ get { return objectAndParents; }
+ }
+
+ object IProvideValueTarget.TargetObject
+ {
+ get { return objectAndParents[0]; }
+ }
+
+ object IProvideValueTarget.TargetProperty
+ {
+ get { throw new NotImplementedException(); }
+ }
+ }
+
+ public class XamlTypeResolver : IXamlTypeResolver
+ {
+ readonly Assembly currentAssembly;
+ readonly GetTypeFromXmlName getTypeFromXmlName;
+ readonly IXmlNamespaceResolver namespaceResolver;
+
+ public XamlTypeResolver(IXmlNamespaceResolver namespaceResolver, Assembly currentAssembly)
+ : this(namespaceResolver, XamlParser.GetElementType, currentAssembly)
+ {
+ }
+
+ internal XamlTypeResolver(IXmlNamespaceResolver namespaceResolver, GetTypeFromXmlName getTypeFromXmlName,
+ Assembly currentAssembly)
+ {
+ this.currentAssembly = currentAssembly;
+ if (namespaceResolver == null)
+ throw new ArgumentNullException();
+ if (getTypeFromXmlName == null)
+ throw new ArgumentNullException();
+
+ this.namespaceResolver = namespaceResolver;
+ this.getTypeFromXmlName = getTypeFromXmlName;
+ }
+
+ Type IXamlTypeResolver.Resolve(string qualifiedTypeName, IServiceProvider serviceProvider)
+ {
+ XamlParseException e;
+ var type = Resolve(qualifiedTypeName, serviceProvider, out e);
+ if (e != null)
+ throw e;
+ return type;
+ }
+
+ bool IXamlTypeResolver.TryResolve(string qualifiedTypeName, out Type type)
+ {
+ XamlParseException exception;
+ type = Resolve(qualifiedTypeName, null, out exception);
+ return exception == null;
+ }
+
+ Type Resolve(string qualifiedTypeName, IServiceProvider serviceProvider, out XamlParseException exception)
+ {
+ exception = null;
+ var split = qualifiedTypeName.Split(':');
+ if (split.Length > 2)
+ return null;
+
+ string prefix, name;
+ if (split.Length == 2)
+ {
+ prefix = split[0];
+ name = split[1];
+ }
+ else
+ {
+ prefix = "";
+ name = split[0];
+ }
+
+ IXmlLineInfo xmlLineInfo = null;
+ if (serviceProvider != null)
+ {
+ var lineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
+ if (lineInfoProvider != null)
+ xmlLineInfo = lineInfoProvider.XmlLineInfo;
+ }
+
+ var namespaceuri = string.IsNullOrEmpty(prefix) ? "" : namespaceResolver.LookupNamespace(prefix);
+ if (namespaceuri == null)
+ {
+ exception = new XamlParseException(string.Format("No xmlns declaration for prefix \"{0}\"", prefix), xmlLineInfo);
+ return null;
+ }
+
+ return getTypeFromXmlName(new XmlType(namespaceuri, name, null), xmlLineInfo, currentAssembly, out exception);
+ }
+
+ internal delegate Type GetTypeFromXmlName(
+ XmlType xmlType, IXmlLineInfo xmlInfo, Assembly currentAssembly, out XamlParseException exception);
+ }
+
+ internal class XamlRootObjectProvider : IRootObjectProvider
+ {
+ public XamlRootObjectProvider(object rootObject)
+ {
+ RootObject = rootObject;
+ }
+
+ public object RootObject { get; }
+ }
+
+ public class XmlLineInfoProvider : IXmlLineInfoProvider
+ {
+ public XmlLineInfoProvider(IXmlLineInfo xmlLineInfo)
+ {
+ XmlLineInfo = xmlLineInfo;
+ }
+
+ public IXmlLineInfo XmlLineInfo { get; }
+ }
+
+ internal interface INameScopeProvider
+ {
+ INameScope NameScope { get; }
+ }
+
+ public class NameScopeProvider : INameScopeProvider
+ {
+ public INameScope NameScope { get; set; }
+ }
+
+ public class XmlNamespaceResolver : IXmlNamespaceResolver
+ {
+ readonly Dictionary<string, string> namespaces = new Dictionary<string, string>();
+
+ public IDictionary<string, string> GetNamespacesInScope(XmlNamespaceScope scope)
+ {
+ throw new NotImplementedException();
+ }
+
+ public string LookupNamespace(string prefix)
+ {
+ string result;
+ if (namespaces.TryGetValue(prefix, out result))
+ return result;
+ return null;
+ }
+
+ public string LookupPrefix(string namespaceName)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Add(string prefix, string ns)
+ {
+ namespaces.Add(prefix, ns);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/XmlName.cs b/Xamarin.Forms.Xaml/XmlName.cs
new file mode 100644
index 00000000..e22a162d
--- /dev/null
+++ b/Xamarin.Forms.Xaml/XmlName.cs
@@ -0,0 +1,58 @@
+using System.Diagnostics;
+
+namespace Xamarin.Forms.Xaml
+{
+ [DebuggerDisplay("{NamespaceURI}:{LocalName}")]
+ internal struct XmlName
+ {
+ public static readonly XmlName _CreateContent = new XmlName("_", "CreateContent");
+ public static readonly XmlName xKey = new XmlName("x", "Key");
+ public static readonly XmlName xName = new XmlName("x", "Name");
+ public static readonly XmlName xTypeArguments = new XmlName("x", "TypeArguments");
+ public static readonly XmlName xArguments = new XmlName("x", "Arguments");
+ public static readonly XmlName xFactoryMethod = new XmlName("x", "xFactoryMethod");
+
+ public string NamespaceURI { get; }
+
+ public string LocalName { get; }
+
+ public XmlName(string namespaceUri, string localName)
+ {
+ NamespaceURI = namespaceUri;
+ LocalName = localName;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ return false;
+ if (obj.GetType() != typeof (XmlName))
+ return false;
+ var other = (XmlName)obj;
+ return NamespaceURI == other.NamespaceURI && LocalName == other.LocalName;
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hashCode = 0;
+ if (NamespaceURI != null)
+ hashCode = NamespaceURI.GetHashCode();
+ if (LocalName != null)
+ hashCode = (hashCode * 397) ^ LocalName.GetHashCode();
+ return hashCode;
+ }
+ }
+
+ public static bool operator ==(XmlName x1, XmlName x2)
+ {
+ return x1.NamespaceURI == x2.NamespaceURI && x1.LocalName == x2.LocalName;
+ }
+
+ public static bool operator !=(XmlName x1, XmlName x2)
+ {
+ return !(x1 == x2);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/XmlnsHelper.cs b/Xamarin.Forms.Xaml/XmlnsHelper.cs
new file mode 100644
index 00000000..778d2947
--- /dev/null
+++ b/Xamarin.Forms.Xaml/XmlnsHelper.cs
@@ -0,0 +1,56 @@
+using System;
+
+namespace Xamarin.Forms.Xaml
+{
+ internal static class XmlnsHelper
+ {
+ public static bool IsCustom(string ns)
+ {
+ switch (ns)
+ {
+ case "":
+ case "http://xamarin.com/schemas/2014/forms":
+ return false;
+ }
+ return true;
+ }
+
+ public static string ParseNamespaceFromXmlns(string xmlns)
+ {
+ string typeName;
+ string ns;
+ string asm;
+
+ ParseXmlns(xmlns, out typeName, out ns, out asm);
+
+ return ns;
+ }
+
+ public static void ParseXmlns(string xmlns, out string typeName, out string ns, out string asm)
+ {
+ typeName = ns = asm = null;
+
+ foreach (var decl in xmlns.Split(';'))
+ {
+ if (decl.StartsWith("clr-namespace:", StringComparison.Ordinal))
+ {
+ ns = decl.Substring(14, decl.Length - 14);
+ continue;
+ }
+ if (decl.StartsWith("assembly=", StringComparison.Ordinal))
+ {
+ asm = decl.Substring(9, decl.Length - 9);
+ continue;
+ }
+ var nsind = decl.LastIndexOf(".", StringComparison.Ordinal);
+ if (nsind > 0)
+ {
+ ns = decl.Substring(0, nsind);
+ typeName = decl.Substring(nsind + 1, decl.Length - nsind - 1);
+ }
+ else
+ typeName = decl;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.iOS.UITests/Device.cs b/Xamarin.Forms.iOS.UITests/Device.cs
new file mode 100644
index 00000000..32b2cf88
--- /dev/null
+++ b/Xamarin.Forms.iOS.UITests/Device.cs
@@ -0,0 +1,21 @@
+namespace Xamarin.Forms.UITests
+{
+
+ public enum DeviceType
+ {
+ Phone,
+ Tablet
+ }
+
+ public class Device
+ {
+ public DeviceType Type { get; set; }
+ public string IP { get; set; }
+
+ public Device (DeviceType type, string ip)
+ {
+ Type = type;
+ IP = ip;
+ }
+ }
+}
diff --git a/Xamarin.Forms.iOS.UITests/Legacy-BaseTestFixture.cs b/Xamarin.Forms.iOS.UITests/Legacy-BaseTestFixture.cs
new file mode 100644
index 00000000..07cbe93d
--- /dev/null
+++ b/Xamarin.Forms.iOS.UITests/Legacy-BaseTestFixture.cs
@@ -0,0 +1,113 @@
+using System;
+using Xamarin.UITest;
+using Xamarin.UITest.iOS;
+using Xamarin.UITest.Queries;
+using NUnit.Framework;
+using System.Threading;
+
+namespace Xamarin.Forms.UITests
+{
+
+ public class BaseTestFixture
+ {
+ string idiomEnvVar;
+ string IPEnvVar;
+
+ public static iOSApp App { get; private set; }
+ public Device Device { get; set; }
+
+ public BaseTestFixture ()
+ {
+ idiomEnvVar = Environment.GetEnvironmentVariable ("DEVICE_IDIOM");
+ IPEnvVar = Environment.GetEnvironmentVariable ("DEVICE_IP");
+
+ Console.WriteLine (string.Format ("****** Connecting to {0} with IP: {1} ********", idiomEnvVar, IPEnvVar));
+
+ Device = SetupDevice (idiomEnvVar, IPEnvVar);
+ }
+
+ [SetUp]
+ public void Setup ()
+ {
+
+ if (string.IsNullOrEmpty (idiomEnvVar) &&
+ string.IsNullOrEmpty (IPEnvVar)) {
+ // IDE Configuration
+ // Use your own device information
+ App = ConfigureApp
+ .iOS
+ .Debug ()
+// .DeviceIp ("10.0.1.159") // iPod iOS 7
+ // .DeviceIp ("10.0.1.163") // iPhone iOS 7
+ // .DeviceIp ("10.0.3.146") // iPod iOS 6
+ .InstalledApp ("com.xamarin.quickui.controlgallery")
+ .StartApp();
+ } else {
+ // CI Configuration
+ App = ConfigureApp
+ .iOS
+ .DeviceIp (Device.IP)
+ .InstalledApp ("com.xamarin.quickui.controlgallery")
+ .StartApp();
+ }
+
+ FixtureSetup ();
+ }
+
+ protected virtual void FixtureSetup ()
+ {
+ App.SetOrientationPortrait ();
+ App.Screenshot ("Begin test");
+ }
+
+ Device SetupDevice (string idiomEnvVar, string IPEnvVar)
+ {
+ Device device;
+
+ if (idiomEnvVar == "PHONE") {
+
+ // default phone
+ device = new Device (DeviceType.Phone, "10.0.3.253");
+
+ if (!string.IsNullOrEmpty (IPEnvVar))
+ device.IP = IPEnvVar;
+
+ } else if (idiomEnvVar == "TABLET") {
+
+ // default tablet
+ device = new Device (DeviceType.Tablet, "10.0.1.159");
+
+ if (!string.IsNullOrEmpty (IPEnvVar))
+ device.IP = IPEnvVar;
+
+ } else {
+
+ // default phone
+ device = new Device (DeviceType.Phone, "10.0.3.253");
+
+ }
+
+ return device;
+ }
+ }
+
+ public static class PlatformStrings
+ {
+ public static string Button = "Button";
+ public static string Cell = "TableViewCell";
+ public static string Entry = "TextField";
+ public static string HomePageTitle = "iOS Controls";
+ public static string Label = "Label";
+ public static string MapPin = "view:'MKPinAnnotationView'";
+ public static string Placeholder = "placeholder";
+ public static string Text = "text";
+ }
+
+ public static class PlatformValues
+ {
+ public static int BoxViewScreenNumber = 3;
+ public static int KeyboardDismissY = 200;
+ public static int OffsetForScrollView = 5;
+ }
+}
+
diff --git a/Xamarin.Forms.iOS.UITests/Legacy-PlatformHelpers.cs b/Xamarin.Forms.iOS.UITests/Legacy-PlatformHelpers.cs
new file mode 100644
index 00000000..410f50ef
--- /dev/null
+++ b/Xamarin.Forms.iOS.UITests/Legacy-PlatformHelpers.cs
@@ -0,0 +1,135 @@
+using System;
+using Xamarin.UITest;
+using Xamarin.UITest.iOS;
+using Xamarin.UITest.Queries;
+using NUnit.Framework;
+using System.Threading;
+
+namespace Xamarin.Forms.UITests
+{
+
+ public static class PlatformHelpers
+ {
+
+ public static string GetTextForQuery (this IApp app, Func<AppQuery, AppQuery> query)
+ {
+ AppResult[] elements = app.Query (query);
+ if (elements.Length > 1) {
+ // Test cloud doesn't support Assert.Fail
+ Assert.False (true, "Query returned more than one result");
+ }
+ return elements [0].Label;
+ }
+
+ public static bool ScrollDownForElement (this IApp app, Func<AppQuery, AppQuery> query, int scrollNumberLimit)
+ {
+ var desiredElement = app.Query (query);
+ var tabBarElement = app.Query (q => q.Raw ("TabBar"));
+ // Check for elements under a TabbedBar
+ // If the element exists and is under the tabbed bar scroll down once
+ if (
+ tabBarElement.Length > 0 &&
+ desiredElement.Length > 0 &&
+ (Math.Abs(desiredElement[0].Rect.Y - tabBarElement[0].Rect.Y) <= 75)
+ )
+ {
+ app.ScrollDown ();
+ return true;
+ }
+
+ // Check if element exists before scrolling
+ if (app.Query (query).Length > 0)
+ return true;
+
+ int scrollNumber = 0;
+ while (app.Query (query).Length == 0) {
+ app.ScrollDown ();
+ scrollNumber++;
+ if (scrollNumber > scrollNumberLimit)
+ return false;
+ }
+
+ // Avoid hidden elements under a tabbed controller
+ app.ScrollDown ();
+ Thread.Sleep (1000);
+
+ return true;
+ }
+
+ public static bool ScrollUpForElement (this IApp app, Func<AppQuery, AppQuery> query, int scrollNumberLimit)
+ {
+ int scrollNumber = 0;
+ while (app.Query (query).Length == 0) {
+ app.ScrollUp ();
+ scrollNumber++;
+ if (scrollNumber > scrollNumberLimit)
+ return false;
+ }
+
+ app.ScrollUp ();
+
+ return true;
+ }
+
+ public static bool DragFromToForElement (this iOSApp app, int scrollNumberLimit, Func<AppQuery, AppQuery> query, float xStart, float yStart, float xEnd, float yEnd)
+ {
+ int numberOfScrolls = 0;
+ // Element exists
+ if (app.Query (query).Length > 0)
+ return true;
+
+ while (app.Query (query).Length == 0) {
+ DragFromTo (app, xStart, yStart, xEnd, yEnd);
+ if (numberOfScrolls > scrollNumberLimit) {
+ return false;
+ }
+ numberOfScrolls++;
+ }
+ // Element found
+ return true;
+ }
+
+ public static void SwipeBackNavigation (this iOSApp app)
+ {
+ app.PanCoordinates (0, 125, 75, 125, TimeSpan.FromSeconds (5));
+ }
+
+ public static void DragFromTo (this iOSApp app, float xStart, float yStart, float xEnd, float yEnd, Speed speed = Speed.Fast)
+ {
+ if (speed == Speed.Slow)
+ app.PanCoordinates (xStart, yStart, xEnd, yEnd, TimeSpan.FromMilliseconds (3000));
+ else
+ app.PanCoordinates (xStart, yStart, xEnd, yEnd, TimeSpan.FromMilliseconds (1000));
+
+ }
+
+ public static void KeyboardIsPresent (this iOSApp app)
+ {
+ // TODO : Add keyboard detection
+ // app.WaitForElement (q => q.Raw ("KBKeyplaneView"));
+ Assert.Inconclusive ("Keyboard should be shown");
+ }
+
+ public static void KeyboardIsDismissed (this iOSApp app)
+ {
+ // TODO : Add keyboard detection
+ // app.WaitForNoElement (q => q.Raw ("KBKeyplaneView"));
+ Assert.Inconclusive ("Keyboard should be dismissed");
+ }
+
+ public static int IndexForElementWithText (this iOSApp app, Func<AppQuery, AppQuery> query, string text)
+ {
+ var elements = app.Query (query);
+ int index = 0;
+ for (int i = 0; i < elements.Length; i++) {
+ string labelText = elements[i].Label;
+ if (labelText == (text)) {
+ index = i;
+ break;
+ }
+ index++;
+ }
+ return index == elements.Length ? -1 : index;
+ }
+ }
+}
diff --git a/Xamarin.Forms.iOS.UITests/Makefile b/Xamarin.Forms.iOS.UITests/Makefile
new file mode 100644
index 00000000..b94c6547
--- /dev/null
+++ b/Xamarin.Forms.iOS.UITests/Makefile
@@ -0,0 +1,15 @@
+console:
+ DEVICE_ENDPOINT=http://10.0.3.253:37265 BUNDLE_ID=com.xamarin.quickui.controlgallery calabash-ios console
+
+run:
+ mono ../packages/NUnit.Runners.2.6.3/tools/nunit-console.exe bin/Debug/Xamarin.Forms.iOS.UITests.dll
+
+run-ios-phone:
+ DEVICE_IDIOM=PHONE DEVICE_IP=192.168.1.145 DEVICE_ID=795a532d7fb4569fb728a79784eb73bbbca995ba mono ../packages/NUnit.Runners.2.6.3/tools/nunit-console-x86.exe -result=iphone-results.xml bin/Debug/Xamarin.Forms.iOS.UITests.dll
+
+run-ios:
+ DEVICE_IDIOM=PHONE mono ../packages/NUnit.Runners.2.6.3/tools/nunit-console-x86.exe -result=iphone-results.xml bin/Debug/Xamarin.Forms.iOS.UITests.dll --include "CITest";
+ DEVICE_IDIOM=TABLET mono ../packages/NUnit.Runners.2.6.3/tools/nunit-console-x86.exe -result=ipad-results.xml bin/Debug/Xamarin.Forms.iOS.UITests.dll --include "CITest"
+
+clean:
+ rm -rf screenshot_* test_servers/ iphone-results.xml ipad-results.xml
diff --git a/Xamarin.Forms.iOS.UITests/PlatformQueries.cs b/Xamarin.Forms.iOS.UITests/PlatformQueries.cs
new file mode 100644
index 00000000..761fa004
--- /dev/null
+++ b/Xamarin.Forms.iOS.UITests/PlatformQueries.cs
@@ -0,0 +1,118 @@
+using System;
+using Xamarin.UITest;
+using Xamarin.UITest.iOS;
+using Xamarin.UITest.Queries;
+using NUnit.Framework;
+using System.Threading;
+
+namespace Xamarin.Forms.UITests
+{
+ public class AndroidUiTestType
+ {
+ public AndroidUiTestType ()
+ {
+
+ }
+ }
+
+ public static class PlatformQueries
+ {
+ public static Func<AppQuery, AppQuery> AbsoluteGalleryBackground = q => q.Raw ("view:'Xamarin_Forms_Platform_iOS_BoxRenderer' parent view index:0");
+ public static Func<AppQuery, AppQuery> ActivityIndicators = q => q.Raw ("ActivityIndicatorView");
+ public static Func<AppQuery, AppQuery> Back = q => q.Raw ("view:'UINavigationItemButtonView'");
+ public static Func<AppQuery, AppQuery> BoxRendererQuery = q => q.Raw ("view:'Xamarin_Forms_Platform_iOS_BoxRenderer'");
+ public static Func<AppQuery, AppQuery> Cells = q => q.Raw ("TableViewCell");
+ public static Func<AppQuery, AppQuery> DismissPickerCustom = q => q.Marked ("Done");
+ public static Func<AppQuery, AppQuery> DismissPickerNormal = q => q.Marked ("Done");
+ public static Func<AppQuery, AppQuery> Entrys = q => q.Raw ("TextField");
+ public static Func<AppQuery, AppQuery> Editors = q => q.Raw ("TextView");
+ public static Func<AppQuery, AppQuery> Frames = q => q.Raw ("view:'Xamarin_Forms_Platform_iOS_FrameRenderer'");
+ public static Func<AppQuery, AppQuery> Images = q => q.Raw ("view:'Xamarin_Forms_Platform_iOS_ImageRenderer'");
+ public static Func<AppQuery, AppQuery> ImageView = q => q.Raw ("ImageView");
+ public static Func<AppQuery, AppQuery> Labels = q => q.Raw ("Label");
+ public static Func<AppQuery, AppQuery> LabelRenderers = q => q.Raw ("view:'Xamarin_Forms_Platform_iOS_LabelRenderer'");
+ public static Func<AppQuery, AppQuery> List = q => q.Raw ("TableView");
+ public static Func<AppQuery, AppQuery> Map = q => q.Raw ("view:'MKMapView'");
+ public static Func<AppQuery, AppQuery> MapPins = q => q.Raw ("all view:'MKPinAnnotationView'");
+ public static Func<AppQuery, AppQuery> NavigationBar = q => q.Raw ("NavigationBar");
+ public static Func<AppQuery, AppQuery> NumberPicker = q => q.Raw ("PickerTableView");
+ public static Func<AppQuery, AppQuery> ProgressBar = q => q.Raw ("ProgressView");
+ public static Func<AppQuery, AppQuery> SearchBars = q => q.Raw ("SearchBar");
+ public static Func<AppQuery, AppQuery> Sliders = q => q.Raw ("Slider");
+ public static Func<AppQuery, AppQuery> Steppers = q => q.Raw ("Stepper");
+ public static Func<AppQuery, AppQuery> Switch = q => q.Raw ("Switch");
+ public static Func<AppQuery, AppQuery> Tables = q => q.Raw ("TableView");
+ public static Func<AppQuery, AppQuery> ThreeXThreeGridCell = q => q.Raw ("view marked:'a block 3x3' parent view:'Xamarin_Forms_Platform_iOS_LabelRenderer'");
+ public static Func<AppQuery, AppQuery> SpanningThreeRows = q => q.Raw ("view marked:'Spanning 3 rows' parent view:'Xamarin_Forms_Platform_iOS_LabelRenderer'");
+
+ public static Func<AppQuery, AppQuery> EntryWithPlaceholder (string text) {
+ return q => q.Raw (string.Format ("TextField placeholder:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryWithText (string text) {
+ return q => q.Raw (string.Format ("TextField text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryCellWithPlaceholder (string text) {
+ return q => q.Raw (string.Format ("TextField placeholder:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryCellWithText (string text) {
+ return q => q.Raw (string.Format ("TextField text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EditorsWithText (string text) {
+ return q => q.Raw (string.Format ("TextView text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> EntryWithIndex (int index) {
+ return q => q.Raw (string.Format ("TextField index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> SearchBarWithIndex (int index) {
+ return q => q.Raw (string.Format ("SearchBar index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> LabelWithIndex (int index) {
+ return q => q.Raw (string.Format ("Label index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> LabelWithText (string text) {
+ return q => q.Raw (string.Format ("Label text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> LabelWithId (string id) {
+ return q => q.Raw (string.Format ("Label id:'{0}'", id));
+ }
+
+ public static Func<AppQuery, AppQuery> PickerEntryWithIndex (int index) {
+ return q => q.Raw (string.Format ("TextField index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> PickerEntryWithPlaceholder (string placeholder) {
+ return q => q.Raw (string.Format ("TextField placeholder:'{0}'", placeholder));
+ }
+
+ public static Func<AppQuery, AppQuery> PickerEntryWithText (string text) {
+ return q => q.Raw (string.Format ("TextField text:'{0}'", text));
+ }
+
+ public static Func<AppQuery, AppQuery> SwitchWithIndex (int index) {
+ return q => q.Raw (string.Format ("Switch index:{0}", index));
+ }
+
+ public static Func<AppQuery, AppQuery> StepperWithIndex (int index) {
+ return q => q.Raw (string.Format ("Stepper index:{0}", index));
+ }
+
+ public static AppResult DetailPage (this iOSApp app)
+ {
+ if (app.Query (q => q.Raw ("view:'UILayoutContainerView'")).Length == 3) {
+ // iPad SplitView Landscape
+ return app.Query (q => q.Raw ("view:'UILayoutContainerView'"))[2];
+ }
+ return app.Query (q => q.Raw ("*"))[0];
+ }
+
+ }
+}
diff --git a/Xamarin.Forms.iOS.UITests/Properties/AssemblyInfo.cs b/Xamarin.Forms.iOS.UITests/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..7ff77aac
--- /dev/null
+++ b/Xamarin.Forms.iOS.UITests/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Xamarin.Forms.iOS.UITests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Xamarin.Forms.iOS.UITests")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("6269ddd8-ec05-4638-97ec-939651fec5a8")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Xamarin.Forms.iOS.UITests/TestHelpers.cs b/Xamarin.Forms.iOS.UITests/TestHelpers.cs
new file mode 100644
index 00000000..981122cb
--- /dev/null
+++ b/Xamarin.Forms.iOS.UITests/TestHelpers.cs
@@ -0,0 +1,34 @@
+using Xamarin.UITest;
+using Xamarin.UITest.Queries;
+
+namespace Xamarin.Forms.UITests
+{
+ public enum Speed
+ {
+ Slow,
+ Fast
+ }
+
+ public static class TestHelpers
+ {
+ public static int ControlGalleryMaxScrolls = 30;
+
+ public static void NavigateBack (this IApp app)
+ {
+ app.Tap (PlatformQueries.Back);
+ }
+
+ public static void NavigateToTestCases (this IApp app)
+ {
+ app.Tap (q => q.Marked ("Test Cases"));
+ app.WaitForElement (q => q.Marked ("Carousel Async Add Page Issue"));
+ }
+
+ public static AppRect MainScreenBounds (this IApp app)
+ {
+ return app.Query (q => q.Raw ("*"))[0].Rect;
+ }
+
+ }
+}
+
diff --git a/Xamarin.Forms.iOS.UITests/Xamarin.Forms.iOS.UITests.csproj b/Xamarin.Forms.iOS.UITests/Xamarin.Forms.iOS.UITests.csproj
new file mode 100644
index 00000000..cfc6d8e8
--- /dev/null
+++ b/Xamarin.Forms.iOS.UITests/Xamarin.Forms.iOS.UITests.csproj
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{6108FD24-F3B1-463D-83E2-35B981A1CB81}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Xamarin.Forms.iOS.UITests</RootNamespace>
+ <AssemblyName>Xamarin.Forms.iOS.UITests</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ <Reference Include="nunit.framework">
+ <HintPath>..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="Xamarin.UITest">
+ <HintPath>..\packages\Xamarin.UITest.0.4.1\lib\Xamarin.UITest.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Legacy-BaseTestFixture.cs" />
+ <Compile Include="TestHelpers.cs" />
+ <Compile Include="PlatformQueries.cs" />
+ <Compile Include="Legacy-PlatformHelpers.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ <Compile Include="Device.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+ </Target>
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ItemGroup>
+ <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+ <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+ <Name>Xamarin.Forms.Core</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup />
+</Project> \ No newline at end of file
diff --git a/Xamarin.Forms.iOS.UITests/packages.config b/Xamarin.Forms.iOS.UITests/packages.config
new file mode 100644
index 00000000..cd848561
--- /dev/null
+++ b/Xamarin.Forms.iOS.UITests/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit" version="2.6.3" targetFramework="net45" />
+ <package id="Xamarin.UITest" version="0.4.1" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/Xamarin.Forms.sln b/Xamarin.Forms.sln
new file mode 100644
index 00000000..d88f6492
--- /dev/null
+++ b/Xamarin.Forms.sln
@@ -0,0 +1,1532 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.24720.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Xamarin.Forms", "Xamarin.Forms", "{9AD757F5-E57A-459D-A0A7-E0675E045B84}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{29AC50BF-B4FB-450B-9386-0C5AD4B84226}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnitTests", "UnitTests", "{33A20844-7EF4-441D-83DA-2ACAF5E1CDFA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Control Gallery", "Control Gallery", "{4F5E2D21-17F6-4A42-B8FB-D03D82E24EC8}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Xamarin.Forms.Xaml", "Xamarin.Forms.Xaml", "{32F608E2-6406-4DCF-9105-E2A7CB7085CF}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform.iOS.Classic", "Xamarin.Forms.Platform.iOS\Xamarin.Forms.Platform.iOS.Classic.csproj", "{4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}"
+ ProjectSection(ProjectDependencies) = postProject
+ {C7131F14-274F-4B55-ACA9-E81731AD012F} = {C7131F14-274F-4B55-ACA9-E81731AD012F}
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform.iOS", "Xamarin.Forms.Platform.iOS\Xamarin.Forms.Platform.iOS.csproj", "{271193C1-6E7C-429C-A36D-3F1BE5267231}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform.Android", "Xamarin.Forms.Platform.Android\Xamarin.Forms.Platform.Android.csproj", "{0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Core.UnitTests", "Xamarin.Forms.Core.UnitTests\Xamarin.Forms.Core.UnitTests.csproj", "{00259593-A283-47A5-ACB7-9C3819B16364}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.ControlGallery.iOS.Classic", "Xamarin.Forms.ControlGallery.iOS\Xamarin.Forms.ControlGallery.iOS.Classic.csproj", "{DEEC5844-D609-4F35-BCF0-5B71C91C8133}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.ControlGallery.Android", "Xamarin.Forms.ControlGallery.Android\Xamarin.Forms.ControlGallery.Android.csproj", "{1346A7F1-4457-4BB4-A371-2C8E28BBD53E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Xaml.Xamlg", "Xamarin.Forms.Xaml.Xamlg\Xamarin.Forms.Xaml.Xamlg.csproj", "{D597E3C6-1A50-4042-99FA-3E7CE28E4819}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Xaml.UnitTests", "Xamarin.Forms.Xaml.UnitTests\Xamarin.Forms.Xaml.UnitTests.csproj", "{4B14D295-C09B-4C38-B880-7CC768E50585}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Xaml.Xamlc", "Xamarin.Forms.Xaml.Xamlc\Xamarin.Forms.Xaml.Xamlc.csproj", "{928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Decompiler", "ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj", "{984CC812-9470-4A13-AFF9-CC44068D666C}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{29583A59-ACE2-4C2C-8A73-768D6979551A}"
+ ProjectSection(SolutionItems) = preProject
+ .nuget\packages.config = .nuget\packages.config
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuspec", ".nuspec", "{7E12C50D-A570-4DF1-94E1-8599843FA87C}"
+ ProjectSection(SolutionItems) = preProject
+ .nuspec\Xamarin.Forms.Debug.targets = .nuspec\Xamarin.Forms.Debug.targets
+ .nuspec\Xamarin.Forms.Maps.nuspec = .nuspec\Xamarin.Forms.Maps.nuspec
+ .nuspec\Xamarin.Forms.Maps.props = .nuspec\Xamarin.Forms.Maps.props
+ .nuspec\Xamarin.Forms.Maps.targets = .nuspec\Xamarin.Forms.Maps.targets
+ .nuspec\Xamarin.Forms.nuspec = .nuspec\Xamarin.Forms.nuspec
+ .nuspec\Xamarin.Forms.targets = .nuspec\Xamarin.Forms.targets
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform.WP8", "Xamarin.Forms.Platform.WP8\Xamarin.Forms.Platform.WP8.csproj", "{517B6AE0-792B-4665-9376-5CA33E539181}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.ControlGallery.WP8", "Xamarin.Forms.ControlGallery.WP8\Xamarin.Forms.ControlGallery.WP8.csproj", "{67F3837C-C663-4668-9CD3-5E6C5ABD59B8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Core", "Xamarin.Forms.Core\Xamarin.Forms.Core.csproj", "{57B8B73D-C3B5-4C42-869E-7B2F17D354AC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Xaml", "Xamarin.Forms.Xaml\Xamarin.Forms.Xaml.csproj", "{9DB2F292-8034-4E06-89AD-98BBDA4306B9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Controls", "Xamarin.Forms.Controls\Xamarin.Forms.Controls.csproj", "{CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Build.Tasks", "Xamarin.Forms.Build.Tasks\Xamarin.Forms.Build.Tasks.csproj", "{96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Xamarin.Forms.Maps", "Xamarin.Forms.Maps", "{132FB9A4-613F-44CE-95D5-758D32D231DD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Maps", "Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj", "{7D13BAC2-C6A4-416A-B07E-C169B199E52B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Maps.iOS", "Xamarin.Forms.Maps.iOS\Xamarin.Forms.Maps.iOS.csproj", "{ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Maps.WP8", "Xamarin.Forms.Maps.WP8\Xamarin.Forms.Maps.WP8.csproj", "{9222D2B8-63A4-4A36-A80E-BC34F27E0951}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Maps.Android", "Xamarin.Forms.Maps.Android\Xamarin.Forms.Maps.Android.csproj", "{BD50B39A-EBC5-408F-9C5E-923A8EBAE473}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UITests", "UITests", "{D4D57221-71D6-4031-A6F4-EC66AF0929D9}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{DDDFBCAF-93DE-4868-8296-FD909EF32EF7}"
+EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "APIDocs", "docs\APIDocs.shproj", "{DC1F3933-AC99-4887-8B09-E13C2B346D4F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform.Android.FormsViewGroup", "Xamarin.Forms.Platform.Android.FormsViewGroup\Xamarin.Forms.Platform.Android.FormsViewGroup.csproj", "{3B72465B-ACAE-43AE-9327-10F372FE5F80}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.UITest.Validator", "Xamarin.Forms.UITest.Validator\Xamarin.Forms.UITest.Validator.csproj", "{115C31B9-C1B2-4B00-BB0E-EA36F105903E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Core.iOS.UITests", "Xamarin.Forms.Core.iOS.UITests\Xamarin.Forms.Core.iOS.UITests.csproj", "{EADD8100-B3AE-4A31-92C4-267A64A1C6EB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Core.Android.UITests", "Xamarin.Forms.Core.Android.UITests\Xamarin.Forms.Core.Android.UITests.csproj", "{A34EBE01-25BF-4E69-A2DC-2288DC625541}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Loader", "Xamarin.Forms.Loader\Xamarin.Forms.Loader.csproj", "{00211725-2F89-4E2C-AC5A-38E5FF61BE67}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.UITest.TestCloud", "Xamarin.Forms.UITest.TestCloud\Xamarin.Forms.UITest.TestCloud.csproj", "{1E238A01-B492-461F-BADE-415E8F9C5DFC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.CustomAttributes", "Xamarin.Forms.CustomAttributes\Xamarin.Forms.CustomAttributes.csproj", "{4DCD0420-1168-4B77-86DB-6196EE4BD491}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Maps.iOS.Classic", "Xamarin.Forms.Maps.iOS\Xamarin.Forms.Maps.iOS.Classic.csproj", "{CA10FACD-22AB-463F-A20E-379C212B0858}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.ControlGallery.iOS", "Xamarin.Forms.ControlGallery.iOS\Xamarin.Forms.ControlGallery.iOS.csproj", "{C7131F14-274F-4B55-ACA9-E81731AD012F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform", "Xamarin.Forms.Platform\Xamarin.Forms.Platform.csproj", "{67F9D3A8-F71E-4428-913F-C37AE82CDB24}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Forwarders", "Forwarders", "{5A2DADBC-9510-4DD1-BE58-01501F2DF65D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform.Android (Forwarders)", "Stubs\Xamarin.Forms.Platform.Android\Xamarin.Forms.Platform.Android (Forwarders).csproj", "{6E53FEB1-1100-46AE-8013-17BBA35CC197}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform.iOS.Classic (Forwarders)", "Stubs\Xamarin.Forms.Platform.iOS.Classic\Xamarin.Forms.Platform.iOS.Classic (Forwarders).csproj", "{3E443AEF-3EC0-48C4-A524-7C6996339E1B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform.iOS (Forwarders)", "Stubs\Xamarin.Forms.Platform.iOS\Xamarin.Forms.Platform.iOS (Forwarders).csproj", "{39B3457F-01D8-43D0-8E84-D8C4F73CF48D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform.WP8 (Forwarders)", "Stubs\Xamarin.Forms.Platform.WP8\Xamarin.Forms.Platform.WP8 (Forwarders).csproj", "{483CDAE7-4353-4AB2-9C20-145A9F148FAD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform.WinRT", "Xamarin.Forms.Platform.WinRT\Xamarin.Forms.Platform.WinRT.csproj", "{F3FDD7AC-8899-4E41-BFD7-EC83403E736D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.ControlGallery.Windows", "Xamarin.Forms.ControlGallery.Windows\Xamarin.Forms.ControlGallery.Windows.csproj", "{1251646E-7FC6-425C-9464-A35DF1FC8E4D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform.WinRT.Tablet", "Xamarin.Forms.Platform.WinRT.Tablet\Xamarin.Forms.Platform.WinRT.Tablet.csproj", "{D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform.WinRT.Phone", "Xamarin.Forms.Platform.WinRT.Phone\Xamarin.Forms.Platform.WinRT.Phone.csproj", "{3361D52C-2E74-433E-8285-9C9A5C485977}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.ControlGallery.WindowsPhone", "Xamarin.Forms.ControlGallery.WindowsPhone\Xamarin.Forms.ControlGallery.WindowsPhone.csproj", "{8CDEC974-E6BE-4424-BC77-0B87400A08AF}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Xamarin.Forms.Controls.Issues", "Xamarin.Forms.Controls.Issues", "{B2927DF0-F98E-45C8-A917-27941B2B6838}"
+EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Xamarin.Forms.Controls.Issues.Shared", "Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Xamarin.Forms.Controls.Issues.Shared.shproj", "{0F0DB9CC-EA65-429C-9363-38624BF8F49C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.ControlGallery.WindowsUniversal", "Xamarin.Forms.ControlGallery.WindowsUniversal\Xamarin.Forms.ControlGallery.WindowsUniversal.csproj", "{AC257966-9368-478A-9DF4-F0D28E320FE3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform.UAP", "Xamarin.Forms.Platform.UAP\Xamarin.Forms.Platform.UAP.csproj", "{00D8D049-FFAA-4759-8FC9-1ECA30777F72}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Xaml.Design", "Xamarin.Forms.Xaml.Design\Xamarin.Forms.Xaml.Design.csproj", "{65BC4888-CC59-428A-9B75-540CF1C09480}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Maps.Design", "Xamarin.Forms.Maps.Design\Xamarin.Forms.Maps.Design.csproj", "{C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Core.Design", "Xamarin.Forms.Core.Design\Xamarin.Forms.Core.Design.csproj", "{98637471-8E5C-4DDE-89CA-2EAA664FB0EF}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Maps.UWP", "Xamarin.Forms.Maps.UWP\Xamarin.Forms.Maps.UWP.csproj", "{04D89A60-78EF-4A32-AE17-87E47E0233A5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Maps.WinRT.Phone", "Xamarin.Forms.Maps.WinRT.Phone\Xamarin.Forms.Maps.WinRT.Phone.csproj", "{2633AF57-F2CB-442A-AC19-F97BD8A06571}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Maps.WinRT.Tablet", "Xamarin.Forms.Maps.WinRT.Tablet\Xamarin.Forms.Maps.WinRT.Tablet.csproj", "{E5C4698D-FB57-4EEC-98C0-89E620F6920A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Core.Windows.UITests", "Xamarin.Forms.Core.Windows.UITests\Xamarin.Forms.Core.Windows.UITests.csproj", "{0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}"
+EndProject
+Global
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ docs\APIDocs.projitems*{dc1f3933-ac99-4887-8b09-e13c2b346d4f}*SharedItemsImports = 13
+ Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Xamarin.Forms.Controls.Issues.Shared.projitems*{a34ebe01-25bf-4e69-a2dc-2288dc625541}*SharedItemsImports = 4
+ Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Xamarin.Forms.Controls.Issues.Shared.projitems*{0a39a74b-6f7a-4d41-84f2-b0ccdce899df}*SharedItemsImports = 4
+ Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Xamarin.Forms.Controls.Issues.Shared.projitems*{0f0db9cc-ea65-429c-9363-38624bf8f49c}*SharedItemsImports = 13
+ Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Xamarin.Forms.Controls.Issues.Shared.projitems*{cb9c96ce-125c-4a68-b6a1-c3ff1fbf93e1}*SharedItemsImports = 4
+ Xamarin.Forms.Controls.Issues\Xamarin.Forms.Controls.Issues.Shared\Xamarin.Forms.Controls.Issues.Shared.projitems*{eadd8100-b3ae-4a31-92c4-267a64a1c6eb}*SharedItemsImports = 4
+ EndGlobalSection
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|ARM = Debug|ARM
+ Debug|iPhone = Debug|iPhone
+ Debug|iPhoneSimulator = Debug|iPhoneSimulator
+ Debug|Templates = Debug|Templates
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|ARM = Release|ARM
+ Release|iPhone = Release|iPhone
+ Release|iPhoneSimulator = Release|iPhoneSimulator
+ Release|Templates = Release|Templates
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Debug|ARM.Build.0 = Debug|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Debug|x64.Build.0 = Debug|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Debug|x86.Build.0 = Debug|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Release|ARM.ActiveCfg = Release|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Release|ARM.Build.0 = Release|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Release|iPhone.Build.0 = Release|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Release|Templates.ActiveCfg = Release|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Release|x64.ActiveCfg = Release|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Release|x64.Build.0 = Release|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Release|x86.ActiveCfg = Release|Any CPU
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B}.Release|x86.Build.0 = Release|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Debug|ARM.Build.0 = Debug|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Debug|x64.Build.0 = Debug|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Debug|x86.Build.0 = Debug|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Release|Any CPU.Build.0 = Release|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Release|ARM.ActiveCfg = Release|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Release|ARM.Build.0 = Release|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Release|iPhone.Build.0 = Release|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Release|Templates.ActiveCfg = Release|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Release|x64.ActiveCfg = Release|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Release|x64.Build.0 = Release|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Release|x86.ActiveCfg = Release|Any CPU
+ {271193C1-6E7C-429C-A36D-3F1BE5267231}.Release|x86.Build.0 = Release|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Debug|ARM.Build.0 = Debug|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Debug|x64.Build.0 = Debug|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Debug|x86.Build.0 = Debug|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Release|ARM.ActiveCfg = Release|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Release|ARM.Build.0 = Release|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Release|iPhone.Build.0 = Release|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Release|Templates.ActiveCfg = Release|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Release|x64.ActiveCfg = Release|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Release|x64.Build.0 = Release|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Release|x86.ActiveCfg = Release|Any CPU
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A}.Release|x86.Build.0 = Release|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Debug|ARM.Build.0 = Debug|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Debug|x64.Build.0 = Debug|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Debug|x86.Build.0 = Debug|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Release|Any CPU.Build.0 = Release|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Release|ARM.ActiveCfg = Release|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Release|ARM.Build.0 = Release|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Release|iPhone.Build.0 = Release|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Release|Templates.ActiveCfg = Release|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Release|x64.ActiveCfg = Release|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Release|x64.Build.0 = Release|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Release|x86.ActiveCfg = Release|Any CPU
+ {00259593-A283-47A5-ACB7-9C3819B16364}.Release|x86.Build.0 = Release|Any CPU
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Debug|Any CPU.Deploy.0 = Debug|iPhoneSimulator
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Debug|ARM.ActiveCfg = Debug|iPhone
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Debug|iPhone.ActiveCfg = Debug|iPhone
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Debug|iPhone.Build.0 = Debug|iPhone
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Debug|iPhone.Deploy.0 = Debug|iPhone
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Debug|Templates.ActiveCfg = Debug|iPhoneSimulator
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Debug|x64.ActiveCfg = Debug|iPhone
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Debug|x86.ActiveCfg = Debug|iPhone
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Release|Any CPU.Build.0 = Release|iPhoneSimulator
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Release|Any CPU.Deploy.0 = Release|iPhoneSimulator
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Release|ARM.ActiveCfg = Release|iPhone
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Release|iPhone.ActiveCfg = Release|iPhone
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Release|iPhone.Build.0 = Release|iPhone
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Release|iPhone.Deploy.0 = Release|iPhone
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Release|Templates.ActiveCfg = Release|iPhoneSimulator
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Release|x64.ActiveCfg = Release|iPhone
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133}.Release|x86.ActiveCfg = Release|iPhone
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|ARM.Build.0 = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|ARM.Deploy.0 = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|iPhone.Deploy.0 = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|x64.Build.0 = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|x64.Deploy.0 = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|x86.Build.0 = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Debug|x86.Deploy.0 = Debug|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|ARM.ActiveCfg = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|ARM.Build.0 = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|ARM.Deploy.0 = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|iPhone.Build.0 = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|iPhone.Deploy.0 = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|Templates.ActiveCfg = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|x64.ActiveCfg = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|x64.Build.0 = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|x64.Deploy.0 = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|x86.ActiveCfg = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|x86.Build.0 = Release|Any CPU
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E}.Release|x86.Deploy.0 = Release|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Debug|ARM.Build.0 = Debug|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Debug|x64.Build.0 = Debug|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Debug|x86.Build.0 = Debug|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Release|ARM.ActiveCfg = Release|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Release|ARM.Build.0 = Release|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Release|iPhone.Build.0 = Release|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Release|Templates.ActiveCfg = Release|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Release|x64.ActiveCfg = Release|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Release|x64.Build.0 = Release|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Release|x86.ActiveCfg = Release|Any CPU
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819}.Release|x86.Build.0 = Release|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Debug|ARM.Build.0 = Debug|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Debug|x64.Build.0 = Debug|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Debug|x86.Build.0 = Debug|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Release|ARM.ActiveCfg = Release|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Release|ARM.Build.0 = Release|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Release|iPhone.Build.0 = Release|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Release|Templates.ActiveCfg = Release|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Release|x64.ActiveCfg = Release|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Release|x64.Build.0 = Release|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Release|x86.ActiveCfg = Release|Any CPU
+ {4B14D295-C09B-4C38-B880-7CC768E50585}.Release|x86.Build.0 = Release|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Debug|ARM.Build.0 = Debug|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Debug|x64.Build.0 = Debug|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Debug|x86.Build.0 = Debug|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|ARM.ActiveCfg = Release|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|ARM.Build.0 = Release|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|iPhone.Build.0 = Release|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|Templates.ActiveCfg = Release|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|x64.ActiveCfg = Release|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|x64.Build.0 = Release|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|x86.ActiveCfg = Release|Any CPU
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF}.Release|x86.Build.0 = Release|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|ARM.Build.0 = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|Templates.Build.0 = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|x64.Build.0 = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|x86.Build.0 = Debug|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|ARM.ActiveCfg = Release|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|ARM.Build.0 = Release|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|iPhone.Build.0 = Release|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Templates.ActiveCfg = Release|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Templates.Build.0 = Release|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|x64.ActiveCfg = Release|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|x64.Build.0 = Release|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|x86.ActiveCfg = Release|Any CPU
+ {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|x86.Build.0 = Release|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Debug|ARM.ActiveCfg = Debug|ARM
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Debug|ARM.Build.0 = Debug|ARM
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Debug|x64.Build.0 = Debug|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Debug|x86.ActiveCfg = Debug|x86
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Debug|x86.Build.0 = Debug|x86
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Release|Any CPU.Build.0 = Release|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Release|ARM.ActiveCfg = Release|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Release|ARM.Build.0 = Release|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Release|iPhone.Build.0 = Release|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Release|Templates.ActiveCfg = Release|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Release|x64.ActiveCfg = Release|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Release|x64.Build.0 = Release|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Release|x86.ActiveCfg = Release|Any CPU
+ {517B6AE0-792B-4665-9376-5CA33E539181}.Release|x86.Build.0 = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|ARM.ActiveCfg = Debug|ARM
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|ARM.Build.0 = Debug|ARM
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|ARM.Deploy.0 = Debug|ARM
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|iPhone.Deploy.0 = Debug|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|x64.Build.0 = Debug|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|x64.Deploy.0 = Debug|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|x86.ActiveCfg = Debug|x86
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|x86.Build.0 = Debug|x86
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Debug|x86.Deploy.0 = Debug|x86
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|ARM.ActiveCfg = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|ARM.Build.0 = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|ARM.Deploy.0 = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|iPhone.Build.0 = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|iPhone.Deploy.0 = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|Templates.ActiveCfg = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|x64.ActiveCfg = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|x64.Build.0 = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|x64.Deploy.0 = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|x86.ActiveCfg = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|x86.Build.0 = Release|Any CPU
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8}.Release|x86.Deploy.0 = Release|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Debug|ARM.Build.0 = Debug|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Debug|x64.Build.0 = Debug|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Debug|x86.Build.0 = Debug|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Release|ARM.ActiveCfg = Release|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Release|ARM.Build.0 = Release|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Release|iPhone.Build.0 = Release|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Release|Templates.ActiveCfg = Release|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Release|x64.ActiveCfg = Release|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Release|x64.Build.0 = Release|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Release|x86.ActiveCfg = Release|Any CPU
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC}.Release|x86.Build.0 = Release|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Debug|ARM.Build.0 = Debug|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Debug|x64.Build.0 = Debug|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Debug|x86.Build.0 = Debug|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Release|ARM.ActiveCfg = Release|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Release|ARM.Build.0 = Release|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Release|iPhone.Build.0 = Release|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Release|Templates.ActiveCfg = Release|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Release|x64.ActiveCfg = Release|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Release|x64.Build.0 = Release|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Release|x86.ActiveCfg = Release|Any CPU
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9}.Release|x86.Build.0 = Release|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Debug|ARM.Build.0 = Debug|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Debug|x64.Build.0 = Debug|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Debug|x86.Build.0 = Debug|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Release|ARM.ActiveCfg = Release|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Release|ARM.Build.0 = Release|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Release|iPhone.Build.0 = Release|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Release|Templates.ActiveCfg = Release|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Release|x64.ActiveCfg = Release|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Release|x64.Build.0 = Release|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Release|x86.ActiveCfg = Release|Any CPU
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1}.Release|x86.Build.0 = Release|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Debug|ARM.Build.0 = Debug|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Debug|x64.Build.0 = Debug|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Debug|x86.Build.0 = Debug|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Release|ARM.ActiveCfg = Release|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Release|ARM.Build.0 = Release|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Release|iPhone.Build.0 = Release|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Release|Templates.ActiveCfg = Release|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Release|x64.ActiveCfg = Release|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Release|x64.Build.0 = Release|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Release|x86.ActiveCfg = Release|Any CPU
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7}.Release|x86.Build.0 = Release|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Debug|ARM.Build.0 = Debug|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Debug|x64.Build.0 = Debug|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Debug|x86.Build.0 = Debug|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Release|ARM.ActiveCfg = Release|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Release|ARM.Build.0 = Release|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Release|iPhone.Build.0 = Release|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Release|Templates.ActiveCfg = Release|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Release|x64.ActiveCfg = Release|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Release|x64.Build.0 = Release|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Release|x86.ActiveCfg = Release|Any CPU
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B}.Release|x86.Build.0 = Release|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Debug|ARM.Build.0 = Debug|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Debug|x64.Build.0 = Debug|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Debug|x86.Build.0 = Debug|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|ARM.ActiveCfg = Release|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|ARM.Build.0 = Release|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|iPhone.Build.0 = Release|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|Templates.ActiveCfg = Release|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|x64.ActiveCfg = Release|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|x64.Build.0 = Release|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|x86.ActiveCfg = Release|Any CPU
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491}.Release|x86.Build.0 = Release|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|ARM.ActiveCfg = Debug|ARM
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|ARM.Build.0 = Debug|ARM
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|x64.Build.0 = Debug|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|x86.ActiveCfg = Debug|x86
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Debug|x86.Build.0 = Debug|x86
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|ARM.ActiveCfg = Release|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|ARM.Build.0 = Release|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|iPhone.Build.0 = Release|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|Templates.ActiveCfg = Release|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|x64.ActiveCfg = Release|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|x64.Build.0 = Release|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|x86.ActiveCfg = Release|Any CPU
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951}.Release|x86.Build.0 = Release|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Debug|ARM.Build.0 = Debug|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Debug|x64.Build.0 = Debug|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Debug|x86.Build.0 = Debug|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Release|ARM.ActiveCfg = Release|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Release|ARM.Build.0 = Release|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Release|iPhone.Build.0 = Release|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Release|Templates.ActiveCfg = Release|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Release|x64.ActiveCfg = Release|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Release|x64.Build.0 = Release|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Release|x86.ActiveCfg = Release|Any CPU
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473}.Release|x86.Build.0 = Release|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Debug|ARM.Build.0 = Debug|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Debug|x64.Build.0 = Debug|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Debug|x86.Build.0 = Debug|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Release|ARM.ActiveCfg = Release|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Release|ARM.Build.0 = Release|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Release|iPhone.Build.0 = Release|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Release|Templates.ActiveCfg = Release|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Release|x64.ActiveCfg = Release|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Release|x64.Build.0 = Release|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Release|x86.ActiveCfg = Release|Any CPU
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80}.Release|x86.Build.0 = Release|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Debug|ARM.Build.0 = Debug|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Debug|x64.Build.0 = Debug|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Debug|x86.Build.0 = Debug|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Release|ARM.ActiveCfg = Release|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Release|ARM.Build.0 = Release|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Release|iPhone.Build.0 = Release|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Release|Templates.ActiveCfg = Release|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Release|x64.ActiveCfg = Release|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Release|x64.Build.0 = Release|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Release|x86.ActiveCfg = Release|Any CPU
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E}.Release|x86.Build.0 = Release|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Debug|ARM.Build.0 = Debug|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Debug|x64.Build.0 = Debug|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Debug|x86.Build.0 = Debug|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Release|ARM.ActiveCfg = Release|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Release|ARM.Build.0 = Release|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Release|iPhone.Build.0 = Release|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Release|Templates.ActiveCfg = Release|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Release|x64.ActiveCfg = Release|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Release|x64.Build.0 = Release|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Release|x86.ActiveCfg = Release|Any CPU
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB}.Release|x86.Build.0 = Release|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Debug|ARM.Build.0 = Debug|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Debug|x64.Build.0 = Debug|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Debug|x86.Build.0 = Debug|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Release|ARM.ActiveCfg = Release|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Release|ARM.Build.0 = Release|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Release|iPhone.Build.0 = Release|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Release|Templates.ActiveCfg = Release|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Release|x64.ActiveCfg = Release|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Release|x64.Build.0 = Release|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Release|x86.ActiveCfg = Release|Any CPU
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541}.Release|x86.Build.0 = Release|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Debug|ARM.Build.0 = Debug|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Debug|x64.Build.0 = Debug|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Debug|x86.Build.0 = Debug|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Release|Any CPU.Build.0 = Release|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Release|ARM.ActiveCfg = Release|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Release|ARM.Build.0 = Release|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Release|iPhone.Build.0 = Release|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Release|Templates.ActiveCfg = Release|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Release|x64.ActiveCfg = Release|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Release|x64.Build.0 = Release|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Release|x86.ActiveCfg = Release|Any CPU
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67}.Release|x86.Build.0 = Release|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Debug|ARM.Build.0 = Debug|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Debug|x64.Build.0 = Debug|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Debug|x86.Build.0 = Debug|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Release|ARM.ActiveCfg = Release|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Release|ARM.Build.0 = Release|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Release|iPhone.Build.0 = Release|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Release|Templates.ActiveCfg = Release|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Release|x64.ActiveCfg = Release|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Release|x64.Build.0 = Release|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Release|x86.ActiveCfg = Release|Any CPU
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC}.Release|x86.Build.0 = Release|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Debug|ARM.Build.0 = Debug|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Debug|x64.Build.0 = Debug|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Debug|x86.Build.0 = Debug|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Release|ARM.ActiveCfg = Release|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Release|ARM.Build.0 = Release|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Release|iPhone.Build.0 = Release|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Release|Templates.ActiveCfg = Release|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Release|x64.ActiveCfg = Release|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Release|x64.Build.0 = Release|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Release|x86.ActiveCfg = Release|Any CPU
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491}.Release|x86.Build.0 = Release|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Debug|ARM.Build.0 = Debug|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Debug|x64.Build.0 = Debug|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Debug|x86.Build.0 = Debug|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Release|ARM.ActiveCfg = Release|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Release|ARM.Build.0 = Release|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Release|iPhone.Build.0 = Release|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Release|Templates.ActiveCfg = Release|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Release|x64.ActiveCfg = Release|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Release|x64.Build.0 = Release|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Release|x86.ActiveCfg = Release|Any CPU
+ {CA10FACD-22AB-463F-A20E-379C212B0858}.Release|x86.Build.0 = Release|Any CPU
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|ARM.ActiveCfg = Debug|iPhone
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|iPhone.ActiveCfg = Debug|iPhone
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|iPhone.Build.0 = Debug|iPhone
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|Templates.ActiveCfg = Debug|iPhone
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|x64.ActiveCfg = Debug|iPhone
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Debug|x86.ActiveCfg = Debug|iPhone
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Release|Any CPU.Build.0 = Release|iPhoneSimulator
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Release|ARM.ActiveCfg = Release|iPhone
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Release|iPhone.ActiveCfg = Release|iPhone
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Release|iPhone.Build.0 = Release|iPhone
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Release|Templates.ActiveCfg = Release|iPhone
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Release|x64.ActiveCfg = Release|iPhone
+ {C7131F14-274F-4B55-ACA9-E81731AD012F}.Release|x86.ActiveCfg = Release|iPhone
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Debug|ARM.Build.0 = Debug|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Debug|x64.Build.0 = Debug|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Debug|x86.Build.0 = Debug|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Release|Any CPU.Build.0 = Release|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Release|ARM.ActiveCfg = Release|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Release|ARM.Build.0 = Release|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Release|iPhone.Build.0 = Release|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Release|Templates.ActiveCfg = Release|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Release|x64.ActiveCfg = Release|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Release|x64.Build.0 = Release|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Release|x86.ActiveCfg = Release|Any CPU
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24}.Release|x86.Build.0 = Release|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Debug|ARM.Build.0 = Debug|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Debug|x64.Build.0 = Debug|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Debug|x86.Build.0 = Debug|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Release|ARM.ActiveCfg = Release|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Release|ARM.Build.0 = Release|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Release|iPhone.Build.0 = Release|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Release|Templates.ActiveCfg = Release|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Release|x64.ActiveCfg = Release|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Release|x64.Build.0 = Release|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Release|x86.ActiveCfg = Release|Any CPU
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197}.Release|x86.Build.0 = Release|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Debug|ARM.Build.0 = Debug|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Debug|x64.Build.0 = Debug|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Debug|x86.Build.0 = Debug|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Release|ARM.ActiveCfg = Release|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Release|ARM.Build.0 = Release|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Release|iPhone.Build.0 = Release|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Release|Templates.ActiveCfg = Release|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Release|x64.ActiveCfg = Release|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Release|x64.Build.0 = Release|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Release|x86.ActiveCfg = Release|Any CPU
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B}.Release|x86.Build.0 = Release|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Debug|ARM.Build.0 = Debug|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Debug|x64.Build.0 = Debug|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Debug|x86.Build.0 = Debug|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Release|ARM.ActiveCfg = Release|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Release|ARM.Build.0 = Release|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Release|iPhone.Build.0 = Release|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Release|Templates.ActiveCfg = Release|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Release|x64.ActiveCfg = Release|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Release|x64.Build.0 = Release|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Release|x86.ActiveCfg = Release|Any CPU
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D}.Release|x86.Build.0 = Release|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Debug|ARM.ActiveCfg = Debug|ARM
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Debug|ARM.Build.0 = Debug|ARM
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Debug|x64.Build.0 = Debug|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Debug|x86.ActiveCfg = Debug|x86
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Debug|x86.Build.0 = Debug|x86
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Release|ARM.ActiveCfg = Release|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Release|ARM.Build.0 = Release|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Release|iPhone.Build.0 = Release|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Release|Templates.ActiveCfg = Release|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Release|x64.ActiveCfg = Release|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Release|x64.Build.0 = Release|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Release|x86.ActiveCfg = Release|Any CPU
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD}.Release|x86.Build.0 = Release|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Debug|ARM.Build.0 = Debug|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Debug|x64.Build.0 = Debug|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Debug|x86.Build.0 = Debug|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Release|ARM.ActiveCfg = Release|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Release|ARM.Build.0 = Release|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Release|iPhone.Build.0 = Release|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Release|Templates.ActiveCfg = Release|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Release|x64.ActiveCfg = Release|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Release|x64.Build.0 = Release|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Release|x86.ActiveCfg = Release|Any CPU
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D}.Release|x86.Build.0 = Release|Any CPU
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|Any CPU.Build.0 = Debug|x86
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|Any CPU.Deploy.0 = Debug|x86
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|ARM.ActiveCfg = Debug|ARM
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|ARM.Build.0 = Debug|ARM
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|ARM.Deploy.0 = Debug|ARM
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|iPhone.ActiveCfg = Debug|ARM
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|iPhone.Build.0 = Debug|ARM
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|iPhone.Deploy.0 = Debug|ARM
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|iPhoneSimulator.ActiveCfg = Debug|x86
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|iPhoneSimulator.Build.0 = Debug|x86
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|iPhoneSimulator.Deploy.0 = Debug|x86
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|x64.ActiveCfg = Debug|x64
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|x64.Build.0 = Debug|x64
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|x64.Deploy.0 = Debug|x64
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|x86.ActiveCfg = Debug|x86
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|x86.Build.0 = Debug|x86
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Debug|x86.Deploy.0 = Debug|x86
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|Any CPU.ActiveCfg = Release|x86
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|Any CPU.Build.0 = Release|x86
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|Any CPU.Deploy.0 = Release|x86
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|ARM.ActiveCfg = Release|ARM
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|ARM.Build.0 = Release|ARM
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|ARM.Deploy.0 = Release|ARM
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|iPhone.Build.0 = Release|Any CPU
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|iPhone.Deploy.0 = Release|Any CPU
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|Templates.ActiveCfg = Release|Any CPU
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|x64.ActiveCfg = Release|x64
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|x64.Build.0 = Release|x64
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|x64.Deploy.0 = Release|x64
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|x86.ActiveCfg = Release|x86
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|x86.Build.0 = Release|x86
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D}.Release|x86.Deploy.0 = Release|x86
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Debug|ARM.ActiveCfg = Debug|ARM
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Debug|ARM.Build.0 = Debug|ARM
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Debug|x64.ActiveCfg = Debug|x64
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Debug|x64.Build.0 = Debug|x64
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Debug|x86.ActiveCfg = Debug|x86
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Debug|x86.Build.0 = Debug|x86
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Release|ARM.ActiveCfg = Release|ARM
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Release|ARM.Build.0 = Release|ARM
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Release|iPhone.Build.0 = Release|Any CPU
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Release|Templates.ActiveCfg = Release|Any CPU
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Release|x64.ActiveCfg = Release|x64
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Release|x64.Build.0 = Release|x64
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Release|x86.ActiveCfg = Release|x86
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF}.Release|x86.Build.0 = Release|x86
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Debug|ARM.ActiveCfg = Debug|ARM
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Debug|ARM.Build.0 = Debug|ARM
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Debug|x64.Build.0 = Debug|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Debug|x86.ActiveCfg = Debug|x86
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Debug|x86.Build.0 = Debug|x86
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Release|ARM.ActiveCfg = Release|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Release|ARM.Build.0 = Release|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Release|iPhone.Build.0 = Release|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Release|Templates.ActiveCfg = Release|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Release|x64.ActiveCfg = Release|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Release|x64.Build.0 = Release|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Release|x86.ActiveCfg = Release|Any CPU
+ {3361D52C-2E74-433E-8285-9C9A5C485977}.Release|x86.Build.0 = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|ARM.ActiveCfg = Debug|ARM
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|ARM.Build.0 = Debug|ARM
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|ARM.Deploy.0 = Debug|ARM
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|iPhone.Deploy.0 = Debug|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|x64.Build.0 = Debug|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|x64.Deploy.0 = Debug|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|x86.ActiveCfg = Debug|x86
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|x86.Build.0 = Debug|x86
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Debug|x86.Deploy.0 = Debug|x86
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|ARM.ActiveCfg = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|ARM.Build.0 = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|ARM.Deploy.0 = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|iPhone.Build.0 = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|iPhone.Deploy.0 = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|Templates.ActiveCfg = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|x64.ActiveCfg = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|x64.Build.0 = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|x64.Deploy.0 = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|x86.ActiveCfg = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|x86.Build.0 = Release|Any CPU
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF}.Release|x86.Deploy.0 = Release|Any CPU
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|Any CPU.Build.0 = Debug|x86
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|Any CPU.Deploy.0 = Debug|x86
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|ARM.ActiveCfg = Debug|ARM
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|ARM.Build.0 = Debug|ARM
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|ARM.Deploy.0 = Debug|ARM
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|iPhone.ActiveCfg = Debug|ARM
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|iPhone.Build.0 = Debug|ARM
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|iPhone.Deploy.0 = Debug|ARM
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|iPhoneSimulator.ActiveCfg = Debug|x86
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|Templates.ActiveCfg = Debug|x86
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|x64.ActiveCfg = Debug|x64
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|x64.Build.0 = Debug|x64
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|x64.Deploy.0 = Debug|x64
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|x86.ActiveCfg = Debug|x86
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|x86.Build.0 = Debug|x86
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Debug|x86.Deploy.0 = Debug|x86
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|Any CPU.ActiveCfg = Release|x86
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|Any CPU.Build.0 = Release|x86
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|Any CPU.Deploy.0 = Release|x86
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|ARM.ActiveCfg = Release|ARM
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|ARM.Build.0 = Release|ARM
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|ARM.Deploy.0 = Release|ARM
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|iPhone.ActiveCfg = Release|ARM
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|iPhone.Build.0 = Release|ARM
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|iPhone.Deploy.0 = Release|ARM
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|iPhoneSimulator.ActiveCfg = Release|x86
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|Templates.ActiveCfg = Release|x86
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|x64.ActiveCfg = Release|x64
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|x64.Build.0 = Release|x64
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|x64.Deploy.0 = Release|x64
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|x86.ActiveCfg = Release|x86
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|x86.Build.0 = Release|x86
+ {AC257966-9368-478A-9DF4-F0D28E320FE3}.Release|x86.Deploy.0 = Release|x86
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Debug|ARM.ActiveCfg = Debug|ARM
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Debug|ARM.Build.0 = Debug|ARM
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Debug|x64.ActiveCfg = Debug|x64
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Debug|x64.Build.0 = Debug|x64
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Debug|x86.ActiveCfg = Debug|x86
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Debug|x86.Build.0 = Debug|x86
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|Any CPU.Build.0 = Release|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|ARM.ActiveCfg = Release|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|ARM.Build.0 = Release|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|iPhone.Build.0 = Release|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|Templates.ActiveCfg = Release|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|x64.ActiveCfg = Release|x64
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|x64.Build.0 = Release|x64
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|x86.ActiveCfg = Release|Any CPU
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72}.Release|x86.Build.0 = Release|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Debug|ARM.Build.0 = Debug|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Debug|Templates.Build.0 = Debug|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Debug|x64.Build.0 = Debug|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Debug|x86.Build.0 = Debug|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Release|Any CPU.Build.0 = Release|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Release|ARM.ActiveCfg = Release|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Release|ARM.Build.0 = Release|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Release|iPhone.Build.0 = Release|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Release|Templates.ActiveCfg = Release|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Release|Templates.Build.0 = Release|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Release|x64.ActiveCfg = Release|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Release|x64.Build.0 = Release|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Release|x86.ActiveCfg = Release|Any CPU
+ {65BC4888-CC59-428A-9B75-540CF1C09480}.Release|x86.Build.0 = Release|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Debug|ARM.Build.0 = Debug|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Debug|Templates.Build.0 = Debug|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Debug|x64.Build.0 = Debug|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Debug|x86.Build.0 = Debug|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Release|ARM.ActiveCfg = Release|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Release|ARM.Build.0 = Release|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Release|iPhone.Build.0 = Release|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Release|Templates.ActiveCfg = Release|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Release|Templates.Build.0 = Release|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Release|x64.ActiveCfg = Release|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Release|x64.Build.0 = Release|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Release|x86.ActiveCfg = Release|Any CPU
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87}.Release|x86.Build.0 = Release|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Debug|ARM.Build.0 = Debug|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Debug|Templates.Build.0 = Debug|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Debug|x64.Build.0 = Debug|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Debug|x86.Build.0 = Debug|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Release|ARM.ActiveCfg = Release|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Release|ARM.Build.0 = Release|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Release|iPhone.Build.0 = Release|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Release|Templates.ActiveCfg = Release|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Release|Templates.Build.0 = Release|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Release|x64.ActiveCfg = Release|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Release|x64.Build.0 = Release|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Release|x86.ActiveCfg = Release|Any CPU
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF}.Release|x86.Build.0 = Release|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Debug|ARM.ActiveCfg = Debug|ARM
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Debug|ARM.Build.0 = Debug|ARM
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Debug|Templates.Build.0 = Debug|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Debug|x64.ActiveCfg = Debug|x64
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Debug|x64.Build.0 = Debug|x64
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Debug|x86.ActiveCfg = Debug|x86
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Debug|x86.Build.0 = Debug|x86
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|ARM.ActiveCfg = Release|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|ARM.Build.0 = Release|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|iPhone.Build.0 = Release|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|Templates.ActiveCfg = Release|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|Templates.Build.0 = Release|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|x64.ActiveCfg = Release|x64
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|x64.Build.0 = Release|x64
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|x86.ActiveCfg = Release|Any CPU
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5}.Release|x86.Build.0 = Release|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Debug|ARM.ActiveCfg = Debug|ARM
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Debug|ARM.Build.0 = Debug|ARM
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Debug|iPhoneSimulator.ActiveCfg = Debug|x86
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Debug|iPhoneSimulator.Build.0 = Debug|x86
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Debug|Templates.Build.0 = Debug|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Debug|x64.Build.0 = Debug|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Debug|x86.ActiveCfg = Debug|x86
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Debug|x86.Build.0 = Debug|x86
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Release|ARM.ActiveCfg = Release|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Release|ARM.Build.0 = Release|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Release|iPhone.Build.0 = Release|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Release|Templates.ActiveCfg = Release|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Release|Templates.Build.0 = Release|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Release|x64.ActiveCfg = Release|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Release|x64.Build.0 = Release|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Release|x86.ActiveCfg = Release|Any CPU
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571}.Release|x86.Build.0 = Release|Any CPU
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Debug|Any CPU.Build.0 = Debug|x86
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Debug|ARM.ActiveCfg = Debug|ARM
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Debug|ARM.Build.0 = Debug|ARM
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Debug|iPhone.ActiveCfg = Debug|ARM
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Debug|iPhone.Build.0 = Debug|ARM
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Debug|iPhoneSimulator.ActiveCfg = Debug|ARM
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Debug|iPhoneSimulator.Build.0 = Debug|ARM
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Debug|Templates.Build.0 = Debug|Any CPU
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Debug|x64.ActiveCfg = Debug|x64
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Debug|x64.Build.0 = Debug|x64
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Debug|x86.ActiveCfg = Debug|x86
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Debug|x86.Build.0 = Debug|x86
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Release|Any CPU.ActiveCfg = Release|x86
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Release|Any CPU.Build.0 = Release|x86
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Release|ARM.ActiveCfg = Release|ARM
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Release|ARM.Build.0 = Release|ARM
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Release|iPhone.Build.0 = Release|Any CPU
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Release|Templates.ActiveCfg = Release|Any CPU
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Release|Templates.Build.0 = Release|Any CPU
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Release|x64.ActiveCfg = Release|x64
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Release|x64.Build.0 = Release|x64
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Release|x86.ActiveCfg = Release|x86
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A}.Release|x86.Build.0 = Release|x86
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Debug|Templates.ActiveCfg = Debug|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Debug|Templates.Build.0 = Debug|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Release|ARM.ActiveCfg = Release|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Release|iPhone.Build.0 = Release|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Release|Templates.ActiveCfg = Release|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Release|Templates.Build.0 = Release|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Release|x64.ActiveCfg = Release|Any CPU
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF}.Release|x86.ActiveCfg = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {4A47B5DF-DDFC-476B-AC41-5105FF3B9B8B} = {29AC50BF-B4FB-450B-9386-0C5AD4B84226}
+ {271193C1-6E7C-429C-A36D-3F1BE5267231} = {29AC50BF-B4FB-450B-9386-0C5AD4B84226}
+ {0E16E70A-D6DD-4323-AD5D-363ABFF42D6A} = {29AC50BF-B4FB-450B-9386-0C5AD4B84226}
+ {00259593-A283-47A5-ACB7-9C3819B16364} = {33A20844-7EF4-441D-83DA-2ACAF5E1CDFA}
+ {DEEC5844-D609-4F35-BCF0-5B71C91C8133} = {4F5E2D21-17F6-4A42-B8FB-D03D82E24EC8}
+ {1346A7F1-4457-4BB4-A371-2C8E28BBD53E} = {4F5E2D21-17F6-4A42-B8FB-D03D82E24EC8}
+ {D597E3C6-1A50-4042-99FA-3E7CE28E4819} = {32F608E2-6406-4DCF-9105-E2A7CB7085CF}
+ {4B14D295-C09B-4C38-B880-7CC768E50585} = {32F608E2-6406-4DCF-9105-E2A7CB7085CF}
+ {928A23F3-2330-4F9F-B6A3-BFE01FE2A2DF} = {32F608E2-6406-4DCF-9105-E2A7CB7085CF}
+ {984CC812-9470-4A13-AFF9-CC44068D666C} = {32F608E2-6406-4DCF-9105-E2A7CB7085CF}
+ {517B6AE0-792B-4665-9376-5CA33E539181} = {29AC50BF-B4FB-450B-9386-0C5AD4B84226}
+ {67F3837C-C663-4668-9CD3-5E6C5ABD59B8} = {4F5E2D21-17F6-4A42-B8FB-D03D82E24EC8}
+ {57B8B73D-C3B5-4C42-869E-7B2F17D354AC} = {9AD757F5-E57A-459D-A0A7-E0675E045B84}
+ {9DB2F292-8034-4E06-89AD-98BBDA4306B9} = {32F608E2-6406-4DCF-9105-E2A7CB7085CF}
+ {CB9C96CE-125C-4A68-B6A1-C3FF1FBF93E1} = {4F5E2D21-17F6-4A42-B8FB-D03D82E24EC8}
+ {96D89208-4EB9-4451-BE73-8A9DF3D9D7B7} = {32F608E2-6406-4DCF-9105-E2A7CB7085CF}
+ {7D13BAC2-C6A4-416A-B07E-C169B199E52B} = {132FB9A4-613F-44CE-95D5-758D32D231DD}
+ {ABA078C4-F9BB-4924-8B2B-10FE0D2F5491} = {132FB9A4-613F-44CE-95D5-758D32D231DD}
+ {9222D2B8-63A4-4A36-A80E-BC34F27E0951} = {132FB9A4-613F-44CE-95D5-758D32D231DD}
+ {BD50B39A-EBC5-408F-9C5E-923A8EBAE473} = {132FB9A4-613F-44CE-95D5-758D32D231DD}
+ {DC1F3933-AC99-4887-8B09-E13C2B346D4F} = {DDDFBCAF-93DE-4868-8296-FD909EF32EF7}
+ {3B72465B-ACAE-43AE-9327-10F372FE5F80} = {29AC50BF-B4FB-450B-9386-0C5AD4B84226}
+ {115C31B9-C1B2-4B00-BB0E-EA36F105903E} = {D4D57221-71D6-4031-A6F4-EC66AF0929D9}
+ {EADD8100-B3AE-4A31-92C4-267A64A1C6EB} = {D4D57221-71D6-4031-A6F4-EC66AF0929D9}
+ {A34EBE01-25BF-4E69-A2DC-2288DC625541} = {D4D57221-71D6-4031-A6F4-EC66AF0929D9}
+ {00211725-2F89-4E2C-AC5A-38E5FF61BE67} = {D4D57221-71D6-4031-A6F4-EC66AF0929D9}
+ {1E238A01-B492-461F-BADE-415E8F9C5DFC} = {D4D57221-71D6-4031-A6F4-EC66AF0929D9}
+ {4DCD0420-1168-4B77-86DB-6196EE4BD491} = {D4D57221-71D6-4031-A6F4-EC66AF0929D9}
+ {CA10FACD-22AB-463F-A20E-379C212B0858} = {132FB9A4-613F-44CE-95D5-758D32D231DD}
+ {C7131F14-274F-4B55-ACA9-E81731AD012F} = {4F5E2D21-17F6-4A42-B8FB-D03D82E24EC8}
+ {67F9D3A8-F71E-4428-913F-C37AE82CDB24} = {29AC50BF-B4FB-450B-9386-0C5AD4B84226}
+ {5A2DADBC-9510-4DD1-BE58-01501F2DF65D} = {29AC50BF-B4FB-450B-9386-0C5AD4B84226}
+ {6E53FEB1-1100-46AE-8013-17BBA35CC197} = {5A2DADBC-9510-4DD1-BE58-01501F2DF65D}
+ {3E443AEF-3EC0-48C4-A524-7C6996339E1B} = {5A2DADBC-9510-4DD1-BE58-01501F2DF65D}
+ {39B3457F-01D8-43D0-8E84-D8C4F73CF48D} = {5A2DADBC-9510-4DD1-BE58-01501F2DF65D}
+ {483CDAE7-4353-4AB2-9C20-145A9F148FAD} = {5A2DADBC-9510-4DD1-BE58-01501F2DF65D}
+ {F3FDD7AC-8899-4E41-BFD7-EC83403E736D} = {29AC50BF-B4FB-450B-9386-0C5AD4B84226}
+ {1251646E-7FC6-425C-9464-A35DF1FC8E4D} = {4F5E2D21-17F6-4A42-B8FB-D03D82E24EC8}
+ {D3F9265A-30AC-43E8-A3EB-59BB76D2D0BF} = {29AC50BF-B4FB-450B-9386-0C5AD4B84226}
+ {3361D52C-2E74-433E-8285-9C9A5C485977} = {29AC50BF-B4FB-450B-9386-0C5AD4B84226}
+ {8CDEC974-E6BE-4424-BC77-0B87400A08AF} = {4F5E2D21-17F6-4A42-B8FB-D03D82E24EC8}
+ {B2927DF0-F98E-45C8-A917-27941B2B6838} = {4F5E2D21-17F6-4A42-B8FB-D03D82E24EC8}
+ {0F0DB9CC-EA65-429C-9363-38624BF8F49C} = {B2927DF0-F98E-45C8-A917-27941B2B6838}
+ {AC257966-9368-478A-9DF4-F0D28E320FE3} = {4F5E2D21-17F6-4A42-B8FB-D03D82E24EC8}
+ {00D8D049-FFAA-4759-8FC9-1ECA30777F72} = {29AC50BF-B4FB-450B-9386-0C5AD4B84226}
+ {65BC4888-CC59-428A-9B75-540CF1C09480} = {32F608E2-6406-4DCF-9105-E2A7CB7085CF}
+ {C4340D4E-BDDB-4053-BFBC-CF4F043FAE87} = {132FB9A4-613F-44CE-95D5-758D32D231DD}
+ {98637471-8E5C-4DDE-89CA-2EAA664FB0EF} = {9AD757F5-E57A-459D-A0A7-E0675E045B84}
+ {04D89A60-78EF-4A32-AE17-87E47E0233A5} = {132FB9A4-613F-44CE-95D5-758D32D231DD}
+ {2633AF57-F2CB-442A-AC19-F97BD8A06571} = {132FB9A4-613F-44CE-95D5-758D32D231DD}
+ {E5C4698D-FB57-4EEC-98C0-89E620F6920A} = {132FB9A4-613F-44CE-95D5-758D32D231DD}
+ {0A39A74B-6F7A-4D41-84F2-B0CCDCE899DF} = {D4D57221-71D6-4031-A6F4-EC66AF0929D9}
+ EndGlobalSection
+EndGlobal
diff --git a/Xamarin.Forms.sln.DotSettings b/Xamarin.Forms.sln.DotSettings
new file mode 100644
index 00000000..3500926c
--- /dev/null
+++ b/Xamarin.Forms.sln.DotSettings
@@ -0,0 +1,670 @@
+<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+ <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String>
+ <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">NEXT_LINE</s:String>
+ <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INITIALIZER_BRACES/@EntryValue">NEXT_LINE</s:String>
+ <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64>
+ <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64>
+ <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/OTHER_BRACES/@EntryValue">NEXT_LINE</s:String>
+ <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_IFELSE_BRACES_STYLE/@EntryValue">ONLY_FOR_MULTILINE</s:String>
+ <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FOR_BRACES_STYLE/@EntryValue">ONLY_FOR_MULTILINE</s:String>
+ <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FOREACH_BRACES_STYLE/@EntryValue">ONLY_FOR_MULTILINE</s:String>
+ <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_WHILE_BRACES_STYLE/@EntryValue">ONLY_FOR_MULTILINE</s:String>
+ <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_USING_BRACES_STYLE/@EntryValue">ONLY_FOR_MULTILINE</s:String>
+ <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FIXED_BRACES_STYLE/@EntryValue">ONLY_FOR_MULTILINE</s:String>
+ <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_AROUND_SINGLE_LINE_AUTO_PROPERTY/@EntryValue">1</s:Int64>
+ <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ELSE_ON_NEW_LINE/@EntryValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CATCH_ON_NEW_LINE/@EntryValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FINALLY_ON_NEW_LINE/@EntryValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
+ <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_LOCK_PARENTHESES/@EntryValue">False</s:Boolean>
+ <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_METHOD_CALL_PARENTHESES/@EntryValue">False</s:Boolean>
+ <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_EMPTY_METHOD_CALL_PARENTHESES/@EntryValue">False</s:Boolean>
+ <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_METHOD_PARENTHESES/@EntryValue">False</s:Boolean>
+ <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_EMPTY_METHOD_PARENTHESES/@EntryValue">False</s:Boolean>
+ <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AROUND_MULTIPLICATIVE_OP/@EntryValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_USING_PARENTHESES/@EntryValue">False</s:Boolean>
+ <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/STICK_COMMENT/@EntryValue">False</s:Boolean>
+ <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_MEMBERS/@EntryValue">None</s:String>
+ <s:String x:Key="/Default/CodeStyle/CSharpFileLayoutPatterns/Pattern/@EntryValue">&lt;?xml version="1.0" encoding="utf-16"?&gt;&#xD;
+&lt;Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"&gt;&#xD;
+ &lt;TypePattern DisplayName="COM interfaces or structs"&gt;&#xD;
+ &lt;TypePattern.Match&gt;&#xD;
+ &lt;Or&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Kind Is="Interface" /&gt;&#xD;
+ &lt;Or&gt;&#xD;
+ &lt;HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /&gt;&#xD;
+ &lt;HasAttribute Name="System.Runtime.InteropServices.ComImport" /&gt;&#xD;
+ &lt;/Or&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;Kind Is="Struct" /&gt;&#xD;
+ &lt;/Or&gt;&#xD;
+ &lt;/TypePattern.Match&gt;&#xD;
+ &lt;/TypePattern&gt;&#xD;
+ &lt;TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"&gt;&#xD;
+ &lt;TypePattern.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Kind Is="Class" /&gt;&#xD;
+ &lt;HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/TypePattern.Match&gt;&#xD;
+ &lt;Entry DisplayName="Setup/Teardown Methods"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Kind Is="Method" /&gt;&#xD;
+ &lt;Or&gt;&#xD;
+ &lt;HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /&gt;&#xD;
+ &lt;HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /&gt;&#xD;
+ &lt;HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /&gt;&#xD;
+ &lt;HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /&gt;&#xD;
+ &lt;/Or&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="All other members" /&gt;&#xD;
+ &lt;Entry Priority="100" DisplayName="Test Methods"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Kind Is="Method" /&gt;&#xD;
+ &lt;HasAttribute Name="NUnit.Framework.TestAttribute" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;/TypePattern&gt;&#xD;
+ &lt;TypePattern DisplayName="Default Pattern"&gt;&#xD;
+ &lt;Entry Priority="100" DisplayName="Public Delegates"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Public" /&gt;&#xD;
+ &lt;Kind Is="Delegate" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry Priority="100" DisplayName="Public Enums"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Public" /&gt;&#xD;
+ &lt;Kind Is="Enum" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Static Fields and Constants"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;Or&gt;&#xD;
+ &lt;Kind Is="Constant" /&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Kind Is="Field" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Or&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Kind Order="Constant Field" /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Fields"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Kind Is="Field" /&gt;&#xD;
+ &lt;Not&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;/Not&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Readonly /&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Constructors"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;Kind Is="Constructor" /&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Access /&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Properties, Indexers"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;Or&gt;&#xD;
+ &lt;Kind Is="Property" /&gt;&#xD;
+ &lt;Kind Is="Indexer" /&gt;&#xD;
+ &lt;/Or&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Access /&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry Priority="100" DisplayName="Interface Implementations"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Kind Is="Member" /&gt;&#xD;
+ &lt;ImplementsInterface /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;ImplementsInterface /&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="All other members"&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Access /&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Nested Types"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;Kind Is="Type" /&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;/TypePattern&gt;&#xD;
+ &lt;TypePattern DisplayName="Forms Pattern" RemoveRegions="All"&gt;&#xD;
+ &lt;Region Name="Statics"&gt;&#xD;
+ &lt;Entry DisplayName="Constructors"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Constructor" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Public Fields"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Field" /&gt;&#xD;
+ &lt;Access Is="Public" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Public Events"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Public" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Event" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Public Properties"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Public" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Property" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Public Methods"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Public" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Method" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Public Other"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Public" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Internal Fields"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Field" /&gt;&#xD;
+ &lt;Access Is="Internal" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Internal Events"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Internal" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Event" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Internal Properties"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Internal" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Property" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Internal Methods"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Internal" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Method" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Internal Other"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Internal" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Protected Fields"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Field" /&gt;&#xD;
+ &lt;Access Is="Protected" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Protected Events"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Protected" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Event" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Protected Properties"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Protected" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Property" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Protected Methods"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Protected" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Method" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Protected Other"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Protected" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Private Fields"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Field" /&gt;&#xD;
+ &lt;Access Is="Private" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Private Events"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Private" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Event" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Private Properties"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Private" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Property" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Private Methods"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Private" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;Kind Is="Method" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Private Other"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Private" /&gt;&#xD;
+ &lt;Static /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;/Region&gt;&#xD;
+ &lt;Entry DisplayName="Constructors"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Kind Is="Constructor" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Public Fields"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Kind Is="Field" /&gt;&#xD;
+ &lt;Access Is="Public" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Public Events"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Public" /&gt;&#xD;
+ &lt;Kind Is="Event" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Public Properties"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Public" /&gt;&#xD;
+ &lt;Kind Is="Property" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Public Methods"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Public" /&gt;&#xD;
+ &lt;Kind Is="Method" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Other"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Public" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Internal Fields"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Kind Is="Field" /&gt;&#xD;
+ &lt;Access Is="Internal" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Internal Events"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Internal" /&gt;&#xD;
+ &lt;Kind Is="Event" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Internal Properties"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Internal" /&gt;&#xD;
+ &lt;Kind Is="Property" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Internal Methods"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Internal" /&gt;&#xD;
+ &lt;Kind Is="Method" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Internal Other"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Internal" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Protected Fields"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Kind Is="Field" /&gt;&#xD;
+ &lt;Access Is="Protected" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Protected Events"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Protected" /&gt;&#xD;
+ &lt;Kind Is="Event" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Protected Properties"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Protected" /&gt;&#xD;
+ &lt;Kind Is="Property" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Protected Methods"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Protected" /&gt;&#xD;
+ &lt;Kind Is="Method" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Protected Other"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Protected" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Private Fields"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Kind Is="Field" /&gt;&#xD;
+ &lt;Access Is="Private" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Kind Is="Member" /&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Private Events"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Private" /&gt;&#xD;
+ &lt;Kind Is="Event" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Private Properties"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Private" /&gt;&#xD;
+ &lt;Kind Is="Property" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Private Methods"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Private" /&gt;&#xD;
+ &lt;Kind Is="Method" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Private Other"&gt;&#xD;
+ &lt;Entry.Match&gt;&#xD;
+ &lt;And&gt;&#xD;
+ &lt;Access Is="Private" /&gt;&#xD;
+ &lt;/And&gt;&#xD;
+ &lt;/Entry.Match&gt;&#xD;
+ &lt;Entry.SortBy&gt;&#xD;
+ &lt;Name /&gt;&#xD;
+ &lt;/Entry.SortBy&gt;&#xD;
+ &lt;/Entry&gt;&#xD;
+ &lt;Entry DisplayName="Other Members" /&gt;&#xD;
+ &lt;/TypePattern&gt;&#xD;
+&lt;/Patterns&gt;</s:String>
+ <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=WP8/@EntryIndexedValue">WP8</s:String>
+ <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=API/@EntryIndexedValue">API</s:String>
+ <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String>
+ <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="s_" Suffix="" Style="aaBb" /&gt;</s:String>
+ <s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForBuiltInTypes/@EntryValue">UseVarWhenEvident</s:String>
+ <s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForSimpleTypes/@EntryValue">UseVarWhenEvident</s:String>
+ <s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForOtherTypes/@EntryValue">UseVarWhenEvident</s:String>
+ <s:Boolean x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=64B48C7709A839499C5E49DBCE502A37/@KeyIndexDefined">True</s:Boolean>
+ <s:String x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=64B48C7709A839499C5E49DBCE502A37/AbsolutePath/@EntryValue">C:\Users\hartez\Documents\Xamarin\Xamarin.DotSettings</s:String>
+ <s:String x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=64B48C7709A839499C5E49DBCE502A37/RelativePath/@EntryValue">..\..\Xamarin.DotSettings</s:String>
+ <s:Boolean x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=File64B48C7709A839499C5E49DBCE502A37/@KeyIndexDefined">True</s:Boolean>
+ <s:Double x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=File64B48C7709A839499C5E49DBCE502A37/RelativePriority/@EntryValue">1</s:Double>
+ <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> \ No newline at end of file
diff --git a/docs/APIDocs.projitems b/docs/APIDocs.projitems
new file mode 100644
index 00000000..b26e0daa
--- /dev/null
+++ b/docs/APIDocs.projitems
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+ <HasSharedItems>true</HasSharedItems>
+ <SharedGUID>dc1f3933-ac99-4887-8b09-e13c2b346d4f</SharedGUID>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration">
+ <Import_RootNamespace>APIDocs</Import_RootNamespace>
+ </PropertyGroup>
+ <ItemGroup>
+ <Content Include="$(MSBuildThisFileDirectory)**\*.xml" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/docs/APIDocs.shproj b/docs/APIDocs.shproj
new file mode 100644
index 00000000..ec2d0a0a
--- /dev/null
+++ b/docs/APIDocs.shproj
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>dc1f3933-ac99-4887-8b09-e13c2b346d4f</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
+ <PropertyGroup />
+ <Import Project="APIDocs.projitems" Label="Shared" />
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
+</Project>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/DynamicResource.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/DynamicResource.xml
new file mode 100644
index 00000000..c520260d
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/DynamicResource.xml
@@ -0,0 +1,53 @@
+<Type Name="DynamicResource" FullName="Xamarin.Forms.Internals.DynamicResource">
+ <TypeSignature Language="C#" Value="public class DynamicResource" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit DynamicResource extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public DynamicResource (string key);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string key) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="key" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="key">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Key">
+ <MemberSignature Language="C#" Value="public string Key { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Key" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/IDataTemplate.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/IDataTemplate.xml
new file mode 100644
index 00000000..d7a21dbd
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/IDataTemplate.xml
@@ -0,0 +1,38 @@
+<Type Name="IDataTemplate" FullName="Xamarin.Forms.Internals.IDataTemplate">
+ <TypeSignature Language="C#" Value="public interface IDataTemplate" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IDataTemplate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="LoadTemplate">
+ <MemberSignature Language="C#" Value="public Func&lt;object&gt; LoadTemplate { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Func`1&lt;object&gt; LoadTemplate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Func&lt;System.Object&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/IDynamicResourceHandler.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/IDynamicResourceHandler.xml
new file mode 100644
index 00000000..a927827f
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/IDynamicResourceHandler.xml
@@ -0,0 +1,38 @@
+<Type Name="IDynamicResourceHandler" FullName="Xamarin.Forms.Internals.IDynamicResourceHandler">
+ <TypeSignature Language="C#" Value="public interface IDynamicResourceHandler" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IDynamicResourceHandler" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="SetDynamicResource">
+ <MemberSignature Language="C#" Value="public void SetDynamicResource (Xamarin.Forms.BindableProperty property, string key);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void SetDynamicResource(class Xamarin.Forms.BindableProperty property, string key) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="key" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="property">To be added.</param>
+ <param name="key">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/INameScope.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/INameScope.xml
new file mode 100644
index 00000000..bdd669ce
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/INameScope.xml
@@ -0,0 +1,103 @@
+<Type Name="INameScope" FullName="Xamarin.Forms.Internals.INameScope">
+ <TypeSignature Language="C#" Value="public interface INameScope" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract INameScope" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="FindByName">
+ <MemberSignature Language="C#" Value="public object FindByName (string name);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object FindByName(string name) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RegisterName">
+ <MemberSignature Language="C#" Value="public void RegisterName (string name, object scopedElement);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void RegisterName(string name, object scopedElement) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="scopedElement" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <param name="scopedElement">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RegisterName">
+ <MemberSignature Language="C#" Value="public void RegisterName (string name, object scopedElement, System.Xml.IXmlLineInfo xmlLineInfo);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void RegisterName(string name, object scopedElement, class System.Xml.IXmlLineInfo xmlLineInfo) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="scopedElement" Type="System.Object" />
+ <Parameter Name="xmlLineInfo" Type="System.Xml.IXmlLineInfo" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <param name="scopedElement">To be added.</param>
+ <param name="xmlLineInfo">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="UnregisterName">
+ <MemberSignature Language="C#" Value="public void UnregisterName (string name);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void UnregisterName(string name) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/NameScope.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/NameScope.xml
new file mode 100644
index 00000000..d4ccdf2d
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/NameScope.xml
@@ -0,0 +1,183 @@
+<Type Name="NameScope" FullName="Xamarin.Forms.Internals.NameScope">
+ <TypeSignature Language="C#" Value="public class NameScope : Xamarin.Forms.Internals.INameScope" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit NameScope extends System.Object implements class Xamarin.Forms.Internals.INameScope" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Internals.INameScope</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public NameScope ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetNameScope">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Internals.INameScope GetNameScope (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.Internals.INameScope GetNameScope(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Internals.INameScope</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="NameScopeProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty NameScopeProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty NameScopeProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetNameScope">
+ <MemberSignature Language="C#" Value="public static void SetNameScope (Xamarin.Forms.BindableObject bindable, Xamarin.Forms.Internals.INameScope value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetNameScope(class Xamarin.Forms.BindableObject bindable, class Xamarin.Forms.Internals.INameScope value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="value" Type="Xamarin.Forms.Internals.INameScope" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Internals.INameScope.FindByName">
+ <MemberSignature Language="C#" Value="object INameScope.FindByName (string name);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.Internals.INameScope.FindByName(string name) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Internals.INameScope.RegisterName">
+ <MemberSignature Language="C#" Value="void INameScope.RegisterName (string name, object scopedElement);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.Internals.INameScope.RegisterName(string name, object scopedElement) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="scopedElement" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <param name="scopedElement">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Internals.INameScope.RegisterName">
+ <MemberSignature Language="C#" Value="void INameScope.RegisterName (string name, object scopedElement, System.Xml.IXmlLineInfo xmlLineInfo);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.Internals.INameScope.RegisterName(string name, object scopedElement, class System.Xml.IXmlLineInfo xmlLineInfo) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="scopedElement" Type="System.Object" />
+ <Parameter Name="xmlLineInfo" Type="System.Xml.IXmlLineInfo" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <param name="scopedElement">To be added.</param>
+ <param name="xmlLineInfo">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Internals.INameScope.UnregisterName">
+ <MemberSignature Language="C#" Value="void INameScope.UnregisterName (string name);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.Internals.INameScope.UnregisterName(string name) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IMarkupExtension.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IMarkupExtension.xml
new file mode 100644
index 00000000..607cbe69
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IMarkupExtension.xml
@@ -0,0 +1,72 @@
+<Type Name="IMarkupExtension" FullName="Xamarin.Forms.Xaml.IMarkupExtension">
+ <TypeSignature Language="C#" Value="public interface IMarkupExtension" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IMarkupExtension" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Defines the interface for Xamarin.Forms XAML markup extensions.</summary>
+ <remarks>
+ <para>
+ Types implementing this interface can be used as custom XAML markup extension.
+ </para>
+ <example>
+ The following example shows declaration of a custom markup extension.
+ <code lang="C#"><![CDATA[
+public class ColorMarkup : IMarkupExtension
+{
+ public int R { get; set; }
+ public int G { get; set; }
+ public int B { get; set; }
+
+ public object ProvideValue (IServiceProvider serviceProvider)
+ {
+ return Color.FromRgb (R, G, B);
+ }
+}
+ ]]></code></example>
+ <example>
+ The markup extension can be used directly in XAML
+ <code lang="XAML"><![CDATA[
+&lt;Label TextColor="{localns:ColorMarkup R=100, G=80, B=60}"/&gt;
+ ]]></code></example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="ProvideValue">
+ <MemberSignature Language="C#" Value="public object ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>Returns the object created from the markup extension.</summary>
+ <returns>The object</returns>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IMarkupExtension`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IMarkupExtension`1.xml
new file mode 100644
index 00000000..c4f07f8d
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IMarkupExtension`1.xml
@@ -0,0 +1,49 @@
+<Type Name="IMarkupExtension&lt;T&gt;" FullName="Xamarin.Forms.Xaml.IMarkupExtension&lt;T&gt;">
+ <TypeSignature Language="C#" Value="public interface IMarkupExtension&lt;out T&gt; : Xamarin.Forms.Xaml.IMarkupExtension" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IMarkupExtension`1&lt;+ T&gt; implements class Xamarin.Forms.Xaml.IMarkupExtension" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="T">
+ <Constraints>
+ <ParameterAttribute>Covariant</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IMarkupExtension</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="ProvideValue">
+ <MemberSignature Language="C#" Value="public T ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance !T ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IProvideValueTarget.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IProvideValueTarget.xml
new file mode 100644
index 00000000..5e4d1566
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IProvideValueTarget.xml
@@ -0,0 +1,65 @@
+<Type Name="IProvideValueTarget" FullName="Xamarin.Forms.Xaml.IProvideValueTarget">
+ <TypeSignature Language="C#" Value="public interface IProvideValueTarget" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IProvideValueTarget" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Interface that defines a target and property to which a value is provided.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="TargetObject">
+ <MemberSignature Language="C#" Value="public object TargetObject { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object TargetObject" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the target object.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TargetProperty">
+ <MemberSignature Language="C#" Value="public object TargetProperty { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object TargetProperty" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets an object that identifies the target property.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IRootObjectProvider.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IRootObjectProvider.xml
new file mode 100644
index 00000000..1ffd8cac
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IRootObjectProvider.xml
@@ -0,0 +1,43 @@
+<Type Name="IRootObjectProvider" FullName="Xamarin.Forms.Xaml.IRootObjectProvider">
+ <TypeSignature Language="C#" Value="public interface IRootObjectProvider" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IRootObjectProvider" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Internal use only.</summary>
+ <remarks>This interface may be removed or made private in the future.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="RootObject">
+ <MemberSignature Language="C#" Value="public object RootObject { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object RootObject" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Internal use only.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IValueProvider.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IValueProvider.xml
new file mode 100644
index 00000000..27fe2805
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IValueProvider.xml
@@ -0,0 +1,37 @@
+<Type Name="IValueProvider" FullName="Xamarin.Forms.Xaml.IValueProvider">
+ <TypeSignature Language="C#" Value="public interface IValueProvider" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IValueProvider" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="ProvideValue">
+ <MemberSignature Language="C#" Value="public object ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IXamlTypeResolver.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IXamlTypeResolver.xml
new file mode 100644
index 00000000..54fc03c8
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IXamlTypeResolver.xml
@@ -0,0 +1,97 @@
+<Type Name="IXamlTypeResolver" FullName="Xamarin.Forms.Xaml.IXamlTypeResolver">
+ <TypeSignature Language="C#" Value="public interface IXamlTypeResolver" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IXamlTypeResolver" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Interface defining the ability to resolve a qualified type name into a Type.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Resolve">
+ <MemberSignature Language="C#" Value="public Type Resolve (string qualifiedTypeName);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Type Resolve(string qualifiedTypeName) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Type</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="qualifiedTypeName" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="qualifiedTypeName">To be added.</param>
+ <summary>Returns the resolved type.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Resolve">
+ <MemberSignature Language="C#" Value="public Type Resolve (string qualifiedTypeName, IServiceProvider serviceProvider = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Type Resolve(string qualifiedTypeName, class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Type</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="qualifiedTypeName" Type="System.String" />
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="qualifiedTypeName">To be added.</param>
+ <param name="serviceProvider">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TryResolve">
+ <MemberSignature Language="C#" Value="public bool TryResolve (string qualifiedTypeName, out Type type);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance bool TryResolve(string qualifiedTypeName, class System.Type type) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="qualifiedTypeName" Type="System.String" />
+ <Parameter Name="type" Type="System.Type&amp;" RefType="out" />
+ </Parameters>
+ <Docs>
+ <param name="qualifiedTypeName">To be added.</param>
+ <param name="type">To be added.</param>
+ <summary>Tries to resolve a type name, putting the type value in <paramref name="type" />, and returns a Boolean value that indicates whether the operation succeeded.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IXmlLineInfoProvider.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IXmlLineInfoProvider.xml
new file mode 100644
index 00000000..eaacbe51
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/IXmlLineInfoProvider.xml
@@ -0,0 +1,33 @@
+<Type Name="IXmlLineInfoProvider" FullName="Xamarin.Forms.Xaml.IXmlLineInfoProvider">
+ <TypeSignature Language="C#" Value="public interface IXmlLineInfoProvider" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IXmlLineInfoProvider" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="XmlLineInfo">
+ <MemberSignature Language="C#" Value="public System.Xml.IXmlLineInfo XmlLineInfo { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Xml.IXmlLineInfo XmlLineInfo" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Xml.IXmlLineInfo</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/XamlParseException.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/XamlParseException.xml
new file mode 100644
index 00000000..0ea33b8e
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/XamlParseException.xml
@@ -0,0 +1,59 @@
+<Type Name="XamlParseException" FullName="Xamarin.Forms.Xaml.XamlParseException">
+ <TypeSignature Language="C#" Value="public class XamlParseException : Exception" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit XamlParseException extends System.Exception" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Exception</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Exception that is thrown when the XAML parser encounters an error.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public XamlParseException (string message, System.Xml.IXmlLineInfo xmlInfo);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string message, class System.Xml.IXmlLineInfo xmlInfo) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="message" Type="System.String" />
+ <Parameter Name="xmlInfo" Type="System.Xml.IXmlLineInfo" />
+ </Parameters>
+ <Docs>
+ <param name="message">To be added.</param>
+ <param name="xmlInfo">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="XmlInfo">
+ <MemberSignature Language="C#" Value="public System.Xml.IXmlLineInfo XmlInfo { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Xml.IXmlLineInfo XmlInfo" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Xml.IXmlLineInfo</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Information about the condition that caused the exception to be thrown.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/XmlLineInfo.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/XmlLineInfo.xml
new file mode 100644
index 00000000..eac45214
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Xaml/XmlLineInfo.xml
@@ -0,0 +1,108 @@
+<Type Name="XmlLineInfo" FullName="Xamarin.Forms.Xaml.XmlLineInfo">
+ <TypeSignature Language="C#" Value="public class XmlLineInfo : System.Xml.IXmlLineInfo" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit XmlLineInfo extends System.Object implements class System.Xml.IXmlLineInfo" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.Xml.IXmlLineInfo</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public XmlLineInfo ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public XmlLineInfo (int linenumber, int lineposition);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(int32 linenumber, int32 lineposition) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="linenumber" Type="System.Int32" />
+ <Parameter Name="lineposition" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="linenumber">To be added.</param>
+ <param name="lineposition">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasLineInfo">
+ <MemberSignature Language="C#" Value="public bool HasLineInfo ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance bool HasLineInfo() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LineNumber">
+ <MemberSignature Language="C#" Value="public int LineNumber { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 LineNumber" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LinePosition">
+ <MemberSignature Language="C#" Value="public int LinePosition { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 LinePosition" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/AbsoluteLayout+IAbsoluteList`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/AbsoluteLayout+IAbsoluteList`1.xml
new file mode 100644
index 00000000..606e3c91
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/AbsoluteLayout+IAbsoluteList`1.xml
@@ -0,0 +1,98 @@
+<Type Name="AbsoluteLayout+IAbsoluteList&lt;T&gt;" FullName="Xamarin.Forms.AbsoluteLayout+IAbsoluteList&lt;T&gt;">
+ <TypeSignature Language="C#" Value="public interface AbsoluteLayout.IAbsoluteList&lt;T&gt; : System.Collections.Generic.ICollection&lt;T&gt;, System.Collections.Generic.IEnumerable&lt;T&gt;, System.Collections.Generic.IList&lt;T&gt; where T : View" />
+ <TypeSignature Language="ILAsm" Value=".class nested public interface auto ansi abstract AbsoluteLayout/IAbsoluteList`1&lt;(class Xamarin.Forms.View) T&gt; implements class System.Collections.Generic.ICollection`1&lt;!T&gt;, class System.Collections.Generic.IEnumerable`1&lt;!T&gt;, class System.Collections.Generic.IList`1&lt;!T&gt;, class System.Collections.IEnumerable" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="T">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.ICollection&lt;T&gt;</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.IEnumerable&lt;T&gt;</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.IList&lt;T&gt;</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <typeparam name="T">The type of elements in the absolute layout.</typeparam>
+ <summary>List interface with overloads for adding elements to an absolute layout.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (Xamarin.Forms.View view, Xamarin.Forms.Point position);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Add(class Xamarin.Forms.View view, valuetype Xamarin.Forms.Point position) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.View" />
+ <Parameter Name="position" Type="Xamarin.Forms.Point" />
+ </Parameters>
+ <Docs>
+ <param name="view">The view to add.</param>
+ <param name="position">The location at which to position the view.</param>
+ <summary>Adds a view to the list at the specified location with automatic sizing.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (Xamarin.Forms.View view, Xamarin.Forms.Rectangle bounds, Xamarin.Forms.AbsoluteLayoutFlags flags = Xamarin.Forms.AbsoluteLayoutFlags.None);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Add(class Xamarin.Forms.View view, valuetype Xamarin.Forms.Rectangle bounds, valuetype Xamarin.Forms.AbsoluteLayoutFlags flags) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.View" />
+ <Parameter Name="bounds" Type="Xamarin.Forms.Rectangle" />
+ <Parameter Name="flags" Type="Xamarin.Forms.AbsoluteLayoutFlags" />
+ </Parameters>
+ <Docs>
+ <param name="view">The view to add.</param>
+ <param name="bounds">The bounds to layout the view with.</param>
+ <param name="flags">The flags to interpret bounds with.</param>
+ <summary>Adds a view to the list with the specified bounds and flags.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/AbsoluteLayout.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/AbsoluteLayout.xml
new file mode 100644
index 00000000..a3a9fb4c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/AbsoluteLayout.xml
@@ -0,0 +1,653 @@
+<Type Name="AbsoluteLayout" FullName="Xamarin.Forms.AbsoluteLayout">
+ <TypeSignature Language="C#" Value="public class AbsoluteLayout : Xamarin.Forms.Layout&lt;Xamarin.Forms.View&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit AbsoluteLayout extends Xamarin.Forms.Layout`1&lt;class Xamarin.Forms.View&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Layout&lt;Xamarin.Forms.View&gt;</BaseTypeName>
+ <BaseTypeArguments>
+ <BaseTypeArgument TypeParamName="T">Xamarin.Forms.View</BaseTypeArgument>
+ </BaseTypeArguments>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Positions child elements at absolute positions.</summary>
+ <remarks>
+ <para>Application developers can control the placement of child elements by providing proportional coordinates, device coordinates, or a combination of both, depending on the <see cref="T:Xamarin.Forms.AbsoluteLayoutFlags" /> values that are passed to <see cref="M:Xamarin.Forms.AbsoluteLayout.SetLayoutFlags" /> method. When one of the proportional <see cref="T:Xamarin.Forms.AbsoluteLayoutFlags" /> enumeration values is provided, the corresponding X, or Y arguments that range between 0.0 and 1.0 will always cause the child to be displayed completely on screen. That is, you do not need to subtract or add the height or width of a child in order to display it flush with the left, right, top, or bottom of the <see cref="T:Xamarin.Forms.AbsoluteLayout" />. For width, height, X, or Y values that are not specified proportionally, application developers use device-dependent units to locate and size the child element.</para>
+ <example>
+ <para>The following example shows how to use an <see cref="T:Xamarin.Forms.AbsoluteLayout" /> with proportional position arguments.</para>
+ <code lang="C#"><![CDATA[
+using System;
+using Xamarin.Forms;
+
+namespace AbsoluteLayoutDemo
+{
+ class AbsoluteLayoutDemoPage : ContentPage
+ {
+ //Label topLeftText;
+ Label topLeftLabel, centerLabel, bottomRightLabel;
+
+ public AbsoluteLayoutDemoPage ()
+ {
+ Label header = new Label {
+ Text = "AbsoluteLayout Demo",
+ Font = Font.SystemFontOfSize (NamedSize.Large),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ AbsoluteLayout simpleLayout = new AbsoluteLayout {
+ BackgroundColor = Color.Blue.WithLuminosity (0.9),
+ VerticalOptions = LayoutOptions.FillAndExpand
+ };
+
+ topLeftLabel = new Label {
+ Text = "Top Left",
+ TextColor = Color.Black
+ };
+
+ centerLabel = new Label {
+ Text = "Centered",
+ TextColor = Color.Black
+ };
+
+ bottomRightLabel = new Label {
+ Text = "Bottom Right",
+ TextColor = Color.Black
+ };
+
+
+ // PositionProportional flag maps the range (0.0, 1.0) to
+ // the range "flush [left|top]" to "flush [right|bottom]"
+ AbsoluteLayout.SetLayoutFlags (bottomRightLabel,
+ AbsoluteLayoutFlags.PositionProportional);
+
+ AbsoluteLayout.SetLayoutBounds (topLeftLabel,
+ new Rectangle (0f,
+ 0f, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
+
+ AbsoluteLayout.SetLayoutFlags (centerLabel,
+ AbsoluteLayoutFlags.PositionProportional);
+
+ AbsoluteLayout.SetLayoutBounds (centerLabel,
+ new Rectangle (0.5,
+ 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
+
+ AbsoluteLayout.SetLayoutFlags (bottomRightLabel,
+ AbsoluteLayoutFlags.PositionProportional);
+
+ AbsoluteLayout.SetLayoutBounds (bottomRightLabel,
+ new Rectangle (1f,
+ 1f, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
+
+ simpleLayout.Children.Add (topLeftLabel);
+ simpleLayout.Children.Add (centerLabel);
+ simpleLayout.Children.Add (bottomRightLabel);
+
+ // Accomodate iPhone status bar.
+ this.Padding =
+ new Thickness (10, Device.OnPlatform (20, 0, 0), 10, 5);
+
+ // Build the page.
+ this.Content = new StackLayout {
+ Children = {
+ header,
+ simpleLayout
+ }
+ };
+
+ }
+ }
+}
+]]></code>
+ <para>The code sample below shows how to place two labels by specifying device-dependent units.</para>
+ <code lang="C#"><![CDATA[
+using System;
+using Xamarin.Forms;
+
+namespace AbsoluteLayoutDemo
+{
+ public class AbsoluteLayoutDeviceUnits : ContentPage
+ {
+ Label topLeftText, middleText;
+
+ public AbsoluteLayoutDeviceUnits ()
+ {
+ AbsoluteLayout simpleLayout = new AbsoluteLayout {
+
+ BackgroundColor = Color.Blue.WithLuminosity (0.9),
+ VerticalOptions = LayoutOptions.FillAndExpand
+ };
+
+ Label header = new Label {
+ Text = "Device Units Demo",
+ TextColor = Color.Black,
+ Font = Font.SystemFontOfSize (NamedSize.Large)
+ };
+
+ topLeftText = new Label {
+ Text = "Left",
+ TextColor = Color.Black
+ };
+
+ AbsoluteLayout.SetLayoutFlags (topLeftText,
+ AbsoluteLayoutFlags.None);
+
+ AbsoluteLayout.SetLayoutBounds (topLeftText,
+ new Rectangle (0f, 0f, 100f, 50f));
+
+ middleText = new Label {
+ Text = "Device-dependent location",
+ TextColor = Color.Black
+ };
+
+ AbsoluteLayout.SetLayoutFlags (middleText,
+ AbsoluteLayoutFlags.None);
+
+ AbsoluteLayout.SetLayoutBounds (middleText,
+ new Rectangle (100f, 200f, 200f, 50f));
+
+ simpleLayout.Children.Add (topLeftText);
+ simpleLayout.Children.Add (middleText);
+
+ // Accomodate iPhone status bar.
+ this.Padding = new Thickness (10, Device.OnPlatform (20, 0, 0), 10, 5);
+
+ this.Content = new StackLayout {
+ Children = {
+ header,
+ simpleLayout
+ }
+ };
+ }
+ }
+}]]></code>
+ </example>
+ <para>The following image shows the AbsoluteLayout demo from the <format type="text/html"><a href="http://developer.xamarin.com/samples/tag/Xamarin.Forms/" target="_blank">FormsGallery</a></format> sample.
+</para>
+ <para>
+ <img href="AbsoluteLayout.TripleScreenShot.png" />
+ </para>
+ <example>
+ <para>XAML for Xamarin.Forms supports the following attached properties for the <see cref="T:Xamarin.Forms.AbsoluteLayout" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Attached Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>AbsoluteLayout.LayoutBounds</term>
+ <description>
+ <para>A comma-separated list—possibly with spaces—of four values that specify the bounding rectangle's position and dimensions. The first two values in the list must represent numbers. The latter two values may each either be numbers, or the string "AutoSize". The <c>AbsoluteLayout.LayoutFlags</c> attached property determines how the values in the list are interpreted to create the bounding rectangle.</para>
+ </description>
+ </item>
+ <item>
+ <term>AbsoluteLayout.LayoutFlags</term>
+ <description>
+ <para>
+ <see cref="T:Xamarin.Forms.AbsoluteLayoutFlags" /> enumeration value names: <c>All</c>, <c>None</c>, <c>HeightProportional</c>, <c>WidthProportional</c>, <c>SizeProportional</c>, <c>XProportional</c>, <c>YProportional</c>, or <c>PositionProportional</c>. Application developers can combine any of these flags together by supplying a comma-separated list. </para>
+ </description>
+ </item>
+ </list>
+ <para>Application developers can use XAML to lay out elements with the <see cref="T:Xamarin.Forms.AbsoluteLayout" /> class. The example below places a blue <see cref="T:Xamarin.Forms.BoxView" /> inside an <see cref="T:Xamarin.Forms.AbsoluteLayout" />: </para>
+ <code lang="XAML"><![CDATA[<AbsoluteLayout VerticalOptions="FillAndExpand"
+ HorizontalOptions="FillAndExpand">
+ <BoxView AbsoluteLayout.LayoutBounds="0.25, 0.25, 0.5, 0.5"
+ Color="Blue"
+ AbsoluteLayout.LayoutFlags="All" />
+</AbsoluteLayout>
+]]></code>
+ </example>
+ <para>The <see cref="T:Xamarin.Forms.AbsoluteLayout" /> class can lay its child elements out in proportional units, device units, or a combination of both. Application developers should remember the following points when specifying a <see cref="T:Xamarin.Forms.Rectangle" /> structure that will define the layout bounds of a child element:
+ <list type="bullet"><item><term>For elements whose height and width fit on the screen, proportional position dimensions in the range [0,1] represent elements that are completely on the screen, regardless of whether the height, width, or both are specified in device or proportional units.</term></item><item><term>The above point means that, to specify an element in the lower right hand corner of the screen and that is half as wide and half as all as the screen, with a <see cref="T:Xamarin.Forms.AbsoluteLayoutFlags" /> value of <c>All</c>, the application developer would specify "1.0, 1.0, 0.5, 0.5".</term></item><item><term>The app developer can inadvertently cause child elements for which one or both size dimensions were specified proportionally to be displayed partially off the screen, or hidden altogether, by specifying device-unit positions that do not leave enough room for the calculated size of the child.</term></item><item><term>Each part of the bounding <see cref="T:Xamarin.Forms.Rectangle" /> structure is interpreted according to the <see cref="T:Xamarin.Forms.AbsoluteLayoutFlags" /> value that controls it. A given rectangle might, for example, have an X-coordinate that is in device units, a Y-coordinate that is in proportional units, a height that is in proportional units, and a width that is in device units, or any other combination of device and proportional units. </term></item><item><term>Rectangles that, when interpreted by using the current <see cref="T:Xamarin.Forms.AbsoluteLayoutFlags" /> set on the child, represent bounding boxes that are partially or wholly off-screen—for example, by having a width that is larger than the screen width—may give unexpected results.</term></item></list></para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public AbsoluteLayout ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the AbsoluteLayout class.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AutoSize">
+ <MemberSignature Language="C#" Value="public static double AutoSize { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property float64 AutoSize" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A value that indicates that the width or height of the child should be sized to that childs native size.</summary>
+ <value>
+ </value>
+ <remarks>
+ <para>Application developers can set the width or height of the <see cref="P:Xamarin.Forms.VisualElement.Bounds" /> property to <see cref="P:Xamarin.Forms.AboluteLayout.AutoSize" /> on a visual element when adding to the layout to cause that element to be measured during the layout pass and sized appropriately.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Children">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.AbsoluteLayout.IAbsoluteList&lt;Xamarin.Forms.View&gt; Children { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.AbsoluteLayout/IAbsoluteList`1&lt;class Xamarin.Forms.View&gt; Children" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.AbsoluteLayout+IAbsoluteList&lt;Xamarin.Forms.View&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the collection of child elements of the AbsoluteLayout.</summary>
+ <value>The collection of child elements.</value>
+ <remarks>
+ <para>Application developers can use implicit collection syntax in XAML to add items to this collection, because this property is the ContentPropertyAttribute for the AbsoluteLayout class.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetLayoutBounds">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Rectangle GetLayoutBounds (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Rectangle GetLayoutBounds(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.BoundsTypeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Rectangle</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">A visual element.</param>
+ <summary>Gets the layout bounds of <paramref name="bindable" />.</summary>
+ <returns>The layout bounds of the object.</returns>
+ <remarks>
+ <para>This method supports the <c>AbsoluteLayout.LayoutBounds</c> XAML attached property. In XAML, Application developers can specify a comma-separated list—possibly with spaces—of four values that specify the bounding rectangle's position and dimensions. The first two values in the list must represent numbers. The latter two values may each either be numbers, or the string "AutoSize". The <c>AbsoluteLayout.LayoutFlags</c> attached property determines how the values in the list are interpreted to create the bounding rectangle.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetLayoutFlags">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.AbsoluteLayoutFlags GetLayoutFlags (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.AbsoluteLayoutFlags GetLayoutFlags(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.AbsoluteLayoutFlags</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">A visual element.</param>
+ <summary>Gets the layout flags that were specified when <paramref name="bindable" /> was added to an <see cref="T:Xamarin.Forms.AbsoluteLayout" />.</summary>
+ <returns>The layout flags of the object.</returns>
+ <remarks>
+ <para>This method supports the <c>AbsoluteLayout.LayoutFlags</c> XAML attached property. In XAML, Application developers can specify the following <see cref="T:Xamarin.Forms.AbsoluteLayoutFlags" /> enumeration value names for the value of this property on the children of a <see cref="T:Xamarin.Forms.AbsoluteLayout" />:</para>
+ <list type="bullet">
+ <item>
+ <term>
+ <c>All</c>
+ </term>
+ </item>
+ <item>
+ <term>
+ <c>None</c>
+ </term>
+ </item>
+ <item>
+ <term>
+ <c>HeightProportional</c>
+ </term>
+ </item>
+ <item>
+ <term>
+ <c>WidthProportional</c>
+ </term>
+ </item>
+ <item>
+ <term>
+ <c>SizeProportional</c>
+ </term>
+ </item>
+ <item>
+ <term>
+ <c>XProportional</c>
+ </term>
+ </item>
+ <item>
+ <term>
+ <c>YProportional</c>
+ </term>
+ </item>
+ <item>
+ <term>
+ <c>PositionProportional</c>
+ </term>
+ </item>
+ </list>
+ <para>Application developers can combine any of the above values by supplying a comma-separated list.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutBoundsProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty LayoutBoundsProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty LayoutBoundsProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Implements the attached property that represents the layout bounds of child elements. Bindable at run time with the string "LayoutBounds". See Remarks.</summary>
+ <remarks>The interface for this property is defined by the <see cref="M:Xamarin.Forms.AbsoluteLayout.GetLayoutBounds" /> and <see cref="M:Xamarin.Forms.AbsoluteLayout.SetLayoutBounds" /> methods.
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutChildren">
+ <MemberSignature Language="C#" Value="protected override void LayoutChildren (double x, double y, double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void LayoutChildren(float64 x, float64 y, float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">The X coordinate of the region that contains the child elements and that is used to calulate proportional values.</param>
+ <param name="y">The Y coordinate of the region that contains the child elements and that is used to calulate proportional values.</param>
+ <param name="width">The width of the the region that contains the child elements and that is used to calulate proportional values.</param>
+ <param name="height">The height of the region that contains the child elements and that is used to calulate proportional values.</param>
+ <summary>Positions and sizes the children of an AbsoluteLayout.</summary>
+ <remarks>
+ <para>Application developers can override <see cref="M:Xamarin.Forms.AbsoluteLayout.LayoutChildren" /> to change the default behavior of <see cref="T:Xamarin.Forms.AbsoluteLayout" />. When doing so, it is recommended to call the base <see cref="M:Xamarin.Forms.AbsoluteLayout.LayoutChildren" /> method and then modify the dimensions and locations of the children directly.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutFlagsProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty LayoutFlagsProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty LayoutFlagsProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Implements the attached property that contains the <see cref="T:Xamarin.Forms.AbsoluteLayoutFlags" /> values for child elements.</summary>
+ <remarks>The interface for this property is defined by the <see cref="M:Xamarin.Forms.AbsoluteLayout.GetLayoutFlags" /> and <see cref="M:Xamarin.Forms.AbsoluteLayout.SetLayoutFlags" /> methods.
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnChildAdded">
+ <MemberSignature Language="C#" Value="protected override void OnChildAdded (Xamarin.Forms.Element child);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnChildAdded(class Xamarin.Forms.Element child) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="child" Type="Xamarin.Forms.Element" />
+ </Parameters>
+ <Docs>
+ <param name="child">The element that was added to the children.</param>
+ <summary>Called when a child is added to the <see cref="T:Xamarin.Forms.AbsoluteLayout" />.</summary>
+ <remarks>
+ <para>Application developers can override <see cref="M:Xamarin.Forms.AbsoluteLayout.OnChildAdded" /> to change the default behavior thata is triggered when a child is added. When doing so, it is recommended to call the base <see cref="M:Xamarin.Forms.AbsoluteLayout.OnChildAdded" /> method and then add additional logic.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnChildRemoved">
+ <MemberSignature Language="C#" Value="protected override void OnChildRemoved (Xamarin.Forms.Element child);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnChildRemoved(class Xamarin.Forms.Element child) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="child" Type="Xamarin.Forms.Element" />
+ </Parameters>
+ <Docs>
+ <param name="child">The element that was removed from the children.</param>
+ <summary>Called when a child is removed from the <see cref="T:Xamarin.Forms.AbsoluteLayout" />.</summary>
+ <remarks>
+ <para>Application developers can override <see cref="M:Xamarin.Forms.AbsoluteLayout.OnChildRemoved" /> to change the default behavior thata is triggered when a child is removed. When doing so, it is recommended to call the base <see cref="M:Xamarin.Forms.AbsoluteLayout.OnChildRemoved" /> method and then add additional logic.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeRequest">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance valuetype Xamarin.Forms.SizeRequest OnSizeRequest(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use OnMeasure")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">The available width for the AbsoluteLayout to use.</param>
+ <param name="heightConstraint">The available height for the AbsoluteLayout to use.</param>
+ <summary>Called during the measure pass of a layout cycle to get the desired size of the AbsoluteLayout.</summary>
+ <returns>A <see cref="T:Xamarin.Forms.SizeRequest" /> which contains the desired size of the AbsoluteLayout.</returns>
+ <remarks>
+ <para>Application developers can override <see cref="M:Xamarin.Forms.AbsoluteLayout.OnSizeRequest" /> to change the default behavior thata is triggered when a child is removed. When doing so, it is recommended to call the base <see cref="M:Xamarin.Forms.AbsoluteLayout.OnSizeRequest" /> method and then modify the dimensions and locations of the children directly.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetLayoutBounds">
+ <MemberSignature Language="C#" Value="public static void SetLayoutBounds (Xamarin.Forms.BindableObject bindable, Xamarin.Forms.Rectangle bounds);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetLayoutBounds(class Xamarin.Forms.BindableObject bindable, valuetype Xamarin.Forms.Rectangle bounds) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="bounds" Type="Xamarin.Forms.Rectangle" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">The view to delimit by <paramref name="bounds" />.</param>
+ <param name="bounds">A rectangle that represents the desired size and shape of <paramref name="bindable" />.</param>
+ <summary>Sets the layout bounds of a view that will be used to size it when it is layed out.</summary>
+ <remarks>
+ <para>This method supports the <c>AbsoluteLayout.LayoutBounds</c> XAML attached property. In XAML, Application developers can specify a comma-separated list—possibly with spaces—of four values that specify the bounding rectangle's position and dimensions. The first two values in the list must represent numbers. The latter two values may each either be numbers, or the string "AutoSize". The <c>AbsoluteLayout.LayoutFlags</c> attached property determines how the values in the list are interpreted to create the bounding rectangle. Application developers can call this method to update the layout of a view after it is added.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetLayoutFlags">
+ <MemberSignature Language="C#" Value="public static void SetLayoutFlags (Xamarin.Forms.BindableObject bindable, Xamarin.Forms.AbsoluteLayoutFlags flags);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetLayoutFlags(class Xamarin.Forms.BindableObject bindable, valuetype Xamarin.Forms.AbsoluteLayoutFlags flags) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="flags" Type="Xamarin.Forms.AbsoluteLayoutFlags" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">The view on which to set the layout flags.</param>
+ <param name="flags">A <see cref="T:Xamarin.Forms.AbsoluteLayoutFlags" /> that describes the how to interpret the layout bounds for <paramref name="bindable" />.</param>
+ <summary>Sets the layout flags of a view that will be used to interpret the layout bounds set on it when it is added to the layout.</summary>
+ <remarks>
+ <para>This method supports the <c>AbsoluteLayout.LayoutFlags</c> XAML attached property. In XAML, Application developers can specify the following <see cref="T:Xamarin.Forms.AbsoluteLayoutFlags" /> enumeration value names for the value of this property on the children of a <see cref="T:Xamarin.Forms.AbsoluteLayout" />:</para>
+ <list type="bullet">
+ <item>
+ <term>
+ <c>All</c>
+ </term>
+ </item>
+ <item>
+ <term>
+ <c>None</c>
+ </term>
+ </item>
+ <item>
+ <term>
+ <c>HeightProportional</c>
+ </term>
+ </item>
+ <item>
+ <term>
+ <c>WidthProportional</c>
+ </term>
+ </item>
+ <item>
+ <term>
+ <c>SizeProportional</c>
+ </term>
+ </item>
+ <item>
+ <term>
+ <c>XProportional</c>
+ </term>
+ </item>
+ <item>
+ <term>
+ <c>YProportional</c>
+ </term>
+ </item>
+ <item>
+ <term>
+ <c>PositionProportional</c>
+ </term>
+ </item>
+ </list>
+ <para>Application developers can combine any of the above values by supplying a comma-separated list. Application developers can call this method to update the layout flags of a view after it is added.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/AbsoluteLayoutFlags.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/AbsoluteLayoutFlags.xml
new file mode 100644
index 00000000..9647157d
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/AbsoluteLayoutFlags.xml
@@ -0,0 +1,191 @@
+<Type Name="AbsoluteLayoutFlags" FullName="Xamarin.Forms.AbsoluteLayoutFlags">
+ <TypeSignature Language="C#" Value="public enum AbsoluteLayoutFlags" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed AbsoluteLayoutFlags extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Flags</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Flags used to modify how layout bounds are interpreted in an <see cref="T:Xamarin.Forms.AbsoluteLayout" />.</summary>
+ <remarks>
+ <para>The <see cref="T:Xamarin.Forms.AbsoluteLayout" /> class can lay its child elements out in proportional units, device units, or a combination of both. Application developers should remember the following points when specifying a <see cref="T:Xamarin.Forms.Rectangle" /> structure that will define the layout bounds of a child element:
+ <list type="bullet"><item><term>For elements whose height and width fit on the screen, proportional position dimensions in the range [0,1] represent elements that are completely on the screen, regardless of whether the height, width, or both are specified in device or proportional units.</term></item><item><term>The above point means that, to specify an element in the lower right hand corner of the screen and that is half as wide and half as all as the screen, with a <see cref="T:Xamarin.Forms.LayoutFlags" /> value of <c>All</c>, the application developer would specify "0.1, 0.1, 0.5, 0.5".</term></item><item><term>The app developer can inadvertently cause child elements for which one or both size dimensions were specified proportionally to be displayed partially off the screen, or hidden altogether, by specifying device-unit positions that do not leave enough room for the calculated size of the child.</term></item><item><term>Each part of the bounding <see cref="T:Xamarin.Forms.Rectangle" /> structure is interpreted according to the <see cref="T:Xamarin.Forms.LayoutFlags" /> value that controls it. A given rectangle might, for example, have an X-coordinate that is in device units, a Y-coordinate that is in proportional units, a height that is in proportional units, and a width that is in device units, or any other combination of device and proportional units. </term></item><item><term>Rectangles that, when interpreted by using the current <see cref="T:Xamarin.Forms.LayoutFlags" /> set on the child, represent bounding boxes that are partially or wholly off-screen—for example, by having a width that is larger than the screen width—may give unexpected results.</term></item></list></para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="All">
+ <MemberSignature Language="C#" Value="All" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.AbsoluteLayoutFlags All = int32(-1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.AbsoluteLayoutFlags</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Interpret all dimensions proportionally.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="HeightProportional">
+ <MemberSignature Language="C#" Value="HeightProportional" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.AbsoluteLayoutFlags HeightProportional = int32(8)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.AbsoluteLayoutFlags</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Interpret height property as proportional to layout height.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="None">
+ <MemberSignature Language="C#" Value="None" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.AbsoluteLayoutFlags None = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.AbsoluteLayoutFlags</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Disable all flags.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="PositionProportional">
+ <MemberSignature Language="C#" Value="PositionProportional" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.AbsoluteLayoutFlags PositionProportional = int32(3)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.AbsoluteLayoutFlags</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Equivalent to both XProportional | YProportional.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="SizeProportional">
+ <MemberSignature Language="C#" Value="SizeProportional" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.AbsoluteLayoutFlags SizeProportional = int32(12)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.AbsoluteLayoutFlags</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Equivalent to both WidthProportional | HeightProportional.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="WidthProportional">
+ <MemberSignature Language="C#" Value="WidthProportional" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.AbsoluteLayoutFlags WidthProportional = int32(4)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.AbsoluteLayoutFlags</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Interpret width property as proportional to layout width.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="XProportional">
+ <MemberSignature Language="C#" Value="XProportional" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.AbsoluteLayoutFlags XProportional = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.AbsoluteLayoutFlags</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Interpret x property as proportional to the remaining space after width is accounted for.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="YProportional">
+ <MemberSignature Language="C#" Value="YProportional" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.AbsoluteLayoutFlags YProportional = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.AbsoluteLayoutFlags</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Interpret y property as proportional to the remaining space after height is accounted for.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ActivityIndicator.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ActivityIndicator.xml
new file mode 100644
index 00000000..bb376feb
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ActivityIndicator.xml
@@ -0,0 +1,177 @@
+<Type Name="ActivityIndicator" FullName="Xamarin.Forms.ActivityIndicator">
+ <TypeSignature Language="C#" Value="public class ActivityIndicator : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ActivityIndicator extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._ActivityIndicatorRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A visual control used to indicate that something is ongoing.</summary>
+ <remarks>
+ <para>This control gives a visual clue to the user that something is happening, without information about its progress.</para>
+ <para>
+ <img href="ActivityIndicator.TripleScreenShot.png" />
+ </para>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.ActivityIndicator" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Color</term>
+ <description>
+ <para>A color specification, with or without the prefix, "Color". For example, "Color.Red" and "Red" both specify the color red.</para>
+ </description>
+ </item>
+ <item>
+ <term>IsRunning</term>
+ <description>
+ <para>
+ <see langword="true" /> or <see langword="false" />, to indicate whether the animation for <see cref="T:Xamarin.Forms.ActivityIndicator" /> is displayed.</para>
+ </description>
+ </item>
+ </list>
+ <example>
+ <para>The example below creates a red activity indicator that is animated to imply that an activity is ongoing:</para>
+ <code lang="XAML"><![CDATA[<ActivityIndicator Color="Red" IsRunning="true" />]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ActivityIndicator ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the ActivityIndicator class.</summary>
+ <remarks>
+ <para> The following example shows the initialization of a running ActivityIndicator.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+var indicator = new ActivityIndicator {
+ IsRunning = true,
+};
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Color">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color Color { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color Color" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the <see cref="T:Xamarin.Forms.Color" /> of the ActivityIndicator. This is a bindable property.</summary>
+ <value>A <see cref="T:Xamarin.Forms.Color" /> used to display the ActivityIndicator. Default is <see cref="P:Xamarin.Forms.Color.Default" />.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Color bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsRunning">
+ <MemberSignature Language="C#" Value="public bool IsRunning { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsRunning" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the value indicating if the ActivityIndicator is running. This is a bindable property.</summary>
+ <value>A <see cref="T:System.Boolean" /> indicating if the ActivityIndicator is running.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsRunningProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsRunningProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsRunningProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Color bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Animation.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Animation.xml
new file mode 100644
index 00000000..06f28675
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Animation.xml
@@ -0,0 +1,285 @@
+<Type Name="Animation" FullName="Xamarin.Forms.Animation">
+ <TypeSignature Language="C#" Value="public class Animation : System.Collections.IEnumerable" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Animation extends System.Object implements class System.Collections.IEnumerable" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.Collections.IEnumerable</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>Encapsulates an animation, a collection of functions that modify properties over a user-perceptible time period.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Animation ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Animation" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Animation (Action&lt;double&gt; callback, double start = 0, double end = 1, Xamarin.Forms.Easing easing = null, Action finished = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Action`1&lt;float64&gt; callback, float64 start, float64 end, class Xamarin.Forms.Easing easing, class System.Action finished) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="callback" Type="System.Action&lt;System.Double&gt;" />
+ <Parameter Name="start" Type="System.Double" />
+ <Parameter Name="end" Type="System.Double" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ <Parameter Name="finished" Type="System.Action" />
+ </Parameters>
+ <Docs>
+ <param name="callback">To be added.</param>
+ <param name="start">To be added.</param>
+ <param name="end">To be added.</param>
+ <param name="easing">To be added.</param>
+ <param name="finished">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Animation" /> object with the specified parameters.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (double beginAt, double finishAt, Xamarin.Forms.Animation animation);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void Add(float64 beginAt, float64 finishAt, class Xamarin.Forms.Animation animation) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="beginAt" Type="System.Double" />
+ <Parameter Name="finishAt" Type="System.Double" />
+ <Parameter Name="animation" Type="Xamarin.Forms.Animation" />
+ </Parameters>
+ <Docs>
+ <param name="beginAt">To be added.</param>
+ <param name="finishAt">To be added.</param>
+ <param name="animation">To be added.</param>
+ <summary>Adds an <see cref="T:Xamarin.Forms.Animation" /> object to this <see cref="T:Xamarin.Forms.Animation" /> that begins at <paramref name="beginAt" /> and finishes at <paramref name="finishAt" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Commit">
+ <MemberSignature Language="C#" Value="public void Commit (Xamarin.Forms.IAnimatable owner, string name, uint rate = 16, uint length = 250, Xamarin.Forms.Easing easing = null, Action&lt;double,bool&gt; finished = null, Func&lt;bool&gt; repeat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void Commit(class Xamarin.Forms.IAnimatable owner, string name, unsigned int32 rate, unsigned int32 length, class Xamarin.Forms.Easing easing, class System.Action`2&lt;float64, bool&gt; finished, class System.Func`1&lt;bool&gt; repeat) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="owner" Type="Xamarin.Forms.IAnimatable" />
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="rate" Type="System.UInt32" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ <Parameter Name="finished" Type="System.Action&lt;System.Double,System.Boolean&gt;" />
+ <Parameter Name="repeat" Type="System.Func&lt;System.Boolean&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="owner">To be added.</param>
+ <param name="name">To be added.</param>
+ <param name="rate">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <param name="finished">To be added.</param>
+ <param name="repeat">To be added.</param>
+ <summary>Runs the <paramref name="owner" /> animation with the supplied parameters.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetCallback">
+ <MemberSignature Language="C#" Value="public Action&lt;double&gt; GetCallback ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Action`1&lt;float64&gt; GetCallback() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Action&lt;System.Double&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns a callback that recursively runs the eased animation step on this <see cref="T:Xamarin.Forms.Animation" /> object and those of its children that have begun and not finished.</summary>
+ <returns>A callback that recursively runs the eased animation step on this <see cref="T:Xamarin.Forms.Animation" /> object and those of its children that have begun and not finished.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetEnumerator">
+ <MemberSignature Language="C#" Value="public System.Collections.IEnumerator GetEnumerator ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Collections.IEnumerator GetEnumerator() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.IEnumerator</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns an enumerator that can be used to iterate over the child <see cref="T:Xamarin.Forms.Animation" /> objects of this <see cref="T:Xamarin.Forms.Animation" /> object.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Insert">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Animation Insert (double beginAt, double finishAt, Xamarin.Forms.Animation animation);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class Xamarin.Forms.Animation Insert(float64 beginAt, float64 finishAt, class Xamarin.Forms.Animation animation) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Animation</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="beginAt" Type="System.Double" />
+ <Parameter Name="finishAt" Type="System.Double" />
+ <Parameter Name="animation" Type="Xamarin.Forms.Animation" />
+ </Parameters>
+ <Docs>
+ <param name="beginAt">To be added.</param>
+ <param name="finishAt">To be added.</param>
+ <param name="animation">To be added.</param>
+ <summary>Adds an <see cref="T:Xamarin.Forms.Animation" /> object to this <see cref="T:Xamarin.Forms.Animation" /> that begins at <paramref name="beginAt" /> and finishes at <paramref name="finishAt" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="WithConcurrent">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Animation WithConcurrent (Xamarin.Forms.Animation animation, double beginAt = 0, double finishAt = 1);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class Xamarin.Forms.Animation WithConcurrent(class Xamarin.Forms.Animation animation, float64 beginAt, float64 finishAt) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Animation</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="animation" Type="Xamarin.Forms.Animation" />
+ <Parameter Name="beginAt" Type="System.Double" />
+ <Parameter Name="finishAt" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="animation">To be added.</param>
+ <param name="beginAt">To be added.</param>
+ <param name="finishAt">To be added.</param>
+ <summary>Adds <paramref name="animation" /> to the children of this <see cref="T:Xamarin.Forms.Animation" /> object and sets the start and end times of <paramref name="animation" /> to <paramref name="beginAt" /> and <paramref name="finishAt" />, respectively.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="WithConcurrent">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Animation WithConcurrent (Action&lt;double&gt; callback, double start = 0, double end = 1, Xamarin.Forms.Easing easing = null, double beginAt = 0, double finishAt = 1);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class Xamarin.Forms.Animation WithConcurrent(class System.Action`1&lt;float64&gt; callback, float64 start, float64 end, class Xamarin.Forms.Easing easing, float64 beginAt, float64 finishAt) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Animation</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="callback" Type="System.Action&lt;System.Double&gt;" />
+ <Parameter Name="start" Type="System.Double" />
+ <Parameter Name="end" Type="System.Double" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ <Parameter Name="beginAt" Type="System.Double" />
+ <Parameter Name="finishAt" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="callback">To be added.</param>
+ <param name="start">To be added.</param>
+ <param name="end">To be added.</param>
+ <param name="easing">To be added.</param>
+ <param name="beginAt">To be added.</param>
+ <param name="finishAt">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Animation" /> object with the specified parameters, and adds it to the children of this <see cref="T:Xamarin.Forms.Animation" /> object.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/AnimationExtensions.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/AnimationExtensions.xml
new file mode 100644
index 00000000..211f5e31
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/AnimationExtensions.xml
@@ -0,0 +1,313 @@
+<Type Name="AnimationExtensions" FullName="Xamarin.Forms.AnimationExtensions">
+ <TypeSignature Language="C#" Value="public static class AnimationExtensions" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract sealed AnimationExtensions extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Extension methods for <see cref="T:Xamarin.Forms.Animation" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="AbortAnimation">
+ <MemberSignature Language="C#" Value="public static bool AbortAnimation (this Xamarin.Forms.IAnimatable self, string handle);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig bool AbortAnimation(class Xamarin.Forms.IAnimatable self, string handle) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.IAnimatable" RefType="this" />
+ <Parameter Name="handle" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="self">To be added.</param>
+ <param name="handle">To be added.</param>
+ <summary>Stops the animation.</summary>
+ <returns>To be added.</returns>
+ <remarks>If <paramref name="handle" /> refers to an animation that belongs to this <see cref="T:Xamarin.Forms.IAnimatable" /> instance, then its tweener handlers are removed, the tweener is stopped, the animation is removed from this <see cref="T:Xamarin.Forms.IAnimatable" /> instance, and it is marked as finished. If <paramref name="handle" /> refers to one of the kinetics that belong to this <see cref="T:Xamarin.Forms.IAnimatable" /> instance, then it and its ticker are removed.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Animate">
+ <MemberSignature Language="C#" Value="public static void Animate (this Xamarin.Forms.IAnimatable self, string name, Action&lt;double&gt; callback, uint rate = 16, uint length = 250, Xamarin.Forms.Easing easing = null, Action&lt;double,bool&gt; finished = null, Func&lt;bool&gt; repeat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Animate(class Xamarin.Forms.IAnimatable self, string name, class System.Action`1&lt;float64&gt; callback, unsigned int32 rate, unsigned int32 length, class Xamarin.Forms.Easing easing, class System.Action`2&lt;float64, bool&gt; finished, class System.Func`1&lt;bool&gt; repeat) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.IAnimatable" RefType="this" />
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="callback" Type="System.Action&lt;System.Double&gt;" />
+ <Parameter Name="rate" Type="System.UInt32" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ <Parameter Name="finished" Type="System.Action&lt;System.Double,System.Boolean&gt;" />
+ <Parameter Name="repeat" Type="System.Func&lt;System.Boolean&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="self">To be added.</param>
+ <param name="name">To be added.</param>
+ <param name="callback">To be added.</param>
+ <param name="rate">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <param name="finished">To be added.</param>
+ <param name="repeat">To be added.</param>
+ <summary>Sets the specified parameters and starts the animation.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Animate">
+ <MemberSignature Language="C#" Value="public static void Animate (this Xamarin.Forms.IAnimatable self, string name, Xamarin.Forms.Animation animation, uint rate = 16, uint length = 250, Xamarin.Forms.Easing easing = null, Action&lt;double,bool&gt; finished = null, Func&lt;bool&gt; repeat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Animate(class Xamarin.Forms.IAnimatable self, string name, class Xamarin.Forms.Animation animation, unsigned int32 rate, unsigned int32 length, class Xamarin.Forms.Easing easing, class System.Action`2&lt;float64, bool&gt; finished, class System.Func`1&lt;bool&gt; repeat) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.IAnimatable" RefType="this" />
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="animation" Type="Xamarin.Forms.Animation" />
+ <Parameter Name="rate" Type="System.UInt32" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ <Parameter Name="finished" Type="System.Action&lt;System.Double,System.Boolean&gt;" />
+ <Parameter Name="repeat" Type="System.Func&lt;System.Boolean&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="self">To be added.</param>
+ <param name="name">To be added.</param>
+ <param name="animation">To be added.</param>
+ <param name="rate">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <param name="finished">To be added.</param>
+ <param name="repeat">To be added.</param>
+ <summary>Sets the specified parameters and starts the animation.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Animate">
+ <MemberSignature Language="C#" Value="public static void Animate (this Xamarin.Forms.IAnimatable self, string name, Action&lt;double&gt; callback, double start, double end, uint rate = 16, uint length = 250, Xamarin.Forms.Easing easing = null, Action&lt;double,bool&gt; finished = null, Func&lt;bool&gt; repeat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Animate(class Xamarin.Forms.IAnimatable self, string name, class System.Action`1&lt;float64&gt; callback, float64 start, float64 end, unsigned int32 rate, unsigned int32 length, class Xamarin.Forms.Easing easing, class System.Action`2&lt;float64, bool&gt; finished, class System.Func`1&lt;bool&gt; repeat) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.IAnimatable" RefType="this" />
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="callback" Type="System.Action&lt;System.Double&gt;" />
+ <Parameter Name="start" Type="System.Double" />
+ <Parameter Name="end" Type="System.Double" />
+ <Parameter Name="rate" Type="System.UInt32" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ <Parameter Name="finished" Type="System.Action&lt;System.Double,System.Boolean&gt;" />
+ <Parameter Name="repeat" Type="System.Func&lt;System.Boolean&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="self">To be added.</param>
+ <param name="name">To be added.</param>
+ <param name="callback">To be added.</param>
+ <param name="start">To be added.</param>
+ <param name="end">To be added.</param>
+ <param name="rate">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <param name="finished">To be added.</param>
+ <param name="repeat">To be added.</param>
+ <summary>Sets the specified parameters and starts the animation.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Animate&lt;T&gt;">
+ <MemberSignature Language="C#" Value="public static void Animate&lt;T&gt; (this Xamarin.Forms.IAnimatable self, string name, Func&lt;double,T&gt; transform, Action&lt;T&gt; callback, uint rate = 16, uint length = 250, Xamarin.Forms.Easing easing = null, Action&lt;T,bool&gt; finished = null, Func&lt;bool&gt; repeat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Animate&lt;T&gt;(class Xamarin.Forms.IAnimatable self, string name, class System.Func`2&lt;float64, !!T&gt; transform, class System.Action`1&lt;!!T&gt; callback, unsigned int32 rate, unsigned int32 length, class Xamarin.Forms.Easing easing, class System.Action`2&lt;!!T, bool&gt; finished, class System.Func`1&lt;bool&gt; repeat) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="T" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.IAnimatable" RefType="this" />
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="transform" Type="System.Func&lt;System.Double,T&gt;" />
+ <Parameter Name="callback" Type="System.Action&lt;T&gt;" />
+ <Parameter Name="rate" Type="System.UInt32" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ <Parameter Name="finished" Type="System.Action&lt;T,System.Boolean&gt;" />
+ <Parameter Name="repeat" Type="System.Func&lt;System.Boolean&gt;" />
+ </Parameters>
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <param name="self">To be added.</param>
+ <param name="name">To be added.</param>
+ <param name="transform">To be added.</param>
+ <param name="callback">To be added.</param>
+ <param name="rate">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <param name="finished">To be added.</param>
+ <param name="repeat">To be added.</param>
+ <summary>Sets the specified parameters and starts the animation.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AnimateKinetic">
+ <MemberSignature Language="C#" Value="public static void AnimateKinetic (this Xamarin.Forms.IAnimatable self, string name, Func&lt;double,double,bool&gt; callback, double velocity, double drag, Action finished = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void AnimateKinetic(class Xamarin.Forms.IAnimatable self, string name, class System.Func`3&lt;float64, float64, bool&gt; callback, float64 velocity, float64 drag, class System.Action finished) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.IAnimatable" RefType="this" />
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="callback" Type="System.Func&lt;System.Double,System.Double,System.Boolean&gt;" />
+ <Parameter Name="velocity" Type="System.Double" />
+ <Parameter Name="drag" Type="System.Double" />
+ <Parameter Name="finished" Type="System.Action" />
+ </Parameters>
+ <Docs>
+ <param name="self">To be added.</param>
+ <param name="name">To be added.</param>
+ <param name="callback">To be added.</param>
+ <param name="velocity">To be added.</param>
+ <param name="drag">To be added.</param>
+ <param name="finished">To be added.</param>
+ <summary>Sets the specified parameters and starts the kinetic animation.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AnimationIsRunning">
+ <MemberSignature Language="C#" Value="public static bool AnimationIsRunning (this Xamarin.Forms.IAnimatable self, string handle);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig bool AnimationIsRunning(class Xamarin.Forms.IAnimatable self, string handle) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.IAnimatable" RefType="this" />
+ <Parameter Name="handle" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="self">To be added.</param>
+ <param name="handle">To be added.</param>
+ <summary>Returns a Boolean value that indicates whether or not the animation that is specified by <paramref name="handle" /> is running.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Interpolate">
+ <MemberSignature Language="C#" Value="public static Func&lt;double,double&gt; Interpolate (double start, double end = 1, double reverseVal = 0, bool reverse = false);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Func`2&lt;float64, float64&gt; Interpolate(float64 start, float64 end, float64 reverseVal, bool reverse) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Func&lt;System.Double,System.Double&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="start" Type="System.Double" />
+ <Parameter Name="end" Type="System.Double" />
+ <Parameter Name="reverseVal" Type="System.Double" />
+ <Parameter Name="reverse" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="start">To be added.</param>
+ <param name="end">To be added.</param>
+ <param name="reverseVal">To be added.</param>
+ <param name="reverse">To be added.</param>
+ <summary>Returns a function that performs a linear interpolation between <paramref name="start" /> and <paramref name="end" />.</summary>
+ <returns>A function that performs a linear interpolation between <paramref name="start" /> and <paramref name="end" />. Application developers can pass values between 0.0f and 1.0f to this function in order to recieve a value that is offset from <paramref name="start" /> or <paramref name="end" />, depending on the value of <paramref name="reverse" />, by the passed value times the distance between <paramref name="start" /> and <paramref name="end" />.</returns>
+ <remarks>If <paramref name="reverse" /> is <see langword="true" />, then the interpolation happens between <paramref name="start" /> and <paramref name="reverseVal" />.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Application.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Application.xml
new file mode 100644
index 00000000..b3b8bdd6
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Application.xml
@@ -0,0 +1,314 @@
+<Type Name="Application" FullName="Xamarin.Forms.Application">
+ <TypeSignature Language="C#" Value="public class Application : Xamarin.Forms.Element" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Application extends Xamarin.Forms.Element" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Element</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IApplicationController</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>Class that represents a cross-platform mobile application.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected Application ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new <see cref="T:Xamarin.Forms.Application" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Current">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Application Current { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property class Xamarin.Forms.Application Current" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Application</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the current application.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MainPage">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Page MainPage { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Page MainPage" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Page</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the main page of the application.</summary>
+ <value>To be added.</value>
+ <remarks>This property throws an exception if the application developer attempts to set it to <see langword="null" />.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ModalPopped">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ModalPoppedEventArgs&gt; ModalPopped;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ModalPoppedEventArgs&gt; ModalPopped" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ModalPoppedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised after a view has been popped modally.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ModalPopping">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ModalPoppingEventArgs&gt; ModalPopping;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ModalPoppingEventArgs&gt; ModalPopping" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ModalPoppingEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when a view is modally popped.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ModalPushed">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ModalPushedEventArgs&gt; ModalPushed;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ModalPushedEventArgs&gt; ModalPushed" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ModalPushedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised after a view has been pushed modally.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ModalPushing">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ModalPushingEventArgs&gt; ModalPushing;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ModalPushingEventArgs&gt; ModalPushing" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ModalPushingEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when a view is modally pushed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnParentSet">
+ <MemberSignature Language="C#" Value="protected override void OnParentSet ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnParentSet() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Throws <see cref="T:System.InvalidOperationException" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnResume">
+ <MemberSignature Language="C#" Value="protected virtual void OnResume ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnResume() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Application developers override this method to perform actions when the application resumes from a sleeping state.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSleep">
+ <MemberSignature Language="C#" Value="protected virtual void OnSleep ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnSleep() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Application developers override this method to perform actions when the application enters the sleeping state.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnStart">
+ <MemberSignature Language="C#" Value="protected virtual void OnStart ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnStart() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Application developers override this method to perform actions when the application starts.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Properties">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IDictionary&lt;string,object&gt; Properties { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IDictionary`2&lt;string, object&gt; Properties" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IDictionary&lt;System.String,System.Object&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the dictionary of properties for this <see cref="T:Xamarin.Forms.Application" /> object.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Resources">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.ResourceDictionary Resources { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.ResourceDictionary Resources" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ResourceDictionary</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the resource dictionary for this <see cref="T:Xamarin.Forms.Application" /> object.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SavePropertiesAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task SavePropertiesAsync ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Threading.Tasks.Task SavePropertiesAsync() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Asynchronously persists the <see cref="P:Xamarin.Forms.Application.Properties" /> dictionary for the application object.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IApplicationController.SetAppIndexingProvider">
+ <MemberSignature Language="C#" Value="void IApplicationController.SetAppIndexingProvider (Xamarin.Forms.IAppIndexingProvider provider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IApplicationController.SetAppIndexingProvider(class Xamarin.Forms.IAppIndexingProvider provider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="provider" Type="Xamarin.Forms.IAppIndexingProvider" />
+ </Parameters>
+ <Docs>
+ <param name="provider">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Aspect.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Aspect.xml
new file mode 100644
index 00000000..af7ad112
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Aspect.xml
@@ -0,0 +1,86 @@
+<Type Name="Aspect" FullName="Xamarin.Forms.Aspect">
+ <TypeSignature Language="C#" Value="public enum Aspect" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed Aspect extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Defines how an image is displayed.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="AspectFill">
+ <MemberSignature Language="C#" Value="AspectFill" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.Aspect AspectFill = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Aspect</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Scale the image to fill the view. Some parts may be clipped in order to fill the view.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AspectFit">
+ <MemberSignature Language="C#" Value="AspectFit" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.Aspect AspectFit = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Aspect</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Scale the image to fit the view. Some parts may be left empty (letter boxing).</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Fill">
+ <MemberSignature Language="C#" Value="Fill" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.Aspect Fill = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Aspect</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Scale the image so it exactly fill the view. Scaling may not be uniform in X and Y.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BackButtonPressedEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BackButtonPressedEventArgs.xml
new file mode 100644
index 00000000..51550dda
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BackButtonPressedEventArgs.xml
@@ -0,0 +1,56 @@
+<Type Name="BackButtonPressedEventArgs" FullName="Xamarin.Forms.BackButtonPressedEventArgs">
+ <TypeSignature Language="C#" Value="public class BackButtonPressedEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit BackButtonPressedEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Internal use only. Contains arguments for the event that is raised when a back button is pressed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public BackButtonPressedEventArgs ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Internal use only. Initializes a new <see cref="T:Xamarin.Forms.BackButtonPressedEventArgs" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Handled">
+ <MemberSignature Language="C#" Value="public bool Handled { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool Handled" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Internal use only. Gets or sets a value that indicates whether the back button event has already been handled.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BaseMenuItem.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BaseMenuItem.xml
new file mode 100644
index 00000000..676ce361
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BaseMenuItem.xml
@@ -0,0 +1,37 @@
+<Type Name="BaseMenuItem" FullName="Xamarin.Forms.BaseMenuItem">
+ <TypeSignature Language="C#" Value="public abstract class BaseMenuItem : Xamarin.Forms.Element" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit BaseMenuItem extends Xamarin.Forms.Element" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Element</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Base class for menu items.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected BaseMenuItem ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Intializes a new <see cref="T:Xamarin.Forms.BaseMenuItem" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Behavior.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Behavior.xml
new file mode 100644
index 00000000..2649043a
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Behavior.xml
@@ -0,0 +1,130 @@
+<Type Name="Behavior" FullName="Xamarin.Forms.Behavior">
+ <TypeSignature Language="C#" Value="public abstract class Behavior : Xamarin.Forms.BindableObject" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit Behavior extends Xamarin.Forms.BindableObject" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Base>
+ <Interfaces>
+ </Interfaces>
+ <Docs>
+ <summary>Base class for generalized user-defined behaviors that can respond to arbitrary conditions and events.</summary>
+ <remarks>Application developers should specialize the <see cref="T:Xamarin.Forms.Behavior`1" /> generic class, instead of directly using <see cref="T:Xamarin.Forms.Behavior" />.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="AssociatedType">
+ <MemberSignature Language="C#" Value="protected Type AssociatedType { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Type AssociatedType" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Type</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the type of the objects with which this <see cref="T:Xamarin.Forms.Behavior" /> can be associated.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnAttachedTo">
+ <MemberSignature Language="C#" Value="protected virtual void OnAttachedTo (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnAttachedTo(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <summary>Application developers override this method to implement the behaviors that will be associated with <paramref name="bindable" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnDetachingFrom">
+ <MemberSignature Language="C#" Value="protected virtual void OnDetachingFrom (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnDetachingFrom(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <summary>Application developers override this method to remove the behaviors from <paramref name="bindable" /> that were implemented in a previous call to the <see cref="M:Xamarin.Forms.Behavior.OnAttachedTo" /> method.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IAttachedObject.AttachTo">
+ <MemberSignature Language="C#" Value="void IAttachedObject.AttachTo (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IAttachedObject.AttachTo(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <summary>Attempts to attach to <paramref name="bindable" />. If successful, calls the <see cref="M:Xamarin.Forms.Behavior.OnAttachedTo" /> method.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IAttachedObject.DetachFrom">
+ <MemberSignature Language="C#" Value="void IAttachedObject.DetachFrom (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IAttachedObject.DetachFrom(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <summary>Detaches from <paramref name="bindable" />. Calls the <see cref="M:Xamarin.Forms.Behavior.OnDetachedFrom" /> method.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Behavior`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Behavior`1.xml
new file mode 100644
index 00000000..b45d2110
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Behavior`1.xml
@@ -0,0 +1,136 @@
+<Type Name="Behavior&lt;T&gt;" FullName="Xamarin.Forms.Behavior&lt;T&gt;">
+ <TypeSignature Language="C#" Value="public abstract class Behavior&lt;T&gt; : Xamarin.Forms.Behavior where T : BindableObject" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit Behavior`1&lt;(class Xamarin.Forms.BindableObject) T&gt; extends Xamarin.Forms.Behavior" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="T">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Behavior</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <typeparam name="T">The type of the objects with which this <see cref="T:Xamarin.Forms.Behavior`1" /> can be associated.</typeparam>
+ <summary>Base generic class for generalized user-defined behaviors that can respond to arbitrary conditions and events.</summary>
+ <remarks>Application developers should specialize this generic class, instead of directly using <see cref="T:Xamarin.Forms.Behavior" />.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected Behavior ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Behavior`1" /> instance.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnAttachedTo">
+ <MemberSignature Language="C#" Value="protected virtual void OnAttachedTo (T bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnAttachedTo(!T bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <summary>Application developers override this method to implement the behaviors that will be associated with <paramref name="bindable" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnAttachedTo">
+ <MemberSignature Language="C#" Value="protected override void OnAttachedTo (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnAttachedTo(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <summary>Attaches to the superclass and then calls the <see cref="M:Xamarin.Forms.Behavior`1.OnAttachedTo(T)" /> method on this object.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnDetachingFrom">
+ <MemberSignature Language="C#" Value="protected virtual void OnDetachingFrom (T bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnDetachingFrom(!T bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <summary>Application developers override this method to remove the behaviors from <paramref name="bindable" /> that were implemented in a previous call to the <see cref="M:Xamarin.Forms.Behavior`1.OnAttachedTo" /> method.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnDetachingFrom">
+ <MemberSignature Language="C#" Value="protected override void OnDetachingFrom (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnDetachingFrom(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <summary>Calls the <see cref="M:Xamarin.Forms.Behavior`1.OnDetachingFrom(T)" /> method and then detaches from the superclass.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableObject.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableObject.xml
new file mode 100644
index 00000000..c72e0948
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableObject.xml
@@ -0,0 +1,748 @@
+<Type Name="BindableObject" FullName="Xamarin.Forms.BindableObject">
+ <TypeSignature Language="C#" Value="public abstract class BindableObject : System.ComponentModel.INotifyPropertyChanged, Xamarin.Forms.Internals.IDynamicResourceHandler" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit BindableObject extends System.Object implements class System.ComponentModel.INotifyPropertyChanged, class Xamarin.Forms.Internals.IDynamicResourceHandler" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.ComponentModel.INotifyPropertyChanged</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Internals.IDynamicResourceHandler</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>Provides a mechanism by which application developers can propagate changes that are made to data in one object to another, by enabling validation, type coercion, and an event system. <see cref="T:Xamarin.Forms.BindableProperty" />.</summary>
+ <remarks>
+ <para>The <see cref="T:Xamarin.Forms.BindableObject" /> class provides a data storage mechanism that enables the application developer to synchronize data between objects in response to changes, for example, between the View and View Model in the MVVM design pattern. All of the visual elements in the <see cref="N:Xamarin.Forms" /> namespace inherit from <see cref="T:Xamarin.Forms.BindableObject" /> class, so they can all be used to bind the data behind their user interface elements to View Models that are supplied by the application developer.</para>
+ <example>
+ <para>To bind the data behind a property in a <see cref="T:Xamarin.Forms.BindableObject" />, typically a view, to a property in the View Model, application developers should do the following.</para>
+ <para> First, the developer creates a pair of properties on the view, one of which is a <see cref="T:Xamarin.Forms.BindableProperty" />, and the other of which is a property of whatever type is required. In the code below, <c>MockBindableObject</c> stands in for what would typically be a user interface object in production code. Application developers should note the use of <see cref="M:Xamarin.Forms.BindableObject.SetValue(Xamarin.Forms.BindableProperty, System.Object)" /> and <see cref="M:Xamarin.Forms.BindableObject.GetValue" /> to get and set the value on the bound property; The property of the desired type provides the interface that the target of the bound property will implement.</para>
+ <code lang="C#"><![CDATA[
+class MockBindableObject : BindableObject
+{
+ // App developers should use the method below in production code for
+ // better performance
+ public static readonly BindableProperty BoundNameProperty =
+ BindableProperty.Create ("Foo", typeof (string),
+ typeof (MockBindableObject),
+ default(string));
+
+ // App developers should use the method below during development for
+ // design-time error checking as the codebase evolves.
+ // public static readonly BindableProperty FooProperty
+ // = BindableProperty.Create<MockBindableObject, string> (
+ // o => o.Foo, default (string)
+ // );
+
+ public string BoundName
+ {
+ get { return (string) GetValue (BoundNameProperty); }
+ set { SetValue (BoundNameProperty, value); }
+ }
+}
+ ]]></code>
+ <para>Second, the developer creates the implementation for the bound property in a class that implements the <see cref="T:System.ComponentModel.INotifyPropertyChanged" /> interface. In the MVVM design pattern, this is typically done by the View Model. Application developers should implement the <see cref="T:System.ComponentModel.INotifyPropertyChanged" /> interface on classes that they want to use as View Models. In the example below, app developers should take note of the idiomatic way that the <c>Name</c> property is implemented to, first, ensure that the property actually changed and return if it did not, and only then assign the value and call the <see cref="M:Xamarin.Forms.BindableObject.OnPropertyChanged" /> method. Additionally, the <c>Name</c> property in the example below merely wraps the <c>name</c> field. In practice, the application developer may choose a different model in which to store application data.</para>
+ <code lang="C#"><![CDATA[
+class MockViewModel : INotifyPropertyChanged
+{
+ string name;
+
+ public string Name
+ {
+ get { return name; }
+ set
+ {
+ // OnPropertyChanged should not be called if the property value
+ // does not change.
+ if (name == value)
+ return;
+ name = value;
+ OnPropertyChanged ();
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ void OnPropertyChanged (string propertyName = null)
+ {
+ PropertyChangedEventHandler handler = PropertyChanged;
+ if (handler != null)
+ handler (this, new PropertyChangedEventArgs (propertyName));
+ }
+}]]></code>
+ <para>Third, and finally, the application developer binds an instance of a BindableObject to an instance that implements INotifyPropertyChanged. In the vocabulary of the MVVM design pattern, this is "binding an instance of the View to an instance of a View Model." Once this step is complete, changes in the data are propagated between the View and View Model in a way that is determined by the value of the <see cref="T:Xamarin.Forms.BindingMode" /> enumeration, if any, that was passed during the binding step.</para>
+ <para>The code below, when included in a project that reference the classes above, creates an instance of both <c>MockBindable</c> and <c>MockViewModel</c>, performs some intitialization, sets the binding, and then demonstrates a one-way binding. The code below runs without throwing an exception.</para>
+ <code lang="C#"><![CDATA[
+public static void OneWayDemo ()
+{
+ var view = new MockBindableObject ();
+ var viewModel = new MockViewModel ();
+
+ // Pre-load the ViewModel, for demonstration purposes
+ viewModel.Name = "Testing";
+
+ // Create a one-way (default) binding
+ view.SetBinding (MockBindableObject.BoundNameProperty, new Binding ("Name"));
+
+ // App developers should only set the binding context after all
+ // calls to SetBinding() have been made, for performance reasons.
+ view.BindingContext = viewModel;
+
+ // In a one way binding, the ViewModel value will be used to update
+ // the values in the View during initialization
+ if (view.BoundName != "Testing")
+ throw new Exception ();
+
+ view.BoundName = "gnitseT";
+
+ // in a one way binding, changes to the View will NOT update the ViewModel
+ if (viewModel.Name == "gnitseT")
+ throw new Exception ();
+}]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected BindableObject ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the BindableObject class.</summary>
+ <remarks>The <see cref="T:Xamarin.Forms.BindableObject" /> class is abstract, and this constructor is protected. It is invoked by child constructors.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ApplyBindings">
+ <MemberSignature Language="C#" Value="protected void ApplyBindings (object oldContext = null);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig instance void ApplyBindings(object oldContext) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="oldContext" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="oldContext">The object that contains the properties that will be targeted by the bound properties that belong to this <see cref="T:Xamarin.Forms.BindableObject" />. This parameter is optional.</param>
+ <summary>Apply the bindings to <c>this</c><see cref="P:Xamarin.Forms.BindableObject.BindingContex" />.</summary>
+ <remarks>
+ <para>If an object is passed for the <paramref name="oldContext" /> argument, bindings are first unapplied from <paramref name="oldContext" />. This method removes any current bindings from the old context, and applies every binding to the current <see cref="P:Xamarin.Forms.BindableObject.BindingContex" />. Application developers could use this method to bind the UI from a new View to an existing ViewModel, while optionally removing the bindings from the old View. Application developers can omit the <paramref name="oldContext" /> argument in order to leave the old bindings in place.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BindingContext">
+ <MemberSignature Language="C#" Value="public object BindingContext { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object BindingContext" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets object that contains the properties that will be targeted by the bound properties that belong to this <see cref="T:Xamarin.Forms.BindableObject" />.</summary>
+ <value>An <see cref="T:System.Object" /> that contains the properties that will be targeted by the bound properties that belong to this <see cref="T:Xamarin.Forms.BindableObject" />. This is a bindable property.</value>
+ <remarks>
+ <block subset="none" type="note">Typically, the runtime performance is better if <see cref="P:Xamarin.Forms.BindableObject.BindingContext" /> is set after all calls to <see cref="M:Xamarin.Forms.BindableObject.SetBinding" /> have been made.</block>
+ <para>The following example shows how to apply a BindingContext and a Binding to a Label (inherits from BindableObject):</para>
+ <example>
+ <code lang="C#"><![CDATA[
+var label = new Label ();
+label.SetBinding (Label.TextProperty, "Name");
+label.BindingContext = new {Name = "John Doe", Company = "Xamarin"};
+Debug.WriteLine (label.Text); //prints "John Doe"
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BindingContextChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler BindingContextChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler BindingContextChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Raised whenever the <see cref="P:Xamarin.Forms.BindableObject.BindingContext" /> property changes.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BindingContextProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty BindingContextProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty BindingContextProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Implements the bound property whose interface is provided by the <see cref="P:Xamarin.Forms.BindableObject.BindingContext" /> property.</summary>
+ <remarks>
+ <block subset="none" type="note">Typically, the runtime performance is better if <see cref="P:Xamarin.Forms.BindableObject.BindingContext" /> is set after all calls to <see cref="M:Xamarin.Forms.BindableObject.SetBinding" /> have been made.</block>
+ <para>The following example shows how to set a binding to the BindingContext:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+class PersonView : ContentView
+{
+ public PersonView ()
+ {
+ var label = new Label ();
+ label.SetBinding (Label.TextProperty, "Name");
+ Content = label;
+ }
+}
+
+var stack = new StackLayout {
+ Orientation = StackOrientation.Vertical,
+};
+
+var jane = new PersonView ();
+jane.SetBinding (BindableObject.BindingContext, "Jane");
+stack.Children.Add (jane);
+
+var john = new PersonView ();
+john.SetBinding (BindableObject.BindingContext, "John");
+stack.Children.Add (john);
+
+stack.BindingContext = new {Jane = new {Name = "Jane Doe"}, John = new {Name = "John Doe"}};
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ClearValue">
+ <MemberSignature Language="C#" Value="public void ClearValue (Xamarin.Forms.BindableProperty property);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void ClearValue(class Xamarin.Forms.BindableProperty property) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ </Parameters>
+ <Docs>
+ <param name="property">The BindableProperty to clear.</param>
+ <summary>Clears any value set by <see cref="M:Xamarin.Forms.BindableObject.SetValue" /> for <paramref name="property" />.</summary>
+ <remarks>
+ <para>Calling this method on a readonly property will result in an InvalidOperationException.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ClearValue">
+ <MemberSignature Language="C#" Value="public void ClearValue (Xamarin.Forms.BindablePropertyKey propertyKey);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void ClearValue(class Xamarin.Forms.BindablePropertyKey propertyKey) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyKey" Type="Xamarin.Forms.BindablePropertyKey" />
+ </Parameters>
+ <Docs>
+ <param name="propertyKey">The BindablePropertyKey that identifies the <see cref="T:Xamarin.Forms.BindableProperty" /> to clear.</param>
+ <summary>Clears any value set by <see cref="M:Xamarin.Forms.BindableObject.SetValue" /> for the property that is identified by <paramref name="propertyKey" />.</summary>
+ <remarks>
+ <para>Calling this method on a readonly property will result in an InvalidOperationException.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetValue">
+ <MemberSignature Language="C#" Value="public object GetValue (Xamarin.Forms.BindableProperty property);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance object GetValue(class Xamarin.Forms.BindableProperty property) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ </Parameters>
+ <Docs>
+ <param name="property">The BindableProperty for which to get the value.</param>
+ <summary>Returns the value that is contained the BindableProperty.</summary>
+ <returns>The value that is contained the <see cref="T:Xamarin.Forms.BindableProperty" />.</returns>
+ <remarks>
+ <para>
+ <see cref="M:Xamarin.Forms.BindableObject.GetValue" /> and <see cref="M:Xamarin.Forms.BindableObject.SetValue" /> are used to access the values of properties that are implemented by a <see cref="T:Xamarin.Forms.BindableProperty" />. That is, application developers typically provide an interface for a bound property by defining <see langword="public" /> property whose <see langword="get" /> accessor casts the result of <see cref="M:Xamarin.Forms.BindableObject.GetValue" /> to the appropriate type and returns it, and whose <see langword="get" /> accessor uses <see cref="M:Xamarin.Forms.BindableObject.SetValue" /> to set the value on the correct property. Application developers should perform no other steps in the public property that defines the interface of the bound property.</para>
+ <example>
+ <para>The following example shows how to create a bindable property interface for an implementation that will be provided in the target property when the binding is made at run time.</para>
+ <code lang="C#"><![CDATA[
+class MyBindable : BindableObject
+{
+ public static readonly BindableProperty MyProperty =
+ BindableProperty.Create<MyBindable, string> (w => w.My, default(string));
+
+ public string My {
+ get { return (string)GetValue (MyProperty); }
+ set { SetValue (MyProperty, value); }
+ }
+}
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBindingContextChanged">
+ <MemberSignature Language="C#" Value="protected virtual void OnBindingContextChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnBindingContextChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Override this method to execute an action when the BindingContext changes.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnPropertyChanged">
+ <MemberSignature Language="C#" Value="protected virtual void OnPropertyChanged (string propertyName = null);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnPropertyChanged(string propertyName) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String">
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.CallerMemberName</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Parameter>
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the property that changed.</param>
+ <summary>Call this method from a child class to notify that a change happened on a property.</summary>
+ <remarks>
+ <para>A <see cref="T:Xamarin.Forms.BindableProperty" /> triggers this by itself. An inheritor only needs to call this for properties without <see cref="T:Xamarin.Forms.BindableProperty" /> as the backend store.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnPropertyChanging">
+ <MemberSignature Language="C#" Value="protected virtual void OnPropertyChanging (string propertyName = null);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnPropertyChanging(string propertyName) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String">
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.CallerMemberName</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Parameter>
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the property that is changing.</param>
+ <summary>Call this method from a child class to notify that a change is going to happen on a property.</summary>
+ <remarks>A <see cref="T:Xamarin.Forms.BindableProperty" /> triggers this by itself. An inheritor only needs to call this for properties without <see cref="T:Xamarin.Forms.BindableProperty" /> as the backend store.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PropertyChanged">
+ <MemberSignature Language="C#" Value="public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.ComponentModel.PropertyChangedEventHandler PropertyChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.ComponentModel.PropertyChangedEventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Raised when a property has changed.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PropertyChanging">
+ <MemberSignature Language="C#" Value="public event Xamarin.Forms.PropertyChangingEventHandler PropertyChanging;" />
+ <MemberSignature Language="ILAsm" Value=".event class Xamarin.Forms.PropertyChangingEventHandler PropertyChanging" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.PropertyChangingEventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Raised when a property is about to change.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RemoveBinding">
+ <MemberSignature Language="C#" Value="public void RemoveBinding (Xamarin.Forms.BindableProperty property);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void RemoveBinding(class Xamarin.Forms.BindableProperty property) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ </Parameters>
+ <Docs>
+ <param name="property">The BindableProperty from which to remove bindings.</param>
+ <summary>Removes a previously set binding.</summary>
+ <remarks>
+ <para>This method succeeds even if <paramref name="property" /> is not bound.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetBinding">
+ <MemberSignature Language="C#" Value="public void SetBinding (Xamarin.Forms.BindableProperty targetProperty, Xamarin.Forms.BindingBase binding);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void SetBinding(class Xamarin.Forms.BindableProperty targetProperty, class Xamarin.Forms.BindingBase binding) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="targetProperty" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="binding" Type="Xamarin.Forms.BindingBase" />
+ </Parameters>
+ <Docs>
+ <param name="targetProperty">The BindableProperty on which to set a binding.</param>
+ <param name="binding">The binding to set.</param>
+ <summary>Assigns a binding to a property.</summary>
+ <remarks>
+ <para>The following example shows how to set a binding to a property:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+var label = new Label ();
+label.SetBinding (Label.TextProperty, new Binding ("Name"));
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetInheritedBindingContext">
+ <MemberSignature Language="C#" Value="protected static void SetInheritedBindingContext (Xamarin.Forms.BindableObject bindable, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method familyorassemblystatic hidebysig void SetInheritedBindingContext(class Xamarin.Forms.BindableObject bindable, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">The object on which to set the inherited binding context.</param>
+ <param name="value">The inherited context to set.</param>
+ <summary>Sets the inherited context to a nested element.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetValue">
+ <MemberSignature Language="C#" Value="public void SetValue (Xamarin.Forms.BindableProperty property, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void SetValue(class Xamarin.Forms.BindableProperty property, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="property">The BindableProperty on which to assign a value.</param>
+ <param name="value">The value to set.</param>
+ <summary>Sets the value of the specified property.</summary>
+ <remarks>
+ <para>
+ <see cref="M:Xamarin.Forms.BindableObject.GetValue" /> and <see cref="M:Xamarin.Forms.BindableObject.SetValue" /> are used to access the values of properties that are implemented by a <see cref="T:Xamarin.Forms.BindableProperty" />. That is, application developers typically provide an interface for a bound property by defining <see langword="public" /> property whose <see langword="get" /> accessor casts the result of <see cref="M:Xamarin.Forms.BindableObject.GetValue" /> to the appropriate type and returns it, and whose <see langword="get" /> accessor uses <see cref="M:Xamarin.Forms.BindableObject.SetValue" /> to set the value on the correct property. Application developers should perform no other steps in the public property that defines the interface of the bound property.</para>
+ <example>
+ <para>The following example shows how to create a bindable property interface for an implementation that will be provided in the target property when the binding is made at run time.</para>
+ <code lang="C#"><![CDATA[
+class MyBindable : BindableObject
+{
+ public static readonly BindableProperty MyProperty =
+ BindableProperty.Create<MyBindable, string> (w => w.My, default(string));
+
+ public string My {
+ get { return (string)GetValue (MyProperty); }
+ set { SetValue (MyProperty, value); }
+ }
+}
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetValue">
+ <MemberSignature Language="C#" Value="public void SetValue (Xamarin.Forms.BindablePropertyKey propertyKey, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void SetValue(class Xamarin.Forms.BindablePropertyKey propertyKey, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyKey" Type="Xamarin.Forms.BindablePropertyKey" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="propertyKey">The BindablePropertyKey on which to assign a value.</param>
+ <param name="value">The value to set.</param>
+ <summary>Sets the value of the propertyKey.</summary>
+ <remarks>
+ <para>This method and <see cref="T:Xamarin.Forms.BindablePropertyKey" /> are useful to implement BindableProperties with limited write access. The write access is limited to the scope of the BindablePropertyKey.</para>
+ <para>The following example shows how to declare a BindableProperty with "internal" write access.</para>
+ <example>
+ <code lang="C#"><![CDATA[
+class MyBindable : BindableObject
+{
+ internal static readonly BindablePropertyKey MyPropertyKey =
+ BindableProperty.CreateReadOnly<MyBindable, string> (w => w.My, default(string));
+ public static readonly BindableProperty MyProperty = MyPropertyKey.BindableProperty;
+
+ public string My {
+ get { return (string)GetValue (MyProperty); }
+ internal set { SetValue (MyPropertyKey, value); }
+ }
+}
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="UnapplyBindings">
+ <MemberSignature Language="C#" Value="protected void UnapplyBindings ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig instance void UnapplyBindings() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Unapplies all previously set bindings.</summary>
+ <remarks>
+ <para>This method removes all current bindings from the current context.</para>
+ <block subset="none" type="note">Changing a bound property requires that the binding count for a bound property must be 0. The <see cref="M:Xamarin.Forms.BindableObject.UnApplyBindings" /> method merely decrements the cound, and does not remove all bindings everywhere.</block>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IDynamicResourceHandler.SetDynamicResource">
+ <MemberSignature Language="C#" Value="void IDynamicResourceHandler.SetDynamicResource (Xamarin.Forms.BindableProperty property, string key);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IDynamicResourceHandler.SetDynamicResource(class Xamarin.Forms.BindableProperty property, string key) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="key" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="property">To be added.</param>
+ <param name="key">To be added.</param>
+ <summary>For internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Internals.IDynamicResourceHandler.SetDynamicResource">
+ <MemberSignature Language="C#" Value="void IDynamicResourceHandler.SetDynamicResource (Xamarin.Forms.BindableProperty property, string key);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.Internals.IDynamicResourceHandler.SetDynamicResource(class Xamarin.Forms.BindableProperty property, string key) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="key" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="property">To be added.</param>
+ <param name="key">To be added.</param>
+ <summary>For internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableObjectExtensions.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableObjectExtensions.xml
new file mode 100644
index 00000000..a37ea69f
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableObjectExtensions.xml
@@ -0,0 +1,161 @@
+<Type Name="BindableObjectExtensions" FullName="Xamarin.Forms.BindableObjectExtensions">
+ <TypeSignature Language="C#" Value="public static class BindableObjectExtensions" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract sealed beforefieldinit BindableObjectExtensions extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Contains convenience extension methods for <see cref="T:Xamarin.Forms.BindableObject" />.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="SetBinding">
+ <MemberSignature Language="C#" Value="public static void SetBinding (this Xamarin.Forms.BindableObject self, Xamarin.Forms.BindableProperty targetProperty, string path);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetBinding(class Xamarin.Forms.BindableObject self, class Xamarin.Forms.BindableProperty targetProperty, string path) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.BindableObject" RefType="this" />
+ <Parameter Name="targetProperty" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="path" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="self">The <see cref="T:Xamarin.Forms.BindableObject" />.</param>
+ <param name="targetProperty">The BindableProperty on which to set a binding.</param>
+ <param name="path">A <see cref="T:System.String" /> indicating the property path to bind to.</param>
+ <summary>Creates and applies a binding to a property.</summary>
+ <remarks>
+ <para>The following example shows how to use the extension method to set a binding.</para>
+ <example>
+ <code lang="C#"><![CDATA[
+var label = new Label ();
+label.SetBinding (Label.TextProperty, "Name");
+label.BindingContext = new {Name = "John Doe", Company = "Xamarin"};
+Debug.WriteLine (label.Text); //prints "John Doe"
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetBinding">
+ <MemberSignature Language="C#" Value="public static void SetBinding (this Xamarin.Forms.BindableObject self, Xamarin.Forms.BindableProperty targetProperty, string path, Xamarin.Forms.BindingMode mode = Xamarin.Forms.BindingMode.Default, Xamarin.Forms.IValueConverter converter = null, string stringFormat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetBinding(class Xamarin.Forms.BindableObject self, class Xamarin.Forms.BindableProperty targetProperty, string path, valuetype Xamarin.Forms.BindingMode mode, class Xamarin.Forms.IValueConverter converter, string stringFormat) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.BindableObject" RefType="this" />
+ <Parameter Name="targetProperty" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="path" Type="System.String" />
+ <Parameter Name="mode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="converter" Type="Xamarin.Forms.IValueConverter" />
+ <Parameter Name="stringFormat" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="self">The <see cref="T:Xamarin.Forms.BindableObject" />.</param>
+ <param name="targetProperty">The BindableProperty on which to set a bindinge.</param>
+ <param name="path">A <see cref="T:System.String" /> indicating the property path to bind to.</param>
+ <param name="mode">The <see cref="T:Xamarin.Forms.BindingMode" /> for the binding. This parameter is optional. Default is <see cref="E:Xamarin.Forms.BindingMode.Default" />.</param>
+ <param name="converter">An <see cref="T:Xamarin.Forms.IValueConverter" /> for the binding. This parameter is optional. Default is <see langword="null" />.</param>
+ <param name="stringFormat">A string used as stringFormat for the binding. This parameter is optional. Default is <see langword="null" />.</param>
+ <summary>Creates and applies a binding to a property.</summary>
+ <remarks>
+ <para>The following example shows how to use the extension method to set a binding.</para>
+ <example>
+ <code lang="C#"><![CDATA[
+var label = new Label ();
+label.SetBinding (Label.TextProperty, "Name");
+label.BindingContext = new {Name = "John Doe", Company = "Xamarin"};
+Debug.WriteLine (label.Text); //prints "John Doe"
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetBinding&lt;TSource&gt;">
+ <MemberSignature Language="C#" Value="public static void SetBinding&lt;TSource&gt; (this Xamarin.Forms.BindableObject self, Xamarin.Forms.BindableProperty targetProperty, System.Linq.Expressions.Expression&lt;Func&lt;TSource,object&gt;&gt; sourceProperty, Xamarin.Forms.BindingMode mode = Xamarin.Forms.BindingMode.Default, Xamarin.Forms.IValueConverter converter = null, string stringFormat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetBinding&lt;TSource&gt;(class Xamarin.Forms.BindableObject self, class Xamarin.Forms.BindableProperty targetProperty, class System.Linq.Expressions.Expression`1&lt;class System.Func`2&lt;!!TSource, object&gt;&gt; sourceProperty, valuetype Xamarin.Forms.BindingMode mode, class Xamarin.Forms.IValueConverter converter, string stringFormat) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TSource" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.BindableObject" RefType="this" />
+ <Parameter Name="targetProperty" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="sourceProperty" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;TSource,System.Object&gt;&gt;" />
+ <Parameter Name="mode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="converter" Type="Xamarin.Forms.IValueConverter" />
+ <Parameter Name="stringFormat" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TSource">The source type.</typeparam>
+ <param name="self">The BindableObject.</param>
+ <param name="targetProperty">The BindableProperty to bind to</param>
+ <param name="sourceProperty">An expression used to retrieve the source path.</param>
+ <param name="mode">The BindingMode for the binding. This parameter is optional. Default is <see cref="E:Xamarin.Forms.BindingMode.Default" />.</param>
+ <param name="converter">An IValueConverter for the binding. This parameter is optional. Default is <see langword="null" />.</param>
+ <param name="stringFormat">A string used as stringFormat for the binding. This parameter is optional. Default is <see langword="null" />.</param>
+ <summary>Creates and applies a binding from an expression.</summary>
+ <remarks>
+ <para>This extension method uses Expression instead of path to creates and sets bindings. Using Expressions is more refactoring friendly.</para>
+ <para>This following example illustrates the setting of a binding using the extension method.</para>
+ <example>
+ <code lang="C#"><![CDATA[
+public class PersonViewModel
+{
+ public string Name { get; set; }
+ public string Company { get; set; }
+}
+
+var label = new Label ();
+label.SetBinding<PersonViewModel> (Label.TextProperty, vm => vm.Name);
+label.BindingContext = new PersonViewModel {
+ Name = "John Doe",
+ Company = "Xamarin"
+};
+Debug.WriteLine (label.Text); //prints "John Doe"
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangedDelegate.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangedDelegate.xml
new file mode 100644
index 00000000..cf42d663
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangedDelegate.xml
@@ -0,0 +1,32 @@
+<Type Name="BindableProperty+BindingPropertyChangedDelegate" FullName="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate">
+ <TypeSignature Language="C#" Value="public delegate void BindableProperty.BindingPropertyChangedDelegate(BindableObject bindable, object oldValue, object newValue);" />
+ <TypeSignature Language="ILAsm" Value=".class nested public auto ansi sealed BindableProperty/BindingPropertyChangedDelegate extends System.MulticastDelegate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Delegate</BaseTypeName>
+ </Base>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="oldValue" Type="System.Object" />
+ <Parameter Name="newValue" Type="System.Object" />
+ </Parameters>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <param name="oldValue">To be added.</param>
+ <param name="newValue">To be added.</param>
+ <summary>Delegate for BindableProperty.PropertyChanged.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangedDelegate`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangedDelegate`1.xml
new file mode 100644
index 00000000..79e59821
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangedDelegate`1.xml
@@ -0,0 +1,40 @@
+<Type Name="BindableProperty+BindingPropertyChangedDelegate&lt;TPropertyType&gt;" FullName="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate&lt;TPropertyType&gt;">
+ <TypeSignature Language="C#" Value="public delegate void BindableProperty.BindingPropertyChangedDelegate&lt;in TPropertyType&gt;(BindableObject bindable, TPropertyType oldValue, TPropertyType newValue);" />
+ <TypeSignature Language="ILAsm" Value=".class nested public auto ansi sealed BindableProperty/BindingPropertyChangedDelegate`1&lt;- TPropertyType&gt; extends System.MulticastDelegate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="TPropertyType">
+ <Constraints>
+ <ParameterAttribute>Contravariant</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>System.Delegate</BaseTypeName>
+ </Base>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="oldValue" Type="TPropertyType" />
+ <Parameter Name="newValue" Type="TPropertyType" />
+ </Parameters>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <typeparam name="TPropertyType">To be added.</typeparam>
+ <param name="bindable">To be added.</param>
+ <param name="oldValue">To be added.</param>
+ <param name="newValue">To be added.</param>
+ <summary>Strongly-typed delegate for BindableProperty.PropertyChanged.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangingDelegate.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangingDelegate.xml
new file mode 100644
index 00000000..a694bab0
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangingDelegate.xml
@@ -0,0 +1,32 @@
+<Type Name="BindableProperty+BindingPropertyChangingDelegate" FullName="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate">
+ <TypeSignature Language="C#" Value="public delegate void BindableProperty.BindingPropertyChangingDelegate(BindableObject bindable, object oldValue, object newValue);" />
+ <TypeSignature Language="ILAsm" Value=".class nested public auto ansi sealed BindableProperty/BindingPropertyChangingDelegate extends System.MulticastDelegate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Delegate</BaseTypeName>
+ </Base>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="oldValue" Type="System.Object" />
+ <Parameter Name="newValue" Type="System.Object" />
+ </Parameters>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <param name="oldValue">To be added.</param>
+ <param name="newValue">To be added.</param>
+ <summary>Delegate for BindableProperty.PropertyChanging.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangingDelegate`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangingDelegate`1.xml
new file mode 100644
index 00000000..24079ce5
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+BindingPropertyChangingDelegate`1.xml
@@ -0,0 +1,40 @@
+<Type Name="BindableProperty+BindingPropertyChangingDelegate&lt;TPropertyType&gt;" FullName="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate&lt;TPropertyType&gt;">
+ <TypeSignature Language="C#" Value="public delegate void BindableProperty.BindingPropertyChangingDelegate&lt;in TPropertyType&gt;(BindableObject bindable, TPropertyType oldValue, TPropertyType newValue);" />
+ <TypeSignature Language="ILAsm" Value=".class nested public auto ansi sealed BindableProperty/BindingPropertyChangingDelegate`1&lt;- TPropertyType&gt; extends System.MulticastDelegate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="TPropertyType">
+ <Constraints>
+ <ParameterAttribute>Contravariant</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>System.Delegate</BaseTypeName>
+ </Base>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="oldValue" Type="TPropertyType" />
+ <Parameter Name="newValue" Type="TPropertyType" />
+ </Parameters>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <typeparam name="TPropertyType">To be added.</typeparam>
+ <param name="bindable">To be added.</param>
+ <param name="oldValue">To be added.</param>
+ <param name="newValue">To be added.</param>
+ <summary>Strongly-typed delegate for BindableProperty.PropertyChanging.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CoerceValueDelegate.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CoerceValueDelegate.xml
new file mode 100644
index 00000000..3f129f3a
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CoerceValueDelegate.xml
@@ -0,0 +1,31 @@
+<Type Name="BindableProperty+CoerceValueDelegate" FullName="Xamarin.Forms.BindableProperty+CoerceValueDelegate">
+ <TypeSignature Language="C#" Value="public delegate object BindableProperty.CoerceValueDelegate(BindableObject bindable, object value);" />
+ <TypeSignature Language="ILAsm" Value=".class nested public auto ansi sealed BindableProperty/CoerceValueDelegate extends System.MulticastDelegate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Delegate</BaseTypeName>
+ </Base>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Delegate for BindableProperty.CoerceValue.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CoerceValueDelegate`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CoerceValueDelegate`1.xml
new file mode 100644
index 00000000..74335f08
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CoerceValueDelegate`1.xml
@@ -0,0 +1,35 @@
+<Type Name="BindableProperty+CoerceValueDelegate&lt;TPropertyType&gt;" FullName="Xamarin.Forms.BindableProperty+CoerceValueDelegate&lt;TPropertyType&gt;">
+ <TypeSignature Language="C#" Value="public delegate TPropertyType BindableProperty.CoerceValueDelegate&lt;TPropertyType&gt;(BindableObject bindable, TPropertyType value);" />
+ <TypeSignature Language="ILAsm" Value=".class nested public auto ansi sealed BindableProperty/CoerceValueDelegate`1&lt;TPropertyType&gt; extends System.MulticastDelegate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="TPropertyType" />
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>System.Delegate</BaseTypeName>
+ </Base>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="value" Type="TPropertyType" />
+ </Parameters>
+ <ReturnValue>
+ <ReturnType>TPropertyType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <typeparam name="TPropertyType">To be added.</typeparam>
+ <param name="bindable">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Strongly-typed delegate for BindableProperty.CoerceValue.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CreateDefaultValueDelegate.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CreateDefaultValueDelegate.xml
new file mode 100644
index 00000000..28578019
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CreateDefaultValueDelegate.xml
@@ -0,0 +1,26 @@
+<Type Name="BindableProperty+CreateDefaultValueDelegate" FullName="Xamarin.Forms.BindableProperty+CreateDefaultValueDelegate">
+ <TypeSignature Language="C#" Value="public delegate object BindableProperty.CreateDefaultValueDelegate(BindableObject bindable);" />
+ <TypeSignature Language="ILAsm" Value=".class nested public auto ansi sealed BindableProperty/CreateDefaultValueDelegate extends System.MulticastDelegate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Delegate</BaseTypeName>
+ </Base>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <summary>Strongly typed delegate for BindableProperty.DefaultValueCreator.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CreateDefaultValueDelegate`2.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CreateDefaultValueDelegate`2.xml
new file mode 100644
index 00000000..cbcaf7de
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+CreateDefaultValueDelegate`2.xml
@@ -0,0 +1,40 @@
+<Type Name="BindableProperty+CreateDefaultValueDelegate&lt;TDeclarer,TPropertyType&gt;" FullName="Xamarin.Forms.BindableProperty+CreateDefaultValueDelegate&lt;TDeclarer,TPropertyType&gt;">
+ <TypeSignature Language="C#" Value="public delegate TPropertyType BindableProperty.CreateDefaultValueDelegate&lt;in TDeclarer,out TPropertyType&gt;(TDeclarer bindable);" />
+ <TypeSignature Language="ILAsm" Value=".class nested public auto ansi sealed BindableProperty/CreateDefaultValueDelegate`2&lt;- TDeclarer, + TPropertyType&gt; extends System.MulticastDelegate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="TDeclarer">
+ <Constraints>
+ <ParameterAttribute>Contravariant</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ <TypeParameter Name="TPropertyType">
+ <Constraints>
+ <ParameterAttribute>Covariant</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>System.Delegate</BaseTypeName>
+ </Base>
+ <Parameters>
+ <Parameter Name="bindable" Type="TDeclarer" />
+ </Parameters>
+ <ReturnValue>
+ <ReturnType>TPropertyType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <typeparam name="TDeclarer">To be added.</typeparam>
+ <typeparam name="TPropertyType">To be added.</typeparam>
+ <param name="bindable">To be added.</param>
+ <summary>Delegate for BindableProperty.DefaultValueCreator.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+ValidateValueDelegate.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+ValidateValueDelegate.xml
new file mode 100644
index 00000000..22b2a020
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+ValidateValueDelegate.xml
@@ -0,0 +1,31 @@
+<Type Name="BindableProperty+ValidateValueDelegate" FullName="Xamarin.Forms.BindableProperty+ValidateValueDelegate">
+ <TypeSignature Language="C#" Value="public delegate bool BindableProperty.ValidateValueDelegate(BindableObject bindable, object value);" />
+ <TypeSignature Language="ILAsm" Value=".class nested public auto ansi sealed BindableProperty/ValidateValueDelegate extends System.MulticastDelegate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Delegate</BaseTypeName>
+ </Base>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Delegate for BindableProperty.ValidateValue.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+ValidateValueDelegate`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+ValidateValueDelegate`1.xml
new file mode 100644
index 00000000..456e5a3d
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty+ValidateValueDelegate`1.xml
@@ -0,0 +1,39 @@
+<Type Name="BindableProperty+ValidateValueDelegate&lt;TPropertyType&gt;" FullName="Xamarin.Forms.BindableProperty+ValidateValueDelegate&lt;TPropertyType&gt;">
+ <TypeSignature Language="C#" Value="public delegate bool BindableProperty.ValidateValueDelegate&lt;in TPropertyType&gt;(BindableObject bindable, TPropertyType value);" />
+ <TypeSignature Language="ILAsm" Value=".class nested public auto ansi sealed BindableProperty/ValidateValueDelegate`1&lt;- TPropertyType&gt; extends System.MulticastDelegate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="TPropertyType">
+ <Constraints>
+ <ParameterAttribute>Contravariant</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>System.Delegate</BaseTypeName>
+ </Base>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="value" Type="TPropertyType" />
+ </Parameters>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <typeparam name="TPropertyType">To be added.</typeparam>
+ <param name="bindable">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Strongly-typed delegate for BindableProperty.ValidateValue.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty.xml
new file mode 100644
index 00000000..871161b5
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindableProperty.xml
@@ -0,0 +1,904 @@
+<Type Name="BindableProperty" FullName="Xamarin.Forms.BindableProperty">
+ <TypeSignature Language="C#" Value="public sealed class BindableProperty" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit BindableProperty extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.DebuggerDisplay("{PropertyName}")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.BindablePropertyConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A BindableProperty is a backing store for properties allowing bindings on <see cref="T:Xamarin.Forms.BindableObject" />.</summary>
+ <remarks>
+ </remarks>
+ <related type="article" href="https://blog.xamarin.com/introduction-to-data-binding/" />
+ </Docs>
+ <Members>
+ <Member MemberName="Create">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindableProperty Create (string propertyName, Type returnType, Type declaringType, object defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWay, Xamarin.Forms.BindableProperty.ValidateValueDelegate validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate coerceValue = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindableProperty Create(string propertyName, class System.Type returnType, class System.Type declaringType, object defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate coerceValue) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ <Parameter Name="returnType" Type="System.Type" />
+ <Parameter Name="declaringType" Type="System.Type" />
+ <Parameter Name="defaultValue" Type="System.Object" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the BindableProperty.</param>
+ <param name="returnType">The type of the property.</param>
+ <param name="declaringType">The type of the declaring object.</param>
+ <param name="defaultValue">The default value for the property.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">A delegate to be ran when the value has changed. This parameter is optional. Default is null.</param>
+ <param name="propertyChanging">A delegate to be ran when the value will change. This parameter is optional. Default is null.</param>
+ <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
+ <summary>Creates a new instance of the BindableProperty class.</summary>
+ <returns>A newly created BindableProperty.</returns>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Create">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindableProperty Create (string propertyName, Type returnType, Type declaringType, object defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWay, Xamarin.Forms.BindableProperty.ValidateValueDelegate validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate coerceValue = null, Xamarin.Forms.BindableProperty.CreateDefaultValueDelegate defaultValueCreator = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindableProperty Create(string propertyName, class System.Type returnType, class System.Type declaringType, object defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate coerceValue, class Xamarin.Forms.BindableProperty/CreateDefaultValueDelegate defaultValueCreator) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ <Parameter Name="returnType" Type="System.Type" />
+ <Parameter Name="declaringType" Type="System.Type" />
+ <Parameter Name="defaultValue" Type="System.Object" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate" />
+ <Parameter Name="defaultValueCreator" Type="Xamarin.Forms.BindableProperty+CreateDefaultValueDelegate" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the BindableProperty.</param>
+ <param name="returnType">The type of the property.</param>
+ <param name="declaringType">The type of the declaring object.</param>
+ <param name="defaultValue">The default value for the property.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">A delegate to be ran when the value has changed. This parameter is optional. Default is null.</param>
+ <param name="propertyChanging">A delegate to be ran when the value will change. This parameter is optional. Default is null.</param>
+ <param name="coerceValue">To be added.</param>
+ <param name="defaultValueCreator">A Func used to initialize default value for reference types..</param>
+ <summary>Creates a new instance of the BindableProperty class.</summary>
+ <returns>A newly created BindableProperty.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Create&lt;TDeclarer,TPropertyType&gt;">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindableProperty Create&lt;TDeclarer,TPropertyType&gt; (System.Linq.Expressions.Expression&lt;Func&lt;TDeclarer,TPropertyType&gt;&gt; getter, TPropertyType defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWay, Xamarin.Forms.BindableProperty.ValidateValueDelegate&lt;TPropertyType&gt; validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate&lt;TPropertyType&gt; propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate&lt;TPropertyType&gt; propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate&lt;TPropertyType&gt; coerceValue = null) where TDeclarer : Xamarin.Forms.BindableObject;" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindableProperty Create&lt;(class Xamarin.Forms.BindableObject) TDeclarer, TPropertyType&gt;(class System.Linq.Expressions.Expression`1&lt;class System.Func`2&lt;!!TDeclarer, !!TPropertyType&gt;&gt; getter, !!TPropertyType defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate`1&lt;!!TPropertyType&gt; validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate`1&lt;!!TPropertyType&gt; propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate`1&lt;!!TPropertyType&gt; propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate`1&lt;!!TPropertyType&gt; coerceValue) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TDeclarer">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ <TypeParameter Name="TPropertyType" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="getter" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;TDeclarer,TPropertyType&gt;&gt;" />
+ <Parameter Name="defaultValue" Type="TPropertyType" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate&lt;TPropertyType&gt;" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
+ <typeparam name="TPropertyType">The type of the property.</typeparam>
+ <param name="getter">An expression identifying the getter for the property using this BindableProperty as backing store.</param>
+ <param name="defaultValue">Default value for the BindableProperty.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">To be added.</param>
+ <param name="propertyChanging">To be added.</param>
+ <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
+ <summary>Deprecated. Do not use.</summary>
+ <returns>A newly created BindableProperty.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Create&lt;TDeclarer,TPropertyType&gt;">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindableProperty Create&lt;TDeclarer,TPropertyType&gt; (System.Linq.Expressions.Expression&lt;Func&lt;TDeclarer,TPropertyType&gt;&gt; getter, TPropertyType defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWay, Xamarin.Forms.BindableProperty.ValidateValueDelegate&lt;TPropertyType&gt; validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate&lt;TPropertyType&gt; propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate&lt;TPropertyType&gt; propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate&lt;TPropertyType&gt; coerceValue = null, Xamarin.Forms.BindableProperty.CreateDefaultValueDelegate&lt;TDeclarer,TPropertyType&gt; defaultValueCreator = null) where TDeclarer : Xamarin.Forms.BindableObject;" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindableProperty Create&lt;(class Xamarin.Forms.BindableObject) TDeclarer, TPropertyType&gt;(class System.Linq.Expressions.Expression`1&lt;class System.Func`2&lt;!!TDeclarer, !!TPropertyType&gt;&gt; getter, !!TPropertyType defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate`1&lt;!!TPropertyType&gt; validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate`1&lt;!!TPropertyType&gt; propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate`1&lt;!!TPropertyType&gt; propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate`1&lt;!!TPropertyType&gt; coerceValue, class Xamarin.Forms.BindableProperty/CreateDefaultValueDelegate`2&lt;!!TDeclarer, !!TPropertyType&gt; defaultValueCreator) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Generic versions of Create () are no longer supported and deprecated. They will be removed soon.")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TDeclarer">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ <TypeParameter Name="TPropertyType" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="getter" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;TDeclarer,TPropertyType&gt;&gt;" />
+ <Parameter Name="defaultValue" Type="TPropertyType" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="defaultValueCreator" Type="Xamarin.Forms.BindableProperty+CreateDefaultValueDelegate&lt;TDeclarer,TPropertyType&gt;" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
+ <typeparam name="TPropertyType">The type of the property.</typeparam>
+ <param name="getter">An expression identifying the getter for the property using this BindableProperty as backing store.</param>
+ <param name="defaultValue">Default value for the BindableProperty.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">To be added.</param>
+ <param name="propertyChanging">To be added.</param>
+ <param name="coerceValue">To be added.</param>
+ <param name="defaultValueCreator">A Func used to initialize default value for reference types..</param>
+ <summary>Deprecated. Do not use.</summary>
+ <returns>A newly created BindableProperty.</returns>
+ <remarks></remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateAttached">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindableProperty CreateAttached (string propertyName, Type returnType, Type declaringType, object defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWay, Xamarin.Forms.BindableProperty.ValidateValueDelegate validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate coerceValue = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindableProperty CreateAttached(string propertyName, class System.Type returnType, class System.Type declaringType, object defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate coerceValue) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ <Parameter Name="returnType" Type="System.Type" />
+ <Parameter Name="declaringType" Type="System.Type" />
+ <Parameter Name="defaultValue" Type="System.Object" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the BindableProperty.</param>
+ <param name="returnType">The type of the property.</param>
+ <param name="declaringType">The type of the declaring object.</param>
+ <param name="defaultValue">The default value for the property.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">A delegate to be ran when the value has changed. This parameter is optional. Default is null.</param>
+ <param name="propertyChanging">A delegate to be ran when the value will change. This parameter is optional. Default is null.</param>
+ <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
+ <summary>Creates a new instance of the BindableProperty class for an attached property.</summary>
+ <returns>A newly created attached BindableProperty.</returns>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateAttached">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindableProperty CreateAttached (string propertyName, Type returnType, Type declaringType, object defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWay, Xamarin.Forms.BindableProperty.ValidateValueDelegate validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate coerceValue = null, Xamarin.Forms.BindableProperty.CreateDefaultValueDelegate defaultValueCreator = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindableProperty CreateAttached(string propertyName, class System.Type returnType, class System.Type declaringType, object defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate coerceValue, class Xamarin.Forms.BindableProperty/CreateDefaultValueDelegate defaultValueCreator) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ <Parameter Name="returnType" Type="System.Type" />
+ <Parameter Name="declaringType" Type="System.Type" />
+ <Parameter Name="defaultValue" Type="System.Object" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate" />
+ <Parameter Name="defaultValueCreator" Type="Xamarin.Forms.BindableProperty+CreateDefaultValueDelegate" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the BindableProperty.</param>
+ <param name="returnType">The type of the property.</param>
+ <param name="declaringType">The type of the declaring object.</param>
+ <param name="defaultValue">The default value for the property.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">A delegate to be ran when the value has changed. This parameter is optional. Default is null.</param>
+ <param name="propertyChanging">A delegate to be ran when the value will change. This parameter is optional. Default is null.</param>
+ <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
+ <param name="defaultValueCreator">A Func used to initialize default value for reference types..</param>
+ <summary>Creates a new instance of the BindableProperty class for an attached property.</summary>
+ <returns>A newly created attached BindableProperty.</returns>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateAttached&lt;TDeclarer,TPropertyType&gt;">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindableProperty CreateAttached&lt;TDeclarer,TPropertyType&gt; (System.Linq.Expressions.Expression&lt;Func&lt;Xamarin.Forms.BindableObject,TPropertyType&gt;&gt; staticgetter, TPropertyType defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWay, Xamarin.Forms.BindableProperty.ValidateValueDelegate&lt;TPropertyType&gt; validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate&lt;TPropertyType&gt; propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate&lt;TPropertyType&gt; propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate&lt;TPropertyType&gt; coerceValue = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindableProperty CreateAttached&lt;TDeclarer, TPropertyType&gt;(class System.Linq.Expressions.Expression`1&lt;class System.Func`2&lt;class Xamarin.Forms.BindableObject, !!TPropertyType&gt;&gt; staticgetter, !!TPropertyType defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate`1&lt;!!TPropertyType&gt; validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate`1&lt;!!TPropertyType&gt; propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate`1&lt;!!TPropertyType&gt; propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate`1&lt;!!TPropertyType&gt; coerceValue) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TDeclarer" />
+ <TypeParameter Name="TPropertyType" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="staticgetter" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;Xamarin.Forms.BindableObject,TPropertyType&gt;&gt;" />
+ <Parameter Name="defaultValue" Type="TPropertyType" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate&lt;TPropertyType&gt;" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
+ <typeparam name="TPropertyType">The type of the property.</typeparam>
+ <param name="staticgetter">An expression identifying a static method returning the value of the property using this BindableProperty as backing store.</param>
+ <param name="defaultValue">Default value for the BindableProperty.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">To be added.</param>
+ <param name="propertyChanging">To be added.</param>
+ <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
+ <summary>Deprecated. Do not use.</summary>
+ <returns>A newly created BindableProperty.</returns>
+ <remarks>
+ <para>Attached properties are bindable properties that are bound to an object other than their parent. Often, they are used for child items in tables and grids, where data about the location of an item is maintained by its parent, but must be accessed from the child item itself.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateAttached&lt;TDeclarer,TPropertyType&gt;">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindableProperty CreateAttached&lt;TDeclarer,TPropertyType&gt; (System.Linq.Expressions.Expression&lt;Func&lt;Xamarin.Forms.BindableObject,TPropertyType&gt;&gt; staticgetter, TPropertyType defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWay, Xamarin.Forms.BindableProperty.ValidateValueDelegate&lt;TPropertyType&gt; validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate&lt;TPropertyType&gt; propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate&lt;TPropertyType&gt; propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate&lt;TPropertyType&gt; coerceValue = null, Xamarin.Forms.BindableProperty.CreateDefaultValueDelegate&lt;Xamarin.Forms.BindableObject,TPropertyType&gt; defaultValueCreator = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindableProperty CreateAttached&lt;TDeclarer, TPropertyType&gt;(class System.Linq.Expressions.Expression`1&lt;class System.Func`2&lt;class Xamarin.Forms.BindableObject, !!TPropertyType&gt;&gt; staticgetter, !!TPropertyType defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate`1&lt;!!TPropertyType&gt; validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate`1&lt;!!TPropertyType&gt; propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate`1&lt;!!TPropertyType&gt; propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate`1&lt;!!TPropertyType&gt; coerceValue, class Xamarin.Forms.BindableProperty/CreateDefaultValueDelegate`2&lt;class Xamarin.Forms.BindableObject, !!TPropertyType&gt; defaultValueCreator) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Generic versions of Create () are no longer supported and deprecated. They will be removed soon.")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TDeclarer" />
+ <TypeParameter Name="TPropertyType" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="staticgetter" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;Xamarin.Forms.BindableObject,TPropertyType&gt;&gt;" />
+ <Parameter Name="defaultValue" Type="TPropertyType" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="defaultValueCreator" Type="Xamarin.Forms.BindableProperty+CreateDefaultValueDelegate&lt;Xamarin.Forms.BindableObject,TPropertyType&gt;" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
+ <typeparam name="TPropertyType">The type of the property.</typeparam>
+ <param name="staticgetter">An expression identifying a static method returning the value of the property using this BindableProperty as backing store.</param>
+ <param name="defaultValue">Default value for the BindableProperty.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">To be added.</param>
+ <param name="propertyChanging">To be added.</param>
+ <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
+ <param name="defaultValueCreator">A Func used to initialize default value for reference types..</param>
+ <summary>Deprecated. Do not use.</summary>
+ <returns>A newly created BindableProperty.</returns>
+ <remarks>
+ <para>Attached properties are bindable properties that are bound to an object other than their parent. Often, they are used for child items in tables and grids, where data about the location of an item is maintained by its parent, but must be accessed from the child item itself.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateAttachedReadOnly">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindablePropertyKey CreateAttachedReadOnly (string propertyName, Type returnType, Type declaringType, object defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWayToSource, Xamarin.Forms.BindableProperty.ValidateValueDelegate validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate coerceValue = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindablePropertyKey CreateAttachedReadOnly(string propertyName, class System.Type returnType, class System.Type declaringType, object defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate coerceValue) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindablePropertyKey</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ <Parameter Name="returnType" Type="System.Type" />
+ <Parameter Name="declaringType" Type="System.Type" />
+ <Parameter Name="defaultValue" Type="System.Object" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the BindableProperty.</param>
+ <param name="returnType">The type of the property.</param>
+ <param name="declaringType">The type of the declaring object.</param>
+ <param name="defaultValue">The default value for the property.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">A delegate to be ran when the value has changed. This parameter is optional. Default is null.</param>
+ <param name="propertyChanging">A delegate to be ran when the value will change. This parameter is optional. Default is null.</param>
+ <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
+ <summary>Creates a new instance of the BindableProperty class for attached read-only properties.</summary>
+ <returns>A newly created attached read-only BindableProperty.</returns>
+ <remarks><para>Attached properties are bindable properties that are bound to an object other than their parent. Often, they are used for child items in tables and grids, where data about the location of an item is maintained by its parent, but must be accessed from the child item itself.</para></remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateAttachedReadOnly">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindablePropertyKey CreateAttachedReadOnly (string propertyName, Type returnType, Type declaringType, object defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWayToSource, Xamarin.Forms.BindableProperty.ValidateValueDelegate validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate coerceValue = null, Xamarin.Forms.BindableProperty.CreateDefaultValueDelegate defaultValueCreator = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindablePropertyKey CreateAttachedReadOnly(string propertyName, class System.Type returnType, class System.Type declaringType, object defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate coerceValue, class Xamarin.Forms.BindableProperty/CreateDefaultValueDelegate defaultValueCreator) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindablePropertyKey</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ <Parameter Name="returnType" Type="System.Type" />
+ <Parameter Name="declaringType" Type="System.Type" />
+ <Parameter Name="defaultValue" Type="System.Object" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate" />
+ <Parameter Name="defaultValueCreator" Type="Xamarin.Forms.BindableProperty+CreateDefaultValueDelegate" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the BindableProperty.</param>
+ <param name="returnType">The type of the property.</param>
+ <param name="declaringType">The type of the declaring object.</param>
+ <param name="defaultValue">The default value for the property.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">A delegate to be ran when the value has changed. This parameter is optional. Default is null.</param>
+ <param name="propertyChanging">A delegate to be ran when the value will change. This parameter is optional. Default is null.</param>
+ <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
+ <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
+ <summary>Creates a new instance of the BindableProperty class for attached read-only properties.</summary>
+ <returns>A newly created attached read-only BindableProperty.</returns>
+ <remarks><para>Attached properties are bindable properties that are bound to an object other than their parent. Often, they are used for child items in tables and grids, where data about the location of an item is maintained by its parent, but must be accessed from the child item itself.</para></remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateAttachedReadOnly&lt;TDeclarer,TPropertyType&gt;">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindablePropertyKey CreateAttachedReadOnly&lt;TDeclarer,TPropertyType&gt; (System.Linq.Expressions.Expression&lt;Func&lt;Xamarin.Forms.BindableObject,TPropertyType&gt;&gt; staticgetter, TPropertyType defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWayToSource, Xamarin.Forms.BindableProperty.ValidateValueDelegate&lt;TPropertyType&gt; validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate&lt;TPropertyType&gt; propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate&lt;TPropertyType&gt; propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate&lt;TPropertyType&gt; coerceValue = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindablePropertyKey CreateAttachedReadOnly&lt;TDeclarer, TPropertyType&gt;(class System.Linq.Expressions.Expression`1&lt;class System.Func`2&lt;class Xamarin.Forms.BindableObject, !!TPropertyType&gt;&gt; staticgetter, !!TPropertyType defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate`1&lt;!!TPropertyType&gt; validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate`1&lt;!!TPropertyType&gt; propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate`1&lt;!!TPropertyType&gt; propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate`1&lt;!!TPropertyType&gt; coerceValue) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindablePropertyKey</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TDeclarer" />
+ <TypeParameter Name="TPropertyType" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="staticgetter" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;Xamarin.Forms.BindableObject,TPropertyType&gt;&gt;" />
+ <Parameter Name="defaultValue" Type="TPropertyType" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate&lt;TPropertyType&gt;" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
+ <typeparam name="TPropertyType">The type of the property.</typeparam>
+ <param name="staticgetter">An expression identifying a static method returning the value of the property using this BindableProperty as backing store.</param>
+ <param name="defaultValue">Default value for the BindableProperty.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">To be added.</param>
+ <param name="propertyChanging">To be added.</param>
+ <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
+ <summary>Deprecated. Do not use.</summary>
+ <returns>A newly created BindablePropertyKey.</returns>
+ <remarks><para>Attached properties are bindable properties that are bound to an object other than their parent. Often, they are used for child items in tables and grids, where data about the location of an item is maintained by its parent, but must be accessed from the child item itself.</para></remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateAttachedReadOnly&lt;TDeclarer,TPropertyType&gt;">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindablePropertyKey CreateAttachedReadOnly&lt;TDeclarer,TPropertyType&gt; (System.Linq.Expressions.Expression&lt;Func&lt;Xamarin.Forms.BindableObject,TPropertyType&gt;&gt; staticgetter, TPropertyType defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWayToSource, Xamarin.Forms.BindableProperty.ValidateValueDelegate&lt;TPropertyType&gt; validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate&lt;TPropertyType&gt; propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate&lt;TPropertyType&gt; propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate&lt;TPropertyType&gt; coerceValue = null, Xamarin.Forms.BindableProperty.CreateDefaultValueDelegate&lt;Xamarin.Forms.BindableObject,TPropertyType&gt; defaultValueCreator = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindablePropertyKey CreateAttachedReadOnly&lt;TDeclarer, TPropertyType&gt;(class System.Linq.Expressions.Expression`1&lt;class System.Func`2&lt;class Xamarin.Forms.BindableObject, !!TPropertyType&gt;&gt; staticgetter, !!TPropertyType defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate`1&lt;!!TPropertyType&gt; validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate`1&lt;!!TPropertyType&gt; propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate`1&lt;!!TPropertyType&gt; propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate`1&lt;!!TPropertyType&gt; coerceValue, class Xamarin.Forms.BindableProperty/CreateDefaultValueDelegate`2&lt;class Xamarin.Forms.BindableObject, !!TPropertyType&gt; defaultValueCreator) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Generic versions of Create () are no longer supported and deprecated. They will be removed soon.")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindablePropertyKey</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TDeclarer" />
+ <TypeParameter Name="TPropertyType" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="staticgetter" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;Xamarin.Forms.BindableObject,TPropertyType&gt;&gt;" />
+ <Parameter Name="defaultValue" Type="TPropertyType" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="defaultValueCreator" Type="Xamarin.Forms.BindableProperty+CreateDefaultValueDelegate&lt;Xamarin.Forms.BindableObject,TPropertyType&gt;" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
+ <typeparam name="TPropertyType">The type of the property.</typeparam>
+ <param name="staticgetter">An expression identifying a static method returning the value of the property using this BindableProperty as backing store.</param>
+ <param name="defaultValue">Default value for the BindableProperty.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">To be added.</param>
+ <param name="propertyChanging">To be added.</param>
+ <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
+ <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
+ <summary>Deprecated. Do not use.</summary>
+ <returns>A newly created BindablePropertyKey.</returns>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateReadOnly">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindablePropertyKey CreateReadOnly (string propertyName, Type returnType, Type declaringType, object defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWayToSource, Xamarin.Forms.BindableProperty.ValidateValueDelegate validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate coerceValue = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindablePropertyKey CreateReadOnly(string propertyName, class System.Type returnType, class System.Type declaringType, object defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate coerceValue) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindablePropertyKey</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ <Parameter Name="returnType" Type="System.Type" />
+ <Parameter Name="declaringType" Type="System.Type" />
+ <Parameter Name="defaultValue" Type="System.Object" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the BindableProperty.</param>
+ <param name="returnType">The type of the property.</param>
+ <param name="declaringType">The type of the declaring object.</param>
+ <param name="defaultValue">The default value for the property.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">To be added.</param>
+ <param name="propertyChanging">To be added.</param>
+ <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
+ <summary>Creates a new instance of the BindablePropertyKey class.</summary>
+ <returns>
+ </returns>
+ <remarks><para>Attached properties are bindable properties that are bound to an object other than their parent. Often, they are used for child items in tables and grids, where data about the location of an item is maintained by its parent, but must be accessed from the child item itself.</para></remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateReadOnly">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindablePropertyKey CreateReadOnly (string propertyName, Type returnType, Type declaringType, object defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWayToSource, Xamarin.Forms.BindableProperty.ValidateValueDelegate validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate coerceValue = null, Xamarin.Forms.BindableProperty.CreateDefaultValueDelegate defaultValueCreator = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindablePropertyKey CreateReadOnly(string propertyName, class System.Type returnType, class System.Type declaringType, object defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate coerceValue, class Xamarin.Forms.BindableProperty/CreateDefaultValueDelegate defaultValueCreator) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindablePropertyKey</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ <Parameter Name="returnType" Type="System.Type" />
+ <Parameter Name="declaringType" Type="System.Type" />
+ <Parameter Name="defaultValue" Type="System.Object" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate" />
+ <Parameter Name="defaultValueCreator" Type="Xamarin.Forms.BindableProperty+CreateDefaultValueDelegate" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the BindableProperty.</param>
+ <param name="returnType">The type of the property.</param>
+ <param name="declaringType">The type of the declaring object.</param>
+ <param name="defaultValue">The default value for the property.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">To be added.</param>
+ <param name="propertyChanging">To be added.</param>
+ <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
+ <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
+ <summary>Creates a new instance of the BindablePropertyKey class.</summary>
+ <returns>
+ </returns><para>Attached properties are bindable properties that are bound to an object other than their parent. Often, they are used for child items in tables and grids, where data about the location of an item is maintained by its parent, but must be accessed from the child item itself.</para><remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateReadOnly&lt;TDeclarer,TPropertyType&gt;">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindablePropertyKey CreateReadOnly&lt;TDeclarer,TPropertyType&gt; (System.Linq.Expressions.Expression&lt;Func&lt;TDeclarer,TPropertyType&gt;&gt; getter, TPropertyType defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWayToSource, Xamarin.Forms.BindableProperty.ValidateValueDelegate&lt;TPropertyType&gt; validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate&lt;TPropertyType&gt; propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate&lt;TPropertyType&gt; propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate&lt;TPropertyType&gt; coerceValue = null) where TDeclarer : Xamarin.Forms.BindableObject;" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindablePropertyKey CreateReadOnly&lt;(class Xamarin.Forms.BindableObject) TDeclarer, TPropertyType&gt;(class System.Linq.Expressions.Expression`1&lt;class System.Func`2&lt;!!TDeclarer, !!TPropertyType&gt;&gt; getter, !!TPropertyType defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate`1&lt;!!TPropertyType&gt; validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate`1&lt;!!TPropertyType&gt; propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate`1&lt;!!TPropertyType&gt; propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate`1&lt;!!TPropertyType&gt; coerceValue) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindablePropertyKey</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TDeclarer">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ <TypeParameter Name="TPropertyType" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="getter" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;TDeclarer,TPropertyType&gt;&gt;" />
+ <Parameter Name="defaultValue" Type="TPropertyType" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate&lt;TPropertyType&gt;" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
+ <typeparam name="TPropertyType">The type of the property.</typeparam>
+ <param name="getter">An expression identifying the getter for the property using this BindableProperty as backing store.</param>
+ <param name="defaultValue">Default value for the BindableProperty.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">A delegate to be ran when the value has changed. This parameter is optional. Default is null.</param>
+ <param name="propertyChanging">A delegate to be ran when the value will change. This parameter is optional. Default is null.</param>
+ <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
+ <summary>Deprecated. Do not use.</summary>
+ <returns>A newly created BindablePropertyKey.</returns>
+ <remarks>
+ <para>A BindablePropertyKey is used to restrict write access to a property, either via SetValue() or binding. A BindableProperty is usually defined too, to give broader read access</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateReadOnly&lt;TDeclarer,TPropertyType&gt;">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindablePropertyKey CreateReadOnly&lt;TDeclarer,TPropertyType&gt; (System.Linq.Expressions.Expression&lt;Func&lt;TDeclarer,TPropertyType&gt;&gt; getter, TPropertyType defaultValue, Xamarin.Forms.BindingMode defaultBindingMode = Xamarin.Forms.BindingMode.OneWayToSource, Xamarin.Forms.BindableProperty.ValidateValueDelegate&lt;TPropertyType&gt; validateValue = null, Xamarin.Forms.BindableProperty.BindingPropertyChangedDelegate&lt;TPropertyType&gt; propertyChanged = null, Xamarin.Forms.BindableProperty.BindingPropertyChangingDelegate&lt;TPropertyType&gt; propertyChanging = null, Xamarin.Forms.BindableProperty.CoerceValueDelegate&lt;TPropertyType&gt; coerceValue = null, Xamarin.Forms.BindableProperty.CreateDefaultValueDelegate&lt;TDeclarer,TPropertyType&gt; defaultValueCreator = null) where TDeclarer : Xamarin.Forms.BindableObject;" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BindablePropertyKey CreateReadOnly&lt;(class Xamarin.Forms.BindableObject) TDeclarer, TPropertyType&gt;(class System.Linq.Expressions.Expression`1&lt;class System.Func`2&lt;!!TDeclarer, !!TPropertyType&gt;&gt; getter, !!TPropertyType defaultValue, valuetype Xamarin.Forms.BindingMode defaultBindingMode, class Xamarin.Forms.BindableProperty/ValidateValueDelegate`1&lt;!!TPropertyType&gt; validateValue, class Xamarin.Forms.BindableProperty/BindingPropertyChangedDelegate`1&lt;!!TPropertyType&gt; propertyChanged, class Xamarin.Forms.BindableProperty/BindingPropertyChangingDelegate`1&lt;!!TPropertyType&gt; propertyChanging, class Xamarin.Forms.BindableProperty/CoerceValueDelegate`1&lt;!!TPropertyType&gt; coerceValue, class Xamarin.Forms.BindableProperty/CreateDefaultValueDelegate`2&lt;!!TDeclarer, !!TPropertyType&gt; defaultValueCreator) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Generic versions of Create () are no longer supported and deprecated. They will be removed soon.")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindablePropertyKey</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TDeclarer">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ <TypeParameter Name="TPropertyType" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="getter" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;TDeclarer,TPropertyType&gt;&gt;" />
+ <Parameter Name="defaultValue" Type="TPropertyType" />
+ <Parameter Name="defaultBindingMode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="validateValue" Type="Xamarin.Forms.BindableProperty+ValidateValueDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanged" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangedDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="propertyChanging" Type="Xamarin.Forms.BindableProperty+BindingPropertyChangingDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="coerceValue" Type="Xamarin.Forms.BindableProperty+CoerceValueDelegate&lt;TPropertyType&gt;" />
+ <Parameter Name="defaultValueCreator" Type="Xamarin.Forms.BindableProperty+CreateDefaultValueDelegate&lt;TDeclarer,TPropertyType&gt;" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
+ <typeparam name="TPropertyType">The type of the property.</typeparam>
+ <param name="getter">An expression identifying the getter for the property using this BindableProperty as backing store.</param>
+ <param name="defaultValue">Default value for the BindableProperty.</param>
+ <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
+ <param name="validateValue">A delegate to be ran when a value is set. This parameter is optional. Default is null.</param>
+ <param name="propertyChanged">A delegate to be ran when the value has changed. This parameter is optional. Default is null.</param>
+ <param name="propertyChanging">A delegate to be ran when the value will change. This parameter is optional. Default is null.</param>
+ <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
+ <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
+ <summary>Deprecated. Do not use.</summary>
+ <returns>A newly created BindablePropertyKey.</returns>
+ <remarks>
+ <para>A BindablePropertyKey is used to restrict write access to a property, either via SetValue() or binding. A BindableProperty is usually defined too, to give broader read access</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="DeclaringType">
+ <MemberSignature Language="C#" Value="public Type DeclaringType { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Type DeclaringType" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Type</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the type declaring the BindableProperty</summary>
+ <value>
+ </value>
+ <remarks>Unused</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="DefaultBindingMode">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.BindingMode DefaultBindingMode { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.BindingMode DefaultBindingMode" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindingMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the default BindingMode.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="DefaultValue">
+ <MemberSignature Language="C#" Value="public object DefaultValue { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object DefaultValue" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the default value for the BindableProperty.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="DefaultValueCreator">
+ <MemberSignature Language="C#" Value="public Func&lt;object&gt; DefaultValueCreator { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Func`1&lt;object&gt; DefaultValueCreator" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Func&lt;System.Object&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the Func used as default value creator.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsReadOnly">
+ <MemberSignature Language="C#" Value="public bool IsReadOnly { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsReadOnly" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value indicating if the BindableProperty is created form a BindablePropertyKey.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PropertyName">
+ <MemberSignature Language="C#" Value="public string PropertyName { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string PropertyName" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the property name.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ReturnType">
+ <MemberSignature Language="C#" Value="public Type ReturnType { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Type ReturnType" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Type</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the type of the BindableProperty.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindablePropertyConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindablePropertyConverter.xml
new file mode 100644
index 00000000..a7872b17
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindablePropertyConverter.xml
@@ -0,0 +1,148 @@
+<Type Name="BindablePropertyConverter" FullName="Xamarin.Forms.BindablePropertyConverter">
+ <TypeSignature Language="C#" Value="public sealed class BindablePropertyConverter : Xamarin.Forms.TypeConverter, Xamarin.Forms.IExtendedTypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit BindablePropertyConverter extends Xamarin.Forms.TypeConverter implements class Xamarin.Forms.IExtendedTypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IExtendedTypeConverter</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TypeConverter" /> for bindable properties.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public BindablePropertyConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="TXamarin.Forms.BindablePropertyConverter" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>Returns <see langword="true" /> if the source type can be converted with this type converter.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Converts <paramref name="value" /> with the specified <paramref name="culture" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Returns a bindable property when supplied a string of the form <c>Type.PropertyName</c>.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IExtendedTypeConverter.ConvertFrom">
+ <MemberSignature Language="C#" Value="object IExtendedTypeConverter.ConvertFrom (System.Globalization.CultureInfo culture, object value, IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.IExtendedTypeConverter.ConvertFrom(class System.Globalization.CultureInfo culture, object value, class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use only.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IExtendedTypeConverter.ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="object IExtendedTypeConverter.ConvertFromInvariantString (string value, IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.IExtendedTypeConverter.ConvertFromInvariantString(string value, class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use only.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindablePropertyKey.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindablePropertyKey.xml
new file mode 100644
index 00000000..add86276
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindablePropertyKey.xml
@@ -0,0 +1,65 @@
+<Type Name="BindablePropertyKey" FullName="Xamarin.Forms.BindablePropertyKey">
+ <TypeSignature Language="C#" Value="public sealed class BindablePropertyKey" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit BindablePropertyKey extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>The secret key to a BindableProperty, used to implement a BindableProperty with restricted write access.</summary>
+ <remarks>
+ <para>The following example shows the creation of a BindablePropertyKey. Write access is <see langword="internal" /> while read access is <see langword="public" />.</para>
+ <example>
+ <code lang="C#"><![CDATA[
+class Bindable : BindableObject
+{
+ internal static readonly BindablePropertyKey FooPropertyKey =
+ BindableProperty.CreateReadOnly<Bindable, string> (w => w.Foo, default(string));
+
+ public static readonly BindableProperty FooProperty = FooPropertyKey.BindableProperty;
+
+ public string Foo {
+ get { return (string)GetValue (FooProperty); }
+ internal set { SetValue (FooPropertyKey, value); }
+ }
+}
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="BindableProperty">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.BindableProperty BindableProperty { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.BindableProperty BindableProperty" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the BindableProperty.</summary>
+ <value>A BindableProperty used for read access.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Binding.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Binding.xml
new file mode 100644
index 00000000..f7e24286
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Binding.xml
@@ -0,0 +1,320 @@
+<Type Name="Binding" FullName="Xamarin.Forms.Binding">
+ <TypeSignature Language="C#" Value="public sealed class Binding : Xamarin.Forms.BindingBase" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit Binding extends Xamarin.Forms.BindingBase" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.BindingBase</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A single 1:1 immutable data binding.</summary>
+ <remarks>This class is immutable.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Binding ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Constructs and initializes a new instance of the <see cref="T:Xamarin.Forms.Binding" /> class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Binding (string path, Xamarin.Forms.BindingMode mode = Xamarin.Forms.BindingMode.Default, Xamarin.Forms.IValueConverter converter = null, object converterParameter = null, string stringFormat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string path, valuetype Xamarin.Forms.BindingMode mode, class Xamarin.Forms.IValueConverter converter, object converterParameter, string stringFormat) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="path" Type="System.String" />
+ <Parameter Name="mode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="converter" Type="Xamarin.Forms.IValueConverter" />
+ <Parameter Name="converterParameter" Type="System.Object" />
+ <Parameter Name="stringFormat" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="path">The property path.</param>
+ <param name="mode">The binding mode. This property is optional. Default is <see cref="E:Xamarin.Forms.BindingMode.Default" />.</param>
+ <param name="converter">The converter. This parameter is optional. Default is <see langword="null" />.</param>
+ <param name="converterParameter">An user-defined parameter to pass to the converter. This parameter is optional. Default is <see langword="null" />.</param>
+ <param name="stringFormat">A String format. This parameter is optional. Default is <see langword="null" />.</param>
+ <summary>Constructs and initializes a new instance of the <see cref="T:Xamarin.Forms.Binding" /> class.</summary>
+ <remarks>
+ <para>The following example shows how to set a binding to a property with a BindingMode and Converter:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+public class PersonViewModel
+{
+ public string Name { get; set; }
+ public string Company { get; set; }
+}
+
+public class ReverseConverter : IValueConverter
+{
+ public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ var s = value as string;
+ if (s == null)
+ return value;
+ return new string (s.Reverse ().ToArray ());
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ var s = value as string;
+ if (s == null)
+ return value;
+ return new string (s.Reverse ().ToArray ());
+ }
+}
+
+var label = new Label ();
+PersonViewModel person;
+label.BindingContext = person = new PersonViewModel { Name = "John Doe", Company= "Xamarin" };
+label.SetBinding (Label.TextProperty, new Binding ("Name", mode: BindingMode.TwoWay, converter: new ReverseConverter ()));
+Debug.WriteLine (label.Text); //prints "eoD nhoJ". ReverseConverter.Convert () is invoked in this case.
+
+label.Text = "ooF";
+Debug.WriteLine (person.Name); //prints "Foo". ReverseConverter.ConvertBack () is invoked in this case. The label Text change is propagated back as the BindingMode is TwoWay.
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Binding (string path, Xamarin.Forms.BindingMode mode = Xamarin.Forms.BindingMode.Default, Xamarin.Forms.IValueConverter converter = null, object converterParameter = null, string stringFormat = null, object source = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string path, valuetype Xamarin.Forms.BindingMode mode, class Xamarin.Forms.IValueConverter converter, object converterParameter, string stringFormat, object source) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="path" Type="System.String" />
+ <Parameter Name="mode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="converter" Type="Xamarin.Forms.IValueConverter" />
+ <Parameter Name="converterParameter" Type="System.Object" />
+ <Parameter Name="stringFormat" Type="System.String" />
+ <Parameter Name="source" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="path">The property path.</param>
+ <param name="mode">The binding mode. This property is optional. Default is <see cref="E:Xamarin.Forms.BindingMode.Default" />.</param>
+ <param name="converter">The converter. This parameter is optional. Default is <see langword="null" />.</param>
+ <param name="converterParameter">An user-defined parameter to pass to the converter. This parameter is optional. Default is <see langword="null" />.</param>
+ <param name="stringFormat">A String format. This parameter is optional. Default is <see langword="null" />.</param>
+ <param name="source">An object used as the source for this binding. This parameter is optional. Default is <see langword="null" />.</param>
+ <summary>Constructs and initializes a new instance of the <see cref="T:Xamarin.Forms.Binding" /> class.</summary>
+ <remarks>
+ <para>The following example shows how to set a binding to a property with a BindingMode and Converter:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+public class PersonViewModel
+{
+ public string Name { get; set; }
+ public string Company { get; set; }
+}
+
+public class ReverseConverter : IValueConverter
+{
+ public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ var s = value as string;
+ if (s == null)
+ return value;
+ return new string (s.Reverse ().ToArray ());
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ var s = value as string;
+ if (s == null)
+ return value;
+ return new string (s.Reverse ().ToArray ());
+ }
+}
+
+var label = new Label ();
+PersonViewModel person;
+label.BindingContext = person = new PersonViewModel { Name = "John Doe", Company= "Xamarin" };
+label.SetBinding (Label.TextProperty, new Binding ("Name", mode: BindingMode.TwoWay, converter: new ReverseConverter ()));
+Debug.WriteLine (label.Text); //prints "eoD nhoJ". ReverseConverter.Convert () is invoked in this case.
+
+label.Text = "ooF";
+Debug.WriteLine (person.Name); //prints "Foo". ReverseConverter.ConvertBack () is invoked in this case. The label Text change is propagated back as the BindingMode is TwoWay.
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Converter">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.IValueConverter Converter { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.IValueConverter Converter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.IValueConverter</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the converter to be used for this binding ?</summary>
+ <value>An IValueConverter, or <see langword="null" />.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConverterParameter">
+ <MemberSignature Language="C#" Value="public object ConverterParameter { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object ConverterParameter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the parameter passed as argument to the converter.</summary>
+ <value>An object, or <see langword="null" />.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Create&lt;TSource&gt;">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Binding Create&lt;TSource&gt; (System.Linq.Expressions.Expression&lt;Func&lt;TSource,object&gt;&gt; propertyGetter, Xamarin.Forms.BindingMode mode = Xamarin.Forms.BindingMode.Default, Xamarin.Forms.IValueConverter converter = null, object converterParameter = null, string stringFormat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.Binding Create&lt;TSource&gt;(class System.Linq.Expressions.Expression`1&lt;class System.Func`2&lt;!!TSource, object&gt;&gt; propertyGetter, valuetype Xamarin.Forms.BindingMode mode, class Xamarin.Forms.IValueConverter converter, object converterParameter, string stringFormat) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Binding</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TSource" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="propertyGetter" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;TSource,System.Object&gt;&gt;" />
+ <Parameter Name="mode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="converter" Type="Xamarin.Forms.IValueConverter" />
+ <Parameter Name="converterParameter" Type="System.Object" />
+ <Parameter Name="stringFormat" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TSource">The type of the source of the binding.</typeparam>
+ <param name="propertyGetter">An expression used to retrieve the binding path.</param>
+ <param name="mode">The binding mode. This property is optional. Default is <see cref="E:Xamarin.Forms.BindingMode.Default" />.</param>
+ <param name="converter">The converter. This parameter is optional. Default is <see langword="null" />.</param>
+ <param name="converterParameter">An user-defined parameter to pass to the converter. This parameter is optional. Default is <see langword="null" />.</param>
+ <param name="stringFormat">A String format. This parameter is optional. Default is <see langword="null" />.</param>
+ <summary>This is a convenient factory method to create a binding from an expression, instead of a property name. This api is more resilient to refactoring.</summary>
+ <returns>A newly created binding.</returns>
+ <remarks>
+ <para>The following example shows how to set a binding to a property :</para>
+ <example>
+ <code lang="C#"><![CDATA[
+public class PersonViewModel
+{
+ public string Name { get; set; }
+ public string Company { get; set; }
+}
+
+var label = new Label ();
+PersonViewModel person;
+label.BindingContext = person = new PersonViewModel { Name = "John Doe", Company= "Xamarin" };
+label.SetBinding (Label.TextProperty, Binding.Create<PersonViewModel> (vm => vm.Name));
+Debug.WriteLine (label.Text); //prints "John Doe".
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Path">
+ <MemberSignature Language="C#" Value="public string Path { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Path" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the path of the property</summary>
+ <value>A string indicating the path to the property.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Source">
+ <MemberSignature Language="C#" Value="public object Source { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Source" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the source of the binding.</summary>
+ <value>An object used as the binding source.</value>
+ <remarks>If the Source is not null, the BindingContext is ignored, and the Source is used instead. This allows to set a source for a single Binding, and not for all the Bindings applied to the BindableObject.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindingBase.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindingBase.xml
new file mode 100644
index 00000000..98611e24
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindingBase.xml
@@ -0,0 +1,172 @@
+<Type Name="BindingBase" FullName="Xamarin.Forms.BindingBase">
+ <TypeSignature Language="C#" Value="public abstract class BindingBase" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit BindingBase extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>An abstract class that provides a <see cref="T:Xamarin.Forms.BindingMode" /> and a formatting option.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="DisableCollectionSynchronization">
+ <MemberSignature Language="C#" Value="public static void DisableCollectionSynchronization (System.Collections.IEnumerable collection);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void DisableCollectionSynchronization(class System.Collections.IEnumerable collection) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="collection" Type="System.Collections.IEnumerable" />
+ </Parameters>
+ <Docs>
+ <param name="collection">To be added.</param>
+ <summary>Stops synchronization on the <paramref name="collection" />.</summary>
+ <remarks>See <see cref="M:Xamarin.Forms.BindingBase.EnableCollectionSynchronization" /> for more information on enabling and disabling synchronization of collections in multithreaded environments.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="EnableCollectionSynchronization">
+ <MemberSignature Language="C#" Value="public static void EnableCollectionSynchronization (System.Collections.IEnumerable collection, object context, Xamarin.Forms.CollectionSynchronizationCallback callback);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void EnableCollectionSynchronization(class System.Collections.IEnumerable collection, object context, class Xamarin.Forms.CollectionSynchronizationCallback callback) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="collection" Type="System.Collections.IEnumerable" />
+ <Parameter Name="context" Type="System.Object" />
+ <Parameter Name="callback" Type="Xamarin.Forms.CollectionSynchronizationCallback" />
+ </Parameters>
+ <Docs>
+ <param name="collection">The collection that will be read or updated.</param>
+ <param name="context">The context or lock object that will be passed to <paramref name="callback" />. May be <see langword="null" />.</param>
+ <param name="callback">The synchronization callback.</param>
+ <summary>Starts synchronization on the <paramref name="collection" /> by using <paramref name="callback" /> and <paramref name="context" />.</summary>
+ <remarks>
+ <para>Application developers implement <paramref name="callback" /> and pass it to the <see cref="M:Xamarin.Forms.BindingBase.EnableCollectionSynchronization" /> method to enable correct multithreaded access to <paramref name="collection" />. After synchronization is enabled, the Xamarin.Forms framework passes an access method, <paramref name="context" />, and a <see langword="bool" /> that indicates whether write access is needed, to the application developer's implementation of <see cref="T:Xamarin.Forms.CollectionSynchronizationCallback" /> each time that the framework needs to modify the collection in a multithreaded environment. The application developer's implementation should decide, based on the <paramref name="context" /> object (which may be merely a locking object or the object on which the collection lives) and the value of the <paramref name="writeAccess" /><see langword="bool" /> parameter, whether or not to <c>lock</c> while calling <paramref name="accessMethod" />.</para>
+ <para>Because Xamarin.Forms maintains a weak reference to <paramref name="collection" />, application developers do not need to call <see cref="M:Xamarin.Forms.BindingBase.DisableCollectionSynchronization" /> to aid in garbage collection.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Mode">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.BindingMode Mode { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.BindingMode Mode" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindingMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the mode for this binding.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="StringFormat">
+ <MemberSignature Language="C#" Value="public string StringFormat { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string StringFormat" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the string format for this binding.</summary>
+ <value>
+ A string specifying the format for the value of this binding.
+ </value>
+ <remarks>
+ <para>
+ Used for providing a display format for the binding value or compositing the value with other
+ text. Implementors of <see cref="T:Xamarin.Forms.BindingBase" /> decide how the string format is utilized, but
+ all support standard <see cref="M:System.String.Format" /> conventions.
+ </para>
+ <para>
+ <see cref="T:Xamarin.Forms.Binding" /> allows for one argument for its singular value.
+ </para>
+ <example>
+ <para>
+ A simple example showing compositing text and determining the display format for the value with a
+ <see cref="T:Xamarin.Forms.Binding" /></para>
+ <code language="C#"><![CDATA[
+Label label = new Label();
+label.AddBinding (new Binding (Label.TextProperty, "Price") {
+ StringFormat = "Price: {0:C2}"
+});
+]]></code>
+ </example>
+ </remarks>
+ <altmember cref="M:System.String.Format" />
+ </Docs>
+ </Member>
+ <Member MemberName="ThrowIfApplied">
+ <MemberSignature Language="C#" Value="protected void ThrowIfApplied ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig instance void ThrowIfApplied() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Throws an <see cref="T:System.InvalidOperationException" /> if the binding has been applied.</summary>
+ <remarks>
+ <para>Use this method in property setters as bindings can not be changed once applied.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindingCondition.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindingCondition.xml
new file mode 100644
index 00000000..b88d3135
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindingCondition.xml
@@ -0,0 +1,102 @@
+<Type Name="BindingCondition" FullName="Xamarin.Forms.BindingCondition">
+ <TypeSignature Language="C#" Value="public sealed class BindingCondition : Xamarin.Forms.Condition, Xamarin.Forms.Xaml.IValueProvider" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit BindingCondition extends Xamarin.Forms.Condition implements class Xamarin.Forms.Xaml.IValueProvider" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Condition</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IValueProvider</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>Class that represents a value comparison with the target of an arbitrary binding.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public BindingCondition ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new <see cref="T:Xamarin.Forms.BindingCondition" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Binding">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.BindingBase Binding { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.BindingBase Binding" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindingBase</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the binding against which the <see cref="P:Xamarin.Forms.BindingCondition.Value" /> property will be compared.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Value">
+ <MemberSignature Language="C#" Value="public object Value { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Value" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The binding value that satisfies the condition.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IValueProvider.ProvideValue">
+ <MemberSignature Language="C#" Value="object IValueProvider.ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.Xaml.IValueProvider.ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>Used by XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindingMode.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindingMode.xml
new file mode 100644
index 00000000..15671f08
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindingMode.xml
@@ -0,0 +1,149 @@
+<Type Name="BindingMode" FullName="Xamarin.Forms.BindingMode">
+ <TypeSignature Language="C#" Value="public enum BindingMode" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed BindingMode extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>The direction of changes propagation for bindings.</summary>
+ <remarks>
+ <para>The following examples shows some BindingMode use cases.</para>
+ <example>
+ <code lang="C#"><![CDATA[
+public class PersonViewModel
+{
+ public string Name { get; set; }
+ public string Company { get; set; }
+}
+
+Label label;
+PersonViewModel viewmodel;
+
+//BindingMode.OneWay
+label = new Label ();
+label.BindingContext = viewmodel = new PersonViewModel ();
+label.SetBinding<PersonViewModel> (Label.TextProperty, vm => vm.Name, mode: BindingMode.OneWay);
+
+viewmodel.Name = "John Doe";
+Debug.WriteLine (label.Text); //prints "John Doe"
+label.Text = "Foo";
+Debug.WriteLine (viewmodel.Name); //prints "John Doe"
+
+
+//BindingMode.TwoWay
+label = new Label ();
+label.BindingContext = viewmodel = new PersonViewModel ();
+label.SetBinding<PersonViewModel> (Label.TextProperty, vm => vm.Name, mode: BindingMode.TwoWay);
+
+viewmodel.Name = "John Doe";
+Debug.WriteLine (label.Text); //prints "John Doe"
+label.Text = "Foo";
+Debug.WriteLine (viewmodel.Name); //prints "Foo"
+
+
+//BindingMode.OneWayToSource
+label = new Label ();
+label.BindingContext = viewmodel = new PersonViewModel ();
+label.SetBinding<PersonViewModel> (Label.TextProperty, vm => vm.Name, mode: BindingMode.OneWayToSource);
+
+viewmodel.Name = "John Doe";
+Debug.WriteLine (label.Text); //prints ""
+label.Text = "Foo";
+Debug.WriteLine (viewmodel.Name); //prints "Foo"
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Default">
+ <MemberSignature Language="C#" Value="Default" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.BindingMode Default = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindingMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>When used in Bindings, indicates that the Binding should use the <see cref="P:Xamarin.Forms.BindableProperty.DefaultBindingMode" />. When used in BindableProperty declaration, defaults to BindingMode.OneWay.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="OneWay">
+ <MemberSignature Language="C#" Value="OneWay" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.BindingMode OneWay = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindingMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that the binding should only propagates changes from source (usually the View Model) to target (the BindableObject). This is the default mode for most BindableProperty values.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="OneWayToSource">
+ <MemberSignature Language="C#" Value="OneWayToSource" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.BindingMode OneWayToSource = int32(3)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindingMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that the binding should only propagates changes from target (the BindableObject) to source (usually the View Model). This is mainly used for read-only BindableProperty values.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="TwoWay">
+ <MemberSignature Language="C#" Value="TwoWay" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.BindingMode TwoWay = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindingMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that the binding should propagates changes from source (usually the View Model) to target (the BindableObject) in both directions.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BindingTypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindingTypeConverter.xml
new file mode 100644
index 00000000..c572c6a5
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BindingTypeConverter.xml
@@ -0,0 +1,117 @@
+<Type Name="BindingTypeConverter" FullName="Xamarin.Forms.BindingTypeConverter">
+ <TypeSignature Language="C#" Value="public sealed class BindingTypeConverter : Xamarin.Forms.TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit BindingTypeConverter extends Xamarin.Forms.TypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Type converter that converts from source types to <see cref="T:Xamarin.Forms.Binding" /></summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public BindingTypeConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.BindingTypeConverter" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>Returns a Boolean value that indicates whether this <see cref="T:Xamarin.Forms.BindingTypeConverter" /> can convert <paramref name="sourceType" /> to <see cref="T:Xamarin.Forms.Binding" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Converts <paramref name="value" /> to <see cref="T:Xamarin.Forms.Binding" /> by using <paramref name="culture" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Converts a property path to a binding.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BoundsConstraint.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BoundsConstraint.xml
new file mode 100644
index 00000000..1ace7b93
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BoundsConstraint.xml
@@ -0,0 +1,52 @@
+<Type Name="BoundsConstraint" FullName="Xamarin.Forms.BoundsConstraint">
+ <TypeSignature Language="C#" Value="public class BoundsConstraint" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit BoundsConstraint extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A bounds layout constraint used by <see cref="T:Xamarin.Forms.RelativeLayout" />s.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="FromExpression">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BoundsConstraint FromExpression (System.Linq.Expressions.Expression&lt;Func&lt;Xamarin.Forms.Rectangle&gt;&gt; expression, System.Collections.Generic.IEnumerable&lt;Xamarin.Forms.View&gt; parents = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BoundsConstraint FromExpression(class System.Linq.Expressions.Expression`1&lt;class System.Func`1&lt;valuetype Xamarin.Forms.Rectangle&gt;&gt; expression, class System.Collections.Generic.IEnumerable`1&lt;class Xamarin.Forms.View&gt; parents) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BoundsConstraint</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="expression" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;Xamarin.Forms.Rectangle&gt;&gt;" />
+ <Parameter Name="parents" Type="System.Collections.Generic.IEnumerable&lt;Xamarin.Forms.View&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="expression">To be added.</param>
+ <param name="parents">To be added.</param>
+ <summary>Returns a <see cref="T:Xamarin.Forms.BoundsConstraint" /> object that contains the compiled version of <paramref name="expression" /> and is relative to either <paramref name="parents" /> or the views referred to in <paramref name="expression" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BoundsTypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BoundsTypeConverter.xml
new file mode 100644
index 00000000..1c8ee544
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BoundsTypeConverter.xml
@@ -0,0 +1,117 @@
+<Type Name="BoundsTypeConverter" FullName="Xamarin.Forms.BoundsTypeConverter">
+ <TypeSignature Language="C#" Value="public class BoundsTypeConverter : Xamarin.Forms.TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit BoundsTypeConverter extends Xamarin.Forms.TypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TypeConverter" /> that converts strings into <see cref="T:Xamarin.Forms.Rectangle" />s for use with <see cref="T:Xamarin.Forms.AbsoluteLayout" />s.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public BoundsTypeConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.BoundsTypeConverter" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>Returns a Boolean value that indicates whether this <see cref="T:Xamarin.Forms.BoundsTypeConverter" /> can convert the <paramref name="sourceType" /> to a <see cref="T:Xamarin.Forms.Rectangle" /> instance.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Converts <paramref name="value" /> into a <see cref="T:Xamarin.Forms.Rectangle" /> by using the specified <paramref name="culture" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Converts <paramref name="value" /> into a <see cref="T:Xamarin.Forms.Rectangle" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/BoxView.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/BoxView.xml
new file mode 100644
index 00000000..baed2b7a
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/BoxView.xml
@@ -0,0 +1,179 @@
+<Type Name="BoxView" FullName="Xamarin.Forms.BoxView">
+ <TypeSignature Language="C#" Value="public class BoxView : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit BoxView extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._BoxViewRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.View" /> used to draw a solid colored rectangle.</summary>
+ <remarks>
+ <para>BoxView is a useful stand-in for images or custom elements when doing initial prototyping. BoxView has a default size request of 40x40. If you need a different size, assign the <see cref="P:Xamarin.Forms.VisualElement.WidthRequest" /> and <see cref="P:Xamarin.Forms.VisualElement.HeightRequest" /> properties.</para>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.BoxView" /> class:</para>
+ <example>
+ <para>The example below creates a red <see cref="T:Xamarin.Forms.Boxview" /> with the default width and height.</para>
+ <code lang="XAML"><![CDATA[<BoxView Color="Red" />]]></code>
+ </example>
+ <para>The following example shows a basic use:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+using System;
+using Xamarin.Forms;
+
+namespace FormsGallery
+{
+ class BoxViewDemoPage : ContentPage
+ {
+ public BoxViewDemoPage()
+ {
+ Label header = new Label
+ {
+ Text = "BoxView",
+ Font = Font.BoldSystemFontOfSize(50),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ BoxView boxView = new BoxView
+ {
+ Color = Color.Accent,
+ WidthRequest = 150,
+ HeightRequest = 150,
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+
+ // Accomodate iPhone status bar.
+ this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
+
+ // Build the page.
+ this.Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ boxView
+ }
+ };
+ }
+ }
+}
+]]></code>
+ </example>
+ <para>
+ <img href="BoxView.TripleScreenShot.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public BoxView ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the BoxView class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Color">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color Color { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color Color" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the color which will fill the rectangle. This is a bindable property.</summary>
+ <value>The color that is used to fill the rectangle. The default is <see cref="P:Xamarin.Forms.Color.Default" />.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Color bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeRequest">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance valuetype Xamarin.Forms.SizeRequest OnSizeRequest(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use OnMeasure")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">To be added.</param>
+ <param name="heightConstraint">To be added.</param>
+ <summary>Method that is called when a size request is made to the box view.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Button.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Button.xml
new file mode 100644
index 00000000..b5614e13
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Button.xml
@@ -0,0 +1,719 @@
+<Type Name="Button" FullName="Xamarin.Forms.Button">
+ <TypeSignature Language="C#" Value="public class Button : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Button extends Xamarin.Forms.View implements class Xamarin.Forms.IElementController, class Xamarin.Forms.IViewController, class Xamarin.Forms.IVisualElementController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._ButtonRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A button <see cref="T:Xamarin.Forms.View" /> that reacts to touch events.</summary>
+ <remarks>
+ <example>
+ <para>The following example shows a basic use:</para>
+ <code lang="C#"><![CDATA[
+using System;
+using Xamarin.Forms;
+
+namespace FormsGallery
+{
+ class ButtonDemoPage : ContentPage
+ {
+ Label label;
+ int clickTotal = 0;
+
+ public ButtonDemoPage()
+ {
+ Label header = new Label
+ {
+ Text = "Button",
+ Font = Font.BoldSystemFontOfSize(50),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ Button button = new Button
+ {
+ Text = "Click Me!",
+ Font = Font.SystemFontOfSize(NamedSize.Large),
+ BorderWidth = 1,
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+ button.Clicked += OnButtonClicked;
+
+ label = new Label
+ {
+ Text = "0 button clicks",
+ Font = Font.SystemFontOfSize(NamedSize.Large),
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+
+ // Accomodate iPhone status bar.
+ this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
+
+ // Build the page.
+ this.Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ button,
+ label
+ }
+ };
+ }
+
+ void OnButtonClicked(object sender, EventArgs e)
+ {
+ clickTotal += 1;
+ label.Text = String.Format("{0} button click{1}",
+ clickTotal, clickTotal == 1 ? "" : "s");
+ }
+ }
+}
+]]></code>
+ </example>
+ <para>
+ <img href="Button.TripleScreenShot.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Button ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the Button class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BorderColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color BorderColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color BorderColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a color that describes the border stroke color of the button. This is a bindable property.</summary>
+ <value>The color that is used as the border stroke color; the default is <see cref="P:Xamarin.Forms.Color.Default" />.</value>
+ <remarks>This property has no effect if <see cref="P:Xamarin.Forms.Button.BorderWidth" /> is set to 0. On Android this property will not have an effect unless <see cref="P:Xamarin.Forms.VisualElement.BackgroundColor" /> is set to a non-default color.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BorderColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty BorderColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty BorderColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the BorderColor bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BorderRadius">
+ <MemberSignature Language="C#" Value="public int BorderRadius { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 BorderRadius" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the corner radius of the border. This is a bindable property.</summary>
+ <value>The corner radius of the button border; the default is 5.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BorderRadiusProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty BorderRadiusProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty BorderRadiusProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the BorderRadius bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BorderWidth">
+ <MemberSignature Language="C#" Value="public double BorderWidth { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 BorderWidth" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the width of the border. This is a bindable property.</summary>
+ <value>The width of the button border; the default is 0.</value>
+ <remarks>Set this value to a non-zero value in order to have a visible border.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BorderWidthProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty BorderWidthProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty BorderWidthProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the BorderWidth bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Clicked">
+ <MemberSignature Language="C#" Value="public event EventHandler Clicked;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Clicked" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs when the Button is clicked.</summary>
+ <remarks>The user may be able to raise the clicked event using accessibility or keyboard controls when the Button has focus.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Command">
+ <MemberSignature Language="C#" Value="public System.Windows.Input.ICommand Command { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Windows.Input.ICommand Command" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Windows.Input.ICommand</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the command to invoke when the button is activated. This is a bindable property.</summary>
+ <value>A command to invoke when the button is activated. The default value is <see langword="null" />.</value>
+ <remarks>This property is used to associate a command with an instance of a button. This property is most often set in the MVVM pattern to bind callbacks back into the ViewModel. <see cref="P:Xamarin.Forms.VisualElement.IsEnabled" /> is controlled by the Command if set.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CommandParameter">
+ <MemberSignature Language="C#" Value="public object CommandParameter { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object CommandParameter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the parameter to pass to the Command property. This is a bindable property.</summary>
+ <value>A object to pass to the command property. The default value is <see langword="null" />.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CommandParameterProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty CommandParameterProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty CommandParameterProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the CommandParameter bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CommandProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty CommandProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty CommandProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the Command bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Font">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Font Font { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Font Font" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Font</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the Font for the Label text. This is a bindable property.</summary>
+ <value>The <see cref="T:Xamarin.Forms.Font" /> value for the button. The default is <see langword="null" />, which represents the default font on the platform.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontAttributes">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.FontAttributes FontAttributes { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.FontAttributes FontAttributes" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FontAttributes</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that indicates whether the font for the button text is bold, italic, or neither.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontAttributesProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontAttributesProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontAttributesProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the FontAttributes property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontFamily">
+ <MemberSignature Language="C#" Value="public string FontFamily { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string FontFamily" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the font family to which the font for the button text belongs.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontFamilyProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontFamilyProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontFamilyProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the FontFamily property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the Font bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontSize">
+ <MemberSignature Language="C#" Value="public double FontSize { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 FontSize" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.FontSizeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the size of the font of the button text.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontSizeProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontSizeProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontSizeProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the FontSize property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Image">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.FileImageSource Image { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.FileImageSource Image" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FileImageSource</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the optional image source to display next to the text in the Button. This is a bindable property.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ImageProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ImageProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ImageProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the Image bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBindingContextChanged">
+ <MemberSignature Language="C#" Value="protected override void OnBindingContextChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnBindingContextChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Method that is raised when the binding context changes.</summary>
+ <remarks>
+ <para>Application developers who override this method in derived classes must call this method in the base class, <see cref="T:Xamarin.Forms.Button" />.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnPropertyChanging">
+ <MemberSignature Language="C#" Value="protected override void OnPropertyChanging (string propertyName = null);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnPropertyChanging(string propertyName) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the changed property.</param>
+ <summary>Call this method from a child class to notify that a change happened on a property.</summary>
+ <remarks>A Button triggers this by itself. An inheritor only need to call this for properties without BindableProperty as backend store.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Text">
+ <MemberSignature Language="C#" Value="public string Text { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Text" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the Text displayed as the content of the button. This is a bindable property.</summary>
+ <value>The text displayed in the button. The default value is <see langword="null" />.</value>
+ <remarks>Changing the Text of a button will trigger a layout cycle.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color TextColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color TextColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the <see cref="T:Xamarin.Forms.Color" /> for the text of the button. This is a bindable property.</summary>
+ <value>The <see cref="T:Xamarin.Forms.Color" /> value.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TextColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TextColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the TextColor bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TextProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TextProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the Text bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IButtonController.SendClicked">
+ <MemberSignature Language="C#" Value="void IButtonController.SendClicked ();" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IButtonController.SendClicked() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Sends a click event.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/CarouselPage.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/CarouselPage.xml
new file mode 100644
index 00000000..4b72572e
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/CarouselPage.xml
@@ -0,0 +1,134 @@
+<Type Name="CarouselPage" FullName="Xamarin.Forms.CarouselPage">
+ <TypeSignature Language="C#" Value="public class CarouselPage : Xamarin.Forms.MultiPage&lt;Xamarin.Forms.ContentPage&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit CarouselPage extends Xamarin.Forms.MultiPage`1&lt;class Xamarin.Forms.ContentPage&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.MultiPage&lt;Xamarin.Forms.ContentPage&gt;</BaseTypeName>
+ <BaseTypeArguments>
+ <BaseTypeArgument TypeParamName="T">Xamarin.Forms.ContentPage</BaseTypeArgument>
+ </BaseTypeArguments>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._CarouselPageRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A Page that users can swipe from side to side to display pages of content, like a gallery.</summary>
+ <remarks>
+ <para>The <see cref="T:Xamarin.Forms.CarouselPage" /> provides a navigation experience that will feel natural and familiar to Windows Phone users. By using <see cref="M:Xamarin.Forms.Device.OnPlatform" />, application developers can provide customized navigation on a per-platform basis. For example, an application developer could use a <see cref="T:Xamarin.Forms.NavigationPage" /> for Android and iOS, and use a <see cref="T:Xamarin.Forms.CarouselPage" /> on Windows Phone.</para>
+ <example>
+ <para>The following XAML example, when properly included and referenced in a Xamarin.Forms project, creates a <see cref="T:Xamarin.Forms.CarouselPage" /> that displays three simple <see cref="T:Xamarin.Forms.ContentPage" /> elements:
+ </para>
+ <code lang="XAML"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
+<CarouselPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="XamlExample1.MyPage">
+ <ContentPage>
+ <StackLayout>
+ <Label Text="Red" />
+ <BoxView Color="Red" VerticalOptions="FillAndExpand" />
+ </StackLayout>
+ </ContentPage>
+ <ContentPage>
+ <StackLayout>
+ <Label Text="Green" />
+ <BoxView Color="Green" VerticalOptions="FillAndExpand" />
+ </StackLayout>
+ </ContentPage>
+ <ContentPage>
+ <StackLayout>
+ <Label Text="Blue" />
+ <BoxView Color="Blue" VerticalOptions="FillAndExpand" />
+ </StackLayout>
+ </ContentPage>
+</CarouselPage>]]></code>
+ </example>
+ <example>
+ <para>The following C# example creates a <see cref="T:Xamarin.Forms.CarouselPage" /> that displays three simple <see cref="T:Xamarin.Forms.ContentPage" /> elements:</para>
+ <code lang="C#"><![CDATA[
+List<ContentPage> pages = new List<ContentPage> (0);
+Color[] colors = { Color.Red, Color.Green, Color.Blue };
+foreach (Color c in colors) {
+ pages.Add (new ContentPage { Content = new StackLayout {
+ Children = {
+ new Label { Text = c.ToString () },
+ new BoxView {
+ Color = c,
+ VerticalOptions = LayoutOptions.FillAndExpand
+ }
+ }
+ }
+ });
+}
+
+MainPage = new CarouselPage {
+ Children = { pages [0],
+ pages [1],
+ pages [2] }
+};
+]]></code>
+ </example>
+ <block subset="none" type="note">When embedding a CarouselPage into a <see cref="P:Xamarin.Forms.MasterDetailPage.Detail" />, application developers should set <see cref="P:Xamarin.Forms.MasterDetailPage.IsGestureEnabled" /> to <see langword="false" /> to prevent gesture conflicts between the CarouselPage and MasterDetailPage.</block>
+ <para>
+ <img href="CarouselPage.TripleScreenShot.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public CarouselPage ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the CarouselPage class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateDefault">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.ContentPage CreateDefault (object item);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance class Xamarin.Forms.ContentPage CreateDefault(object item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ContentPage</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="item">The object representing the model ofr the page.</param>
+ <summary>Creates a default page, suitable for display in <c>this</c><see cref="T:Xamarin.Forms.CarouselPage" />, for an object.</summary>
+ <returns>A page that is titled with the string value of <paramref name="item" />.</returns>
+ <remarks>This returns a new <see cref="T:Xamarin.Forms.Page" /> object that has its <see cref="P:Xamarin.Forms.Page.Title" /> property set to the value of <see cref="M:Object.ToString" /> when called on <paramref name="item" />.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/CarouselView.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/CarouselView.xml
new file mode 100644
index 00000000..688fd68e
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/CarouselView.xml
@@ -0,0 +1,230 @@
+<Type Name="CarouselView" FullName="Xamarin.Forms.CarouselView">
+ <TypeSignature Language="C#" Value="public class CarouselView : Xamarin.Forms.ItemsView, Xamarin.Forms.ICarouselViewController" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit CarouselView extends Xamarin.Forms.ItemsView implements class Xamarin.Forms.ICarouselViewController, class Xamarin.Forms.IItemViewController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.ItemsView</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.ICarouselViewController</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._CarouselViewRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public CarouselView ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Item">
+ <MemberSignature Language="C#" Value="public int Item { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 Item" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ItemProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ItemProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemSelected">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.SelectedItemChangedEventArgs&gt; ItemSelected;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.SelectedItemChangedEventArgs&gt; ItemSelected" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.SelectedItemChangedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnMeasure">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.SizeRequest OnMeasure (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance valuetype Xamarin.Forms.SizeRequest OnMeasure(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">To be added.</param>
+ <param name="heightConstraint">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Position">
+ <MemberSignature Language="C#" Value="public int Position { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 Position" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PositionProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty PositionProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty PositionProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PositionSelected">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.SelectedPositionChangedEventArgs&gt; PositionSelected;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.SelectedPositionChangedEventArgs&gt; PositionSelected" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.SelectedPositionChangedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.ICarouselViewController.SendPositionAppearing">
+ <MemberSignature Language="C#" Value="void ICarouselViewController.SendPositionAppearing (int position);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.ICarouselViewController.SendPositionAppearing(int32 position) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="position" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="position">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.ICarouselViewController.SendPositionDisappearing">
+ <MemberSignature Language="C#" Value="void ICarouselViewController.SendPositionDisappearing (int position);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.ICarouselViewController.SendPositionDisappearing(int32 position) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="position" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="position">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.ICarouselViewController.SendSelectedItemChanged">
+ <MemberSignature Language="C#" Value="void ICarouselViewController.SendSelectedItemChanged (object item);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.ICarouselViewController.SendSelectedItemChanged(object item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="item">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.ICarouselViewController.SendSelectedPositionChanged">
+ <MemberSignature Language="C#" Value="void ICarouselViewController.SendSelectedPositionChanged (int position);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.ICarouselViewController.SendSelectedPositionChanged(int32 position) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="position" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="position">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Cell.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Cell.xml
new file mode 100644
index 00000000..f94a9479
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Cell.xml
@@ -0,0 +1,508 @@
+<Type Name="Cell" FullName="Xamarin.Forms.Cell">
+ <TypeSignature Language="C#" Value="public abstract class Cell : Xamarin.Forms.Element" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit Cell extends Xamarin.Forms.Element" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Element</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Provides base class and capabilities for all Forms cells. Cells are elements meant to be added to <see cref="T:Xamarin.Forms.ListView" /> or <see cref="T:Xamarin.Forms.TableView" />.</summary>
+ <remarks>
+ <para>The subtypes of <see cref="T:Xamarin.Forms.Cell" /> are:</para>
+ <list type="table">
+ <listheader>
+ <term>Type</term>
+ <description>Description</description>
+ </listheader>
+ <item>
+ <term>EntryCell</term>
+ <description>A <see cref="T:Xamarin.Forms.Cell" /> with a label and a single line text entry field.</description>
+ </item>
+ <item>
+ <term>SwitchCell</term>
+ <description>A <see cref="T:Xamarin.Forms.Cell" /> with a label and an on/off switch.</description>
+ </item>
+ <item>
+ <term>TextCell</term>
+ <description>A <see cref="T:Xamarin.Forms.Cell" /> with primary and secondary text.</description>
+ </item>
+ <item>
+ <term>ImageCell</term>
+ <description>A <see cref="T:Xamarin.Forms.TextCell" /> that also includes an image.</description>
+ </item>
+ <item>
+ <term>ViewCell</term>
+ <description>A <see cref="T:Xamarin.Forms.Cell" /> containing a developer-defined <see cref="T:Xamarin.Forms.View" />.</description>
+ </item>
+ </list>
+ <para>The various subclasses are shown in the following image:</para>
+ <para>
+ <img href="Cell.Gallery.png" />
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+Content = new TableView
+{
+ Root = new TableRoot ("Table Title")
+ {
+ new TableSection("Section 1 Title")
+ {
+ new TextCell
+ {
+ Text = "TextCell Text",
+ Detail = "TextCell Detail"
+ },
+ new ImageCell
+ {
+ Text = "ImageCell Text",
+ Detail = "ImageCell Detail",
+ ImageSource = "http://xamarin.com/images/index/ide-xamarin-studio.png"
+ },
+ new EntryCell
+ {
+ Label = "EntryCell:",
+ Placeholder = "default keyboard",
+ Keyboard = Keyboard.Default
+ }
+ },
+ new TableSection("Section 2 Title")
+ {
+ new EntryCell
+ {
+ Label = "Another EntryCell:",
+ Placeholder = "phone keyboard",
+ Keyboard = Keyboard.Telephone
+ },
+ new SwitchCell
+ {
+ Text = "SwitchCell:"
+ },
+ new ViewCell
+ {
+ View = new StackLayout
+ {
+ Orientation = StackOrientation.Horizontal,
+ Children =
+ {
+ new Label
+ {
+ Text = "Custom Slider View:"
+ },
+ new Slider
+ {
+ }
+ }
+ }
+ }
+ }
+ }
+}
+ ]]></code>
+ </example>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.Cell" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>ContextActions</term>
+ <description>
+ <para>A list of <see cref="T:Xamarin.Forms.MenuItem" /> objects to display when the user performs the context action.</para>
+ </description>
+ </item>
+ <item>
+ <term>IsEnabled</term>
+ <description>
+ <para>
+ <see langword="true" /> or <see langword="false" />, indicating whether the animation for <see cref="T:Xamarin.Forms.ActivityIndicator" /> is displayed.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected Cell ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the Cell class.</summary>
+ <remarks>Cell class is abstract, this constructor is never invoked directly.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Appearing">
+ <MemberSignature Language="C#" Value="public event EventHandler Appearing;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Appearing" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs when the visual representation of the Cell is being added to the visual layout.</summary>
+ <remarks>This method is raised before the cell is on screen.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ContextActions">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.MenuItem&gt; ContextActions { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.MenuItem&gt; ContextActions" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.MenuItem&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a list of menu items to display when the user performs the device-specific context gesture on the Cell.</summary>
+ <value>The list of menu items that will be displayed when the user performs the device-specific context gesture on the Cell.</value>
+ <remarks>The context gesture on the iOS platform is a left swipe. For Android and Windows Phone operating systems, the context gesture is a press and hold.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Disappearing">
+ <MemberSignature Language="C#" Value="public event EventHandler Disappearing;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Disappearing" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs when the visual representation of the Cell is being removed from the visual layout.</summary>
+ <remarks>This method is for virtualization usage only. It is not gauranteed to fire for all visible Cells when the ListView or TableView is removed from the screen. Additionally it fires during virtualization, which may not correspond directly with removal from the screen depending on the platform virtualization technique used.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ForceUpdateSize">
+ <MemberSignature Language="C#" Value="public void ForceUpdateSize ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void ForceUpdateSize() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Immediately updates the cell's size.</summary>
+ <remarks><para>Developers can call this method to update the cell's size, even if the cell is currently visible. Developers should note that this operation can be expensive.</para></remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasContextActions">
+ <MemberSignature Language="C#" Value="public bool HasContextActions { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool HasContextActions" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that indicates whether the cell has at least one menu item in its <see cref="P:Xamarin.Forms.Cell.ContextActions" /> list property.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Height">
+ <MemberSignature Language="C#" Value="public double Height { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Height" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the height of the Cell.</summary>
+ <value>A double that represents the height of the cell.</value>
+ <remarks>The <see cref="P:Xamarin.Forms.Cell.Height" /> property is ignored if the app developer sets the <see cref="P:Xamarin.Forms.ListView.HasUnevenRows" /> or <see cref="P:Xamarin.Forms.TableView.HasUnevenRows" /> property on the surrounding <see cref="T:Xamarin.Forms.View" /> to <see langword="false" />. In that case, the <see cref="P:Xamarin.Forms.ListView.RowHeight" /> or <see cref="P:Xamarin.Forms.TableView.RowHeight" /> property is used instead.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsEnabled">
+ <MemberSignature Language="C#" Value="public bool IsEnabled { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsEnabled" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the IsEnabled state of the Cell. This is a bindable property.</summary>
+ <value>A bool. Default is <see langword="true" />.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsEnabledProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsEnabledProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsEnabledProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the IsEnabled bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnAppearing">
+ <MemberSignature Language="C#" Value="protected virtual void OnAppearing ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnAppearing() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invoked whenever an <see cref="E:Xamarin.Forms.Cell.Appearing" /> event occurs. Implement this method to add class handling for this event.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBindingContextChanged">
+ <MemberSignature Language="C#" Value="protected override void OnBindingContextChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnBindingContextChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Event that is raised when the binding context is changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnDisappearing">
+ <MemberSignature Language="C#" Value="protected virtual void OnDisappearing ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnDisappearing() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invoked whenever an <see cref="E:Xamarin.Forms.Cell.Disappearing" /> event occurs. Implement this method to add class handling for this event.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnLongPressed">
+ <MemberSignature Language="C#" Value="protected virtual void OnLongPressed ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyorassemblyhidebysig newslot virtual instance void OnLongPressed() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invoked whenever a long press is applied to the Cell.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnParentSet">
+ <MemberSignature Language="C#" Value="protected override void OnParentSet ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnParentSet() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Application developers can override this method to do actions when the cell's parent is set.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnPropertyChanging">
+ <MemberSignature Language="C#" Value="protected override void OnPropertyChanging (string propertyName = null);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnPropertyChanging(string propertyName) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the property on which to monitor value changes.</param>
+ <summary>TApplication developers can override this method to do actions when the property named by <paramref name="propertyName" /> is set.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnTapped">
+ <MemberSignature Language="C#" Value="protected virtual void OnTapped ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyorassemblyhidebysig newslot virtual instance void OnTapped() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invoked whenever the Cell is Tapped.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RenderHeight">
+ <MemberSignature Language="C#" Value="public double RenderHeight { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 RenderHeight" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the height of the rendered cell on the device.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Tapped">
+ <MemberSignature Language="C#" Value="public event EventHandler Tapped;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Tapped" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs when the Cell is Tapped.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/CollectionSynchronizationCallback.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/CollectionSynchronizationCallback.xml
new file mode 100644
index 00000000..57857076
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/CollectionSynchronizationCallback.xml
@@ -0,0 +1,34 @@
+<Type Name="CollectionSynchronizationCallback" FullName="Xamarin.Forms.CollectionSynchronizationCallback">
+ <TypeSignature Language="C#" Value="public delegate void CollectionSynchronizationCallback(IEnumerable collection, object context, Action accessMethod, bool writeAccess);" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed CollectionSynchronizationCallback extends System.MulticastDelegate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Delegate</BaseTypeName>
+ </Base>
+ <Parameters>
+ <Parameter Name="collection" Type="System.Collections.IEnumerable" />
+ <Parameter Name="context" Type="System.Object" />
+ <Parameter Name="accessMethod" Type="System.Action" />
+ <Parameter Name="writeAccess" Type="System.Boolean" />
+ </Parameters>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <param name="collection">The collection that was passed to <see cref="M:Xamarin.Forms.BindingBase.EnableCollectionSynchronization" />.</param>
+ <param name="context">The context or lock object that was passed to <see cref="M:Xamarin.Forms.BindingBase.EnableCollectionSynchronization" />.</param>
+ <param name="accessMethod">An action that reads or modifies <paramref name="collection" />.</param>
+ <param name="writeAccess">A value that tells whether write access is required by <paramref name="accessMethod" />.</param>
+ <summary>Delegate for callback in <see cref="M:Xamarin.Forms.BindingBase.EnableCollectionSynchronization" />.</summary>
+ <remarks>Application developers implement a <see cref="M:Xamarin.Forms.CollectionSynchronizationCallback" /> method and pass it to the <see cref="M:Xamarin.Forms.BindingBase.EnableCollectionSynchronization" /> method to enable correct multithreaded access to <paramref name="collection" />. After synchronization is enabled, the Xamarin.Forms framework passes <paramref name="accessMethod" /> to the application developer's implementation of <see cref="M:Xamarin.Forms.CollectionSynchronizationCallback" /> each time that the framework needs to modify the collection in a multithreaded environment. The application developer's implementation should decide, based on the <paramref name="context" /> object (which may be merely a locking object or the object on which the collection lives) and the value of the <paramref name="writeAccess" /> parameter, whether or not to <c>lock</c> while calling <paramref name="accessMethod" />.</remarks>
+ </Docs>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Color.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Color.xml
new file mode 100644
index 00000000..755a61df
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Color.xml
@@ -0,0 +1,1221 @@
+<Type Name="Color" FullName="Xamarin.Forms.Color">
+ <TypeSignature Language="C#" Value="public struct Color" />
+ <TypeSignature Language="ILAsm" Value=".class public sequential ansi sealed beforefieldinit Color extends System.ValueType" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.ValueType</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.DebuggerDisplay("R={R}, G={G}, B={B}, A={A}, Hue={Hue}, Saturation={Saturation}, Luminosity={Luminosity}")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.ColorTypeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Class that represents a color and exposes it as RGBA and HSL values.</summary>
+ <remarks>
+ <para>This type is immutable. Colors can be expressed in the RGB or HSL modes. While the <see cref="C:Xamarin.Forms.Color" /> constructor takes R, G, B, and A values, the <see cref="T:Xamarin.Forms.Color" /> class also calculates and makes available HSL data for the color.</para>
+ <example>
+ <para>In XAML, application developers can specify any property that is of type <see cref="T:Xamarin.Forms.Color" />, for example, <see cref="P:Xamarin.Forms.Label.TextColor" /> either as a XAML attribute or as a nested tag. The following code example shows how to specify the text color for a label by using an attribute:</para>
+ <code lang="XAML"><![CDATA[
+<Label VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand" TextColor="Green">
+ <Label.Text>Hello, World!</Label.Text>
+</Label>]]></code>
+ <para>The example below shows how to specify the text color for a label by using a nested tag:</para>
+ <code lang="XAML"><![CDATA[
+<Label VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
+ <Label.Text>Hello, World!</Label.Text>
+ <Label.TextColor>Color.Blue</Label.TextColor>
+</Label>]]></code>
+ </example>
+ <para>Application developers can specify colors in XAML either as a hexadecimal number or as a valid color name.</para>
+ <para>When specifying a color with a hexadecimal number, app developers can use 3, 4, or 6 digits. If the developer specifies 3 digits, they are interpreted as RGB doublet data for a fully opaque color. For example, "#123" specifies the color that is represented by "#FF112233". If the developer provides a 4-digit hexadecimal number, then the data are interpreted as above, except that the first digit specifies the alpha channel. For example, "#1234" specifies the color that is represented by "#11223344". Finally, if the developer provides a 6 digit hexadecimal number, the data are interpreted as a fully opaque color with those RGB values. For example, "#112233" specifies the color that is represented by "#FF112233".</para>
+ <para>When specifying a color with a string, app developers can use color name in isolation, or prefix it with "Color.". For example, both <c>Purple</c> and <c>Color.Purple</c> are valid ways to specify the color purple. The following table describes the valid color names that can be used to specify colors in XAML.
+<list type="table"><listheader><term>Color</term><description>Short Name</description><description>RGB Value</description></listheader><item><term>Color.Transparent</term><description>Transparent</description><description>0, 0, 0 (With the alpha channel set to 0.)</description></item><item><term>Color.Aqua</term><description>Aqua</description><description>0, 255, 255</description></item><item><term>Color.Black</term><description>Black</description><description>0, 0, 0</description></item><item><term>Color.Blue</term><description>Blue</description><description>0, 0, 255</description></item><item><term>Color.Fuchsia</term><description>Fuchsia</description><description>255, 0, 255</description></item><item><term>Color.Gray</term><description>Gray</description><description>128, 128, 128</description></item><item><term>Color.Green</term><description>Green</description><description>0, 128, 0</description></item><item><term>Color.Lime</term><description>Lime</description><description>0, 255, 0</description></item><item><term>Color.Maroon</term><description>Maroon</description><description>128, 0, 0</description></item><item><term>Color.Navy</term><description>Navy</description><description>0, 0, 128</description></item><item><term>Color.Olive</term><description>Olive</description><description>128, 128, 0</description></item><item><term>Color.Purple</term><description>Purple</description><description>128, 0, 128</description></item><item><term>Color.Pink</term><description>Pink</description><description>255, 102, 255</description></item><item><term>Color.Red</term><description>Red</description><description>255, 0, 0</description></item><item><term>Color.Silver</term><description>Silver</description><description>192, 192, 192</description></item><item><term>Color.Teal</term><description>Teal</description><description>0, 128, 128</description></item><item><term>Color.White</term><description>White</description><description>255, 255, 255</description></item><item><term>Color.Yellow</term><description>Yellow</description><description>255, 255, 0</description></item></list></para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Color (double value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 value) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="value" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="value">The luminosity of the gray-scale color.</param>
+ <summary>Initialize a new gray color.</summary>
+ <remarks>This is equivalent to new Color (value, value, value). The value is clamped to [0-1]. App developers should use the <see cref="M:Xamarin.Forms.Color.FromRgb" /> equivalent methods, instead.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Color (double r, double g, double b);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 r, float64 g, float64 b) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="r" Type="System.Double" />
+ <Parameter Name="g" Type="System.Double" />
+ <Parameter Name="b" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="r">The red component of the color.</param>
+ <param name="g">The green component of the color.</param>
+ <param name="b">The blue component of the color.</param>
+ <summary>Initializes a new RGB color.</summary>
+ <remarks>This is equivalent to new Color (r, g, b, 1). Values are clamped to [0-1]. Prefer the <see cref="M:Xamarin.Forms.Color.FromRgb" /> equivalent methods.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Color (double r, double g, double b, double a);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 r, float64 g, float64 b, float64 a) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="r" Type="System.Double" />
+ <Parameter Name="g" Type="System.Double" />
+ <Parameter Name="b" Type="System.Double" />
+ <Parameter Name="a" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="r">The red component of the color.</param>
+ <param name="g">The green component of the color.</param>
+ <param name="b">The blue component of the color.</param>
+ <param name="a">The alpha component of the color.</param>
+ <summary>Initializes a new RGB color with an alpha channel.</summary>
+ <remarks>Values are clamped to [0-1].</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="A">
+ <MemberSignature Language="C#" Value="public double A { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 A" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the alpha component of the color.</summary>
+ <value>The Alpha component of the color as a double that is in the inclusive range [0-1].</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Accent">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Color Accent { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property valuetype Xamarin.Forms.Color Accent" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the accent or tint color from the application.</summary>
+ <value>A Color.</value>
+ <remarks>The accent color is platform and device dependent.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AddLuminosity">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color AddLuminosity (double delta);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Color AddLuminosity(float64 delta) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="delta" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="delta">The delta (positive or negative) to add to the luminosity channel.</param>
+ <summary>Returns a new Color with a modified luminosity channel.</summary>
+ <returns>A new color with a possibly modified luminosity channel.</returns>
+ <remarks>The <paramref name="delta" /> parameter is added to the current luminosity, and the resulting luminosity is then clamped to the inclusive range [0,1].</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Aqua">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Aqua;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Aqua" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Aqua, the color that is represented by the RGB value #00ffff.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="B">
+ <MemberSignature Language="C#" Value="public double B { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 B" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the blue component of the color.</summary>
+ <value>The Blue component of the color as a double that is in the inclusive range [0-1].</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Black">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Black;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Black" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Black, the color that is represented by the RGB value #000000.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Blue">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Blue;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Blue" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Blue, the color that is represented by the RGB value #0000ff.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Default">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Color Default { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property valuetype Xamarin.Forms.Color Default" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Returns the default color.</summary>
+ <value>The default color.</value>
+ <remarks>The Default color is used to unset any Color, and revert to the default one.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Equals">
+ <MemberSignature Language="C#" Value="public override bool Equals (object obj);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool Equals(object obj) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="obj" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="obj">The <see cref="T:System.Object" /> value to compare to this <see cref="T:Xamarin.Forms.Color" /> structure.</param>
+ <summary>Determine if the provided <see cref="T:System.Object" /> is equivalent to the current Color.</summary>
+ <returns>
+ <see langword="true" /> if the provided object is an equivalent Color. Otherwies, <see langword="false" />.</returns>
+ <remarks>Overriden.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromHex">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Color FromHex (string hex);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Color FromHex(string hex) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="hex" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="hex">A string that contains the hexadecimal (A)RGB color representation.</param>
+ <summary>Returns a new RGB Color instance with the requested Red, Green, and Blue channels. The Alpha channel is set if <paramref name="hex" /> contains one.</summary>
+ <returns>A color.</returns>
+ <remarks>
+ <para>When specifying a color with a hexadecimal number, app developers can use 3, 4, 6, or 8 digits. If the developer specifies 3 digits, they are interpreted as RGB doublet data for a fully opaque color. For example, "#123" specifies the color that is represented by "#FF112233". If the developer provides a 4-digit hexadecimal number, then the data are interpreted as above, except that the first digit specifies the alpha channel. For example, "#1234" specifies the color that is represented by "#11223344". If the developer provides a 6 digit hexadecimal number, the data are interpreted as a fully opaque color with those RGB values. For example, "#112233" specifies the color that is represented by "#FF112233". Finally, the developer can explicitly provide an 8-digit number that completely specifies the Alpha, Red, Green, and Blue channels, in that order.</para>
+ <para>Note that, in the paragraph above, the fully expanded color description is of the format, AARRGGBB. That is: the first pair of hexadecimal digits specifies the Alpha channel; the second pair specifies the Red channel; the third pair specifies the Green channel; and the final pair specifies the Blue channel.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromHsla">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Color FromHsla (double h, double s, double l, double a = 1);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Color FromHsla(float64 h, float64 s, float64 l, float64 a) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="h" Type="System.Double" />
+ <Parameter Name="s" Type="System.Double" />
+ <Parameter Name="l" Type="System.Double" />
+ <Parameter Name="a" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="h">The Hue component of the color.</param>
+ <param name="s">The Saturation component of the color.</param>
+ <param name="l">The Luminosity component of the color.</param>
+ <param name="a">The alpha value of the color.</param>
+ <summary>Returns a new HSL Color with an alpha channel</summary>
+ <returns>An HSL color</returns>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromRgb">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Color FromRgb (double r, double g, double b);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Color FromRgb(float64 r, float64 g, float64 b) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="r" Type="System.Double" />
+ <Parameter Name="g" Type="System.Double" />
+ <Parameter Name="b" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="r">The red component of the color.</param>
+ <param name="g">The green component of the color.</param>
+ <param name="b">The blue component of the color.</param>
+ <summary>Returns a new rgb color instance.</summary>
+ <returns>An RGB color</returns>
+ <remarks>Component values are clamped to [0,1]. The <see cref="M:Xamarin.Forms.Color.FromRgb" /> method is striclty equivalent to <c>new Color (r, g, b)</c>, and is present for API consistency.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromRgb">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Color FromRgb (int r, int g, int b);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Color FromRgb(int32 r, int32 g, int32 b) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="r" Type="System.Int32" />
+ <Parameter Name="g" Type="System.Int32" />
+ <Parameter Name="b" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="r">The red component of the color.</param>
+ <param name="g">The green component of the color.</param>
+ <param name="b">The blue component of the color.</param>
+ <summary>Returns a new rgb color instance.</summary>
+ <returns>A new RGB color.</returns>
+ <remarks>Component values are clamped to [0,255].</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromRgba">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Color FromRgba (double r, double g, double b, double a);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Color FromRgba(float64 r, float64 g, float64 b, float64 a) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="r" Type="System.Double" />
+ <Parameter Name="g" Type="System.Double" />
+ <Parameter Name="b" Type="System.Double" />
+ <Parameter Name="a" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="r">The red component of the color.</param>
+ <param name="g">The green component of the color.</param>
+ <param name="b">The blue component of the color.</param>
+ <param name="a">The alpha component of the color.</param>
+ <summary>Returns a new RGBA color instance.</summary>
+ <returns>A new RGBA color.</returns>
+ <remarks>Component values are clamped to [0,1]. The <see cref="M:Xamarin.Forms.Color.FromRgba" /> method is striclty equivalent to <c>new Color (r, g, b, a)</c>, and is present for API consistency.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromRgba">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Color FromRgba (int r, int g, int b, int a);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Color FromRgba(int32 r, int32 g, int32 b, int32 a) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="r" Type="System.Int32" />
+ <Parameter Name="g" Type="System.Int32" />
+ <Parameter Name="b" Type="System.Int32" />
+ <Parameter Name="a" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="r">The red component of the color.</param>
+ <param name="g">The green component of the color.</param>
+ <param name="b">The blue component of the color.</param>
+ <param name="a">The alpha component of the color.</param>
+ <summary>Returns a new RGBA color instance.</summary>
+ <returns>A new RGBA color.</returns>
+ <remarks>Component values are clamped to [0,255].</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromUint">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Color FromUint (uint argb);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Color FromUint(unsigned int32 argb) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="argb" Type="System.UInt32" />
+ </Parameters>
+ <Docs>
+ <param name="argb">A uint that represents the ARGB value of the color.</param>
+ <summary>Returns a new Color with the requested RGBA value.</summary>
+ <returns>An RGBA color.</returns>
+ <remarks>
+ <para>The <paramref name="argb" /> parameter must represent an unsigned integer that can be represented by hexadecimal string that matches the format "AARRGGBB".</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Fuchsia">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Fuchsia;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Fuchsia" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Fucshia, the color that is represented by the RGB value #ff00ff.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Fuschia">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Fuschia;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Fuschia" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Fuschia is obsolete as of version 1.3, please use the correct spelling of Fuchsia")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Fucshia, the color that is represented by the RGB value #ff00ff. Deprecated. See Remarks.</summary>
+ <remarks>Use the <see cref="F:Xamarin.Forms.Color.Fucshia" /> color, instead.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="G">
+ <MemberSignature Language="C#" Value="public double G { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 G" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the Green component of the color.</summary>
+ <value>The Green component of the color as a double that is in the inclusive range [0-1].</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetHashCode">
+ <MemberSignature Language="C#" Value="public override int GetHashCode ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance int32 GetHashCode() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns the Hashcode for this <see cref="T:System.Object" />.</summary>
+ <returns>A signed 32-bit hash code.</returns>
+ <remarks>Overriden.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Gray">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Gray;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Gray" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gray, the color that is represented by the RGB value #808080.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Green">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Green;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Green" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Green, the color that is represented by the RGB value #008000.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Hue">
+ <MemberSignature Language="C#" Value="public double Hue { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Hue" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the Hue of the color.</summary>
+ <value>The Hue component of the color as a double that is in the inclusive range [0-1].</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Lime">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Lime;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Lime" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Lime, the color that is represented by the RGB value #00ff00.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Luminosity">
+ <MemberSignature Language="C#" Value="public double Luminosity { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Luminosity" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the Luminosity fo the color.</summary>
+ <value>The Luminosity component of the color as a double that is in the inclusive range [0-1].</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Maroon">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Maroon;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Maroon" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Maroon, the color that is represented by the RGB value #800000.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MultiplyAlpha">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color MultiplyAlpha (double alpha);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Color MultiplyAlpha(float64 alpha) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="alpha" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="alpha">The alpha multiplicator.</param>
+ <summary>Returns a new color with the alpha channel multiplied by alpha, clamped to the inclusive range [0-1].</summary>
+ <returns>A new RGBA color with a possibly new value for its alpha channel. See Remarks.</returns>
+ <remarks>The resulting color has its alpha channel clamped toto the inclusive range [0-1], preventing invalid colors.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Navy">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Navy;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Navy" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Navy, the color that is represented by the RGB value #000080.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Olive">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Olive;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Olive" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Olive, the color that is represented by the RGB value #808000.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Equality">
+ <MemberSignature Language="C#" Value="public static bool op_Equality (Xamarin.Forms.Color color1, Xamarin.Forms.Color color2);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Equality(valuetype Xamarin.Forms.Color color1, valuetype Xamarin.Forms.Color color2) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="color1" Type="Xamarin.Forms.Color" />
+ <Parameter Name="color2" Type="Xamarin.Forms.Color" />
+ </Parameters>
+ <Docs>
+ <param name="color1">To be added.</param>
+ <param name="color2">To be added.</param>
+ <summary>Returns <see langword="true" /> if <paramref name="color1" /> represents the same color as <paramref name="color1" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Inequality">
+ <MemberSignature Language="C#" Value="public static bool op_Inequality (Xamarin.Forms.Color color1, Xamarin.Forms.Color color2);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Inequality(valuetype Xamarin.Forms.Color color1, valuetype Xamarin.Forms.Color color2) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="color1" Type="Xamarin.Forms.Color" />
+ <Parameter Name="color2" Type="Xamarin.Forms.Color" />
+ </Parameters>
+ <Docs>
+ <param name="color1">To be added.</param>
+ <param name="color2">To be added.</param>
+ <summary>Returns <see langword="true" /> if <paramref name="color1" /> does not represent the same color as <paramref name="color1" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Pink">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Pink;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Pink" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Pink, the color that is represented by the RGB value #ff66ff.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Purple">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Purple;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Purple" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Purple, the color that is represented by the RGB value #800080.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="R">
+ <MemberSignature Language="C#" Value="public double R { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 R" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the Red component of the color.</summary>
+ <value>The Red component of the color as a double that is in the inclusive range [0-1].</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Red">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Red;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Red" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Red, the color that is represented by the RGB value #ff0000.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Saturation">
+ <MemberSignature Language="C#" Value="public double Saturation { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Saturation" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the Saturation of the color</summary>
+ <value>The Saturation component of the color as a double that is in the inclusive range [0-1].</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Silver">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Silver;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Silver" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Silver, the color that is represented by the RGB value #c0c0c0.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Teal">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Teal;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Teal" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Teal, the color that is represented by the RGB value #008080.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ToString">
+ <MemberSignature Language="C#" Value="public override string ToString ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance string ToString() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns a string representation of the Color.</summary>
+ <returns>A string.</returns>
+ <remarks>Overriden. </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Transparent">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Transparent;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Transparent" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The transparent color, represented by the RGB value #00000000.</summary>
+ <remarks>The Alpha channel of the <see cref="F:Xamarin.Forms.Color.Transparent" /> color is set to <c>0</c>.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="White">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color White;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color White" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>White, the color that is represented by the RGB value #ffffff.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="WithHue">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color WithHue (double hue);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Color WithHue(float64 hue) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="hue" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="hue">The modified Hue.</param>
+ <summary>Returns a color with modified Hue, but keeping the same Saturation and Luminosity.</summary>
+ <returns>A color.</returns>
+ <remarks>The Hue is clamped to the inclusive range [0,1]. This method is useful for creating color palettes.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="WithLuminosity">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color WithLuminosity (double luminosity);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Color WithLuminosity(float64 luminosity) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="luminosity" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="luminosity">The modified luminosity.</param>
+ <summary>Returns a color with modified Luminosity.</summary>
+ <returns>A new HSL color.</returns>
+ <remarks>The new Luminosity is clamped to [0,1]. This method is useful for creating color palettes.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="WithSaturation">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color WithSaturation (double saturation);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Color WithSaturation(float64 saturation) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="saturation" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="saturation">The modified Saturation.</param>
+ <summary>Returns a new color with modified Saturation.</summary>
+ <returns>A new HSLcolor.</returns>
+ <remarks>The Saturation is clamped to [0,1]. This method is useful for creating color palettes.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Yellow">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Color Yellow;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Color Yellow" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Yellow, the color that is represented by the RGB value #ffff00..</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ColorTypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ColorTypeConverter.xml
new file mode 100644
index 00000000..895ff7db
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ColorTypeConverter.xml
@@ -0,0 +1,133 @@
+<Type Name="ColorTypeConverter" FullName="Xamarin.Forms.ColorTypeConverter">
+ <TypeSignature Language="C#" Value="public class ColorTypeConverter : Xamarin.Forms.TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ColorTypeConverter extends Xamarin.Forms.TypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TypeConverter" /> that converts from strings to a <see cref="T:Xamarin.Forms.Color" />.</summary>
+ <remarks>
+ <para>The following example shows some variations of <see cref="T:Xamarin.Forms.ColorTypeConverter" />:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+var converter = new ColorTypeConverter ();
+Assert.True (converter.CanConvertFrom (typeof(string)));
+Assert.AreEqual (Color.Blue, converter.ConvertFrom ("Color.Blue"));
+Assert.AreEqual (Color.Blue, converter.ConvertFrom ("Blue"));
+Assert.AreEqual (Color.Blue, converter.ConvertFrom ("#0000ff"));
+Assert.AreEqual (Color.Default, converter.ConvertFrom ("Color.Default"));
+Assert.AreEqual (Color.Accent, converter.ConvertFrom ("Accent"));
+var hotpink = Color.FromHex ("#FF69B4");
+Color.Accent = hotpink;
+Assert.AreEqual (Color.Accent, converter.ConvertFrom ("Accent"));
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ColorTypeConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.ColorTypeConverter" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>Returns a Boolean value that indicates whether this <see cref="T:Xamarin.Forms.ColorTypeConverter" /> can convert the <paramref name="sourceType" /> to a <see cref="T:Xamarin.Forms.Color" /> instance.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Converts <paramref name="value" /> into a <see cref="T:Xamarin.Forms.Color" /> by using the specified <paramref name="culture" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Creates a color from a valid color name.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ColumnDefinition.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ColumnDefinition.xml
new file mode 100644
index 00000000..fe94f31e
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ColumnDefinition.xml
@@ -0,0 +1,135 @@
+<Type Name="ColumnDefinition" FullName="Xamarin.Forms.ColumnDefinition">
+ <TypeSignature Language="C#" Value="public sealed class ColumnDefinition : Xamarin.Forms.BindableObject, Xamarin.Forms.IDefinition" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit ColumnDefinition extends Xamarin.Forms.BindableObject implements class Xamarin.Forms.IDefinition" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IDefinition</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>An <see cref="T:Xamarin.Forms.IDefinition" /> that defines properties for a column in a <see cref="T:Xamarin.Forms.Grid" />.</summary>
+ <remarks>
+ <para>XAML for Xamarin.Forms supports the following property for the <see cref="T:Xamarin.Forms.ColumnDefinition" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Width</term>
+ <description>
+ <para>"*" or "Auto" to indicate the corresponding <see cref="T:Xamarin.Forms.GridUnitType" /> enumeration values, or a number to indicate an absolute width.</para>
+ </description>
+ </item>
+ </list>
+ <example>
+ <para>App developers can specify <see cref="T:Xamarin.Forms.GridUnitType" /> values for the <see cref="P:Xamarin.Forms.ColumnDefinition.Width" /> property in XAML by nesting <c>ColumnDefinition</c> tags inside tags for the <see cref="P:Xamarin.Forms.Grid.ColumnDefinitions" /> collection property. The following example demonstrates setting three column widths to each of the three valid <see cref="T:Xamarin.Forms.GridUnitType" /> values:</para>
+ <code lang="XAML"><![CDATA[
+<Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="100" />
+</Grid.ColumnDefinitions>
+]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ColumnDefinition ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.ColumnDefinition" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SizeChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler SizeChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler SizeChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the size of the column is changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Width">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.GridLength Width { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.GridLength Width" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GridLength</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the width of the column.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="WidthProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty WidthProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty WidthProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ColumnDefinition.Width" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ColumnDefinitionCollection.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ColumnDefinitionCollection.xml
new file mode 100644
index 00000000..949db320
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ColumnDefinitionCollection.xml
@@ -0,0 +1,57 @@
+<Type Name="ColumnDefinitionCollection" FullName="Xamarin.Forms.ColumnDefinitionCollection">
+ <TypeSignature Language="C#" Value="public sealed class ColumnDefinitionCollection : Xamarin.Forms.DefinitionCollection&lt;Xamarin.Forms.ColumnDefinition&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit ColumnDefinitionCollection extends Xamarin.Forms.DefinitionCollection`1&lt;class Xamarin.Forms.ColumnDefinition&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.DefinitionCollection&lt;Xamarin.Forms.ColumnDefinition&gt;</BaseTypeName>
+ <BaseTypeArguments>
+ <BaseTypeArgument TypeParamName="T">Xamarin.Forms.ColumnDefinition</BaseTypeArgument>
+ </BaseTypeArguments>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.DefinitionCollection`1" /> for <see cref="T:Xamarin.Forms.ColumnDefinition" />s.</summary>
+ <remarks>
+ <para>App developers can specify <see cref="T:Xamarin.Forms.GridUnitType" /> values for the <see cref="P:Xamarin.Forms.ColumnDefinition.Width" /> property in XAML by nesting <c>ColumnDefinition</c> tags inside tags for the <see cref="P:Xamarin.Forms.Grid.ColumnDefinitions" /> collection property. The following example demonstrates setting three column widths to each of the three valid <see cref="T:Xamarin.Forms.GridUnitType" /> values:</para>
+ <example>
+ <code lang="XAML"><![CDATA[
+<Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="100" />
+</Grid.ColumnDefinitions>
+]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ColumnDefinitionCollection ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new empty <see cref="T:Xamarin.Forms.ColumnDefinitionCollection" /> collection.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Command.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Command.xml
new file mode 100644
index 00000000..3e2d4ecf
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Command.xml
@@ -0,0 +1,249 @@
+<Type Name="Command" FullName="Xamarin.Forms.Command">
+ <TypeSignature Language="C#" Value="public class Command : System.Windows.Input.ICommand" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Command extends System.Object implements class System.Windows.Input.ICommand" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.Windows.Input.ICommand</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>Defines an <see cref="T:System.Windows.Input.ICommand" /> implementation wrapping an <see cref="System.Action" />.</summary>
+ <remarks>
+ <para>
+ The following example creates a new Command and set it to a button.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+var command = new Command (() => Debug.WriteLine ("Command executed"));
+var button = new Button {
+ Text = "Hit me to execute the command",
+ Command = command,
+};
+]]></code>
+ </example>
+ <para>
+ More useful scenarios takes a parameter
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+var command = new Command (o => Debug.WriteLine ("Command executed: {0}", o));
+var button = new Button {
+ Text = "Hit me to execute the command",
+ Command = command,
+ CommandParameter = "button0",
+};
+]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Command (Action execute);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Action execute) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="execute" Type="System.Action" />
+ </Parameters>
+ <Docs>
+ <param name="execute">An Action to execute when the Command is executed.</param>
+ <summary>Initializes a new instance of the Command class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Command (Action&lt;object&gt; execute);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Action`1&lt;object&gt; execute) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="execute" Type="System.Action&lt;System.Object&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="execute">An Action&lt;object&gt; to execute when the Command is executed.</param>
+ <summary>Initializes a new instance of the Command class.</summary>
+ <remarks>The Action will be executed with a parameter.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Command (Action execute, Func&lt;bool&gt; canExecute);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Action execute, class System.Func`1&lt;bool&gt; canExecute) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="execute" Type="System.Action" />
+ <Parameter Name="canExecute" Type="System.Func&lt;System.Boolean&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="execute">An Action to execute when the Command is executed.</param>
+ <param name="canExecute">A <see cref="T:System.Func&lt;bool&gt;" /> indicating if the Command can be executed.</param>
+ <summary>Initializes a new instance of the Command class.</summary>
+ <remarks>Wehenever the value returned by canExecute has changed, a call to <see cref="M:Xamarin.QuickuI.Command.ChangeCanExecute" /> is required to trigger <see cref="E:System.Windows.Input.ICommand.CanExecuteChanged" />.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Command (Action&lt;object&gt; execute, Func&lt;object,bool&gt; canExecute);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Action`1&lt;object&gt; execute, class System.Func`2&lt;object, bool&gt; canExecute) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="execute" Type="System.Action&lt;System.Object&gt;" />
+ <Parameter Name="canExecute" Type="System.Func&lt;System.Object,System.Boolean&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="execute">An Action&lt;object&gt; to execute when the Command is executed.</param>
+ <param name="canExecute">A <see cref="T:System.Func&lt;object,bool&gt;" /> indicating if the Command can be executed.</param>
+ <summary>Initializes a new instance of the Command class.</summary>
+ <remarks>Wehenever the value returned by canExecute has changed, a call to <see cref="M:Xamarin.QuickuI.Command.ChangeCanExecute" /> is required to trigger <see cref="E:System.Windows.Input.ICommand.CanExecuteChanged" />.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanExecute">
+ <MemberSignature Language="C#" Value="public bool CanExecute (object parameter);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance bool CanExecute(object parameter) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="parameter" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="parameter">An <see cref="T:System.Object" /> used as parameter to determine if the Command can be executed.</param>
+ <summary>Returns a <see cref="T:System.Boolean" /> indicating if the Command can be exectued with the given parameter.</summary>
+ <returns>
+ <see langword="true" /> if the Command can be executed, <see langword="false" /> otherwise.</returns>
+ <remarks>
+ <para>If no canExecute parameter was passed to the Command constructor, this method always returns <see langword="true" />.</para>
+ <para>If the Command was created with non-generic execute parameter, the parameter of this method is ignored.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanExecuteChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler CanExecuteChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler CanExecuteChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs when the target of the Command should reevaluate whether or not the Command can be executed.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ChangeCanExecute">
+ <MemberSignature Language="C#" Value="public void ChangeCanExecute ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void ChangeCanExecute() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Send a <see cref="E:System.Windows.Input.ICommand.CanExecuteChanged" /></summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Execute">
+ <MemberSignature Language="C#" Value="public void Execute (object parameter);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Execute(object parameter) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="parameter" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="parameter">An <see cref="T:System.Object" /> used as parameter for the execute Action.</param>
+ <summary>Invokes the execute Action</summary>
+ <remarks>
+ <para>If the Command was created with non-generic execute parameter, the parameter of this method is ignored.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Command`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Command`1.xml
new file mode 100644
index 00000000..e212dbc2
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Command`1.xml
@@ -0,0 +1,90 @@
+<Type Name="Command&lt;T&gt;" FullName="Xamarin.Forms.Command&lt;T&gt;">
+ <TypeSignature Language="C#" Value="public sealed class Command&lt;T&gt; : Xamarin.Forms.Command" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit Command`1&lt;T&gt; extends Xamarin.Forms.Command" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="T" />
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Command</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <typeparam name="T">The Type of the parameter,</typeparam>
+ <summary>Defines an <see cref="T:System.Windows.Input.ICommand" /> implementation wrapping a generic Action&lt;T&gt;.</summary>
+ <remarks>
+ <para>
+ The following example creates a new Command and set it to a button.
+ </para>
+ <example language="C#">
+ <code lang="C#"><![CDATA[
+var command = new Command<string> (s => Debug.WriteLine ("Command executed: {0}", s));
+var button = new Button {
+ Text = "Hit me to execute the command",
+ Command = command,
+ CommandParameter = "button0",
+};
+]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Command (Action&lt;T&gt; execute);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Action`1&lt;!T&gt; execute) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="execute" Type="System.Action&lt;T&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="execute">An Action to execute when the Command is executed.</param>
+ <summary>Initializes a new instance of the Command class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Command (Action&lt;T&gt; execute, Func&lt;T,bool&gt; canExecute);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Action`1&lt;!T&gt; execute, class System.Func`2&lt;!T, bool&gt; canExecute) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="execute" Type="System.Action&lt;T&gt;" />
+ <Parameter Name="canExecute" Type="System.Func&lt;T,System.Boolean&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="execute">An Action to execute when the Command is executed.</param>
+ <param name="canExecute">A <see cref="T:System.Func&lt;T,bool&gt;" /> indicating if the Command can be executed.</param>
+ <summary>Initializes a new instance of the Command class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Condition.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Condition.xml
new file mode 100644
index 00000000..db7e0867
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Condition.xml
@@ -0,0 +1,21 @@
+<Type Name="Condition" FullName="Xamarin.Forms.Condition">
+ <TypeSignature Language="C#" Value="public abstract class Condition" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit Condition extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Base class for conditions.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Constraint.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Constraint.xml
new file mode 100644
index 00000000..927573cb
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Constraint.xml
@@ -0,0 +1,135 @@
+<Type Name="Constraint" FullName="Xamarin.Forms.Constraint">
+ <TypeSignature Language="C#" Value="public sealed class Constraint" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit Constraint extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.ConstraintTypeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A layout constraint used by <see cref="T:Xamarin.Forms.RelativeLayout" />s.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Constant">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Constraint Constant (double size);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.Constraint Constant(float64 size) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Constraint</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="size" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="size">To be added.</param>
+ <summary>Returns a <see cref="T:Xamarin.Forms.Constraint" /> object that constrains an element to <paramref name="size" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromExpression">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Constraint FromExpression (System.Linq.Expressions.Expression&lt;Func&lt;double&gt;&gt; expression);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.Constraint FromExpression(class System.Linq.Expressions.Expression`1&lt;class System.Func`1&lt;float64&gt;&gt; expression) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Constraint</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="expression" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;System.Double&gt;&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="expression">To be added.</param>
+ <summary>Returns a <see cref="T:Xamarin.Forms.Constraint" /> that is calculated from <paramref name="expression" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RelativeToParent">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Constraint RelativeToParent (Func&lt;Xamarin.Forms.RelativeLayout,double&gt; measure);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.Constraint RelativeToParent(class System.Func`2&lt;class Xamarin.Forms.RelativeLayout, float64&gt; measure) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Constraint</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="measure" Type="System.Func&lt;Xamarin.Forms.RelativeLayout,System.Double&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="measure">To be added.</param>
+ <summary>Returns a <see cref="T:Xamarin.Forms.Constraint" /> object that constrains an element relative to its parent's size.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RelativeToView">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Constraint RelativeToView (Xamarin.Forms.View view, Func&lt;Xamarin.Forms.RelativeLayout,Xamarin.Forms.View,double&gt; measure);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.Constraint RelativeToView(class Xamarin.Forms.View view, class System.Func`3&lt;class Xamarin.Forms.RelativeLayout, class Xamarin.Forms.View, float64&gt; measure) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Constraint</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.View" />
+ <Parameter Name="measure" Type="System.Func&lt;Xamarin.Forms.RelativeLayout,Xamarin.Forms.View,System.Double&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="measure">To be added.</param>
+ <summary>Returns a <see cref="T:Xamarin.Forms.Constraint" /> object that constrains an element relative to the <paramref name="view" /> parameter.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ConstraintExpression.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ConstraintExpression.xml
new file mode 100644
index 00000000..34a112f6
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ConstraintExpression.xml
@@ -0,0 +1,222 @@
+<Type Name="ConstraintExpression" FullName="Xamarin.Forms.ConstraintExpression">
+ <TypeSignature Language="C#" Value="public class ConstraintExpression : Xamarin.Forms.Xaml.IMarkupExtension" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ConstraintExpression extends System.Object implements class Xamarin.Forms.Xaml.IMarkupExtension" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IMarkupExtension</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>Defines a constraint relationship.</summary>
+ <remarks>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.ConstraintExpression" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Constant</term>
+ <description>
+ <para>An optionally signed integer literal.</para>
+ </description>
+ </item>
+ <item>
+ <term>ElementName</term>
+ <description>
+ <para>The name of a source element against which to calculate the constraint.</para>
+ </description>
+ </item>
+ <item>
+ <term>Factor</term>
+ <description>
+ <para>A decimal literal in the range (0,1].</para>
+ </description>
+ </item>
+ <item>
+ <term>Property</term>
+ <description>
+ <para>The name of the property on the source element to use in the constraint calculation.</para>
+ </description>
+ </item>
+ <item>
+ <term>Type</term>
+ <description>
+ <para>
+ <c>Constant</c>, <c>RelativeToParent</c>, or <c>RelativeToView</c>.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ConstraintExpression ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.ConstraintExpression" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Constant">
+ <MemberSignature Language="C#" Value="public double Constant { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Constant" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the constant constraint value..</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ElementName">
+ <MemberSignature Language="C#" Value="public string ElementName { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string ElementName" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the name of a source element against which to calculate the constraint.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Factor">
+ <MemberSignature Language="C#" Value="public double Factor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Factor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the factor by which to scale a constrained dimension, relative to the source element.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Property">
+ <MemberSignature Language="C#" Value="public string Property { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Property" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets name of the property on the source element to use in the constraint calculation.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ProvideValue">
+ <MemberSignature Language="C#" Value="public object ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>Returns a <see cref="T:Xamarin.Forms.Constraint" /> for this <see cref="T:Xamarin.Forms.ConstraintExpression" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Type">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.ConstraintType Type { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.ConstraintType Type" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ConstraintType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the constraint type.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ConstraintType.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ConstraintType.xml
new file mode 100644
index 00000000..05498e82
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ConstraintType.xml
@@ -0,0 +1,83 @@
+<Type Name="ConstraintType" FullName="Xamarin.Forms.ConstraintType">
+ <TypeSignature Language="C#" Value="public enum ConstraintType" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed ConstraintType extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumeration specifying whether a constraint is constant, relative to a view, or relative to its parent.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Constant">
+ <MemberSignature Language="C#" Value="Constant" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ConstraintType Constant = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ConstraintType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A constant constraint.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="RelativeToParent">
+ <MemberSignature Language="C#" Value="RelativeToParent" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ConstraintType RelativeToParent = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ConstraintType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A constraint that is relative to a parent element.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="RelativeToView">
+ <MemberSignature Language="C#" Value="RelativeToView" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ConstraintType RelativeToView = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ConstraintType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A constraint that is relative to a view.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ConstraintTypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ConstraintTypeConverter.xml
new file mode 100644
index 00000000..32e208c3
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ConstraintTypeConverter.xml
@@ -0,0 +1,117 @@
+<Type Name="ConstraintTypeConverter" FullName="Xamarin.Forms.ConstraintTypeConverter">
+ <TypeSignature Language="C#" Value="public class ConstraintTypeConverter : Xamarin.Forms.TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ConstraintTypeConverter extends Xamarin.Forms.TypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TypeConverter" /> that converts from strings to a <see cref="T:Xamarin.Forms.Constraint" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ConstraintTypeConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.ConstraintTypeConverter" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>Returns a Boolean value that indicates whether this <see cref="T:Xamarin.Forms.ConstraintTypeConverter" /> can convert the <paramref name="sourceType" /> to a <see cref="T:Xamarin.Forms.Constraint" /> instance.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Converts <paramref name="value" /> into a <see cref="T:Xamarin.Forms.Constraint" /> by using the specified <paramref name="culture" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>>Converts <paramref name="value" /> into a <see cref="T:Xamarin.Forms.Constraint" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ContentPage.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ContentPage.xml
new file mode 100644
index 00000000..f58679df
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ContentPage.xml
@@ -0,0 +1,146 @@
+<Type Name="ContentPage" FullName="Xamarin.Forms.ContentPage">
+ <TypeSignature Language="C#" Value="public class ContentPage : Xamarin.Forms.TemplatedPage" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ContentPage extends Xamarin.Forms.TemplatedPage" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TemplatedPage</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Content")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.Page" /> that displays a single view.</summary>
+ <remarks>
+ <para>This is a Page displaying a single View, often a container like a <see cref="T:Xamarin.Forms.StackLayout" /> or <see cref="T:Xamarin.Forms.ScrollView" />.</para>
+ <example>
+ <para>The example below is taken from he App.cs file that is contained in the default "Hello, Forms!" app. It uses a <see cref="T:Xamarin.Forms.ContenPage" /> to display a label, which is a typical, though basic, use of the <see cref="T:Xamarin.Forms.ContenPage" /> class.</para>
+ <code lang="C#"><![CDATA[
+using System;
+using Xamarin.Forms;
+
+namespace ContentPageExample
+{
+ public class App
+ {
+ public static Page GetMainPage ()
+ {
+ return new ContentPage {
+ Content = new Label {
+ Text = "Hello, Forms!",
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ HorizontalOptions = LayoutOptions.CenterAndExpand,
+ },
+ };
+ }
+ }
+}
+ ]]></code>
+ <para>The FormsGallery sample, which can be found on the <format type="text/html"><a href="http://developer.xamarin.com/samples/tag/Xamarin.Forms/" target="_blank">Sample Applications</a></format> page, has a ContentPageDemoPage.cs file. This file contains a longer and more complicated example.</para>
+ <para>XAML for Xamarin.Forms supports the following property for the <see cref="T:Xamarin.Forms.ContentPage" /> class:</para>
+ <para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Content</term>
+ <description>
+ <para>A list of <see cref="T:Xamarin.Forms.View" /> objects that represent the visual content of the <see cref="T:Xamarin.Forms.ContentPage" />. This tag can be omitted, and the contents listed directly.</para>
+ </description>
+ </item>
+ </list>A <c>ContentPage</c> tag can be the root element of a XAML document.</para>
+ <para>
+ </para>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ContentPage ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new ContentPage instance.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Content">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.View Content { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.View Content" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.View</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the view that contains the content of the Page.</summary>
+ <value>A <see cref="T:Xamarin.Forms.View" /> subclass, or <see langword="null" />.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ContentProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ContentProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ContentProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ContentPage.Content" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBindingContextChanged">
+ <MemberSignature Language="C#" Value="protected override void OnBindingContextChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnBindingContextChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Method that is called when the binding context changes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ContentPresenter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ContentPresenter.xml
new file mode 100644
index 00000000..bed48692
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ContentPresenter.xml
@@ -0,0 +1,114 @@
+<Type Name="ContentPresenter" FullName="Xamarin.Forms.ContentPresenter">
+ <TypeSignature Language="C#" Value="public class ContentPresenter : Xamarin.Forms.Layout" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ContentPresenter extends Xamarin.Forms.Layout" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Layout</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Layout manager for templated views.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ContentPresenter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new empty <see cref="T:Xamarin.Forms.ContentPresenter" /> with default values</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Content">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.View Content { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.View Content" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.View</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the view whose layout is managed by this <see cref="T:Xamarin.Forms.ContentPresenter" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ContentProperty">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BindableProperty ContentProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static class Xamarin.Forms.BindableProperty ContentProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ContentPresenter.Content" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutChildren">
+ <MemberSignature Language="C#" Value="protected override void LayoutChildren (double x, double y, double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void LayoutChildren(float64 x, float64 y, float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">The X coordinate of the upper left corner of the layout rectangle.</param>
+ <param name="y">The Y coordinate of the upper left corner of the layout rectangle.</param>
+ <param name="width">The width of the layout rectangle.</param>
+ <param name="height">The height of the layout rectangle.</param>
+ <summary>Lays out the children of the <see cref="P:Xamarin.Forms.ContentPresenter.Content" /> property within the rectangle that is defined by <paramref name="x" />, <paramref name="y" />, <paramref name="widht" />, and <paramref name="height" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeRequest">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance valuetype Xamarin.Forms.SizeRequest OnSizeRequest(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use OnMeasure")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">The width constraint of the size request.</param>
+ <param name="heightConstraint">The width constraint of the size request..</param>
+ <summary>Method that is raised when a size request is made.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ContentPropertyAttribute.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ContentPropertyAttribute.xml
new file mode 100644
index 00000000..160ed7ea
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ContentPropertyAttribute.xml
@@ -0,0 +1,94 @@
+<Type Name="ContentPropertyAttribute" FullName="Xamarin.Forms.ContentPropertyAttribute">
+ <TypeSignature Language="C#" Value="public sealed class ContentPropertyAttribute : Attribute" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit ContentPropertyAttribute extends System.Attribute" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Attribute</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple=false, Inherited=true)</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Indicates the property of the type that is the (default) content property.</summary>
+ <remarks>
+ <para>XAML processor uses to determine the content property.</para>
+ <para>
+Decorating types with ContentPropertyAttribute allows shorter XAML syntax. As </para>
+ <example>
+ <see cref="T:Xamarin.Forms.ContentView" /> has a ContentProperty attribute applied, this XAML is valid:
+<code lang="C#"><![CDATA[
+<ContentView>
+ <Label Text="Hello, Forms"\>
+</ContentView>
+ ]]></code>
+This is equivalent to the following, more explicit XAML
+<code lang="C#"><![CDATA[
+<ContentView>
+ <ContentView.Content>
+ <Label Text="Hello, Forms"\>
+ </ContentView.Content>
+</ContentView>
+ ]]></code></example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ContentPropertyAttribute (string name);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string name) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="name">The name of the property.</param>
+ <summary>Initializes a new instance of the ContentPropertyAttribute class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Name">
+ <MemberSignature Language="C#" Value="public string Name { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Name" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the name of the content property</summary>
+ <value>A string representing the name of the content property.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ContentView.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ContentView.xml
new file mode 100644
index 00000000..e372611c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ContentView.xml
@@ -0,0 +1,192 @@
+<Type Name="ContentView" FullName="Xamarin.Forms.ContentView">
+ <TypeSignature Language="C#" Value="public class ContentView : Xamarin.Forms.TemplatedView" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ContentView extends Xamarin.Forms.TemplatedView" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TemplatedView</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Content")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>An element that contains a single child element.</summary>
+ <remarks>
+ <para>XAML for Xamarin.Forms supports the following property for the <see cref="T:Xamarin.Forms.ContentView" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Content</term>
+ <description>
+ <para>The <see cref="T:Xamarin.Forms.View" /> object that represents the visual content of the <see cref="T:Xamarin.Forms.ContentView" />.</para>
+ </description>
+ </item>
+ </list>
+ <para>
+ The following example shows how to construct a new ContentView with a Label inside.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+MainPage = new ContentPage () {
+ // Accomodate iPhone status bar.
+ Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5),
+ Content = new ContentView {
+ Content = new Label { Text = "I'm Content!" },
+ }
+};
+ ]]></code>
+ </example>
+ <para>
+ <img href="ContentView.TripleScreenShot.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ContentView ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance fo the ContentView class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Content">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.View Content { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.View Content" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.View</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the content of the ContentView.</summary>
+ <value>A <see cref="T:Xamarin.Forms.View" /> that contains the content.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ContentProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ContentProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ContentProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ContentView.Content" /> property..</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutChildren">
+ <MemberSignature Language="C#" Value="protected override void LayoutChildren (double x, double y, double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void LayoutChildren(float64 x, float64 y, float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">A value representing the x coordinate of the child region bounding box.</param>
+ <param name="y">A value representing the y coordinate of the child region bounding box.</param>
+ <param name="width">A value representing the y coordinate of the child region bounding box.</param>
+ <param name="height">A value representing the y coordinate of the child region bounding box.</param>
+ <summary>Positions and sizes the content of a ContentView.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBindingContextChanged">
+ <MemberSignature Language="C#" Value="protected override void OnBindingContextChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnBindingContextChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Method that is called when the binding context changes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeRequest">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance valuetype Xamarin.Forms.SizeRequest OnSizeRequest(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">The available width for the ContentView to use</param>
+ <param name="heightConstraint">The available height for the ContentView to use.</param>
+ <summary>This method is called during the measure pass of a layout cycle to get the desired size of the ContentView.</summary>
+ <returns>A <see cref="T:Xamarin.Forms.SizeRequest" /> which contains the desired size of the StackLayout.</returns>
+ <remarks>The results of this method will be the desired size of its content.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ControlTemplate.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ControlTemplate.xml
new file mode 100644
index 00000000..1e478cbe
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ControlTemplate.xml
@@ -0,0 +1,47 @@
+<Type Name="ControlTemplate" FullName="Xamarin.Forms.ControlTemplate">
+ <TypeSignature Language="C#" Value="public class ControlTemplate : Xamarin.Forms.ElementTemplate" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ControlTemplate extends Xamarin.Forms.ElementTemplate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.ElementTemplate</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Template that specifies a group of styles and effects for controls.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ControlTemplate ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>For internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ControlTemplate (Type type);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Type type) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="type" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="type">To be added.</param>
+ <summary>Creates a new control template for the specified control type.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/DataTemplate.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/DataTemplate.xml
new file mode 100644
index 00000000..887c47f7
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/DataTemplate.xml
@@ -0,0 +1,351 @@
+<Type Name="DataTemplate" FullName="Xamarin.Forms.DataTemplate">
+ <TypeSignature Language="C#" Value="public class DataTemplate : Xamarin.Forms.ElementTemplate" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit DataTemplate extends Xamarin.Forms.ElementTemplate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.ElementTemplate</BaseTypeName>
+ </Base>
+ <Interfaces>
+ </Interfaces>
+ <Docs>
+ <summary>A template for multiple bindings, commonly used by <see cref="T:Xamarin.Forms.ListView" />s and <see cref="T:Xamarin.Forms.MultiPage" />s.</summary>
+ <remarks>In XAML, application developers can nest markup inside a <c>DataTemplate</c> tag to create a <see cref="T:Xamarin.Forms.View" /> whose members are bound to the properties of data objects that are contained in a <see cref="P:Xamarin.Forms.MultiPage`1.ItemsSource" /> list.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public DataTemplate ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>For internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public DataTemplate (Func&lt;object&gt; loadTemplate);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Func`1&lt;object&gt; loadTemplate) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="loadTemplate" Type="System.Func&lt;System.Object&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="loadTemplate">A custom content generator to be called </param>
+ <summary>Creates and initializes a new instance of the <see cref="T:Xamarin.Forms.DataTemplate" /> class.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public DataTemplate (Type type);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Type type) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="type" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="type">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.DataTemplate" /> for type <paramref name="type" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Bindings">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IDictionary&lt;Xamarin.Forms.BindableProperty,Xamarin.Forms.BindingBase&gt; Bindings { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IDictionary`2&lt;class Xamarin.Forms.BindableProperty, class Xamarin.Forms.BindingBase&gt; Bindings" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IDictionary&lt;Xamarin.Forms.BindableProperty,Xamarin.Forms.BindingBase&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a dictionary of bindings, indexed by the bound properties.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateContent">
+ <MemberSignature Language="C#" Value="public object CreateContent ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance object CreateContent() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Loads the template for the type that is represented by this <see cref="T:Xamarin.Forms.DataTemplate" /> and sets all of the bindings and values.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetBinding">
+ <MemberSignature Language="C#" Value="public void SetBinding (Xamarin.Forms.BindableProperty property, Xamarin.Forms.BindingBase binding);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void SetBinding(class Xamarin.Forms.BindableProperty property, class Xamarin.Forms.BindingBase binding) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="binding" Type="Xamarin.Forms.BindingBase" />
+ </Parameters>
+ <Docs>
+ <param name="property">To be added.</param>
+ <param name="binding">To be added.</param>
+ <summary>Sets the binding for <paramref name="property" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetValue">
+ <MemberSignature Language="C#" Value="public void SetValue (Xamarin.Forms.BindableProperty property, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void SetValue(class Xamarin.Forms.BindableProperty property, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="property">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Sets the value of <paramref name="property" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Values">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IDictionary&lt;Xamarin.Forms.BindableProperty,object&gt; Values { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IDictionary`2&lt;class Xamarin.Forms.BindableProperty, object&gt; Values" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IDictionary&lt;Xamarin.Forms.BindableProperty,System.Object&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Returns a dictionary of property values for this <see cref="T:Xamarin.Forms.DataTemplate" />, indexed by property.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IDataTemplate.LoadTemplate">
+ <MemberSignature Language="C#" Value="Func&lt;object&gt; Xamarin.Forms.IDataTemplate.LoadTemplate { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Func`1&lt;object&gt; Xamarin.Forms.IDataTemplate.LoadTemplate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Func&lt;System.Object&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use only.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElement.AddResourcesChangedListener">
+ <MemberSignature Language="C#" Value="void IElement.AddResourcesChangedListener (Action&lt;object,Xamarin.Forms.ResourcesChangedEventArgs&gt; onchanged);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IElement.AddResourcesChangedListener(class System.Action`2&lt;object, class Xamarin.Forms.ResourcesChangedEventArgs&gt; onchanged) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="onchanged" Type="System.Action&lt;System.Object,Xamarin.Forms.ResourcesChangedEventArgs&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="onchanged">To be added.</param>
+ <summary>For internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElement.Parent">
+ <MemberSignature Language="C#" Value="Xamarin.Forms.Element Xamarin.Forms.IElement.Parent { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Element Xamarin.Forms.IElement.Parent" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Element</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the parent element of this <see cref="T:Xamarin.Forms.DataTemplate" /> object.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElement.RemoveResourcesChangedListener">
+ <MemberSignature Language="C#" Value="void IElement.RemoveResourcesChangedListener (Action&lt;object,Xamarin.Forms.ResourcesChangedEventArgs&gt; onchanged);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IElement.RemoveResourcesChangedListener(class System.Action`2&lt;object, class Xamarin.Forms.ResourcesChangedEventArgs&gt; onchanged) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="onchanged" Type="System.Action&lt;System.Object,Xamarin.Forms.ResourcesChangedEventArgs&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="onchanged">To be added.</param>
+ <summary>For internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElement.ResourceDictionary">
+ <MemberSignature Language="C#" Value="Xamarin.Forms.IResourceDictionary Xamarin.Forms.IElement.ResourceDictionary { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.IResourceDictionary Xamarin.Forms.IElement.ResourceDictionary" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.IResourceDictionary</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>
+ <para />
+ </summary>
+ <value>
+ <para />
+ </value>
+ <remarks>
+ <para />
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElement.XamlParent">
+ <MemberSignature Language="C#" Value="WeakReference&lt;Xamarin.Forms.Element&gt; Xamarin.Forms.IElement.XamlParent { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.WeakReference`1&lt;class Xamarin.Forms.Element&gt; Xamarin.Forms.IElement.XamlParent" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.WeakReference&lt;Xamarin.Forms.Element&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use only.</summary>
+ <value>
+ <para />
+ </value>
+ <remarks>
+ <para />
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Internals.IDataTemplate.LoadTemplate">
+ <MemberSignature Language="C#" Value="Func&lt;object&gt; Xamarin.Forms.Internals.IDataTemplate.LoadTemplate { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Func`1&lt;object&gt; Xamarin.Forms.Internals.IDataTemplate.LoadTemplate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Func&lt;System.Object&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use only.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/DataTemplateSelector.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/DataTemplateSelector.xml
new file mode 100644
index 00000000..b8e5f4bf
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/DataTemplateSelector.xml
@@ -0,0 +1,121 @@
+<Type Name="DataTemplateSelector" FullName="Xamarin.Forms.DataTemplateSelector">
+ <TypeSignature Language="C#" Value="public abstract class DataTemplateSelector : Xamarin.Forms.DataTemplate" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit DataTemplateSelector extends Xamarin.Forms.DataTemplate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.DataTemplate</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Selects <see cref="T:Xamarin.Forms.DataTemplate" /> objects by data type and container.</summary>
+ <remarks><para>Application developers override the <see cref="M:Xamarin.Froms.DataTemplateSelector.OnSelectTemplate" /> method to return a unique <see cref="T:Xamarin.Forms.DataTemplate" /> for a data type and parent container combination. Additionally, because the same exact template instance must be returned for a given piece of data across successive calls to <see cref="M:Xamarin.Froms.DataTemplateSelector.SelectTemplate" />, developers should create and store these <see cref="T:Xamarin.Forms.DataTemplate" /> in their constructor overrides.</para>
+<block subset="none" type="note">Developers should note the following items: <list type="bullet">
+ <item><term>OnSelectTemplate must not return another DataTemplateSelector, and
+ </term></item>
+ <item><term>The Android platform is limited to 20 templates per list view.</term></item>
+ </list></block>
+<example>The following example shows a basic use:
+<code lang="c#"><![CDATA[class MyDataTemplateSelector : DataTemplateSelector
+{
+ public MyDataTemplateSelector ()
+ {
+ // Retain instances
+ this.templateOne = new DataTemplate (typeof (ViewA));
+ this.templateTwo = new DataTemplate (typeof (ViewB));
+ }
+
+ protected override DataTemplate OnSelectTemplate (object item, BindableObject container)
+ {
+ if (item is double)
+ return this.templateOne;
+ return this.templateTwo;
+ }
+
+ private readonly DataTemplate templateOne;
+ private readonly DataTemplate templateTwo;
+}]]></code></example></remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected DataTemplateSelector ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.DataTemplateSelector" /> with default values.</summary>
+ <remarks>Application developers should provide their own constructors to create and store the <see cref="T:Xamarin.Forms.DataTemplate" /> objects that can be returned by this <see cref="T:Xamarin.Forms.DataTemplateSelector" />.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSelectTemplate">
+ <MemberSignature Language="C#" Value="protected abstract Xamarin.Forms.DataTemplate OnSelectTemplate (object item, Xamarin.Forms.BindableObject container);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance class Xamarin.Forms.DataTemplate OnSelectTemplate(object item, class Xamarin.Forms.BindableObject container) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.DataTemplate</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ <Parameter Name="container" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="item">The data for which to return a template.</param>
+ <param name="container">An optional container object in which the developer may have opted to store <see cref="T:Xamarin.Forms.DataTemplateSelector" /> objects.</param>
+ <summary>Calls <see cref="M:Xamarin.Forms.DataTemplateSelector.SelectTemplate" />.</summary>
+ <returns>A developer-defined <see cref="T:Xamarin.Forms.DataTemplate" /> that can be used to display <paramref name="item" />.</returns>
+ <remarks><para>This method throws an exception if <see cref="M:Xamarin.Forms.DataTemplateSelector.SelectTemplate" /> returns an instance of <see cref="T:Xamarin.Forms.DataTemplateSelector" />.</para></remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SelectTemplate">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.DataTemplate SelectTemplate (object item, Xamarin.Forms.BindableObject container);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class Xamarin.Forms.DataTemplate SelectTemplate(object item, class Xamarin.Forms.BindableObject container) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.DataTemplate</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ <Parameter Name="container" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="item">The data for which to return a template.</param>
+ <param name="container">An optional container object in which the developer may have opted to store <see cref="T:Xamarin.Forms.DataTemplateSelector" /> objects.</param>
+ <summary>When overriden by developers in a derived class, returns a <see cref="T:Xamarin.Forms.DataTemplate" /> for <paramref name="item" />.</summary>
+ <returns><para>A developer-defined <see cref="T:Xamarin.Forms.DataTemplate" /> that can be used to display <paramref name="item" />.</para></returns>
+ <remarks><para>Developers should ensure that this method never returns a <see cref="T:Xamarin.Forms.DataTemplateSelector" /> object, as this will cause the <see cref="M:Xamarin.Forms.DataTemplateSelector.OnSelectTemplate" /> method to throw an exception.</para>
+ <block subset="none" type="note"><para>Developers should note that the he Android platform is limited to 20 templates per list view.</para></block>
+<example>The following example shows a basic use:
+<code lang="c#"><![CDATA[class MyDataTemplateSelector : DataTemplateSelector
+{
+ public MyDataTemplateSelector ()
+ {
+ // Retain instances
+ this.templateOne = new DataTemplate (typeof (ViewA));
+ this.templateTwo = new DataTemplate (typeof (ViewB));
+ }
+
+ protected override DataTemplate OnSelectTemplate (object item, BindableObject container)
+ {
+ if (item is double)
+ return this.templateOne;
+ return this.templateTwo;
+ }
+
+ private readonly DataTemplate templateOne;
+ private readonly DataTemplate templateTwo;
+}]]></code></example></remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/DataTrigger.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/DataTrigger.xml
new file mode 100644
index 00000000..39337fe0
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/DataTrigger.xml
@@ -0,0 +1,161 @@
+<Type Name="DataTrigger" FullName="Xamarin.Forms.DataTrigger">
+ <TypeSignature Language="C#" Value="public sealed class DataTrigger : Xamarin.Forms.TriggerBase, Xamarin.Forms.Xaml.IValueProvider" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit DataTrigger extends Xamarin.Forms.TriggerBase implements class Xamarin.Forms.Xaml.IValueProvider" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TriggerBase</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IValueProvider</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Setters")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Class that represents a binding condition and a list of <see cref="T:Xamarin.Forms.Setter" /> objects that will be applied when the condition is met.</summary>
+ <remarks>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.DataTrigger" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Property</term>
+ <description>
+ <para>The name of the property whose value to compare against <c>Value</c>.</para>
+ </description>
+ </item>
+ <item>
+ <term>Value</term>
+ <description>
+ <para>The value of the property that will trigger the setters in <c>Setters</c>.</para>
+ </description>
+ </item>
+ <item>
+ <term>Setters</term>
+ <description>
+ <para>A list of setters that are called when the property condition is met. Each <c>Setter</c> tag or tag pair in the list has a <c>Property</c> and <c>Value</c> that represents the assignments to perform when the condition is met.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public DataTrigger (Type targetType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Type targetType) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="targetType" Type="System.Type">
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.TypeTypeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Parameter>
+ </Parameters>
+ <Docs>
+ <param name="targetType">To be added.</param>
+ <summary>Initializes a new <see cref="T:Xamarin.Forms.DataTrigger" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Binding">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.BindingBase Binding { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.BindingBase Binding" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindingBase</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the binding whose value will be compared to <see cref="P:Xamarin.Forms.DataTrigger.Value" /> to determine when to invoke the setters.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Setters">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt; Setters { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Setter&gt; Setters" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the list of <see cref="T:Xamarin.Forms.Setter" /> objects that will be applied when the binding that is named by the <see cref="P:Xamarin.Forms.DataTrigger.Binding" /> property becomes equal to <see cref="P:Xamarin.Forms.DataTrigger.Value" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Value">
+ <MemberSignature Language="C#" Value="public object Value { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Value" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the value of the binding, named by the <see cref="P:Xamarin.Forms.DataTrigger.Binding" /> property, that will cause the setters to be applied.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IValueProvider.ProvideValue">
+ <MemberSignature Language="C#" Value="object IValueProvider.ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.Xaml.IValueProvider.ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/DateChangedEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/DateChangedEventArgs.xml
new file mode 100644
index 00000000..6f6c9a06
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/DateChangedEventArgs.xml
@@ -0,0 +1,92 @@
+<Type Name="DateChangedEventArgs" FullName="Xamarin.Forms.DateChangedEventArgs">
+ <TypeSignature Language="C#" Value="public class DateChangedEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit DateChangedEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Event arguments for <see cref="E:Xamarin.Forms.DatePicker.DateSelected" /> event.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public DateChangedEventArgs (DateTime oldDate, DateTime newDate);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(valuetype System.DateTime oldDate, valuetype System.DateTime newDate) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="oldDate" Type="System.DateTime" />
+ <Parameter Name="newDate" Type="System.DateTime" />
+ </Parameters>
+ <Docs>
+ <param name="oldDate">To be added.</param>
+ <param name="newDate">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.DateChangedEventArgs" /> object that represents a change from <paramref name="oldDate" /> to <paramref name="newDate" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="NewDate">
+ <MemberSignature Language="C#" Value="public DateTime NewDate { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype System.DateTime NewDate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.DateTime</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The date that the user entered.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OldDate">
+ <MemberSignature Language="C#" Value="public DateTime OldDate { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype System.DateTime OldDate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.DateTime</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The date that was on the element at the time that the user selected it.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/DatePicker.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/DatePicker.xml
new file mode 100644
index 00000000..913fdd7d
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/DatePicker.xml
@@ -0,0 +1,319 @@
+<Type Name="DatePicker" FullName="Xamarin.Forms.DatePicker">
+ <TypeSignature Language="C#" Value="public class DatePicker : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit DatePicker extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._DatePickerRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.View" /> that allows date picking.</summary>
+ <remarks>
+ <para>The visual representation of a DatePicker is very similar to the one of <see cref="T:Xamarin.Forms.Entry" />, except that a special control for picking a date appears in place of a keyboard.</para>
+ <para>
+ <img href="DatePicker.TripleScreenShot.png" />
+ </para>
+ <para>The following example shows a basic use:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+DatePicker datePicker = new DatePicker
+ {
+ Format = "D",
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+
+]]></code>
+ </example>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.DatePicker" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Format</term>
+ <description>
+ <para>A string that specifies the display format in the control of the chosen date.</para>
+ </description>
+ </item>
+ <item>
+ <term>Date</term>
+ <description>
+ <para>An <c>x:FactoryMethod</c> call to the <see cref="M:System.DateTime.Parse" /> method, or a markup extension call to a method that produces a <see cref="T:System.DateTime" /> object. See below.</para>
+ </description>
+ </item>
+ <item>
+ <term>MinimumDate</term>
+ <description>
+ <para>An <c>x:FactoryMethod</c> call to the <see cref="M:System.DateTime.Parse" /> method, or a markup extension call to a method that produces a <see cref="T:System.DateTime" /> object. See below.</para>
+ </description>
+ </item>
+ <item>
+ <term>MaximumDate</term>
+ <description>
+ <para>An <c>x:FactoryMethod</c> call to the <see cref="M:System.DateTime.Parse" /> method, or a markup extension call to a method that produces a <see cref="T:System.DateTime" /> object. See below.</para>
+ </description>
+ </item>
+ </list>
+ <example>
+ <para>The example below creates a working <see cref="T:Xamarin.Forms.DatePicker" /> that displays the current date and allows the user to select a date between the specified ranges. The value for the <see cref="P:Xamarin.Forms.DatePicker.Date" /> property is specified with the <c>x:Static</c> markup extension, and the <see cref="P:Xamarin.Forms.DatePicker.MinimumDate" /> and <see cref="P:Xamarin.Forms.DatePicker.MaximumDate" /> properties are specified by calling the <see cref="M:System.DateTime.Parse" /> method with the <c>x:FactoryMethod</c> and <x>x:Arguments</x> tags. <block type="note">The example below requires a namespace declaration in the root <c>ContentPage</c> or <c>ContentView</c> tags. In particular, <c>xmlns:sys="clr-namespace:System;assembly=mscorlib"</c> must appear in the attribute list for the root element, so that the XAML parser can resolve the name, <c>sys:DateTime</c>.</block></para>
+ <code lang="XAML"><![CDATA[<StackLayout>
+ <DatePicker VerticalOptions="CenterAndExpand" Date="{x:Static sys:DateTime.Now}">
+ <DatePicker.Format>yyyy-MM-dd</DatePicker.Format>
+ <DatePicker.MinimumDate>
+ <sys:DateTime x:FactoryMethod="Parse">
+ <x:Arguments>
+ <x:String>Jan 1 2000</x:String>
+ </x:Arguments>
+ </sys:DateTime>
+ </DatePicker.MinimumDate>
+ <DatePicker.MaximumDate>
+ <sys:DateTime x:FactoryMethod="Parse">
+ <x:Arguments>
+ <x:String>Dec 31 2050</x:String>
+ </x:Arguments>
+ </sys:DateTime>
+ </DatePicker.MaximumDate>
+ </DatePicker>
+ </StackLayout>]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public DatePicker ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the DatePicker class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Date">
+ <MemberSignature Language="C#" Value="public DateTime Date { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype System.DateTime Date" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.DateTime</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the displayed date. This is a bindable property.</summary>
+ <value>The <see cref="T:System.DateTime" /> displayed in the DatePicker.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="DateProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty DateProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty DateProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Date bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="DateSelected">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.DateChangedEventArgs&gt; DateSelected;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.DateChangedEventArgs&gt; DateSelected" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.DateChangedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>An event fired when the Date property changes.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Format">
+ <MemberSignature Language="C#" Value="public string Format { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Format" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The format of the date to display to the user. This is a dependency property.</summary>
+ <value>A valid date format.</value>
+ <remarks>Format string is the same is passed to DateTime.ToString (string format).</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FormatProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FormatProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FormatProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Format dependency property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MaximumDate">
+ <MemberSignature Language="C#" Value="public DateTime MaximumDate { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype System.DateTime MaximumDate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.DateTime</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The highest date selectable for this DatePicker. This is a bindable property.</summary>
+ <value>The maximum <see cref="T:System.DateTime" /> selectable for the DateEntry. Default December 31, 2100.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MaximumDateProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty MaximumDateProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty MaximumDateProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the MaximumDate bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MinimumDate">
+ <MemberSignature Language="C#" Value="public DateTime MinimumDate { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype System.DateTime MinimumDate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.DateTime</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The lowest date selectable for this DatePicker. This is a bindable property.</summary>
+ <value>The minimum <see cref="T:System.DateTime" /> selectable for the DateEntry. Default January 1, 1900.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MinimumDateProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty MinimumDateProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty MinimumDateProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the MinimumDate bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/DefinitionCollection`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/DefinitionCollection`1.xml
new file mode 100644
index 00000000..07cc7053
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/DefinitionCollection`1.xml
@@ -0,0 +1,392 @@
+<Type Name="DefinitionCollection&lt;T&gt;" FullName="Xamarin.Forms.DefinitionCollection&lt;T&gt;">
+ <TypeSignature Language="C#" Value="public class DefinitionCollection&lt;T&gt; : System.Collections.Generic.ICollection&lt;T&gt;, System.Collections.Generic.IEnumerable&lt;T&gt;, System.Collections.Generic.IList&lt;T&gt; where T : IDefinition" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit DefinitionCollection`1&lt;(class Xamarin.Forms.IDefinition) T&gt; extends System.Object implements class System.Collections.Generic.ICollection`1&lt;!T&gt;, class System.Collections.Generic.IEnumerable`1&lt;!T&gt;, class System.Collections.Generic.IList`1&lt;!T&gt;, class System.Collections.IEnumerable" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="T">
+ <Constraints>
+ <InterfaceName>Xamarin.Forms.IDefinition</InterfaceName>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.ICollection&lt;T&gt;</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.IEnumerable&lt;T&gt;</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.IList&lt;T&gt;</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <summary>A collection parameterized by an <see cref="T:Xamarin.Forms.IDefinition" />. Base class for <see cref="T:Xamarin.Forms.ColumnDefinitionCollection" /> and <see cref="T:Xamarin.Forms.RowDefinitionCollection" />.</summary>
+ <remarks>
+ <para>Objects of type <see cref="T:Xamarin.Forms.DefinitionCollection`1" /> are parameterized with a type of <see cref="T:Xamarin.Forms.IDefinition" />.</para>
+ <para>
+ <img href="IDefinition.DefinitionCollectionRelation.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (T item);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Add(!T item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="item">The <see cref="T:Xamarin.Forms.IDefinition" /> to add.</param>
+ <summary>Adds a <see cref="T:Xamarin.Forms.IDefinition" /> to the collection.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Clear">
+ <MemberSignature Language="C#" Value="public void Clear ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Clear() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Removes all values from this <see cref="T:Xamarin.Forms.DefinitionCollection`1" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Contains">
+ <MemberSignature Language="C#" Value="public bool Contains (T item);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance bool Contains(!T item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="item">The <see cref="T:Xamarin.Forms.IDefinition" /> to check for in this <see cref="T:Xamarin.Forms.DefinitionCollection`1" /> .</param>
+ <summary>Returns a Boolean value that indicates whether or not this <see cref="T:Xamarin.Forms.DefinitionCollection`1" /> contains the specified <see cref="T:Xamarin.Forms.IDefinition" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CopyTo">
+ <MemberSignature Language="C#" Value="public void CopyTo (T[] array, int arrayIndex);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void CopyTo(!T[] array, int32 arrayIndex) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="array" Type="T[]" />
+ <Parameter Name="arrayIndex" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="array">To be added.</param>
+ <param name="arrayIndex">To be added.</param>
+ <summary>Copies <see cref="T:Xamarin.Forms.IDefinition" /> instances from this <see cref="T:Xamarin.Forms.DefinitionCollection`1" /> to an array, starting at the specified index.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Count">
+ <MemberSignature Language="C#" Value="public int Count { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 Count" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the number of <see cref="T:Xamarin.Forms.IDefinition" /> instances contained in this <see cref="T:Xamarin.Forms.DefinitionCollection`1" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetEnumerator">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IEnumerator&lt;T&gt; GetEnumerator ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Collections.Generic.IEnumerator`1&lt;!T&gt; GetEnumerator() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IEnumerator&lt;T&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns an enumerator that iterates through the <see cref="T:Xamarin.Forms.IDefinition" /> instances in this <see cref="T:Xamarin.Forms.DefinitionCollection`1" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IndexOf">
+ <MemberSignature Language="C#" Value="public int IndexOf (T item);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance int32 IndexOf(!T item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="item">The <see cref="T:Xamarin.Forms.IDefinition" /> instance to find.</param>
+ <summary>Returns the index of the first occurrence of <paramref name="item" /> in this <see cref="T:Xamarin.Forms.DefinitionCollection`1" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Insert">
+ <MemberSignature Language="C#" Value="public void Insert (int index, T item);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Insert(int32 index, !T item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="index" Type="System.Int32" />
+ <Parameter Name="item" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="index">The position at which to insert <paramref name="item" />.</param>
+ <param name="item">The <see cref="T:Xamarin.Forms.IDefinition" /> to insert.</param>
+ <summary>Inserts a <see cref="T:Xamarin.Forms.IDefinition" /> into this <see cref="T:Xamarin.Forms.DefinitionCollection`1" /> at the location that is specified by <paramref name="index" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsReadOnly">
+ <MemberSignature Language="C#" Value="public bool IsReadOnly { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsReadOnly" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>
+ <see langword="false" />. <see cref="T:Xamarin.Forms.DefinitionCollection`1" /> instances can have items added to them and removed from them.</summary>
+ <value>
+ <see langword="false" />
+ </value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Item">
+ <MemberSignature Language="C#" Value="public T this[int index] { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance !T Item(int32)" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="index" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="index">The location of the item to get or set.</param>
+ <summary>Gets or sets the value indexed by <paramref name="index" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemSizeChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler ItemSizeChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler ItemSizeChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the display size of item in the collection changes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Remove">
+ <MemberSignature Language="C#" Value="public bool Remove (T item);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance bool Remove(!T item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="item">The <see cref="T:Xamarin.Forms.IDefinition" /> to remove from this <see cref="T:Xamarin.Forms.DefinitionCollection`1" />.</param>
+ <summary>Removes a <see cref="T:Xamarin.Forms.IDefinition" /> from this <see cref="T:Xamarin.Forms.DefinitionCollection`1" /> and returns <see langword="true" /> if the item was removed.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="item" /> was in this <see cref="T:Xamarin.Forms.DefinitionCollection`1" /> and was therefore removed. <see langword="false" /> if <paramref name="item" /> was not in this <see cref="T:Xamarin.Forms.DefinitionCollection`1" />. </returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RemoveAt">
+ <MemberSignature Language="C#" Value="public void RemoveAt (int index);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void RemoveAt(int32 index) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="index" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="index">The location in this <see cref="T:Xamarin.Forms.DefinitionCollection`1" /> from which to remove an <see cref="T:Xamarin.Forms.IDefinition" /> instance.</param>
+ <summary>Removes an item from this <see cref="T:Xamarin.Forms.DefinitionCollection`1" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="System.Collections.IEnumerable.GetEnumerator">
+ <MemberSignature Language="C#" Value="System.Collections.IEnumerator IEnumerable.GetEnumerator ();" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance class System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.IEnumerator</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Gets an enumerator that can be used to iterate over the <see cref="T:Xamarin.Forms.IDefinition" /> instances in this <see cref="T:Xamarin.Forms.DefinitionCollection`1" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/DependencyAttribute.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/DependencyAttribute.xml
new file mode 100644
index 00000000..e7bc85b2
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/DependencyAttribute.xml
@@ -0,0 +1,51 @@
+<Type Name="DependencyAttribute" FullName="Xamarin.Forms.DependencyAttribute">
+ <TypeSignature Language="C#" Value="public class DependencyAttribute : Attribute" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit DependencyAttribute extends System.Attribute" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Attribute</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.AttributeUsage(System.AttributeTargets.Assembly, AllowMultiple=true, Inherited=false)</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>An attribute that indicates that the specified type provides a concrete implementation of a needed interface.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public DependencyAttribute (Type implementorType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Type implementorType) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="implementorType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="implementorType">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.DependencyAttribute" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/DependencyFetchTarget.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/DependencyFetchTarget.xml
new file mode 100644
index 00000000..564f1e5c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/DependencyFetchTarget.xml
@@ -0,0 +1,70 @@
+<Type Name="DependencyFetchTarget" FullName="Xamarin.Forms.DependencyFetchTarget">
+ <TypeSignature Language="C#" Value="public enum DependencyFetchTarget" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed DependencyFetchTarget extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumeration specifying whether <see cref="M:Xamarin.Forms.DependencyService.Get" /> should return a reference to a global or new instance.</summary>
+ <remarks>
+ <para>The following example shows how <see cref="T:Xamarin.Forms.DependencyFetchTarget" /> can be used to specify a new instance:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+var secondFetch = DependencyService.Get<IDependencyTest> (DependencyFetchTarget.NewInstance);
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="GlobalInstance">
+ <MemberSignature Language="C#" Value="GlobalInstance" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.DependencyFetchTarget GlobalInstance = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.DependencyFetchTarget</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Return a global instance.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="NewInstance">
+ <MemberSignature Language="C#" Value="NewInstance" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.DependencyFetchTarget NewInstance = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.DependencyFetchTarget</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Return a new instance.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/DependencyService.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/DependencyService.xml
new file mode 100644
index 00000000..005eab4c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/DependencyService.xml
@@ -0,0 +1,119 @@
+<Type Name="DependencyService" FullName="Xamarin.Forms.DependencyService">
+ <TypeSignature Language="C#" Value="public static class DependencyService" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract sealed beforefieldinit DependencyService extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Static class that provides the <see cref="M:Xamarin.Forms.DependencyService.Get{T}" /> factory method for retrieving platform-specific implementations of the specified type T.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Get&lt;T&gt;">
+ <MemberSignature Language="C#" Value="public static T Get&lt;T&gt; (Xamarin.Forms.DependencyFetchTarget fetchTarget = Xamarin.Forms.DependencyFetchTarget.GlobalInstance) where T : class;" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig !!T Get&lt;class T&gt;(valuetype Xamarin.Forms.DependencyFetchTarget fetchTarget) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="T">
+ <Constraints>
+ <ParameterAttribute>ReferenceTypeConstraint</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="fetchTarget" Type="Xamarin.Forms.DependencyFetchTarget" />
+ </Parameters>
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <param name="fetchTarget">To be added.</param>
+ <summary>Returns the platform-specific implementation of type T.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Register&lt;T&gt;">
+ <MemberSignature Language="C#" Value="public static void Register&lt;T&gt; () where T : class;" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Register&lt;class T&gt;() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="T">
+ <Constraints>
+ <ParameterAttribute>ReferenceTypeConstraint</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Parameters />
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <summary>Registers the platform-specific implementation of type T.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Register&lt;T,TImpl&gt;">
+ <MemberSignature Language="C#" Value="public static void Register&lt;T,TImpl&gt; () where T : class where TImpl : class, T;" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Register&lt;class T, class (!!T) TImpl&gt;() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="T">
+ <Constraints>
+ <ParameterAttribute>ReferenceTypeConstraint</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ <TypeParameter Name="TImpl">
+ <Constraints>
+ <ParameterAttribute>ReferenceTypeConstraint</ParameterAttribute>
+ <BaseTypeName>T</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Parameters />
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <typeparam name="TImpl">To be added.</typeparam>
+ <summary>Registers the platform-specific implementation of type T.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Device+Styles.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Device+Styles.xml
new file mode 100644
index 00000000..8221f5c0
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Device+Styles.xml
@@ -0,0 +1,237 @@
+<Type Name="Device+Styles" FullName="Xamarin.Forms.Device+Styles">
+ <TypeSignature Language="C#" Value="public static class Device.Styles" />
+ <TypeSignature Language="ILAsm" Value=".class nested public auto ansi abstract sealed beforefieldinit Device/Styles extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Class that exposes device-specific styles as static fields.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="BodyStyle">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Style BodyStyle;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Style BodyStyle" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Style</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The device-specific body style.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BodyStyleKey">
+ <MemberSignature Language="C#" Value="public static readonly string BodyStyleKey;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly string BodyStyleKey" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The key that identifies the device-specific <see cref="F:Xamarin.Forms.Device+Styles.BodyStyle" /> in the base resource.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CaptionStyle">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Style CaptionStyle;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Style CaptionStyle" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Style</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The device-specific caption style.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CaptionStyleKey">
+ <MemberSignature Language="C#" Value="public static readonly string CaptionStyleKey;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly string CaptionStyleKey" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The key that identifies the device-specific <see cref="F:Xamarin.Forms.Device+Styles.CaptionStyle" /> in the base resource.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ListItemDetailTextStyle">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Style ListItemDetailTextStyle;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Style ListItemDetailTextStyle" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Style</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The device-specific style for detail text in list items.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ListItemDetailTextStyleKey">
+ <MemberSignature Language="C#" Value="public static readonly string ListItemDetailTextStyleKey;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly string ListItemDetailTextStyleKey" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The key that identifies the device-specific <see cref="F:Xamarin.Forms.Device+Styles.ListItemDetailTextStyle" /> in the base resource.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ListItemTextStyle">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Style ListItemTextStyle;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Style ListItemTextStyle" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Style</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The device-specific style for text in list items.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ListItemTextStyleKey">
+ <MemberSignature Language="C#" Value="public static readonly string ListItemTextStyleKey;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly string ListItemTextStyleKey" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The key that identifies the device-specific <see cref="F:Xamarin.Forms.Device+Styles.ListItemTextStyle" /> in the base resource.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SubtitleStyle">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Style SubtitleStyle;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Style SubtitleStyle" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Style</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The device-specific subtitle style.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SubtitleStyleKey">
+ <MemberSignature Language="C#" Value="public static readonly string SubtitleStyleKey;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly string SubtitleStyleKey" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The key that identifies the device-specific <see cref="F:Xamarin.Forms.Device+Styles.SubtitleStyle" /> in the base resource.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TitleStyle">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Style TitleStyle;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Style TitleStyle" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Style</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The device-specific title style.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TitleStyleKey">
+ <MemberSignature Language="C#" Value="public static readonly string TitleStyleKey;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly string TitleStyleKey" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The key that identifies the device-specific <see cref="F:Xamarin.Forms.Device+Styles.TitleStyle" /> in the base resource.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Device.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Device.xml
new file mode 100644
index 00000000..d5c3fce4
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Device.xml
@@ -0,0 +1,289 @@
+<Type Name="Device" FullName="Xamarin.Forms.Device">
+ <TypeSignature Language="C#" Value="public static class Device" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract sealed beforefieldinit Device extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A utility class to interact with the current Device/Platform.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="BeginInvokeOnMainThread">
+ <MemberSignature Language="C#" Value="public static void BeginInvokeOnMainThread (Action action);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void BeginInvokeOnMainThread(class System.Action action) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="action" Type="System.Action" />
+ </Parameters>
+ <Docs>
+ <param name="action">The Action to invoke </param>
+ <summary>Invokes an Action on the device main (UI) thread.</summary>
+ <remarks>
+ <para>This example shows how to set the Text of Label on the main thread, e.g. in response to an async event.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+Device.BeginInvokeOnMainThread (() => {
+ label.Text = "Async operation completed";
+});
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetNamedSize">
+ <MemberSignature Language="C#" Value="public static double GetNamedSize (Xamarin.Forms.NamedSize size, Type targetElementType);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig float64 GetNamedSize(valuetype Xamarin.Forms.NamedSize size, class System.Type targetElementType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="size" Type="Xamarin.Forms.NamedSize" />
+ <Parameter Name="targetElementType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="size">To be added.</param>
+ <param name="targetElementType">To be added.</param>
+ <summary>Returns a double that represents the named size for the font that is used on the element on the native platform.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetNamedSize">
+ <MemberSignature Language="C#" Value="public static double GetNamedSize (Xamarin.Forms.NamedSize size, Xamarin.Forms.Element targetElement);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig float64 GetNamedSize(valuetype Xamarin.Forms.NamedSize size, class Xamarin.Forms.Element targetElement) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="size" Type="Xamarin.Forms.NamedSize" />
+ <Parameter Name="targetElement" Type="Xamarin.Forms.Element" />
+ </Parameters>
+ <Docs>
+ <param name="size">To be added.</param>
+ <param name="targetElement">To be added.</param>
+ <summary>Returns a double that represents a font size that corresponds to <paramref name="size" /> on <paramref name="targetElement" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Idiom">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.TargetIdiom Idiom { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property valuetype Xamarin.Forms.TargetIdiom Idiom" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TargetIdiom</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the kind of device that Xamarin.Forms is currently working on.</summary>
+ <value>A <see cref="T:Xamarin.Forms.TargetIdiom" /> that represents the device type.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnPlatform">
+ <MemberSignature Language="C#" Value="public static void OnPlatform (Action iOS = null, Action Android = null, Action WinPhone = null, Action Default = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void OnPlatform(class System.Action iOS, class System.Action Android, class System.Action WinPhone, class System.Action Default) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="iOS" Type="System.Action" />
+ <Parameter Name="Android" Type="System.Action" />
+ <Parameter Name="WinPhone" Type="System.Action" />
+ <Parameter Name="Default" Type="System.Action" />
+ </Parameters>
+ <Docs>
+ <param name="iOS">(optional) The Action to execute on iOS.</param>
+ <param name="Android">(optional) The Action to execute on Android.</param>
+ <param name="WinPhone">(optional) The Action to execute on WinPhone.</param>
+ <param name="Default">(optional) The Action to execute if no Action was provided for the current OS.</param>
+ <summary>Executes different Actions depending on the <see cref="T:Xamarin.QcuikUI.TargetOS" /> that Xamarin.Forms is working on.</summary>
+ <remarks>
+ <para>This example shows how to change the font of a Label on a single OS.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+Device.OnPlatform (iOS: () => label.Font = Font.OfSize ("HelveticaNeue-UltraLight", NamedSize.Large));
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnPlatform&lt;T&gt;">
+ <MemberSignature Language="C#" Value="public static T OnPlatform&lt;T&gt; (T iOS, T Android, T WinPhone);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig !!T OnPlatform&lt;T&gt;(!!T iOS, !!T Android, !!T WinPhone) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="T" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="iOS" Type="T" />
+ <Parameter Name="Android" Type="T" />
+ <Parameter Name="WinPhone" Type="T" />
+ </Parameters>
+ <Docs>
+ <typeparam name="T">The type of the value to be returned.</typeparam>
+ <param name="iOS">The value for iOS.</param>
+ <param name="Android">The value for Android.</param>
+ <param name="WinPhone">The value for WinPhone.</param>
+ <summary>Returns different values depending on the <see cref="T:Xamarin.Forms.TargetOS" /> Xamarin.Forms is working on.</summary>
+ <returns>The value for the current OS.</returns>
+ <remarks>
+ <para>This example shows how to use different heights for a Button on different OS.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+button.HeightRequest = Device.OnPlatform (20,30,30);
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OpenUri">
+ <MemberSignature Language="C#" Value="public static void OpenUri (Uri uri);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void OpenUri(class System.Uri uri) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="uri" Type="System.Uri" />
+ </Parameters>
+ <Docs>
+ <param name="uri">The <see cref="T:ystem.Uri" /> to open.</param>
+ <summary>Request the device to open the Uri.</summary>
+ <remarks>This often navigates out of the application.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OS">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.TargetPlatform OS { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property valuetype Xamarin.Forms.TargetPlatform OS" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TargetPlatform</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the <see cref="Xamarin.Forms.TargetPlatform" /> indicating the OS Xamarin.Forms is working on.</summary>
+ <value>A <see cref="Xamarin.Forms.TargetPlatform" /> that indicates the current OS.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="StartTimer">
+ <MemberSignature Language="C#" Value="public static void StartTimer (TimeSpan interval, Func&lt;bool&gt; callback);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void StartTimer(valuetype System.TimeSpan interval, class System.Func`1&lt;bool&gt; callback) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="interval" Type="System.TimeSpan" />
+ <Parameter Name="callback" Type="System.Func&lt;System.Boolean&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="interval">The interval between invocations of the callback.</param>
+ <param name="callback">The action to run when the timer elapses.</param>
+ <summary>Starts a recurring timer using the device clock capabilities.</summary>
+ <remarks>While the callback returns <see langword="true" />, the timer will keep recurring.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Easing.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Easing.xml
new file mode 100644
index 00000000..ffd8b16f
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Easing.xml
@@ -0,0 +1,495 @@
+<Type Name="Easing" FullName="Xamarin.Forms.Easing">
+ <TypeSignature Language="C#" Value="public class Easing" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi Easing extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Functions that modify values non-linearly, generally used for animations.</summary>
+ <remarks>
+ <para>Easing functions are applied to input values in the range [0,1]. The cubic easing functions are often considered to look most natural.</para>
+ <para>If developers wish to use their own easing functions, they should return a value of 0 for an input of 0 and a value of 1 for an input of 1 or the animation will have a jump.</para>
+ <para>The predefined <see cref="T:Xamarin.Forms.Easing" /> functions have the following forms:</para>
+ <list type="table">
+ <listheader>
+ <term>Member</term>
+ <description>Graph</description>
+ </listheader>
+ <item>
+ <term>
+ <see cref="F:Xamarin.Forms.Easing.BounceIn" />
+ </term>
+ <description>
+ <para>
+ <img href="Easing.BounceIn.png" />
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>
+ <see cref="F:Xamarin.Forms.Easing.BounceOut" />
+ </term>
+ <description>
+ <para>
+ <img href="Easing.BounceOut.png" />
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>
+ <see cref="F:Xamarin.Forms.Easing.CubicIn" />
+ </term>
+ <description>
+ <para>
+ <img href="Easing.CubicIn.png" />
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>
+ <see cref="F:Xamarin.Forms.Easing.CubicInOut" />
+ </term>
+ <description>
+ <para>
+ <img href="Easing.CubicInOut.png" />
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>
+ <see cref="F:Xamarin.Forms.Easing.CubicOut" />
+ </term>
+ <description>
+ <para>
+ <img href="Easing.CubicOut.png" />
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>
+ <see cref="F:Xamarin.Forms.Easing.Linear" />
+ </term>
+ <description>
+ <para>
+ <img href="Easing.Linear.png" />
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>
+ <see cref="F:Xamarin.Forms.Easing.SinIn" />
+ </term>
+ <description>
+ <para>
+ <img href="Easing.SinIn.gif" />
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>
+ <see cref="F:Xamarin.Forms.Easing.SinInOut" />
+ </term>
+ <description>
+ <para>
+ <img href="Easing.SinInOut.gif" />
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>
+ <see cref="F:Xamarin.Forms.Easing.SinOut" />
+ </term>
+ <description>
+ <para>
+ <img href="Easing.SinOut.gif" />
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>
+ <see cref="F:Xamarin.Forms.Easing.SpringIn" />
+ </term>
+ <description>
+ <para>
+ <img href="Easing.SpringIn.png" />
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>
+ <see cref="F:Xamarin.Forms.Easing.SpringOut" />
+ </term>
+ <description>
+ <para>
+ <img href="Easing.SpringOut.png" />
+ </para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Easing (Func&lt;double,double&gt; easingFunc);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Func`2&lt;float64, float64&gt; easingFunc) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="easingFunc" Type="System.Func&lt;System.Double,System.Double&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="easingFunc">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Easing" /> object with the <paramref name="easingFunc" /> function.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BounceIn">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Easing BounceIn;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Easing BounceIn" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Easing</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Jumps towards, and then bounces as it settles at the final value. (Note: Known bug in 1.0.0 release)</summary>
+ <remarks>
+ <para>NOTE: The 1.0.0. release of <see cref="F:Xamarin.Forms.Easing.BounceIn" /> has a known bug and runs backwards. The following graph shows the desired behavior, shortly to be released:</para>
+ <para>
+ <img href="Easing.BounceIn.png" />
+ </para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BounceOut">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Easing BounceOut;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Easing BounceOut" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Easing</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Leaps to final values, bounces 3 times, and settles.</summary>
+ <remarks>
+ <para>
+ <img href="Easing.BounceOut.png" />
+ </para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CubicIn">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Easing CubicIn;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Easing CubicIn" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Easing</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Starts slowly and accelerates.</summary>
+ <remarks>
+ <para>
+ <img href="Easing.CubicIn.png" />
+ </para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CubicInOut">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Easing CubicInOut;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Easing CubicInOut" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Easing</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Accelerates and decelerates. Often a natural-looking choice.</summary>
+ <remarks>
+ <para>
+ <img href="Easing.CubicInOut.png" />
+ </para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CubicOut">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Easing CubicOut;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Easing CubicOut" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Easing</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Starts quickly and the decelerates.</summary>
+ <remarks>
+ <para>
+ <img href="Easing.CubicOut.png" />
+ </para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Ease">
+ <MemberSignature Language="C#" Value="public double Ease (double v);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance float64 Ease(float64 v) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="v" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="v">A value in the range [0,1] to which the easing function should be applied.</param>
+ <summary>Applies the easing function to the specified value <paramref name="v" />.</summary>
+ <returns>The value of the easing function when applied to the value <paramref name="v" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Linear">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Easing Linear;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Easing Linear" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Easing</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Linear transformation.</summary>
+ <remarks>
+ <para>
+ <img href="Easing.Linear.png" />
+ </para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Implicit">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Easing op_Implicit (Func&lt;double,double&gt; func);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname class Xamarin.Forms.Easing op_Implicit(class System.Func`2&lt;float64, float64&gt; func) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Easing</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="func" Type="System.Func&lt;System.Double,System.Double&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="func">An easing function.</param>
+ <summary>Converts a function into an <see cref="T:Xamarin.Forms.Easing" />.</summary>
+ <returns>An <see cref="T:Xamarin.Forms.Easing" /> for the <paramref name="func" />.</returns>
+ <remarks>
+ <para>An easing function should return a value of (or near) 0 at 0 and 1 (or near) for 1. </para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SinIn">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Easing SinIn;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Easing SinIn" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Easing</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Smoothly accelerates.</summary>
+ <remarks>
+ <para>
+ <img href="Easing.SinIn.gif" />
+ </para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SinInOut">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Easing SinInOut;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Easing SinInOut" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Easing</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Accelerates in and out.</summary>
+ <remarks>
+ <para>
+ <img href="Easing.SinInOut.gif" />
+ </para>.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SinOut">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Easing SinOut;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Easing SinOut" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Easing</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Smoothly decelerates.</summary>
+ <remarks>
+ <para>
+ <img href="Easing.SinOut.gif" />
+ </para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SpringIn">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Easing SpringIn;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Easing SpringIn" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Easing</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Moves away and then leaps toward the final value.</summary>
+ <remarks>
+ <para>
+ <img href="Easing.SpringIn.png" />
+ </para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SpringOut">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Easing SpringOut;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.Easing SpringOut" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Easing</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Overshoots and then returns.</summary>
+ <remarks>
+ <para>
+ <img href="Easing.SpringOut.png" />
+ </para>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Editor.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Editor.xml
new file mode 100644
index 00000000..3c45623a
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Editor.xml
@@ -0,0 +1,300 @@
+<Type Name="Editor" FullName="Xamarin.Forms.Editor">
+ <TypeSignature Language="C#" Value="public class Editor : Xamarin.Forms.InputView" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Editor extends Xamarin.Forms.InputView" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.InputView</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._EditorRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A control that can edit multiple lines of text.</summary>
+ <remarks>
+ <para>For single line entries, see <see cref="T:Xamarin.Forms.Entry" />.</para>
+ <para>
+ <img href="Editor.TripleScreenShot.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Editor ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the Editor class.</summary>
+ <remarks>
+ <para>
+ The following example creates a Editor with a Chat keyboard that fills the available space.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+var editor = new Editor {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Keyboard = Keyboard.Chat,
+};
+ ]]></code>
+ </example>
+ <para>XAML for Xamarin.Forms supports the following property for the <see cref="T:Xamarin.Forms.Editor" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Text</term>
+ <description>
+ <para>The initial text that will appear in the editor.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Completed">
+ <MemberSignature Language="C#" Value="public event EventHandler Completed;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Completed" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is fired when editing has completed.</summary>
+ <remarks>iOS (Unfocusing the editor or pressing "Done" triggers the event). Android / Windows Phone (Unfocusing the Editor triggers the event)</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontAttributes">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.FontAttributes FontAttributes { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.FontAttributes FontAttributes" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FontAttributes</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that indicates whether the font for the editor is bold, italic, or neither.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontAttributesProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontAttributesProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontAttributesProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the FontAttributes property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontFamily">
+ <MemberSignature Language="C#" Value="public string FontFamily { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string FontFamily" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the font family to which the font for the editor belongs.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontFamilyProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontFamilyProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontFamilyProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the FontFamily property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontSize">
+ <MemberSignature Language="C#" Value="public double FontSize { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 FontSize" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.FontSizeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the size of the font for the editor.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontSizeProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontSizeProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontSizeProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the FontSize property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Text">
+ <MemberSignature Language="C#" Value="public string Text { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Text" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the text of the entry. This is a bindable property.</summary>
+ <value>A string containing the text of the entry. The default value is null.</value>
+ <remarks>Setting this property will cause the <see cref="E:Xamarin.Forms.Editor.TextChanged" /> event to be emitted.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.TextChangedEventArgs&gt; TextChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.TextChangedEventArgs&gt; TextChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.TextChangedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs when the text of the Editor changes.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color TextColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color TextColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the text color.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TextColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TextColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.Editor.TextColor" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TextProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TextProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Text bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Effect.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Effect.xml
new file mode 100644
index 00000000..2ccc573f
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Effect.xml
@@ -0,0 +1,130 @@
+<Type Name="Effect" FullName="Xamarin.Forms.Effect">
+ <TypeSignature Language="C#" Value="public abstract class Effect" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit Effect extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A collection of styles and properties that can be added to an element at run time.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Element">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Element Element { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Element Element" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Element</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the element to which the style is attached.</summary>
+ <value>The <see cref="T:Xamarin.Forms.Element" /> to which the property is attached, if the property is attached. Otherwise, <see langword="null" />.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsAttached">
+ <MemberSignature Language="C#" Value="public bool IsAttached { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsAttached" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that tells whether the effect is attached to an element.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnAttached">
+ <MemberSignature Language="C#" Value="protected abstract void OnAttached ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnAttached() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Method that is called after the effect is attached and made valid.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnDetached">
+ <MemberSignature Language="C#" Value="protected abstract void OnDetached ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnDetached() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Method that is called after the effect is detached and invalidated.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Resolve">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Effect Resolve (string name);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.Effect Resolve(string name) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Effect</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <summary>Returns an <see cref="T:Xamarin.Forms.Effect" /> for the specified name, which is of the form <c>ResolutionGroupName.ExportEffect</c>.</summary>
+ <returns>The uniquely identified effect.</returns>
+ <remarks>The <see cref="T:Xamarin.Forms.Effect.Resolve" /> method takes a string that is the concatenation of a resolution group name (supplied to <see cref="T:Xamarin.Forms.ResolutionGroupNameAttribute" />), <c>'.'</c>, and the unique name that was supplied to <see cref="T:Xamarin.Forms.ExportEffectAttribute" />, and returns the specified effect.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ResolveId">
+ <MemberSignature Language="C#" Value="public string ResolveId { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string ResolveId" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the ID that is used to resolve this effect at runtime.</summary>
+ <value>The ID that is used to resolve this effect at runtime.</value>
+ <remarks><para>Developers must supply a name to <see cref="T:Xamarin.Forms.ExportEffectAttribute" /> that is unique over the scope of the name that they supply to <see cref="T:Xamarin.Forms.ResolutionGroupNameAttribute" />. The <see cref="T:Xamarin.Forms.Effect.Resolve" /> method takes a string that is the concatenation of <paramref name="name" /> (the resolution group name), <c>'.'</c>, and the unique name that was supplied to <see cref="T:Xamarin.Forms.ExportEffectAttribute" />, and returns the specified effect.</para>
+ <example><para>For example, with the declarations:</para>
+ <code lang="c#"><![CDATA[
+ [assembly: ResolutionGroupName ("com.YourCompany")]
+ [assembly: ExportEffect (typeof (ShadowEffect), "ShadowEffect")]]]>
+ </code>
+ <para>Then the code below will add the effect to a button:</para>
+ <code lang="c#"><![CDATA[
+ [var button = new Button { Text = "I have a shadow" };
+ button.Effects.Add (Effect.Resolve ("com.YourCompany.ShadowEffect"));]]>
+ </code>
+ </example>
+<para>This property returns the string that developers pass to <see cref="T:Xamarin.Forms.Effect.Resolve" /> to get the effect at runtime.</para></remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Element.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Element.xml
new file mode 100644
index 00000000..917a24eb
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Element.xml
@@ -0,0 +1,885 @@
+<Type Name="Element" FullName="Xamarin.Forms.Element">
+ <TypeSignature Language="C#" Value="public abstract class Element : Xamarin.Forms.BindableObject, Xamarin.Forms.IElementController, Xamarin.Forms.Internals.INameScope" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit Element extends Xamarin.Forms.BindableObject implements class Xamarin.Forms.IElementController, class Xamarin.Forms.Internals.INameScope" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IElementController</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Internals.INameScope</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>Provides the base class for all Forms hierarchal elements. This class contains all the methods and properties required to represent an element in the Forms hierarchy.</summary>
+ <remarks>
+ <para>The following diagram shows the classes derived from <see cref="T:Xamarin.Forms.Element" />. </para>
+ <para>
+ <img href="Element.Hierarchy.png" />
+ </para>
+ <para>The diagram shows some important categories:</para>
+ <list type="table">
+ <listheader>
+ <term>Class</term>
+ <description>Description</description>
+ </listheader>
+ <item>
+ <term>
+ <see cref="T:Xamarin.Forms.VisualElement" />
+ </term>
+ <description>A <see cref="T:Xamarin.Forms.Element" /> that occupies an area on the screen, has a visual appearance, and can obtain touch input.</description>
+ </item>
+ <item>
+ <term>
+ <see cref="T:Xamarin.Forms.Cell" />
+ </term>
+ <description>Cells are elements meant to be added to <see cref="T:Xamarin.Forms.ListView" /> or <see cref="T:Xamarin.Forms.TableView" />.</description>
+ </item>
+ <item>
+ <term>
+ <see cref="T:Xamarin.Forms.Page" />
+ </term>
+ <description>A <see cref="T:Xamarin.Forms.VisualElement" /> that occupies most or all of the screen and contains a single child.</description>
+ </item>
+ <item>
+ <term>
+ <see cref="T:Xamarin.Forms.Layout" />
+ </term>
+ <description>
+ <see cref="T:Xamarin.Forms.Layout" /> have a single child of type <see cref="T:Xamarin.Forms.View" />, while subclasses of <see cref="T:Xamarin.Forms.Layout`1" /> have a collection of multiple children views, including other layouts.</description>
+ </item>
+ <item>
+ <term>
+ Controls and specialized <see cref="T:Xamarin.Forms.View" />s
+ </term>
+ <description>The lower part of the diagram shows the Xamarin.Forms classes for universally-available controls, such as <see cref="T:Xamarin.Forms.Button" />s and <see cref="T:Xamarin.Forms.TableView" />s.</description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected Element ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Protected constructor used to initialize a the element.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AutomationId">
+ <MemberSignature Language="C#" Value="public string AutomationId { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string AutomationId" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ChildAdded">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ElementEventArgs&gt; ChildAdded;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ElementEventArgs&gt; ChildAdded" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ElementEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs whenever a child element is added to the element.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ChildRemoved">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ElementEventArgs&gt; ChildRemoved;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ElementEventArgs&gt; ChildRemoved" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ElementEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs whenever a child element is removed from the element.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ClassId">
+ <MemberSignature Language="C#" Value="public string ClassId { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string ClassId" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value used to identify a collection of semantically similar elements.</summary>
+ <value>A string that represents the collection the element belongs to.</value>
+ <remarks>Use the class id property to collect together elements into semantically similar groups for identification in ui testing and in theme engines.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ClassIdProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ClassIdProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ClassIdProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the ClassId bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="DescendantAdded">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ElementEventArgs&gt; DescendantAdded;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ElementEventArgs&gt; DescendantAdded" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ElementEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs whenever a child element is added to the elements subtree.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="DescendantRemoved">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ElementEventArgs&gt; DescendantRemoved;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ElementEventArgs&gt; DescendantRemoved" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ElementEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs whenever a child element is removed from the elements subtree.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Effects">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.Effect&gt; Effects { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Effect&gt; Effects" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.Effect&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A list of the effects that are applied to this item.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Id">
+ <MemberSignature Language="C#" Value="public Guid Id { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype System.Guid Id" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Guid</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that can be used to uniquely identify an element through the run of an application.</summary>
+ <value>A Guid uniquely identifying the element.</value>
+ <remarks>This value is generated at runtime and is not stable across runs of your app.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBindingContextChanged">
+ <MemberSignature Language="C#" Value="protected override void OnBindingContextChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnBindingContextChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invoked whenever the binding context of the element changes. Implement this method to add class handling for this event.</summary>
+ <remarks>Implementors must call the base method.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnChildAdded">
+ <MemberSignature Language="C#" Value="protected virtual void OnChildAdded (Xamarin.Forms.Element child);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnChildAdded(class Xamarin.Forms.Element child) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="child" Type="Xamarin.Forms.Element" />
+ </Parameters>
+ <Docs>
+ <param name="child">The element that was added.</param>
+ <summary>Invoked whenever the <see cref="E:Xamarin.Forms.Element.ChildAdded" /> event needs to be emitted. Implement this method to add class handling for this event.</summary>
+ <remarks>This method has no default implementation. You should still call the base implementation in case an intermediate class has implemented this method.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnChildRemoved">
+ <MemberSignature Language="C#" Value="protected virtual void OnChildRemoved (Xamarin.Forms.Element child);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnChildRemoved(class Xamarin.Forms.Element child) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="child" Type="Xamarin.Forms.Element" />
+ </Parameters>
+ <Docs>
+ <param name="child">The element that was removed.</param>
+ <summary>Invoked whenever the <see cref="E:Xamarin.Forms.Element.ChildRemoved" /> event needs to be emitted. Implement this method to add class handling for this event.</summary>
+ <remarks>This method has no default implementation. You should still call the base implementation in case an intermediate class has implemented this method.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnParentSet">
+ <MemberSignature Language="C#" Value="protected virtual void OnParentSet ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnParentSet() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invoked whenever the Parent of an element is set. Implement this method in order to add behavior when the element is added to a parent.</summary>
+ <remarks>Implementors must call the base method.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnPropertyChanged">
+ <MemberSignature Language="C#" Value="protected override void OnPropertyChanged (string propertyName = null);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnPropertyChanged(string propertyName) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String">
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.CallerMemberName</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Parameter>
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the bound property that changed.</param>
+ <summary>Method that is called when a bound property is changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Parent">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Element Parent { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Element Parent" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Element</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the parent element of the element.</summary>
+ <value>The element which should be the parent of this element.</value>
+ <remarks>Most application authors will not need to set the parent element by hand.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ParentView">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.VisualElement ParentView { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.VisualElement ParentView" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use Parent")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.VisualElement</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the element which is the closest ancestor of this element that is a <see cref="T:Xamarin.Forms.VisualElement" />.</summary>
+ <value>The closest ansestor which is a <see cref="T:Xamarin.Forms.VisualElement" />.</value>
+ <remarks>Convenient way of accessing the nearest ancestor of an element which is actually represented on screen visually. If this element is a visual element, its bounds are relative to its ParentView.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RemoveDynamicResource">
+ <MemberSignature Language="C#" Value="public void RemoveDynamicResource (Xamarin.Forms.BindableProperty property);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void RemoveDynamicResource(class Xamarin.Forms.BindableProperty property) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ </Parameters>
+ <Docs>
+ <param name="property">The BindableProperty from which to remove the DynamicResource.</param>
+ <summary>Removes a previously set dynamic resource</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetDynamicResource">
+ <MemberSignature Language="C#" Value="public void SetDynamicResource (Xamarin.Forms.BindableProperty property, string key);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void SetDynamicResource(class Xamarin.Forms.BindableProperty property, string key) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="key" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="property">The BindableProperty.</param>
+ <param name="key">The key of the DynamicResource</param>
+ <summary>Sets the BindableProperty property of this element to be updated via the DynamicResource with the provided key.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="StyleId">
+ <MemberSignature Language="C#" Value="public string StyleId { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string StyleId" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a user defined value to uniquely identify the element.</summary>
+ <value>A string uniquely identifying the element.</value>
+ <remarks>Use the StyleId property to identify individual elements in your application for identification in ui testing and in theme engines.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElement.AddResourcesChangedListener">
+ <MemberSignature Language="C#" Value="void IElement.AddResourcesChangedListener (Action&lt;object,Xamarin.Forms.ResourcesChangedEventArgs&gt; onchanged);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IElement.AddResourcesChangedListener(class System.Action`2&lt;object, class Xamarin.Forms.ResourcesChangedEventArgs&gt; onchanged) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="onchanged" Type="System.Action&lt;System.Object,Xamarin.Forms.ResourcesChangedEventArgs&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="onchanged">To be added.</param>
+ <summary>Internal.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElement.RemoveResourcesChangedListener">
+ <MemberSignature Language="C#" Value="void IElement.RemoveResourcesChangedListener (Action&lt;object,Xamarin.Forms.ResourcesChangedEventArgs&gt; onchanged);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IElement.RemoveResourcesChangedListener(class System.Action`2&lt;object, class Xamarin.Forms.ResourcesChangedEventArgs&gt; onchanged) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="onchanged" Type="System.Action&lt;System.Object,Xamarin.Forms.ResourcesChangedEventArgs&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="onchanged">To be added.</param>
+ <summary>Internal.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElement.ResourceDictionary">
+ <MemberSignature Language="C#" Value="Xamarin.Forms.IResourceDictionary Xamarin.Forms.IElement.ResourceDictionary { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.IResourceDictionary Xamarin.Forms.IElement.ResourceDictionary" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.IResourceDictionary</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>
+ Internal.
+ </summary>
+ <value>
+ <para />
+ </value>
+ <remarks>
+ <para />
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElement.XamlParent">
+ <MemberSignature Language="C#" Value="WeakReference&lt;Xamarin.Forms.Element&gt; Xamarin.Forms.IElement.XamlParent { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.WeakReference`1&lt;class Xamarin.Forms.Element&gt; Xamarin.Forms.IElement.XamlParent" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.WeakReference&lt;Xamarin.Forms.Element&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a weak reference to the parent of this <see cref="T:Xamarin.Forms.Element" /> object.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElementController.EffectControlProvider">
+ <MemberSignature Language="C#" Value="Xamarin.Forms.IEffectControlProvider Xamarin.Forms.IElementController.EffectControlProvider { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.IEffectControlProvider Xamarin.Forms.IElementController.EffectControlProvider" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.IEffectControlProvider</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use only.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElementController.SetValueFromRenderer">
+ <MemberSignature Language="C#" Value="void IElementController.SetValueFromRenderer (Xamarin.Forms.BindableProperty property, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IElementController.SetValueFromRenderer(class Xamarin.Forms.BindableProperty property, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="property">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Sets a value from a renderer without breaking the binding on a bound property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElementController.SetValueFromRenderer">
+ <MemberSignature Language="C#" Value="void IElementController.SetValueFromRenderer (Xamarin.Forms.BindablePropertyKey property, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IElementController.SetValueFromRenderer(class Xamarin.Forms.BindablePropertyKey property, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="property" Type="Xamarin.Forms.BindablePropertyKey" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="property">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Sets a value from a renderer without breaking the binding on a bound property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.INameScope.FindByName">
+ <MemberSignature Language="C#" Value="object INameScope.FindByName (string name);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.INameScope.FindByName(string name) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="name">The identifier of the <see cref="T:Xamarin.Forms.Element" /> being sought.</param>
+ <summary>Finds an object previously registered with <see cref="M:Xamarin.Forms.Element.RegisterName" />.</summary>
+ <returns>The Object previously associated with <paramref name="name" /> by a call to <see cref="M:Xamarin.Forms.Element.RegisterName" />. Raises a <see cref="T:System.InvalidOperationException" /> if <c>this</c> is not in an <see cref="T:Xamarin.Forms.INameScope" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.INameScope.RegisterName">
+ <MemberSignature Language="C#" Value="void INameScope.RegisterName (string name, Lazy&lt;object&gt; scopedElement);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.INameScope.RegisterName(string name, class System.Lazy`1&lt;object&gt; scopedElement) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="scopedElement" Type="System.Lazy&lt;System.Object&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <param name="scopedElement">To be added.</param>
+ <summary>Internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.INameScope.RegisterName">
+ <MemberSignature Language="C#" Value="void INameScope.RegisterName (string name, object scopedElement);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.INameScope.RegisterName(string name, object scopedElement) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="scopedElement" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="name">Identifier to be used with the <paramref name="scopedElement" />.</param>
+ <param name="scopedElement">Object to be associated with the <paramref name="name" />.</param>
+ <summary>Within an <see cref="T:Xamarin.Forms.INameScope" />, creates an association between <paramref name="name" /> and <paramref name="scopedElement" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.INameScope.RegisterName">
+ <MemberSignature Language="C#" Value="void INameScope.RegisterName (string name, object scopedElement, System.Xml.IXmlLineInfo xmlLineInfo);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.INameScope.RegisterName(string name, object scopedElement, class System.Xml.IXmlLineInfo xmlLineInfo) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="scopedElement" Type="System.Object" />
+ <Parameter Name="xmlLineInfo" Type="System.Xml.IXmlLineInfo" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <param name="scopedElement">To be added.</param>
+ <param name="xmlLineInfo">To be added.</param>
+ <summary>Internal.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.INameScope.UnregisterName">
+ <MemberSignature Language="C#" Value="void INameScope.UnregisterName (string name);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.INameScope.UnregisterName(string name) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="name">The identifier to be removed.</param>
+ <summary>Removes <paramref name="name" /> from an <see cref="T:Xamarin.Forms.INameScope" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Internals.INameScope.FindByName">
+ <MemberSignature Language="C#" Value="object INameScope.FindByName (string name);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.Internals.INameScope.FindByName(string name) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <summary>For internal use only.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Internals.INameScope.RegisterName">
+ <MemberSignature Language="C#" Value="void INameScope.RegisterName (string name, object scopedElement);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.Internals.INameScope.RegisterName(string name, object scopedElement) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="scopedElement" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <param name="scopedElement">To be added.</param>
+ <summary>For internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Internals.INameScope.RegisterName">
+ <MemberSignature Language="C#" Value="void INameScope.RegisterName (string name, object scopedElement, System.Xml.IXmlLineInfo xmlLineInfo);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.Internals.INameScope.RegisterName(string name, object scopedElement, class System.Xml.IXmlLineInfo xmlLineInfo) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="scopedElement" Type="System.Object" />
+ <Parameter Name="xmlLineInfo" Type="System.Xml.IXmlLineInfo" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <param name="scopedElement">To be added.</param>
+ <param name="xmlLineInfo">To be added.</param>
+ <summary>For internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Internals.INameScope.UnregisterName">
+ <MemberSignature Language="C#" Value="void INameScope.UnregisterName (string name);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.Internals.INameScope.UnregisterName(string name) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <summary>For internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ElementEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ElementEventArgs.xml
new file mode 100644
index 00000000..9ba903ee
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ElementEventArgs.xml
@@ -0,0 +1,75 @@
+<Type Name="ElementEventArgs" FullName="Xamarin.Forms.ElementEventArgs">
+ <TypeSignature Language="C#" Value="public class ElementEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ElementEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Provides data for events pertaining to a single <see cref="T:Xamarin.Forms.Element" />.</summary>
+ <remarks>
+ </remarks>
+ <altmember cref="E:Xamarin.Forms.Element.ChildAdded" />
+ <altmember cref="E:Xamarin.Forms.Element.ChildRemoved" />
+ <altmember cref="E:Xamarin.Forms.Element.DescendantAdded" />
+ <altmember cref="E:Xamarin.Forms.Element.DescendantRemoved" />
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ElementEventArgs (Xamarin.Forms.Element element);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class Xamarin.Forms.Element element) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="element" Type="Xamarin.Forms.Element" />
+ </Parameters>
+ <Docs>
+ <param name="element">The element relevant to the event.</param>
+ <summary>Constructs and initializes a new instance of the <see cref="T:Xamarin.Forms.ElementEventArgs" /> class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Element">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Element Element { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Element Element" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Element</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the element relevant to the event.</summary>
+ <value>The element relevant to the event.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ElementTemplate.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ElementTemplate.xml
new file mode 100644
index 00000000..c482868c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ElementTemplate.xml
@@ -0,0 +1,55 @@
+<Type Name="ElementTemplate" FullName="Xamarin.Forms.ElementTemplate">
+ <TypeSignature Language="C#" Value="public class ElementTemplate : Xamarin.Forms.Internals.IDataTemplate" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ElementTemplate extends System.Object implements class Xamarin.Forms.Internals.IDataTemplate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Internals.IDataTemplate</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>Base class for <see cref="T:Xamarin.Forms.DataTemplate" /> and <see cref="T:Xamarin.Forms.ControlTemplate" /> classes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="CreateContent">
+ <MemberSignature Language="C#" Value="public object CreateContent ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance object CreateContent() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Used by the XAML infrastructure to load data templates and set up the content of the resulting UI.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Internals.IDataTemplate.LoadTemplate">
+ <MemberSignature Language="C#" Value="Func&lt;object&gt; Xamarin.Forms.Internals.IDataTemplate.LoadTemplate { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Func`1&lt;object&gt; Xamarin.Forms.Internals.IDataTemplate.LoadTemplate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Func&lt;System.Object&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use only.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Entry.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Entry.xml
new file mode 100644
index 00000000..a176db57
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Entry.xml
@@ -0,0 +1,496 @@
+<Type Name="Entry" FullName="Xamarin.Forms.Entry">
+ <TypeSignature Language="C#" Value="public class Entry : Xamarin.Forms.InputView" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Entry extends Xamarin.Forms.InputView" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.InputView</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._EntryRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A control that can edit a single line of text.</summary>
+ <remarks>
+ <para>Entry is a single line text entry. It is best used for collecting small discrete pieces of information, like usernames and passwords.</para>
+ <example>
+ <para>
+ The following example creates a new username and password set of entries.
+ </para>
+ <code lang="C#"><![CDATA[
+View CreateLoginForm ()
+{
+ var usernameEntry = new Entry {Placeholder = "Username"};
+ var passwordEntry = new Entry {
+ Placeholder = "Password",
+ IsPassword = true
+ };
+
+ return new StackLayout {
+ Children = {
+ usernameEntry,
+ passwordEntry
+ }
+ };
+}
+ ]]></code>
+ <para>The FormsGallery sample, which can be found on the <format type="text/html"><a href="http://developer.xamarin.com/samples/tag/Xamarin.Forms/" target="_blank">Sample Applications</a></format> page, has an EntryDemoPage.cs file. This file contains a longer and more complicated example.</para>
+ </example>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.Entry" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>IsPassword</term>
+ <description>
+ <c>true</c> to indicate that the <see cref="T:Xamarin.Forms.Entry" /> is a password field. Otherwise, <c>false</c>.</description>
+ </item>
+ <item>
+ <term>Placeholder</term>
+ <description>The default text that will appear in the control.</description>
+ </item>
+ <item>
+ <term>Text</term>
+ <description>
+ <para>The initial text that will appear in the entry.</para>
+ </description>
+ </item>
+ <item>
+ <term>TextColor</term>
+ <description>
+ <para>A color specification, with or without the prefix, "Color". For example, "Color.Red" and "Red" both specify the color red.</para>
+ </description>
+ </item>
+ </list>
+ <para>
+ <img href="Entry.TripleScreenShot.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Entry ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the Entry class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Completed">
+ <MemberSignature Language="C#" Value="public event EventHandler Completed;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Completed" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs when the user finalizes the text in an entry with the return key.</summary>
+ <remarks>This finalization will usually but not always be accompanied by IsFocused being set to false.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontAttributes">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.FontAttributes FontAttributes { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.FontAttributes FontAttributes" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FontAttributes</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that indicates whether the font for the Entry element text is bold, italic, or neither.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontAttributesProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontAttributesProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontAttributesProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the FontAttributes property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontFamily">
+ <MemberSignature Language="C#" Value="public string FontFamily { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string FontFamily" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the font family for the Entry element text.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontFamilyProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontFamilyProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontFamilyProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the FontFamily property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontSize">
+ <MemberSignature Language="C#" Value="public double FontSize { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 FontSize" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.FontSizeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the size of the font for the Entry element text.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontSizeProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontSizeProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontSizeProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.Entry.FontSize" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HorizontalTextAlignment">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.TextAlignment HorizontalTextAlignment { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.TextAlignment HorizontalTextAlignment" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TextAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the horizontal text alignment.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HorizontalTextAlignmentProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HorizontalTextAlignmentProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HorizontalTextAlignmentProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the HorizontalTextAlignment property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsPassword">
+ <MemberSignature Language="C#" Value="public bool IsPassword { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsPassword" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that indicates if the entry should visually obscure typed text. This is a bindable property.</summary>
+ <value>
+ <see langword="true" /> if the element is a password box; otherwise, <see langword="false" />. Default value is <see langword="false" />.</value>
+ <remarks>Toggling this value does not reset the contents of the entry, therefore it is advisable to be careful about setting IsPassword to false, as it may contain sensitive information.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsPasswordProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsPasswordProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsPasswordProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the IsPassword bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Placeholder">
+ <MemberSignature Language="C#" Value="public string Placeholder { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Placeholder" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the placeholder text shown when the entry <see cref="P:Xamarin.Forms.Entry.Text" /> is null or empty. This is a bindable property.</summary>
+ <value>The placeholder text shown when <see cref="P:Xamarin.Forms.Entry.Text" /> is null or empty. The default value is <see langword="null" />.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PlaceholderColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color PlaceholderColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color PlaceholderColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the color of the placeholder text.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PlaceholderColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty PlaceholderColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty PlaceholderColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.Entry.PlaceholderColor" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PlaceholderProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty PlaceholderProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty PlaceholderProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Placeholder bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Text">
+ <MemberSignature Language="C#" Value="public string Text { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Text" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the text of the entry. This is a bindable property.</summary>
+ <value>A string containing the text of the entry. The default value is <see langword="null" />.</value>
+ <remarks>Setting this property will cause the <see cref="E:Xamarin.Forms.Entry.ValueChanged" /> event to be emitted.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.TextChangedEventArgs&gt; TextChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.TextChangedEventArgs&gt; TextChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.TextChangedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the text in this <see cref="T:Xamarin.Forms.Entry" /> element is changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color TextColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color TextColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the <see cref="T:Xamarin.Forms.Color" /> for the text of the Entry. This is a bindable property.</summary>
+ <value>The <see cref="T:Xamarin.Forms.Color" /> of the text.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TextColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TextColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the TextColor bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TextProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TextProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Text bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/EntryCell.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/EntryCell.xml
new file mode 100644
index 00000000..49a7f662
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/EntryCell.xml
@@ -0,0 +1,474 @@
+<Type Name="EntryCell" FullName="Xamarin.Forms.EntryCell">
+ <TypeSignature Language="C#" Value="public class EntryCell : Xamarin.Forms.Cell" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit EntryCell extends Xamarin.Forms.Cell" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Cell</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.Cell" /> with a label and a single line text entry field.</summary>
+ <remarks>
+ <para>The following example shows a basic use.</para>
+ <example>
+ <code lang="C#"><![CDATA[using System;
+using Xamarin.Forms;
+
+namespace FormsGallery
+{
+ class EntryCellDemoPage : ContentPage
+ {
+ public EntryCellDemoPage()
+ {
+ Label header = new Label
+ {
+ Text = "EntryCell",
+ FontSize = Device.GetNamedSize (NamedSize.Large, typeof(EntryCell)),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ TableView tableView = new TableView
+ {
+ Intent = TableIntent.Form,
+ Root = new TableRoot
+ {
+ new TableSection
+ {
+ new EntryCell
+ {
+ Label = "EntryCell:",
+ Placeholder = "Type Text Here"
+ }
+ }
+ }
+ };
+
+ // Accomodate iPhone status bar.
+ this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
+
+ // Build the page.
+ this.Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ tableView
+ }
+ };
+ }
+ }
+}
+]]></code>
+ </example>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.EntryCell" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Keyboard</term>
+ <description>A <see cref="T:Xamarin.Forms.Keyboard" /> property name that indicates which keyboard to present to the user when editing text.</description>
+ </item>
+ <item>
+ <term>Label</term>
+ <description>
+ <para>The text that is presented next to the entry area in the <see cref="T:Xamarin.Forms.EntryCell" />. </para>
+ </description>
+ </item>
+ <item>
+ <term>LabelColor</term>
+ <description>
+ <para>A color specification, with or without the prefix, "Color". For example, "Color.Red" and "Red" both specify the color red.</para>
+ </description>
+ </item>
+ <item>
+ <term>Placeholder</term>
+ <description>The default text that will appear in the control when it is empty.</description>
+ </item>
+ <item>
+ <term>Text</term>
+ <description>
+ <para>The initial text that will appear in the editor.</para>
+ </description>
+ </item>
+ <item>
+ <term>XAlign</term>
+ <description>
+ <para>
+ <c>Center</c>, <c>End</c>, or <c>Start</c>, to indicate the placement of the text that is entered by the user.</para>
+ </description>
+ </item>
+ </list>
+ <para>
+ <img href="EntryCell.TripleScreenShot.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public EntryCell ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the EntryCell class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Completed">
+ <MemberSignature Language="C#" Value="public event EventHandler Completed;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Completed" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event fired when the user presses 'Done' on the EntryCell's keyboard</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HorizontalTextAlignment">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.TextAlignment HorizontalTextAlignment { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.TextAlignment HorizontalTextAlignment" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TextAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the horizontal alignement of the Text property. This is a bindable property.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HorizontalTextAlignmentProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HorizontalTextAlignmentProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HorizontalTextAlignmentProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the HorizontalTextAlignment bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Keyboard">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Keyboard Keyboard { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Keyboard Keyboard" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Keyboard</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the Keyboard to display while editing the EntryCell. This is a bindable property.</summary>
+ <value>A <see cref="T:Xamarin.Forms.Keyboard" /> representing the keyboard kind. Default is <see cref="P:Xamarin.Forms.Keyboard.Default" />.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="KeyboardProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty KeyboardProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty KeyboardProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Keyboard bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Label">
+ <MemberSignature Language="C#" Value="public string Label { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Label" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the fixed text presented next to the Entry in the EntryCell. This is a bindable property.</summary>
+ <value>A <see cref="T:System.String" />.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LabelColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color LabelColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color LabelColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the Color used for rendering the Label property. This is a bindable property.</summary>
+ <value>Default is Color.Default.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LabelColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty LabelColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty LabelColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the LabelColor bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LabelProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty LabelProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty LabelProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Label bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Placeholder">
+ <MemberSignature Language="C#" Value="public string Placeholder { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Placeholder" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the placeholder text displayed in the Entry when the Text is null or empty. This is a bindable property.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PlaceholderProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty PlaceholderProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty PlaceholderProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Placeholder bindable property,</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Text">
+ <MemberSignature Language="C#" Value="public string Text { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Text" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the content of the Entry of the EntryCell. This is a bindable property.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TextProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TextProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Text bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="XAlign">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.TextAlignment XAlign { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.TextAlignment XAlign" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("XAlign is obsolete. Please use HorizontalTextAlignment instead.")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TextAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the horizontal alignement of the Text property. This is a bindable property.</summary>
+ <value>Default is <see cref="E:Xamarin.Forms.TextAlignment.Start" />.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="XAlignProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty XAlignProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty XAlignProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("XAlignProperty is obsolete. Please use HorizontalTextAlignmentProperty instead.")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the XAlign bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/EventTrigger.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/EventTrigger.xml
new file mode 100644
index 00000000..460d81a0
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/EventTrigger.xml
@@ -0,0 +1,142 @@
+<Type Name="EventTrigger" FullName="Xamarin.Forms.EventTrigger">
+ <TypeSignature Language="C#" Value="public sealed class EventTrigger : Xamarin.Forms.TriggerBase" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit EventTrigger extends Xamarin.Forms.TriggerBase" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TriggerBase</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Actions")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Class that represents a triggering event and a list of <see cref="T:Xamarin.Forms.TriggerAction" /> objects that will be invoked when the event is raised.</summary>
+ <remarks>
+ <para>XAML for Xamarin.Forms supports the following property for the <see cref="T:Xamarin.Forms.EventTrigger" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Event</term>
+ <description>
+ <para>The name of the event to which to respond.</para>
+ </description>
+ </item>
+ <item>
+ <term>Object name</term>
+ <description>
+ <para>The qualified name of a <see cref="T:Xamarin.Forms.TriggerAction`1" /> implementation that has been defined by the application developer. This object is instantiated and its <see cref="M:Xamarin.Forms.TriggerAction`1.Invoke" /> method is called when the triggering event is raised. Attributes on this tag set corresponding proptery values on the <see cref="T:Xamarin.Forms.TriggerAction`1" /> implementation</para> before the <see cref="M:Xamarin.Forms.TriggerAction`1.Invoke" /> method is called.</description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public EventTrigger ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.EventTrigger" /> instance.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Actions">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.TriggerAction&gt; Actions { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.TriggerAction&gt; Actions" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.TriggerAction&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the list of <see cref="T:Xamarin.Forms.TriggerAction" /> objects that will be invoked when the event that is identified by the <see cref="P:Xamarin.Forms.EventTrigger.Event" /> property is raised.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Event">
+ <MemberSignature Language="C#" Value="public string Event { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Event" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the name of the event that will cause the actions that are contained in the <see cref="P:Xamarin.Forms.EventTrigger.Actions" /> to be invoked.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnAttached">
+ <MemberSignature Language="C#" Value="protected override void OnAttached ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnAttached() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Internal.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnDetaching">
+ <MemberSignature Language="C#" Value="protected override void OnDetaching ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnDetaching() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Internal.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ExportEffectAttribute.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ExportEffectAttribute.xml
new file mode 100644
index 00000000..ae6c33f3
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ExportEffectAttribute.xml
@@ -0,0 +1,65 @@
+<Type Name="ExportEffectAttribute" FullName="Xamarin.Forms.ExportEffectAttribute">
+ <TypeSignature Language="C#" Value="public class ExportEffectAttribute : Attribute" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ExportEffectAttribute extends System.Attribute" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Attribute</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.AttributeUsage(System.AttributeTargets.Assembly, AllowMultiple=true, Inherited=false)</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Attribute that identifies a <see cref="T:Xamarin.Forms.Effect" /> with a unique identifer that can be used with <see cref="MXamarin.Forms.Effect.Resolve" /> to locate an effect.</summary>
+ <remarks><para>Developers must supply a name that is unique over the scope of the value that was supplied to <see cref="T:Xamarin.Forms.ResolutionGroupNameAttribute" />. The <see cref="T:Xamarin.Forms.Effect.Resolve" /> method takes a string that is the concatenation of the the resolution group name that was provided to <see cref="T:Xamarin.Forms.ResolutionGroupNameAttribute" />, '<c>.</c>', and the name that was supplied to <see cref="T:Xamarin.Forms.ExportEffectAttribute" />, and returns an effect that will have the type <paramref name="effectType" />.</para>
+ <example><para>For example, with the declarations:</para>
+ <code lang="c#"><![CDATA[
+ [assembly: ResolutionGroupName ("com.YourCompany")]
+ [assembly: ExportEffect (typeof (ShadowEffect), "ShadowEffect")]]]>
+ </code>
+ <para>Then the code below will add the effect to a button:</para>
+ <code lang="c#"><![CDATA[
+ [var button = new Button { Text = "I have a shadow" };
+button.Effects.Add (Effect.Resolve ("com.YourCompany.ShadowEffect"));]]>
+ </code>
+</example></remarks>
+ <altmember cref="T:Xamarin.Forms.ResolutionGroupNameAttribute" />
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ExportEffectAttribute (Type effectType, string uniqueName);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Type effectType, string uniqueName) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="effectType" Type="System.Type" />
+ <Parameter Name="uniqueName" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="effectType">The type of the marked <see cref="T:Xamarin.Forms.Effect" />.</param>
+ <param name="uniqueName">A unique name for the <see cref="T:Xamarin.Forms.Effect" />.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.ExportEffectAttribute" />.</summary>
+ <remarks><para>Developers must supply a <paramref name="uniqueName" /> that is unique over the scope of the value that was supplied to <see cref="T:Xamarin.Forms.ResolutionGroupNameAttribute" />. The <see cref="T:Xamarin.Forms.Effect.Resolve" /> method takes a string that is the concatenation of the the resolution group name that was provided to <see cref="T:Xamarin.Forms.ResolutionGroupNameAttribute" />, '<c>.</c>', and the name that was supplied to <see cref="T:Xamarin.Forms.ExportEffectAttribute" />, and returns an effect that will have the type <paramref name="effectType" />.</para>
+ <example><para>For example, with the declarations:</para>
+ <code lang="c#"><![CDATA[
+ [assembly: ResolutionGroupName ("com.YourCompany")]
+ [assembly: ExportEffect (typeof (ShadowEffect), "ShadowEffect")]]]>
+ </code>
+ <para>Then the code below will add the effect to a button:</para>
+ <code lang="c#"><![CDATA[
+ [var button = new Button { Text = "I have a shadow" };
+button.Effects.Add (Effect.Resolve ("com.YourCompany.ShadowEffect"));]]>
+ </code>
+</example></remarks>
+ <altmember cref="T:Xamarin.Forms.ResolutionGroupNameAttribute" />
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/FileImageSource.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/FileImageSource.xml
new file mode 100644
index 00000000..61fe4dcc
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/FileImageSource.xml
@@ -0,0 +1,187 @@
+<Type Name="FileImageSource" FullName="Xamarin.Forms.FileImageSource">
+ <TypeSignature Language="C#" Value="public sealed class FileImageSource : Xamarin.Forms.ImageSource" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit FileImageSource extends Xamarin.Forms.ImageSource" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.ImageSource</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.FileImageSourceConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>An <see cref="T:Xamarin.Forms.ImageSource" /> that reads an image from a file.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public FileImageSource ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.FileImageSource" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Cancel">
+ <MemberSignature Language="C#" Value="public override System.Threading.Tasks.Task&lt;bool&gt; Cancel ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance class System.Threading.Tasks.Task`1&lt;bool&gt; Cancel() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Request a cancel of the ImageSource loading.</summary>
+ <returns>An awaitable Task.</returns>
+ <remarks>Overriden for FileImageSource. FileImageSource are not cancellable, so this will always returns a completed Task with <see langword="false" /> as Result.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="File">
+ <MemberSignature Language="C#" Value="public string File { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string File" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the file from which this <see cref="T:Xamarin.Forms.FileImageSource" /> will load an image.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FileProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FileProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FileProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.FileImageSource.File" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnPropertyChanged">
+ <MemberSignature Language="C#" Value="protected override void OnPropertyChanged (string propertyName = null);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnPropertyChanged(string propertyName) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">To be added.</param>
+ <summary>Method that is called when the property that is specified by <paramref name="propertyName" /> is changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Implicit">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.FileImageSource op_Implicit (string file);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname class Xamarin.Forms.FileImageSource op_Implicit(string file) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FileImageSource</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="file" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="file">To be added.</param>
+ <summary>Allows implicit casting from a string.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Implicit">
+ <MemberSignature Language="C#" Value="public static string op_Implicit (Xamarin.Forms.FileImageSource file);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname string op_Implicit(class Xamarin.Forms.FileImageSource file) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="file" Type="Xamarin.Forms.FileImageSource" />
+ </Parameters>
+ <Docs>
+ <param name="file">To be added.</param>
+ <summary>Allows implicit casting to a string.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/FileImageSourceConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/FileImageSourceConverter.xml
new file mode 100644
index 00000000..3a1cbffe
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/FileImageSourceConverter.xml
@@ -0,0 +1,97 @@
+<Type Name="FileImageSourceConverter" FullName="Xamarin.Forms.FileImageSourceConverter">
+ <TypeSignature Language="C#" Value="public sealed class FileImageSourceConverter : Xamarin.Forms.TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit FileImageSourceConverter extends Xamarin.Forms.TypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TypeConverter" /> that converts to <see cref="P:Xamarin.Forms.FileImageSource" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public FileImageSourceConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="P:Xamarin.Forms.FileImageSource" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>Returns <see langword="true" /> if the source type can be converted with this type converter.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Converts <paramref name="value" /> with the specified <paramref name="culture" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Creates a file image source given a path to an image.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/FocusEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/FocusEventArgs.xml
new file mode 100644
index 00000000..802148e0
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/FocusEventArgs.xml
@@ -0,0 +1,97 @@
+<Type Name="FocusEventArgs" FullName="Xamarin.Forms.FocusEventArgs">
+ <TypeSignature Language="C#" Value="public class FocusEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit FocusEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Event args for <see cref="T:Xamarin.Forms.VisualElement" />'s <see cref="E:Xamarin.Forms.VisualElement.Focused" /> and <see cref="T:Xamarin.Forms.VisualElement.Unfocused" /> events.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public FocusEventArgs (Xamarin.Forms.VisualElement visualElement, bool isFocused);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class Xamarin.Forms.VisualElement visualElement, bool isFocused) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="visualElement" Type="Xamarin.Forms.VisualElement" />
+ <Parameter Name="isFocused" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="visualElement">The <see cref="T:Xamarin.Foms.VisualElement" /> who's focused was changed.</param>
+ <param name="isFocused">Whether or not the <paramref name="visualElement" /> was focused.</param>
+ <summary>Constructs and initializes a new instance of the <see cref="T:Xamarin.Forms.FocusEventArgs" /> class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsFocused">
+ <MemberSignature Language="C#" Value="public bool IsFocused { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsFocused" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets whether or not the <see cref="P:Xamarin.Forms.FocusEventArgs.View" /> was focused.</summary>
+ <value>
+ <see langword="true" /> if the view was focused, <see langword="false" /> otherwise.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="VisualElement">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.VisualElement VisualElement { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.VisualElement VisualElement" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.VisualElement</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the <see cref="T:Xamarin.Foms.VisualElement" /> who's focused was changed.</summary>
+ <value>The <see cref="T:Xamarin.Foms.VisualElement" /> who's focused was changed.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Font.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Font.xml
new file mode 100644
index 00000000..cd5eb227
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Font.xml
@@ -0,0 +1,591 @@
+<Type Name="Font" FullName="Xamarin.Forms.Font">
+ <TypeSignature Language="C#" Value="public struct Font" />
+ <TypeSignature Language="ILAsm" Value=".class public sequential ansi sealed beforefieldinit Font extends System.ValueType" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.ValueType</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.FontTypeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>The font used to display text.</summary>
+ <remarks>The available fonts, and the matching between <see cref="T:Xamarin.Forms.Font" /> and real displayed fonts is device-dependent.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="BoldSystemFontOfSize">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Font BoldSystemFontOfSize (double size);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Font BoldSystemFontOfSize(float64 size) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("BoldSystemFontOfSize is obsolete, please use SystemFontOfSize (double, FontAttributes)")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Font</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="size" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="size">The desired font size.</param>
+ <summary>Returns a font instance that represents the default bold font, in the requested size, for the device.</summary>
+ <returns>The requested bold <see cref="T:Xamarin.Forms.Font" />.</returns>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BoldSystemFontOfSize">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Font BoldSystemFontOfSize (Xamarin.Forms.NamedSize size);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Font BoldSystemFontOfSize(valuetype Xamarin.Forms.NamedSize size) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("BoldSystemFontOfSize is obsolete, please use SystemFontOfSize (NamedSize, FontAttributes)")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Font</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="size" Type="Xamarin.Forms.NamedSize" />
+ </Parameters>
+ <Docs>
+ <param name="size">The desired font <see cref="T:Xamarin.Forms.NamedSize" />.</param>
+ <summary>Returns an usable font instance representing the default bold font, in the requested NamedSize, for the device.</summary>
+ <returns>The requested bold <see cref="T:Xamarin.Forms.Font" />.</returns>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Default">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Font Default { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property valuetype Xamarin.Forms.Font Default" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Font</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the default font for the device.</summary>
+ <value>The default font for the device.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Equals">
+ <MemberSignature Language="C#" Value="public override bool Equals (object obj);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool Equals(object obj) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="obj" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="obj">The <see cref="T:System.Object" /> value to compare this font to.</param>
+ <summary>Determine if the provided <see cref="T:System.Object" /> is equivalent to the current Font.</summary>
+ <returns>
+ <see langword="true" /> if the provided object is an equivalent font. <see langword="false" /> otherwise.</returns>
+ <remarks>Overriden.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontAttributes">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.FontAttributes FontAttributes { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.FontAttributes FontAttributes" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FontAttributes</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that indicates whether the font is bold, italic, or neither.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontFamily">
+ <MemberSignature Language="C#" Value="public string FontFamily { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string FontFamily" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the font family to which this font belongs.</summary>
+ <value>The font family to which this <see cref="T:Xamarin.Forms.Font" /> structure belongs.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontSize">
+ <MemberSignature Language="C#" Value="public double FontSize { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 FontSize" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the size of the font.</summary>
+ <value>A <see langword="double" /> that indicates the size of the font.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetHashCode">
+ <MemberSignature Language="C#" Value="public override int GetHashCode ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance int32 GetHashCode() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Get the Hashcode for this <see cref="T:System.Object" />.</summary>
+ <returns>A signed 32-bit hash code.</returns>
+ <remarks>Overriden.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsDefault">
+ <MemberSignature Language="C#" Value="public bool IsDefault { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsDefault" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that tells whether this font has no attributes, belongs to the default family, and has no attributes set.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="NamedSize">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.NamedSize NamedSize { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.NamedSize NamedSize" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.NamedSize</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the named font size, such as "Large" or "Small".</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OfSize">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Font OfSize (string name, double size);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Font OfSize(string name, float64 size) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Font</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="size" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="name">The name of the targeted system font.</param>
+ <param name="size">The desired font size.</param>
+ <summary>Returns a <see cref="T:Xamarin.Forms.Font" /> structure with the requested font and size.</summary>
+ <returns>A <see cref="T:Xamarin.Forms.Font" /> instance.</returns>
+ <remarks>Font availability is platform- and device-dependent.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OfSize">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Font OfSize (string name, Xamarin.Forms.NamedSize size);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Font OfSize(string name, valuetype Xamarin.Forms.NamedSize size) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Font</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="size" Type="Xamarin.Forms.NamedSize" />
+ </Parameters>
+ <Docs>
+ <param name="name">The name of the targeted system font.</param>
+ <param name="size">The desired font <see cref="T:Xamarin.Forms.NamedSize" />.</param>
+ <summary>Returns an usable <see cref="T:Xamarin.Forms.Font" />, with the requested font and NamedSize.</summary>
+ <returns>A Font instance.</returns>
+ <remarks>Font availability is platform and device dependent.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Equality">
+ <MemberSignature Language="C#" Value="public static bool op_Equality (Xamarin.Forms.Font left, Xamarin.Forms.Font right);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Equality(valuetype Xamarin.Forms.Font left, valuetype Xamarin.Forms.Font right) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="left" Type="Xamarin.Forms.Font" />
+ <Parameter Name="right" Type="Xamarin.Forms.Font" />
+ </Parameters>
+ <Docs>
+ <param name="left">To be added.</param>
+ <param name="right">To be added.</param>
+ <summary>Returns <see langword="true" /> if <paramref name="left" /> represents the same font that <paramref name="right" /> represents. Otherwise, <see langword="false" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Inequality">
+ <MemberSignature Language="C#" Value="public static bool op_Inequality (Xamarin.Forms.Font left, Xamarin.Forms.Font right);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Inequality(valuetype Xamarin.Forms.Font left, valuetype Xamarin.Forms.Font right) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="left" Type="Xamarin.Forms.Font" />
+ <Parameter Name="right" Type="Xamarin.Forms.Font" />
+ </Parameters>
+ <Docs>
+ <param name="left">To be added.</param>
+ <param name="right">To be added.</param>
+ <summary>Returns <see langword="true" /> if <paramref name="left" /> does not represent the same font that <paramref name="right" /> represents. Otherwise, <see langword="false" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SystemFontOfSize">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Font SystemFontOfSize (double size);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Font SystemFontOfSize(float64 size) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Font</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="size" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="size">The desired font size.</param>
+ <summary>Returns an usable font instance representing the default font, in the requested size, for the device and platform.</summary>
+ <returns>The requested <see cref="T:Xamarin.Forms.Font" />.</returns>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SystemFontOfSize">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Font SystemFontOfSize (Xamarin.Forms.NamedSize size);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Font SystemFontOfSize(valuetype Xamarin.Forms.NamedSize size) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Font</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="size" Type="Xamarin.Forms.NamedSize" />
+ </Parameters>
+ <Docs>
+ <param name="size">The desired font <see cref="T:Xamarin.Forms.NamedSize" />.</param>
+ <summary>Returns an usable font instance representing the default font, in the requested size, for the device and platform.</summary>
+ <returns>The requested bold <see cref="T:Xamarin.Forms.Font" />.</returns>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SystemFontOfSize">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Font SystemFontOfSize (double size, Xamarin.Forms.FontAttributes attributes);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Font SystemFontOfSize(float64 size, valuetype Xamarin.Forms.FontAttributes attributes) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Font</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="size" Type="System.Double" />
+ <Parameter Name="attributes" Type="Xamarin.Forms.FontAttributes" />
+ </Parameters>
+ <Docs>
+ <param name="size">The requested font size.</param>
+ <param name="attributes">Whether the font is bold, italic, or neither.</param>
+ <summary>Returns a font structure with the specified size and attributes.</summary>
+ <returns>A <see cref="T:Xamarin.Forms.Font" /> structure with the specified <paramref name="attributes" /> and <paramref name="size" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SystemFontOfSize">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Font SystemFontOfSize (Xamarin.Forms.NamedSize size, Xamarin.Forms.FontAttributes attributes);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Font SystemFontOfSize(valuetype Xamarin.Forms.NamedSize size, valuetype Xamarin.Forms.FontAttributes attributes) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Font</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="size" Type="Xamarin.Forms.NamedSize" />
+ <Parameter Name="attributes" Type="Xamarin.Forms.FontAttributes" />
+ </Parameters>
+ <Docs>
+ <param name="size">The requested named font size.</param>
+ <param name="attributes">Whether the font is bold, italic, or neither.</param>
+ <summary>Returns a font structure with the specified size and attributes.</summary>
+ <returns>A <see cref="T:Xamarin.Forms.Font" /> structure with the specified <paramref name="attributes" /> and <paramref name="size" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ToString">
+ <MemberSignature Language="C#" Value="public override string ToString ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance string ToString() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns a string representation of this font structure.</summary>
+ <returns>A string representation of this <see cref="T:Xamarin.Forms.Font" /> structure.</returns>
+ <remarks>The <see cref="M:Xamarin.Forms.Font.ToString" /> method returns a string that contains a labeled, comma-separated list of the <see cref="P:Xamarin.Forms.Font.FontFamily" />, <see cref="P:Xamarin.Forms.Font.FontSize" />, <see cref="P:Xamarin.Forms.Font.NamedSize" /> , and <see cref="P:Xamarin.Forms.Font.FontAttributes" /> properties.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="UseNamedSize">
+ <MemberSignature Language="C#" Value="public bool UseNamedSize { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool UseNamedSize" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that indicates whether the target operating system should use size that is specified by the <see cref="T:Xamarin.Forms.Font.NamedSize" /> property.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="WithAttributes">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Font WithAttributes (Xamarin.Forms.FontAttributes fontAttributes);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Font WithAttributes(valuetype Xamarin.Forms.FontAttributes fontAttributes) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Font</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="fontAttributes" Type="Xamarin.Forms.FontAttributes" />
+ </Parameters>
+ <Docs>
+ <param name="fontAttributes">Whether the font is italic, bold, or neither.</param>
+ <summary>Returns a new font structure with the specified attributes.</summary>
+ <returns>A new <see cref="T:Xamarin.Forms.Font" /> structure with the attributes that were specified with <paramref name="fontAttributes" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="WithSize">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Font WithSize (double size);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Font WithSize(float64 size) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Font</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="size" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="size">The requested font size.</param>
+ <summary>Returns a new font structure with the size that was specified with <paramref name="size" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="WithSize">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Font WithSize (Xamarin.Forms.NamedSize size);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Font WithSize(valuetype Xamarin.Forms.NamedSize size) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Font</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="size" Type="Xamarin.Forms.NamedSize" />
+ </Parameters>
+ <Docs>
+ <param name="size">The requested named font size.</param>
+ <summary>A new <see cref="T:Xamarin.Forms.Font" /> structure with the size that was specified with <paramref name="size" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/FontAttributes.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/FontAttributes.xml
new file mode 100644
index 00000000..c805482f
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/FontAttributes.xml
@@ -0,0 +1,80 @@
+<Type Name="FontAttributes" FullName="Xamarin.Forms.FontAttributes">
+ <TypeSignature Language="C#" Value="public enum FontAttributes" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed FontAttributes extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Flags</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Enumerates values that describe font styles.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Bold">
+ <MemberSignature Language="C#" Value="Bold" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.FontAttributes Bold = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FontAttributes</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The font is bold.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Italic">
+ <MemberSignature Language="C#" Value="Italic" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.FontAttributes Italic = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FontAttributes</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The font is italic.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="None">
+ <MemberSignature Language="C#" Value="None" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.FontAttributes None = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FontAttributes</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The font is unmodified.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/FontSizeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/FontSizeConverter.xml
new file mode 100644
index 00000000..a7822caa
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/FontSizeConverter.xml
@@ -0,0 +1,162 @@
+<Type Name="FontSizeConverter" FullName="Xamarin.Forms.FontSizeConverter">
+ <TypeSignature Language="C#" Value="public class FontSizeConverter : Xamarin.Forms.TypeConverter, Xamarin.Forms.IExtendedTypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit FontSizeConverter extends Xamarin.Forms.TypeConverter implements class Xamarin.Forms.IExtendedTypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IExtendedTypeConverter</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>Converts a string into a font size.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public FontSizeConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new <see cref="T:Xamarin.Forms.FontSizeConverter" /> object.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>Returns a value that indicates if the source type can be converted to a font size.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Converts an object into a font size.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Converts a string representation of a font size into a font size.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IExtendedTypeConverter.ConvertFrom">
+ <MemberSignature Language="C#" Value="object IExtendedTypeConverter.ConvertFrom (System.Globalization.CultureInfo culture, object value, IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.IExtendedTypeConverter.ConvertFrom(class System.Globalization.CultureInfo culture, object value, class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("use ConvertFromInvariantString (string, IServiceProvider)")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use only.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IExtendedTypeConverter.ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="object IExtendedTypeConverter.ConvertFromInvariantString (string value, IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.IExtendedTypeConverter.ConvertFromInvariantString(string value, class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use only.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/FontTypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/FontTypeConverter.xml
new file mode 100644
index 00000000..cd35ab75
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/FontTypeConverter.xml
@@ -0,0 +1,117 @@
+<Type Name="FontTypeConverter" FullName="Xamarin.Forms.FontTypeConverter">
+ <TypeSignature Language="C#" Value="public sealed class FontTypeConverter : Xamarin.Forms.TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit FontTypeConverter extends Xamarin.Forms.TypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TypeConverter" /> that converts from strings to <see cref="T:Xamarin.Forms.Core.Font" />.</summary>
+ <remarks>String should be formatted as "[name],[attributes],[size]" there may be multiple attributes, e.g. "Georgia, Bold, Italic, 42"</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public FontTypeConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.FontTypeConverter" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>Returns a Boolean value that indicates whether this <see cref="T:Xamarin.Forms.FontTypeConverter" /> can convert the <paramref name="sourceType" /> to a <see cref="T:Xamarin.Forms.Core.Font" /> instance.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Converts <paramref name="value" /> into a <see cref="T:Xamarin.Forms.Core.Font" /> by using the specified <paramref name="culture" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Converts <paramref name="value" /> into a <see cref="T:Xamarin.Forms.Core.Font" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/FormattedString.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/FormattedString.xml
new file mode 100644
index 00000000..fb7fda2e
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/FormattedString.xml
@@ -0,0 +1,157 @@
+<Type Name="FormattedString" FullName="Xamarin.Forms.FormattedString">
+ <TypeSignature Language="C#" Value="public class FormattedString : System.ComponentModel.INotifyPropertyChanged" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit FormattedString extends System.Object implements class System.ComponentModel.INotifyPropertyChanged" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.ComponentModel.INotifyPropertyChanged</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Spans")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Represents a text with attributes applied to some parts.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public FormattedString ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the FormattedString class.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Explicit">
+ <MemberSignature Language="C#" Value="public static string op_Explicit (Xamarin.Forms.FormattedString formatted);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname string op_Explicit(class Xamarin.Forms.FormattedString formatted) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="formatted" Type="Xamarin.Forms.FormattedString" />
+ </Parameters>
+ <Docs>
+ <param name="formatted">To be added.</param>
+ <summary>Cast the FormattedString to a string, stripping all the attributes.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Implicit">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.FormattedString op_Implicit (string text);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname class Xamarin.Forms.FormattedString op_Implicit(string text) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FormattedString</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="text" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="text">To be added.</param>
+ <summary>Cast a string to a FromattedString that contains a single span with no attribute set.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PropertyChanged">
+ <MemberSignature Language="C#" Value="public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.ComponentModel.PropertyChangedEventHandler PropertyChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.ComponentModel.PropertyChangedEventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when a bound property is changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Spans">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.Span&gt; Spans { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Span&gt; Spans" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.Span&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the collection of spans.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ToString">
+ <MemberSignature Language="C#" Value="public override string ToString ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance string ToString() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns the text of the formatted string as an unformatted string.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Frame.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Frame.xml
new file mode 100644
index 00000000..6a199ce0
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Frame.xml
@@ -0,0 +1,181 @@
+<Type Name="Frame" FullName="Xamarin.Forms.Frame">
+ <TypeSignature Language="C#" Value="public class Frame : Xamarin.Forms.ContentView" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Frame extends Xamarin.Forms.ContentView" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.ContentView</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Content")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._FrameRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>An element containing a single child, with some framing options.</summary>
+ <remarks>
+ <para>Frame have a default <see cref="P:Xamarin.Forms.Layout.Padding" /> of 20.</para>
+ <para>
+ The following example shows how to construct a new Frame with an Outline color.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+MainPage = new ContentPage () {
+ Content = new Frame {
+ Content = new Label { Text = "I'm Framous!" },
+ OutlineColor = Color.Silver,
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ HorizontalOptions = LayoutOptions.Center
+ }
+};
+ ]]></code>
+ </example>
+ <para>
+ <img href="Frame.TripleScreenShot.png" />
+ </para>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.Frame" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>HasShadow</term>
+ <description>
+ <para>
+ <c>true</c> or <c>false</c>, to indicate whether to show a shadow effect where the platform supports it.</para>
+ </description>
+ </item>
+ <item>
+ <term>OutlineColor</term>
+ <description>
+ <para>A color specification, with or without the prefix, "Color". For example, "Color.Red" and "Red" both specify the color red.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Frame ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the Frame class.</summary>
+ <remarks>A Frame has a default <see cref="P:Xamarin.Forms.Layout.Padding" /> of 20.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasShadow">
+ <MemberSignature Language="C#" Value="public bool HasShadow { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool HasShadow" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a flag indicating if the Frame has a shadow displayed. This is a bindable property.</summary>
+ <value>A <see cref="T:System.Boolean" /> indicating whether or not the Frame has a shadow. Default is <see langword="true" />.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasShadowProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HasShadowProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HasShadowProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the HasShadow bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OutlineColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color OutlineColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color OutlineColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the color of the border of the Frame. This is a bindable property.</summary>
+ <value>A <see cref="T:Xamarin.Forms.Color" /> representing the border Color. Default is <see cref="P:Xamarin.Forms.Color.Default" />.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OutlineColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty OutlineColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty OutlineColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the OutlineColor bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/GestureRecognizer.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/GestureRecognizer.xml
new file mode 100644
index 00000000..3fe9556e
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/GestureRecognizer.xml
@@ -0,0 +1,69 @@
+<Type Name="GestureRecognizer" FullName="Xamarin.Forms.GestureRecognizer">
+ <TypeSignature Language="C#" Value="public class GestureRecognizer : Xamarin.Forms.Element, System.ComponentModel.INotifyPropertyChanged, Xamarin.Forms.IGestureRecognizer" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit GestureRecognizer extends Xamarin.Forms.Element implements class System.ComponentModel.INotifyPropertyChanged, class Xamarin.Forms.IGestureRecognizer" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Element</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.ComponentModel.INotifyPropertyChanged</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IGestureRecognizer</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>The base class for all gesture recognizers.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Parent">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Element Parent { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Element Parent" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Element</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The parent element of the gesture recognizer.</summary>
+ <value>An element from which the binding context will be inherited.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElement.XamlParent">
+ <MemberSignature Language="C#" Value="WeakReference&lt;Xamarin.Forms.Element&gt; Xamarin.Forms.IElement.XamlParent { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.WeakReference`1&lt;class Xamarin.Forms.Element&gt; Xamarin.Forms.IElement.XamlParent" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.WeakReference&lt;Xamarin.Forms.Element&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a weak reference to the parent of this <see cref="T:Xamarin.Forms.GestureRecognizer" /> object.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/GestureState.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/GestureState.xml
new file mode 100644
index 00000000..37fe72f4
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/GestureState.xml
@@ -0,0 +1,143 @@
+<Type Name="GestureState" FullName="Xamarin.Forms.GestureState">
+ <TypeSignature Language="C#" Value="public enum GestureState" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed GestureState extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumeration specifying the various states of a gesture.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Began">
+ <MemberSignature Language="C#" Value="Began" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.GestureState Began = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GestureState</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The gesture has begun and has not ended, failed, or been cancelled.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Cancelled">
+ <MemberSignature Language="C#" Value="Cancelled" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.GestureState Cancelled = int32(4)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GestureState</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The gesture was cancelled.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Ended">
+ <MemberSignature Language="C#" Value="Ended" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.GestureState Ended = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GestureState</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The gesture has ended.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Failed">
+ <MemberSignature Language="C#" Value="Failed" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.GestureState Failed = int32(3)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GestureState</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The gesture was not recognized.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Possible">
+ <MemberSignature Language="C#" Value="Possible" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.GestureState Possible = int32(5)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GestureState</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The gesture is in progress and may still become recognizable.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Update">
+ <MemberSignature Language="C#" Value="Update" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.GestureState Update = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GestureState</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The gesture state is being updated.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/GestureStatus.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/GestureStatus.xml
new file mode 100644
index 00000000..17eaa3fd
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/GestureStatus.xml
@@ -0,0 +1,78 @@
+<Type Name="GestureStatus" FullName="Xamarin.Forms.GestureStatus">
+ <TypeSignature Language="C#" Value="public enum GestureStatus" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed GestureStatus extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumerates possible gesture states.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Canceled">
+ <MemberSignature Language="C#" Value="Canceled" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.GestureStatus Canceled = int32(3)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GestureStatus</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The gesture was canceled.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Completed">
+ <MemberSignature Language="C#" Value="Completed" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.GestureStatus Completed = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GestureStatus</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The gesture completed.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Running">
+ <MemberSignature Language="C#" Value="Running" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.GestureStatus Running = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GestureStatus</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The gesture is still being recognized.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Started">
+ <MemberSignature Language="C#" Value="Started" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.GestureStatus Started = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GestureStatus</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The gesture started.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Grid+IGridList`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Grid+IGridList`1.xml
new file mode 100644
index 00000000..40b445f2
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Grid+IGridList`1.xml
@@ -0,0 +1,204 @@
+<Type Name="Grid+IGridList&lt;T&gt;" FullName="Xamarin.Forms.Grid+IGridList&lt;T&gt;">
+ <TypeSignature Language="C#" Value="public interface Grid.IGridList&lt;T&gt; : System.Collections.Generic.ICollection&lt;T&gt;, System.Collections.Generic.IEnumerable&lt;T&gt;, System.Collections.Generic.IList&lt;T&gt; where T : View" />
+ <TypeSignature Language="ILAsm" Value=".class nested public interface auto ansi abstract Grid/IGridList`1&lt;(class Xamarin.Forms.View) T&gt; implements class System.Collections.Generic.ICollection`1&lt;!T&gt;, class System.Collections.Generic.IEnumerable`1&lt;!T&gt;, class System.Collections.Generic.IList`1&lt;!T&gt;, class System.Collections.IEnumerable" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="T">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.ICollection&lt;T&gt;</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.IEnumerable&lt;T&gt;</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.IList&lt;T&gt;</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <typeparam name="T">The type of elements in the grid.</typeparam>
+ <summary>List interface with overloads for adding elements to a grid.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (Xamarin.Forms.View view, int left, int top);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Add(class Xamarin.Forms.View view, int32 left, int32 top) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.View" />
+ <Parameter Name="left" Type="System.Int32" />
+ <Parameter Name="top" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="view">The view to add.</param>
+ <param name="left">The column to add the view to.</param>
+ <param name="top">The row to add the view to.</param>
+ <summary>Adds a view to the List at the specified location with a RowSpan and HeightSpan of 1.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (Xamarin.Forms.View view, int left, int right, int top, int bottom);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Add(class Xamarin.Forms.View view, int32 left, int32 right, int32 top, int32 bottom) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.View" />
+ <Parameter Name="left" Type="System.Int32" />
+ <Parameter Name="right" Type="System.Int32" />
+ <Parameter Name="top" Type="System.Int32" />
+ <Parameter Name="bottom" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="view">The view to add.</param>
+ <param name="left">The left edge of the column span. Must be greater than 0.</param>
+ <param name="right">The right edge of the column span. Must be greater than left.</param>
+ <param name="top">The top edge of the row span. Must be greater than 0.</param>
+ <param name="bottom">The bottom edge of the row span. Must be greater than top.</param>
+ <summary>Adds a view to the List at the specified row and column spans.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AddHorizontal">
+ <MemberSignature Language="C#" Value="public void AddHorizontal (System.Collections.Generic.IEnumerable&lt;Xamarin.Forms.View&gt; views);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void AddHorizontal(class System.Collections.Generic.IEnumerable`1&lt;class Xamarin.Forms.View&gt; views) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="views" Type="System.Collections.Generic.IEnumerable&lt;Xamarin.Forms.View&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="views">The views to add.</param>
+ <summary>Add a collection views to the List such that they are horizontally stacked to the right of the current contents of the Grid.</summary>
+ <remarks>The final span of each view is defined to be the height of the grid at the add time, and one column wide at the end of the current arrangement.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AddHorizontal">
+ <MemberSignature Language="C#" Value="public void AddHorizontal (Xamarin.Forms.View view);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void AddHorizontal(class Xamarin.Forms.View view) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.View" />
+ </Parameters>
+ <Docs>
+ <param name="view">The view to add.</param>
+ <summary>Add a view to the List such that it is horizontally stacked to the right of the current contents of the Grid.</summary>
+ <remarks>The final span of the view is defined to be the height of the grid at the add time, and one column wide at the end of the current arrangement.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AddVertical">
+ <MemberSignature Language="C#" Value="public void AddVertical (System.Collections.Generic.IEnumerable&lt;Xamarin.Forms.View&gt; views);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void AddVertical(class System.Collections.Generic.IEnumerable`1&lt;class Xamarin.Forms.View&gt; views) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="views" Type="System.Collections.Generic.IEnumerable&lt;Xamarin.Forms.View&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="views">The views to add.</param>
+ <summary>Add a collection views to the List such that they are vertically stacked below the current contents of the Grid.</summary>
+ <remarks>The final span of each view is defined to be the width of the grid at the add time, and one row tall at the end of the current arrangement.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AddVertical">
+ <MemberSignature Language="C#" Value="public void AddVertical (Xamarin.Forms.View view);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void AddVertical(class Xamarin.Forms.View view) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.View" />
+ </Parameters>
+ <Docs>
+ <param name="view">The view to add.</param>
+ <summary>Add a view to the List such that it is vertically stacked below the current contents of the Grid.</summary>
+ <remarks>The final span of the view is defined to be the width of the grid at the add time, and one row tall at the end of the current arrangement.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Grid.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Grid.xml
new file mode 100644
index 00000000..b4c12eed
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Grid.xml
@@ -0,0 +1,1002 @@
+<Type Name="Grid" FullName="Xamarin.Forms.Grid">
+ <TypeSignature Language="C#" Value="public class Grid : Xamarin.Forms.Layout&lt;Xamarin.Forms.View&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Grid extends Xamarin.Forms.Layout`1&lt;class Xamarin.Forms.View&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Layout&lt;Xamarin.Forms.View&gt;</BaseTypeName>
+ <BaseTypeArguments>
+ <BaseTypeArgument TypeParamName="T">Xamarin.Forms.View</BaseTypeArgument>
+ </BaseTypeArguments>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A layout that arranges views in rows and columns.</summary>
+ <remarks>
+ <example>
+ <para>The following example shows a basic use:</para>
+ <code lang="C#"><![CDATA[
+using System;
+using Xamarin.Forms;
+
+namespace FormsGallery
+{
+ class GridDemoPage : ContentPage
+ {
+ public GridDemoPage()
+ {
+ Grid grid = new Grid
+ {
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ RowDefinitions =
+ {
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
+ new RowDefinition { Height = new GridLength(100, GridUnitType.Absolute) }
+ },
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = GridLength.Auto },
+ new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength(100, GridUnitType.Absolute) }
+ }
+ };
+
+ grid.Children.Add(new Label
+ {
+ Text = "Grid",
+ FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
+ HorizontalOptions = LayoutOptions.Center
+ }, 0, 3, 0, 1);
+
+ grid.Children.Add(new Label
+ {
+ Text = "Autosized cell",
+ TextColor = Color.White,
+ BackgroundColor = Color.Blue
+ }, 0, 1);
+
+ grid.Children.Add(new BoxView
+ {
+ Color = Color.Silver,
+ HeightRequest = 0
+ }, 1, 1);
+
+ grid.Children.Add(new BoxView
+ {
+ Color = Color.Teal
+ }, 0, 2);
+
+ grid.Children.Add(new Label
+ {
+ Text = "Leftover space",
+ TextColor = Color.Purple,
+ BackgroundColor = Color.Aqua,
+ HorizontalTextAlignment = TextAlignment.Center,
+ VerticalTextAlignment = TextAlignment.Center,
+ }, 1, 2);
+
+ grid.Children.Add(new Label
+ {
+ Text = "Span two rows (or more if you want)",
+ TextColor = Color.Yellow,
+ BackgroundColor = Color.Navy,
+ HorizontalTextAlignment = TextAlignment.Center,
+ VerticalTextAlignment = TextAlignment.Center
+ }, 2, 3, 1, 3);
+
+ grid.Children.Add(new Label
+ {
+ Text = "Span 2 columns",
+ TextColor = Color.Blue,
+ BackgroundColor = Color.Yellow,
+ HorizontalTextAlignment = TextAlignment.Center,
+ VerticalTextAlignment = TextAlignment.Center
+ }, 0, 2, 3, 4);
+
+ grid.Children.Add(new Label
+ {
+ Text = "Fixed 100x100",
+ TextColor = Color.Aqua,
+ BackgroundColor = Color.Red,
+ HorizontalTextAlignment = TextAlignment.Center,
+ VerticalTextAlignment = TextAlignment.Center
+ }, 2, 3);
+
+ // Accomodate iPhone status bar.
+ this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
+
+ // Build the page.
+ this.Content = grid;
+ }
+ }
+}
+]]></code>
+ </example>
+ <para>The following shows Grids on the various platforms:</para>
+ <para>
+ <img href="Grid.TripleScreenShot.png" />
+ </para>
+ <para>It is convenient for the <see cref="T:Xamarin.Forms.Grid" /> layout class arranges to store row and column indices of each of its child elements. Additionally, when a <see cref="T:Xamarin.Forms.View" /> element is laid out with a grid, application developers can access and change the child's position and span from the child itself by using the <see cref="M:Xamarin.Forms.Get(BindableObject)" />, <see cref="M:Xamarin.Forms..Grid.GetRow(BindableObject)" />, <see cref="M:Xamarin.Forms.Grid.SetRow(BindableObject)" />, <see cref="M:Xamarin.Forms.Grid.GetRowSpan(BindableObject)" />, <see cref="M:Xamarin.Forms.Grid.SetRowSpan(BindableObject)" /> static methods, and the equivalent static methods for columns and column spans.</para>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.Grid" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Children</term>
+ <description>
+ <para>Nested visual elements that are displayed in the Grid.</para>
+ </description>
+ </item>
+ <item>
+ <term>ColumnDefinitions</term>
+ <description>
+ <para>A list of <c>ColumnDefinition</c> specifications. See <see cref="T:Xamarin.Forms.ColumnDefinition" />.</para>
+ </description>
+ </item>
+ <item>
+ <term>ColumnSpacing</term>
+ <description>An integer.<para></para></description>
+ </item>
+ <item>
+ <term>RowDefinitions</term>
+ <description>
+ <para>A list of <c>RowDefinition</c> specifications. See <see cref="T:Xamarin.Forms.RowDefinition" />.</para>
+ </description>
+ </item>
+ <item>
+ <term>RowSpacing</term>
+ <description>
+ <para>An integer.</para>
+ </description>
+ </item>
+ </list>
+ <para>XAML for Xamarin.Forms supports the following attached properties for the <see cref="T:Xamarin.Forms.Grid" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Attached Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Column</term>
+ <description>
+ <para>An integer that represents the Column in which the item will appear.</para>
+ </description>
+ </item>
+ <item>
+ <term>ColumnSpan</term>
+ <description>An integer that represents the number of Columns that the item will span.<para></para></description>
+ </item>
+ <item>
+ <term>Row</term>
+ <description>
+ <para>An integer that represents the row in which the item will appear.</para>
+ </description>
+ </item>
+ <item>
+ <term>RowSpan</term>
+ <description>
+ <para>An integer that represents the number of rows that the item will span.</para>
+ </description>
+ </item>
+ </list>
+ <para>The documentation for the following <see cref="T:Xamarin.Forms.Grid" /> member methods contains XAML syntax examples:
+<list type="bullet"><item><term><see cref="M:Xamarin.Forms.Grid.SetRow" /></term></item><item><term><see cref="M:Xamarin.Forms.Grid.SetRowSpan" /></term></item><item><term><see cref="M:Xamarin.Forms.Grid.SetColumn" /></term></item><item><term><see cref="M:Xamarin.Forms.Grid.SetColumnSpan" /></term></item></list></para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Grid ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the Grid class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Children">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Grid.IGridList&lt;Xamarin.Forms.View&gt; Children { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Grid/IGridList`1&lt;class Xamarin.Forms.View&gt; Children" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Grid+IGridList&lt;Xamarin.Forms.View&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the collection of child elements of the Grid.</summary>
+ <value>The collection of child elements.</value>
+ <remarks>
+ <para>Application developers can use implicit collection syntax in XAML to add items to this collection, because this property is the <c>ContentPropertyAttribute</c> for the Grid class.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ColumnDefinitions">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.ColumnDefinitionCollection ColumnDefinitions { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.ColumnDefinitionCollection ColumnDefinitions" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ColumnDefinitionCollection</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Provides the interface for the bound property that gets or sets the ordered collection of <see cref="T:Xamarin.Forms.ColumnDefinition" /> objects that control the layout of columns in the <see cref="T:Xamarin.Forms.Grid" />.</summary>
+ <value>A ColumnDefinitionCollection for the Grid instance.</value>
+ <remarks>
+ <para>ColumnDefinitions is an ordered set of ColumnDefinition objects that determine the width of each column. Each successive ColumnDefintion controls the width of each successive column. If ColumnDefinitions is empty, or if there are more columns than definitions, then columns for which there is no definition are rendered as if they were controlled by a ColumnDefinition object that has its <see cref="P:Xamarin.Forms.ColumnDefinition.Width" /> property set to <see cref="P:Xamarin.Forms.GridLength.Auto" />.</para>
+ <para>The <see cref="P:Xamarin.Forms.Grid.ColumnDefinitions" /> property has XAML syntax support. The syntax for this operation is shown below.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ColumnDefinitionsProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ColumnDefinitionsProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ColumnDefinitionsProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Implements the <see cref="P:Xamarin.Forms.Grid.ColumnDefinitions" /> property, and allows the <see cref="T:Xamarin.Forms.Grid" /> class to bind it to properties on other objects at run time.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ColumnProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ColumnProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ColumnProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Implements the attached property that represents the zero-based column index of a child element. See Remarks.</summary>
+ <remarks>
+ <para>The interface for this property is defined by the <see cref="M:Xamarin.Forms.Grid.GetColumn" /> and <see cref="M:Xamarin.Forms.Grid.SetColumn" /> methods.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ColumnSpacing">
+ <MemberSignature Language="C#" Value="public double ColumnSpacing { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 ColumnSpacing" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Provides the interface for the bound property that gets or sets the distance between columns in the Grid.</summary>
+ <value>The space between columns in this <see cref="T:Xamarin.Forms.Grid" />layout.</value>
+ <remarks>
+ <para>The <see cref="P:Xamarin.Forms.Grid.ColumnSpacing" /> property does not control spacing on the left and right edges of the <see cref="T:Xamarin.Forms.Grid" /> layout. Application developers can control the spacing around the outside of the <see cref="T:Xamarin.Forms.Grid" /> layout by setting the <see cref="P:Xamarin.Forms.Page.Padding" /> property of the visual element to which it belongs.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ColumnSpacingProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ColumnSpacingProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ColumnSpacingProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Implements the <see cref="P:Xamarin.Forms.Grid.ColumnSpacing" /> property, and allows the <see cref="T:Xamarin.Forms.Grid" /> class to bind it to properties on other objects at run time.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ColumnSpanProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ColumnSpanProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ColumnSpanProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Implements the attached property that represents the number of columns that a child element spans. See Remarks.</summary>
+ <remarks>
+ <para>The interface for this property is defined by the <see cref="M:Xamarin.Forms.Grid.GetColumnSpan" /> and <see cref="M:Xamarin.Forms.Grid.SetColumnSpan" /> methods.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetColumn">
+ <MemberSignature Language="C#" Value="public static int GetColumn (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig int32 GetColumn(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">An element that belongs to the Grid layout.</param>
+ <summary>Gets the column of the <paramref name="bindable" /> child element.</summary>
+ <returns>The column that the child element is in.</returns>
+ <remarks>
+ <para>The <see cref="M:Xamarin.Forms.Grid.GetColum" /> method corresponds to the value that is set by the following XAML attached property.</para>
+ <list type="table">
+ <listheader>
+ <term>Attached Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Column</term>
+ <description>
+ <para>An integer that represents the Column in which the item will appear.</para>
+ </description>
+ </item>
+ </list>
+ <para>The remarks for the <see cref="M:Xamarin.Forms.Grid.SetColumn" /> method contain syntax for and information about the <c>Column</c> attached property.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetColumnSpan">
+ <MemberSignature Language="C#" Value="public static int GetColumnSpan (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig int32 GetColumnSpan(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">An element that belongs to the Grid layout.</param>
+ <summary>Gets the column span of the <paramref name="bindable" /> child element.</summary>
+ <returns>The column that the child element is in.</returns>
+ <remarks>
+ <para>The <see cref="M:Xamarin.Forms.Grid.GetColumSpan" /> method corresponds to the value that is set by the following XAML attached property.</para>
+ <list type="table">
+ <listheader>
+ <term>Attached Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>ColumnSpan</term>
+ <description>
+ <para>An integer that represents the number of Columns that the item will span.</para>
+ </description>
+ </item>
+ </list>
+ <para>The remarks for the <see cref="M:Xamarin.Forms.Grid.SetColumnSpan" /> method contain syntax for and information about the <c>ColumnSpan</c> attached property.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetRow">
+ <MemberSignature Language="C#" Value="public static int GetRow (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig int32 GetRow(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">An element that belongs to the Grid layout.</param>
+ <summary>Gets the row of the <paramref name="bindable" /> child element.</summary>
+ <returns>The row that the child element is in.</returns>
+ <remarks>
+ <para>The <see cref="M:Xamarin.Forms.Grid.GetRow" /> method corresponds to the following XAML attached property:</para>
+ <list type="table">
+ <listheader>
+ <term>Attached Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Row</term>
+ <description>
+ <para>An integer that represents the row in which the item will appear.</para>
+ </description>
+ </item>
+ </list>
+ <para>The remarks for the <see cref="M:Xamarin.Forms.Grid.SetRow" /> method contain syntax for and information about the <c>Row</c> attached property.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetRowSpan">
+ <MemberSignature Language="C#" Value="public static int GetRowSpan (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig int32 GetRowSpan(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">An element that belongs to the Grid layout.</param>
+ <summary>Gets the row span of the <paramref name="bindable" /> child element.</summary>
+ <returns>The row that the child element is in.</returns>
+ <remarks>
+ <para>The <see cref="M:Xamarin.Forms.Grid.GetRowSpan" /> method corresponds to the following XAML attached properties:</para>
+ <list type="table">
+ <listheader>
+ <term>Attached Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>RowSpan</term>
+ <description>An integer that represents the number of rows that the item will span.<para></para></description>
+ </item>
+ </list>
+ <para>The remarks for the <see cref="M:Xamarin.Forms.Grid.SetRowSpan" /> method contain syntax for and information about the <c>RowSpan</c> attached property.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="InvalidateMeasure">
+ <MemberSignature Language="C#" Value="protected override void InvalidateMeasure ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void InvalidateMeasure() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invalidates the grid layout.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutChildren">
+ <MemberSignature Language="C#" Value="protected override void LayoutChildren (double x, double y, double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void LayoutChildren(float64 x, float64 y, float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">X-coordinate of the top left corner of the bounding rectangle.</param>
+ <param name="y">Y-coordinate of the top left corner of the bounding rectangle.</param>
+ <param name="width">Width of the bounding rectangle.</param>
+ <param name="height">Height of the bounding rectangle.</param>
+ <summary>
+ <para>Lays out the child elements when the layout is invalidated.</para>
+ </summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnAdded">
+ <MemberSignature Language="C#" Value="protected override void OnAdded (Xamarin.Forms.View view);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnAdded(class Xamarin.Forms.View view) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.View" />
+ </Parameters>
+ <Docs>
+ <param name="view">The element that was added.</param>
+ <summary>Method that is called when a child is added to this <see cref="T:Xamarin.Forms.Grid" /> element.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBindingContextChanged">
+ <MemberSignature Language="C#" Value="protected override void OnBindingContextChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnBindingContextChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Application developers override this to respond when the binding context changes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnRemoved">
+ <MemberSignature Language="C#" Value="protected override void OnRemoved (Xamarin.Forms.View view);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnRemoved(class Xamarin.Forms.View view) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.View" />
+ </Parameters>
+ <Docs>
+ <param name="view">The element that was removed.</param>
+ <summary>Method that is called when a child is removed from this <see cref="T:Xamarin.Forms.Grid" /> element.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeRequest">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance valuetype Xamarin.Forms.SizeRequest OnSizeRequest(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use OnMeasure")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">The requested width.</param>
+ <param name="heightConstraint">The requested height.</param>
+ <summary>Method that is called when an attempt is made to resize this <see cref="T:Xamarin.Forms.Grid" /> element.</summary>
+ <returns>
+ <para>The new requested size.</para>
+ </returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RowDefinitions">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.RowDefinitionCollection RowDefinitions { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.RowDefinitionCollection RowDefinitions" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.RowDefinitionCollection</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Provides the interface for the bound property that gets or sets the collection of RowDefinition objects that control the heights of each row.</summary>
+ <value>A RowDefinitionCollection for the Grid instance.</value>
+ <remarks>
+ <para>RowDefinitions is an ordered set of <see cref="T:Xamarin.Forms.RowDefinition" /> objects that determine the height of each column. Each successive RowDefintion controls the width of each successive column. If RowDefinitions is empty, or if there are more rows than definitions, then rows for which there is no definition are rendered as if they were controlled by a RowDefinition object that has its <see cref="P:Xamarin.Forms.RowDefinition.Height" /> property set to <see cref="P:Xamarin.Forms.GridLength.Auto" />.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RowDefinitionsProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty RowDefinitionsProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty RowDefinitionsProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Implements the <see cref="P:Xamarin.Forms.Grid.RowDefinitions" /> property, and allows the <see cref="T:Xamarin.Forms.Grid" /> class to bind it to properties on other objects at run time.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RowProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty RowProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty RowProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Implements the attached property that represents the zero-based row index of a child element. See Remarks.</summary>
+ <remarks>
+ <para>The interface for this property is defined by the <see cref="M:Xamarin.Forms.Grid.GetRow" /> and <see cref="M:Xamarin.Forms.Grid.SetRowf" /> methods.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RowSpacing">
+ <MemberSignature Language="C#" Value="public double RowSpacing { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 RowSpacing" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the amount of space left between rows in the Grid. This is a bindable property.</summary>
+ <value>The space between rows</value>
+ <remarks>
+ <para>The <see cref="P:Xamarin.Forms.Grid.RowSpacing" /> property does not control spacing on the top and bottom edges of the <see cref="T:Xamarin.Forms.Grid" /> layout. Application developers can control the spacing around the outside of the <see cref="T:Xamarin.Forms.Grid" /> layout by setting the <see cref="P:Xamarin.Forms.Page.Padding" /> property of the visual element to which it belongs.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RowSpacingProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty RowSpacingProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty RowSpacingProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Implements the <see cref="P:Xamarin.Forms.Grid.RowSpacing" /> property, and allows the <see cref="T:Xamarin.Forms.Grid" /> class to bind it to properties on other objects at run time.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RowSpanProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty RowSpanProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty RowSpanProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Implements the attached property that represents the number of rows that a child element spans, and allows the <see cref="T:Xamarin.Forms.Grid" /> class to bind it to properties on other objects at run time.</summary>
+ <remarks>
+ <para>The interface for this property is defined by the <see cref="M:Xamarin.Forms.Grid.GetRowSpan" /> and <see cref="M:Xamarin.Forms.Grid.SetRowSpan" /> methods.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetColumn">
+ <MemberSignature Language="C#" Value="public static void SetColumn (Xamarin.Forms.BindableObject bindable, int value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetColumn(class Xamarin.Forms.BindableObject bindable, int32 value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="value" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">A child element of this Grid to move to a different column.</param>
+ <param name="value">The column in which to place the child element.</param>
+ <summary>Changes the column in which a child element will be placed.</summary>
+ <remarks>
+ <para>The <see cref="M:Xamarin.Forms.Grid.GetColumSpan" /> method corresponds to the value that is set by the following XAML attached property.</para>
+ <list type="table">
+ <listheader>
+ <term>Attached Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>ColumnSpan</term>
+ <description>
+ <para>An integer that represents the Column in which the item will appear.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetColumnSpan">
+ <MemberSignature Language="C#" Value="public static void SetColumnSpan (Xamarin.Forms.BindableObject bindable, int value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetColumnSpan(class Xamarin.Forms.BindableObject bindable, int32 value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="value" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">A child element of this Grid on which to assign a new column span.</param>
+ <param name="value">The new column span.</param>
+ <summary>Changes the column span of the specified child element.</summary>
+ <remarks>
+ <para>The <see cref="M:Xamarin.Forms.Grid.GetColum" /> method corresponds to the value that is set by the following XAML attached property.</para>
+ <list type="table">
+ <listheader>
+ <term>Attached Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Column</term>
+ <description>
+ <para>An integer that represents the number of Columns that the item will span.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetRow">
+ <MemberSignature Language="C#" Value="public static void SetRow (Xamarin.Forms.BindableObject bindable, int value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetRow(class Xamarin.Forms.BindableObject bindable, int32 value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="value" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">A child element of this Grid to move to a different row.</param>
+ <param name="value">The row in which to place the child element.</param>
+ <summary>Changes the row in which a child element will be placed.</summary>
+ <remarks>
+ <para>The <see cref="M:Xamarin.Forms.Grid.SetRow" /> method corresponds to the following XAML attached property:</para>
+ <list type="table">
+ <listheader>
+ <term>Attached Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Row</term>
+ <description>
+ <para>An integer that represents the row in which the item will appear.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetRowSpan">
+ <MemberSignature Language="C#" Value="public static void SetRowSpan (Xamarin.Forms.BindableObject bindable, int value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetRowSpan(class Xamarin.Forms.BindableObject bindable, int32 value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="value" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">A child element of this Grid on which to assign a new row span.</param>
+ <param name="value">The new row span.</param>
+ <summary>Changes the row span of the specified child element.</summary>
+ <remarks>
+ <para>The <see cref="M:Xamarin.Forms.Grid.SetRowSpan" /> method corresponds to the following XAML attached property:</para>
+ <list type="table">
+ <listheader>
+ <term>Attached Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>RowSpan</term>
+ <description>An integer that represents the number of rows that the item will span.<para></para></description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/GridLength.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/GridLength.xml
new file mode 100644
index 00000000..da9f2bd5
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/GridLength.xml
@@ -0,0 +1,316 @@
+<Type Name="GridLength" FullName="Xamarin.Forms.GridLength">
+ <TypeSignature Language="C#" Value="public struct GridLength" />
+ <TypeSignature Language="ILAsm" Value=".class public sequential ansi sealed beforefieldinit GridLength extends System.ValueType" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.ValueType</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.DebuggerDisplay("{Value}.{GridUnitType}")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.GridLengthTypeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Used to define the size (width/height) of Grid ColumnDefinition and RowDefinition.</summary>
+ <remarks>
+ <para>GridLength of type GridUnitType.Absolute represents exact size. The ones of type GridUnitType.Auto adapts for fitting the size of the elements in the gird column/row. GridLenght of type GridUnitType.Star are used to split the available size in proportional buckets.</para>
+ <para>This valuetype is readonly.</para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public GridLength (double value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 value) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="value" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Initializes a new Absolute GridLength.</summary>
+ <remarks>This is striclty equivalent to new GridLength (value, GridUnitType.Absolute).</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public GridLength (double value, Xamarin.Forms.GridUnitType type);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 value, valuetype Xamarin.Forms.GridUnitType type) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="value" Type="System.Double" />
+ <Parameter Name="type" Type="Xamarin.Forms.GridUnitType" />
+ </Parameters>
+ <Docs>
+ <param name="value">The size of the GridLength.</param>
+ <param name="type">The GridUnitType (Auto, Star, Absolute) of the GridLength.</param>
+ <summary>Initializes a new GridLength.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Auto">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.GridLength Auto { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property valuetype Xamarin.Forms.GridLength Auto" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GridLength</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A ready to reuse GridLength of GridUnitType.Auto.</summary>
+ <value>
+ </value>
+ <remarks>Value has no meaning for GridLength ot type GridUnitType.Auto.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Equals">
+ <MemberSignature Language="C#" Value="public override bool Equals (object obj);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool Equals(object obj) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="obj" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="obj">A GridLength to compare to.</param>
+ <summary>Test the equality of this GridLength and another one.</summary>
+ <returns>true is the GridLength are equal. False otherwise.</returns>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetHashCode">
+ <MemberSignature Language="C#" Value="public override int GetHashCode ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance int32 GetHashCode() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns a value that is used for efficient storage of this object in collections.</summary>
+ <returns>To be added.</returns>
+ <remarks>overriden.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GridUnitType">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.GridUnitType GridUnitType { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.GridUnitType GridUnitType" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GridUnitType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the GridUnitType of the GridLength</summary>
+ <value>The GridUnitType of the GridLength</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsAbsolute">
+ <MemberSignature Language="C#" Value="public bool IsAbsolute { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsAbsolute" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets wether or not the GridUnitType of the GridLength is GridUnitType.Absolute.</summary>
+ <value>true if the GridUnitType of the GridLength is GridUnitType.Absolute</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsAuto">
+ <MemberSignature Language="C#" Value="public bool IsAuto { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsAuto" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets wether or not the GridUnitType of the GridLength is GridUnitType.Auto.</summary>
+ <value>true if the GridUnitType of the GridLength is GridUnitType.Auto</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsStar">
+ <MemberSignature Language="C#" Value="public bool IsStar { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsStar" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that indicates whether the GridUnitType of the GridLength is GridUnitType.Star.</summary>
+ <value>true if the GridUnitType of the GridLength is GridUnitType.Star</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Implicit">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.GridLength op_Implicit (double absoluteValue);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname valuetype Xamarin.Forms.GridLength op_Implicit(float64 absoluteValue) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GridLength</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="absoluteValue" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="absoluteValue">The absolute size</param>
+ <summary>Casting operator to convert a double into a GridLength of type GridUnitType.Absolute</summary>
+ <returns>A GridLength of type GridUnitType.Absolute and of size absolutesize</returns>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ToString">
+ <MemberSignature Language="C#" Value="public override string ToString ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance string ToString() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns the value and the grid unit type, separated by a ".".</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Value">
+ <MemberSignature Language="C#" Value="public double Value { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Value" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the Value of the GridLength.</summary>
+ <value>The value in GridUnitType of the GridLength.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/GridLengthTypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/GridLengthTypeConverter.xml
new file mode 100644
index 00000000..8a854dea
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/GridLengthTypeConverter.xml
@@ -0,0 +1,131 @@
+<Type Name="GridLengthTypeConverter" FullName="Xamarin.Forms.GridLengthTypeConverter">
+ <TypeSignature Language="C#" Value="public class GridLengthTypeConverter : Xamarin.Forms.TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit GridLengthTypeConverter extends Xamarin.Forms.TypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TypeConverter" /> that converts from strings to <see cref="T:Xamarin.Forms.GridLength" />s.</summary>
+ <remarks>
+ <para>The following example shows some uses of <see cref="T:Xamarin.Forms.GridLengthTypeConverter" />:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+ var converter = new GridLengthTypeConverter ();
+
+ Assert.AreEqual (new GridLength (42), converter.ConvertFrom ("42"));
+ Assert.AreEqual (new GridLength (42.2), converter.ConvertFrom ("42.2"));
+ Assert.AreEqual (GridLength.Auto, converter.ConvertFrom ("auto"));
+ Assert.AreEqual (GridLength.Auto, converter.ConvertFrom (" AuTo "));
+ Assert.AreEqual (new GridLength (1, GridUnitType.Star), converter.ConvertFrom ("*"));
+ Assert.AreEqual (new GridLength (42, GridUnitType.Star), converter.ConvertFrom ("42*"));
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public GridLengthTypeConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.GridLength" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>Returns a Boolean value that indicates whether this <see cref="T:Xamarin.Forms.GridLengthTypeConverter" /> can convert the <paramref name="sourceType" /> to a <see cref="T:Xamarin.Forms.GridLength" /> instance.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Converts <paramref name="value" /> into a <see cref="T:Xamarin.Forms.GridLength" /> by using the specified <paramref name="culture" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Converts a valid grid length descriptor in to a <see cref="T:Xamarin.Forms.GridLength" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/GridUnitType.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/GridUnitType.xml
new file mode 100644
index 00000000..66c2d830
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/GridUnitType.xml
@@ -0,0 +1,86 @@
+<Type Name="GridUnitType" FullName="Xamarin.Forms.GridUnitType">
+ <TypeSignature Language="C#" Value="public enum GridUnitType" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed GridUnitType extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumerates values that control how the <see cref="P:Xamarin.Forms.GridLength.Value" /> property is interpreted for row and column definitions.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Absolute">
+ <MemberSignature Language="C#" Value="Absolute" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.GridUnitType Absolute = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GridUnitType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Interpret the <see cref="P:Xamarin.Forms.GridLength.Value" /> property value as the number of device-specific units.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Auto">
+ <MemberSignature Language="C#" Value="Auto" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.GridUnitType Auto = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GridUnitType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Ignore the <see cref="P:Xamarin.Forms.GridLength.Value" /> property value and choose a size that fits the children of the row or column.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Star">
+ <MemberSignature Language="C#" Value="Star" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.GridUnitType Star = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GridUnitType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Interpret the <see cref="P:Xamarin.Forms.GridLength.Value" /> property value as a proportional weight, to be laid out after rows and columns with <see cref="F:Xamarin.Forms.GridUnitType.Absolute" /> or <see cref="F:Xamarin.Forms.GridUnitType.Auto" /> are accounted for.</summary>
+ <remarks>After all the rows and columns of type <see cref="F:Xamarin.Forms.GridUnitType.Absolute" /> and <see cref="F:Xamarin.Forms.GridUnitType.Auto" /> are laid out, each of the corresponding remaining rows or columns, which are of type <see cref="F:Xamarin.Forms.GridUnitType.Star" />, receive a fraction of the remaining available space. This fraction is determined by dividing each row's or column's <see cref="P:Xamarin.Forms.GridLength.Value" /> property value by the sum of all the row or column <see cref="P:Xamarin.Forms.GridLength.Value" /> property values, correspondingly, including its own.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/HandlerAttribute.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/HandlerAttribute.xml
new file mode 100644
index 00000000..8a07f679
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/HandlerAttribute.xml
@@ -0,0 +1,76 @@
+<Type Name="HandlerAttribute" FullName="Xamarin.Forms.HandlerAttribute">
+ <TypeSignature Language="C#" Value="public abstract class HandlerAttribute : Attribute" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit HandlerAttribute extends System.Attribute" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Attribute</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.AttributeUsage(System.AttributeTargets.Assembly, AllowMultiple=true)</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>An abstract attribute whose subclasses specify the platform-specific renderers for Xamarin.Forms abstract controls.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected HandlerAttribute (Type handler, Type target);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor(class System.Type handler, class System.Type target) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="handler" Type="System.Type" />
+ <Parameter Name="target" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="handler">To be added.</param>
+ <param name="target">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.HandlerAttribute" /> object that maps events from <paramref name="target" /> to <paramref name="handler" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ShouldRegister">
+ <MemberSignature Language="C#" Value="public virtual bool ShouldRegister ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance bool ShouldRegister() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns a Boolean value that indicates whether the runtime should automatically register the handler for the target.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/HtmlWebViewSource.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/HtmlWebViewSource.xml
new file mode 100644
index 00000000..6c7818c6
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/HtmlWebViewSource.xml
@@ -0,0 +1,129 @@
+<Type Name="HtmlWebViewSource" FullName="Xamarin.Forms.HtmlWebViewSource">
+ <TypeSignature Language="C#" Value="public class HtmlWebViewSource : Xamarin.Forms.WebViewSource" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit HtmlWebViewSource extends Xamarin.Forms.WebViewSource" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.WebViewSource</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A WebViewSource bound to an HTML-formatted string.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public HtmlWebViewSource ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new empty <see cref="T:Xamarin.Forms.HtmlWebViewSource" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BaseUrl">
+ <MemberSignature Language="C#" Value="public string BaseUrl { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string BaseUrl" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The base URL for the source HTML document.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BaseUrlProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty BaseUrlProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty BaseUrlProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.BaseUrl" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Html">
+ <MemberSignature Language="C#" Value="public string Html { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Html" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The HTML content.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HtmlProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HtmlProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HtmlProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.BaseUrl" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IAnimatable.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IAnimatable.xml
new file mode 100644
index 00000000..10cd207e
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IAnimatable.xml
@@ -0,0 +1,65 @@
+<Type Name="IAnimatable" FullName="Xamarin.Forms.IAnimatable">
+ <TypeSignature Language="C#" Value="public interface IAnimatable" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IAnimatable" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Defines an interface for elements that can be animated.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="BatchBegin">
+ <MemberSignature Language="C#" Value="public void BatchBegin ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void BatchBegin() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Implement this method to begin a batch of animations that have been committed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BatchCommit">
+ <MemberSignature Language="C#" Value="public void BatchCommit ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void BatchCommit() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Implement this method to commit a batch of animations so that they can be run with the <see cref="M:Xamarin.Forms.IAnimatable.BatchBegin" /> method.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IApplicationController.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IApplicationController.xml
new file mode 100644
index 00000000..47ba7923
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IApplicationController.xml
@@ -0,0 +1,34 @@
+<Type Name="IApplicationController" FullName="Xamarin.Forms.IApplicationController">
+ <TypeSignature Language="C#" Value="public interface IApplicationController" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IApplicationController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="SetAppIndexingProvider">
+ <MemberSignature Language="C#" Value="public void SetAppIndexingProvider (Xamarin.Forms.IAppIndexingProvider appIndexing);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void SetAppIndexingProvider(class Xamarin.Forms.IAppIndexingProvider appIndexing) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="appIndexing" Type="Xamarin.Forms.IAppIndexingProvider" />
+ </Parameters>
+ <Docs>
+ <param name="appIndexing">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IAttachedObject.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IAttachedObject.xml
new file mode 100644
index 00000000..c54e3385
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IAttachedObject.xml
@@ -0,0 +1,71 @@
+<Type Name="IAttachedObject" FullName="Xamarin.Forms.IAttachedObject">
+ <TypeSignature Language="C#" Value="public interface IAttachedObject" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IAttachedObject" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Declare the common interface for objects that can attach to others.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="AssociatedObject">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.BindableObject AssociatedObject { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.BindableObject AssociatedObject" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableObject</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the AssociatedObject.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Attach">
+ <MemberSignature Language="C#" Value="public void Attach (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Attach(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">The object to attach to.</param>
+ <summary>Attach the bindable.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Detach">
+ <MemberSignature Language="C#" Value="public void Detach ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Detach() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Detach from the AssociatedObject.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ICarouselViewController.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ICarouselViewController.xml
new file mode 100644
index 00000000..46259b19
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ICarouselViewController.xml
@@ -0,0 +1,95 @@
+<Type Name="ICarouselViewController" FullName="Xamarin.Forms.ICarouselViewController">
+ <TypeSignature Language="C#" Value="public interface ICarouselViewController : Xamarin.Forms.IItemViewController" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract ICarouselViewController implements class Xamarin.Forms.IItemViewController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IItemViewController</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="SendPositionAppearing">
+ <MemberSignature Language="C#" Value="public void SendPositionAppearing (int position);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void SendPositionAppearing(int32 position) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="position" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="position">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SendPositionDisappearing">
+ <MemberSignature Language="C#" Value="public void SendPositionDisappearing (int position);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void SendPositionDisappearing(int32 position) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="position" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="position">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SendSelectedItemChanged">
+ <MemberSignature Language="C#" Value="public void SendSelectedItemChanged (object item);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void SendSelectedItemChanged(object item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="item">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SendSelectedPositionChanged">
+ <MemberSignature Language="C#" Value="public void SendSelectedPositionChanged (int position);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void SendSelectedPositionChanged(int32 position) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="position" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="position">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IDefinition.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IDefinition.xml
new file mode 100644
index 00000000..65f26ce0
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IDefinition.xml
@@ -0,0 +1,47 @@
+<Type Name="IDefinition" FullName="Xamarin.Forms.IDefinition">
+ <TypeSignature Language="C#" Value="public interface IDefinition" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IDefinition" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Interface defining the type of <see cref="T:Xamarin.Forms.RowDefinition" /> and <see cref="T:Xamarin.Forms.ColumnDefinition" />.</summary>
+ <remarks>
+ <para>Objects of type <see cref="T:Xamarin.Forms.DefinitionCollection`1" /> are parameterized with a type of <see cref="T:Xamarin.Forms.IDefinition" />.</para>
+ <para>
+ <img href="IDefinition.DefinitionCollectionRelation.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="SizeChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler SizeChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler SizeChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the size of the row or column changes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IEffectControlProvider.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IEffectControlProvider.xml
new file mode 100644
index 00000000..5f7e82ce
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IEffectControlProvider.xml
@@ -0,0 +1,34 @@
+<Type Name="IEffectControlProvider" FullName="Xamarin.Forms.IEffectControlProvider">
+ <TypeSignature Language="C#" Value="public interface IEffectControlProvider" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IEffectControlProvider" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>When implemented in a renderer, registers a platform-specific effect on an element.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="RegisterEffect">
+ <MemberSignature Language="C#" Value="public void RegisterEffect (Xamarin.Forms.Effect effect);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void RegisterEffect(class Xamarin.Forms.Effect effect) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="effect" Type="Xamarin.Forms.Effect" />
+ </Parameters>
+ <Docs>
+ <param name="effect">The effect to register.</param>
+ <summary>Registers the effect with the element by establishing the parent-child relations needed for rendering on the specific platform.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IElementController.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IElementController.xml
new file mode 100644
index 00000000..af57007c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IElementController.xml
@@ -0,0 +1,82 @@
+<Type Name="IElementController" FullName="Xamarin.Forms.IElementController">
+ <TypeSignature Language="C#" Value="public interface IElementController" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IElementController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>When implemented in a derived class, sets the value on bound properties so that their bindings are preserved.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="EffectControlProvider">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.IEffectControlProvider EffectControlProvider { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.IEffectControlProvider EffectControlProvider" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.IEffectControlProvider</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>When implemented in a derived class, gets or sets the provider that registers platform-specific effects.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetValueFromRenderer">
+ <MemberSignature Language="C#" Value="public void SetValueFromRenderer (Xamarin.Forms.BindableProperty property, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void SetValueFromRenderer(class Xamarin.Forms.BindableProperty property, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="property">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>When implemented in a derived class, sets the value on bound properties so that their bindings are preserved.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetValueFromRenderer">
+ <MemberSignature Language="C#" Value="public void SetValueFromRenderer (Xamarin.Forms.BindablePropertyKey propertyKey, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void SetValueFromRenderer(class Xamarin.Forms.BindablePropertyKey propertyKey, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyKey" Type="Xamarin.Forms.BindablePropertyKey" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="propertyKey">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Sets a bound property value from a renderer without breaking the binding.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IExtendedTypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IExtendedTypeConverter.xml
new file mode 100644
index 00000000..667bb67b
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IExtendedTypeConverter.xml
@@ -0,0 +1,68 @@
+<Type Name="IExtendedTypeConverter" FullName="Xamarin.Forms.IExtendedTypeConverter">
+ <TypeSignature Language="C#" Value="public interface IExtendedTypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IExtendedTypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Base class for type converters.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public object ConvertFrom (System.Globalization.CultureInfo culture, object value, IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value, class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("use ConvertFromInvariantString (string, IServiceProvider)")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <param name="serviceProvider">To be added.</param>
+ <summary>Converts <paramref name="value" /> with the specified <paramref name="culture" /> and <paramref name="serviceProvider" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public object ConvertFromInvariantString (string value, IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ConvertFromInvariantString(string value, class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <param name="serviceProvider">To be added.</param>
+ <summary>Converts <paramref name="value" /> with the specified <paramref name="serviceProvider" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IGestureRecognizer.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IGestureRecognizer.xml
new file mode 100644
index 00000000..0fb2c78a
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IGestureRecognizer.xml
@@ -0,0 +1,24 @@
+<Type Name="IGestureRecognizer" FullName="Xamarin.Forms.IGestureRecognizer">
+ <TypeSignature Language="C#" Value="public interface IGestureRecognizer : System.ComponentModel.INotifyPropertyChanged" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IGestureRecognizer implements class System.ComponentModel.INotifyPropertyChanged" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.ComponentModel.INotifyPropertyChanged</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>The base interface all gesture recognizers must implement.</summary>
+ <remarks>This interface is currently empty, this will likely change.</remarks>
+ </Docs>
+ <Members />
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IItemViewController.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IItemViewController.xml
new file mode 100644
index 00000000..03a410f2
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IItemViewController.xml
@@ -0,0 +1,96 @@
+<Type Name="IItemViewController" FullName="Xamarin.Forms.IItemViewController">
+ <TypeSignature Language="C#" Value="public interface IItemViewController" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IItemViewController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="BindView">
+ <MemberSignature Language="C#" Value="public void BindView (Xamarin.Forms.View view, object item);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void BindView(class Xamarin.Forms.View view, object item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.View" />
+ <Parameter Name="item" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="item">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateView">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.View CreateView (object itemType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class Xamarin.Forms.View CreateView(object itemType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.View</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="itemType" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="itemType">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetItem">
+ <MemberSignature Language="C#" Value="public object GetItem (int index);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object GetItem(int32 index) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="index" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="index">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetItemType">
+ <MemberSignature Language="C#" Value="public object GetItemType (object item);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object GetItemType(object item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="item">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ILayout.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ILayout.xml
new file mode 100644
index 00000000..275f6895
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ILayout.xml
@@ -0,0 +1,42 @@
+<Type Name="ILayout" FullName="Xamarin.Forms.ILayout">
+ <TypeSignature Language="C#" Value="public interface ILayout" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract ILayout" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Interface indicating layout behavior and exposing the <see cref="E:Xamarin.Forms.ILayout.LayoutChanged" /> event.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="LayoutChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler LayoutChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler LayoutChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the layout changes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ILayoutController.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ILayoutController.xml
new file mode 100644
index 00000000..48b2c9e5
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ILayoutController.xml
@@ -0,0 +1,37 @@
+<Type Name="ILayoutController" FullName="Xamarin.Forms.ILayoutController">
+ <TypeSignature Language="C#" Value="public interface ILayoutController" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract ILayoutController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Class that renderers implement in order participate in the layout cycle.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Children">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IReadOnlyList&lt;Xamarin.Forms.Element&gt; Children { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IReadOnlyList`1&lt;class Xamarin.Forms.Element&gt; Children" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IReadOnlyList&lt;Xamarin.Forms.Element&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a read-only list of the immediate children of the renderer that implements the interface.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/INativeElementView.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/INativeElementView.xml
new file mode 100644
index 00000000..bbfa5926
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/INativeElementView.xml
@@ -0,0 +1,33 @@
+<Type Name="INativeElementView" FullName="Xamarin.Forms.INativeElementView">
+ <TypeSignature Language="C#" Value="public interface INativeElementView" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract INativeElementView" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Interface that contains a read-only property that returns the platform-specific native view for a Xamarin.Forms element.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Element">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Element Element { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Element Element" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Element</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the platform-specific native view for a Xamarin.Forms element.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/INavigation.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/INavigation.xml
new file mode 100644
index 00000000..5d0f7b0b
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/INavigation.xml
@@ -0,0 +1,389 @@
+<Type Name="INavigation" FullName="Xamarin.Forms.INavigation">
+ <TypeSignature Language="C#" Value="public interface INavigation" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract INavigation" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Interface abstracting platform-specific navigation.</summary>
+ <remarks>
+ <para>Note that on the Android platform, <see cref="T:Xamarin.Forms.INavigation" /> operations do not generate activity lifecycle notifications. For each <see cref="T:Xamarin.Forms.Page" /> that you push or pop, the Android implementation of <see cref="T:Xamarin.Forms.NavigationPage" /> simply adds or removes the content of the page to or from a single activity.</para>
+ <para>Also note that the Windows Phone platform provides navigation natively. Therefore, you do not need to use a <see cref="T:Xamarin.Forms.NavigationPage" /> object to get navigation on that platform.</para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="InsertPageBefore">
+ <MemberSignature Language="C#" Value="public void InsertPageBefore (Xamarin.Forms.Page page, Xamarin.Forms.Page before);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void InsertPageBefore(class Xamarin.Forms.Page page, class Xamarin.Forms.Page before) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="page" Type="Xamarin.Forms.Page" />
+ <Parameter Name="before" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="page">The page to add.</param>
+ <param name="before">The existing page, before which <paramref name="page" /> will be inserted.</param>
+ <summary>Inserts a page in the navigation stack before an existing page in the stack.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ModalStack">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IReadOnlyList&lt;Xamarin.Forms.Page&gt; ModalStack { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IReadOnlyList`1&lt;class Xamarin.Forms.Page&gt; ModalStack" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IReadOnlyList&lt;Xamarin.Forms.Page&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the modal navigation stack.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="NavigationStack">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IReadOnlyList&lt;Xamarin.Forms.Page&gt; NavigationStack { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IReadOnlyList`1&lt;class Xamarin.Forms.Page&gt; NavigationStack" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IReadOnlyList&lt;Xamarin.Forms.Page&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the stack of pages in the navigation.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PopAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task&lt;Xamarin.Forms.Page&gt; PopAsync ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Threading.Tasks.Task`1&lt;class Xamarin.Forms.Page&gt; PopAsync() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;Xamarin.Forms.Page&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Asynchronously removes the most recent <see cref="T:Xamarin.Forms.Page" /> from the navigation stack.</summary>
+ <returns>The <see cref="T:Xamarin.Forms.Page" /> that had been at the top of the navigation stack.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PopAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task&lt;Xamarin.Forms.Page&gt; PopAsync (bool animated);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Threading.Tasks.Task`1&lt;class Xamarin.Forms.Page&gt; PopAsync(bool animated) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;Xamarin.Forms.Page&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="animated" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="animated">To be added.</param>
+ <summary>Asynchronously removes the most recent <see cref="T:Xamarin.Forms.Page" /> from the navigation stack, with optional animation.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PopModalAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task&lt;Xamarin.Forms.Page&gt; PopModalAsync ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Threading.Tasks.Task`1&lt;class Xamarin.Forms.Page&gt; PopModalAsync() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;Xamarin.Forms.Page&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Asynchronously dismisses the most recent modally presented <see cref="T:Xamarin.Forms.Page" />.</summary>
+ <returns>An awaitable Task&lt;Page&gt;, indicating the PopModalAsync completion. The Task.Result is the Page that has been popped.</returns>
+ <remarks>
+ <para>The following example shows PushModal and PopModal usage:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+var modalPage = new ContentPage ();
+await Navigation.PushModalAsync (modalPage);
+Debug.WriteLine ("The modal page is now on screen");
+var poppedPage = await Navigation.PopModalAsync ();
+Debug.WriteLine ("The modal page is dismissed");
+Debug.WriteLine (Object.ReferenceEquals (modalPage, poppedPage)); //prints "true"
+ ]]></code>
+ </example>
+ <block subset="none" type="note">
+ <para>Application developers must <see langword="await" /> the result of <see cref="M:Xamarin.Forms.INavigation.PushModal" /> and <see cref="M:Xamarin.Forms.INavigation.PopModal" />. Calling <see cref="M:System.Threading.Tasks.Task.Wait" /> may cause a deadlock if a previous call to <see cref="M:Xamarin.Forms.INavigation.PushModal" /> or <see cref="M:Xamarin.Forms.INavigation.PopModal" /> has not completed.</para>
+ </block>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PopModalAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task&lt;Xamarin.Forms.Page&gt; PopModalAsync (bool animated);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Threading.Tasks.Task`1&lt;class Xamarin.Forms.Page&gt; PopModalAsync(bool animated) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;Xamarin.Forms.Page&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="animated" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="animated">To be added.</param>
+ <summary>Asynchronously dismisses the most recent modally presented <see cref="T:Xamarin.Forms.Page" />, with optional animation.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PopToRootAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task PopToRootAsync ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Threading.Tasks.Task PopToRootAsync() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Pops all but the root <see cref="T:Xamarin.Forms.Page" /> off the navigation stack.</summary>
+ <returns>A task representing the asynchronous dismiss operation.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PopToRootAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task PopToRootAsync (bool animated);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Threading.Tasks.Task PopToRootAsync(bool animated) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="animated" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="animated">To be added.</param>
+ <summary>Pops all but the root <see cref="T:Xamarin.Forms.Page" /> off the navigation stack, with optional animation.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PushAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task PushAsync (Xamarin.Forms.Page page);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Threading.Tasks.Task PushAsync(class Xamarin.Forms.Page page) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="page" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="page">The <see cref="T:Xamarin.Forms.Page" /> to be pushed on top of the navigation stack.</param>
+ <summary>Asynchronously adds a <see cref="T:Xamarin.Forms.Page" /> to the top of the navigation stack.</summary>
+ <returns>A task representing the asynchronous dismiss operation.</returns>
+ <remarks>
+ <para>
+ The following example shows <see cref="M:Xamarin.Forms.INavigation.Push" /> and <see cref="M:Xamarin.Forms.INavigation.Pop" /> usage:
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+var newPage = new ContentPage ();
+await Navigation.PushAsync (newPage);
+Debug.WriteLine ("the new page is now showing");
+var poppedPage = await Navigation.PopAsync ();
+Debug.WriteLine ("the new page is dismissed");
+Debug.WriteLine (Object.ReferenceEquals (newPage, poppedPage)); //prints "true"
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PushAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task PushAsync (Xamarin.Forms.Page page, bool animated);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Threading.Tasks.Task PushAsync(class Xamarin.Forms.Page page, bool animated) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="page" Type="Xamarin.Forms.Page" />
+ <Parameter Name="animated" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="page">To be added.</param>
+ <param name="animated">To be added.</param>
+ <summary>Asynchronously adds a <see cref="T:Xamarin.Forms.Page" /> to the top of the navigation stack, with optional animation.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PushModalAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task PushModalAsync (Xamarin.Forms.Page page);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Threading.Tasks.Task PushModalAsync(class Xamarin.Forms.Page page) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="page" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="page">The <see cref="T:Xamarin.Forms.Page" /> to present modally.</param>
+ <summary>Presents a <see cref="T:Xamarin.Forms.Page" /> modally.</summary>
+ <returns>An awaitable Task, indicating the PushModal completion.</returns>
+ <remarks>
+ <para>The following example shows PushModalAsync and PopModalAsync usage:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+var modalPage = new ContentPage ();
+await Navigation.PushModalAsync (modalPage);
+Debug.WriteLine ("The modal page is now on screen");
+var poppedPage = await Navigation.PopModalAsync ();
+Debug.WriteLine ("The modal page is dismissed");
+Debug.WriteLine (Object.ReferenceEquals (modalPage, poppedPage)); //prints "true"
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PushModalAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task PushModalAsync (Xamarin.Forms.Page page, bool animated);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Threading.Tasks.Task PushModalAsync(class Xamarin.Forms.Page page, bool animated) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="page" Type="Xamarin.Forms.Page" />
+ <Parameter Name="animated" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="page">To be added.</param>
+ <param name="animated">To be added.</param>
+ <summary>Presents a <see cref="T:Xamarin.Forms.Page" /> modally, with optional animation.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RemovePage">
+ <MemberSignature Language="C#" Value="public void RemovePage (Xamarin.Forms.Page page);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void RemovePage(class Xamarin.Forms.Page page) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="page" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="page">To be added.</param>
+ <summary>Removes the specified page from the navigation stack.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IOpenGLViewController.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IOpenGLViewController.xml
new file mode 100644
index 00000000..bb2a2ac6
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IOpenGLViewController.xml
@@ -0,0 +1,36 @@
+<Type Name="IOpenGLViewController" FullName="Xamarin.Forms.IOpenGLViewController">
+ <TypeSignature Language="C#" Value="public interface IOpenGLViewController : Xamarin.Forms.IViewController" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IOpenGLViewController implements class Xamarin.Forms.IElementController, class Xamarin.Forms.IViewController, class Xamarin.Forms.IVisualElementController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IViewController</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>A view controller for displaying OpenGL content.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="DisplayRequested">
+ <MemberSignature Language="C#" Value="public event EventHandler DisplayRequested;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler DisplayRequested" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when an OpenGL display is requested.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IPageContainer`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IPageContainer`1.xml
new file mode 100644
index 00000000..724aba42
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IPageContainer`1.xml
@@ -0,0 +1,52 @@
+<Type Name="IPageContainer&lt;T&gt;" FullName="Xamarin.Forms.IPageContainer&lt;T&gt;">
+ <TypeSignature Language="C#" Value="public interface IPageContainer&lt;out T&gt; where T : Page" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IPageContainer`1&lt;(class Xamarin.Forms.Page) + T&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="T">
+ <Constraints>
+ <ParameterAttribute>Covariant</ParameterAttribute>
+ <BaseTypeName>Xamarin.Forms.Page</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Interfaces />
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <summary>Interface defining a container for <see cref="T:Xamarin.Forms.Page" />s and exposing a <see cref="P:Xamarin.Forms.IPageContainer`1.CurrentPage" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="CurrentPage">
+ <MemberSignature Language="C#" Value="public T CurrentPage { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance !T CurrentPage" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the current page.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IPlatform.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IPlatform.xml
new file mode 100644
index 00000000..5edc9fc9
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IPlatform.xml
@@ -0,0 +1,123 @@
+<Type Name="IPlatform" FullName="Xamarin.Forms.IPlatform">
+ <TypeSignature Language="C#" Value="public interface IPlatform" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IPlatform" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Interface defining the abstraction of a native platform.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="BindingContext">
+ <MemberSignature Language="C#" Value="public object BindingContext { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object BindingContext" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The binding context for the native platform.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BindingContextChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler BindingContextChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler BindingContextChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the binding context changes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Engine">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.IPlatformEngine Engine { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.IPlatformEngine Engine" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.IPlatformEngine</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The platform engine, useful for getting the screen size and for finding out if the paltform supports 3D.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Page">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Page Page { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Page Page" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Page</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the root page of the platform.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetPage">
+ <MemberSignature Language="C#" Value="public void SetPage (Xamarin.Forms.Page newRoot);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void SetPage(class Xamarin.Forms.Page newRoot) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="newRoot" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="newRoot">To be added.</param>
+ <summary>Sets the root page of the platform.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IPlatformEngine.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IPlatformEngine.xml
new file mode 100644
index 00000000..7a38c8ae
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IPlatformEngine.xml
@@ -0,0 +1,70 @@
+<Type Name="IPlatformEngine" FullName="Xamarin.Forms.IPlatformEngine">
+ <TypeSignature Language="C#" Value="public interface IPlatformEngine" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IPlatformEngine" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Interface defining a native platform rendering engine.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="GetNativeSize">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.SizeRequest GetNativeSize (Xamarin.Forms.VisualElement view, double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance valuetype Xamarin.Forms.SizeRequest GetNativeSize(class Xamarin.Forms.VisualElement view, float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" />
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="widthConstraint">To be added.</param>
+ <param name="heightConstraint">To be added.</param>
+ <summary>Performs a size request on the native platform.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Supports3D">
+ <MemberSignature Language="C#" Value="public bool Supports3D { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool Supports3D" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a Boolean value that indicates whether the native platform supports 3D graphics.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IRegisterable.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IRegisterable.xml
new file mode 100644
index 00000000..04c940ae
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IRegisterable.xml
@@ -0,0 +1,20 @@
+<Type Name="IRegisterable" FullName="Xamarin.Forms.IRegisterable">
+ <TypeSignature Language="C#" Value="public interface IRegisterable" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IRegisterable" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Internally-used flagging interface indicating types that can be registered with <see cref="T:Xamarin.Forms.Registrar" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members />
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IScrollViewController.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IScrollViewController.xml
new file mode 100644
index 00000000..a1c89c03
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IScrollViewController.xml
@@ -0,0 +1,104 @@
+<Type Name="IScrollViewController" FullName="Xamarin.Forms.IScrollViewController">
+ <TypeSignature Language="C#" Value="public interface IScrollViewController : Xamarin.Forms.ILayoutController" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IScrollViewController implements class Xamarin.Forms.ILayoutController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.ILayoutController</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>Interface for a scrollview controller.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="GetScrollPositionForElement">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Point GetScrollPositionForElement (Xamarin.Forms.VisualElement item, Xamarin.Forms.ScrollToPosition position);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance valuetype Xamarin.Forms.Point GetScrollPositionForElement(class Xamarin.Forms.VisualElement item, valuetype Xamarin.Forms.ScrollToPosition position) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Point</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="Xamarin.Forms.VisualElement" />
+ <Parameter Name="position" Type="Xamarin.Forms.ScrollToPosition" />
+ </Parameters>
+ <Docs>
+ <param name="item">To be added.</param>
+ <param name="position">To be added.</param>
+ <summary>Calculates and returns a point that represents the scroll position that results in <paramref name="item" /> being displayed at <paramref name="position" /> in the scroll view.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ScrollToRequested">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ScrollToRequestedEventArgs&gt; ScrollToRequested;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ScrollToRequestedEventArgs&gt; ScrollToRequested" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ScrollToRequestedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when a request has been made to scroll the scroll view.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SendScrollFinished">
+ <MemberSignature Language="C#" Value="public void SendScrollFinished ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void SendScrollFinished() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Attempts to set the scroll task completion source state to <c>RanToCompletion</c>.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetScrolledPosition">
+ <MemberSignature Language="C#" Value="public void SetScrolledPosition (double x, double y);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void SetScrolledPosition(float64 x, float64 y) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">To be added.</param>
+ <param name="y">To be added.</param>
+ <summary>Sets the scroll position to (<paramref name="x" />,
+ <paramref name="y" />).</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IValueConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IValueConverter.xml
new file mode 100644
index 00000000..93a92949
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IValueConverter.xml
@@ -0,0 +1,85 @@
+<Type Name="IValueConverter" FullName="Xamarin.Forms.IValueConverter">
+ <TypeSignature Language="C#" Value="public interface IValueConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IValueConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces />
+ <Docs>
+ <summary>Interface defining methods for two-way value conversion between types.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Convert">
+ <MemberSignature Language="C#" Value="public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object Convert(object value, class System.Type targetType, object parameter, class System.Globalization.CultureInfo culture) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.Object" />
+ <Parameter Name="targetType" Type="System.Type" />
+ <Parameter Name="parameter" Type="System.Object" />
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <param name="targetType">To be added.</param>
+ <param name="parameter">To be added.</param>
+ <param name="culture">To be added.</param>
+ <summary>Implement this method to convert <paramref name="value" /> to <paramref name="targetType" /> by using <paramref name="parameter" /> and <paramref name="culture" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertBack">
+ <MemberSignature Language="C#" Value="public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ConvertBack(object value, class System.Type targetType, object parameter, class System.Globalization.CultureInfo culture) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.Object" />
+ <Parameter Name="targetType" Type="System.Type" />
+ <Parameter Name="parameter" Type="System.Object" />
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <param name="targetType">To be added.</param>
+ <param name="parameter">To be added.</param>
+ <param name="culture">To be added.</param>
+ <summary>Implement this method to convert <paramref name="value" /> back from <paramref name="targetType" /> by using <paramref name="parameter" /> and <paramref name="culture" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IViewContainer`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IViewContainer`1.xml
new file mode 100644
index 00000000..86dabcd3
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IViewContainer`1.xml
@@ -0,0 +1,53 @@
+<Type Name="IViewContainer&lt;T&gt;" FullName="Xamarin.Forms.IViewContainer&lt;T&gt;">
+ <TypeSignature Language="C#" Value="public interface IViewContainer&lt;T&gt; where T : VisualElement" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IViewContainer`1&lt;(class Xamarin.Forms.VisualElement) T&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="T">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.VisualElement</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Interfaces />
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <summary>The type of element that can be added to the container.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Children">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;T&gt; Children { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;!T&gt; Children" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;T&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The children collection of a visual element.</summary>
+ <value>The collection containing the visual elements children.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IViewController.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IViewController.xml
new file mode 100644
index 00000000..2a791b85
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IViewController.xml
@@ -0,0 +1,21 @@
+<Type Name="IViewController" FullName="Xamarin.Forms.IViewController">
+ <TypeSignature Language="C#" Value="public interface IViewController : Xamarin.Forms.IVisualElementController" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IViewController implements class Xamarin.Forms.IElementController, class Xamarin.Forms.IVisualElementController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IVisualElementController</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>Contains methods that set values from renderers on bound properties without breaking the binding.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members />
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/IVisualElementController.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/IVisualElementController.xml
new file mode 100644
index 00000000..a2b63a36
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/IVisualElementController.xml
@@ -0,0 +1,41 @@
+<Type Name="IVisualElementController" FullName="Xamarin.Forms.IVisualElementController">
+ <TypeSignature Language="C#" Value="public interface IVisualElementController : Xamarin.Forms.IElementController" />
+ <TypeSignature Language="ILAsm" Value=".class public interface auto ansi abstract IVisualElementController implements class Xamarin.Forms.IElementController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IElementController</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>Method that is called when the native size of a visual element changes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="NativeSizeChanged">
+ <MemberSignature Language="C#" Value="public void NativeSizeChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void NativeSizeChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>When implemented in a renderer, called to invalidate the layout when the native size of a visual element changes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Image.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Image.xml
new file mode 100644
index 00000000..0f863018
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Image.xml
@@ -0,0 +1,364 @@
+<Type Name="Image" FullName="Xamarin.Forms.Image">
+ <TypeSignature Language="C#" Value="public class Image : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Image extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._ImageRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>
+ <see cref="T:Xamarin.Forms.View" /> that holds an image.</summary>
+ <remarks>
+ <para>
+ The following example creates a new image from a file
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+var image = new Image { Source = "picture.png" };]]></code>
+ </example>
+ <para>The FormsGallery sample, which can be found on the <format type="text/html"><a href="http://developer.xamarin.com/samples/tag/Xamarin.Forms/" target="_blank">Sample Applications</a></format> page, has a ImageDemoPage.cs file. This file contains a longer and more complicated example.</para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Image ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the Image class.</summary>
+ <remarks>
+ <para>
+ The following example creates a new image from a file
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+ var image = new Image { Source = "picture.png" };]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Aspect">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Aspect Aspect { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Aspect Aspect" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Aspect</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the scaling mode for the image. This is a bindable property.</summary>
+ <value>A <see cref="T:Xamarin.Forms.Aspect" /> representing the scaling mode of the image. Default is <see cref="E:Xamarin.Forms.Aspect.AspectFit" />.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AspectProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty AspectProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty AspectProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Aspect bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsLoading">
+ <MemberSignature Language="C#" Value="public bool IsLoading { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsLoading" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the loading status of the image. This is a bindable property.</summary>
+ <value>A <see cref="T:System.Boolean" /> indicating if the image is loadin. Default is false.</value>
+ <remarks>
+ <para>
+ The following example illustrates running a <see cref="T:Xamarin.Forms.ActivityIndicator" /> to indicate that the image is loading:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+var image = new Image {
+ Source = new ImageLoader {
+ Uri = new Uri ("http://eoimages.gsfc.nasa.gov/images/imagerecords/57000/57723/globe_west_2048.jpg"),
+ CachingEnabled = false,
+ },
+ WidthRequest = 200,
+ HeightRequest = 200,
+};
+
+var indicator = new ActivityIndicator {Color = new Color (.5),};
+indicator.SetBinding (ActivityIndicator.IsRunningProperty, "IsLoading");
+indicator.BindingContext = image;]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsLoadingProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsLoadingProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsLoadingProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the IsLoading bindable property.</summary>
+ <remarks>This bindable property is readonly.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsOpaque">
+ <MemberSignature Language="C#" Value="public bool IsOpaque { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsOpaque" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the opacity flag for the image. This is a bindable property.</summary>
+ <value>A <see cref="T:System.Boolean" /> indicating the value for the property. Default is false.</value>
+ <remarks>If true, you'll be able to see through transparent parts of the image.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsOpaqueProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsOpaqueProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsOpaqueProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the IsOpaque bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBindingContextChanged">
+ <MemberSignature Language="C#" Value="protected override void OnBindingContextChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnBindingContextChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invoked when the BindingContext changes.</summary>
+ <remarks>Overriden for Image.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnPropertyChanged">
+ <MemberSignature Language="C#" Value="protected override void OnPropertyChanged (string propertyName);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnPropertyChanged(string propertyName) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the property.</param>
+ <summary>Invoked when a property has changed.</summary>
+ <remarks>Overriden for Image.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnPropertyChanging">
+ <MemberSignature Language="C#" Value="protected override void OnPropertyChanging (string propertyName);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnPropertyChanging(string propertyName) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the property.</param>
+ <summary>Invoked when a property will change.</summary>
+ <remarks>Overriden for Image.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeRequest">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance valuetype Xamarin.Forms.SizeRequest OnSizeRequest(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use OnMeasure")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">The available width.</param>
+ <param name="heightConstraint">The available height.</param>
+ <summary>Invoked when the layotu cycle request the element desired size.</summary>
+ <returns>
+ </returns>
+ <remarks>Overriden for Image.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Source">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.ImageSource Source { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.ImageSource Source" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.ImageSourceConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ImageSource</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the source of the image. This is a bindable property.</summary>
+ <value>An <see cref="T:Xamarin.Forms.ImageSource" /> representing the image source. Default is null.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SourceProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty SourceProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty SourceProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Source bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ImageCell.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ImageCell.xml
new file mode 100644
index 00000000..6cf4e995
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ImageCell.xml
@@ -0,0 +1,177 @@
+<Type Name="ImageCell" FullName="Xamarin.Forms.ImageCell">
+ <TypeSignature Language="C#" Value="public class ImageCell : Xamarin.Forms.TextCell" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ImageCell extends Xamarin.Forms.TextCell" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TextCell</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TextCell" /> that has an image.</summary>
+ <remarks>
+ <para>
+ <see cref="T:Xamarin.Forms.ImageCell" /> objects are used to place images and accompanying text into a table.</para>
+ <example>
+ <para>The following example shows a basic use.</para>
+ <code lang="C#"><![CDATA[using System;
+using Xamarin.Forms;
+
+namespace FormsGallery
+{
+ class ImageCellDemoPage : ContentPage
+ {
+ public ImageCellDemoPage()
+ {
+ Label header = new Label
+ {
+ Text = "ImageCell",
+ FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ TableView tableView = new TableView
+ {
+ Intent = TableIntent.Form,
+ Root = new TableRoot
+ {
+ new TableSection
+ {
+ new ImageCell
+ {
+ // Some differences with loading images in initial release.
+ ImageSource =
+ Device.OnPlatform(ImageSource.FromUri(new Uri("http://xamarin.com/images/index/ide-xamarin-studio.png")),
+ ImageSource.FromFile("ide_xamarin_studio.png"),
+ ImageSource.FromFile("Images/ide-xamarin-studio.png")),
+ Text = "This is an ImageCell",
+ Detail = "This is some detail text",
+ }
+ }
+ }
+ };
+
+ // Accomodate iPhone status bar.
+ this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
+
+ // Build the page.
+ this.Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ tableView
+ }
+ };
+ }
+ }
+}]]></code>
+ </example>
+ <para>
+ <img href="ImageCell.TripleScreenShot.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ImageCell ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the ImageCell class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ImageSource">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.ImageSource ImageSource { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.ImageSource ImageSource" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.ImageSourceConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ImageSource</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the ImageSource from which the Image is loaded. This is a bindable property.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ImageSourceProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ImageSourceProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ImageSourceProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the ImageSource bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBindingContextChanged">
+ <MemberSignature Language="C#" Value="protected override void OnBindingContextChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnBindingContextChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Overriden..</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ImageSource.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ImageSource.xml
new file mode 100644
index 00000000..162b3a10
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ImageSource.xml
@@ -0,0 +1,382 @@
+<Type Name="ImageSource" FullName="Xamarin.Forms.ImageSource">
+ <TypeSignature Language="C#" Value="public abstract class ImageSource : Xamarin.Forms.Element" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit ImageSource extends Xamarin.Forms.Element" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Element</BaseTypeName>
+ </Base>
+ <Interfaces>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.ImageSourceConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Abstract class whose implementors load images from files or the Web.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Cancel">
+ <MemberSignature Language="C#" Value="public virtual System.Threading.Tasks.Task&lt;bool&gt; Cancel ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Threading.Tasks.Task`1&lt;bool&gt; Cancel() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Request a cancel of the ImageSource loading.</summary>
+ <returns>An awaitable Task. The result of the Task indicates if the Task was successfully cancelled.</returns>
+ <remarks>Calling Cancel() multiple times will throw an exception.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CancellationTokenSource">
+ <MemberSignature Language="C#" Value="protected System.Threading.CancellationTokenSource CancellationTokenSource { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Threading.CancellationTokenSource CancellationTokenSource" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.CancellationTokenSource</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the CancellationTokenSource.</summary>
+ <value>
+ </value>
+ <remarks>Used by inheritors to implement cancellable loads.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromFile">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.ImageSource FromFile (string file);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.ImageSource FromFile(string file) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ImageSource</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="file" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="file">The name of a file that contains a valid image.</param>
+ <summary>Returns a new <see cref="T:Xamarin.Forms.FileImageSource" /> that reads from <paramref name="file" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromResource">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.ImageSource FromResource (string resource);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.ImageSource FromResource(string resource) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ImageSource</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="resource" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="resource">A string representing the id of the EmbeddedResource to load.</param>
+ <summary>Creates an ImageSource for an EmbeddedResource included in the Assembly from which the call to FromResource is made.</summary>
+ <returns>A newly created ImageSource.</returns>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromResource">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.ImageSource FromResource (string resource, System.Reflection.Assembly sourceAssembly = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.ImageSource FromResource(string resource, class System.Reflection.Assembly sourceAssembly) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ImageSource</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="resource" Type="System.String" />
+ <Parameter Name="sourceAssembly" Type="System.Reflection.Assembly" />
+ </Parameters>
+ <Docs>
+ <param name="resource">The name of a valid image resource in <paramref name="sourceAssembly" />.</param>
+ <param name="sourceAssembly">The source assembly in which to search for the image.</param>
+ <summary>Creates a <see cref="T:Xamarin.Forms.ImageSource" /> from the specified resource in the specified source assembly.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromResource">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.ImageSource FromResource (string resource, Type resolvingType);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.ImageSource FromResource(string resource, class System.Type resolvingType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ImageSource</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="resource" Type="System.String" />
+ <Parameter Name="resolvingType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="resource">The name of a valid image resource in the assembly to which <paramref name="resolvingType" /> belongs.</param>
+ <param name="resolvingType">A type from the assembly in which to look up the image resource with <paramref name="resource" />.</param>
+ <summary>Creates a <see cref="T:Xamarin.Forms.ImageSource" /> from the specified resource in the specified source assembly.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromStream">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.ImageSource FromStream (Func&lt;System.IO.Stream&gt; stream);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.ImageSource FromStream(class System.Func`1&lt;class System.IO.Stream&gt; stream) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ImageSource</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="stream" Type="System.Func&lt;System.IO.Stream&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="stream">A stream that supplies image data.</param>
+ <summary>Returns a new <see cref="T:Xamarin.Forms.StreamImageSource" /> that reads from <paramref name="stream" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromUri">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.ImageSource FromUri (Uri uri);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.ImageSource FromUri(class System.Uri uri) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ImageSource</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="uri" Type="System.Uri" />
+ </Parameters>
+ <Docs>
+ <param name="uri">A URI that identifies a valid image.</param>
+ <summary>Returns a new <see cref="T:Xamarin.Forms.UriImageSource" /> that reads from <paramref name="uri" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnLoadingCompleted">
+ <MemberSignature Language="C#" Value="protected void OnLoadingCompleted (bool cancelled);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig instance void OnLoadingCompleted(bool cancelled) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="cancelled" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="cancelled">A bool indicating if the source was cancelled.</param>
+ <summary>Called by inheritors to indicate the end of the loading of the source.</summary>
+ <remarks>OnLoadingCompleted should follow a OnLoadingStarted.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnLoadingStarted">
+ <MemberSignature Language="C#" Value="protected void OnLoadingStarted ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig instance void OnLoadingStarted() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Called by inheritors to indicate the beginning of a loading operation.</summary>
+ <remarks>OnLoadingCompleted should follow a OnLoadingStarted.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSourceChanged">
+ <MemberSignature Language="C#" Value="protected void OnSourceChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig instance void OnSourceChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Called by inheritors to indicate that the source changed..</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Implicit">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.ImageSource op_Implicit (string source);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname class Xamarin.Forms.ImageSource op_Implicit(string source) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ImageSource</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="source" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="source">A string that represents an image location.</param>
+ <summary>Allows implicit casting from a string that represents an absolute URI.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Implicit">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.ImageSource op_Implicit (Uri uri);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname class Xamarin.Forms.ImageSource op_Implicit(class System.Uri uri) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ImageSource</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="uri" Type="System.Uri" />
+ </Parameters>
+ <Docs>
+ <param name="uri">A absolute URI that specifies an image location.</param>
+ <summary>Allows implicit casting from <see cref="T:System.Uri" /> objects that were created with an absolute URI.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElement.Parent">
+ <MemberSignature Language="C#" Value="Xamarin.Forms.Element Xamarin.Forms.IElement.Parent { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Element Xamarin.Forms.IElement.Parent" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Element</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the element to which this <see cref="T:Xamarin.Forms.ImageSource" /> object belongs.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElement.XamlParent">
+ <MemberSignature Language="C#" Value="WeakReference&lt;Xamarin.Forms.Element&gt; Xamarin.Forms.IElement.XamlParent { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.WeakReference`1&lt;class Xamarin.Forms.Element&gt; Xamarin.Forms.IElement.XamlParent" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.WeakReference&lt;Xamarin.Forms.Element&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a weak reference to the parent of this <see cref="T:Xamarin.Forms.ImageSource" /> object.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ImageSourceConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ImageSourceConverter.xml
new file mode 100644
index 00000000..189b462b
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ImageSourceConverter.xml
@@ -0,0 +1,98 @@
+<Type Name="ImageSourceConverter" FullName="Xamarin.Forms.ImageSourceConverter">
+ <TypeSignature Language="C#" Value="public sealed class ImageSourceConverter : Xamarin.Forms.TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit ImageSourceConverter extends Xamarin.Forms.TypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Class that takes a string representation of an image file location and returns a <see cref="T:Xamarin.Forms.ImageSource" /> from the specified resource.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ImageSourceConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.ImageSourceConverter" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">A type to query.</param>
+ <summary>Returns <see langword="true" /> if the converter can create and return a <see cref="T:Xamarin.Forms.ImageSource" /> for items of the specified source type. Otherwise, <see langword="false" />.</summary>
+ <returns>
+ <see langword="true" /> if the converter can create and return a <see cref="T:Xamarin.Forms.ImageSource" /> for items of the specified source type. Otherwise, <see langword="false" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Creates and returns a <see cref="T:Xamarin.Forms.ImageSource" /> for the specified <paramref name="value" /> and <paramref name="culture" />.</summary>
+ <returns>A <see cref="T:Xamarin.Forms.ImageSource" /> for the specified <paramref name="value" /> and <paramref name="culture" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Returns an image source created from a URI that is contained in <paramref name="value" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/InputView.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/InputView.xml
new file mode 100644
index 00000000..7e81cb2d
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/InputView.xml
@@ -0,0 +1,69 @@
+<Type Name="InputView" FullName="Xamarin.Forms.InputView">
+ <TypeSignature Language="C#" Value="public class InputView : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit InputView extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>The base class of a view which can take keyboard input.</summary>
+ <remarks>The constructor of this class is internal. Forms does not provide any renderer for InputView base class.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Keyboard">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Keyboard Keyboard { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Keyboard Keyboard" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Keyboard</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the Keyboard for the InputView. This is a bindable property.</summary>
+ <value>The <see cref="T:Xamarin.Forms.Keyboard" /> to use for the InputView.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="KeyboardProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty KeyboardProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty KeyboardProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Keyboard bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ItemTappedEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ItemTappedEventArgs.xml
new file mode 100644
index 00000000..466709c2
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ItemTappedEventArgs.xml
@@ -0,0 +1,92 @@
+<Type Name="ItemTappedEventArgs" FullName="Xamarin.Forms.ItemTappedEventArgs">
+ <TypeSignature Language="C#" Value="public class ItemTappedEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ItemTappedEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Event arguments for the <see cref="E:Xamarin.Forms.ListView.ItemTapped" /> event.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ItemTappedEventArgs (object group, object item);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(object group, object item) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="group" Type="System.Object" />
+ <Parameter Name="item" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="group">To be added.</param>
+ <param name="item">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.ItemTappedEventArgs" /> object for the specified <paramref name="item" /> that was tapped and the <paramref name="group" /> to which it belongs.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Group">
+ <MemberSignature Language="C#" Value="public object Group { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Group" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The collection of elements to which the tapped item belongs.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Item">
+ <MemberSignature Language="C#" Value="public object Item { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Item" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The visual element that the user tapped.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ItemVisibilityEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ItemVisibilityEventArgs.xml
new file mode 100644
index 00000000..c1806fb7
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ItemVisibilityEventArgs.xml
@@ -0,0 +1,71 @@
+<Type Name="ItemVisibilityEventArgs" FullName="Xamarin.Forms.ItemVisibilityEventArgs">
+ <TypeSignature Language="C#" Value="public sealed class ItemVisibilityEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit ItemVisibilityEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Event args when an items visiblity has been changed in a <see cref="T:Xamarin.Forms.ListView" />.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ItemVisibilityEventArgs (object item);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(object item) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="item">The modified item.</param>
+ <summary>Initializes a new instance of the ItemVisibilityEventArgs class with the item whose visibility has changed.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Item">
+ <MemberSignature Language="C#" Value="public object Item { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Item" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The item from the <see cref="P:Xamarin.Forms.ListView.ItemsSource" /> whose visibility has changed.</summary>
+ <value>An object.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ItemsView.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ItemsView.xml
new file mode 100644
index 00000000..6f8d1ca5
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ItemsView.xml
@@ -0,0 +1,206 @@
+<Type Name="ItemsView" FullName="Xamarin.Forms.ItemsView">
+ <TypeSignature Language="C#" Value="public abstract class ItemsView : Xamarin.Forms.View, Xamarin.Forms.IItemViewController" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit ItemsView extends Xamarin.Forms.View implements class Xamarin.Forms.IItemViewController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IItemViewController</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Count">
+ <MemberSignature Language="C#" Value="public int Count { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 Count" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemsSource">
+ <MemberSignature Language="C#" Value="public System.Collections.IEnumerable ItemsSource { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.IEnumerable ItemsSource" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.IEnumerable</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemsSourceProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ItemsSourceProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ItemsSourceProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemTemplate">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.DataTemplate ItemTemplate { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.DataTemplate ItemTemplate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.DataTemplate</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemTemplateProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ItemTemplateProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ItemTemplateProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnPropertyChanged">
+ <MemberSignature Language="C#" Value="protected override void OnPropertyChanged (string propertyName = null);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnPropertyChanged(string propertyName) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String">
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.CallerMemberName</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Parameter>
+ </Parameters>
+ <Docs>
+ <param name="propertyName">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IItemViewController.BindView">
+ <MemberSignature Language="C#" Value="void IItemViewController.BindView (Xamarin.Forms.View view, object item);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IItemViewController.BindView(class Xamarin.Forms.View view, object item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.View" />
+ <Parameter Name="item" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="item">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IItemViewController.CreateView">
+ <MemberSignature Language="C#" Value="Xamarin.Forms.View IItemViewController.CreateView (object type);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance class Xamarin.Forms.View Xamarin.Forms.IItemViewController.CreateView(object type) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.View</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="type" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="type">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IItemViewController.GetItem">
+ <MemberSignature Language="C#" Value="object IItemViewController.GetItem (int index);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.IItemViewController.GetItem(int32 index) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="index" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="index">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IItemViewController.GetItemType">
+ <MemberSignature Language="C#" Value="object IItemViewController.GetItemType (object item);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.IItemViewController.GetItemType(object item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="item">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ItemsView`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ItemsView`1.xml
new file mode 100644
index 00000000..31bd14aa
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ItemsView`1.xml
@@ -0,0 +1,338 @@
+<Type xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/mono/mono/master/mcs/tools/mdoc/Resources/monodoc-ecma.xsd" Name="ItemsView&lt;TVisual&gt;" FullName="Xamarin.Forms.ItemsView&lt;TVisual&gt;">
+ <TypeSignature Language="C#" Value="public abstract class ItemsView&lt;TVisual&gt; : Xamarin.Forms.View where TVisual : BindableObject" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit ItemsView`1&lt;(class Xamarin.Forms.BindableObject) TVisual&gt; extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="TVisual">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces>
+ </Interfaces>
+ <Docs>
+ <typeparam name="TVisual">The type of visual that the <see cref="P:Xamarin.Forms.ItemsView{TVisual}.ItemsSource" /> items will be templated into.</typeparam>
+ <summary>A base class for a view that contains a templated list of items.</summary>
+ <remarks>
+ <para>
+ This class is used as a base class for views that wish to take in a list of user objects and produce views for each of them to be displayed, such as <see cref="T:Xamarin.Forms.ListView" />. The generic
+ argument is used to specify the type of visual that the view expects. In the case of <see cref="T:Xamarin.Forms.ListView" />, only <see cref="T:Xamarin.Forms.Cell" /> subclasses are accepted, so that's
+ what it provides as its argument.
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="CreateDefault">
+ <MemberSignature Language="C#" Value="protected abstract TVisual CreateDefault (object item);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance !TVisual CreateDefault(object item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>TVisual</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="item">The user object </param>
+ <summary>Creates a default <typeparamref name="TVisual" /> instance for <paramref name="item" />.</summary>
+ <returns>An instance of the <typeparamref name="TVisual" /> class.</returns>
+ <remarks>
+ <para>This method is called by the templating system when <see cref="P:Xamarin.Forms.ItemsView{TVisual}.ItemTemplate" /> is <see langword="null" />.</para>
+ <para>The <see cref="P:Xamarin.Forms.BindableObject.BindingContext" /> of the returned object will automatically be set to <paramref name="item" />, there is no
+ need to set it yourself. If you do, it will be overridden.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemsSource">
+ <MemberSignature Language="C#" Value="public System.Collections.IEnumerable ItemsSource { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.IEnumerable ItemsSource" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.IEnumerable</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the source of items to template and display.</summary>
+ <value>To be added.</value>
+ <remarks>
+ <para>While any <see cref="T:System.Collections.IEnumerable" /> implementer is accepted, any that do not implement <see cref="T:System.Collections.IList" /> or <see cref="T:System.Collections.Generic.IReadOnlyList{T}" />
+ (where T is a class) will be converted to list by iterating.</para>
+ <para>If your collection implements <see cref="T:System.Collections.Specialized.INotifyCollectionChanged" />, any changes raised from the event on this interface will be reflected in the items view. Note that if the event
+ is raised on another thread the main thread, the results will be unpredictable depending on the platform. To safely modify your collection (and raise the event) from another thread, call
+ <see cref="M:Xamarin.Forms.BindingBase.EnableCollectionSynchronization" /> to enable proper synchronization of access to the thread.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemsSourceProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ItemsSourceProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ItemsSourceProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.ItemsView{TVisual}.ItemSource" /> property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemTemplate">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.DataTemplate ItemTemplate { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.DataTemplate ItemTemplate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.DataTemplate</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the <see cref="T:Xamarin.Forms.DataTemplate" /> to apply to the <see cref="M:Xamarin.Forms.ItemsView{TVisual}.ItemsSource" />.</summary>
+ <value>The <see cref="T:Xamarin.Forms.DataTemplate" /> for the <see cref="T:Xamarin.Forms.ItemsView" />, or <see langword="null" /></value>
+ <remarks>
+ <para>The ItemTemplate is used to define the visual appearance of objects from the <see cref="P.Xamarin.Forms.ItemsView{TVisual}.ItemsSource" />. Through
+ the item template you can set up data bindings to the user objects supplied to automatically fill in the visual and respond to any changes in the user
+ object.</para>
+ <para>If the item template is <see langword="null" />, <see cref="M.Xamarin.Forms.ItemsView{TVisual}.CreateDefault" /> is called and the result is used as the visual.</para>
+ <example>
+ <para>In this example, a template for a <see cref="T:Xamarin.Forms.TextCell" /> is created for a simple user object.</para>
+ <code lang="C#"><![CDATA[
+class Person
+{
+ public string FullName
+ {
+ get;
+ set;
+ }
+
+ public string Address
+ {
+ get;
+ set;
+ }
+}
+
+void SetupView()
+{
+ var template = new DataTemplate (typeof (TextCell));
+
+ // We can set data bindings to our supplied objects.
+ template.SetBinding (TextCell.TextProperty, "FullName");
+ template.SetBinding (TextCell.DetailProperty, "Address");
+
+ // We can also set values that will apply to each item.
+ template.SetValue (TextCell.TextColorProperty, Color.Red);
+
+ itemsView.ItemTemplate = template;
+ itemsView.ItemsSource = new[] {
+ new Person { FullName = "James Smith", Address = "404 Nowhere Street" },
+ new Person { FullName = "John Doe", Address = "404 Nowhere Ave" }
+ };
+}
+ ]]></code>
+ </example>
+ </remarks>
+ <altmember cref="T:Xamarin.Forms.DataTemplate" />
+ <altmember cref="P:Xamarin.Forms.ItemsView{TVisual}.ItemsSource" />
+ <altmember cref="M:Xamarin.Forms.ItemsView{TVisual}.CreateDefault" />
+ </Docs>
+ </Member>
+ <Member MemberName="ItemTemplateProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ItemTemplateProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ItemTemplateProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.ItemsView{TVisual}.ItemTemplate" /> property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetupContent">
+ <MemberSignature Language="C#" Value="protected virtual void SetupContent (TVisual content, int index);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void SetupContent(!TVisual content, int32 index) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="content" Type="TVisual" />
+ <Parameter Name="index" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="content">The visual content to setup.</param>
+ <param name="index">The index of the content.</param>
+ <summary>Performs any additional setup for the content at creation time.</summary>
+ <remarks>
+ <para>This method is called when the <see cref="T:Xamarin.Forms.ItemsView{TVisual}" /> is creating visuals for user items. At this point,
+ the <see cref="P:Xamarin.Forms.BindableObject.BindingContext" /> will have been set. You can override this method to perform additional setup
+ for content specific to your <see cref="T:Xamarin.Forms.ItemsView{TVisual}" /> subclass. <see cref="T:Xamarin.Forms.ListView" />, for example, uses
+ this method to set <see cref="P:Xamarin.Forms.Element.Parent" /> to itself.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="UnhookContent">
+ <MemberSignature Language="C#" Value="protected virtual void UnhookContent (TVisual content);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void UnhookContent(!TVisual content) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="content" Type="TVisual" />
+ </Parameters>
+ <Docs>
+ <param name="content">To be added.</param>
+ <summary>Application developers override this method to unregister event handlers for items that they registered in <see cref="M:Xamarin.Forms.ItemsView{TVisual}.SetupContent(`0, int)" />.</summary>
+ <remarks>
+ <para>Application developers must call <see cref="M:Xamarin.Forms.ItemsView{TVisual}.UnhookContent(`0, int)" /> before performing any other action when overriding this method.</para>
+ <block type="note">Application developers who override <see cref="M:Xamarin.Forms.ItemsView{TVisual}.SetupContent(`0, int)" /> to allocate resources must override this method in order to deallocate them.</block>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IItemsView&lt;TVisual&gt;.CreateDefault">
+ <MemberSignature Language="C#" Value="TVisual IItemsView&lt;TVisual&gt;.CreateDefault (object item);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance !TVisual Xamarin.Forms.IItemsView&lt;TVisual&gt;.CreateDefault(object item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>TVisual</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="item">To be added.</param>
+ <summary>Creates a default TVisual by using <paramref name="item" /></summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IItemsView&lt;TVisual&gt;.SetupContent">
+ <MemberSignature Language="C#" Value="void IItemsView&lt;TVisual&gt;.SetupContent (TVisual content, int index);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IItemsView&lt;TVisual&gt;.SetupContent(!TVisual content, int32 index) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="content" Type="TVisual" />
+ <Parameter Name="index" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="content">To be added.</param>
+ <param name="index">To be added.</param>
+ <summary>Configures <paramref name="content" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IItemsView&lt;TVisual&gt;.UnhookContent">
+ <MemberSignature Language="C#" Value="void IItemsView&lt;TVisual&gt;.UnhookContent (TVisual content);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IItemsView&lt;TVisual&gt;.UnhookContent(!TVisual content) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="content" Type="TVisual" />
+ </Parameters>
+ <Docs>
+ <param name="content">To be added.</param>
+ <summary>Internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Keyboard.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Keyboard.xml
new file mode 100644
index 00000000..1fa660cc
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Keyboard.xml
@@ -0,0 +1,209 @@
+<Type Name="Keyboard" FullName="Xamarin.Forms.Keyboard">
+ <TypeSignature Language="C#" Value="public class Keyboard" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Keyboard extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.KeyboardTypeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Default keyboard and base class for specialized keyboards, such as those for telephone numbers, email, and URLs.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Chat">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Keyboard Chat { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property class Xamarin.Forms.Keyboard Chat" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Keyboard</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets an instance of type "ChatKeyboard".</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Create">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Keyboard Create (Xamarin.Forms.KeyboardFlags flags);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.Keyboard Create(valuetype Xamarin.Forms.KeyboardFlags flags) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Keyboard</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="flags" Type="Xamarin.Forms.KeyboardFlags" />
+ </Parameters>
+ <Docs>
+ <param name="flags">To be added.</param>
+ <summary>Returns a new keyboard with the specified <see cref="T:Xamarin.Forms.KeyboardFlags" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Default">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Keyboard Default { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property class Xamarin.Forms.Keyboard Default" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Keyboard</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets an instance of type "Keyboard".</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Email">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Keyboard Email { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property class Xamarin.Forms.Keyboard Email" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Keyboard</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets an instance of type "EmailKeyboard".</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Numeric">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Keyboard Numeric { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property class Xamarin.Forms.Keyboard Numeric" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Keyboard</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets an instance of type "NumericKeyboard".</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Telephone">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Keyboard Telephone { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property class Xamarin.Forms.Keyboard Telephone" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Keyboard</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets an instance of type "TelephoneKeyboard".</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Text">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Keyboard Text { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property class Xamarin.Forms.Keyboard Text" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Keyboard</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets an instance of type "TextKeyboard".</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Url">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Keyboard Url { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property class Xamarin.Forms.Keyboard Url" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Keyboard</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets an instance of type "UrlKeyboard"..</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/KeyboardFlags.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/KeyboardFlags.xml
new file mode 100644
index 00000000..ea7d6a39
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/KeyboardFlags.xml
@@ -0,0 +1,108 @@
+<Type Name="KeyboardFlags" FullName="Xamarin.Forms.KeyboardFlags">
+ <TypeSignature Language="C#" Value="public enum KeyboardFlags" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed KeyboardFlags extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Flags</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Flagging enumeration for Keyboard options such as Capitalization, Spellcheck, and Suggestions.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="All">
+ <MemberSignature Language="C#" Value="All" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.KeyboardFlags All = int32(-1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.KeyboardFlags</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Capitalize the first words of sentences, and perform spellcheck and offer suggested word completions on text that the user enters.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="CapitalizeSentence">
+ <MemberSignature Language="C#" Value="CapitalizeSentence" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.KeyboardFlags CapitalizeSentence = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.KeyboardFlags</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Capitalize the first words of sentences.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Spellcheck">
+ <MemberSignature Language="C#" Value="Spellcheck" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.KeyboardFlags Spellcheck = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.KeyboardFlags</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Perform spellcheck on text that the user enters.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Suggestions">
+ <MemberSignature Language="C#" Value="Suggestions" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.KeyboardFlags Suggestions = int32(4)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.KeyboardFlags</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Offer suggested word completions on text that the user enters.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/KeyboardTypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/KeyboardTypeConverter.xml
new file mode 100644
index 00000000..5a5a2719
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/KeyboardTypeConverter.xml
@@ -0,0 +1,141 @@
+<Type Name="KeyboardTypeConverter" FullName="Xamarin.Forms.KeyboardTypeConverter">
+ <TypeSignature Language="C#" Value="public class KeyboardTypeConverter : Xamarin.Forms.TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit KeyboardTypeConverter extends Xamarin.Forms.TypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TypeConverter" /> that converts a string into a <see cref="T:Xamarin.Forms.Keyboard" />.</summary>
+ <remarks>
+ <para>The following XAML snippet illustrates a case where a KeyboardTypeConverter is used behind the scenes:</para>
+ <example>
+ <code lang="XAML"><![CDATA[
+<Entry Keyboard="Keyboard.Telephone" />
+ ]]></code>
+ </example>
+ <para>The following shows some examples of <see cref="T:Xamarin.Forms.KeyboardTypeConverter" /> forms:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+var converter = new KeyboardTypeConverter ();
+foreach (var kvp in new Dictionary<string, Keyboard> {
+ {"Keyboard.Default", Keyboard.Default},
+ {"Keyboard.Email", Keyboard.Email},
+ {"Keyboard.Text", Keyboard.Text},
+ {"Keyboard.Url", Keyboard.Url},
+ {"Keyboard.Telephone", Keyboard.Telephone},
+ {"Keyboard.Chat", Keyboard.Chat},
+})
+Assert.AreSame (kvp.Value, converter.ConvertFrom (kvp.Key));
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public KeyboardTypeConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the KayboardTypeConverter class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">The type of the object.</param>
+ <summary>Returns wheher this converter can convert an object of the given type.</summary>
+ <returns>
+ <see langword="true" /> if the KeyboardTypeConverter can convert from sourceType. <see langword="false" /> otherwise.</returns>
+ <remarks>This method only returns <see langword="true" /> is sourceType is <see cref="T:System.String" />.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">The Culture fo the value parameter.</param>
+ <param name="value">The object to convert from.</param>
+ <summary>TConvert the given value into a Keyboard.</summary>
+ <returns>A <see cref="T:Xamarin.Forms.Keyboard" />.</returns>
+ <remarks>This will throw an IvalidOperationException if the conversion failed.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Returns a keyboard for a valid keyboard name.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Label.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Label.xml
new file mode 100644
index 00000000..47a9a6b0
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Label.xml
@@ -0,0 +1,663 @@
+<Type Name="Label" FullName="Xamarin.Forms.Label">
+ <TypeSignature Language="C#" Value="public class Label : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Label extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Text")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._LabelRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.View" /> that displays text.</summary>
+ <remarks>
+ <para>A Label is used to display single-line text elements as well as multi-line blocks of text.</para>
+ <para>
+ <img href="Label.TripleScreenShot.png" />
+ </para>
+ <para>The following example, adapted from the default Xamarin Forms solution, shows a basic use:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+public class App : Application
+{
+ public App ()
+ {
+ MainPage = new ContentPage {
+ Content = new Label {
+ Text = "Hello, Forms!",
+ FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ HorizontalOptions = LayoutOptions.CenterAndExpand,
+ },
+ };
+}
+]]></code>
+ <para>The FormsGallery sample, which can be found on the <format type="text/html"><a href="http://developer.xamarin.com/samples/tag/Xamarin.Forms/" target="_blank">Sample Applications</a></format> page, has a LabelDemoPage.cs file. This file contains a longer and more complete example.</para>
+ </example>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.Label" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Font</term>
+ <description>
+ <para>Deprecated. Use <c>FontAttributes</c>, <c>FontFamily</c>, and <c>FontSize</c>, instead. A string of the format <c>[name],[attributes],[size]</c>. The font specification may contain multiple attributes, e.g. <c>Georgia, Bold, Italic, 42</c>.</para>
+ </description>
+ </item>
+ <item>
+ <term>FontAttributes</term>
+ <description>
+ <para>
+ <c>Bold</c>, <c>Bold,Italic</c>, or <c>None</c>.</para>
+ </description>
+ </item>
+ <item>
+ <term>FontFamily</term>
+ <description>
+ <para>A font family, such as <c>sans-serif</c> or <c>monospace</c>.</para>
+ </description>
+ </item>
+ <item>
+ <term>FontSize</term>
+ <description>
+ <para>A named size, such as <c>Large</c>, or an integer that represents the size in device units.</para>
+ </description>
+ </item>
+ <!--TODO: Figure this out. ON HOLD from ermau 2014-01-20
+ <item>
+ <term>FormattedText</term>
+ <description><para></para></description>
+ </item>-->
+ <item>
+ <term>LineBreakMode</term>
+ <description>
+ <para>A string that corresponds to a <see cref="T:Xamarin.Forms.LineBreakMode" /> enumeration value.</para>
+ </description>
+ </item>
+ <item>
+ <term>Text</term>
+ <description>
+ <para>The text that will appear on the label.</para>
+ </description>
+ </item>
+ <item>
+ <term>TextColor</term>
+ <description>
+ <para>A color specification, with or without the prefix, "Color". For example, "Color.Red" and "Red" both specify the color red.</para>
+ </description>
+ </item>
+ <item>
+ <term>HorizontalTextAlignment</term>
+ <description>
+ <para>
+ <c>Center</c>, <c>End</c>, or <c>Start</c>, to indicate the horizontal placement of the label text.</para>
+ </description>
+ </item>
+ <item>
+ <term>VerticalTextAlignment</term>
+ <description>
+ <para>
+ <c>Center</c>, <c>End</c>, or <c>Start</c>, to indicate the vertical placement of the label text.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Label ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the Label class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Font">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Font Font { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Font Font" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Please use the Font attributes which are on the class itself. Obsoleted in v1.3.0")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Font</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the Font for the Label. This is a bindable property.</summary>
+ <value>The <see cref="T:Xamarin.Forms.Font" /> value for the Label. The default is <see langword="null" />, which represents the default font on the platform.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontAttributes">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.FontAttributes FontAttributes { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.FontAttributes FontAttributes" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FontAttributes</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that indicates whether the font for the label is bold, italic, or neither.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontAttributesProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontAttributesProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontAttributesProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the FontAttributes property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontFamily">
+ <MemberSignature Language="C#" Value="public string FontFamily { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string FontFamily" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the font family to which the font for the label belongs.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontFamilyProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontFamilyProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontFamilyProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the FontFamily property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the Font bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontSize">
+ <MemberSignature Language="C#" Value="public double FontSize { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 FontSize" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.FontSizeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the size of the font for the label.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontSizeProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontSizeProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontSizeProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the FontSize property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FormattedText">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.FormattedString FormattedText { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.FormattedString FormattedText" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FormattedString</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the formatted text for the Label. This is a bindable property.</summary>
+ <value>The <see cref="T:Xamarin.Forms.FormattedString" /> value to be displayed inside of the Label. This is a bindable property.</value>
+ <remarks>Setting FromattedText to a non-null value will set the Text property to null.
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FormattedTextProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FormattedTextProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FormattedTextProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the FormattedText property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HorizontalTextAlignment">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.TextAlignment HorizontalTextAlignment { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.TextAlignment HorizontalTextAlignment" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TextAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the horizontal alignement of the Text property. This is a bindable property.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HorizontalTextAlignmentProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HorizontalTextAlignmentProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HorizontalTextAlignmentProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the HorizontalTextAlignment bindable property</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LineBreakMode">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.LineBreakMode LineBreakMode { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.LineBreakMode LineBreakMode" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LineBreakMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the LineBreakMode for the Label. This is a bindable property.</summary>
+ <value>The <see cref="T:Xamarin.Forms.LineBreakMode" /> value for the Label. The default is <see cref="E:Xamarin.Forms.LineBreakMode.WordWrap" /></value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LineBreakModeProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty LineBreakModeProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty LineBreakModeProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the LineBreakMode bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Text">
+ <MemberSignature Language="C#" Value="public string Text { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Text" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the text for the Label. This is a bindable property.</summary>
+ <value>The <see cref="T:System.String" /> value to be displayed inside of the Label.</value>
+ <remarks>Setting Text to a non-null value will set the FormattedText property to null.
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color TextColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color TextColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the <see cref="T:Xamarin.Forms.Color" /> for the text of this Label. This is a bindable property.</summary>
+ <value>The <see cref="T:Xamarin.Forms.Color" /> value.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TextColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TextColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the TextColor bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TextProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TextProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the Text bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="VerticalTextAlignment">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.TextAlignment VerticalTextAlignment { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.TextAlignment VerticalTextAlignment" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TextAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the vertical alignement of the Text property. This is a bindable property.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="VerticalTextAlignmentProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty VerticalTextAlignmentProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty VerticalTextAlignmentProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the VerticalTextAlignment bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="XAlign">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.TextAlignment XAlign { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.TextAlignment XAlign" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("XAlign is obsolete. Please use HorizontalTextAlignment instead.")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TextAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the horizontal alignment for the Text inside of the Label bound.</summary>
+ <value>The <see cref="T:Xamarin.Forms.TextAlignment" /> value. The default is <see cref="E:Xamarin.Forms.TextAlignment.Start" />, i.e. the text is left-aligned.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="XAlignProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty XAlignProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty XAlignProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("XAlignProperty is obsolete. Please use HorizontalTextAlignmentProperty instead.")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the XAlign bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="YAlign">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.TextAlignment YAlign { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.TextAlignment YAlign" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("YAlign is obsolete. Please use VerticalTextAlignment instead.")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TextAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the vertical alignment for the Text inside of the Label bound.</summary>
+ <value>The <see cref="T:Xamarin.Forms.TextAlignment" /> value. The default is <see cref="E:Xamarin.Forms.TextAlignment.Start" />, i.e. the text is top-aligned.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="YAlignProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty YAlignProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty YAlignProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("YAlignProperty is obsolete. Please use VerticalTextAlignmentProperty instead.")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the YAlign bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Layout.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Layout.xml
new file mode 100644
index 00000000..3b46b814
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Layout.xml
@@ -0,0 +1,563 @@
+<Type Name="Layout" FullName="Xamarin.Forms.Layout">
+ <TypeSignature Language="C#" Value="public abstract class Layout : Xamarin.Forms.View, Xamarin.Forms.ILayout, Xamarin.Forms.ILayoutController" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit Layout extends Xamarin.Forms.View implements class Xamarin.Forms.ILayout, class Xamarin.Forms.ILayoutController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ <BaseTypeArguments>
+ <BaseTypeArgument TypeParamName="T">Xamarin.Forms.View</BaseTypeArgument>
+ </BaseTypeArguments>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.ILayout</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.ILayoutController</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>
+ <para>Provides the base class for all Layout elements. Use Layout elements to position and size child elements in Forms applications.</para>
+ </summary>
+ <remarks>
+ <para>Subtypes of <see cref="T:Xamarin.Forms.Layout" /> include <see cref="T:Xamarin.Forms.ContentView" />, <see cref="T:Xamarin.Forms.ScrollView" />, and <see cref="T:Xamarin.Forms.Layout`1" />, as shown in the following diagram.</para>
+ <para>The <see cref="P:Xamarin.Forms.Layout`1.Children" /> property of <see cref="T:Xamarin.Forms.Layout`1" /> contains a list of children of the parameterized type <c>T</c>, which must be a type of <see cref="T:Xamarin.Forms.View" />. Since <see cref="T:Xamarin.Forms.Layout" /> is itself a subclass of <see cref="T:Xamarin.Forms.View" />, this allows <see cref="T:Xamarin.Forms.Layout" />s to hold sub-layouts, scrolling regions, etc.</para>
+ <!-- Until and unless we get a tool to do these graphics properl. Will need intro text for this, too.
+ <para>
+ <img href="Element.Hierarchy.png" />
+ </para>-->
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.Layout" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>IsClippedToBounds</term>
+ <description>
+ <para>
+ <c>true</c> or <c>false</c>, to indicate whether the layout is clipped to its bounding rectangle.</para>
+ </description>
+ </item>
+ <item>
+ <term>Padding</term>
+ <description>
+ <para>A comma-separated list of 4 integers that represent a <see cref="T:Xamarin.Forms.Thickness" /> structure.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ <altmember cref="T:Xamarin.Forms.ContentView" />
+ <altmember cref="T:Xamarin.Forms.Layout`1" />
+ <altmember cref="T:Xamarin.Forms.ScrollView" />
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected Layout ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Intitializes a new <see cref="T:Xamarin.Forms.Layout" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ForceLayout">
+ <MemberSignature Language="C#" Value="public void ForceLayout ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void ForceLayout() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Forces a layout cycle on the element and all of its descendants.</summary>
+ <remarks>
+ <para>Calling ForceLayout frequently can have negative impacts on performance.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetSizeRequest">
+ <MemberSignature Language="C#" Value="public override sealed Xamarin.Forms.SizeRequest GetSizeRequest (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance valuetype Xamarin.Forms.SizeRequest GetSizeRequest(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use Measure")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">The available width that a parent Layout can allocate to a child. Value will be between 0 and double.PositiveInfinity.</param>
+ <param name="heightConstraint">The available height that a parent Layout can allocate to a child. Value will be between 0 and double.PositiveInfinity.</param>
+ <summary>Returns the <see cref="T:Xamarin.Forms.SizeRequest" /> of the Layout. Calling this method begins the measure pass of a layout cycle.</summary>
+ <returns>A <see cref="T:Xamarin.Forms.SizeRequest" /> which contains a requested size and a minimum size.</returns>
+ <remarks>
+ <para>
+ Calling GetSizeRequest causes a measure pass to occur for the subtree of elements it is called on. It is ideal to only call GetSizeRequest when needed as excessive calls can negatively impact the performance of the app. Overriding GetSizeRequest should only be done if the developer wants to ignore Width/HeightRequest. More likely a subclass would wish to override <see cref="M:Xamarin.Forms.VisualElement.OnSizeRequest (double, double)" />.
+ </para>
+ </remarks>
+ <altmember cref="M:Xamarin.Forms.OnSizeRequest (double, double)" />
+ </Docs>
+ </Member>
+ <Member MemberName="InvalidateLayout">
+ <MemberSignature Language="C#" Value="protected virtual void InvalidateLayout ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void InvalidateLayout() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.2.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invalidates the current layout.</summary>
+ <remarks>Calling this method will invalidate the measure and triggers a new layout cycle.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsClippedToBounds">
+ <MemberSignature Language="C#" Value="public bool IsClippedToBounds { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsClippedToBounds" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value which determines if the Layout should clip its children to its bounds.</summary>
+ <value>
+ <see langword="true" /> if the Layout is clipped; otherwise, <see langword="false" />. The default value is <see langword="false" />.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsClippedToBoundsProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsClippedToBoundsProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsClippedToBoundsProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.Layout.IsClippedToBounds" /> bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler LayoutChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler LayoutChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs at the end of a layout cycle if any of the child element's <see cref="P:Xamarin.Forms.VisualElement.Bounds" /> have changed.</summary>
+ <remarks>
+ <para>Developers wishing to implement animations may wish to begin them at the end of a LayoutChanged event.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutChildIntoBoundingRegion">
+ <MemberSignature Language="C#" Value="public static void LayoutChildIntoBoundingRegion (Xamarin.Forms.VisualElement child, Xamarin.Forms.Rectangle region);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void LayoutChildIntoBoundingRegion(class Xamarin.Forms.VisualElement child, valuetype Xamarin.Forms.Rectangle region) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="child" Type="Xamarin.Forms.VisualElement" />
+ <Parameter Name="region" Type="Xamarin.Forms.Rectangle" />
+ </Parameters>
+ <Docs>
+ <param name="child">The child element to be positioned.</param>
+ <param name="region">The bounding region in which the child should be positioned.</param>
+ <summary>Positions a child element into a bounding region while respecting the child elements <see cref="P:Xamarin.Forms.VisualElement.HorizontalOptions" /> and <see cref="P:Xamarin.Forms.VisualElement.VerticalOptions" />.</summary>
+ <remarks>This method is called in the layout cycle after the general regions for each child have been calculated. This method will handle positioning the element relative to the bounding region given if the bounding region given is larger than the child's desired size.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutChildren">
+ <MemberSignature Language="C#" Value="protected abstract void LayoutChildren (double x, double y, double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void LayoutChildren(float64 x, float64 y, float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">A value representing the x coordinate of the child region bounding box.</param>
+ <param name="y">A value representing the y coordinate of the child region bounding box.</param>
+ <param name="width">A value representing the width of the child region bounding box.</param>
+ <param name="height">A value representing the height of the child region bounding box.</param>
+ <summary>Positions and sizes the children of a Layout.</summary>
+ <remarks>Implementors wishing to change the default behavior of a Layout should override this method. It is suggested to still call the base method and modify its calculated results.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LowerChild">
+ <MemberSignature Language="C#" Value="public void LowerChild (Xamarin.Forms.View view);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void LowerChild(class Xamarin.Forms.View view) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.View" />
+ </Parameters>
+ <Docs>
+ <param name="view">The view to lower in the visual stack.</param>
+ <summary>Sends a child to the back of the visual stack.</summary>
+ <remarks>Children are internally stored in visual stack order. This means that raising or lowering a child also changes the order in which the children are enumerated.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnChildMeasureInvalidated">
+ <MemberSignature Language="C#" Value="protected virtual void OnChildMeasureInvalidated ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnChildMeasureInvalidated() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invoked whenever a child of the layout has emitted <see cref="E:Xamarin.Forms.VisualElement.MeaureInvalidated" />. Implement this method to add class handling for this event.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnChildMeasureInvalidated">
+ <MemberSignature Language="C#" Value="protected void OnChildMeasureInvalidated (object sender, EventArgs e);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig instance void OnChildMeasureInvalidated(object sender, class System.EventArgs e) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sender" Type="System.Object" />
+ <Parameter Name="e" Type="System.EventArgs" />
+ </Parameters>
+ <Docs>
+ <param name="sender">The child element whose preferred size changed.</param>
+ <param name="e">The event data.</param>
+ <summary>Invoked whenever a child of the layout has emitted <see cref="E:Xamarin.Forms.VisualElement.MeaureInvalidated" />. Implement this method to add class handling for this event.</summary>
+ <remarks>This method has a default implementation and and application developers must call the base implementation.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeAllocated">
+ <MemberSignature Language="C#" Value="protected override void OnSizeAllocated (double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnSizeAllocated(float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="width">The new width of the element.</param>
+ <param name="height">The new height of the element.</param>
+ <summary>This method is called when the size of the element is set during a layout cycle. This method is called directly before the <see cref="E:Xamarin.Forms.VisualElement.SizeChanged" /> event is emitted. Implement this method to add class handling for this event.</summary>
+ <remarks>This method has a default implementation which triggers the layout cycle of the Layout to begin.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Padding">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Thickness Padding { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Thickness Padding" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Thickness</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the inner padding of the Layout.</summary>
+ <value>The Thickness values for the layout. The default value is a Thickness with all values set to 0.</value>
+ <remarks>
+ <para>
+ The padding is the space between the bounds of a layout and the bounding region into which its children should be arranged into.
+ </para>
+ <para>
+ The following example shows setting the padding of a Layout to inset its children.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+ var stackLayout = new StackLayout {
+ Padding = new Thickness (10, 10, 10, 20),
+ Children = {
+ new Label {Text = "Hello"},
+ new Label {Text = "World"}
+ }
+ }
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PaddingProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty PaddingProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty PaddingProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Padding bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RaiseChild">
+ <MemberSignature Language="C#" Value="public void RaiseChild (Xamarin.Forms.View view);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void RaiseChild(class Xamarin.Forms.View view) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.View" />
+ </Parameters>
+ <Docs>
+ <param name="view">The view to raise in the visual stack.</param>
+ <summary>Sends a child to the front of the visual stack.</summary>
+ <remarks>Children are internally stored in visual stack order. This means that raising or lowering a child also changes the order in which they are enumerated.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ShouldInvalidateOnChildAdded">
+ <MemberSignature Language="C#" Value="protected virtual bool ShouldInvalidateOnChildAdded (Xamarin.Forms.View child);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance bool ShouldInvalidateOnChildAdded(class Xamarin.Forms.View child) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="child" Type="Xamarin.Forms.View" />
+ </Parameters>
+ <Docs>
+ <param name="child">To be added.</param>
+ <summary>When implemented, should return <see langword="true" /> if <paramref name="child" /> should call <see cref="M:Xamarin.Forms.VisualElement.InvalidateMeasure" />, and to return <see langword="false" /> if it should not.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ShouldInvalidateOnChildRemoved">
+ <MemberSignature Language="C#" Value="protected virtual bool ShouldInvalidateOnChildRemoved (Xamarin.Forms.View child);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance bool ShouldInvalidateOnChildRemoved(class Xamarin.Forms.View child) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="child" Type="Xamarin.Forms.View" />
+ </Parameters>
+ <Docs>
+ <param name="child">To be added.</param>
+ <summary>When implemented, should return <see langword="true" /> if <paramref name="child" /> should call <see cref="M:Xamarin.Forms.VisualElement.InvalidateMeasure" /> when it is removed, and to return <see langword="false" /> if it should not.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="UpdateChildrenLayout">
+ <MemberSignature Language="C#" Value="protected void UpdateChildrenLayout ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig instance void UpdateChildrenLayout() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Instructs the layout to relayout all of its children.</summary>
+ <remarks>This method starts a new layout cycle for the layout. Invoking this method frequently can negatively impact performance.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.ILayoutController.Children">
+ <MemberSignature Language="C#" Value="System.Collections.Generic.IReadOnlyList&lt;Xamarin.Forms.Element&gt; Xamarin.Forms.ILayoutController.Children { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IReadOnlyList`1&lt;class Xamarin.Forms.Element&gt; Xamarin.Forms.ILayoutController.Children" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IReadOnlyList&lt;Xamarin.Forms.Element&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Internal.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/LayoutAlignment.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/LayoutAlignment.xml
new file mode 100644
index 00000000..4c5835ef
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/LayoutAlignment.xml
@@ -0,0 +1,108 @@
+<Type Name="LayoutAlignment" FullName="Xamarin.Forms.LayoutAlignment">
+ <TypeSignature Language="C#" Value="public enum LayoutAlignment" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed LayoutAlignment extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Flags</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Values that represent LayoutAlignment.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Center">
+ <MemberSignature Language="C#" Value="Center" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.LayoutAlignment Center = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LayoutAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The center of an alignment.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="End">
+ <MemberSignature Language="C#" Value="End" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.LayoutAlignment End = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LayoutAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The end of an alignment. Usually the Bottom or Right.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Fill">
+ <MemberSignature Language="C#" Value="Fill" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.LayoutAlignment Fill = int32(3)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LayoutAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Fill the entire area if possible.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Start">
+ <MemberSignature Language="C#" Value="Start" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.LayoutAlignment Start = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LayoutAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The start of an alignment. Usually the Top or Left.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/LayoutOptions.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/LayoutOptions.xml
new file mode 100644
index 00000000..f230cd29
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/LayoutOptions.xml
@@ -0,0 +1,265 @@
+<Type Name="LayoutOptions" FullName="Xamarin.Forms.LayoutOptions">
+ <TypeSignature Language="C#" Value="public struct LayoutOptions" />
+ <TypeSignature Language="ILAsm" Value=".class public sequential ansi sealed beforefieldinit LayoutOptions extends System.ValueType" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.ValueType</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.LayoutOptionsConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A struct whose static members define various alignment and expansion options.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public LayoutOptions (Xamarin.Forms.LayoutAlignment alignment, bool expands);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(valuetype Xamarin.Forms.LayoutAlignment alignment, bool expands) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="alignment" Type="Xamarin.Forms.LayoutAlignment" />
+ <Parameter Name="expands" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="alignment">An alignment value.</param>
+ <param name="expands">Whether or not an element will expand to fill available space in its parent.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.LayoutOptions" /> object with <paramref name="alignment" /> and <paramref name="expands" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Alignment">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.LayoutAlignment Alignment { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.LayoutAlignment Alignment" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LayoutAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that indicates how an element will be aligned.</summary>
+ <value>The <see cref="T:Xamarin.Forms.LayoutAlignment" /> flags that describe the behavior of an element.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Center">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.LayoutOptions Center;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.LayoutOptions Center" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LayoutOptions</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.LayoutOptions" /> structure that describes an element that is centered and does not expand.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CenterAndExpand">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.LayoutOptions CenterAndExpand;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.LayoutOptions CenterAndExpand" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LayoutOptions</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.LayoutOptions" /> structure that describes an element that is centered and expands.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="End">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.LayoutOptions End;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.LayoutOptions End" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LayoutOptions</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.LayoutOptions" /> structure that describes an element that appears at the end of its parent and does not expand.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="EndAndExpand">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.LayoutOptions EndAndExpand;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.LayoutOptions EndAndExpand" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LayoutOptions</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.LayoutOptions" /> object that describes an element that appears at the end of its parent and expands.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Expands">
+ <MemberSignature Language="C#" Value="public bool Expands { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool Expands" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that indicates whether or not the element that is described by this <see cref="T:Xamarin.Forms.LayoutOptions" /> structure will occupy the largest space that its parent will give to it.</summary>
+ <value>Whether or not the element that is described by this <see cref="T:Xamarin.Forms.LayoutOptions" /> structure will occupy the largest space that its parent will give it. <see langword="true" /> if the element will occupy the largest space the parent will give to it. <see langword="false" /> if the element will be as compact as it can be.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Fill">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.LayoutOptions Fill;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.LayoutOptions Fill" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LayoutOptions</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.LayoutOptions" /> stucture that describes an element that has no padding around itself and does not expand.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FillAndExpand">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.LayoutOptions FillAndExpand;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.LayoutOptions FillAndExpand" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LayoutOptions</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.LayoutOptions" /> structure that describes an element that has no padding around itself and expands.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Start">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.LayoutOptions Start;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.LayoutOptions Start" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LayoutOptions</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.LayoutOptions" /> structure that describes an element that appears at the start of its parent and does not expand.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="StartAndExpand">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.LayoutOptions StartAndExpand;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.LayoutOptions StartAndExpand" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LayoutOptions</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.LayoutOptions" /> structure that describes an element that appears at the start of its parent and expands.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/LayoutOptionsConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/LayoutOptionsConverter.xml
new file mode 100644
index 00000000..89423c59
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/LayoutOptionsConverter.xml
@@ -0,0 +1,97 @@
+<Type Name="LayoutOptionsConverter" FullName="Xamarin.Forms.LayoutOptionsConverter">
+ <TypeSignature Language="C#" Value="public sealed class LayoutOptionsConverter : Xamarin.Forms.TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit LayoutOptionsConverter extends Xamarin.Forms.TypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Class that takes a string representation of a <see cref="T:Xamarin.Forms.LayoutOptions" /> and returns a corresponding <see cref="T:Xamarin.Forms.LayoutOptions" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public LayoutOptionsConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.LayoutOptions" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">A type to query.</param>
+ <summary>Returns <see langword="true" /> if the converter can create and return a <see cref="T:Xamarin.Forms.LayoutOptions" /> for items of the specified source type. Otherwise, <see langword="false" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Creates and returns a <see cref="T:Xamarin.Forms.LayoutOptions" /> for the specified <paramref name="value" /> and <paramref name="culture" />.</summary>
+ <returns>A <see cref="T:Xamarin.Forms.LayoutOptions" /> for the specified <paramref name="value" /> and <paramref name="culture" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Returns a <see cref="T:Xamarin.Forms.LayoutOptions" /> for a valid layout options string.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Layout`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Layout`1.xml
new file mode 100644
index 00000000..0f9adbb2
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Layout`1.xml
@@ -0,0 +1,213 @@
+<Type Name="Layout&lt;T&gt;" FullName="Xamarin.Forms.Layout&lt;T&gt;">
+ <TypeSignature Language="C#" Value="public abstract class Layout&lt;T&gt; : Xamarin.Forms.Layout, Xamarin.Forms.IViewContainer&lt;T&gt; where T : View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit Layout`1&lt;(class Xamarin.Forms.View) T&gt; extends Xamarin.Forms.Layout implements class Xamarin.Forms.IViewContainer`1&lt;!T&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="T">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Layout</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IViewContainer&lt;T&gt;</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Children")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <typeparam name="T">The subclass of <see cref="T:Xamarin.Forms.View" /> the layout contains.</typeparam>
+ <summary>A base implementation of a layout with undefined behavior and multiple children.</summary>
+ <remarks>
+ <para>
+ <see cref="T:Xamarin.Forms.Layout`1" />s contain <see cref="P:Xamarin.Forms.Layout`1.Children" /> that are of the type <c>T</c> with which the <see cref="T:Xamarin.Forms.Layout`1" /> was specified. This <c>T</c> must be of type <see cref="T:Xamarin.Forms.View" />. Since <see cref="T:Xamarin.Forms.Layout" />s are subclasses of <see cref="T:Xamarin.Forms.View" />, this means that layouts may be nested, contain scrolling regions, etc.
+ </para>
+ <para>The following image shows the relationship between <see cref="T:Xamarin.Forms.View" />, <see cref="T:Xamarin.Forms.Layout" />, <see cref="T:Xamarin.Forms.Layout`1" />, and important subtypes.</para>
+ <para>
+ <img href="Element.Hierarchy.png" />
+ </para>
+ <para>
+ The following example shows adding and removing elements from a layout.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+ void UpdateItems (Layout<View> layout, IEnumerable newItems)
+ {
+ layout.Children.Clear ();
+ foreach (var item in newItems) {
+ layout.Children.Add (item);
+ }
+ }
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected Layout ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Provides the base initialization for objects derived from the Layout&lt;T&gt; class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Children">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;T&gt; Children { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;!T&gt; Children" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;T&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets an IList&lt;View&gt; of child element of the Layout.</summary>
+ <value>A IList&lt;View&gt;. The default is an empty list.</value>
+ <remarks>
+ <para>
+ The Children collection of a Layout contains all the children added throught the public add/remove interface. Internal children will not be exposed through this collection.
+ </para>
+ <para>
+ The following shows the creation of a layout, setting a property, and adding the children in the object initializer.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+ var stack = new StackLayout {
+ Spacing = 20,
+ Children = {
+ new Label {Text = "Hello World!"},
+ new Button {Text = "Click Me!"}
+ }
+ };
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnAdded">
+ <MemberSignature Language="C#" Value="protected virtual void OnAdded (T view);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnAdded(!T view) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="view">The view which was added.</param>
+ <summary>Invoked when a child is added to the layout. Implement this method to add class handling for this event.</summary>
+ <remarks>This method is different from <see cref="M:Xamarin.Forms.Element.OnChildAdded (Xamarin.Forms.Element element)" /> in that it provides a typed child consistent with the type of the Layout&lt;T&gt;.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnChildAdded">
+ <MemberSignature Language="C#" Value="protected override void OnChildAdded (Xamarin.Forms.Element child);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnChildAdded(class Xamarin.Forms.Element child) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="child" Type="Xamarin.Forms.Element" />
+ </Parameters>
+ <Docs>
+ <param name="child">To be added.</param>
+ <summary>Application developers can override this method to respond when a child is added.</summary>
+ <remarks>Application developers who override this method must call base.OnChildAdded before performing any other actions in their override.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnChildRemoved">
+ <MemberSignature Language="C#" Value="protected override void OnChildRemoved (Xamarin.Forms.Element child);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnChildRemoved(class Xamarin.Forms.Element child) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="child" Type="Xamarin.Forms.Element" />
+ </Parameters>
+ <Docs>
+ <param name="child">To be added.</param>
+ <summary>Application developers can override this method to respond when a child is removed.</summary>
+ <remarks>Application developers who override this method must call base.OnChildRemoved before performing any other actions in their override.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnRemoved">
+ <MemberSignature Language="C#" Value="protected virtual void OnRemoved (T view);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnRemoved(!T view) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="view">The view which was removed.</param>
+ <summary>Invoked when a child is removed from the layout. Implement this method to add class handling for this event.</summary>
+ <remarks>This method is different from <see cref="M:Xamarin.Forms.Element.OnChildRemoved (Xamarin.Forms.Element element)" /> in that it provides a typed child consistent with the type of the Layout&lt;T&gt;.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/LineBreakMode.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/LineBreakMode.xml
new file mode 100644
index 00000000..ebaac6a7
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/LineBreakMode.xml
@@ -0,0 +1,143 @@
+<Type Name="LineBreakMode" FullName="Xamarin.Forms.LineBreakMode">
+ <TypeSignature Language="C#" Value="public enum LineBreakMode" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed LineBreakMode extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumeration specifying various options for line breaking.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="CharacterWrap">
+ <MemberSignature Language="C#" Value="CharacterWrap" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.LineBreakMode CharacterWrap = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LineBreakMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Wrap at character boundaries.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="HeadTruncation">
+ <MemberSignature Language="C#" Value="HeadTruncation" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.LineBreakMode HeadTruncation = int32(3)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LineBreakMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Truncate the head of text.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="MiddleTruncation">
+ <MemberSignature Language="C#" Value="MiddleTruncation" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.LineBreakMode MiddleTruncation = int32(5)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LineBreakMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Truncate the middle of text. This may be done, for example, by replacing it with an ellipsis.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="NoWrap">
+ <MemberSignature Language="C#" Value="NoWrap" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.LineBreakMode NoWrap = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LineBreakMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Do not wrap text.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="TailTruncation">
+ <MemberSignature Language="C#" Value="TailTruncation" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.LineBreakMode TailTruncation = int32(4)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LineBreakMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Truncate the tail of text.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="WordWrap">
+ <MemberSignature Language="C#" Value="WordWrap" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.LineBreakMode WordWrap = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LineBreakMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Wrap at word boundaries.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ListView.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ListView.xml
new file mode 100644
index 00000000..ba37658e
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ListView.xml
@@ -0,0 +1,1531 @@
+<Type Name="ListView" FullName="Xamarin.Forms.ListView">
+ <TypeSignature Language="C#" Value="public class ListView : Xamarin.Forms.ItemsView&lt;Xamarin.Forms.Cell&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ListView extends Xamarin.Forms.ItemsView`1&lt;class Xamarin.Forms.Cell&gt; implements class Xamarin.Forms.IElementController, class Xamarin.Forms.IViewController, class Xamarin.Forms.IVisualElementController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.ItemsView&lt;Xamarin.Forms.Cell&gt;</BaseTypeName>
+ <BaseTypeArguments>
+ <BaseTypeArgument TypeParamName="TVisual">Xamarin.Forms.Cell</BaseTypeArgument>
+ </BaseTypeArguments>
+ </Base>
+ <Interfaces>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._ListViewRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>An <see cref="T:Xamarin.Forms.ItemsView" /> that displays a collection of data as a vertical list.</summary>
+ <remarks>
+ <para>
+ <img href="ListView.TripleScreenShot.png" />
+ </para>
+ <para>The following example shows a basic use:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+using System;
+using System.Collections.Generic;
+using Xamarin.Forms;
+
+namespace FormsGallery
+{
+class ListViewDemoPage : ContentPage
+ {
+ class Person
+ {
+ public Person(string name, DateTime birthday, Color favoriteColor)
+ {
+ this.Name = name;
+ this.Birthday = birthday;
+ this.FavoriteColor = favoriteColor;
+ }
+
+ public string Name { private set; get; }
+
+ public DateTime Birthday { private set; get; }
+
+ public Color FavoriteColor { private set; get; }
+ };
+
+ public ListViewDemoPage()
+ {
+ Label header = new Label
+ {
+ Text = "ListView",
+ FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ // Define some data.
+ List<Person> people = new List<Person>
+ {
+ new Person("Abigail", new DateTime(1975, 1, 15), Color.Aqua),
+ new Person("Bob", new DateTime(1976, 2, 20), Color.Black),
+ // ...etc.,...
+ new Person("Yvonne", new DateTime(1987, 1, 10), Color.Purple),
+ new Person("Zachary", new DateTime(1988, 2, 5), Color.Red)
+ };
+
+ // Create the ListView.
+ ListView listView = new ListView
+ {
+ // Source of data items.
+ ItemsSource = people,
+
+ // Define template for displaying each item.
+ // (Argument of DataTemplate constructor is called for
+ // each item; it must return a Cell derivative.)
+ ItemTemplate = new DataTemplate(() =>
+ {
+ // Create views with bindings for displaying each property.
+ Label nameLabel = new Label();
+ nameLabel.SetBinding(Label.TextProperty, "Name");
+
+ Label birthdayLabel = new Label();
+ birthdayLabel.SetBinding(Label.TextProperty,
+ new Binding("Birthday", BindingMode.OneWay,
+ null, null, "Born {0:d}"));
+
+ BoxView boxView = new BoxView();
+ boxView.SetBinding(BoxView.ColorProperty, "FavoriteColor");
+
+ // Return an assembled ViewCell.
+ return new ViewCell
+ {
+ View = new StackLayout
+ {
+ Padding = new Thickness(0, 5),
+ Orientation = StackOrientation.Horizontal,
+ Children =
+ {
+ boxView,
+ new StackLayout
+ {
+ VerticalOptions = LayoutOptions.Center,
+ Spacing = 0,
+ Children =
+ {
+ nameLabel,
+ birthdayLabel
+ }
+ }
+ }
+ }
+ };
+ })
+ };
+
+ // Accomodate iPhone status bar.
+ this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
+
+ // Build the page.
+ this.Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ listView
+ }
+ };
+ }
+ }
+}
+
+]]></code>
+ </example>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.ListView" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <!-- TODO: Ask about these bindings.
+ <item>
+ <term>GroupDisplayBinding</term>
+ <description><para></para></description>
+ </item>
+ <item>
+ <term>GroupHeaderTemplate</term>
+ <description><para></para></description>
+ </item>
+ <item>
+ <item>
+ <term>GroupShortNameBinding</term>
+ <description><para></para></description>
+ </item>-->
+ <item>
+ <term>HasUnevenRows</term>
+ <description>
+ <para>
+ <c>true</c> or <c>false</c>, to indicate whether the items in the list all have the same height.</para>
+ </description>
+ </item>
+ <item>
+ <term>IsGroupingEnabled</term>
+ <description>
+ <para>
+ <c>true</c> or <c>false</c>, to indicate whether grouping is enabled.</para>
+ </description>
+ </item>
+ <item>
+ <term>RowHeight</term>
+ <description>
+ <para>An integer that describes the height of the items in the list. This is ignored if <c>HasUnevenRows</c> is <c>true</c>.</para>
+ </description>
+ </item>
+ <!-- TODO: Named item? Index? What works?
+ <item>
+ <term>SelectedItem</term>
+ <description><para></para></description>
+ </item>-->
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ListView ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates and initializes a new instance of the <see cref="T:Xamarin.Forms.ListView" /> class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ListView (Xamarin.Forms.ListViewCachingStrategy cachingStrategy);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(valuetype Xamarin.Forms.ListViewCachingStrategy cachingStrategy) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="cachingStrategy" Type="Xamarin.Forms.ListViewCachingStrategy" />
+ </Parameters>
+ <Docs>
+ <param name="cachingStrategy">A value that indicates how the List View should manage memory when displaying data items using a data template.</param>
+ <summary>Creates and initializes a new instance of the <see cref="T:Xamarin.Forms.ListView" /> class, with the specified caching strategy.</summary>
+ <remarks>
+ <para>For memory and performance reasons, application developers should strongly prefer <see cref="F:Xamarin.Forms.ListViewCachingStrategy.RecycleElement" />, when possible. See <see cref="T:Xamarin.Forms.ListViewCachingStrategy" /> for more details.</para>
+ <para>
+ <block type="note">When devolopers specify <see cref="F:Xamarin.Forms.ListViewCachingStrategy.RecycleElement" />, <c>OnElementChanged</c> events are not raised when cells are recycled. Instead, the cell is retained and its property values change when the binding context is updated to that of an available cell, <c>OnElementPropertyChanged</c> events are raised. Application developers should remember to listen for the correct events, and should note that their renderers will need to be updated if the default behavior changes to <see cref="F:Xamarin.Forms.ListViewCachingStrategy.RecycleElement" /> in a future release. </block>
+ </para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BeginRefresh">
+ <MemberSignature Language="C#" Value="public void BeginRefresh ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void BeginRefresh() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Enters the refreshing state by setting the <see cref="P:Xamarin.Forms.ListView.IsRefreshing" /> property to <see langword="true" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateDefault">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.Cell CreateDefault (object item);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance class Xamarin.Forms.Cell CreateDefault(object item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Cell</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="item">The item to create a default visual for.</param>
+ <summary>Creates an instance of the default visual representation of an item.</summary>
+ <returns>
+ A <see cref="T:Xamarin.Forms.TextCell" /> instance with its text set to the string representation of the object (<see cref="M:System.Object.ToString" />).
+ </returns>
+ <remarks>
+ <para>
+ This method is called by the templating system when <see cref="P:Xamarin.Forms.ListView.ItemTemplate" /> is <see langword="null" />.
+ </para>
+ <para>
+ The <see cref="P:Xamarin.Forms.BindableObject.BindingContext" /> of the returned object will automatically be set to <paramref name="item" />, there is no
+ need to set it yourself. If you do, it will be overridden.
+ </para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="EndRefresh">
+ <MemberSignature Language="C#" Value="public void EndRefresh ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void EndRefresh() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Exits the refreshing state by setting the <see cref="P:Xamarin.Forms.ListView.IsRefreshing" /> property to <see langword="false" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Footer">
+ <MemberSignature Language="C#" Value="public object Footer { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Footer" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the string, binding, or view that will be displayed at the bottom of the list view.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FooterProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FooterProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FooterProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ListView.Footer" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FooterTemplate">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.DataTemplate FooterTemplate { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.DataTemplate FooterTemplate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.DataTemplate</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a data template to use to format a data object for display at the bottom of the list view.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FooterTemplateProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FooterTemplateProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FooterTemplateProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ListView.FooterTemplate" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GroupDisplayBinding">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.BindingBase GroupDisplayBinding { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.BindingBase GroupDisplayBinding" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindingBase</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the binding to use for display the group header.</summary>
+ <value>The <see cref="T:Xamarin.Forms.BindingBase" /> instance to apply to grouped lists, or <see cref="null" />.</value>
+ <remarks>
+ <para>
+ This binding can be used to simply set a the text of the group headers without defining a full template and uses the default visuals
+ of the platform to display it. The binding is applied to the <see cref="T:System.Collections.IEnumerable" /> of the group.
+ </para>
+ <para>
+ This property is mutually exclusive with <see cref="P:Xamarin.Forms.ListView.GroupHeaderTemplate" /> property. Setting it will set
+ <see cref="P:Xamarin.Forms.ListView.GroupHeaderTemplate" /> to <see langword="null" />.
+ </para>
+ </remarks>
+ <example>
+ <para>This example shows an alphabetized list of people, grouped by first initial with the display binding set.</para>
+ <code lang="C#"><![CDATA[
+ class Person
+ {
+ public string FullName
+ {
+ get;
+ set;
+ }
+
+ public string Address
+ {
+ get;
+ set;
+ }
+ }
+ ]]></code>
+ <code lang="C#"><![CDATA[
+ class Group : ObservableCollection<Person>
+ {
+ public Group (string firstInitial)
+ {
+ FirstInitial = firstInitial;
+ }
+
+ public string FirstInitial
+ {
+ get;
+ private set;
+ }
+ }
+ ]]></code>
+ <code lang="C#"><![CDATA[
+ ListView CreateListView()
+ {
+ var listView = new ListView {
+ IsGroupingEnabled = true,
+ GroupDisplayBinding = new Binding ("FirstInitial"),
+ GroupShortNameBinding = new Binding ("FirstInitial")
+ };
+
+ var template = new DataTemplate (typeof (TextCell));
+ template.SetBinding (TextCell.TextProperty, "FullName");
+ template.SetBinding (TextCell.DetailProperty, "Address");
+
+ itemsView.ItemTemplate = template;
+ itemsView.ItemsSource = new[] {
+ new Group ("C") {
+ new Person { FullName = "Caprice Nave" }
+ },
+
+ new Group ("J") {
+ new Person { FullName = "James Smith", Address = "404 Nowhere Street" },
+ new Person { FullName = "John Doe", Address = "404 Nowhere Ave" }
+ }
+ };
+ }
+ ]]></code>
+ </example>
+ </Docs>
+ </Member>
+ <Member MemberName="GroupDisplayBindingProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty GroupDisplayBindingProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty GroupDisplayBindingProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.ListView.GroupDisplayBinding" /> property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GroupHeaderTemplate">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.DataTemplate GroupHeaderTemplate { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.DataTemplate GroupHeaderTemplate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.DataTemplate</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a <see cref="T:Xamarin.Forms.DataTemplate" /> for group headers.</summary>
+ <value>The <see cref="T:Xamarin.Forms.DataTemplate" /> for group headers, or <see langword="null" />.</value>
+ <remarks>
+ <para>
+ Use this property to define a template for a <see cref="T:Xamarin.Forms.Cell" /> that will be used as the header for groups in this
+ <see cref="T:Xamarin.Forms.ListView" />. The <see cref="P:Xamarin.BindableObject.BindingContext" /> will be the <see cref="T:System.Collections.IEnumerable" />
+ for each group.
+ </para>
+ <para>
+ GroupHeaderTemplate is mutually exclusive with <see cref="P:Xamarin.Forms.ListView.GroupDisplayBinding" />. Setting this property
+ will set <see cref="P:Xamarin.Forms.ListView.GroupDisplayBinding" /> to <see langword="null" />.
+ </para>
+ <para>Empty groups will still display a group header.</para>
+ </remarks>
+ <altmember cref="P:Xamarin.Forms.ListView.ItemsSource" />
+ <altmember cref="P:Xamarin.Forms.ListView.GroupDisplayBinding" />
+ <altmember cref="P:Xamarin.Forms.ListView.IsGroupingEnabled" />
+ </Docs>
+ </Member>
+ <Member MemberName="GroupHeaderTemplateProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty GroupHeaderTemplateProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty GroupHeaderTemplateProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.ListView.GroupHeaderTemplate" /> property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GroupShortNameBinding">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.BindingBase GroupShortNameBinding { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.BindingBase GroupShortNameBinding" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindingBase</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a binding for the name to display in grouped jump lists.</summary>
+ <value>The <see cref="T:Xamarin.Forms.BindingBase" /> instance to apply to grouped lists, or <see langword="null" />.</value>
+ <remarks>
+ <para>
+ When grouping items in a <see cref="T:Xamarin.Forms.ListView" />, it is often useful to have jump lists to jump to specific
+ sections in the list. For example, in an alphabetically grouped lists, the jump list would be the the letter of each group.
+ This binding is applied against the <see cref="T:System.Collections.IEnumerable" /> of each group to select the short name to display
+ in the jump list.
+ </para>
+ <para>
+ Note: On Android, there is no displayed jump list.
+ </para>
+ </remarks>
+ <example>
+ <para>This example shows an alphabetized list of people, grouped by first initial with the short name binding set.</para>
+ <code lang="C#"><![CDATA[
+class Person
+{
+ public string FullName
+ {
+ get;
+ set;
+ }
+
+ public string Address
+ {
+ get;
+ set;
+ }
+}
+ ]]></code>
+ <code lang="C#"><![CDATA[
+class Group : ObservableCollection<Person>
+{
+ public Group (string firstInitial)
+ {
+ FirstInitial = firstInitial;
+ }
+
+ public string FirstInitial
+ {
+ get;
+ private set;
+ }
+}
+ ]]></code>
+ <code lang="C#"><![CDATA[
+ListView CreateListView()
+{
+ var listView = new ListView {
+ IsGroupingEnabled = true,
+ GroupDisplayBinding = new Binding ("FirstInitial"),
+ GroupShortNameBinding = new Binding ("FirstInitial")
+ };
+
+ var template = new DataTemplate (typeof (TextCell));
+ template.SetBinding (TextCell.TextProperty, "FullName");
+ template.SetBinding (TextCell.DetailProperty, "Address");
+
+ itemsView.ItemTemplate = template;
+ itemsView.ItemsSource = new[] {
+ new Group ("C") {
+ new Person { FullName = "Caprice Nave" }
+ },
+
+ new Group ("J") {
+ new Person { FullName = "James Smith", Address = "404 Nowhere Street" },
+ new Person { FullName = "John Doe", Address = "404 Nowhere Ave" }
+ }
+ };
+}
+ ]]></code>
+ </example>
+ </Docs>
+ </Member>
+ <Member MemberName="GroupShortNameBindingProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty GroupShortNameBindingProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty GroupShortNameBindingProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.ListView.GroupShortNameBinding" /> property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasUnevenRows">
+ <MemberSignature Language="C#" Value="public bool HasUnevenRows { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool HasUnevenRows" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a Boolean value that indicates whether this <see cref="T:Xamarin.Forms.ListView" /> element has uneven rows.</summary>
+ <value>
+ <see langword="true" /> if this <see cref="T:Xamarin.Forms.ListView" /> control has uneven rows. Otherwise, <see langword="false" /></value>
+ <remarks>
+ <para>Application developers will find that the easiest and least error-prone way to automatically size list view rows for content is: first, to set the <see cref="P:Xamarin.Forms.ListView.HasUnevenRows" /> property to <see langword="true" />; and, second, to either leave <see cref="P:Xamarin.Forms.ListView.RowHeight" /> at its default value of -1, or set it to -1 if it has been changed.</para>
+ <para>Application developers will find that the easiest and least error-prone way to set all rows to a constant size is to first set <see cref="P:Xamarin.Forms.ListView.HasUnevenRows" /> to <see langword="false" />, and then either: leave <see cref="P:Xamarin.Forms.ListView.RowHeight" /> at its default value of -1 (or set it back to that value if it has been changed) in order to get the default height for the system; or set the <see cref="P:Xamarin.Forms.ListView.RowHeight" /> property to the desired uniform row height.</para>
+ <para>A more detailed discussion follows, below.</para>
+ <para>When the app developer sets the <see cref="P:Xamarin.Forms.ListView.HasUnevenRows" /> property to <see langword="false" />, the behavior of the list view depends on the <see cref="P:Xamarin.Forms.ListView.RowHeight" /> property. First, if the developer sets the <see cref="P:Xamarin.Forms.ListView.RowHeight" /> property to a positive value, then all rows in the <see cref="T:Xamarin.Forms.ListView" />, irrespective of the height of their content, will be as tall as the specified <see cref="P:Xamarin.Forms.ListView.RowHeight" /> property value. Second, if the develper instead does not set the <see cref="P:Xamarin.Forms.ListView.RowHeight" /> property, or sets it to a nonpositive value, then all rows in the <see cref="T:Xamarin.Forms.ListView" />, irrespective of the height of their content, will have the default row height for the system.</para>
+ <para>When the app developer sets the <see cref="P:Xamarin.Forms.ListView.HasUnevenRows" /> property to <see langword="true" />, the behavior of the list view still depends on the <see cref="P:Xamarin.Forms.ListView.RowHeight" /> property. First, if the developer either does not set the <see cref="P:Xamarin.Forms.ListView.RowHeight" /> property or sets it to -1, list view items are autosized to fit their contents. This is the desired behavior and the intended use case for a <see cref="P:Xamarin.Forms.ListView.HasUnevenRows" /> value of <see langword="true" />, as noted above. Second, if the developer sets the <see cref="P:Xamarin.Forms.ListView.RowHeight" /> property to 0 or to a negative value other than -1, then all rows in the <see cref="T:Xamarin.Forms.ListView" /> will, irrespective of the height of their content, have the default height for the system. Third, and finally, if the developer sets <see cref="P:Xamarin.Forms.ListView.RowHeight" /> to a positive value, then all rows in the <see cref="T:Xamarin.Forms.ListView" /> will, irrespective of the height of their content, be as tall as <see cref="P:Xamarin.Forms.ListView.RowHeight" />, as if <see cref="P:Xamarin.Forms.ListView.HasUnevenRows" /> had been set to <see langword="true" />.
+ </para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasUnevenRowsProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HasUnevenRowsProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HasUnevenRowsProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.ListView.HasUnevenRowsProperty" /> property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Header">
+ <MemberSignature Language="C#" Value="public object Header { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Header" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the string, binding, or view that will be displayed at the top of the list view.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HeaderProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HeaderProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HeaderProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ListView.Header" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HeaderTemplate">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.DataTemplate HeaderTemplate { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.DataTemplate HeaderTemplate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.DataTemplate</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a data template to use to format a data object for display at the top of the list view.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HeaderTemplateProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HeaderTemplateProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HeaderTemplateProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ListView.HeaderTemplate" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsGroupingEnabled">
+ <MemberSignature Language="C#" Value="public bool IsGroupingEnabled { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsGroupingEnabled" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets whether or not grouping is enabled for <see cref="T:Xamarin.Forms.ListView" />.</summary>
+ <value>
+ <see langword="true" /> if grouping is enabled, <see langword="false" /> otherwise and by default.
+ </value>
+ <remarks>
+ </remarks>
+ <altmember cref="P:Xamarin.Forms.ListView.GroupDisplayBinding" />
+ <altmember cref="P:Xamarin.Forms.ListView.GroupHeaderTemplate" />
+ </Docs>
+ </Member>
+ <Member MemberName="IsGroupingEnabledProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsGroupingEnabledProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsGroupingEnabledProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.ListView.IsGroupingEnabledProperty" /> property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsPullToRefreshEnabled">
+ <MemberSignature Language="C#" Value="public bool IsPullToRefreshEnabled { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsPullToRefreshEnabled" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that tells whether the user can swipe down to cause the application to refresh.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsPullToRefreshEnabledProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsPullToRefreshEnabledProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsPullToRefreshEnabledProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ListView.IsPullToRefreshEnabled" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsRefreshing">
+ <MemberSignature Language="C#" Value="public bool IsRefreshing { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsRefreshing" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that tells whether the list view is currently refreshing.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsRefreshingProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsRefreshingProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsRefreshingProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ListView.IsRefreshing" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemAppearing">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ItemVisibilityEventArgs&gt; ItemAppearing;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ItemVisibilityEventArgs&gt; ItemAppearing" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ItemVisibilityEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs when the visual representation of an item is being added to the visual layout.</summary>
+ <remarks>This method is guaranteed to fire at some point before the element is on screen.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemDisappearing">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ItemVisibilityEventArgs&gt; ItemDisappearing;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ItemVisibilityEventArgs&gt; ItemDisappearing" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ItemVisibilityEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs when the visual representation of an item is being removed from the visual layout.</summary>
+ <remarks>This method is for virtualization usage only. It is not guaranteed to fire for all visible items when the List is removed from the screen. Additionally it fires during virtualization, which may not correspond directly with removal from the screen depending on the platform virtualization technique used.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemSelected">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.SelectedItemChangedEventArgs&gt; ItemSelected;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.SelectedItemChangedEventArgs&gt; ItemSelected" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.SelectedItemChangedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when a new item is selected.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemTapped">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ItemTappedEventArgs&gt; ItemTapped;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ItemTappedEventArgs&gt; ItemTapped" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ItemTappedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when an item is tapped.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeRequest">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance valuetype Xamarin.Forms.SizeRequest OnSizeRequest(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use OnMeasure")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">To be added.</param>
+ <param name="heightConstraint">To be added.</param>
+ <summary>Method that is called when a size request is made..</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RefreshCommand">
+ <MemberSignature Language="C#" Value="public System.Windows.Input.ICommand RefreshCommand { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Windows.Input.ICommand RefreshCommand" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Windows.Input.ICommand</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the command that is run when the list view enters the refreshing state.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RefreshCommandProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty RefreshCommandProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty RefreshCommandProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ListView.RefreshCommand" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Refreshing">
+ <MemberSignature Language="C#" Value="public event EventHandler Refreshing;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Refreshing" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the list view refreshes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RowHeight">
+ <MemberSignature Language="C#" Value="public int RowHeight { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 RowHeight" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that represents the height of a row.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RowHeightProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty RowHeightProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty RowHeightProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The backing store for the <see cref="P:Xamarin.Forms.ListView.RowHeightProperty" /> property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ScrollTo">
+ <MemberSignature Language="C#" Value="public void ScrollTo (object item, Xamarin.Forms.ScrollToPosition position, bool animated);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void ScrollTo(object item, valuetype Xamarin.Forms.ScrollToPosition position, bool animated) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ <Parameter Name="position" Type="Xamarin.Forms.ScrollToPosition" />
+ <Parameter Name="animated" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="item">The item from your <see cref="P:Xamarin.Forms.ListView.ItemsSource" /> to scroll to.</param>
+ <param name="position">How the item should be positioned on screen.</param>
+ <param name="animated">Whether or not the scroll should be animated.</param>
+ <summary>Scrolls the ListView to the <paramref name="item" />.</summary>
+ <remarks>
+ <para>A linear search is done for the item, so if the same reference appears multiple times in the list, the first item will be scrolled to. This includes if grouping is enabled.</para>
+ </remarks>
+ <exception cref="T:System.ArgumentException">
+ <paramref name="position" /> contains an invalid value for <see cref="T:Xamarin.Forms.ScrollToPosition" />.</exception>
+ </Docs>
+ </Member>
+ <Member MemberName="ScrollTo">
+ <MemberSignature Language="C#" Value="public void ScrollTo (object item, object group, Xamarin.Forms.ScrollToPosition position, bool animated);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void ScrollTo(object item, object group, valuetype Xamarin.Forms.ScrollToPosition position, bool animated) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ <Parameter Name="group" Type="System.Object" />
+ <Parameter Name="position" Type="Xamarin.Forms.ScrollToPosition" />
+ <Parameter Name="animated" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="item">The item from your <see cref="P:Xamarin.Forms.ListView.ItemsSource" /> to scroll to.</param>
+ <param name="group">The group from your <see cref="P:Xamarin.Forms.ListView.ItemsSource" /> to scroll to.</param>
+ <param name="position">How the item should be positioned on screen.</param>
+ <param name="animated">Whether or not the scroll should be animated.</param>
+ <summary>Scrolls the ListView to the <paramref name="item" /> in the <paramref name="group" /></summary>
+ <remarks>
+ <para>A linear search is done for the item, so if the same reference appears multiple times in the <paramref name="group" />, the first item will be scrolled to. The same item in a different group will be ignored.</para>
+ </remarks>
+ <exception cref="T:System.ArgumentException">
+ <paramref name="position" /> contains an invalid value for <see cref="T:Xamarin.Forms.ScrollToPosition" />.
+ </exception>
+ <exception cref="T:System.InvalidOperationException">
+ <see cref="P:Xamarin.Forms.ListView.IsGroupingEnabled" /> is <see langword="false" />.</exception>
+ </Docs>
+ </Member>
+ <Member MemberName="SelectedItem">
+ <MemberSignature Language="C#" Value="public object SelectedItem { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object SelectedItem" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the currently selected item from the <see cref="P:Xamarin.Forms.ListView.ItemsSource" />.</summary>
+ <value>The selected item or <see langword="null" /> if no item is selected.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SelectedItemProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty SelectedItemProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty SelectedItemProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.ListView.SelectedItemProperty" /> property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SeparatorColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color SeparatorColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color SeparatorColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the color of the bar that separates list items.</summary>
+ <value>To be added.</value>
+ <remarks>The default value is <c>Color.Default</c>. This property has no effect if <see cref="P:Xamarin.Forms.ListView.SeparatorVisibility" /> is <see langword="false" />.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SeparatorColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty SeparatorColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty SeparatorColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ListView.SeparatorColor" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SeparatorVisibility">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.SeparatorVisibility SeparatorVisibility { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.SeparatorVisibility SeparatorVisibility" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SeparatorVisibility</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that tells whether separators are visible between items.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SeparatorVisibilityProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty SeparatorVisibilityProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty SeparatorVisibilityProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ListView.SeparatorVisibility" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetupContent">
+ <MemberSignature Language="C#" Value="protected override void SetupContent (Xamarin.Forms.Cell content, int index);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void SetupContent(class Xamarin.Forms.Cell content, int32 index) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="content" Type="Xamarin.Forms.Cell" />
+ <Parameter Name="index" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="content">The cell to set up.</param>
+ <param name="index">The index of the cell in the list of items.</param>
+ <summary>Application developers override this method to register event handlers for list view items.</summary>
+ <remarks>
+ <para>Application developers must call <see cref="M:Xamarin.Forms.ListView.SetupContent(Xamarin.Forms.Cell, int)" /> before performing any other action when overriding this method.</para>
+ <block type="note">Application developers who override this method to allocate resources must override <see cref="M:Xamarin.Forms.ListView.UnhookContent(Xamarin.Forms.Cell)" /> in order to deallocate them.</block>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="UnhookContent">
+ <MemberSignature Language="C#" Value="protected override void UnhookContent (Xamarin.Forms.Cell content);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void UnhookContent(class Xamarin.Forms.Cell content) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="content" Type="Xamarin.Forms.Cell" />
+ </Parameters>
+ <Docs>
+ <param name="content">To be added.</param>
+ <summary>Application developers override this method to unregister event handlers for list view items that they registered in <see cref="M:Xamarin.Forms.ListView.SetupContent(Xamarin.Forms.Cell, int)" />.</summary>
+ <remarks>
+ <para>Application developers must call <see cref="M:Xamarin.Forms.ListView.UnhookContent(Xamarin.Forms.Cell, int)" /> before performing any other action when overriding this method.</para>
+ <block type="note">Application developers who override <see cref="M:Xamarin.Forms.ListView.SetupContent(Xamarin.Forms.Cell, int)" /> to allocate resources must override this method in order to deallocate them.</block>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.ICellVisibilityProxy.SendCellAppearing">
+ <MemberSignature Language="C#" Value="void ICellVisibilityProxy.SendCellAppearing (Xamarin.Forms.Cell cell);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.ICellVisibilityProxy.SendCellAppearing(class Xamarin.Forms.Cell cell) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="cell" Type="Xamarin.Forms.Cell" />
+ </Parameters>
+ <Docs>
+ <param name="cell">To be added.</param>
+ <summary>Raises the <see cref="E:Xamarin.Forms.ListView.ItemAppearing" /> event for <paramref name="cell" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.ICellVisibilityProxy.SendCellDisappearing">
+ <MemberSignature Language="C#" Value="void ICellVisibilityProxy.SendCellDisappearing (Xamarin.Forms.Cell cell);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.ICellVisibilityProxy.SendCellDisappearing(class Xamarin.Forms.Cell cell) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="cell" Type="Xamarin.Forms.Cell" />
+ </Parameters>
+ <Docs>
+ <param name="cell">To be added.</param>
+ <summary>Raises the <see cref="E:Xamarin.Forms.ListView.ItemDisappearing" /> event for <paramref name="cell" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IListViewController.FooterElement">
+ <MemberSignature Language="C#" Value="Xamarin.Forms.Element Xamarin.Forms.IListViewController.FooterElement { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Element Xamarin.Forms.IListViewController.FooterElement" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Element</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Internal.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IListViewController.HeaderElement">
+ <MemberSignature Language="C#" Value="Xamarin.Forms.Element Xamarin.Forms.IListViewController.HeaderElement { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Element Xamarin.Forms.IListViewController.HeaderElement" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Element</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Internal.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IListOrCarouselViewController.SendCellAppearing">
+ <MemberSignature Language="C#" Value="void IListOrCarouselViewController.SendCellAppearing (Xamarin.Forms.Cell cell);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IListOrCarouselViewController.SendCellAppearing(class Xamarin.Forms.Cell cell) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="cell" Type="Xamarin.Forms.Cell" />
+ </Parameters>
+ <Docs>
+ <param name="cell">To be added.</param>
+ <summary>Internal.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IListOrCarouselViewController.SendCellDisappearing">
+ <MemberSignature Language="C#" Value="void IListOrCarouselViewController.SendCellDisappearing (Xamarin.Forms.Cell cell);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IListOrCarouselViewController.SendCellDisappearing(class Xamarin.Forms.Cell cell) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="cell" Type="Xamarin.Forms.Cell" />
+ </Parameters>
+ <Docs>
+ <param name="cell">To be added.</param>
+ <summary>Internal.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IListViewController.SendRefreshing">
+ <MemberSignature Language="C#" Value="void IListViewController.SendRefreshing ();" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IListViewController.SendRefreshing() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Internal.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ListViewCachingStrategy.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ListViewCachingStrategy.xml
new file mode 100644
index 00000000..f783b452
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ListViewCachingStrategy.xml
@@ -0,0 +1,64 @@
+<Type Name="ListViewCachingStrategy" FullName="Xamarin.Forms.ListViewCachingStrategy">
+ <TypeSignature Language="C#" Value="public enum ListViewCachingStrategy" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed ListViewCachingStrategy extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumerates caching strategies for a ListView.</summary>
+ <remarks>
+ <para>Application developers can specify one of these values when constructing a <see cref="T:Xamarin.Forms.ListView" /> to determine whether the List View will minimize their memory footprint and speed execution by recycling list cells, or will instead generate a cell for every item in the list. Currently, the default behavior is to retain item data in their generated cells when they are not needed. (Items are not needed, for example, when they are far enough off screen that their display is not imminent.) This behavior corresponds to a value of <see cref="F:Xamarin.Forms.ListViewCachingStrategy.RetainElement" />. For performance reasons, it is likely that the default behavior will be changed to <see cref="F:Xamarin.Forms.ListViewCachingStrategy.RecycleElement" /> in a future release. In the meantime, for memory and performance reasons, app developers should specify <see cref="F:Xamarin.Forms.ListViewCachingStrategy.RecycleElement" /> when constructing a new List View.</para>
+ <para>The performance advantage of <see cref="F:Xamarin.Forms.ListViewCachingStrategy.RecycleElement" /> is so great that application developers have been provided with a XAML syntax shortcut for initializing List Views. Instead of <c>x:TypeArguments</c> syntax that specifies a parameter for the <see cref="M:Xamarin.Forms.ListView.ListView(Xamarin.Forms.ListViewCachingStrategy)" /> constructor, XAML for Xamarin.Forms provides a XAML attribute for a non-existent property that corresponds to the caching strategy argument of the constructor. Application developers can set the <c>CachingStrategy</c> attribute to either of the <c>RecycleElement</c> (preferred) or <c>RetainElement</c> values to choose a caching strategy. For example:</para>
+ <code lang="XAML"><![CDATA[
+<ListView CachingStrategy="RecycleElement" >
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <ViewCell>
+ <!-- ... -->
+ </ViewCell>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+</ListView>]]></code>
+ <para>
+ <block type="note">When devolopers specify <see cref="F:Xamarin.Forms.ListViewCachingStrategy.RecycleElement" />, <c>OnElementChanged</c> events are not raised when cells are recycled. Instead, the cell is retained and its property values change when the binding context is updated to that of an available cell, <c>OnElementPropertyChanged</c> events are raised. Application developers should remember to listen for the correct events, and should note that their renderers will need to be updated if the default behavior changes to <see cref="F:Xamarin.Forms.ListViewCachingStrategy.RecycleElement" /> in a future release. </block>
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="RecycleElement">
+ <MemberSignature Language="C#" Value="RecycleElement" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ListViewCachingStrategy RecycleElement = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ListViewCachingStrategy</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that unneeded cells will have their binding contexts updated to that of a cell that is needed.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="RetainElement">
+ <MemberSignature Language="C#" Value="RetainElement" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ListViewCachingStrategy RetainElement = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ListViewCachingStrategy</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that for every item in the List View's <see cref="P:Xamarin.Forms.ItemsView{TVisual}.ItemsSource" /> property, a single unique element will be constructed from the DataTemplate.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/MasterBehavior.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/MasterBehavior.xml
new file mode 100644
index 00000000..e8178cef
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/MasterBehavior.xml
@@ -0,0 +1,105 @@
+<Type Name="MasterBehavior" FullName="Xamarin.Forms.MasterBehavior">
+ <TypeSignature Language="C#" Value="public enum MasterBehavior" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed MasterBehavior extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumerates values that control how detail content is displayed in a master-detail page.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Default">
+ <MemberSignature Language="C#" Value="Default" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.MasterBehavior Default = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.MasterBehavior</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Details are displayed in the default way for the platform.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Popover">
+ <MemberSignature Language="C#" Value="Popover" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.MasterBehavior Popover = int32(3)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.MasterBehavior</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Details pop over the page.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Split">
+ <MemberSignature Language="C#" Value="Split" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.MasterBehavior Split = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.MasterBehavior</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Details are always displayed in a split screen.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="SplitOnLandscape">
+ <MemberSignature Language="C#" Value="SplitOnLandscape" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.MasterBehavior SplitOnLandscape = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.MasterBehavior</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Details are displayed in a split screen when the device is in landscape orientation.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="SplitOnPortrait">
+ <MemberSignature Language="C#" Value="SplitOnPortrait" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.MasterBehavior SplitOnPortrait = int32(4)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.MasterBehavior</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Details are displayed in a split screen when the device is in portrait orientation.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/MasterDetailPage.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/MasterDetailPage.xml
new file mode 100644
index 00000000..81d1ef3e
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/MasterDetailPage.xml
@@ -0,0 +1,466 @@
+<Type Name="MasterDetailPage" FullName="Xamarin.Forms.MasterDetailPage">
+ <TypeSignature Language="C#" Value="public class MasterDetailPage : Xamarin.Forms.Page" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit MasterDetailPage extends Xamarin.Forms.Page" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Page</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._MasterDetailPageRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.Page" /> that manages two panes of information: A master page that presents data at a high level, and a detail page that displays low-level details about information in the master.</summary>
+ <remarks>
+ <para>The following example code, taken from the <format type="text/html"><a href="https://github.com/xamarin/xamarin-forms-samples/tree/master/FormsGallery/FormsGallery/FormsGallery">FormsGallery</a></format> sample application, creates a <see cref="T:Xamarin.Forms.MasterDetailPage" /> that allows the user to view detailed information about a color that she chooses from a list. Note that the <c>NamedColorPage</c> class, defined in as a sublcass of <see cref="T:Xamarin.Forms.ContentPage" /> in another file in the sample application, simply displays RGB data, a <see cref="T:Xamarin.Forms.BoxView" /> with its background color set to the color that the user selected, and, finally, hue, saturation, and luminosity data.</para>
+ <para>The sample below illustrates three key concepts. First, the "Master" portion of the MasterDetailPage is represented by the <see cref="P:Xamarin.Forms.MasterDetailPage.Master" /> property, which is set to a <see cref="T:Xamarin.Forms.ListView" /> element in this example. This <see cref="T:Xamarin.Forms.ListView" /> element contains a label and a list of colors. Second, the "Detail" portion of the <see cref="T:Xamarin.Forms.MasterDetailPage" /> is represented by the <see cref="P:Xamarin.Forms.MasterDetailPage.Detail" /> property, which, in this example, is set to the <c>NamedColorPage</c> that was noted above. Third, and finally, the page that is represented by the <see cref="P:Xamarin.Forms.MasterDetailPage.Detail" /> property is displayed by setting the <see cref="P:Xamarin.Forms.MasterDetailPage.IsPresented" /> property to <see langword="false" />; That is, the <see cref="P:Xamarin.Forms.MasterDetailPage.IsPresented" /> property controls whether or not the page that is represented by the <see cref="P:Xamarin.Forms.MasterDetailPage.Master" /> is presented to the user.</para>
+ <block type="note">The <see cref="P:Xamarin.Forms.MasterDetailPage.Master" /> page must have its <see cref="P:Xamarin.Forms.Page.Title" /> property set. Additionally, the <see cref="P:Xamarin.Forms.MasterDetailPage.Detail" /> page will only display a navigation bar if it is an instance of <see cref="T:Xamarin.Forms.NavigationPage" />.</block>
+ <example>
+ <code lang="C#"><![CDATA[
+using System;
+using Xamarin.Forms;
+
+namespace FormsGallery
+{
+ class MasterDetailPageDemoPage : MasterDetailPage
+ {
+ public MasterDetailPageDemoPage()
+ {
+ Label header = new Label
+ {
+ Text = "MasterDetailPage",
+ FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ // Assemble an array of NamedColor objects.
+ NamedColor[] namedColors =
+ {
+ new NamedColor("Aqua", Color.Aqua),
+ new NamedColor("Black", Color.Black),
+ new NamedColor("Blue", Color.Blue),
+ new NamedColor("Fuschia", Color.Fuschia),
+ new NamedColor("Gray", Color.Gray),
+ new NamedColor("Green", Color.Green),
+ new NamedColor("Lime", Color.Lime),
+ new NamedColor("Maroon", Color.Maroon),
+ new NamedColor("Navy", Color.Navy),
+ new NamedColor("Olive", Color.Olive),
+ new NamedColor("Purple", Color.Purple),
+ new NamedColor("Red", Color.Red),
+ new NamedColor("Silver", Color.Silver),
+ new NamedColor("Teal", Color.Teal),
+ new NamedColor("White", Color.White),
+ new NamedColor("Yellow", Color.Yellow)
+ };
+
+ // Create ListView for the master page.
+ ListView listView = new ListView
+ {
+ ItemsSource = namedColors
+ };
+
+ // Create the master page with the ListView.
+ this.Master = new ContentPage
+ {
+ Title = header.Text,
+ Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ listView
+ }
+ }
+ };
+
+ // Create the detail page using NamedColorPage and wrap it in a
+ // navigation page to provide a NavigationBar and Toggle button
+ this.Detail = new NavigationPage(new NamedColorPage(true));
+
+ // For Windows Phone, provide a way to get back to the master page.
+ if (Device.OS == TargetPlatform.WinPhone)
+ {
+ (this.Detail as ContentPage).Content.GestureRecognizers.Add(
+ new TapGestureRecognizer((view) =>
+ {
+ this.IsPresented = true;
+ }));
+ }
+
+ // Define a selected handler for the ListView.
+ listView.ItemSelected += (sender, args) =>
+ {
+ // Set the BindingContext of the detail page.
+ this.Detail.BindingContext = args.SelectedItem;
+
+ // Show the detail page.
+ this.IsPresented = false;
+ };
+
+ // Initialize the ListView selection.
+ listView.SelectedItem = namedColors[0];
+
+
+ }
+ }
+}
+ ]]></code>
+ </example>
+ <block subset="none" type="note">
+ <para>The Windows Phone and Android platforms do not support sliding the detail screen in order to show or hide it. Application developers can use a <see cref="T:Xamarin.Forms.TapGestureRecognizer" /> to provide the user an additional way to show and hide the Detail screen on these platforms. On Windows Phone, developers could consider using a user interface class that provides an experience that is more consistent with that platform, such as <see cref="T:Xamarin.Forms.CarouselPage" />.</para>
+ </block>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public MasterDetailPage ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new empty <see cref="T:Xamarin.Forms.MasterDetailPage" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Detail">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Page Detail { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Page Detail" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Page</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the detail page that is used to display details about items on the master page.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsGestureEnabled">
+ <MemberSignature Language="C#" Value="public bool IsGestureEnabled { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsGestureEnabled" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that turns on or off the gesture to reveal the master page. This is a bindable property.</summary>
+ <value>
+ <see langword="true" /> if gesture is enabled; otherwise <see langword="false" />. Default is <see langword="true" />.</value>
+ <remarks>Has no effect on Windows Phone.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsGestureEnabledProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsGestureEnabledProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsGestureEnabledProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the IsGestureEnabled bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsPresented">
+ <MemberSignature Language="C#" Value="public bool IsPresented { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsPresented" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that indicates whether or not the visual element that is represented by the <see cref="P:Xamarin.Forms.MasterDetailPage.Master" /> property is presented to the user.</summary>
+ <value>To be added.</value>
+ <remarks>Setting this property causes the <see cref="E:Xamarin.Forms.MasterDetailPage.IsPresentedChanged" /> event to be raised.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsPresentedChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler IsPresentedChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler IsPresentedChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the visual element that is represented by the <see cref="P:Xamarin.Forms.MasterDetailPage.Master" /> property is presented or hidden.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsPresentedProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsPresentedProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsPresentedProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.MasterDetailPage.IsPresented" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutChildren">
+ <MemberSignature Language="C#" Value="protected override void LayoutChildren (double x, double y, double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void LayoutChildren(float64 x, float64 y, float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">To be added.</param>
+ <param name="y">To be added.</param>
+ <param name="width">To be added.</param>
+ <param name="height">To be added.</param>
+ <summary>Lays out the master and detail pages.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Master">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Page Master { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Page Master" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Page</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the master page.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MasterBehavior">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.MasterBehavior MasterBehavior { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.MasterBehavior MasterBehavior" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.MasterBehavior</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that indicates how detail content is displayed.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MasterBehaviorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty MasterBehaviorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty MasterBehaviorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the MasterBehavior property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnAppearing">
+ <MemberSignature Language="C#" Value="protected override void OnAppearing ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnAppearing() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Event that is raised when a detail appears.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBackButtonPressed">
+ <MemberSignature Language="C#" Value="protected override bool OnBackButtonPressed ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance bool OnBackButtonPressed() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Event that is raised when the back button is pressed.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnDisappearing">
+ <MemberSignature Language="C#" Value="protected override void OnDisappearing ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnDisappearing() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Event that is raised when a detail disappears.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnParentSet">
+ <MemberSignature Language="C#" Value="protected override void OnParentSet ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnParentSet() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Method that is called when the <see cref="P:Xamarin.Forms.Element.Parent" /> property of this <see cref="Xamarin.Forms.MasterDetailPage" /> is set.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ShouldShowToolbarButton">
+ <MemberSignature Language="C#" Value="public virtual bool ShouldShowToolbarButton ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance bool ShouldShowToolbarButton() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns a value that tells whether the list view should display a toolbar button.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/MeasureFlags.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/MeasureFlags.xml
new file mode 100644
index 00000000..be498b17
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/MeasureFlags.xml
@@ -0,0 +1,50 @@
+<Type Name="MeasureFlags" FullName="Xamarin.Forms.MeasureFlags">
+ <TypeSignature Language="C#" Value="public enum MeasureFlags" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed MeasureFlags extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Flags</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Enumerates values that tell whether margins are included when laying out windows.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="IncludeMargins">
+ <MemberSignature Language="C#" Value="IncludeMargins" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.MeasureFlags IncludeMargins = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.MeasureFlags</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Include margins in a layout measurement.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="None">
+ <MemberSignature Language="C#" Value="None" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.MeasureFlags None = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.MeasureFlags</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Do not include margins in a layout measurement.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/MenuItem.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/MenuItem.xml
new file mode 100644
index 00000000..19b4049f
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/MenuItem.xml
@@ -0,0 +1,297 @@
+<Type Name="MenuItem" FullName="Xamarin.Forms.MenuItem">
+ <TypeSignature Language="C#" Value="public class MenuItem : Xamarin.Forms.BaseMenuItem" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit MenuItem extends Xamarin.Forms.BaseMenuItem" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.BaseMenuItem</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Class that presents a menu item and associates it with a command.</summary>
+ <remarks>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.MenuItem" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Command</term>
+ <description>
+ <para>A binding to a command.</para>
+ </description>
+ </item>
+ <item>
+ <term>CommandParameter</term>
+ <description>
+ <para>A parameter to pass to the command.</para>
+ </description>
+ </item>
+ <!-- TODO: Getting info from Jason on how to specify images
+ <item>
+ <term>Icon</term>
+ <description><para></para></description>
+ </item> -->
+ <item>
+ <term>IsDestructive</term>
+ <description>
+ <para>
+ <c>true</c> or <c>false</c>, to indicate whether the command deletes an item in a list.</para>
+ </description>
+ </item>
+ <item>
+ <term>Text</term>
+ <description>
+ <para>The text to display on the menu item.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public MenuItem ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Intitializes a new <see cref="T:Xamarin.Forms.MenuItem" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Clicked">
+ <MemberSignature Language="C#" Value="public event EventHandler Clicked;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Clicked" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the menu item is clicked.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Command">
+ <MemberSignature Language="C#" Value="public System.Windows.Input.ICommand Command { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Windows.Input.ICommand Command" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Windows.Input.ICommand</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the command that is run when the menu is clicked.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CommandParameter">
+ <MemberSignature Language="C#" Value="public object CommandParameter { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object CommandParameter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the parameter that is passed to the command.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CommandParameterProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty CommandParameterProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty CommandParameterProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the command parameter bound property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CommandProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty CommandProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty CommandProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the command bound property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Icon">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.FileImageSource Icon { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.FileImageSource Icon" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FileImageSource</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the icon for the menu item.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IconProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IconProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IconProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identfies the icon bound property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsDestructive">
+ <MemberSignature Language="C#" Value="public bool IsDestructive { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsDestructive" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that indicates whether or not the menu item removes its associated UI element.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsDestructiveProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsDestructiveProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsDestructiveProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the IsDestructive bound property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnClicked">
+ <MemberSignature Language="C#" Value="protected virtual void OnClicked ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnClicked() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>When overriden by an app dev, implements behavior when the menu item is clicked.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Text">
+ <MemberSignature Language="C#" Value="public string Text { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Text" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The text of the menu item.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TextProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TextProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the text bound property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/MessagingCenter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/MessagingCenter.xml
new file mode 100644
index 00000000..f21f0116
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/MessagingCenter.xml
@@ -0,0 +1,263 @@
+<Type Name="MessagingCenter" FullName="Xamarin.Forms.MessagingCenter">
+ <TypeSignature Language="C#" Value="public static class MessagingCenter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract sealed beforefieldinit MessagingCenter extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Associates a callback on subscribers with a specific message name.</summary>
+ <remarks>
+ <para>The following shows a simple example of a strongly-typed callback using <see cref="T:Xamarin.Forms.MessagingCenter" /> is:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+public class SubscriberThing
+{
+ public int IntProperty { get; set; }
+}
+
+var subscriber = new SubscriberThing();
+MessagingCenter.Subscribe<MyPage, int> (subscriber, "IntPropertyMessage", (s, e) => {
+ subscriber.IntProperty = e;
+});
+
+//...later...
+
+MessagingCenter.Send<MyPage, int>(this, "IntPropertyMessage", 2);
+Assert.AreEqual(2, subscriber.IntProperty);
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Send&lt;TSender&gt;">
+ <MemberSignature Language="C#" Value="public static void Send&lt;TSender&gt; (TSender sender, string message) where TSender : class;" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Send&lt;class TSender&gt;(!!TSender sender, string message) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TSender">
+ <Constraints>
+ <ParameterAttribute>ReferenceTypeConstraint</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="sender" Type="TSender" />
+ <Parameter Name="message" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TSender">To be added.</typeparam>
+ <param name="sender">To be added.</param>
+ <param name="message">To be added.</param>
+ <summary>Sends a named message that has no arguments.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Send&lt;TSender,TArgs&gt;">
+ <MemberSignature Language="C#" Value="public static void Send&lt;TSender,TArgs&gt; (TSender sender, string message, TArgs args) where TSender : class;" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Send&lt;class TSender, TArgs&gt;(!!TSender sender, string message, !!TArgs args) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TSender">
+ <Constraints>
+ <ParameterAttribute>ReferenceTypeConstraint</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ <TypeParameter Name="TArgs" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="sender" Type="TSender" />
+ <Parameter Name="message" Type="System.String" />
+ <Parameter Name="args" Type="TArgs" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TSender">To be added.</typeparam>
+ <typeparam name="TArgs">To be added.</typeparam>
+ <param name="sender">To be added.</param>
+ <param name="message">To be added.</param>
+ <param name="args">To be added.</param>
+ <summary>Sends a named message with the specified arguments.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Subscribe&lt;TSender&gt;">
+ <MemberSignature Language="C#" Value="public static void Subscribe&lt;TSender&gt; (object subscriber, string message, Action&lt;TSender&gt; callback, TSender source = null) where TSender : class;" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Subscribe&lt;class TSender&gt;(object subscriber, string message, class System.Action`1&lt;!!TSender&gt; callback, !!TSender source) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TSender">
+ <Constraints>
+ <ParameterAttribute>ReferenceTypeConstraint</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="subscriber" Type="System.Object" />
+ <Parameter Name="message" Type="System.String" />
+ <Parameter Name="callback" Type="System.Action&lt;TSender&gt;" />
+ <Parameter Name="source" Type="TSender" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TSender">To be added.</typeparam>
+ <param name="subscriber">To be added.</param>
+ <param name="message">To be added.</param>
+ <param name="callback">To be added.</param>
+ <param name="source">To be added.</param>
+ <summary>Run the <paramref name="callback" /> on <paramref name="subscriber" /> in response to messages that are named <paramref name="message" /> and that are created by <paramref name="source" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Subscribe&lt;TSender,TArgs&gt;">
+ <MemberSignature Language="C#" Value="public static void Subscribe&lt;TSender,TArgs&gt; (object subscriber, string message, Action&lt;TSender,TArgs&gt; callback, TSender source = null) where TSender : class;" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Subscribe&lt;class TSender, TArgs&gt;(object subscriber, string message, class System.Action`2&lt;!!TSender, !!TArgs&gt; callback, !!TSender source) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TSender">
+ <Constraints>
+ <ParameterAttribute>ReferenceTypeConstraint</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ <TypeParameter Name="TArgs" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="subscriber" Type="System.Object" />
+ <Parameter Name="message" Type="System.String" />
+ <Parameter Name="callback" Type="System.Action&lt;TSender,TArgs&gt;" />
+ <Parameter Name="source" Type="TSender" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TSender">To be added.</typeparam>
+ <typeparam name="TArgs">To be added.</typeparam>
+ <param name="subscriber">To be added.</param>
+ <param name="message">To be added.</param>
+ <param name="callback">To be added.</param>
+ <param name="source">To be added.</param>
+ <summary>Run the <paramref name="callback" /> on <paramref name="subscriber" /> in response to parameterized messages that are named <paramref name="message" /> and that are created by <paramref name="source" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Unsubscribe&lt;TSender&gt;">
+ <MemberSignature Language="C#" Value="public static void Unsubscribe&lt;TSender&gt; (object subscriber, string message) where TSender : class;" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Unsubscribe&lt;class TSender&gt;(object subscriber, string message) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TSender">
+ <Constraints>
+ <ParameterAttribute>ReferenceTypeConstraint</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="subscriber" Type="System.Object" />
+ <Parameter Name="message" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TSender">To be added.</typeparam>
+ <param name="subscriber">To be added.</param>
+ <param name="message">To be added.</param>
+ <summary>Unsubscribes a subscriber from the specified messages that come from the specified sender.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Unsubscribe&lt;TSender,TArgs&gt;">
+ <MemberSignature Language="C#" Value="public static void Unsubscribe&lt;TSender,TArgs&gt; (object subscriber, string message) where TSender : class;" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Unsubscribe&lt;class TSender, TArgs&gt;(object subscriber, string message) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TSender">
+ <Constraints>
+ <ParameterAttribute>ReferenceTypeConstraint</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ <TypeParameter Name="TArgs" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="subscriber" Type="System.Object" />
+ <Parameter Name="message" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TSender">To be added.</typeparam>
+ <typeparam name="TArgs">To be added.</typeparam>
+ <param name="subscriber">To be added.</param>
+ <param name="message">To be added.</param>
+ <summary>Unsubscribes from the specified parameterless subscriber messages.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ModalEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ModalEventArgs.xml
new file mode 100644
index 00000000..dbee4950
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ModalEventArgs.xml
@@ -0,0 +1,59 @@
+<Type Name="ModalEventArgs" FullName="Xamarin.Forms.ModalEventArgs">
+ <TypeSignature Language="C#" Value="public abstract class ModalEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit ModalEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Base class for <see cref="T:Xamarin.Forms.ModalPushedEventArgs" />, <see cref="T:Xamarin.Forms.ModalPushingEventArgs" />, <see cref="T:Xamarin.Forms.ModalPoppedEventArgs" />, and <see cref="T:Xamarin.Forms.ModalPoppingEventArgs" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected ModalEventArgs (Xamarin.Forms.Page modal);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor(class Xamarin.Forms.Page modal) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="modal" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="modal">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.ModalEventArgs" /> object for a navigation event that happened to the <paramref name="modal" /> page.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Modal">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Page Modal { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Page Modal" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Page</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the page whose navigation triggered the event.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPoppedEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPoppedEventArgs.xml
new file mode 100644
index 00000000..cd0b61d4
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPoppedEventArgs.xml
@@ -0,0 +1,40 @@
+<Type Name="ModalPoppedEventArgs" FullName="Xamarin.Forms.ModalPoppedEventArgs">
+ <TypeSignature Language="C#" Value="public class ModalPoppedEventArgs : Xamarin.Forms.ModalEventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ModalPoppedEventArgs extends Xamarin.Forms.ModalEventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.ModalEventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Arguments for the event that is raised when a modal window is popped from the navigation stack.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ModalPoppedEventArgs (Xamarin.Forms.Page modal);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class Xamarin.Forms.Page modal) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="modal" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="modal">To be added.</param>
+ <summary>Constructs a new <see cref="T:Xamarin.Forms.ModalPoppedEventArgs" /> object for the page that was just popped.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPoppingEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPoppingEventArgs.xml
new file mode 100644
index 00000000..64164629
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPoppingEventArgs.xml
@@ -0,0 +1,59 @@
+<Type Name="ModalPoppingEventArgs" FullName="Xamarin.Forms.ModalPoppingEventArgs">
+ <TypeSignature Language="C#" Value="public class ModalPoppingEventArgs : Xamarin.Forms.ModalEventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ModalPoppingEventArgs extends Xamarin.Forms.ModalEventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.ModalEventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Arguments for the event that is raised when a modal window is popping from the navigation stack.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ModalPoppingEventArgs (Xamarin.Forms.Page modal);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class Xamarin.Forms.Page modal) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="modal" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="modal">To be added.</param>
+ <summary>Constructs a new <see cref="T:Xamarin.Forms.ModalPoppingEventArgs" /> object for the page that is being popped.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Cancel">
+ <MemberSignature Language="C#" Value="public bool Cancel { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool Cancel" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that tells whether the modal navigation was canceled.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPushedEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPushedEventArgs.xml
new file mode 100644
index 00000000..f8ab3b2b
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPushedEventArgs.xml
@@ -0,0 +1,40 @@
+<Type Name="ModalPushedEventArgs" FullName="Xamarin.Forms.ModalPushedEventArgs">
+ <TypeSignature Language="C#" Value="public class ModalPushedEventArgs : Xamarin.Forms.ModalEventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ModalPushedEventArgs extends Xamarin.Forms.ModalEventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.ModalEventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Arguments for the event that is raised when a modal window is pushed onto the navigation stack.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ModalPushedEventArgs (Xamarin.Forms.Page modal);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class Xamarin.Forms.Page modal) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="modal" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="modal">To be added.</param>
+ <summary>Constructs a new <see cref="T:Xamarin.Forms.ModalPushedEventArgs" /> object for the page that was just popped.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPushingEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPushingEventArgs.xml
new file mode 100644
index 00000000..14009263
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ModalPushingEventArgs.xml
@@ -0,0 +1,40 @@
+<Type Name="ModalPushingEventArgs" FullName="Xamarin.Forms.ModalPushingEventArgs">
+ <TypeSignature Language="C#" Value="public class ModalPushingEventArgs : Xamarin.Forms.ModalEventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ModalPushingEventArgs extends Xamarin.Forms.ModalEventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.ModalEventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Arguments for the event that is raised when a modal window is being pushed onto the navigation stack.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ModalPushingEventArgs (Xamarin.Forms.Page modal);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class Xamarin.Forms.Page modal) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="modal" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="modal">To be added.</param>
+ <summary>Constructs a new <see cref="T:Xamarin.Forms.ModalPushingEventArgs" /> object for the page that is being pushed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/MultiPage`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/MultiPage`1.xml
new file mode 100644
index 00000000..a0c863de
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/MultiPage`1.xml
@@ -0,0 +1,599 @@
+<Type Name="MultiPage&lt;T&gt;" FullName="Xamarin.Forms.MultiPage&lt;T&gt;">
+ <TypeSignature Language="C#" Value="public abstract class MultiPage&lt;T&gt; : Xamarin.Forms.Page, Xamarin.Forms.IPageContainer&lt;T&gt;, Xamarin.Forms.IViewContainer&lt;T&gt; where T : Page" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit MultiPage`1&lt;(class Xamarin.Forms.Page) T&gt; extends Xamarin.Forms.Page implements class Xamarin.Forms.IPageContainer`1&lt;!T&gt;, class Xamarin.Forms.IViewContainer`1&lt;!T&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="T">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.Page</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Page</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IPageContainer&lt;T&gt;</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IViewContainer&lt;T&gt;</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Children")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <typeparam name="T">The particular subclass of <see cref="T:Xamarin.Forms.Page" /> that the MultiPage services.</typeparam>
+ <summary>A bindable, templatable base class for pages which contain multiple sub-pages.</summary>
+ <remarks>
+ <para>Provides a base implementation for binding and templating pages.</para>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.MultiPage`1" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>ItemsSource</term>
+ <description>
+ <para>A static collection of data objects.</para>
+ </description>
+ </item>
+ <item>
+ <term>ItemTemplate</term>
+ <description>
+ <para>A view that has bindings to properties on the members of the collection that is specified by <c>ItemsSource</c>.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected MultiPage ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Provides the base initialization for objects derived from the MultiPage&lt;T&gt; class.</summary>
+ <remarks>
+ <see cref="N:Xamarin.Forms" /> provides two classes that are derived from <see cref="T:Xamarin.Forms.Multipage`1" />, <see cref="T:Xamarin.Forms.TabbedPage" /> and <see cref="T:Xamarin.Forms.CarouselPage" />.
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Children">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;T&gt; Children { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;!T&gt; Children" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;T&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets an IList&lt;Page&gt; of child elements of the MultiPage.</summary>
+ <value>A IList&lt;Page&gt;. The default is an empty list.</value>
+ <remarks>
+ <para>
+ The <see cref="P:Xamarin.Forms.Multipage`1.Children" /> collection of a <see cref="T:Xamarin.Forms.Multipage`1" /> contains all the children added through the public add/remove interface. Internal children will not be exposed through this collection.
+ </para>
+ <para>
+ The following shows the creation of a <see cref="T:Xamarin.Forms.TabbedPage" />, which descends from <see cref="T:Xamarin.Forms.Multipage`1" />.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+Page pageOne = CreatePageOne ();
+Page pageTwo = CreatePageTwo ();
+
+var tabbedPage = new TabbedPage {
+Title = "My App",
+Children = {
+ pageOne,
+ pageTwo
+}
+};
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateDefault">
+ <MemberSignature Language="C#" Value="protected abstract T CreateDefault (object item);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance !T CreateDefault(object item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="item">The object which the default page should be templated from.</param>
+ <summary>Create default provides a default method of creating new pages from objects in a binding scenario.</summary>
+ <returns>The newly created page.</returns>
+ <remarks>Most implementors will not need to use or override CreateDefault.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CurrentPage">
+ <MemberSignature Language="C#" Value="public T CurrentPage { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance !T CurrentPage" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the currently selected page.</summary>
+ <value>The current page. The default value is null.</value>
+ <remarks>The default page will usually get set when the multi-page is displayed or templated.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CurrentPageChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler CurrentPageChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler CurrentPageChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Raised when the <see cref="P:Xamarin.MultiPage{T}.CurrentPage" /> property changes.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemsSource">
+ <MemberSignature Language="C#" Value="public System.Collections.IEnumerable ItemsSource { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.IEnumerable ItemsSource" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.IEnumerable</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The source for the items to be displayed.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemsSourceProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ItemsSourceProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ItemsSourceProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.MultiPage`1.ItemsSource" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemTemplate">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.DataTemplate ItemTemplate { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.DataTemplate ItemTemplate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.DataTemplate</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The template for displaying items.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ItemTemplateProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ItemTemplateProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ItemTemplateProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.MultiPage`1.ItemTemplate" /> bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBackButtonPressed">
+ <MemberSignature Language="C#" Value="protected override bool OnBackButtonPressed ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance bool OnBackButtonPressed() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Event that is raised when the back button is pressed.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnChildAdded">
+ <MemberSignature Language="C#" Value="protected override void OnChildAdded (Xamarin.Forms.Element child);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnChildAdded(class Xamarin.Forms.Element child) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="child" Type="Xamarin.Forms.Element" />
+ </Parameters>
+ <Docs>
+ <param name="child">The child that was added.</param>
+ <summary>Called when a child has been added to the <see cref="T:Xamarin.Forms.MultiPage`1" />.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnCurrentPageChanged">
+ <MemberSignature Language="C#" Value="protected virtual void OnCurrentPageChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnCurrentPageChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Raises the <see cref="E:Xamarin.Forms.MultiPage{T}.CurrentPageChanged" /> event.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnPagesChanged">
+ <MemberSignature Language="C#" Value="protected virtual void OnPagesChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs e);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnPagesChanged(class System.Collections.Specialized.NotifyCollectionChangedEventArgs e) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="e" Type="System.Collections.Specialized.NotifyCollectionChangedEventArgs" />
+ </Parameters>
+ <Docs>
+ <param name="e">To be added.</param>
+ <summary>Called when the pages of the <see cref="T:Xamarin.Forms.MultiPage`1" /> have been changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnPropertyChanged">
+ <MemberSignature Language="C#" Value="protected override void OnPropertyChanged (string propertyName = null);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnPropertyChanged(string propertyName) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String">
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.CallerMemberName</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Parameter>
+ </Parameters>
+ <Docs>
+ <param name="propertyName">The name of the property that was changed.</param>
+ <summary>Called when a bindable property has changed.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PagesChanged">
+ <MemberSignature Language="C#" Value="public event System.Collections.Specialized.NotifyCollectionChangedEventHandler PagesChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.Collections.Specialized.NotifyCollectionChangedEventHandler PagesChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Specialized.NotifyCollectionChangedEventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Raised when the children pages of the <see cref="T:Xamarin.Forms.MultiPage`1" /> have changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SelectedItem">
+ <MemberSignature Language="C#" Value="public object SelectedItem { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object SelectedItem" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The currently selected item.</summary>
+ <value>The selected item from the <see cref="P:Xamarin.MultiPage{T}.ItemsSource" /> or <see langword="null" /> if nothing selected.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SelectedItemProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty SelectedItemProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty SelectedItemProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.MultiPage`1.SelectedItem" /> bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetupContent">
+ <MemberSignature Language="C#" Value="protected virtual void SetupContent (T content, int index);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void SetupContent(!T content, int32 index) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="content" Type="T" />
+ <Parameter Name="index" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="content">To be added.</param>
+ <param name="index">To be added.</param>
+ <summary>When overriden in a derived class, performs initialization of <paramref name="content" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="UnhookContent">
+ <MemberSignature Language="C#" Value="protected virtual void UnhookContent (T content);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void UnhookContent(!T content) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="content" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="content">To be added.</param>
+ <summary>Application developers override this method to unregister event handlers for items that they registered in <see cref="M:Xamarin.Forms.MultiPage{TVisual}.SetupContent(`0, int)" />.</summary>
+ <remarks>
+ <para>Application developers must call <see cref="M:Xamarin.Forms.MultiPage{TVisual}.UnhookContent(`0, int)" /> before performing any other action when overriding this method.</para>
+ <block type="note">Application developers who override <see cref="M:Xamarin.Forms.MultiPage{TVisual}.SetupContent(`0, int)" /> to allocate resources must override this method in order to deallocate them.</block>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IItemsView&lt;T&gt;.CreateDefault">
+ <MemberSignature Language="C#" Value="T IItemsView&lt;T&gt;.CreateDefault (object item);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance !T Xamarin.Forms.IItemsView&lt;T&gt;.CreateDefault(object item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="item">To be added.</param>
+ <summary>Sets the page that is specified by <paramref name="item" /> as the default page.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IItemsView&lt;T&gt;.SetupContent">
+ <MemberSignature Language="C#" Value="void IItemsView&lt;T&gt;.SetupContent (T content, int index);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IItemsView&lt;T&gt;.SetupContent(!T content, int32 index) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="content" Type="T" />
+ <Parameter Name="index" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="content">To be added.</param>
+ <param name="index">To be added.</param>
+ <summary>Performs initialization of <paramref name="content" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IItemsView&lt;T&gt;.UnhookContent">
+ <MemberSignature Language="C#" Value="void IItemsView&lt;T&gt;.UnhookContent (T content);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IItemsView&lt;T&gt;.UnhookContent(!T content) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="content" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="content">To be added.</param>
+ <summary>Internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/MultiTrigger.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/MultiTrigger.xml
new file mode 100644
index 00000000..30273dc0
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/MultiTrigger.xml
@@ -0,0 +1,109 @@
+<Type Name="MultiTrigger" FullName="Xamarin.Forms.MultiTrigger">
+ <TypeSignature Language="C#" Value="public sealed class MultiTrigger : Xamarin.Forms.TriggerBase" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit MultiTrigger extends Xamarin.Forms.TriggerBase" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TriggerBase</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Setters")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Class that represents a list of property and binding conditions, and a list of setters that are applied when all of the conditions in the list are met.</summary>
+ <remarks>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.MultiTrigger" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Conditions</term>
+ <description>
+ <para>A list of <c>PropertyCondition</c> and/or <c>BindingCondition</c> markup instances that specify the conditions that all must be met before all of the setters that are listed in <c>Setters</c> are applied.</para>
+ </description>
+ </item>
+ <item>
+ <term>Setters</term>
+ <description>
+ <para>A list of setters that are applied when all of the property conditions are met. Each <c>Setter</c> tag or tag pair in the list has a <c>Property</c> and <c>Value</c> that represents the assignments to perform when the condition is met.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public MultiTrigger (Type targetType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Type targetType) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="targetType" Type="System.Type">
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.TypeTypeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Parameter>
+ </Parameters>
+ <Docs>
+ <param name="targetType">To be added.</param>
+ <summary>Initializes a new <see cref="T:Xamarin.Forms.MultiTrigger" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Conditions">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.Condition&gt; Conditions { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Condition&gt; Conditions" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.Condition&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the list of conditions that must be satisfied in ordeer for the setters in the <see cref="P:Xamarin.Forms.MultiTrigger.Setters" /> list to be invoked.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Setters">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt; Setters { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Setter&gt; Setters" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the list of <see cref="T:Xamarin.Forms.Setter" /> objects that will be applied when the list of conditions in the <see cref="P:Xamarin.Forms.MultiTrigger.Conditions" /> property are all met.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/NameScopeExtensions.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/NameScopeExtensions.xml
new file mode 100644
index 00000000..c9b15409
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/NameScopeExtensions.xml
@@ -0,0 +1,56 @@
+<Type Name="NameScopeExtensions" FullName="Xamarin.Forms.NameScopeExtensions">
+ <TypeSignature Language="C#" Value="public static class NameScopeExtensions" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract sealed beforefieldinit NameScopeExtensions extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Extension methods for <see cref="T:Xamarin.Forms.Element" /> and <see cref="T:Xamarin.Forms.INameScope" /> that add strongly-typed FindByName methods.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="FindByName&lt;T&gt;">
+ <MemberSignature Language="C#" Value="public static T FindByName&lt;T&gt; (this Xamarin.Forms.Element element, string name);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig !!T FindByName&lt;T&gt;(class Xamarin.Forms.Element element, string name) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="T" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="element" Type="Xamarin.Forms.Element" RefType="this" />
+ <Parameter Name="name" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <param name="element">To be added.</param>
+ <param name="name">To be added.</param>
+ <summary>Returns the instance of type <paramref name="T" /> that has name <paramref name="T" /> in the scope that includes <paramref name="element" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/NamedSize.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/NamedSize.xml
new file mode 100644
index 00000000..26bf8dd7
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/NamedSize.xml
@@ -0,0 +1,120 @@
+<Type Name="NamedSize" FullName="Xamarin.Forms.NamedSize">
+ <TypeSignature Language="C#" Value="public enum NamedSize" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed NamedSize extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Represents pre-defined font sizes.</summary>
+ <remarks>The exact pixel-value depends on the platform on which Forms runs.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Default">
+ <MemberSignature Language="C#" Value="Default" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.NamedSize Default = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.NamedSize</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The default font size.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Large">
+ <MemberSignature Language="C#" Value="Large" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.NamedSize Large = int32(4)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.NamedSize</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A Large font size, for titles or other important text elements.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Medium">
+ <MemberSignature Language="C#" Value="Medium" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.NamedSize Medium = int32(3)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.NamedSize</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A default font size, to be used in stand alone labels or buttons.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Micro">
+ <MemberSignature Language="C#" Value="Micro" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.NamedSize Micro = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.NamedSize</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The smallest readable font size for the device. Think about this like legal footnotes.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Small">
+ <MemberSignature Language="C#" Value="Small" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.NamedSize Small = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.NamedSize</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A small but readable font size. Use this for block of text.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/NavigationEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/NavigationEventArgs.xml
new file mode 100644
index 00000000..7eae8b41
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/NavigationEventArgs.xml
@@ -0,0 +1,78 @@
+<Type Name="NavigationEventArgs" FullName="Xamarin.Forms.NavigationEventArgs">
+ <TypeSignature Language="C#" Value="public class NavigationEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit NavigationEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>EventArgs for the NavigationPage's navigation events.</summary>
+ <remarks>
+ </remarks>
+ <altmember cref="E:Xamarin.Forms.NavigationPage.Pushed" />
+ <altmember cref="E:Xamarin.Forms.NavigationPage.Popped" />
+ <altmember cref="E:Xamarin.Forms.NavigationPage.PoppedToRoot" />
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public NavigationEventArgs (Xamarin.Forms.Page page);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class Xamarin.Forms.Page page) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="page" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="page">The page that was popped or is newly visible.</param>
+ <summary>
+ </summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Page">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Page Page { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Page Page" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Page</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the page that was removed or is newly visible.</summary>
+ <value>
+ </value>
+ <remarks>
+ <para>For <see cref="E:Xamarin.Forms.NavigationPage.Pushed" />, this is the <see cref="T:Xamarin.Forms.Page" /> that was removed. For <see cref="E:Xamarin.Forms.NavigationPage.Pushed" />
+ and <see cref="E:Xamarin.Forms.NavigationPage.PoppedToRoot" /> it is the newly visible page, the pushed page or the root respectively.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/NavigationMenu.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/NavigationMenu.xml
new file mode 100644
index 00000000..c125a6c5
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/NavigationMenu.xml
@@ -0,0 +1,90 @@
+<Type Name="NavigationMenu" FullName="Xamarin.Forms.NavigationMenu">
+ <TypeSignature Language="C#" Value="public class NavigationMenu : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit NavigationMenu extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._NavigationMenuRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>For internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public NavigationMenu ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>For internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (Xamarin.Forms.Page target);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void Add(class Xamarin.Forms.Page target) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="target" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="target">To be added.</param>
+ <summary>For internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Remove">
+ <MemberSignature Language="C#" Value="public void Remove (Xamarin.Forms.Page target);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void Remove(class Xamarin.Forms.Page target) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="target" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="target">To be added.</param>
+ <summary>For internal use only.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Targets">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IEnumerable&lt;Xamarin.Forms.Page&gt; Targets { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IEnumerable`1&lt;class Xamarin.Forms.Page&gt; Targets" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IEnumerable&lt;Xamarin.Forms.Page&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use only.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/NavigationPage.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/NavigationPage.xml
new file mode 100644
index 00000000..1004ed1e
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/NavigationPage.xml
@@ -0,0 +1,815 @@
+<Type Name="NavigationPage" FullName="Xamarin.Forms.NavigationPage">
+ <TypeSignature Language="C#" Value="public class NavigationPage : Xamarin.Forms.Page, Xamarin.Forms.IPageContainer&lt;Xamarin.Forms.Page&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit NavigationPage extends Xamarin.Forms.Page implements class Xamarin.Forms.IPageContainer`1&lt;class Xamarin.Forms.Page&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Page</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IPageContainer&lt;Xamarin.Forms.Page&gt;</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._NavigationPageRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.Page" /> that manages the navigation and user-experience of a stack of other pages.</summary>
+ <remarks>
+ <para>Note that on the Android platform, <see cref="T:Xamarin.Forms.INavigation" /> operations do not generate activity lifecycle notifications. For each <see cref="T:Xamarin.Forms.Page" /> that you push or pop, the Android implementation of <see cref="T:Xamarin.Forms.NavigationPage" /> simply adds or removes the content of the page to or from a single activity.</para>
+ <para>Also note that the Windows Phone platform provides navigation natively. Therefore, you do not need to use a <see cref="T:Xamarin.Forms.NavigationPage" /> object to get navigation on that platform.</para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public NavigationPage ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new <see cref="T:Xamarin.Forms.NavigationPage" /> object.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public NavigationPage (Xamarin.Forms.Page root);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class Xamarin.Forms.Page root) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="root" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="root">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.NavigationPage" /> element with <paramref name="root" /> as its root element.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BackButtonTitleProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty BackButtonTitleProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty BackButtonTitleProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the property associated with the title of the back button.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BarBackgroundColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color BarBackgroundColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color BarBackgroundColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the background color for the bar at the top of the NavigationPage.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BarBackgroundColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty BarBackgroundColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty BarBackgroundColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the property associated with the color of the NavigationPage's bar background color.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BarTextColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color BarTextColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color BarTextColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the text that appears on the bar at the top of the NavigationPage.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BarTextColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty BarTextColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty BarTextColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the property associated with the color of the NavigationPage's bar text color.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CurrentPage">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Page CurrentPage { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Page CurrentPage" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Page</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The <see cref="T:Xamarin.Forms.Page" /> that is currently top-most on the navigation stack.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CurrentPageProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty CurrentPageProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty CurrentPageProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.NavigationPage.CurrentPage" /> property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetBackButtonTitle">
+ <MemberSignature Language="C#" Value="public static string GetBackButtonTitle (Xamarin.Forms.BindableObject page);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig string GetBackButtonTitle(class Xamarin.Forms.BindableObject page) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="page" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="page">The <see cref="T:Xamarin.Forms.Page" /> whose back-button's title is being requested.</param>
+ <summary>The title of the back button for the specified <paramref name="page" />.</summary>
+ <returns>The title of the back button that would be shown if the specified <paramref name="page" /> were the <see cref="P:Xamarin.Forms.CurrentPage" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetHasBackButton">
+ <MemberSignature Language="C#" Value="public static bool GetHasBackButton (Xamarin.Forms.Page page);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig bool GetHasBackButton(class Xamarin.Forms.Page page) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="page" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="page">To be added.</param>
+ <summary>Returns a value that indicates whether <paramref name="page" /> has a back button.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetHasNavigationBar">
+ <MemberSignature Language="C#" Value="public static bool GetHasNavigationBar (Xamarin.Forms.BindableObject page);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig bool GetHasNavigationBar(class Xamarin.Forms.BindableObject page) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="page" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="page">The <see cref="T:Xamarin.Forms.Page" /> being queried.</param>
+ <summary>Returns a value that indicates whether the <paramref name="page" /> has a navigation bar.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="page" /> would display a navigation bar were it the <see cref="P:Xamarin.Forms.NavigationPage.CurrentPage" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetTitleIcon">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.FileImageSource GetTitleIcon (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.FileImageSource GetTitleIcon(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FileImageSource</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">The <see cref="T:Xamarin.Forms.BindableObject" /> whose title icon is being set.</param>
+ <summary>Retrieves the path to the file providing the title icon for the <paramref name="bindable" />.</summary>
+ <returns>The path to the file providing the title icon for the <paramref name="bindable" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasBackButtonProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HasBackButtonProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HasBackButtonProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the HasBackButton property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasNavigationBarProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HasNavigationBarProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HasNavigationBarProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the HasNavigationBar property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBackButtonPressed">
+ <MemberSignature Language="C#" Value="protected override bool OnBackButtonPressed ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance bool OnBackButtonPressed() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Event that is raised when the hardware back button is pressed. This event is not raised on iOS.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PopAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task&lt;Xamarin.Forms.Page&gt; PopAsync ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Threading.Tasks.Task`1&lt;class Xamarin.Forms.Page&gt; PopAsync() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;Xamarin.Forms.Page&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Asynchronously removes the top <see cref="T:Xamarin.Forms.Page" /> from the navigation stack.</summary>
+ <returns>The <see cref="T:Xamarin.Forms.Page" /> that had been at the top of the navigation stack.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PopAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task&lt;Xamarin.Forms.Page&gt; PopAsync (bool animated);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Threading.Tasks.Task`1&lt;class Xamarin.Forms.Page&gt; PopAsync(bool animated) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.DebuggerStepThrough</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.AsyncStateMachine(typeof(Xamarin.Forms.NavigationPage/&lt;PopAsync&gt;d__68))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;Xamarin.Forms.Page&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="animated" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="animated">To be added.</param>
+ <summary>Asynchronously removes the top <see cref="T:Xamarin.Forms.Page" /> from the navigation stack, with optional animation.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Popped">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.NavigationEventArgs&gt; Popped;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.NavigationEventArgs&gt; Popped" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.NavigationEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised after a page is popped from this <see cref="T:Xamarin.Forms.NavigationPage" /> element.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PoppedToRoot">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.NavigationEventArgs&gt; PoppedToRoot;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.NavigationEventArgs&gt; PoppedToRoot" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.NavigationEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the last nonroot element is popped from this <see cref="T:Xamarin.Forms.NavigationPage" /> element.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PopToRootAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task PopToRootAsync ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Threading.Tasks.Task PopToRootAsync() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Pops all but the root <see cref="T:Xamarin.Forms.Page" /> off the navigation stack.</summary>
+ <returns>A task that represents the asynchronous dismiss operation.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PopToRootAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task PopToRootAsync (bool animated);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Threading.Tasks.Task PopToRootAsync(bool animated) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.DebuggerStepThrough</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.AsyncStateMachine(typeof(Xamarin.Forms.NavigationPage/&lt;PopToRootAsync&gt;d__71))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="animated" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="animated">To be added.</param>
+ <summary>A task for asynchronously popping all pages off of the navigation stack.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PushAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task PushAsync (Xamarin.Forms.Page page);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Threading.Tasks.Task PushAsync(class Xamarin.Forms.Page page) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="page" Type="Xamarin.Forms.Page" />
+ </Parameters>
+ <Docs>
+ <param name="page">The <see cref="T:Xamarin.Forms.Page" /> to present modally.</param>
+ <summary>Presents a <see cref="T:Xamarin.Forms.Page" /> modally.</summary>
+ <returns>An awaitable Task, indicating the PushModal completion.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PushAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task PushAsync (Xamarin.Forms.Page page, bool animated);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Threading.Tasks.Task PushAsync(class Xamarin.Forms.Page page, bool animated) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.DebuggerStepThrough</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.AsyncStateMachine(typeof(Xamarin.Forms.NavigationPage/&lt;PushAsync&gt;d__65))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="page" Type="Xamarin.Forms.Page" />
+ <Parameter Name="animated" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="page">To be added.</param>
+ <param name="animated">To be added.</param>
+ <summary>A task for asynchronously pushing a page onto the navigation stack, with optional animation.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Pushed">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.NavigationEventArgs&gt; Pushed;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.NavigationEventArgs&gt; Pushed" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.NavigationEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when a page is pushed onto this <see cref="T:Xamarin.Forms.NavigationPage" /> element.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetBackButtonTitle">
+ <MemberSignature Language="C#" Value="public static void SetBackButtonTitle (Xamarin.Forms.BindableObject page, string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetBackButtonTitle(class Xamarin.Forms.BindableObject page, string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="page" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="page">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Sets the title that appears on the back button for <paramref name="page" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetHasBackButton">
+ <MemberSignature Language="C#" Value="public static void SetHasBackButton (Xamarin.Forms.Page page, bool value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetHasBackButton(class Xamarin.Forms.Page page, bool value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="page" Type="Xamarin.Forms.Page" />
+ <Parameter Name="value" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="page">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Adds or removes a back button to <paramref name="page" />, with optional animation.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetHasNavigationBar">
+ <MemberSignature Language="C#" Value="public static void SetHasNavigationBar (Xamarin.Forms.BindableObject page, bool value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetHasNavigationBar(class Xamarin.Forms.BindableObject page, bool value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="page" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="value" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="page">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Sets a value that indicates whether or not this <see cref="T:Xamarin.Forms.NavigationPage" /> element has a navigation bar.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetTitleIcon">
+ <MemberSignature Language="C#" Value="public static void SetTitleIcon (Xamarin.Forms.BindableObject bindable, Xamarin.Forms.FileImageSource value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetTitleIcon(class Xamarin.Forms.BindableObject bindable, class Xamarin.Forms.FileImageSource value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="value" Type="Xamarin.Forms.FileImageSource" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">The <see cref="T:Xamarin.Forms.BindableObject" /> whose title icon is being set.</param>
+ <param name="value">The FileImageSource of the icon.</param>
+ <summary>Sets the title icon of the <paramref name="bindable" /> to the icon file at <paramref name="value" />.</summary>
+ <remarks>
+ <example>
+ <code lang="C#"><![CDATA[
+public class MyPage : NavigationPage
+{
+ public MyPage ()
+ {
+ var myContentPage = new MyContentPage (Color.White);
+ this.Push (myContentPage);
+
+ var s = "icon-45.png";
+ NavigationPage.SetTitleIcon (myContentPage, s);
+ }
+}
+ ]]></code>
+ </example>
+ <para>
+ <img href="NavigationPage.TitleIcon.png" />
+ </para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Tint">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color Tint { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color Tint" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use BarBackgroundColor and BarTextColor to change NavigationPage bar color properties")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The color to be used as the Tint of the <see cref="T:Xamarin.Forms.NavigationPage" />.</summary>
+ <value>To be added.</value>
+ <remarks>
+ <para>Tint is especially important in iOS 7 and later, where the Tint is primary way to specify which controls on screen are active or have an action associated with them.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TintProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TintProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TintProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use BarBackgroundColorProperty and BarTextColorProperty to change NavigationPage bar color properties")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.NavigationPage.Tint" /> bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TitleIconProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TitleIconProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TitleIconProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates the <see cref="M:Xamarin.Forms.NavigationPage.SetTitleIcon" />/<see cref="M:Xamarin.Forms.NavigationPage.GetTitleIcon" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/OnIdiom`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/OnIdiom`1.xml
new file mode 100644
index 00000000..14b412e8
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/OnIdiom`1.xml
@@ -0,0 +1,127 @@
+<Type Name="OnIdiom&lt;T&gt;" FullName="Xamarin.Forms.OnIdiom&lt;T&gt;">
+ <TypeSignature Language="C#" Value="public class OnIdiom&lt;T&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit OnIdiom`1&lt;T&gt; extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="T" />
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <summary>Provides idiom-specific implementation of T for the current TargetIdiom.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public OnIdiom ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of OnIdiom</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Implicit">
+ <MemberSignature Language="C#" Value="public static T op_Implicit (Xamarin.Forms.OnIdiom&lt;T&gt; onIdiom);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname !T op_Implicit(class Xamarin.Forms.OnIdiom`1&lt;!T&gt; onIdiom) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="onIdiom" Type="Xamarin.Forms.OnIdiom&lt;T&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="onIdiom">To be added.</param>
+ <summary>Implicitly converts OnIdiom to T, depending on Device.Idiom.</summary>
+ <returns>The value of the Phone or Tablet property, depending on the current Device.Idiom.</returns>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Phone">
+ <MemberSignature Language="C#" Value="public T Phone { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance !T Phone" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the value applied on Phone-like devices.</summary>
+ <value>A T.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Tablet">
+ <MemberSignature Language="C#" Value="public T Tablet { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance !T Tablet" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the value applied on Tablet-like devices.</summary>
+ <value>A T.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/OnPlatform`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/OnPlatform`1.xml
new file mode 100644
index 00000000..38714876
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/OnPlatform`1.xml
@@ -0,0 +1,139 @@
+<Type Name="OnPlatform&lt;T&gt;" FullName="Xamarin.Forms.OnPlatform&lt;T&gt;">
+ <TypeSignature Language="C#" Value="public class OnPlatform&lt;T&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit OnPlatform`1&lt;T&gt; extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="T" />
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <summary>Provides the platform-specific implementation of T for the current <see cref="P:Xamarin.Forms.Device.OS" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public OnPlatform ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new instance of the <see cref="T:Xamarin.Forms.OnPlatform" /> type.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Android">
+ <MemberSignature Language="C#" Value="public T Android { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance !T Android" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The type as it is implemented on the Android platform.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="iOS">
+ <MemberSignature Language="C#" Value="public T iOS { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance !T iOS" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The type as it is implemented on the iOS platform.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Implicit">
+ <MemberSignature Language="C#" Value="public static T op_Implicit (Xamarin.Forms.OnPlatform&lt;T&gt; onPlatform);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname !T op_Implicit(class Xamarin.Forms.OnPlatform`1&lt;!T&gt; onPlatform) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="onPlatform" Type="Xamarin.Forms.OnPlatform&lt;T&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="onPlatform">To be added.</param>
+ <summary>Casts the type to the version that corresponds to the platform.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="WinPhone">
+ <MemberSignature Language="C#" Value="public T WinPhone { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance !T WinPhone" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The type as it is implemented on the WinPhone platform.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/OpenGLView.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/OpenGLView.xml
new file mode 100644
index 00000000..303a1565
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/OpenGLView.xml
@@ -0,0 +1,221 @@
+<Type Name="OpenGLView" FullName="Xamarin.Forms.OpenGLView">
+ <TypeSignature Language="C#" Value="public sealed class OpenGLView : Xamarin.Forms.View, Xamarin.Forms.IOpenGLViewController" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit OpenGLView extends Xamarin.Forms.View implements class Xamarin.Forms.IElementController, class Xamarin.Forms.IOpenGLViewController, class Xamarin.Forms.IViewController, class Xamarin.Forms.IVisualElementController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IOpenGLViewController</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._OpenGLViewRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.View" /> that displays OpenGL content.</summary>
+ <remarks>
+ <para>
+ <see cref="T:Xamarin.Forms.OpenGLView" />s are easiest to program using Shared Projects, in which case the reference to OpenTK is straightforward. The following example shows a simple OpenGL app with a render loop:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+using Xamarin.Forms;
+using OpenTK.Graphics.ES30;
+
+namespace opengl
+{
+ public class OpenGLPage : ContentPage
+ {
+ float red, green, blue;
+
+ public OpenGLPage ()
+ {
+ Title = "OpenGL";
+ var view = new OpenGLView { HasRenderLoop = true };
+ var toggle = new Switch { IsToggled = true };
+ var button = new Button { Text = "Display" };
+
+ view.HeightRequest = 300;
+ view.WidthRequest = 300;
+
+ view.OnDisplay = r => {
+
+ GL.ClearColor (red, green, blue, 1.0f);
+ GL.Clear ((ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit));
+
+ red += 0.01f;
+ if (red >= 1.0f)
+ red -= 1.0f;
+ green += 0.02f;
+ if (green >= 1.0f)
+ green -= 1.0f;
+ blue += 0.03f;
+ if (blue >= 1.0f)
+ blue -= 1.0f;
+ };
+
+ toggle.Toggled += (s, a) => {
+ view.HasRenderLoop = toggle.IsToggled;
+ };
+ button.Clicked += (s, a) => view.Display ();
+
+ var stack = new StackLayout {
+ Padding = new Size (20, 20),
+ Children = {view, toggle, button}
+ };
+
+ Content = stack;
+ }
+ }
+}
+
+ ]]></code>
+ </example>
+ <para>
+ <img href="OpenGL.Example.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public OpenGLView ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.OpenGLView" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Display">
+ <MemberSignature Language="C#" Value="public void Display ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void Display() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Called prior to rendering.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasRenderLoop">
+ <MemberSignature Language="C#" Value="public bool HasRenderLoop { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool HasRenderLoop" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Whether this <see cref="T:Xamarin.Forms.OpenGLView" /> has a custom rendering loop.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasRenderLoopProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HasRenderLoopProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HasRenderLoopProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.OpenGLView.HasRenderLoop" /> bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnDisplay">
+ <MemberSignature Language="C#" Value="public Action&lt;Xamarin.Forms.Rectangle&gt; OnDisplay { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Action`1&lt;valuetype Xamarin.Forms.Rectangle&gt; OnDisplay" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Action&lt;Xamarin.Forms.Rectangle&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Overridden to create a custom rendering loop.</summary>
+ <value>To be added.</value>
+ <remarks>
+ <para>When overridden, creates a custom renderer: </para>
+ <example>
+ <code lang="C#"><![CDATA[
+ var view = new OpenGLView { HasRenderLoop = true };
+ view.OnDisplay = r => {
+
+ GL.ClearColor (red, green, blue, 1.0f);
+ GL.Clear ((ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit));
+
+ red += 0.01f;
+ if (red >= 1.0f)
+ red -= 1.0f;
+ green += 0.02f;
+ if (green >= 1.0f)
+ green -= 1.0f;
+ blue += 0.03f;
+ if (blue >= 1.0f)
+ blue -= 1.0f;
+ };
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Page.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Page.xml
new file mode 100644
index 00000000..2c12d59c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Page.xml
@@ -0,0 +1,875 @@
+<Type Name="Page" FullName="Xamarin.Forms.Page">
+ <TypeSignature Language="C#" Value="public class Page : Xamarin.Forms.VisualElement, Xamarin.Forms.ILayout" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Page extends Xamarin.Forms.VisualElement implements class Xamarin.Forms.ILayout" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.VisualElement</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.ILayout</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._PageRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.VisualElement" /> that occupies the entire screen.</summary>
+ <remarks>
+ <para>
+ <see cref="T:Xamarin.Forms.Page" /> is primarily a base class for more useful derived types. Objects that are derived from the see <see cref="T:Xamarin.Forms.Page" /> class are most prominently used as the top level UI element in Xamarin.Forms applications. Typically, application developers will provide such an object to the target platforms by returning it from a static method that the developer created in a project that references <see cref="N:Xamarin.Forms" />. The contents of a typical App.cs file that would appear in a project that reference <see cref="N:Xamarin.Forms" /> are shown below:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+using System;
+using Xamarin.Forms;
+
+namespace MyFirstFormsApp
+{
+ public class App : Application
+ {
+
+ public App()
+ {
+ MainPage = new ContentPage {
+ Content = new Label {
+ Text = "Hello, Forms!",
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ HorizontalOptions = LayoutOptions.CenterAndExpand,
+ }
+ };
+ }
+ protected override void OnStart ()
+ {
+ // Handle when your app starts
+ }
+
+ protected override void OnSleep ()
+ {
+ // Handle when your app sleeps
+ }
+
+ protected override void OnResume ()
+ {
+ // Handle when your app resumes
+ }
+ }
+}]]></code>
+ </example>
+ <para>While a <see cref="T:Xamarin.Forms.ContentPage" /> object was returned in the example above, note that any class that extends <see cref="T:Xamarin.Forms.Page" /> could have been passed, instead. For example, by using conditional compilation or by checking the platform, the developr can pass a <see cref="T:Xamarin.Forms.CarouselPage" /> to Windows Phone applications, in order to better match the style of the user interface on that platform, while passing <see cref="T:Xamarin.Forms.ContentPage" /> objects or other Page types to the other platforms.</para>
+ <para>The other projects in the solution that target the Windows Phone, iOS, and Android platforms can call the GetMainPage method to obtain the <see cref="T:Xamarin.Forms.Page" /> descendant that describes the portable user interface. This object can then be used with platform-specific static methods or extension methods to incorporate it into the native UI for each platform.</para>
+ <note>On all platforms, Application developers must call the <see cref="M:Xamarin.Forms.Forms.Init" /> method before they get or create any <see cref="N:Xamarin.Forms" /> elements.</note>
+ <para>Each targeted platform uses the returned page in a different way. The <c>Xamarin.Forms.Platform.iOS</c> library provides <c>Xamarin.Forms.Page.CreateViewController()</c> extension method, which returns a UIViewController that application developers can assign to the <c>UIWindow.RootViewController</c> property of the top-level UI. This code is typically placed inside the <c>UIApplicationDelegate.FinishedLaunching</c> override for the main application class. A typical example is shown below:</para>
+ <example>
+ <code lang="C#">
+using System;
+using Xamarin.Forms;
+
+namespace MyFirstFormsApp.iOS
+{
+ [Register("AppDelegate")]
+ public partial class AppDelegate : UIApplicationDelegate
+ {
+ UIWindow window;
+
+ public override bool FinishedLaunching(UIApplication app,
+ NSDictionary options)
+ {
+ Forms.Init();
+
+ window = new UIWindow(UIScreen.MainScreen.Bounds);
+
+ window.RootViewController = App.GetMainPage().CreateViewController();
+ window.MakeKeyAndVisible();
+
+ return true;
+ }
+ }
+}
+
+</code>
+ </example>
+ <para>The Xamarin.Forms.Platform.Android.AndroidActivity class provides the <c>Xamarin.Forms.Platform.Android.AndroidActivity.SetPage</c> method, which performs the work that is necessary to make its page argument the top-level UI element of the <c>Xamarin.Forms.Platform.Android.AndroidActivity</c>. A typical example is shown below:</para>
+ <example>
+ <code lang="C#">
+using System;
+using Android.App;
+using Android.OS;
+using Xamarin.Forms.Platform.Android;
+
+
+namespace MyFirstFormsApp.Android
+{
+ [Activity(Label = "MyFirstFormsApp", MainLauncher = true)]
+ public class MainActivity : AndroidActivity
+ {
+ protected override void OnCreate(Bundle bundle)
+ {
+ base.OnCreate(bundle);
+
+ Xamarin.Forms.Forms.Init(this, bundle);
+
+ SetPage(App.GetMainPage());
+ }
+ }
+}
+</code>
+ </example>
+ <para>For Windows Phone, <see cref="N:Xamarin.Forms" /> provides an extension method for <see cref="T:Xamarin.Forms.Page" /> that is called <see cref="M:Xamarin.Forms.Page.ConvertPageToUIElement" />. This method returns a System.Windows.UIElement object that has the page that was passed to it as its current page. A typical example is shown below:</para>
+ <example>
+ <code lang="C#">
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Navigation;
+using Microsoft.Phone.Controls;
+using Microsoft.Phone.Shell;
+
+using Xamarin.Forms;
+
+
+namespace MyFirstFormsApp.WinPhone
+{
+ public partial class MainPage : PhoneApplicationPage
+ {
+ public MainPage()
+ {
+ InitializeComponent();
+
+ Forms.Init();
+ Content = Phoneword.App.GetMainPage().ConvertPageToUIElement(this);
+ }
+ }
+} </code>
+ </example>
+ <para>In addition to their role as the main pages of <see cref="N:Xamarin.Forms" /> applications, <see cref="T:Xamarin.Forms.Page" /> objects and their descendants can be used with navigation classes, such as <see cref="T:Xamarin.Forms.Navigation" /> or <see cref="T:Xamarin.Forms.MasterDetailPage" />, among others, to provide rich user experiences that conform to the expected behaviors on each platform.</para>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.Page" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>BackgroundImage</term>
+ <description>
+ <para>A local file specification that identifies an image.</para>
+ </description>
+ </item>
+ <item>
+ <term>Icon</term>
+ <description>
+ <para>A local file specification that identifies an image.</para>
+ </description>
+ </item>
+ <item>
+ <term>Padding</term>
+ <description>
+ <para>A comma-separated list of 4 integers that represent a <see cref="T:Xamarin.Forms.Thickness" /> structure.</para>
+ </description>
+ </item>
+ <item>
+ <term>Title</term>
+ <description>
+ <para>Text that represents the title of the page.</para>
+ </description>
+ </item>
+ <item>
+ <term>ToolbarItems</term>
+ <description>
+ <para>A list of <c>ToolBarItem</c> elements.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Page ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Page" /> element with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Appearing">
+ <MemberSignature Language="C#" Value="public event EventHandler Appearing;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Appearing" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that the <see cref="T:Xamarin.Forms.Page" /> is about to appear.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BackgroundImage">
+ <MemberSignature Language="C#" Value="public string BackgroundImage { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string BackgroundImage" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the image used as a background for the <see cref="T:Xamarin.Forms.Page" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BackgroundImageProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty BackgroundImageProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty BackgroundImageProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.Page.BackgroundImage" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Disappearing">
+ <MemberSignature Language="C#" Value="public event EventHandler Disappearing;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Disappearing" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that the <see cref="T:Xamarin.Forms.Page" /> is about to cease displaying.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="DisplayActionSheet">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task&lt;string&gt; DisplayActionSheet (string title, string cancel, string destruction, string[] buttons);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Threading.Tasks.Task`1&lt;string&gt; DisplayActionSheet(string title, string cancel, string destruction, string[] buttons) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.String&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="title" Type="System.String" />
+ <Parameter Name="cancel" Type="System.String" />
+ <Parameter Name="destruction" Type="System.String" />
+ <Parameter Name="buttons" Type="System.String[]">
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.ParamArray</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Parameter>
+ </Parameters>
+ <Docs>
+ <param name="title">Title of the displayed action sheet. Must not be <see langword="null" />.</param>
+ <param name="cancel">Text to be displayed in the 'Cancel' button. Can be <see langword="null" /> to hide the cancel action.</param>
+ <param name="destruction">Text to be displayed in the 'Destruct' button. Can be <see langword="null" /> to hide the destructive option.</param>
+ <param name="buttons">Text labels for additional buttons. Must not be <see langword="null" />.</param>
+ <summary>Displays a native platform action sheet, allowing the application user to choose from several buttons.</summary>
+ <returns>An awaitable Task that displays an action sheet and returns the Text of the button pressed by the user.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="DisplayAlert">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task DisplayAlert (string title, string message, string cancel);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Threading.Tasks.Task DisplayAlert(string title, string message, string cancel) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="title" Type="System.String" />
+ <Parameter Name="message" Type="System.String" />
+ <Parameter Name="cancel" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="title">The title of the alert dialog.</param>
+ <param name="message">The body text of the alert dialog.</param>
+ <param name="cancel">Text to be displayed on the 'Cancel' button.</param>
+ <summary>Presents an alert dialog to the application user with a single cancel button.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="DisplayAlert">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task&lt;bool&gt; DisplayAlert (string title, string message, string accept, string cancel);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Threading.Tasks.Task`1&lt;bool&gt; DisplayAlert(string title, string message, string accept, string cancel) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="title" Type="System.String" />
+ <Parameter Name="message" Type="System.String" />
+ <Parameter Name="accept" Type="System.String" />
+ <Parameter Name="cancel" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="title">The title of the alert dialog.</param>
+ <param name="message">The body text of the alert dialog.</param>
+ <param name="accept">Text to be displayed on the 'Accept' button.</param>
+ <param name="cancel">Text to be displayed on the 'Cancel' button.</param>
+ <summary>Presents an alert dialog to the application user with an accept and a cancel button.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ForceLayout">
+ <MemberSignature Language="C#" Value="public void ForceLayout ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void ForceLayout() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Forces the <see cref="T:Xamarin.Forms.Page" /> to perform a layout pass.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Icon">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.FileImageSource Icon { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.FileImageSource Icon" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FileImageSource</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Resource identifier for the <see cref="T:Xamarin.Forms.Page" />'s associated icon.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IconProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IconProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IconProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.Page.Icon" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsBusy">
+ <MemberSignature Language="C#" Value="public bool IsBusy { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsBusy" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Marks the Page as busy. This will cause the platform specific global activity indicator to show a busy state.</summary>
+ <value>A bool indicating if the Page is busy or not.</value>
+ <remarks>Setting IsBusy to true on multiple pages at once will cause the global activity indicator to run until both are set back to false. It is the authors job to unset the IsBusy flag before cleaning up a Page.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsBusyProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsBusyProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsBusyProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.Page.IsBusy" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler LayoutChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler LayoutChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Raised when the layout of the <see cref="T:Xamarin.Forms.Page" /> has changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutChildren">
+ <MemberSignature Language="C#" Value="protected virtual void LayoutChildren (double x, double y, double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void LayoutChildren(float64 x, float64 y, float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">Left-hand side of layout area.</param>
+ <param name="y">Top of layout area.</param>
+ <param name="width">Width of layout area.</param>
+ <param name="height">Height of layout area.</param>
+ <summary>Lays out children <see cref="T:Xamarin.Forms.Element" />s into the specified area.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnAppearing">
+ <MemberSignature Language="C#" Value="protected virtual void OnAppearing ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnAppearing() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>When overridden, allows application developers to customize behavior immediately prior to the <see cref="T:Xamarin.Forms.Page" /> becoming visible.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBackButtonPressed">
+ <MemberSignature Language="C#" Value="protected virtual bool OnBackButtonPressed ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance bool OnBackButtonPressed() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Application developers can override this method to provide behavior when the back button is pressed.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBindingContextChanged">
+ <MemberSignature Language="C#" Value="protected override void OnBindingContextChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnBindingContextChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>
+ Invoked whenever the binding context of the <see cref="T:Xamarin.Forms.Page" /> changes. Override this method to add class handling for this event.
+ </summary>
+ <remarks>
+ <para>Overriders must call the base method.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnChildMeasureInvalidated">
+ <MemberSignature Language="C#" Value="protected virtual void OnChildMeasureInvalidated (object sender, EventArgs e);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnChildMeasureInvalidated(object sender, class System.EventArgs e) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sender" Type="System.Object" />
+ <Parameter Name="e" Type="System.EventArgs" />
+ </Parameters>
+ <Docs>
+ <param name="sender">To be added.</param>
+ <param name="e">To be added.</param>
+ <summary>Indicates that the preferred size of a child <see cref="T:Xamarin.Forms.Element" /> has changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnDisappearing">
+ <MemberSignature Language="C#" Value="protected virtual void OnDisappearing ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnDisappearing() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>When overridden, allows the application developer to customize behavior as the <see cref="T:Xamarin.Forms.Page" /> disappears.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnParentSet">
+ <MemberSignature Language="C#" Value="protected override void OnParentSet ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnParentSet() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Called when the <see cref="T:Xamarin.Forms.Page" />'s <see cref="P:Xamarin.Forms.Element.Parent" /> property has changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeAllocated">
+ <MemberSignature Language="C#" Value="protected override void OnSizeAllocated (double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnSizeAllocated(float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="width">The width allocated to the <see cref="T:Xamarin.Forms.Page" />.</param>
+ <param name="height">The height allocated to the <see cref="T:Xamarin.Forms.Page" />.</param>
+ <summary>Indicates that the <see cref="T:Xamarin.Forms.Page" /> has been assigned a size.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Padding">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Thickness Padding { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Thickness Padding" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Thickness</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The space between the content of the <see cref="T:Xamarin.Forms.Page" /> and it's border.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PaddingProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty PaddingProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty PaddingProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.Page.Padding" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SendBackButtonPressed">
+ <MemberSignature Language="C#" Value="public bool SendBackButtonPressed ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance bool SendBackButtonPressed() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Calls <see cref="M:Xamarin.Forms.Page.OnBackButtonPressed" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Title">
+ <MemberSignature Language="C#" Value="public string Title { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Title" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The <see cref="T:Xamarin.Forms.Page" />'s title.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TitleProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TitleProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TitleProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.Page.Title" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ToolbarItems">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.ToolbarItem&gt; ToolbarItems { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.ToolbarItem&gt; ToolbarItems" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.ToolbarItem&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A set of <see cref="T:Xamarin.Forms.ToolbarItem" />s, implemented in a platform-specific manner.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="UpdateChildrenLayout">
+ <MemberSignature Language="C#" Value="protected void UpdateChildrenLayout ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig instance void UpdateChildrenLayout() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Requests that the children <see cref="T:Xamarin.Forms.Element" />s of the <see cref="T:Xamarin.Forms.Page" /> update their layouts.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/PanGestureRecognizer.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/PanGestureRecognizer.xml
new file mode 100644
index 00000000..5918f36d
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/PanGestureRecognizer.xml
@@ -0,0 +1,82 @@
+<Type Name="PanGestureRecognizer" FullName="Xamarin.Forms.PanGestureRecognizer">
+ <TypeSignature Language="C#" Value="public class PanGestureRecognizer : Xamarin.Forms.GestureRecognizer" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit PanGestureRecognizer extends Xamarin.Forms.GestureRecognizer" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.GestureRecognizer</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A gesture recognizer for panning content that is larger than its parent view.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public PanGestureRecognizer ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.PanGestureRecognizer" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PanUpdated">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.PanUpdatedEventArgs&gt; PanUpdated;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.PanUpdatedEventArgs&gt; PanUpdated" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.PanUpdatedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the pan gesture changes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TouchPoints">
+ <MemberSignature Language="C#" Value="public int TouchPoints { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 TouchPoints" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the number of touch points in the gesture.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TouchPointsProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TouchPointsProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TouchPointsProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.PanGestureRecognizer.TouchPoints" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/PanUpdatedEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/PanUpdatedEventArgs.xml
new file mode 100644
index 00000000..69dd65d5
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/PanUpdatedEventArgs.xml
@@ -0,0 +1,129 @@
+<Type Name="PanUpdatedEventArgs" FullName="Xamarin.Forms.PanUpdatedEventArgs">
+ <TypeSignature Language="C#" Value="public class PanUpdatedEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit PanUpdatedEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Event that is raised when a pan gesture updates.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public PanUpdatedEventArgs (Xamarin.Forms.GestureStatus type, int gestureId);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(valuetype Xamarin.Forms.GestureStatus type, int32 gestureId) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="type" Type="Xamarin.Forms.GestureStatus" />
+ <Parameter Name="gestureId" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="type">Whether the gesture just began, is continuing, was completed, or is canceled.</param>
+ <param name="gestureId">An identifier for the gesture.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.PanUpdatedEventArgs" /> with the specified values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public PanUpdatedEventArgs (Xamarin.Forms.GestureStatus type, int gestureId, double totalx, double totaly);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(valuetype Xamarin.Forms.GestureStatus type, int32 gestureId, float64 totalx, float64 totaly) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="type" Type="Xamarin.Forms.GestureStatus" />
+ <Parameter Name="gestureId" Type="System.Int32" />
+ <Parameter Name="totalx" Type="System.Double" />
+ <Parameter Name="totaly" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="type">Whether the gesture just began, is continuing, was completed, or is canceled.</param>
+ <param name="gestureId">An identifier for the gesture.</param>
+ <param name="totalx">The total change in the X direction since the beginning of the gesture.</param>
+ <param name="totaly">The total change in the Y direction since the beginning of the gesture.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.PanUpdatedEventArgs" /> with the specified values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GestureId">
+ <MemberSignature Language="C#" Value="public int GestureId { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 GestureId" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the identifier for the gesture that raised the event.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="StatusType">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.GestureStatus StatusType { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.GestureStatus StatusType" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GestureStatus</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that tells if this event is for a newly started gesture, a running gesture, a completed gesture, or a canceled gesture.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TotalX">
+ <MemberSignature Language="C#" Value="public double TotalX { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 TotalX" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the total change in the X direction since the beginning of the gesture..</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TotalY">
+ <MemberSignature Language="C#" Value="public double TotalY { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 TotalY" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the total change in the Y direction since the beginning of the gesture..</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Picker.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Picker.xml
new file mode 100644
index 00000000..87d63758
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Picker.xml
@@ -0,0 +1,294 @@
+<Type Name="Picker" FullName="Xamarin.Forms.Picker">
+ <TypeSignature Language="C#" Value="public class Picker : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Picker extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._PickerRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.View" /> control for picking an element in a list.</summary>
+ <remarks>
+ <para>The visual representation of a Picker is similar to a <see cref="T:Xamarin.Forms.Entry" />, but a picker control appears in place of a keyboard.</para>
+ <para>The following example shows the creation of a Picker.</para>
+ <example>
+ <code lang="C#"><![CDATA[using System;
+using System.Collections.Generic;
+using Xamarin.Forms;
+
+namespace FormsGallery
+{
+ class PickerDemoPage : ContentPage
+ {
+ // Dictionary to get Color from color name.
+ Dictionary<string, Color> nameToColor = new Dictionary<string, Color>
+ {
+ { "Aqua", Color.Aqua }, { "Black", Color.Black },
+ { "Blue", Color.Blue }, { "Fuschia", Color.Fuschia },
+ { "Gray", Color.Gray }, { "Green", Color.Green },
+ { "Lime", Color.Lime }, { "Maroon", Color.Maroon },
+ { "Navy", Color.Navy }, { "Olive", Color.Olive },
+ { "Purple", Color.Purple }, { "Red", Color.Red },
+ { "Silver", Color.Silver }, { "Teal", Color.Teal },
+ { "White", Color.White }, { "Yellow", Color.Yellow }
+ };
+
+ public PickerDemoPage()
+ {
+ Label header = new Label
+ {
+ Text = "Picker",
+ FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ Picker picker = new Picker
+ {
+ Title = "Color",
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+
+ foreach (string colorName in nameToColor.Keys)
+ {
+ picker.Items.Add(colorName);
+ }
+
+ // Create BoxView for displaying picked Color
+ BoxView boxView = new BoxView
+ {
+ WidthRequest = 150,
+ HeightRequest = 150,
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+
+ picker.SelectedIndexChanged += (sender, args) =>
+ {
+ if (picker.SelectedIndex == -1)
+ {
+ boxView.Color = Color.Default;
+ }
+ else
+ {
+ string colorName = picker.Items[picker.SelectedIndex];
+ boxView.Color = nameToColor[colorName];
+ }
+ };
+
+ // Accomodate iPhone status bar.
+ this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
+
+ // Build the page.
+ this.Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ picker,
+ boxView
+ }
+ };
+
+ }
+ }
+}
+]]></code>
+ </example>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.Picker" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Items</term>
+ <description>
+ <para>A local file specification that identifies an image.</para>
+ </description>
+ </item>
+ <item>
+ <term>SelectedIndex</term>
+ <description>
+ <para>An integer, from 0 to 1 less than the count of items that are listed in <c>Items</c>. Currently, this element must be specified in a tag that appears lexically below <c>Items</c>.</para>
+ </description>
+ </item>
+ <item>
+ <term>Title</term>
+ <description>
+ <para>Text that represents the title of the picker.</para>
+ </description>
+ </item>
+ </list>
+ <para>
+ <img href="Picker.TripleScreenShot.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Picker ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the Picker class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Items">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;string&gt; Items { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;string&gt; Items" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;System.String&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the list of choices.</summary>
+ <value>An IList&lt;string&gt; representing the Picker choices.</value>
+ <remarks>This property is read-only, but exposes the IList&lt;&gt; interface, so items can be added using Add().</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SelectedIndex">
+ <MemberSignature Language="C#" Value="public int SelectedIndex { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 SelectedIndex" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the index of the slected item of the picker. This is a bindable property.</summary>
+ <value>An 0-based index representing the selected item in the list. Default is -1.</value>
+ <remarks>A value of -1 represents no item selected.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SelectedIndexChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler SelectedIndexChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler SelectedIndexChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Raised when the value of the SelectIndex property has changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SelectedIndexProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty SelectedIndexProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty SelectedIndexProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the SelectedIndex bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Title">
+ <MemberSignature Language="C#" Value="public string Title { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Title" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the title for the Picker. This is a bindable property.</summary>
+ <value>A string.</value>
+ <remarks>Depending on the platform, the Title is shown as a placeholder, headline, or not showed at all.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TitleProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TitleProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TitleProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Title bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/PinchGestureRecognizer.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/PinchGestureRecognizer.xml
new file mode 100644
index 00000000..e3ac0a7b
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/PinchGestureRecognizer.xml
@@ -0,0 +1,49 @@
+<Type Name="PinchGestureRecognizer" FullName="Xamarin.Forms.PinchGestureRecognizer">
+ <TypeSignature Language="C#" Value="public sealed class PinchGestureRecognizer : Xamarin.Forms.GestureRecognizer" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit PinchGestureRecognizer extends Xamarin.Forms.GestureRecognizer" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.GestureRecognizer</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Recognizer for pinch gestures.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public PinchGestureRecognizer ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Constructs a new pinch gesture recognizer.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PinchUpdated">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.PinchGestureUpdatedEventArgs&gt; PinchUpdated;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.PinchGestureUpdatedEventArgs&gt; PinchUpdated" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.PinchGestureUpdatedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when a pinch gesture updates.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/PinchGestureUpdatedEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/PinchGestureUpdatedEventArgs.xml
new file mode 100644
index 00000000..73671ec8
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/PinchGestureUpdatedEventArgs.xml
@@ -0,0 +1,117 @@
+<Type Name="PinchGestureUpdatedEventArgs" FullName="Xamarin.Forms.PinchGestureUpdatedEventArgs">
+ <TypeSignature Language="C#" Value="public class PinchGestureUpdatedEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit PinchGestureUpdatedEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Event arguments for the <see cref="E:Xamarin.Forms.PinchGestureRecognizer.PinchUpdated" /> event.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public PinchGestureUpdatedEventArgs (Xamarin.Forms.GestureStatus status);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(valuetype Xamarin.Forms.GestureStatus status) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="status" Type="Xamarin.Forms.GestureStatus" />
+ </Parameters>
+ <Docs>
+ <param name="status">To be added.</param>
+ <summary>Constructs a new <see cref="T:Xamarin.Forms.PinchGestureUpdatedEventArgs" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public PinchGestureUpdatedEventArgs (Xamarin.Forms.GestureStatus status, double scale, Xamarin.Forms.Point origin);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(valuetype Xamarin.Forms.GestureStatus status, float64 scale, valuetype Xamarin.Forms.Point origin) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="status" Type="Xamarin.Forms.GestureStatus" />
+ <Parameter Name="scale" Type="System.Double" />
+ <Parameter Name="origin" Type="Xamarin.Forms.Point" />
+ </Parameters>
+ <Docs>
+ <param name="status">Whether the gesture is starting, running, or has ended.</param>
+ <param name="scale">The current scale of the pinch gesture.</param>
+ <param name="origin">The updated origin of the pinch gesture.</param>
+ <summary>Constructs a new <see cref="T:Xamarin.Forms.PinchGestureUpdatedEventArgs" /> object with the specified values.</summary>
+ <remarks>
+ <para>The origin of the pinch is the center of the pinch gesture, and changes if the user translates their pinch while they scale. Application developers may want to store the pinch origin when the gesture begins and use it for all scaling operations for that gesture.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Scale">
+ <MemberSignature Language="C#" Value="public double Scale { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Scale" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The relative size of the user's pinch gesture.</summary>
+ <value>The distance between the user's digits, divided by the initial distance between the user's digits in the pinch gesture.</value>
+ <remarks>
+ <para>The initial value of the <see cref="P:Xamarin.Forms.PinchGestureUpdatedEventArgs.Scale" /> property for each new pinch gesture is <c>1.0</c>.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ScaleOrigin">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Point ScaleOrigin { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Point ScaleOrigin" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Point</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The updated origin of the pinch gesture.</summary>
+ <value>The midpoint of the pinch gesture.</value>
+ <remarks>
+ <para>The origin of the pinch is the center of the pinch gesture, and changes if the user translates their pinch while they scale. Application developers may want to store the pinch origin when the gesture begins and use it for all scaling operations for that gesture.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Status">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.GestureStatus Status { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.GestureStatus Status" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GestureStatus</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Whether the gesture started, is running, or has finished.</summary>
+ <value>Whether the gesture started, is running, or has finished.</value>
+ <remarks>
+ <para>The origin of the pinch, <see cref="P:Xamarin.Forms.PinchGestureUpdatedEventArgs.ScaleOrigin" />, is the center of the pinch gesture, and changes if the user translates their pinch while they scale. Application developers may want to store the pinch origin when the gesture begins and use it for all scaling operations for that gesture.</para>
+ <para>The initial value of the <see cref="P:Xamarin.Forms.PinchGestureUpdatedEventArgs.Scale" /> property for each new pinch gesture is <c>1.0</c>.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/PlatformEffect`2.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/PlatformEffect`2.xml
new file mode 100644
index 00000000..25fda9a6
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/PlatformEffect`2.xml
@@ -0,0 +1,103 @@
+<Type Name="PlatformEffect&lt;TContainer,TControl&gt;" FullName="Xamarin.Forms.PlatformEffect&lt;TContainer,TControl&gt;">
+ <TypeSignature Language="C#" Value="public abstract class PlatformEffect&lt;TContainer,TControl&gt; : Xamarin.Forms.Effect where TContainer : class where TControl : class" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit PlatformEffect`2&lt;class TContainer, class TControl&gt; extends Xamarin.Forms.Effect" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="TContainer">
+ <Constraints>
+ <ParameterAttribute>ReferenceTypeConstraint</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ <TypeParameter Name="TControl">
+ <Constraints>
+ <ParameterAttribute>ReferenceTypeConstraint</ParameterAttribute>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Effect</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <typeparam name="TContainer">To be added.</typeparam>
+ <typeparam name="TControl">To be added.</typeparam>
+ <summary>Base class for platform-specific effect classes.</summary>
+ <remarks><para>App developers derive from the
+ <list type="bullet">
+ <item><term><c>Xamarin.Forms.Platform.Android.PlatformEffect</c>,</term></item>
+ <item><term><c>Xamarin.Forms.Platform.iOS.PlatformEffect</c>,</term></item>
+ <item><term><c>Xamarin.Forms.Platform.UWP.PlatformEffect</c>, or</term></item>
+ <item><term><c>Xamarin.Forms.Platform.WinPhone.PlatformEffect</c></term></item>
+ </list>
+ classes to implement effects on the respective platforms.</para></remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected PlatformEffect ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new platform-specific effect with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Container">
+ <MemberSignature Language="C#" Value="public TContainer Container { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance !TContainer Container" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>TContainer</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Returns the container for the platform-specific effect.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Control">
+ <MemberSignature Language="C#" Value="public TControl Control { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance !TControl Control" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>TControl</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Returns the control for the platform-specific effect.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnElementPropertyChanged">
+ <MemberSignature Language="C#" Value="protected virtual void OnElementPropertyChanged (System.ComponentModel.PropertyChangedEventArgs args);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnElementPropertyChanged(class System.ComponentModel.PropertyChangedEventArgs args) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="args" Type="System.ComponentModel.PropertyChangedEventArgs" />
+ </Parameters>
+ <Docs>
+ <param name="args">The arguments for the property changed event.</param>
+ <summary>Method that is called when a element property has changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Point.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Point.xml
new file mode 100644
index 00000000..57be657b
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Point.xml
@@ -0,0 +1,459 @@
+<Type Name="Point" FullName="Xamarin.Forms.Point">
+ <TypeSignature Language="C#" Value="public struct Point" />
+ <TypeSignature Language="ILAsm" Value=".class public sequential ansi sealed beforefieldinit Point extends System.ValueType" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.ValueType</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.DebuggerDisplay("X={X}, Y={Y}")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.PointTypeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Struct defining a 2-D point as a pair of doubles.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Point (Xamarin.Forms.Size sz);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(valuetype Xamarin.Forms.Size sz) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="sz" Type="Xamarin.Forms.Size" />
+ </Parameters>
+ <Docs>
+ <param name="sz">
+ <see cref="T:Xamarin.Forms.Size" /> that specifies a <see cref="T:Xamarin.Forms.Point" /> that has the coordinates (<see cref="P:Xamarin.Forms.Size.width" />, <see cref="P:Xamarin.Forms.Size.height" />).</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Point" /> object that has coordinates that are specified by the width and height of <paramref name="sz" />, in that order.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Point (double x, double y);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 x, float64 y) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">The horizontal coordinate.</param>
+ <param name="y">The vertical coordinate.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Point" /> object that represents the point (<paramref name="x" />,<paramref name="y" />).</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Distance">
+ <MemberSignature Language="C#" Value="public double Distance (Xamarin.Forms.Point other);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance float64 Distance(valuetype Xamarin.Forms.Point other) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="other" Type="Xamarin.Forms.Point" />
+ </Parameters>
+ <Docs>
+ <param name="other">The <see cref="T:Xamarin.Forms.Point" /> to which the distance is calculated.</param>
+ <summary>Calculates the distance between two points.</summary>
+ <returns>The distance between <c>this</c> and the <paramref name="other" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Equals">
+ <MemberSignature Language="C#" Value="public override bool Equals (object o);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool Equals(object o) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="o" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="o">Another <see cref="T:Xamarin.Forms.Point" />.</param>
+ <summary>Returns <see langword="true" /> if the X and Y values of this are exactly equal to those in the argument.</summary>
+ <returns>
+ <see langword="true" /> if the X and Y values are equal to those in <paramref name="o" />. Returns <see langword="false" /> if <paramref name="o" /> is not a <see cref="T:Xamarin.Forms.Point" />.</returns>
+ <remarks>
+ <para>The <see cref="P:Xamarin.Forms.Point.X" /> and <see cref="P:Xamarin.Forms.Point.Y" /> values of the <see cref="T:Xamarin.Forms.Point" /> are stored as <see langword="double" />s. Developers should be aware of the precision limits and issues that can arise when comparing floating-point values. In some circumstances, developers should consider the possibility of measuring approximate equality using the (considerably slower) <see cref="M:Xamarin.Forms.Point.Distance" /> method.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetHashCode">
+ <MemberSignature Language="C#" Value="public override int GetHashCode ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance int32 GetHashCode() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns a hash value for the <see cref="T:Xamarin.Forms.Point" />.</summary>
+ <returns>A value intended for efficient insertion and lookup in hashtable-based data structures.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsEmpty">
+ <MemberSignature Language="C#" Value="public bool IsEmpty { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsEmpty" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Whether both X and Y are 0.</summary>
+ <value>
+ <see langword="true" /> if both <see cref="P:Xamarin.Forms.Point.X" /> and <see cref="P:Xamarin.Forms.Point.Y" /> are 0.0.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Offset">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Point Offset (double dx, double dy);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Point Offset(float64 dx, float64 dy) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Point</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="dx" Type="System.Double" />
+ <Parameter Name="dy" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="dx">The amount to add along the X axis.</param>
+ <param name="dy">The amount to add along the Y axis.</param>
+ <summary>Returns a new <see cref="T:Xamarin.Forms.Point" /> that translates the current <see cref="T:Xamarin.Forms.Point" /> by <paramref name="dx" /> and <paramref name="dy" />.</summary>
+ <returns>A new <see cref="T:Xamarin.Forms.Point" /> at <c>[this.X + dx, this.Y + dy]</c>.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Addition">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Point op_Addition (Xamarin.Forms.Point pt, Xamarin.Forms.Size sz);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname valuetype Xamarin.Forms.Point op_Addition(valuetype Xamarin.Forms.Point pt, valuetype Xamarin.Forms.Size sz) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Point</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="pt" Type="Xamarin.Forms.Point" />
+ <Parameter Name="sz" Type="Xamarin.Forms.Size" />
+ </Parameters>
+ <Docs>
+ <param name="pt">The <see cref="T:Xamarin.Forms.Point" /> to which <paramref name="sz" /> is being added.</param>
+ <param name="sz">The values to add to <paramref name="pt" />.</param>
+ <summary>Returns a new <see cref="T:Xamarin.Forms.Point" /> by adding a <see cref="T:Xamarin.Forms.Size" /> to a <see cref="T:Xamarin.Forms.Point" />.</summary>
+ <returns>A new <see cref="T:Xamarin.Forms.Point" /> at <c>[pt.X + sz.Width, pt.Y + sz.Height]</c>.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Equality">
+ <MemberSignature Language="C#" Value="public static bool op_Equality (Xamarin.Forms.Point pt_a, Xamarin.Forms.Point pt_b);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Equality(valuetype Xamarin.Forms.Point pt_a, valuetype Xamarin.Forms.Point pt_b) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="pt_a" Type="Xamarin.Forms.Point" />
+ <Parameter Name="pt_b" Type="Xamarin.Forms.Point" />
+ </Parameters>
+ <Docs>
+ <param name="pt_a">A <see cref="T:Xamarin.Forms.Point" /> to be compared.</param>
+ <param name="pt_b">A <see cref="T:Xamarin.Forms.Point" /> to be compared.</param>
+ <summary>Whether the two <see cref="T:Xamarin.Forms.Point" />s are equal.</summary>
+ <returns>
+ <see langword="true" /> if the two <see cref="T:Xamarin.Forms.Point" />s have equal values.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Explicit">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Size op_Explicit (Xamarin.Forms.Point pt);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname valuetype Xamarin.Forms.Size op_Explicit(valuetype Xamarin.Forms.Point pt) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Size</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="pt" Type="Xamarin.Forms.Point" />
+ </Parameters>
+ <Docs>
+ <param name="pt">The <see cref="T:Xamarin.Forms.Point" /> to be translated as a <see cref="T:Xamarin.Forms.Size" />.</param>
+ <summary>Returns a new <see cref="T:Xamarin.Forms.Size" /> whose <see cref="P:Xamarin.Forms.Size.Width" /> and <see cref="P:Xamarin.Forms.Size.Height" /> and equivalent to the <paramref name="pt" />'s <see cref="P:Xamarin.Forms.Point.X" /> and <see cref="P:Xamarin.Forms.Point.Y" /> properties.</summary>
+ <returns>A new <see cref="T:Xamarin.Forms.Size" /> based on the <paramref name="pt" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Inequality">
+ <MemberSignature Language="C#" Value="public static bool op_Inequality (Xamarin.Forms.Point pt_a, Xamarin.Forms.Point pt_b);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Inequality(valuetype Xamarin.Forms.Point pt_a, valuetype Xamarin.Forms.Point pt_b) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="pt_a" Type="Xamarin.Forms.Point" />
+ <Parameter Name="pt_b" Type="Xamarin.Forms.Point" />
+ </Parameters>
+ <Docs>
+ <param name="pt_a">A <see cref="T:Xamarin.Forms.Point" /> to be compared.</param>
+ <param name="pt_b">A <see cref="T:Xamarin.Forms.Point" /> to be compared.</param>
+ <summary>Whether two points are not equal.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="pt_a" /> and <paramref name="pt_b" /> do not have equivalent X and Y values.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Subtraction">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Point op_Subtraction (Xamarin.Forms.Point pt, Xamarin.Forms.Size sz);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname valuetype Xamarin.Forms.Point op_Subtraction(valuetype Xamarin.Forms.Point pt, valuetype Xamarin.Forms.Size sz) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Point</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="pt" Type="Xamarin.Forms.Point" />
+ <Parameter Name="sz" Type="Xamarin.Forms.Size" />
+ </Parameters>
+ <Docs>
+ <param name="pt">The <see cref="T:Xamarin.Forms.Point" /> from which <paramref name="sz" /> is to be subtracted.</param>
+ <param name="sz">The <see cref="T:Xamarin.Forms.Size" /> whose <see cref="P:Xamarin.Forms.Size.Width" /> and <see cref="P:Xamarin.Forms.Size.Height" /> will be subtracted from <paramref name="pt" />'s <see cref="P:Xamarin.Forms.Point.X" /> and <see cref="P:Xamarin.Forms.Point.Y" />.</param>
+ <summary>Returns a new <see cref="T:Xamarin.Forms.Point" /> by subtracting a <see cref="T:Xamarin.Forms.Size" /> from a <see cref="T:Xamarin.Forms.Point" />.</summary>
+ <returns>A new <see cref="T:Xamarin.Forms.Point" /> at <c>[pt.X - sz.Width, pt.Y - sz.Height]</c>.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Round">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Point Round ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Point Round() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Point</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns a new <see cref="T:Xamarin.Forms.Point" /> whose <see cref="P:Xamarin.Forms.Point.X" /> and <see cref="P:Xamarin.Forms.Point.Y" /> have been rounded to the nearest integral value.</summary>
+ <returns>A new <see cref="T:Xamarin.Forms.Point" /> whose <see cref="P:Xamarin.Forms.Point.X" /> and <see cref="P:Xamarin.Forms.Point.Y" /> have been rounded to the nearest integral value, per the behavior of Math.Round(Double).</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ToString">
+ <MemberSignature Language="C#" Value="public override string ToString ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance string ToString() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>A human-readable representation of the <see cref="T:Xamarin.Forms.Point" />.</summary>
+ <returns>The string is formatted as "{{X={0} Y={1}}}".</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="X">
+ <MemberSignature Language="C#" Value="public double X { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 X" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Location along the horizontal axis.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Y">
+ <MemberSignature Language="C#" Value="public double Y { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Y" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Location along the vertical axis.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Zero">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Point Zero;" />
+ <MemberSignature Language="ILAsm" Value=".field public static valuetype Xamarin.Forms.Point Zero" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Point</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The <see cref="T:Xamarin.Forms.Point" /> at {0,0}.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/PointTypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/PointTypeConverter.xml
new file mode 100644
index 00000000..db54a58a
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/PointTypeConverter.xml
@@ -0,0 +1,117 @@
+<Type Name="PointTypeConverter" FullName="Xamarin.Forms.PointTypeConverter">
+ <TypeSignature Language="C#" Value="public class PointTypeConverter : Xamarin.Forms.TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit PointTypeConverter extends Xamarin.Forms.TypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TypeConverter" /> that converts from a string to a <see cref="T:Xamarin.Forms.Point" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public PointTypeConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.PointTypeConverter" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>Returns a Boolean value that indicates whether this <see cref="T:Xamarin.Forms.PointTypeConverter" /> can convert the <paramref name="sourceType" /> to a <see cref="T:Xamarin.Forms.Point" /> instance.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Converts <paramref name="value" /> into a <see cref="T:Xamarin.Forms.Point" /> by using the specified <paramref name="culture" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Returns a point for a valid point description.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ProgressBar.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ProgressBar.xml
new file mode 100644
index 00000000..ed9cc2b8
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ProgressBar.xml
@@ -0,0 +1,156 @@
+<Type Name="ProgressBar" FullName="Xamarin.Forms.ProgressBar">
+ <TypeSignature Language="C#" Value="public class ProgressBar : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ProgressBar extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._ProgressBarRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.View" /> control that displays progress.</summary>
+ <remarks>
+ <para>The following example shows the usage of a ProgressBar.</para>
+ <example>
+ <code lang="C#"><![CDATA[
+
+//initial progress is 20%
+var progressBar = new ProgressBar {
+ Progress = .2,
+};
+
+// animate the progression to 80%, in 250ms
+await progressBar.ProgressTo (.8, 250, Easing.Linear);
+
+Debug.WriteLine ("Animation completed");
+]]></code>
+ </example>
+ <para>
+ <img href="ProgressBar.TripleScreenShot.png" />
+ </para>
+ <para>XAML for Xamarin.Forms supports the following property for the <see cref="T:Xamarin.Forms.ProgressBar" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Progress</term>
+ <description>
+ <para>A decimal value between 0 and 1, inclusive, that specifies the fraction of the bar that is colored.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ProgressBar ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the ProgressBar class</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Progress">
+ <MemberSignature Language="C#" Value="public double Progress { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Progress" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the progress value. This is s bindable property.</summary>
+ <value>Gets or sets a value that specifies the fraction of the bar that is colored.</value>
+ <remarks>Values less than 0 or larger than 1 will be clamped to the range [0-1].</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ProgressProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ProgressProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ProgressProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Progress bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ProgressTo">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task&lt;bool&gt; ProgressTo (double value, uint length, Xamarin.Forms.Easing easing);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Threading.Tasks.Task`1&lt;bool&gt; ProgressTo(float64 value, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Animate the Progress property to value.</summary>
+ <returns>A Task&lt;bool&gt; you can await on.</returns>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/PropertyChangingEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/PropertyChangingEventArgs.xml
new file mode 100644
index 00000000..b6299da8
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/PropertyChangingEventArgs.xml
@@ -0,0 +1,68 @@
+<Type Name="PropertyChangingEventArgs" FullName="Xamarin.Forms.PropertyChangingEventArgs">
+ <TypeSignature Language="C#" Value="public class PropertyChangingEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit PropertyChangingEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Event arguments for the <see cref="T:Xamarin.Forms.PropertyChangingEventHandler" /> delegate.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public PropertyChangingEventArgs (string propertyName);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string propertyName) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.PropertyChangingEventArgs" /> object that indicates that <paramref name="propertyName" /> is changing.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PropertyName">
+ <MemberSignature Language="C#" Value="public virtual string PropertyName { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string PropertyName" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the name of the property that is changing.</summary>
+ <value>The name of the property that is changing.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/PropertyChangingEventHandler.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/PropertyChangingEventHandler.xml
new file mode 100644
index 00000000..7b0141d7
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/PropertyChangingEventHandler.xml
@@ -0,0 +1,30 @@
+<Type Name="PropertyChangingEventHandler" FullName="Xamarin.Forms.PropertyChangingEventHandler">
+ <TypeSignature Language="C#" Value="public delegate void PropertyChangingEventHandler(object sender, PropertyChangingEventArgs e);" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed PropertyChangingEventHandler extends System.MulticastDelegate" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Delegate</BaseTypeName>
+ </Base>
+ <Parameters>
+ <Parameter Name="sender" Type="System.Object" />
+ <Parameter Name="e" Type="Xamarin.Forms.PropertyChangingEventArgs" />
+ </Parameters>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <param name="sender">To be added.</param>
+ <param name="e">To be added.</param>
+ <summary>Delegate for the <see cref="E:Xamarin.Forms.BindableObject.PropertyChanging" /> event.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/PropertyCondition.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/PropertyCondition.xml
new file mode 100644
index 00000000..7baedb01
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/PropertyCondition.xml
@@ -0,0 +1,122 @@
+<Type Name="PropertyCondition" FullName="Xamarin.Forms.PropertyCondition">
+ <TypeSignature Language="C#" Value="public sealed class PropertyCondition : Xamarin.Forms.Condition, Xamarin.Forms.Xaml.IValueProvider" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit PropertyCondition extends Xamarin.Forms.Condition implements class Xamarin.Forms.Xaml.IValueProvider" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Condition</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IValueProvider</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>Class that represents a value comparison with a property.</summary>
+ <remarks>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.PropertyCondition" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Property</term>
+ <description>
+ <para>The name of the property to check.</para>
+ </description>
+ </item>
+ <item>
+ <term>Value</term>
+ <description>
+ <para>The value for which the condition is met.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public PropertyCondition ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new <see cref="T:Xamarin.Forms.PropertyCondition" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Property">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.BindableProperty Property { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.BindableProperty Property" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the property against which the <see cref="P:Xamarin.Forms.PropertyCondition.Value" /> property will be compared.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Value">
+ <MemberSignature Language="C#" Value="public object Value { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Value" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The binding value that satisfies the condition.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IValueProvider.ProvideValue">
+ <MemberSignature Language="C#" Value="object IValueProvider.ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.Xaml.IValueProvider.ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>Provides a value by using the supplied service provider.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Rectangle.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Rectangle.xml
new file mode 100644
index 00000000..150f8d00
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Rectangle.xml
@@ -0,0 +1,935 @@
+<Type Name="Rectangle" FullName="Xamarin.Forms.Rectangle">
+ <TypeSignature Language="C#" Value="public struct Rectangle" />
+ <TypeSignature Language="ILAsm" Value=".class public sequential ansi sealed beforefieldinit Rectangle extends System.ValueType" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.ValueType</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.DebuggerDisplay("X={X}, Y={Y}, Width={Width}, Height={Height}")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.RectangleTypeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Struct defining a rectangle, using doubles.</summary>
+ <remarks>
+ <para>Application developers should be aware of the limits of floating-point representations, specifically the possibility of incorrect comparisons and equality checks for values with small differences. David Goldberg's paper <format type="text/html"><a href="http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html">What Every Computer Scientist Should Know About Floating-Point Arithmetic</a></format> describes the issues excellently. </para>
+ <block type="note">Where Xamarin.Forms supports XAML for <see cref="T:Xamarin.Forms.Rectangle" /> structures, app devs can represent the rectangle as a comma-separated list of the X-coordinate, Y-Coordinate, Width, and Height.</block>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Rectangle (Xamarin.Forms.Point loc, Xamarin.Forms.Size sz);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(valuetype Xamarin.Forms.Point loc, valuetype Xamarin.Forms.Size sz) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="loc" Type="Xamarin.Forms.Point" />
+ <Parameter Name="sz" Type="Xamarin.Forms.Size" />
+ </Parameters>
+ <Docs>
+ <param name="loc">To be added.</param>
+ <param name="sz">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Rectangle" /> object with its top left corner at <paramref name="loc" /> with a height and width that are specified by <paramref name="sz" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Rectangle (double x, double y, double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 x, float64 y, float64 width, float64 height) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">To be added.</param>
+ <param name="y">To be added.</param>
+ <param name="width">To be added.</param>
+ <param name="height">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Rectangle" /> object with its top left corner at (<paramref name="x" />, <paramref name="y" />) and <paramref name="width" /> wide and <paramref name="height" /> tall.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Bottom">
+ <MemberSignature Language="C#" Value="public double Bottom { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Bottom" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The bottom of the <see cref="T:Xamarin.Forms.Rectangle" />.</summary>
+ <value>To be added.</value>
+ <remarks>
+ <para>Modifying this value also modifies the <see cref="P:Xamarin.Forms.Rectangle.Height" /> property.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Center">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Point Center { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Point Center" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Point</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The <see cref="T:Xamarin.Forms.Point" /> halfway between <see cref="P:Xamarin.Forms.Rectangle.Left" /> and <see cref="P:Xamarin.Forms.Rectangle.Right" />, <see cref="P:Xamarin.Forms.Rectangle.Top" /> and <see cref="P:Xamarin.Forms.Rectangle.Bottom" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Contains">
+ <MemberSignature Language="C#" Value="public bool Contains (Xamarin.Forms.Point pt);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance bool Contains(valuetype Xamarin.Forms.Point pt) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="pt" Type="Xamarin.Forms.Point" />
+ </Parameters>
+ <Docs>
+ <param name="pt">The <see cref="T:Xamarin.Forms.Point" /> being checked for containment.</param>
+ <summary>Whether the <paramref name="pt" /> is within, or along the periphery, of this <see cref="T:Xamarin.Forms.Rectangle" />.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="pt" /> is within, or along the periphery, of <c>this</c><see cref="T:Xamarin.Forms.Rectangle" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Contains">
+ <MemberSignature Language="C#" Value="public bool Contains (Xamarin.Forms.Rectangle rect);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance bool Contains(valuetype Xamarin.Forms.Rectangle rect) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="rect" Type="Xamarin.Forms.Rectangle" />
+ </Parameters>
+ <Docs>
+ <param name="rect">The <see cref="T:Xamarin.Forms.Rectangle" /> being checked for containment.</param>
+ <summary>Whether <paramref name="rect" /> is entirely within, or along the periphery, of this <see cref="T:Xamarin.Forms.Rectangle" />.</summary>
+ <returns>
+ <see langword="true" /> if the borders of <paramref name="rect" /> are entirely within, or along the periphery, of <c>this</c><see cref="T:Xamarin.Forms.Rectangle" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Contains">
+ <MemberSignature Language="C#" Value="public bool Contains (double x, double y);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance bool Contains(float64 x, float64 y) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">The X location of the point being checked.</param>
+ <param name="y">The Y location of the point being checked.</param>
+ <summary>Whether the point described by <paramref name="x" /> and <paramref name="y" /> is within, or along the periphery of, this <see cref="T:Xamarin.Forms.Rectangle" />.</summary>
+ <returns>
+ <see langword="true" /> if the point described by <paramref name="x" /> and <paramref name="y" /> is within, or along the periphery of, <c>this</c><see cref="T:Xamarin.Forms.Rectangle" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Equals">
+ <MemberSignature Language="C#" Value="public override bool Equals (object obj);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool Equals(object obj) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="obj" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="obj">An Object to compare to <c>this</c>.</param>
+ <summary>Whether an <see cref="T:System.Object" /> is a <see cref="T:Xamarin.Forms.Rectangle" /> and has exactly the same values as <c>this</c><see cref="T:Xamarin.Forms.Rectangle" />.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="obj" /> is a <see cref="T:Xamarin.Forms.Rectangle" /> that has exactly the same values as <c>this</c><see cref="T:Xamarin.Forms.Rectangle" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Equals">
+ <MemberSignature Language="C#" Value="public bool Equals (Xamarin.Forms.Rectangle other);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance bool Equals(valuetype Xamarin.Forms.Rectangle other) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="other" Type="Xamarin.Forms.Rectangle" />
+ </Parameters>
+ <Docs>
+ <param name="other">The <see cref="T:Xamarin.Forms.Rectangle" /> being compared to <c>this</c><see cref="T:Xamarin.Forms.Rectangle" />.</param>
+ <summary>Whether a <see cref="T:Xamarin.Forms.Rectangle" /> has exactly the same values as <c>this</c><see cref="T:Xamarin.Forms.Rectangle" />.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="other" /> has exactly the same values as <c>this</c><see cref="T:Xamarin.Forms.Rectangle" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromLTRB">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Rectangle FromLTRB (double left, double top, double right, double bottom);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Rectangle FromLTRB(float64 left, float64 top, float64 right, float64 bottom) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Rectangle</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="left" Type="System.Double" />
+ <Parameter Name="top" Type="System.Double" />
+ <Parameter Name="right" Type="System.Double" />
+ <Parameter Name="bottom" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="left">To be added.</param>
+ <param name="top">To be added.</param>
+ <param name="right">To be added.</param>
+ <param name="bottom">To be added.</param>
+ <summary>Factory method to create a <see cref="T:Xamarin.Forms.Rectangle" /> from <paramref name="left" />, <paramref name="top" />, <paramref name="right" />, and <paramref name="bottom" />.</summary>
+ <returns>A new <see cref="T:Xamarin.Forms.Rectangle" /> whose values are equal to the arguments.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetHashCode">
+ <MemberSignature Language="C#" Value="public override int GetHashCode ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance int32 GetHashCode() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>The hashcode for the <see cref="T:Xamarin.Forms.Rectangle" />.</summary>
+ <returns>A value optimized for fast insertion and retrieval in a hash-based data structure.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Height">
+ <MemberSignature Language="C#" Value="public double Height { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Height" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Extent along the Y axis.</summary>
+ <value>To be added.</value>
+ <remarks>
+ <para>Modifying this value modifies the <see cref="P:Xamarin.Forms.Rectangle.Bottom" /> property.</para>.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Inflate">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Rectangle Inflate (Xamarin.Forms.Size sz);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Rectangle Inflate(valuetype Xamarin.Forms.Size sz) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Rectangle</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sz" Type="Xamarin.Forms.Size" />
+ </Parameters>
+ <Docs>
+ <param name="sz">Values to inflate all the borders.</param>
+ <summary>Creates a <see cref="T:Xamarin.Forms.Rectangle" /> whose borders are inflated in every direction.</summary>
+ <returns>A new <see cref="T:Xamarin.Forms.Rectangle" /> whose <see cref="P:Xamarin.Forms.Rectangle.Left" /> and <see cref="P:Xamarin.Forms.Rectangle.Right" /> are inflated by <paramref name="sz" />'s <see cref="P:Xamarin.Forms.Size.Width" /> and whose <see cref="P:Xamarin.Forms.Rectangle.Top" /> and <see cref="P:Xamarin.Forms.Rectangle.Bottom" /> are inflated by <paramref name="sz" />'s <see cref="P:Xamarin.Forms.Size.Height" />.</returns>
+ <remarks>
+ <para>Application developers should note that since the inflation occurs in every direction, the returned <see cref="T:Xamarin.Forms.Rectangle" /> is larger in each dimension by twice <paramref name="sz" />.</para>
+ <example>
+ <code lang="C#"><![CDATA[
+var rect = new Rectangle (10, 10, 5, 5);
+var larger = rect.Inflate (new Size (1, 1));
+Assert.AreEqual (larger, new Rectangle (9, 9, 7, 7));
+]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Inflate">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Rectangle Inflate (double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Rectangle Inflate(float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Rectangle</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="width">Value to shift <see cref="P:Xamarin.Forms.Rectangle.Left" /> to the left and <see cref="P:Xamarin.Forms.Rectangle.Right" /> to the right.</param>
+ <param name="height">Value to shift <see cref="P:Xamarin.Forms.Rectangle.Top" /> upward and <see cref="P:Xamarin.Forms.Rectangle.Bottom" /> downward.</param>
+ <summary>Creates a <see cref="T:Xamarin.Forms.Rectangle" /> whose borders are inflated in every direction.</summary>
+ <returns>A new <see cref="T:Xamarin.Forms.Rectangle" /> whose <see cref="P:Xamarin.Forms.Rectangle.Left" /> and <see cref="P:Xamarin.Forms.Rectangle.Right" /> are inflated by <paramref name="width" /> and whose <see cref="P:Xamarin.Forms.Rectangle.Top" /> and <see cref="P:Xamarin.Forms.Rectangle.Bottom" /> are inflated by <paramref name="height" />.</returns>
+ <remarks>
+ <para>Application developers should note that since the inflation occurs in every direction, the returned <see cref="T:Xamarin.Forms.Rectangle" /> is larger in X by twice <paramref name="width" /> and larger in Y by twice <paramref name="height" />.</para>
+ <example>
+ <code lang="C#"><![CDATA[
+var rect = new Rectangle (10, 10, 5, 5);
+var larger = rect.Inflate (1,1);
+Assert.AreEqual (larger, new Rectangle (9, 9, 7, 7));
+]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Intersect">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Rectangle Intersect (Xamarin.Forms.Rectangle r);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Rectangle Intersect(valuetype Xamarin.Forms.Rectangle r) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Rectangle</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="r" Type="Xamarin.Forms.Rectangle" />
+ </Parameters>
+ <Docs>
+ <param name="r">A <see cref="T:Xamarin.Forms.Rectangle" /><c>this</c> will be intersected with.</param>
+ <summary>A new <see cref="T:Xamarin.Forms.Rectangle" /> that is the intersection of <c>this</c> and <paramref name="r" />.</summary>
+ <returns>Returns a new <see cref="T:Xamarin.Forms.Rectangle" /> that is the intersection of <c>this</c><see cref="T:Xamarin.Forms.Rectangle" /> and <paramref name="r" />, or <see cref="P:Xamarin.Forms.Rectangle.Zero" /> if there is no intersection.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Intersect">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Rectangle Intersect (Xamarin.Forms.Rectangle r1, Xamarin.Forms.Rectangle r2);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Rectangle Intersect(valuetype Xamarin.Forms.Rectangle r1, valuetype Xamarin.Forms.Rectangle r2) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Rectangle</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="r1" Type="Xamarin.Forms.Rectangle" />
+ <Parameter Name="r2" Type="Xamarin.Forms.Rectangle" />
+ </Parameters>
+ <Docs>
+ <param name="r1">A <see cref="T:Xamarin.Forms.Rectangle" /> being intersected.</param>
+ <param name="r2">A <see cref="T:Xamarin.Forms.Rectangle" /> being intersected.</param>
+ <summary>A new <see cref="T:Xamarin.Forms.Rectangle" /> that is the intersection of <paramref name="r1" /> and <paramref name="r2" />.</summary>
+ <returns>Returns a new <see cref="T:Xamarin.Forms.Rectangle" /> that is the intersection of <paramref name="r1" /> and <paramref name="r2" />, or <see cref="P:Xamarin.Forms.Rectangle.Zero" /> if there is no intersection.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IntersectsWith">
+ <MemberSignature Language="C#" Value="public bool IntersectsWith (Xamarin.Forms.Rectangle r);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance bool IntersectsWith(valuetype Xamarin.Forms.Rectangle r) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="r" Type="Xamarin.Forms.Rectangle" />
+ </Parameters>
+ <Docs>
+ <param name="r">The <see cref="T:Xamarin.Forms.Rectangle" /> being intersected.</param>
+ <summary>Whether <c>this</c><see cref="T:Xamarin.Forms.Rectangle" /> intersects <paramref name="r" />.</summary>
+ <returns>
+ <see langword="true" /> if <c>this</c><see cref="T:Xamarin.Forms.Rectangle" /> intersects <paramref name="r" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsEmpty">
+ <MemberSignature Language="C#" Value="public bool IsEmpty { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsEmpty" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Whether <c>this</c><see cref="T:Xamarin.Forms.Rectangle" /> has either <see cref="P:Xamarin.Forms.Rectangle.Height" /> or <see cref="P:Xamarin.Forms.Rectangle.Width" /> less than or equal to 0.</summary>
+ <value>
+ <see langword="true" /> if either <see cref="P:Xamarin.Forms.Rectangle.Width" /> or <see cref="P:Xamarin.Forms.Rectangle.Height" /> is less than or equal to 0.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Left">
+ <MemberSignature Language="C#" Value="public double Left { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Left" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The position of the <see cref="T:Xamarin.Forms.Rectangle" /> on the X axis.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Location">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Point Location { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Point Location" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Point</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The <see cref="T:Xamarin.Forms.Point" /> defined by <see cref="P:Xamarin.Forms.Rectangle.Left" /> and <see cref="P:Xamarin.Forms.Rectangle.Top" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Offset">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Rectangle Offset (Xamarin.Forms.Point dr);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Rectangle Offset(valuetype Xamarin.Forms.Point dr) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Rectangle</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="dr" Type="Xamarin.Forms.Point" />
+ </Parameters>
+ <Docs>
+ <param name="dr">A <see cref="T:Xamarin.Forms.Point" /> whose X and Y values should be added to <c>this</c><see cref="T:Xamarin.Forms.Rectangle" />'s <see cref="P:Xamarin.Forms.Rectangle.Location" />.</param>
+ <summary>A new <see cref="T:Xamarin.Forms.Rectangle" /> whose <see cref="P:Xamarin.Forms.Rectangle.Location" /> is offset by <paramref name="dr" />.</summary>
+ <returns>A new <see cref="T:Xamarin.Forms.Rectangle" /> whose <see cref="P:Xamarin.Forms.Rectangle.Location" /> is equal to <c>this</c><see cref="T:Xamarin.Forms.Rectangle" />'s <see cref="P:Xamarin.Forms.Rectangle.Location" /> translated by <paramref name="dr" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Offset">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Rectangle Offset (double dx, double dy);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Rectangle Offset(float64 dx, float64 dy) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Rectangle</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="dx" Type="System.Double" />
+ <Parameter Name="dy" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="dx">Change along the X axis.</param>
+ <param name="dy">Change along the Y axis.</param>
+ <summary>A new <see cref="T:Xamarin.Forms.Rectangle" /> whose <see cref="P:Xamarin.Forms.Rectangle.Location" /> is offset by <paramref name="dx" /> and <paramref name="dy" />.</summary>
+ <returns>A new <see cref="T:Xamarin.Forms.Rectangle" /> whose <see cref="P:Xamarin.Forms.Rectangle.Location" /> is equal to <c>this</c><see cref="T:Xamarin.Forms.Rectangle" />'s <see cref="P:Xamarin.Forms.Rectangle.Location" /> translated by <paramref name="dx" /> and <paramref name="dy" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Equality">
+ <MemberSignature Language="C#" Value="public static bool op_Equality (Xamarin.Forms.Rectangle r1, Xamarin.Forms.Rectangle r2);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Equality(valuetype Xamarin.Forms.Rectangle r1, valuetype Xamarin.Forms.Rectangle r2) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="r1" Type="Xamarin.Forms.Rectangle" />
+ <Parameter Name="r2" Type="Xamarin.Forms.Rectangle" />
+ </Parameters>
+ <Docs>
+ <param name="r1">A <see cref="T:Xamarin.Forms.Rectangle" /> being compared.</param>
+ <param name="r2">A <see cref="T:Xamarin.Forms.Rectangle" /> being compared.</param>
+ <summary>Whether two <see cref="T:Xamarin.Forms.Rectangle" />s have equal values.</summary>
+ <returns>
+ <see langword="true" /> if both the <see cref="P:Xamarin.Forms.Rectangle.Position" /> and <see cref="P:Xamarin.Forms.Rectangle.Size" /> of the two rectangles are equivalent.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Inequality">
+ <MemberSignature Language="C#" Value="public static bool op_Inequality (Xamarin.Forms.Rectangle r1, Xamarin.Forms.Rectangle r2);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Inequality(valuetype Xamarin.Forms.Rectangle r1, valuetype Xamarin.Forms.Rectangle r2) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="r1" Type="Xamarin.Forms.Rectangle" />
+ <Parameter Name="r2" Type="Xamarin.Forms.Rectangle" />
+ </Parameters>
+ <Docs>
+ <param name="r1">A <see cref="T:Xamarin.Forms.Rectangle" /> being compared.</param>
+ <param name="r2">A <see cref="T:Xamarin.Forms.Rectangle" /> being compared.</param>
+ <summary>Whether two <see cref="T:Xamarin.Forms.Rectangle" />s have unequal values.</summary>
+ <returns>
+ <see langword="true" /> if either the <see cref="P:Xamarin.Forms.Rectangle.Position" /> or <see cref="P:Xamarin.Forms.Rectangle.Size" /> of the two rectangles have differences.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Right">
+ <MemberSignature Language="C#" Value="public double Right { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Right" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The furthest extent along the X axis.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Round">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Rectangle Round ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Rectangle Round() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Rectangle</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns a new <see cref="T:Xamarin.Forms.Rectangle" /> whose values have been rounded to their nearest integral value.</summary>
+ <returns>A new <see cref="T:Xamarin.Forms.Rectangle" /> whose <see cref="P:Xamarin.Forms.Rectangle.X" />, <see cref="P:Xamarin.Forms.Rectangle.Y" />, <see cref="P:Xamarin.Forms.Rectangle.Width" />, and <see cref="P:Xamarin.Forms.Rectangle.Height" /> have been rounded to their nearest integral values.</returns>
+ <remarks>
+ <para>The rounding is applied to each property independently.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Size">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Size Size { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Size Size" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Size</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The extent of the <see cref="T:Xamarin.Forms.Rectangle" /> along its X and Y axes.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Top">
+ <MemberSignature Language="C#" Value="public double Top { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Top" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The top of the <see cref="T:Xamarin.Forms.Rectangle" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ToString">
+ <MemberSignature Language="C#" Value="public override string ToString ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance string ToString() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>A human-readable description of the <see cref="T:Xamarin.Forms.Rectangle" />.</summary>
+ <returns>The format is "{X={0} Y={1} Width={2} Height={3}}".</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Union">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Rectangle Union (Xamarin.Forms.Rectangle r);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.Rectangle Union(valuetype Xamarin.Forms.Rectangle r) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Rectangle</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="r" Type="Xamarin.Forms.Rectangle" />
+ </Parameters>
+ <Docs>
+ <param name="r">The <see cref="T:Xamarin.Forms.Rectangle" /> whose union is being calculated.</param>
+ <summary>A new <see cref="T:Xamarin.Forms.Rectangle" /> whose bounds cover the union of <c>this</c><see cref="T:Xamarin.Forms.Rectangle" /> and <paramref name="r" />.</summary>
+ <returns>Returns a new <see cref="T:Xamarin.Forms.Rectangle" /> whose bounds cover the union of <c>this</c><see cref="T:Xamarin.Forms.Rectangle" /> and <paramref name="r" />. </returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Union">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Rectangle Union (Xamarin.Forms.Rectangle r1, Xamarin.Forms.Rectangle r2);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Rectangle Union(valuetype Xamarin.Forms.Rectangle r1, valuetype Xamarin.Forms.Rectangle r2) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Rectangle</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="r1" Type="Xamarin.Forms.Rectangle" />
+ <Parameter Name="r2" Type="Xamarin.Forms.Rectangle" />
+ </Parameters>
+ <Docs>
+ <param name="r1">A <see cref="T:Xamarin.Forms.Rectangle" /> whose union is being calculated.</param>
+ <param name="r2">A <see cref="T:Xamarin.Forms.Rectangle" /> whose union is being calculated.</param>
+ <summary>A new <see cref="T:Xamarin.Forms.Rectangle" /> whose bounds cover the union of <paramref name="r1" /> and <paramref name="r2" />.</summary>
+ <returns>Returns a new <see cref="T:Xamarin.Forms.Rectangle" /> whose bounds cover the union of <paramref name="r1" /> and <paramref name="r2" />. </returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Width">
+ <MemberSignature Language="C#" Value="public double Width { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Width" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The extent of this <see cref="T:Xamarin.Forms.Rectangle" /> along the X axis.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="X">
+ <MemberSignature Language="C#" Value="public double X { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 X" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The position of this <see cref="T:Xamarin.Forms.Rectangle" /> on the X axis.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Y">
+ <MemberSignature Language="C#" Value="public double Y { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Y" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The position of this <see cref="T:Xamarin.Forms.Rectangle" /> on the Y axis.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Zero">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Rectangle Zero;" />
+ <MemberSignature Language="ILAsm" Value=".field public static valuetype Xamarin.Forms.Rectangle Zero" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Rectangle</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The <see cref="T:Xamarin.Forms.Rectangle" /> at {0,0} whose Size is {0,0}.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/RectangleTypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/RectangleTypeConverter.xml
new file mode 100644
index 00000000..6555a407
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/RectangleTypeConverter.xml
@@ -0,0 +1,117 @@
+<Type Name="RectangleTypeConverter" FullName="Xamarin.Forms.RectangleTypeConverter">
+ <TypeSignature Language="C#" Value="public class RectangleTypeConverter : Xamarin.Forms.TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit RectangleTypeConverter extends Xamarin.Forms.TypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TypeConverter" /> that converts a string to a <see cref="T:Xamarin.Forms.Rectangle" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public RectangleTypeConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.RectangleTypeConverter" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>Returns a Boolean value that indicates whether this <see cref="T:Xamarin.Forms.RectangleTypeConverter" /> can convert the <paramref name="sourceType" /> to a <see cref="T:Xamarin.Forms.Rectangle" /> instance.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Converts <paramref name="value" /> into a <see cref="T:Xamarin.Forms.Rectangle" /> by using the specified <paramref name="culture" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Returns a <see cref="T:Xamarin.Forms.Rectangle" /> for a comma-separated list of <c>double</c> values.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/RelativeLayout+IRelativeList`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/RelativeLayout+IRelativeList`1.xml
new file mode 100644
index 00000000..da7d0eae
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/RelativeLayout+IRelativeList`1.xml
@@ -0,0 +1,132 @@
+<Type Name="RelativeLayout+IRelativeList&lt;T&gt;" FullName="Xamarin.Forms.RelativeLayout+IRelativeList&lt;T&gt;">
+ <TypeSignature Language="C#" Value="public interface RelativeLayout.IRelativeList&lt;T&gt; : System.Collections.Generic.ICollection&lt;T&gt;, System.Collections.Generic.IEnumerable&lt;T&gt;, System.Collections.Generic.IList&lt;T&gt; where T : View" />
+ <TypeSignature Language="ILAsm" Value=".class nested public interface auto ansi abstract RelativeLayout/IRelativeList`1&lt;(class Xamarin.Forms.View) T&gt; implements class System.Collections.Generic.ICollection`1&lt;!T&gt;, class System.Collections.Generic.IEnumerable`1&lt;!T&gt;, class System.Collections.Generic.IList`1&lt;!T&gt;, class System.Collections.IEnumerable" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="T">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.ICollection&lt;T&gt;</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.IEnumerable&lt;T&gt;</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.IList&lt;T&gt;</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <summary>An <see cref="T:System.Collections.Generic.IList`1" /> of <see cref="T:Xamarin.Forms.View" />s used by a <see cref="T:Xamarin.Forms.RelativeLayout" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (T view, System.Linq.Expressions.Expression&lt;Func&lt;Xamarin.Forms.Rectangle&gt;&gt; bounds);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Add(!T view, class System.Linq.Expressions.Expression`1&lt;class System.Func`1&lt;valuetype Xamarin.Forms.Rectangle&gt;&gt; bounds) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="T" />
+ <Parameter Name="bounds" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;Xamarin.Forms.Rectangle&gt;&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="bounds">To be added.</param>
+ <summary>Constrains <paramref name="view" /> to <paramref name="bounds" /> and adds it to the layout.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (T view, System.Linq.Expressions.Expression&lt;Func&lt;double&gt;&gt; x = null, System.Linq.Expressions.Expression&lt;Func&lt;double&gt;&gt; y = null, System.Linq.Expressions.Expression&lt;Func&lt;double&gt;&gt; width = null, System.Linq.Expressions.Expression&lt;Func&lt;double&gt;&gt; height = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Add(!T view, class System.Linq.Expressions.Expression`1&lt;class System.Func`1&lt;float64&gt;&gt; x, class System.Linq.Expressions.Expression`1&lt;class System.Func`1&lt;float64&gt;&gt; y, class System.Linq.Expressions.Expression`1&lt;class System.Func`1&lt;float64&gt;&gt; width, class System.Linq.Expressions.Expression`1&lt;class System.Func`1&lt;float64&gt;&gt; height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="T" />
+ <Parameter Name="x" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;System.Double&gt;&gt;" />
+ <Parameter Name="y" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;System.Double&gt;&gt;" />
+ <Parameter Name="width" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;System.Double&gt;&gt;" />
+ <Parameter Name="height" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;System.Double&gt;&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="x">To be added.</param>
+ <param name="y">To be added.</param>
+ <param name="width">To be added.</param>
+ <param name="height">To be added.</param>
+ <summary>Constrains <paramref name="view" /> to the rectangle that is defined by <paramref name="x" />, <paramref name="y" />, <paramref name="width" />, and <paramref name="height" />, and adds it to the layout.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (T view, Xamarin.Forms.Constraint xConstraint = null, Xamarin.Forms.Constraint yConstraint = null, Xamarin.Forms.Constraint widthConstraint = null, Xamarin.Forms.Constraint heightConstraint = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Add(!T view, class Xamarin.Forms.Constraint xConstraint, class Xamarin.Forms.Constraint yConstraint, class Xamarin.Forms.Constraint widthConstraint, class Xamarin.Forms.Constraint heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="T" />
+ <Parameter Name="xConstraint" Type="Xamarin.Forms.Constraint" />
+ <Parameter Name="yConstraint" Type="Xamarin.Forms.Constraint" />
+ <Parameter Name="widthConstraint" Type="Xamarin.Forms.Constraint" />
+ <Parameter Name="heightConstraint" Type="Xamarin.Forms.Constraint" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="xConstraint">To be added.</param>
+ <param name="yConstraint">To be added.</param>
+ <param name="widthConstraint">To be added.</param>
+ <param name="heightConstraint">To be added.</param>
+ <summary>Constrains <paramref name="view" /> by <paramref name="xConstraint" />, <paramref name="yConstraint" />, <paramref name="widthConstraint" />, and <paramref name="heightConstraint" />, and adds it to the layout.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/RelativeLayout.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/RelativeLayout.xml
new file mode 100644
index 00000000..8d1082e9
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/RelativeLayout.xml
@@ -0,0 +1,513 @@
+<Type Name="RelativeLayout" FullName="Xamarin.Forms.RelativeLayout">
+ <TypeSignature Language="C#" Value="public class RelativeLayout : Xamarin.Forms.Layout&lt;Xamarin.Forms.View&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit RelativeLayout extends Xamarin.Forms.Layout`1&lt;class Xamarin.Forms.View&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Layout&lt;Xamarin.Forms.View&gt;</BaseTypeName>
+ <BaseTypeArguments>
+ <BaseTypeArgument TypeParamName="T">Xamarin.Forms.View</BaseTypeArgument>
+ </BaseTypeArguments>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.Layout`1" /> that uses <see cref="T:Xamarin.Forms.Constraint" />s to layout its children.</summary>
+ <remarks>
+ <para>The <c>RelativeLayoutExample</c> class in the following code extends the <see cref="T:Xamarin.Forms.ContentPage" /> class by adding a <see cref="T:Xamarin.Forms.RelativeLayout" /> that contains a heading and another label. Both labels are positioned relative to the <see cref="T:Xamarin.Forms.ContentPage" />:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+public class RelativeLayoutExample : ContentPage
+{
+ public RelativeLayoutExample ()
+ {
+ this.Padding = new Thickness (10, Device.OnPlatform (20, 0, 0), 10, 5);
+
+ Label heading = new Label {
+ Text = "RelativeLayout Example",
+ TextColor = Color.Red,
+ };
+
+ Label relativelyPositioned = new Label {
+ Text = "Positioned relative to my parent."
+ };
+
+ RelativeLayout relativeLayout = new RelativeLayout ();
+
+ relativeLayout.Children.Add (heading, Constraint.RelativeToParent ((parent) => {
+ return 0;
+ }));
+
+ relativeLayout.Children.Add (relativelyPositioned,
+ Constraint.RelativeToParent ((parent) => {
+ return parent.Width / 3;
+ }),
+ Constraint.RelativeToParent ((parent) => {
+ return parent.Height / 2;
+ }));
+ this.Content = relativeLayout;
+ }
+}
+]]></code>
+ </example>
+ <para>For a more complete example that exercises many more of the layout options for the <see cref="T:Xamarin.Forms.RelativeLayout" /> class, see the FormsGallery sample that can be found on the <format type="text/html"><a href="http://developer.xamarin.com/samples/tag/Xamarin.Forms/" target="_blank">Sample Applications</a></format> page.</para>
+ <para>XAML for Xamarin.Forms supports the following attached properties for the <see cref="T:Xamarin.Forms.RelativeLayout" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>AttachedProperty</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>XConstraint</term>
+ <description>
+ <para>XAML markup extension for a constraint expression. See <see cref="T:Xamarin.Forms.ConstraintExpression" />.</para>
+ </description>
+ </item>
+ <item>
+ <term>YConstraint</term>
+ <description>
+ <para>XAML markup extension for a constraint expression. See <see cref="T:Xamarin.Forms.ConstraintExpression" />.</para>
+ </description>
+ </item>
+ <item>
+ <term>WidthConstraint</term>
+ <description>
+ <para>XAML markup extension for a constraint expression. See <see cref="T:Xamarin.Forms.ConstraintExpression" />.</para>
+ </description>
+ </item>
+ <item>
+ <term>HeightConstraint</term>
+ <description>
+ <para>XAML markup extension for a constraint expression. See <see cref="T:Xamarin.Forms.ConstraintExpression" />.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public RelativeLayout ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.RelativeLayout" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BoundsConstraintProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty BoundsConstraintProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty BoundsConstraintProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the bindable property associated with <see cref="M:Xamarin.Forms.RelativeLayout.GetBoundsConstraint" />/<see cref="M:Xamarin.Forms.RelativeLayout.SetBoundsConstraint" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Children">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.RelativeLayout.IRelativeList&lt;Xamarin.Forms.View&gt; Children { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.RelativeLayout/IRelativeList`1&lt;class Xamarin.Forms.View&gt; Children" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.RelativeLayout+IRelativeList&lt;Xamarin.Forms.View&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>List of <see cref="T:Xamarin.Forms.View" />s that are children of this <see cref="T:Xamarin.Forms.RelativeLayout" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetBoundsConstraint">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.BoundsConstraint GetBoundsConstraint (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.BoundsConstraint GetBoundsConstraint(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BoundsConstraint</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">The <see cref="T:Xamarin.Forms.BindableObject" /> for which the bounds constraint is being requested.</param>
+ <summary>Returns the bounds constraint of the <paramref name="bindable" />.</summary>
+ <returns>The <see cref="T:Xamarin.Forms.BoundsConstraint" /> of the <paramref name="bindable" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetHeightConstraint">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Constraint GetHeightConstraint (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.Constraint GetHeightConstraint(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Constraint</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">The <see cref="T:Xamarin.Forms.BindableObject" /> for which the height constraint is being requested.</param>
+ <summary>Returns the height constraint of the <paramref name="bindable" />.</summary>
+ <returns>The <see cref="T:Xamarin.Forms.Constraint" /> on the height of the <paramref name="bindable" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetWidthConstraint">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Constraint GetWidthConstraint (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.Constraint GetWidthConstraint(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Constraint</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">The <see cref="T:Xamarin.Forms.BindableObject" /> for which the width constraint is being requested.</param>
+ <summary>Returns the width constraint of the <paramref name="bindable" />.</summary>
+ <returns>The <see cref="T:Xamarin.Forms.Constraint" /> on the width of the <paramref name="bindable" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetXConstraint">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Constraint GetXConstraint (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.Constraint GetXConstraint(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Constraint</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">The <see cref="T:Xamarin.Forms.BindableObject" /> for which the X constraint is being requested.</param>
+ <summary>Returns the X constraint of the <paramref name="bindable" />.</summary>
+ <returns>The <see cref="T:Xamarin.Forms.Constraint" /> on the X position of the <paramref name="bindable" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetYConstraint">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Constraint GetYConstraint (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.Constraint GetYConstraint(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Constraint</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">The <see cref="T:Xamarin.Forms.BindableObject" /> for which the Y constraint is being requested.</param>
+ <summary>Returns the Y constraint of the <paramref name="bindable" />.</summary>
+ <returns>The <see cref="T:Xamarin.Forms.Constraint" /> on the Y position of the <paramref name="bindable" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HeightConstraintProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HeightConstraintProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HeightConstraintProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the bindable property associated with the <see cref="M:Xamarin.Forms.RelativeLayout.GetHeightConstraint" /> / <see cref="M:Xamarin.Forms.RelativeLayout.SetHeightConstraint" /> methods.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutChildren">
+ <MemberSignature Language="C#" Value="protected override void LayoutChildren (double x, double y, double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void LayoutChildren(float64 x, float64 y, float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">The left-side bound of the rectangle into which the children will be laid out.</param>
+ <param name="y">The top bound of the rectangle into which the children will be laid out.</param>
+ <param name="width">The width of the rectangle into which the children will be laid out.</param>
+ <param name="height">The height of the rectangle into which the children will be laid out.</param>
+ <summary>Lays out the <see cref="P:Xamarin.Forms.RelativeLayout.Children" /> in the specified rectangle.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnAdded">
+ <MemberSignature Language="C#" Value="protected override void OnAdded (Xamarin.Forms.View view);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnAdded(class Xamarin.Forms.View view) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.View" />
+ </Parameters>
+ <Docs>
+ <param name="view">The <see cref="T:Xamarin.Forms.View" /> added to the <see cref="P:Xamarin.Forms.RelativeLayout.Children" />.</param>
+ <summary>Called when a <see cref="T:Xamarin.Forms.View" /> is added to the <see cref="P:Xamarin.Forms.RelativeLayout.Children" /> collection.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnRemoved">
+ <MemberSignature Language="C#" Value="protected override void OnRemoved (Xamarin.Forms.View view);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnRemoved(class Xamarin.Forms.View view) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.View" />
+ </Parameters>
+ <Docs>
+ <param name="view">The <see cref="T:Xamarin.Forms.View" /> removed from the <see cref="P:Xamarin.Forms.RelativeLayout.Children" /> collection.</param>
+ <summary>Called when a <see cref="T:Xamarin.Forms.View" /> is removed from the <see cref="P:Xamarin.Forms.RelativeLayout.Children" /> collection.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeRequest">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance valuetype Xamarin.Forms.SizeRequest OnSizeRequest(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use OnMeasure")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">To be added.</param>
+ <param name="heightConstraint">To be added.</param>
+ <summary>Called when this <see cref="T:Xamarin.Forms.RelativeLayout" /> has received a size request.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SetBoundsConstraint">
+ <MemberSignature Language="C#" Value="public static void SetBoundsConstraint (Xamarin.Forms.BindableObject bindable, Xamarin.Forms.BoundsConstraint value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetBoundsConstraint(class Xamarin.Forms.BindableObject bindable, class Xamarin.Forms.BoundsConstraint value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ <Parameter Name="value" Type="Xamarin.Forms.BoundsConstraint" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">The <see cref="T:Xamarin.Forms.BindableObject" /> to which the constraint will be applied.</param>
+ <param name="value">The <see cref="T:Xamarin.Forms.BoundsConstraint" /> on the <paramref name="bindable" />.</param>
+ <summary>Sets <paramref name="value" /> as a constraint on the bounds of <paramref name="bindable" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="WidthConstraintProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty WidthConstraintProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty WidthConstraintProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the width constraint.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="XConstraintProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty XConstraintProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty XConstraintProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the constraint on X.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="YConstraintProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty YConstraintProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty YConstraintProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the constraint on Y.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/RenderWithAttribute.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/RenderWithAttribute.xml
new file mode 100644
index 00000000..7769ce19
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/RenderWithAttribute.xml
@@ -0,0 +1,64 @@
+<Type Name="RenderWithAttribute" FullName="Xamarin.Forms.RenderWithAttribute">
+ <TypeSignature Language="C#" Value="public sealed class RenderWithAttribute : Attribute" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit RenderWithAttribute extends System.Attribute" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Attribute</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.AttributeUsage(System.AttributeTargets.Class)</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Associate view with renderer.</summary>
+ <remarks>Lazily assoicate a view with it's renderer.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public RenderWithAttribute (Type type);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Type type) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="type" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="type">The view to render.</param>
+ <summary>The view to render.</summary>
+ <remarks>The view to render.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Type">
+ <MemberSignature Language="C#" Value="public Type Type { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Type Type" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Type</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The renderer for this view.</summary>
+ <value>The renderer for this view.</value>
+ <remarks>The renderer for this view.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ResolutionGroupNameAttribute.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ResolutionGroupNameAttribute.xml
new file mode 100644
index 00000000..ece1f895
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ResolutionGroupNameAttribute.xml
@@ -0,0 +1,62 @@
+<Type Name="ResolutionGroupNameAttribute" FullName="Xamarin.Forms.ResolutionGroupNameAttribute">
+ <TypeSignature Language="C#" Value="public class ResolutionGroupNameAttribute : Attribute" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ResolutionGroupNameAttribute extends System.Attribute" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Attribute</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.AttributeUsage(System.AttributeTargets.Assembly, AllowMultiple=false, Inherited=false)</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Attribute that identifies a group name, typically a company name or reversed company URL, that provides a scope for effect names.</summary>
+ <remarks><para>Developers must supply a name to <see cref="T:Xamarin.Forms.ExportEffectAttribute" /> that is unique over the scope of the <param name="name" /> that they supply to <see cref="T:Xamarin.Forms.ResolutionGroupNameAttribute" />. The <see cref="T:Xamarin.Forms.Effect.Resolve" /> method takes a string that is the concatenation of <paramref name="name" /> (the resolution group name), <c>'.'</c>, and the unique name that was supplied to <see cref="T:Xamarin.Forms.ExportEffectAttribute" />, and returns the specified effect.</para>
+ <example><para>For example, with the declarations:</para>
+ <code lang="c#"><![CDATA[
+ [assembly: ResolutionGroupName ("com.YourCompany")]
+ [assembly: ExportEffect (typeof (ShadowEffect), "ShadowEffect")]]]>
+ </code>
+ <para>Then the code below will add the effect to a button:</para>
+ <code lang="c#"><![CDATA[
+ [var button = new Button { Text = "I have a shadow" };
+button.Effects.Add (Effect.Resolve ("com.YourCompany.ShadowEffect"));]]>
+ </code>
+</example></remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ResolutionGroupNameAttribute (string name);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string name) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="name">A name, such as a company name or reversed company URL, that helps to uniquely identify effects.</param>
+ <summary>Creates a new resolution group name attribute.</summary>
+ <remarks><para>Developers must supply a name to <see cref="T:Xamarin.Forms.ExportEffectAttribute" /> that is unique over the scope of the <param name="name" /> that they supply to <see cref="T:Xamarin.Forms.ResolutionGroupNameAttribute" />. The <see cref="T:Xamarin.Forms.Effect.Resolve" /> method takes a string that is the concatenation of <paramref name="name" /> (the resolution group name), <c>'.'</c>, and the unique name that was supplied to <see cref="T:Xamarin.Forms.ExportEffectAttribute" />, and returns the specified effect.</para>
+ <example><para>For example, with the declarations:</para>
+ <code lang="c#"><![CDATA[
+ [assembly: ResolutionGroupName ("com.YourCompany")]
+ [assembly: ExportEffect (typeof (ShadowEffect), "ShadowEffect")]]]>
+ </code>
+ <para>Then the code below will add the effect to a button:</para>
+ <code lang="c#"><![CDATA[
+ [var button = new Button { Text = "I have a shadow" };
+ button.Effects.Add (Effect.Resolve ("com.YourCompany.ShadowEffect"));]]>
+ </code>
+ </example></remarks>
+ <altmember cref="T:Xamarin.Forms.ExportEffectAttribute" />
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ResourceDictionary.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ResourceDictionary.xml
new file mode 100644
index 00000000..862bf40a
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ResourceDictionary.xml
@@ -0,0 +1,473 @@
+<Type Name="ResourceDictionary" FullName="Xamarin.Forms.ResourceDictionary">
+ <TypeSignature Language="C#" Value="public sealed class ResourceDictionary : System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;string,object&gt;&gt;, System.Collections.Generic.IDictionary&lt;string,object&gt;, System.Collections.Generic.IEnumerable&lt;System.Collections.Generic.KeyValuePair&lt;string,object&gt;&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit ResourceDictionary extends System.Object implements class System.Collections.Generic.ICollection`1&lt;valuetype System.Collections.Generic.KeyValuePair`2&lt;string, object&gt;&gt;, class System.Collections.Generic.IDictionary`2&lt;string, object&gt;, class System.Collections.Generic.IEnumerable`1&lt;valuetype System.Collections.Generic.KeyValuePair`2&lt;string, object&gt;&gt;, class System.Collections.IEnumerable" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;&gt;</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.IDictionary&lt;System.String,System.Object&gt;</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.IEnumerable&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;&gt;</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>An IDictionary that maps identifier strings to arbitrary resource objects.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ResourceDictionary ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new empty <see cref="T:Xamarin.Forms.ResourceDictionary" /> object.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (Xamarin.Forms.Style style);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void Add(class Xamarin.Forms.Style style) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="implicitStyle" Type="Xamarin.Forms.Style" />
+ </Parameters>
+ <Docs>
+ <param name="style">To be added.</param>
+ <summary>
+ <para>Add an implicit Style to the ResourceDictionary. Implicit Styles are applied to all VisualElements matching TargetType in the descendants of this ResourceDictionary owner, unless a Style is explicitely applied to the Element.</para>
+ <para />
+ <para>Implicit Styles are added to a ResourceDictionary in XAML by not specifying an x:Key for the Element.</para>
+ </summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (string key, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Add(string key, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="key" Type="System.String" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="key">The identifier to be used to retrieve the <paramref name="value" />.</param>
+ <param name="value">The <see cref="T:System.Object" /> associated with the <paramref name="key" />.</param>
+ <summary>Adds <paramref name="key" /> and <paramref name="value" /> to the <see cref="T:Xamarin.Forms.ResourceDictionary" /> as a key-value pair.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Clear">
+ <MemberSignature Language="C#" Value="public void Clear ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Clear() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Empties the <see cref="T:Xamarin.Forms.ResourceDictionary" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ContainsKey">
+ <MemberSignature Language="C#" Value="public bool ContainsKey (string key);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance bool ContainsKey(string key) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="key" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="key">The identifier being searched for.</param>
+ <summary>Whether the <see cref="T:Xamarin.Forms.ResourceDictionary" /> contains a key-value pair identified by <paramref name="key" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Count">
+ <MemberSignature Language="C#" Value="public int Count { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 Count" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The number of entries in the <see cref="T:Xamarin.Forms.ResourceDictionary" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetEnumerator">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IEnumerator&lt;System.Collections.Generic.KeyValuePair&lt;string,object&gt;&gt; GetEnumerator ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Collections.Generic.IEnumerator`1&lt;valuetype System.Collections.Generic.KeyValuePair`2&lt;string, object&gt;&gt; GetEnumerator() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IEnumerator&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns a <see cref="T:System.Collections.Generic.IEnumerator`1" /> of the <see cref="T:Xamarin.Forms.ResourceDictionary" />'s <see cref="T:System.Collections.Generic.KeyValuePair`1" />s.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Item">
+ <MemberSignature Language="C#" Value="public object this[string index] { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Item(string)" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="index" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="index">The identifier of the desired object.</param>
+ <summary>Retrieves the <see cref="T:System.Object" /> value associated with the key <paramref name="index" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Keys">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.ICollection&lt;string&gt; Keys { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.ICollection`1&lt;string&gt; Keys" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.ICollection&lt;System.String&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The collection of identifier <see langword="string" />s that are keys in the <see cref="T:Xamarin.Forms.ResourceDictionary" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Remove">
+ <MemberSignature Language="C#" Value="public bool Remove (string key);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance bool Remove(string key) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="key" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="key">The identifier of the key-value pair to be removed.</param>
+ <summary>Removes the key and value identified by <paramref name="key" /> from the <see cref="T:Xamarin.Forms.ResourceDictionary" />.</summary>
+ <returns>
+ <see langword="true" /> if the key existed and the removal was successful.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;&gt;.Add">
+ <MemberSignature Language="C#" Value="void ICollection&lt;KeyValuePair&lt;string,object&gt;&gt;.Add (System.Collections.Generic.KeyValuePair&lt;string,object&gt; item);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;&gt;.Add(valuetype System.Collections.Generic.KeyValuePair`2&lt;string, object&gt; item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="item">To be added.</param>
+ <summary>Adds an item to the collection.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;&gt;.Contains">
+ <MemberSignature Language="C#" Value="bool ICollection&lt;KeyValuePair&lt;string,object&gt;&gt;.Contains (System.Collections.Generic.KeyValuePair&lt;string,object&gt; item);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance bool System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;&gt;.Contains(valuetype System.Collections.Generic.KeyValuePair`2&lt;string, object&gt; item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="item">To be added.</param>
+ <summary>Returns a value that indicates whether the dictionary contains the value in <paramref name="item" />, indexed by the key in <paramref name="item" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;&gt;.CopyTo">
+ <MemberSignature Language="C#" Value="void ICollection&lt;KeyValuePair&lt;string,object&gt;&gt;.CopyTo (System.Collections.Generic.KeyValuePair&lt;string,object&gt;[] array, int arrayIndex);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;&gt;.CopyTo(valuetype System.Collections.Generic.KeyValuePair`2&lt;string, object&gt;[] array, int32 arrayIndex) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="array" Type="System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;[]" />
+ <Parameter Name="arrayIndex" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="array">To be added.</param>
+ <param name="arrayIndex">To be added.</param>
+ <summary>Copies the values in the dictionary to <paramref name="array" />, starting at position <paramref name="arrayIndex" /> in <paramref name="array" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;&gt;.IsReadOnly">
+ <MemberSignature Language="C#" Value="bool System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;&gt;.IsReadOnly { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;&gt;.IsReadOnly" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that indicates whether the resource dictionary is read-only.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;&gt;.Remove">
+ <MemberSignature Language="C#" Value="bool ICollection&lt;KeyValuePair&lt;string,object&gt;&gt;.Remove (System.Collections.Generic.KeyValuePair&lt;string,object&gt; item);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance bool System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;&gt;.Remove(valuetype System.Collections.Generic.KeyValuePair`2&lt;string, object&gt; item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Collections.Generic.KeyValuePair&lt;System.String,System.Object&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="item">To be added.</param>
+ <summary>Removes the value in <paramref name="item" />, indexed by the key in <paramref name="item" />, from the dictionary, if present.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="System.Collections.IEnumerable.GetEnumerator">
+ <MemberSignature Language="C#" Value="System.Collections.IEnumerator IEnumerable.GetEnumerator ();" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance class System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.IEnumerator</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns a <see cref="T:System.Collections.IEnumerator" /> of the <see cref="T:Xamarin.Forms.ResourceDictionary" />'s <see cref="T:System.Collections.Generic.KeyValuePair`1" />s.</summary>
+ <returns>An <see cref="T:System.Collections.IEnumerator" /> of the <see cref="T:Xamarin.Forms.ResourceDictionary" />'s <see cref="T:System.Collections.Generic.KeyValuePair`1" />s.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TryGetValue">
+ <MemberSignature Language="C#" Value="public bool TryGetValue (string key, out object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance bool TryGetValue(string key, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="key" Type="System.String" />
+ <Parameter Name="value" Type="System.Object&amp;" RefType="out" />
+ </Parameters>
+ <Docs>
+ <param name="key">The identifier of the object to be retrieved.</param>
+ <param name="value">An <see langword="out" /> reference to the object being retrieved, or it's default value.</param>
+ <summary>Retrieves the object specified by <paramref name="key" /> or, if not present, the default value of <see langword="null" />.</summary>
+ <returns>The object specified by <paramref name="key" /> or, if not present, the default value of <see langword="null" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Values">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.ICollection&lt;object&gt; Values { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.ICollection`1&lt;object&gt; Values" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.ICollection&lt;System.Object&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Retrieves the values of the <see cref="T:Xamarin.Forms.ResourceDictionary" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/RoutingEffect.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/RoutingEffect.xml
new file mode 100644
index 00000000..022016e2
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/RoutingEffect.xml
@@ -0,0 +1,66 @@
+<Type Name="RoutingEffect" FullName="Xamarin.Forms.RoutingEffect">
+ <TypeSignature Language="C#" Value="public class RoutingEffect : Xamarin.Forms.Effect" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit RoutingEffect extends Xamarin.Forms.Effect" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Effect</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Platform-independent effect that wraps an inner effect, which is usually platform-specific.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected RoutingEffect (string effectId);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor(string effectId) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="effectId" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="effectId">To be added.</param>
+ <summary>Creates a new routing effect with the specified <paramref name="effectId" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnAttached">
+ <MemberSignature Language="C#" Value="protected override void OnAttached ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnAttached() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Method that is called after the effect is attached and made valid.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnDetached">
+ <MemberSignature Language="C#" Value="protected override void OnDetached ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnDetached() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Method that is called after the effect is detached and invalidated.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/RowDefinition.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/RowDefinition.xml
new file mode 100644
index 00000000..2c18764e
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/RowDefinition.xml
@@ -0,0 +1,135 @@
+<Type Name="RowDefinition" FullName="Xamarin.Forms.RowDefinition">
+ <TypeSignature Language="C#" Value="public sealed class RowDefinition : Xamarin.Forms.BindableObject, Xamarin.Forms.IDefinition" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit RowDefinition extends Xamarin.Forms.BindableObject implements class Xamarin.Forms.IDefinition" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IDefinition</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>An <see cref="T:Xamarin.Forms.IDefinition" /> that defines properties for a row in a <see cref="T:Xamarin.Forms.Grid" />.</summary>
+ <remarks>
+ <para>XAML for Xamarin.Forms supports the following property for the <see cref="T:Xamarin.Forms.RowDefinition" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Height</term>
+ <description>
+ <para>"*" or "Auto" to indicate the corresponding <see cref="T:Xamarin.Forms.GridUnitType" /> enumeration values, or a number to indicate an absolute height.</para>
+ </description>
+ </item>
+ </list>
+ <example>
+ <para>App developers can specify <see cref="T:Xamarin.Forms.GridUnitType" /> values for the <see cref="P:Xamarin.Forms.ColumnDefinition.Height" /> property in XAML. This is typically done inside tags for the <see cref="P:Xamarin.Forms.Grid.RowDefinitions" /> collection property. The following example demonstrates setting three row heights to each of the three valid <see cref="T:Xamarin.Forms.GridUnitType" /> values:</para>
+ <code lang="XAML"><![CDATA[
+<Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ <RowDefinition Height="100" />
+</Grid.RowDefinitions>
+]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public RowDefinition ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.RowDefinition" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Height">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.GridLength Height { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.GridLength Height" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.GridLength</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the height of the row.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HeightProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HeightProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HeightProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.RowDefinition.Height" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SizeChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler SizeChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler SizeChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the size of the row is changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/RowDefinitionCollection.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/RowDefinitionCollection.xml
new file mode 100644
index 00000000..1febebe4
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/RowDefinitionCollection.xml
@@ -0,0 +1,46 @@
+<Type Name="RowDefinitionCollection" FullName="Xamarin.Forms.RowDefinitionCollection">
+ <TypeSignature Language="C#" Value="public sealed class RowDefinitionCollection : Xamarin.Forms.DefinitionCollection&lt;Xamarin.Forms.RowDefinition&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit RowDefinitionCollection extends Xamarin.Forms.DefinitionCollection`1&lt;class Xamarin.Forms.RowDefinition&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.DefinitionCollection&lt;Xamarin.Forms.RowDefinition&gt;</BaseTypeName>
+ <BaseTypeArguments>
+ <BaseTypeArgument TypeParamName="T">Xamarin.Forms.RowDefinition</BaseTypeArgument>
+ </BaseTypeArguments>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.DefinitionCollection`1" /> for <see cref="T:Xamarin.Forms.RowDefinition" />s.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public RowDefinitionCollection ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new empty <see cref="T:Xamarin.Forms.RowDefinitionCollection" /> object.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollOrientation.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollOrientation.xml
new file mode 100644
index 00000000..cfaa2357
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollOrientation.xml
@@ -0,0 +1,77 @@
+<Type Name="ScrollOrientation" FullName="Xamarin.Forms.ScrollOrientation">
+ <TypeSignature Language="C#" Value="public enum ScrollOrientation" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed ScrollOrientation extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumeration specifying vertical or horizontal scrolling directions.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Both">
+ <MemberSignature Language="C#" Value="Both" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ScrollOrientation Both = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ScrollOrientation</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Scroll both horizontally and vertically.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Horizontal">
+ <MemberSignature Language="C#" Value="Horizontal" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ScrollOrientation Horizontal = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ScrollOrientation</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Scroll Horizontally.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Vertical">
+ <MemberSignature Language="C#" Value="Vertical" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ScrollOrientation Vertical = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ScrollOrientation</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Scroll vertically.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollToMode.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollToMode.xml
new file mode 100644
index 00000000..6c85de0e
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollToMode.xml
@@ -0,0 +1,51 @@
+<Type Name="ScrollToMode" FullName="Xamarin.Forms.ScrollToMode">
+ <TypeSignature Language="C#" Value="public enum ScrollToMode" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed ScrollToMode extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumerates values that describe how a scroll request is made.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Element">
+ <MemberSignature Language="C#" Value="Element" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ScrollToMode Element = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ScrollToMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Scroll positions are specified by element.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Position">
+ <MemberSignature Language="C#" Value="Position" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ScrollToMode Position = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ScrollToMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Scroll positions are specified by a float.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollToPosition.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollToPosition.xml
new file mode 100644
index 00000000..4a36cd56
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollToPosition.xml
@@ -0,0 +1,88 @@
+<Type Name="ScrollToPosition" FullName="Xamarin.Forms.ScrollToPosition">
+ <TypeSignature Language="C#" Value="public enum ScrollToPosition" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed ScrollToPosition extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumerates values that describe a scroll request.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Center">
+ <MemberSignature Language="C#" Value="Center" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ScrollToPosition Center = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ScrollToPosition</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Scroll to the center of a list.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="End">
+ <MemberSignature Language="C#" Value="End" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ScrollToPosition End = int32(3)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ScrollToPosition</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Scroll to the end of a list.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="MakeVisible">
+ <MemberSignature Language="C#" Value="MakeVisible" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ScrollToPosition MakeVisible = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ScrollToPosition</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Scroll to make a specified list item visible.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Start">
+ <MemberSignature Language="C#" Value="Start" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ScrollToPosition Start = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ScrollToPosition</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Scroll to the start of a list.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollToRequestedEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollToRequestedEventArgs.xml
new file mode 100644
index 00000000..a734af84
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollToRequestedEventArgs.xml
@@ -0,0 +1,128 @@
+<Type Name="ScrollToRequestedEventArgs" FullName="Xamarin.Forms.ScrollToRequestedEventArgs">
+ <TypeSignature Language="C#" Value="public class ScrollToRequestedEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ScrollToRequestedEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Arguments for the event that is raised when a scroll is requested.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Element">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Element Element { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Element Element" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Element</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>An element to scroll to.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Mode">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.ScrollToMode Mode { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.ScrollToMode Mode" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ScrollToMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Whether to scroll by element or by position.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Position">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.ScrollToPosition Position { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.ScrollToPosition Position" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ScrollToPosition</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>An enumeration value that describes which part of an element to scroll to.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ScrollX">
+ <MemberSignature Language="C#" Value="public double ScrollX { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 ScrollX" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The X position to scroll to.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ScrollY">
+ <MemberSignature Language="C#" Value="public double ScrollY { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 ScrollY" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The Y position to scroll to.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ShouldAnimate">
+ <MemberSignature Language="C#" Value="public bool ShouldAnimate { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool ShouldAnimate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that tells whether the scroll operation should be animated.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollView.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollView.xml
new file mode 100644
index 00000000..9b93bd05
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrollView.xml
@@ -0,0 +1,485 @@
+<Type Name="ScrollView" FullName="Xamarin.Forms.ScrollView">
+ <TypeSignature Language="C#" Value="public class ScrollView : Xamarin.Forms.Layout, Xamarin.Forms.IScrollViewController" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ScrollView extends Xamarin.Forms.Layout implements class Xamarin.Forms.ILayoutController, class Xamarin.Forms.IScrollViewController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.3.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Layout</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IScrollViewController</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Content")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._ScrollViewRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>An element capable of scrolling if its Content requires.</summary>
+ <remarks>
+ <para> The following example shows the creation of a ScrollView with a large <see cref="T:Xamarin.Forms.StackLayout" /> in it.</para>
+ <example>
+ <code lang="C#"><![CDATA[
+StackLayout stack;
+var scrollview = new ScrollView {
+ Content = new StackLayout {
+ Padding = new Thickness (20),
+ },
+};
+
+for (var i=0; i<100; i++)
+ stack.Children.Add (new Button { Text = "Foo"});
+ ]]></code>
+ </example>
+ <block type="note">Application developers should not nest one <see cref="T:Xamarin.Forms.ScrollView" /> within another. Additionally, they should refrain from nesting them other elements that can scroll, such as <see cref="T:Xamarin.Forms.WebView" />.</block>
+ <para>
+ <img href="ScrollView.TripleScreenShot.png" />
+ </para>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.ScrollView" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Content</term>
+ <description>
+ <para>Markup that specifies a <see cref="T:Xamarin.Forms.View" /> to display in the <see cref="T:Xamarin.Forms.ScrollView" />.</para>
+ </description>
+ </item>
+ <item>
+ <term>Orientation</term>
+ <description>
+ <para>
+ <c>Horizontal</c> or <c>Vertical</c>, to indicate the scroll direction.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ScrollView ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.3.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the ScrollView class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Content">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.View Content { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.View Content" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.3.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.View</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a <see cref="T:Xamarin.Forms.View" /> to display in the <see cref="T:Xamarin.Forms.ScrollView" />.</summary>
+ <value>The <see cref="T:Xamarin.Forms.View" /> that is displayed.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ContentSize">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Size ContentSize { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Size ContentSize" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.3.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Size</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the size of the Content. This is a bindable property.</summary>
+ <value>A <see cref="T:Xamarin.Forms.Size" /> that represents the size of the content.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ContentSizeProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ContentSizeProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ContentSizeProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.3.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the ContentSize bindable property.</summary>
+ <remarks>This bindable property is read-only.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutChildren">
+ <MemberSignature Language="C#" Value="protected override void LayoutChildren (double x, double y, double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void LayoutChildren(float64 x, float64 y, float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.3.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">A value that represents the x coordinate of the child region bounding box.</param>
+ <param name="y">A value that represents the y coordinate of the child region bounding box.</param>
+ <param name="width">A value that represents the y coordinate of the child region bounding box.</param>
+ <param name="height">A value that represents the y coordinate of the child region bounding box.</param>
+ <summary>Positions and sizes the content of a ScrollView.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeRequest">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance valuetype Xamarin.Forms.SizeRequest OnSizeRequest(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.3.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use OnMeasure")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">The available width for the element to use.</param>
+ <param name="heightConstraint">The available height for the element to use.</param>
+ <summary>This method is called during the measure pass of a layout cycle to get the desired size of an element.</summary>
+ <returns>
+ A <see cref="T:Xamarin.Forms.SizeRequest&gt;" /> which contains the desired size of the element.
+ </returns>
+ <remarks>The results of this method will be (-1, -1) if the element has not yet been realized with a platform specific backing control. Overriding this method does not require a call to the base class so long as a valid SizeRequest is returned.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Orientation">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.ScrollOrientation Orientation { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.ScrollOrientation Orientation" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.3.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ScrollOrientation</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the scrolling direction of the ScrollView. This is a bindable property.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OrientationProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty OrientationProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty OrientationProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.3.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Orientation bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Scrolled">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ScrolledEventArgs&gt; Scrolled;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ScrolledEventArgs&gt; Scrolled" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ScrolledEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised after a scroll completes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ScrollToAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task ScrollToAsync (double x, double y, bool animated);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Threading.Tasks.Task ScrollToAsync(float64 x, float64 y, bool animated) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ <Parameter Name="animated" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="x">To be added.</param>
+ <param name="y">To be added.</param>
+ <param name="animated">To be added.</param>
+ <summary>Returns a task that scrolls the scroll view to a position asynchronously.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ScrollToAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task ScrollToAsync (Xamarin.Forms.Element element, Xamarin.Forms.ScrollToPosition position, bool animated);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Threading.Tasks.Task ScrollToAsync(class Xamarin.Forms.Element element, valuetype Xamarin.Forms.ScrollToPosition position, bool animated) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="element" Type="Xamarin.Forms.Element" />
+ <Parameter Name="position" Type="Xamarin.Forms.ScrollToPosition" />
+ <Parameter Name="animated" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="element">To be added.</param>
+ <param name="position">To be added.</param>
+ <param name="animated">To be added.</param>
+ <summary>Returns a task that scrolls the scroll view to an element asynchronously.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ScrollX">
+ <MemberSignature Language="C#" Value="public double ScrollX { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 ScrollX" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the current X scroll position.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ScrollXProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ScrollXProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ScrollXProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ScrollView.ScrollX" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ScrollY">
+ <MemberSignature Language="C#" Value="public double ScrollY { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 ScrollY" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the current Y scroll position..</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ScrollYProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ScrollYProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ScrollYProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ScrollView.ScrollY" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IScrollViewController.GetScrollPositionForElement">
+ <MemberSignature Language="C#" Value="Xamarin.Forms.Point IScrollViewController.GetScrollPositionForElement (Xamarin.Forms.VisualElement item, Xamarin.Forms.ScrollToPosition pos);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance valuetype Xamarin.Forms.Point Xamarin.Forms.IScrollViewController.GetScrollPositionForElement(class Xamarin.Forms.VisualElement item, valuetype Xamarin.Forms.ScrollToPosition pos) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Point</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="Xamarin.Forms.VisualElement" />
+ <Parameter Name="pos" Type="Xamarin.Forms.ScrollToPosition" />
+ </Parameters>
+ <Docs>
+ <param name="item">To be added.</param>
+ <param name="pos">To be added.</param>
+ <summary>Internal.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IScrollViewController.SendScrollFinished">
+ <MemberSignature Language="C#" Value="void IScrollViewController.SendScrollFinished ();" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IScrollViewController.SendScrollFinished() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Internal.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IScrollViewController.SetScrolledPosition">
+ <MemberSignature Language="C#" Value="void IScrollViewController.SetScrolledPosition (double x, double y);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IScrollViewController.SetScrolledPosition(float64 x, float64 y) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">To be added.</param>
+ <param name="y">To be added.</param>
+ <summary>Internal.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrolledEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrolledEventArgs.xml
new file mode 100644
index 00000000..abe04d55
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ScrolledEventArgs.xml
@@ -0,0 +1,76 @@
+<Type Name="ScrolledEventArgs" FullName="Xamarin.Forms.ScrolledEventArgs">
+ <TypeSignature Language="C#" Value="public class ScrolledEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ScrolledEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Arguments for the event that is raised when a window is scrolled.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ScrolledEventArgs (double x, double y);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 x, float64 y) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">To be added.</param>
+ <param name="y">To be added.</param>
+ <summary>Constructs a new <see cref="T:Xamarin.Forms.ScrolledEventArgs" /> object for a scroll to <paramref name="x" /> and <paramref name="y" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ScrollX">
+ <MemberSignature Language="C#" Value="public double ScrollX { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 ScrollX" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The X position of the finished scroll.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ScrollY">
+ <MemberSignature Language="C#" Value="public double ScrollY { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 ScrollY" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The Y position of the finished scroll.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/SearchBar.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/SearchBar.xml
new file mode 100644
index 00000000..e923a674
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/SearchBar.xml
@@ -0,0 +1,588 @@
+<Type Name="SearchBar" FullName="Xamarin.Forms.SearchBar">
+ <TypeSignature Language="C#" Value="public class SearchBar : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit SearchBar extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._SearchBarRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.View" /> control that provides a search box.</summary>
+ <remarks>
+ <para>The following example shows a basic use.</para>
+ <example>
+ <code lang="C#"><![CDATA[
+public class App : Application
+{
+ Label resultsLabel;
+ SearchBar searchBar;
+ public App ()
+ {
+ resultsLabel = new Label {
+ Text = "Result will appear here.",
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ FontSize = 25
+ };
+
+ searchBar = new SearchBar {
+ Placeholder = "Enter search term",
+ SearchCommand = new Command(() => {resultsLabel.Text = "Result: " + searchBar.Text + " is what you asked for.";})
+ };
+
+ MainPage = new ContentPage {
+ Content = new StackLayout {
+ VerticalOptions = LayoutOptions.Start,
+ Children = {
+ new Label {
+ HorizontalTextAlignment = TextAlignment.Center,
+ Text = "SearchBar",
+ FontSize = 50
+ },
+ searchBar,
+ new ScrollView
+ {
+ Content = resultsLabel,
+ VerticalOptions = LayoutOptions.FillAndExpand
+ }
+ },
+ Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5)
+ }
+ };
+ }
+
+ // OnStart, OnSleep, and OnResume implementations, & etc.
+
+}]]></code>
+ </example>
+ <para>
+ <img href="SearchBar.TripleScreenShot.png" />
+ </para>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.SearchBar" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>CancelButtonColor</term>
+ <description>
+ <para>A color specification, with or without the prefix, "Color". For example, "Color.Red" and "Red" both specify the color red.</para>
+ </description>
+ </item>
+ <item>
+ <term>Placeholder</term>
+ <description>
+ <para>The default text that will appear in the search bar when it is empty.</para>
+ </description>
+ </item>
+ <item>
+ <term>SearchCommand</term>
+ <description>
+ <para>XAML markup extension that describes a binding to a command.</para>
+ </description>
+ </item>
+ <item>
+ <term>SearchCommandParameter</term>
+ <description>
+ <para>The parameter for the search command.</para>
+ </description>
+ </item>
+ <item>
+ <term>Text</term>
+ <description>
+ <para>The initial text that will appear in the search bar.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public SearchBar ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.SearchBar" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CancelButtonColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color CancelButtonColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color CancelButtonColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the color of the cancel button.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CancelButtonColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty CancelButtonColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty CancelButtonColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the CancelButtonColor property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontAttributes">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.FontAttributes FontAttributes { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.FontAttributes FontAttributes" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FontAttributes</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that indicates whether the font for the searchbar text is bold, italic, or neither.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontAttributesProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontAttributesProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontAttributesProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the FontAttributes property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontFamily">
+ <MemberSignature Language="C#" Value="public string FontFamily { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string FontFamily" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the font family for the search bar text.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontFamilyProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontFamilyProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontFamilyProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the FontFamily property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontSize">
+ <MemberSignature Language="C#" Value="public double FontSize { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 FontSize" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.FontSizeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the size of the font for the text in the searchbar.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontSizeProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FontSizeProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FontSizeProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the FontSize property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HorizontalTextAlignment">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.TextAlignment HorizontalTextAlignment { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.TextAlignment HorizontalTextAlignment" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TextAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the horizontal text alignment.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HorizontalTextAlignmentProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HorizontalTextAlignmentProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HorizontalTextAlignmentProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.SearchBar.HorizontalTextAlignment" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Placeholder">
+ <MemberSignature Language="C#" Value="public string Placeholder { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Placeholder" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the text that is displayed when the <see cref="T:Xamarin.Forms.SearchBar" /> is empty.</summary>
+ <value>The text that is displayed when the <see cref="T:Xamarin.Forms.SearchBar" /> is empty.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PlaceholderColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color PlaceholderColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color PlaceholderColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the color of the placheholder text.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PlaceholderColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty PlaceholderColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty PlaceholderColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.SearchBar.PlaceholderColor" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PlaceholderProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty PlaceholderProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty PlaceholderProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.SearchBar.Placeholder" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SearchButtonPressed">
+ <MemberSignature Language="C#" Value="public event EventHandler SearchButtonPressed;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler SearchButtonPressed" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the user presses the Search button.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SearchCommand">
+ <MemberSignature Language="C#" Value="public System.Windows.Input.ICommand SearchCommand { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Windows.Input.ICommand SearchCommand" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Windows.Input.ICommand</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the command that is run when the user presses Search button.</summary>
+ <value>The command that is run when the user presses Search button.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SearchCommandParameter">
+ <MemberSignature Language="C#" Value="public object SearchCommandParameter { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object SearchCommandParameter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the parameter that is sent to the <see cref="P:Xamarin.Forms.SearchBar.SearchCommand" />.</summary>
+ <value>The parameter that is sent to the <see cref="P:Xamarin.Forms.SearchBar.SearchCommand" />.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SearchCommandParameterProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty SearchCommandParameterProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty SearchCommandParameterProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.SearchBar.SearchCommandParameter" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SearchCommandProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty SearchCommandProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty SearchCommandProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.SearchBar.SearchCommand" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Text">
+ <MemberSignature Language="C#" Value="public string Text { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Text" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the text that is displayed in the <see cref="T:Xamarin.Forms.SearchBar" />.</summary>
+ <value>The text that is displayed in the <see cref="T:Xamarin.Forms.SearchBar" />.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.TextChangedEventArgs&gt; TextChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.TextChangedEventArgs&gt; TextChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.TextChangedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the <see cref="P:Xamarin.Forms.SearchBar.Text" /> property is changed. For example, this event is raised as the user edits the text in the SearchBar.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color TextColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color TextColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the text color.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TextColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TextColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.SearchBar.TextColor" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TextProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TextProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.SearchBar.Text" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/SelectedItemChangedEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/SelectedItemChangedEventArgs.xml
new file mode 100644
index 00000000..30c7455f
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/SelectedItemChangedEventArgs.xml
@@ -0,0 +1,68 @@
+<Type Name="SelectedItemChangedEventArgs" FullName="Xamarin.Forms.SelectedItemChangedEventArgs">
+ <TypeSignature Language="C#" Value="public class SelectedItemChangedEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit SelectedItemChangedEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Event arguments for the <see cref="E:Xamarin.Forms.ListView.ItemSelected" /> event.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public SelectedItemChangedEventArgs (object selectedItem);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(object selectedItem) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="selectedItem" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="selectedItem">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.SelectedItemChangedEventArgs" /> event that indicates that the user has selected <paramref name="selectedItem" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SelectedItem">
+ <MemberSignature Language="C#" Value="public object SelectedItem { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object SelectedItem" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the new selected item.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/SelectedPositionChangedEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/SelectedPositionChangedEventArgs.xml
new file mode 100644
index 00000000..0fc4e73a
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/SelectedPositionChangedEventArgs.xml
@@ -0,0 +1,50 @@
+<Type Name="SelectedPositionChangedEventArgs" FullName="Xamarin.Forms.SelectedPositionChangedEventArgs">
+ <TypeSignature Language="C#" Value="public class SelectedPositionChangedEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit SelectedPositionChangedEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public SelectedPositionChangedEventArgs (int selectedPosition);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(int32 selectedPosition) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="selectedPosition" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="selectedPosition">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SelectedPosition">
+ <MemberSignature Language="C#" Value="public object SelectedPosition { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object SelectedPosition" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/SeparatorVisibility.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/SeparatorVisibility.xml
new file mode 100644
index 00000000..f6fcf261
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/SeparatorVisibility.xml
@@ -0,0 +1,54 @@
+<Type Name="SeparatorVisibility" FullName="Xamarin.Forms.SeparatorVisibility">
+ <TypeSignature Language="C#" Value="public enum SeparatorVisibility" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed SeparatorVisibility extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumerates values that control the visibility of list item separators.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Default">
+ <MemberSignature Language="C#" Value="Default" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.SeparatorVisibility Default = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SeparatorVisibility</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Use the default visibility for the platform.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="None">
+ <MemberSignature Language="C#" Value="None" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.SeparatorVisibility None = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.5.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SeparatorVisibility</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Do not display separators.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Setter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Setter.xml
new file mode 100644
index 00000000..8e060434
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Setter.xml
@@ -0,0 +1,131 @@
+<Type Name="Setter" FullName="Xamarin.Forms.Setter">
+ <TypeSignature Language="C#" Value="public sealed class Setter : Xamarin.Forms.Xaml.IValueProvider" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit Setter extends System.Object implements class Xamarin.Forms.Xaml.IValueProvider" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IValueProvider</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Value")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Represents an assignment of a property to a value, typically in a style or in response to a trigger.</summary>
+ <remarks>
+ <para>Setters are used with triggers and styles.</para>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.Setter" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Property</term>
+ <description>
+ <para>The name of the property to set.</para>
+ </description>
+ </item>
+ <item>
+ <term>Value</term>
+ <description>
+ <para>The value to apply to the property.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Setter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Setter" /> object.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Property">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.BindableProperty Property { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.BindableProperty Property" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The property on which to apply the assignment.</summary>
+ <value>To be added.</value>
+ <remarks>
+ <para>Only bindable properties can be set with a <see cref="T:Xamarin.Forms.Setter" />.</para>.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Value">
+ <MemberSignature Language="C#" Value="public object Value { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Value" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The value to assign to the property.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IValueProvider.ProvideValue">
+ <MemberSignature Language="C#" Value="object IValueProvider.ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.Xaml.IValueProvider.ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>
+ <para />
+ </summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/SettersExtensions.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/SettersExtensions.xml
new file mode 100644
index 00000000..d33d5890
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/SettersExtensions.xml
@@ -0,0 +1,101 @@
+<Type Name="SettersExtensions" FullName="Xamarin.Forms.SettersExtensions">
+ <TypeSignature Language="C#" Value="public static class SettersExtensions" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract sealed beforefieldinit SettersExtensions extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Defines extensions methods for IList&lt;Setter&gt;</summary>
+ <remarks>
+ <para />
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public static void Add (this System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt; setters, Xamarin.Forms.BindableProperty property, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Add(class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Setter&gt; setters, class Xamarin.Forms.BindableProperty property, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="setters" Type="System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt;" RefType="this" />
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="setters">To be added.</param>
+ <param name="property">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Add a Setter with a value to the IList&lt;Setter&gt;</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AddBinding">
+ <MemberSignature Language="C#" Value="public static void AddBinding (this System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt; setters, Xamarin.Forms.BindableProperty property, Xamarin.Forms.Binding binding);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void AddBinding(class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Setter&gt; setters, class Xamarin.Forms.BindableProperty property, class Xamarin.Forms.Binding binding) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="setters" Type="System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt;" RefType="this" />
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="binding" Type="Xamarin.Forms.Binding" />
+ </Parameters>
+ <Docs>
+ <param name="setters">To be added.</param>
+ <param name="property">To be added.</param>
+ <param name="binding">To be added.</param>
+ <summary>Add a Setter with a Binding to the IList&lt;Setter&gt;</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AddDynamicResource">
+ <MemberSignature Language="C#" Value="public static void AddDynamicResource (this System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt; setters, Xamarin.Forms.BindableProperty property, string key);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void AddDynamicResource(class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Setter&gt; setters, class Xamarin.Forms.BindableProperty property, string key) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="setters" Type="System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt;" RefType="this" />
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="key" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="setters">To be added.</param>
+ <param name="property">To be added.</param>
+ <param name="key">To be added.</param>
+ <summary>Add a Setter with a DynamicResource to the IList&lt;Setter&gt;</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Size.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Size.xml
new file mode 100644
index 00000000..44701ace
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Size.xml
@@ -0,0 +1,425 @@
+<Type Name="Size" FullName="Xamarin.Forms.Size">
+ <TypeSignature Language="C#" Value="public struct Size" />
+ <TypeSignature Language="ILAsm" Value=".class public sequential ansi sealed beforefieldinit Size extends System.ValueType" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.ValueType</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.DebuggerDisplay("Width={Width}, Height={Height}")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Struct defining height and width as a pair of doubles.</summary>
+ <remarks>
+ <para>Application developers should be aware of the limits of floating-point representations, specifically the possibility of incorrect comparisons and equality checks for values with small differences. David Goldberg's paper <format type="text/html"><a href="http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html">What Every Computer Scientist Should Know About Floating-Point Arithmetic</a></format> describes the issues excellently. </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Size (double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 width, float64 height) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="width">To be added.</param>
+ <param name="height">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Size" /> object with <paramref name="width" /> and <paramref name="height" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Equals">
+ <MemberSignature Language="C#" Value="public override bool Equals (object obj);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool Equals(object obj) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="obj" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="obj">The object to which <c>this</c> is being compared.</param>
+ <summary>Whether <c>this</c><see cref="T:Xamarin.Forms.Size" /> is equivalent to <paramref name="obj" />.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="obj" /> is a <see cref="T:Xamarin.Forms.Size" /> whose values are identical to <c>this</c><see cref="T:Xamarin.Forms.Size" />'s <see cref="P:Xamarin.Forms.Size.Height" /> and <see cref="P:Xamarin.Forms.Size.Width" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Equals">
+ <MemberSignature Language="C#" Value="public bool Equals (Xamarin.Forms.Size other);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance bool Equals(valuetype Xamarin.Forms.Size other) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="other" Type="Xamarin.Forms.Size" />
+ </Parameters>
+ <Docs>
+ <param name="other">The <see cref="T:Xamarin.Forms.Size" /> to which <c>this</c> is being compared.</param>
+ <summary>Whether <c>this</c><see cref="T:Xamarin.Forms.Size" /> is equivalent to <paramref name="other" />.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="other" />'s values are identical to <c>this</c><see cref="T:Xamarin.Forms.Size" />'s <see cref="P:Xamarin.Forms.Size.Height" /> and <see cref="P:Xamarin.Forms.Size.Width" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetHashCode">
+ <MemberSignature Language="C#" Value="public override int GetHashCode ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance int32 GetHashCode() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns a hash value for the <see cref="T:Xamarin.Forms.Size" />.</summary>
+ <returns>A value intended for efficient insertion and lookup in hashtable-based data structures.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Height">
+ <MemberSignature Language="C#" Value="public double Height { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Height" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.ComponentModel.DefaultValue(0)</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Magnitude along the vertical axis, in platform-specific units.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsZero">
+ <MemberSignature Language="C#" Value="public bool IsZero { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsZero" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Whether the <see cref="T:Xamarin.Forms.Size" /> has <see cref="P:Xamarin.Forms.Size.Height" /> and <see cref="P:Xamarin.Forms.Size.Width" /> of 0.0.</summary>
+ <value>
+ <see langword="true" /> if both <see cref="P:Xamarin.Forms.Size.Height" /> and <see cref="P:Xamarin.Forms.Width" /> are 0.0.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Addition">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Size op_Addition (Xamarin.Forms.Size s1, Xamarin.Forms.Size s2);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname valuetype Xamarin.Forms.Size op_Addition(valuetype Xamarin.Forms.Size s1, valuetype Xamarin.Forms.Size s2) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Size</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="s1" Type="Xamarin.Forms.Size" />
+ <Parameter Name="s2" Type="Xamarin.Forms.Size" />
+ </Parameters>
+ <Docs>
+ <param name="s1">A <see cref="T:Xamarin.Forms.Size" /> to be added.</param>
+ <param name="s2">A <see cref="T:Xamarin.Forms.Size" /> to be added.</param>
+ <summary>Returns a new <see cref="T:Xamarin.Forms.Size" /> whose <see cref="P:Xamarin.Forms.Size.Height" /> and <see cref="P:Xamarin.Forms.Size.Width" /> are the sum of the component's height and width.</summary>
+ <returns>A <see cref="T:Xamarin.Forms.Size" /> whose <see cref="P:Xamarin.Forms.Size.Width" /> is equal to <c>s1.Width + s2.Width</c> and whose <see cref="P:Xamarin.Forms.Size.Height" /> is equal to <c>sz1.Height + sz2.Height</c>.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Equality">
+ <MemberSignature Language="C#" Value="public static bool op_Equality (Xamarin.Forms.Size s1, Xamarin.Forms.Size s2);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Equality(valuetype Xamarin.Forms.Size s1, valuetype Xamarin.Forms.Size s2) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="s1" Type="Xamarin.Forms.Size" />
+ <Parameter Name="s2" Type="Xamarin.Forms.Size" />
+ </Parameters>
+ <Docs>
+ <param name="s1">A <see cref="T:Xamarin.Forms.Size" /> to be compared.</param>
+ <param name="s2">A <see cref="T:Xamarin.Forms.Size" /> to be compared.</param>
+ <summary>Whether two <see cref="T:Xamarin.Forms.Size" />s have equal values.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="s1" /> and <paramref name="s2" /> have equal values for <see cref="P:Xamarin.Forms.Size.Height" /> and <see cref="P:Xamarin.Forms.Size.Width" />.</returns>
+ <remarks>
+ <para>Application developers should be aware that <see cref="P:Xamarin.Forms.Size.Width" /> and <see cref="P:Xamarin.Forms.Size.Height" /> are stored internally as <see langword="double" />s. Values with small differences may compare incorrectly due to internal rounding limitations.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Explicit">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Point op_Explicit (Xamarin.Forms.Size size);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname valuetype Xamarin.Forms.Point op_Explicit(valuetype Xamarin.Forms.Size size) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Point</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="size" Type="Xamarin.Forms.Size" />
+ </Parameters>
+ <Docs>
+ <param name="size">The <see cref="T:Xamarin.Forms.Size" /> to be converted to a <see cref="T:Xamarin.Forms.Point" />.</param>
+ <summary>Returns a new <see cref="T:Xamarin.Forms.Point" /> based on a <see cref="T:Xamarin.Forms.Size" />.</summary>
+ <returns>A <see cref="T:Xamarin.Forms.Point" /> whose <see cref="P:Xamarin.Forms.Point.X" /> and <see cref="P:Xamarin.Forms.Point.Y" /> are equal to <paramref name="size" />'s <see cref="P:Xamarin.Forms.Size.Width" /> and <see cref="P:Xamarin.Forms.Size.Height" />, respectively.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Inequality">
+ <MemberSignature Language="C#" Value="public static bool op_Inequality (Xamarin.Forms.Size s1, Xamarin.Forms.Size s2);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Inequality(valuetype Xamarin.Forms.Size s1, valuetype Xamarin.Forms.Size s2) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="s1" Type="Xamarin.Forms.Size" />
+ <Parameter Name="s2" Type="Xamarin.Forms.Size" />
+ </Parameters>
+ <Docs>
+ <param name="s1">To be added.</param>
+ <param name="s2">To be added.</param>
+ <summary>Whether two <see cref="T:Xamarin.Forms.Size" />s have unequal values.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="s1" /> and <paramref name="s2" /> have unequal values for either <see cref="P:Xamarin.Forms.Size.Height" /> or <see cref="P:Xamarin.Forms.Size.Width" />.</returns>
+ <remarks>
+ <para>Application developers should be aware that <see cref="P:Xamarin.Forms.Size.Width" /> and <see cref="P:Xamarin.Forms.Size.Height" /> are stored internally as <see langword="double" />s. Values with small differences may compare incorrectly due to internal rounding limitations.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Multiply">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Size op_Multiply (Xamarin.Forms.Size s1, double value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname valuetype Xamarin.Forms.Size op_Multiply(valuetype Xamarin.Forms.Size s1, float64 value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Size</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="s1" Type="Xamarin.Forms.Size" />
+ <Parameter Name="value" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="s1">A <see cref="T:Xamarin.Forms.Size" /> to be scaled.</param>
+ <param name="value">A factor by which to multiple <paramref name="s1" />'s <see cref="P:Xamarin.Forms.Size.Width" /> and <see cref="P:Xamarin.Forms.Size.Height" /> values.</param>
+ <summary>Scales both <see cref="P:Xamarin.Forms.Size.Width" /> and <see cref="P:Xamarin.Forms.Size.Height" />.</summary>
+ <returns>A new <see cref="T:Xamarin.Forms.Size" /> whose <see cref="P:Xamarin.Forms.Size.Width" /> and <see cref="P:Xamarin.Forms.Size.Height" /> have been scaled by <paramref name="value" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Subtraction">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Size op_Subtraction (Xamarin.Forms.Size s1, Xamarin.Forms.Size s2);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname valuetype Xamarin.Forms.Size op_Subtraction(valuetype Xamarin.Forms.Size s1, valuetype Xamarin.Forms.Size s2) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Size</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="s1" Type="Xamarin.Forms.Size" />
+ <Parameter Name="s2" Type="Xamarin.Forms.Size" />
+ </Parameters>
+ <Docs>
+ <param name="s1">A <see cref="T:Xamarin.Forms.Size" /> from whose values a size will be subtracted.</param>
+ <param name="s2">The <see cref="T:Xamarin.Forms.Size" /> to subtract from <paramref name="s1" />.</param>
+ <summary>Returns a new <see cref="T:Xamarin.Forms.Size" /> whose <see cref="P:Xamarin.Forms.Size.Height" /> and <see cref="P:Xamarin.Forms.Size.Width" /> are <paramref name="s1" />'s height and width minus the values in <paramref name="s2" />.</summary>
+ <returns>A <see cref="T:Xamarin.Forms.Size" /> whose <see cref="P:Xamarin.Forms.Size.Width" /> is equal to <c>s1.Width - s2.Width</c> and whose <see cref="P:Xamarin.Forms.Size.Height" /> is equal to <c>sz1.Height - sz2.Height</c>.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ToString">
+ <MemberSignature Language="C#" Value="public override string ToString ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance string ToString() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns a human-readable representation of the <see cref="T:Xamarin.Forms.Size" />.</summary>
+ <returns>The format has the pattern "{Width={0} Height={1}}".</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Width">
+ <MemberSignature Language="C#" Value="public double Width { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Width" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.ComponentModel.DefaultValue(0)</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Magnitude along the horizontal axis, in platform-defined units.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Zero">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.Size Zero;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly valuetype Xamarin.Forms.Size Zero" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Size</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The <see cref="T:Xamarin.Forms.Size" /> whose values for height and width are 0.0.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/SizeRequest.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/SizeRequest.xml
new file mode 100644
index 00000000..7edf929f
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/SizeRequest.xml
@@ -0,0 +1,144 @@
+<Type Name="SizeRequest" FullName="Xamarin.Forms.SizeRequest">
+ <TypeSignature Language="C#" Value="public struct SizeRequest" />
+ <TypeSignature Language="ILAsm" Value=".class public sequential ansi sealed beforefieldinit SizeRequest extends System.ValueType" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.4.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.ValueType</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.DebuggerDisplay("Request={Request.Width}x{Request.Height}, Minimum={Minimum.Width}x{Minimum.Height}")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Struct that definse minimum and maximum <see cref="T:Xamarin.Forms.Size" />s.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public SizeRequest (Xamarin.Forms.Size request);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(valuetype Xamarin.Forms.Size request) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.4.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="request" Type="Xamarin.Forms.Size" />
+ </Parameters>
+ <Docs>
+ <param name="request">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.SizeRequest" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public SizeRequest (Xamarin.Forms.Size request, Xamarin.Forms.Size minimum);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(valuetype Xamarin.Forms.Size request, valuetype Xamarin.Forms.Size minimum) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.4.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="request" Type="Xamarin.Forms.Size" />
+ <Parameter Name="minimum" Type="Xamarin.Forms.Size" />
+ </Parameters>
+ <Docs>
+ <param name="request">To be added.</param>
+ <param name="minimum">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.SizeRequest" /> object that requests at least the size <paramref name="minimum" />, but preferably the size <paramref name="request" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Minimum">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Size Minimum { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Size Minimum" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.4.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Size</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The minimum acceptable size.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Request">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Size Request { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Size Request" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.4.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Size</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The requested size.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ToString">
+ <MemberSignature Language="C#" Value="public override string ToString ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance string ToString() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.4.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns a string representation of the size request.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Slider.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Slider.xml
new file mode 100644
index 00000000..3ae554ef
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Slider.xml
@@ -0,0 +1,320 @@
+<Type Name="Slider" FullName="Xamarin.Forms.Slider">
+ <TypeSignature Language="C#" Value="public class Slider : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Slider extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._SliderRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.View" /> control that inputs a linear value.</summary>
+ <remarks>
+ <para>
+ <img href="Slider.TripleScreenShot.png" />
+ </para>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.Slider" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Maximum</term>
+ <description>
+ <para>An integer or decimal literal.</para>
+ </description>
+ </item>
+ <item>
+ <term>Minimum</term>
+ <description>
+ <para>An integer or decimal literal. If this value is nonnegative, it must appear lexically below <c>Maximum</c>, so that validation can succeed.</para>
+ </description>
+ </item>
+ <item>
+ <term>Value</term>
+ <description>
+ <para>An integer or decimal literal that represents a number that is in the range[<c>Minimum</c>,<c>Maximum</c>].</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Slider ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the Slider class.</summary>
+ <remarks>
+ <para>The following example shows a basic use.</para>
+ <example>
+ <code lang="C#"><![CDATA[using System;
+using Xamarin.Forms;
+
+namespace FormsGallery
+{
+ class SliderDemoPage : ContentPage
+ {
+ Label label;
+
+ public SliderDemoPage()
+ {
+ Label header = new Label
+ {
+ Text = "Slider",
+ Font = Font.BoldSystemFontOfSize(50),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ Slider slider = new Slider
+ {
+ Minimum = 0,
+ Maximum = 100,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+ slider.ValueChanged += OnSliderValueChanged;
+
+ label = new Label
+ {
+ Text = "Slider value is 0",
+ Font = Font.SystemFontOfSize(NamedSize.Large),
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+
+ // Accomodate iPhone status bar.
+ this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
+
+ // Build the page.
+ this.Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ slider,
+ label
+ }
+ };
+ }
+
+ void OnSliderValueChanged(object sender, ValueChangedEventArgs e)
+ {
+ label.Text = String.Format("Slider value is {0:F1}", e.NewValue);
+ }
+ }
+}]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Slider (double min, double max, double val);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 min, float64 max, float64 val) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="min" Type="System.Double" />
+ <Parameter Name="max" Type="System.Double" />
+ <Parameter Name="val" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="min">The minimum selectable value.</param>
+ <param name="max">The maximum selectable value.</param>
+ <param name="val">The actual value.</param>
+ <summary>Initializes a new instance of the Slider class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Maximum">
+ <MemberSignature Language="C#" Value="public double Maximum { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Maximum" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the maximum selectable value for the Slider. This is a bindable property.</summary>
+ <value>A double.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MaximumProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty MaximumProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty MaximumProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Maximum bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Minimum">
+ <MemberSignature Language="C#" Value="public double Minimum { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Minimum" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the minimum selectable value for the Slider. This is a bindable property.</summary>
+ <value>A double.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MinimumProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty MinimumProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty MinimumProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Minimum bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Value">
+ <MemberSignature Language="C#" Value="public double Value { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Value" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the current value. This is a bindable property.</summary>
+ <value>A double.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ValueChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ValueChangedEventArgs&gt; ValueChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ValueChangedEventArgs&gt; ValueChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ValueChangedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The ValueChanged event is fired when the Value property changes.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ValueProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ValueProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ValueProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Value bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Span.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Span.xml
new file mode 100644
index 00000000..b6d74c5f
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Span.xml
@@ -0,0 +1,214 @@
+<Type Name="Span" FullName="Xamarin.Forms.Span">
+ <TypeSignature Language="C#" Value="public sealed class Span : System.ComponentModel.INotifyPropertyChanged" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit Span extends System.Object implements class System.ComponentModel.INotifyPropertyChanged" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.ComponentModel.INotifyPropertyChanged</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Text")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Represents a part of a FormattedString.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Span ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initialize a new instance of the Span class.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BackgroundColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color BackgroundColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color BackgroundColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the Color of the span background.</summary>
+ <value>To be added.</value>
+ <remarks>Not supported on WindowsPhone.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Font">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Font Font { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Font Font" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Please use the Font properties directly. Obsolete in 1.3.0")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Font</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the Font for the text in the span.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontAttributes">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.FontAttributes FontAttributes { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.FontAttributes FontAttributes" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FontAttributes</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that indicates whether the font for the span is bold, italic, or neither.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontFamily">
+ <MemberSignature Language="C#" Value="public string FontFamily { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string FontFamily" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the font family to which the font for the text in the span belongs.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FontSize">
+ <MemberSignature Language="C#" Value="public double FontSize { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 FontSize" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.FontSizeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the size of the font for the text in the span.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ForegroundColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color ForegroundColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color ForegroundColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the Color for the text in the span.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PropertyChanged">
+ <MemberSignature Language="C#" Value="public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.ComponentModel.PropertyChangedEventHandler PropertyChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.ComponentModel.PropertyChangedEventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when a property is changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Text">
+ <MemberSignature Language="C#" Value="public string Text { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Text" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the text of the span.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/StackLayout.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/StackLayout.xml
new file mode 100644
index 00000000..df187061
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/StackLayout.xml
@@ -0,0 +1,357 @@
+<Type Name="StackLayout" FullName="Xamarin.Forms.StackLayout">
+ <TypeSignature Language="C#" Value="public class StackLayout : Xamarin.Forms.Layout&lt;Xamarin.Forms.View&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit StackLayout extends Xamarin.Forms.Layout`1&lt;class Xamarin.Forms.View&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Layout&lt;Xamarin.Forms.View&gt;</BaseTypeName>
+ <BaseTypeArguments>
+ <BaseTypeArgument TypeParamName="T">Xamarin.Forms.View</BaseTypeArgument>
+ </BaseTypeArguments>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.Layout`1" /> that positions child elements in a single line which can be oriented vertically or horizontally.</summary>
+ <remarks>
+ <para>Because <see cref="T:Xamarin.Forms.StackLayout" /> layouts override the bounds on their child elements, application developers should not set bounds on them.</para>
+ <example>
+ <para>The following example code, adapted from the <format type="text/html"><a href="http://developer.xamarin.com/samples/tag/Xamarin.Forms/" target="_blank">FormsGallery</a></format> example shows how to create a new <see cref="T:Xamarin.Forms.StackLayout" /> with children that explore many of the layout behaviors of <see cref="T:Xamarin.Forms.StackLayout" />:</para>
+ <code lang="C#"><![CDATA[
+StackLayout stackLayout = new StackLayout
+{
+ Spacing = 0,
+ VerticalOptions = LayoutOptions.FillAndExpand,
+ Children =
+ {
+ new Label
+ {
+ Text = "StackLayout",
+ HorizontalOptions = LayoutOptions.Start
+ },
+ new Label
+ {
+ Text = "stacks its children",
+ HorizontalOptions = LayoutOptions.Center
+ },
+ new Label
+ {
+ Text = "vertically",
+ HorizontalOptions = LayoutOptions.End
+ },
+ new Label
+ {
+ Text = "by default,",
+ HorizontalOptions = LayoutOptions.Center
+ },
+ new Label
+ {
+ Text = "but horizontal placement",
+ HorizontalOptions = LayoutOptions.Start
+ },
+ new Label
+ {
+ Text = "can be controlled with",
+ HorizontalOptions = LayoutOptions.Center
+ },
+ new Label
+ {
+ Text = "the HorizontalOptions property.",
+ HorizontalOptions = LayoutOptions.End
+ },
+ new Label
+ {
+ Text = "An Expand option allows one or more children " +
+ "to occupy the an area within the remaining " +
+ "space of the StackLayout after it's been sized " +
+ "to the height of its parent.",
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ HorizontalOptions = LayoutOptions.End
+ },
+ new StackLayout
+ {
+ Spacing = 0,
+ Orientation = StackOrientation.Horizontal,
+ Children =
+ {
+ new Label
+ {
+ Text = "Stacking",
+ },
+ new Label
+ {
+ Text = "can also be",
+ HorizontalOptions = LayoutOptions.CenterAndExpand
+ },
+ new Label
+ {
+ Text = "horizontal.",
+ },
+ }
+ }
+ }
+};
+]]></code>
+ </example>
+ <para>
+ <img href="StackLayout.TripleScreenShot.png" />
+ </para>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.StackLayout" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Orientation</term>
+ <description>
+ <para>
+ <c>Horizontal</c> or <c>Vertical</c>. The default is <c>Vertical</c>.</para>
+ </description>
+ </item>
+ <item>
+ <term>Spacing</term>
+ <description>
+ <para>An integer or decimal.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public StackLayout ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the StackLayout class.</summary>
+ <remarks>
+ <para>
+ The following example shows the initialization of a new StackLayout and setting its orientation and children.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+var stackLayout = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ firstChild,
+ secondChild,
+ thirdChild
+ }
+};
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="InvalidateMeasure">
+ <MemberSignature Language="C#" Value="protected override void InvalidateMeasure ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void InvalidateMeasure() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invalidates the layout.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutChildren">
+ <MemberSignature Language="C#" Value="protected override void LayoutChildren (double x, double y, double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void LayoutChildren(float64 x, float64 y, float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">A value representing the x coordinate of the child region bounding box.</param>
+ <param name="y">A value representing the y coordinate of the child region bounding box.</param>
+ <param name="width">A value representing the width of the child region bounding box.</param>
+ <param name="height">A value representing the height of the child region bounding box.</param>
+ <summary>Positions and sizes the children of a StackLayout.</summary>
+ <remarks>Implementors wishing to change the default behavior of a StackLayout should override this method. It is suggested to still call the base method and modify its calculated results.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeRequest">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance valuetype Xamarin.Forms.SizeRequest OnSizeRequest(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use OnMeasure")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">The available width for the StackLayout to use.</param>
+ <param name="heightConstraint">The available height for the StackLayout to use.</param>
+ <summary>This method is called during the measure pass of a layout cycle to get the desired size of the StackLayout.</summary>
+ <returns>A <see cref="T:Xamarin.Forms.SizeRequest" /> which contains the desired size of the StackLayout.</returns>
+ <remarks>The results of this method will be a sum of all the desired sizes of its children along the orientation axis, and the maximum along the non-orientation axis.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Orientation">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.StackOrientation Orientation { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.StackOrientation Orientation" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.StackOrientation</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the value which indicates the direction which child elements are positioned.</summary>
+ <value>A <see cref="T:Xamarin.Forms.StackOrientation" /> which indicates the direction children layouts flow. The default value is Vertical.</value>
+ <remarks>Setting the Orientation of a StackLayout triggers a layout cycle if the stack is already inside of a parent layout. To prevent wasted layout cycles, set the orientation prior to adding the StackLayout to a parent.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OrientationProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty OrientationProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty OrientationProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Orientation bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Spacing">
+ <MemberSignature Language="C#" Value="public double Spacing { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Spacing" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value which indicates the amount of space between each child element.</summary>
+ <value>A value in device pixels which indicates the amount of space between each element. The default value is 6.0.</value>
+ <remarks>
+ <para>
+ Setting this value triggers a layout cycle if the StackLayout is already in a parent Layout.
+ </para>
+ <para>
+ The following example sets the Spacing on construction of a StackLayout.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+var stackLayout = new StackLayout {
+ Spacing = 10
+};
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SpacingProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty SpacingProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty SpacingProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.3.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Spacing bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/StackOrientation.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/StackOrientation.xml
new file mode 100644
index 00000000..f8d6ee29
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/StackOrientation.xml
@@ -0,0 +1,64 @@
+<Type Name="StackOrientation" FullName="Xamarin.Forms.StackOrientation">
+ <TypeSignature Language="C#" Value="public enum StackOrientation" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed StackOrientation extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>The orientations the a StackLayout can have.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Horizontal">
+ <MemberSignature Language="C#" Value="Horizontal" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.StackOrientation Horizontal = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.StackOrientation</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>StackLayout should be horizontally oriented.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Vertical">
+ <MemberSignature Language="C#" Value="Vertical" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.StackOrientation Vertical = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.StackOrientation</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>StackLayout should be vertically oriented.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Stepper.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Stepper.xml
new file mode 100644
index 00000000..2aae02bb
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Stepper.xml
@@ -0,0 +1,371 @@
+<Type Name="Stepper" FullName="Xamarin.Forms.Stepper">
+ <TypeSignature Language="C#" Value="public class Stepper : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Stepper extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._StepperRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.View" /> control that inputs a discrete value, constrained to a range.</summary>
+ <remarks>
+ <para>The following example shows a basic use.</para>
+ <example>
+ <code lang="C#"><![CDATA[using System;
+ using System;
+ using Xamarin.Forms;
+
+ namespace FormsGallery
+ {
+ class StepperDemoPage : ContentPage
+ {
+ Label label;
+
+ public StepperDemoPage()
+ {
+ Label header = new Label
+ {
+ Text = "Stepper",
+ FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ Stepper stepper = new Stepper
+ {
+ Value = 5,
+ Minimum = 0,
+ Maximum = 10,
+ Increment = 0.1,
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+ stepper.ValueChanged += OnStepperValueChanged;
+
+ label = new Label
+ {
+ Text = String.Format("Stepper value is {0:F1}", stepper.Value),
+ FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+
+ // Accomodate iPhone status bar.
+ this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
+
+ // Build the page.
+ this.Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ stepper,
+ label
+ }
+ };
+ }
+
+ void OnStepperValueChanged(object sender, ValueChangedEventArgs e)
+ {
+ label.Text = String.Format("Stepper value is {0:F1}", e.NewValue);
+ }
+ }
+ }]]></code>
+ </example>
+ <para>
+ <img href="Stepper.TripleScreenShot.png" />
+ </para>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.Stepper" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Increment</term>
+ <description>
+ <para>An integer or decimal literal.</para>
+ </description>
+ </item>
+ <item>
+ <term>Maximum</term>
+ <description>
+ <para>An integer or decimal literal.</para>
+ </description>
+ </item>
+ <item>
+ <term>Minimum</term>
+ <description>
+ <para>An integer or decimal literal. If this value is nonnegative, it must appear lexically below <c>Maximum</c>, so that validation can succeed.</para>
+ </description>
+ </item>
+ <item>
+ <term>Value</term>
+ <description>
+ <para>An integer or decimal literal that represents a number that is in the range [<c>Minimum</c>,<c>Maximum</c>].</para>
+ </description>
+ </item>
+ <item>
+ <term>ValueChanged</term>
+ <description>The name of an event handler. Note that this tag must appear below <c>Value</c>.</description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Stepper ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the Stepper class.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Stepper (double min, double max, double val, double increment);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 min, float64 max, float64 val, float64 increment) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="min" Type="System.Double" />
+ <Parameter Name="max" Type="System.Double" />
+ <Parameter Name="val" Type="System.Double" />
+ <Parameter Name="increment" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="min">The minimum selectable value.</param>
+ <param name="max">The maximum selectable value.</param>
+ <param name="val">The current selected value.</param>
+ <param name="increment">The increment by which Value is increased or decreased.</param>
+ <summary>Initializes a new instance of the Stepper class.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Increment">
+ <MemberSignature Language="C#" Value="public double Increment { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Increment" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the increment by which Value is increased or decreased. This is a bindable property.</summary>
+ <value>A double.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IncrementProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IncrementProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IncrementProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Increment bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Maximum">
+ <MemberSignature Language="C#" Value="public double Maximum { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Maximum" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the maximum selectable value. This is a bindable property.</summary>
+ <value>A double.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MaximumProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty MaximumProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty MaximumProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Maximum bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Minimum">
+ <MemberSignature Language="C#" Value="public double Minimum { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Minimum" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the minimum selectabel value. This is a bindable property.</summary>
+ <value>A double.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MinimumProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty MinimumProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty MinimumProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Minimum bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Value">
+ <MemberSignature Language="C#" Value="public double Value { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Value" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the current value. This is a bindable property.</summary>
+ <value>A double.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ValueChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ValueChangedEventArgs&gt; ValueChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ValueChangedEventArgs&gt; ValueChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ValueChangedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Raised when the <see cref="P:Xamarin.Forms.Stepper.Value" /> property changes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ValueProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ValueProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ValueProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Value bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/StreamImageSource.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/StreamImageSource.xml
new file mode 100644
index 00000000..1e173b75
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/StreamImageSource.xml
@@ -0,0 +1,114 @@
+<Type Name="StreamImageSource" FullName="Xamarin.Forms.StreamImageSource">
+ <TypeSignature Language="C#" Value="public class StreamImageSource : Xamarin.Forms.ImageSource" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit StreamImageSource extends Xamarin.Forms.ImageSource" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.ImageSource</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>
+ <see cref="T:Xamarin.Forms.ImageSource" /> that loads an image from a <see cref="T:System.IO.Stream" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public StreamImageSource ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.StreamImageSource" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnPropertyChanged">
+ <MemberSignature Language="C#" Value="protected override void OnPropertyChanged (string propertyName);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnPropertyChanged(string propertyName) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">To be added.</param>
+ <summary>Method that is called when the property that is specified by <paramref name="propertyName" /> is changed..</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Stream">
+ <MemberSignature Language="C#" Value="public virtual Func&lt;System.Threading.CancellationToken,System.Threading.Tasks.Task&lt;System.IO.Stream&gt;&gt; Stream { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Func`2&lt;valuetype System.Threading.CancellationToken, class System.Threading.Tasks.Task`1&lt;class System.IO.Stream&gt;&gt; Stream" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Func&lt;System.Threading.CancellationToken,System.Threading.Tasks.Task&lt;System.IO.Stream&gt;&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the delegate responsible for returning a <see cref="T:System.IO.Stream" /> for the Image.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="StreamProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty StreamProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty StreamProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.StreamImageSource.Stream" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Style.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Style.xml
new file mode 100644
index 00000000..92982f2c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Style.xml
@@ -0,0 +1,259 @@
+<Type Name="Style" FullName="Xamarin.Forms.Style">
+ <TypeSignature Language="C#" Value="public sealed class Style" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit Style extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Setters")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Class that contains triggers, setters, and behaviors that completely or partially define the appearance and behavior of a class of visual elements.</summary>
+ <remarks>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.Style" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>BasedOn</term>
+ <description>
+ <para>A <c>StaticResource</c> markup extension that names the style on which this style is based.</para>
+ </description>
+ </item>
+ <item>
+ <term>BaseResourceKey</term>
+ <description>
+ <para>A resource dictionary key that names a dynamic base style.</para>
+ </description>
+ </item>
+ <item>
+ <term>Behaviors</term>
+ <description>
+ <para>Markup for the behaviors that are associated with the style.</para>
+ </description>
+ </item>
+ <item>
+ <term>Setters</term>
+ <description>
+ <para>A list of setters containing <c>Property</c> and <c>Value</c> elements or attributes.</para>
+ </description>
+ </item>
+ <item>
+ <term>TargetType</term>
+ <description>
+ <para>The name of the type that the style is intended for.</para>
+ </description>
+ </item>
+ <item>
+ <term>Triggers</term>
+ <description>
+ <para>A list of triggers.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Style (Type targetType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Type targetType) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="targetType" Type="System.Type">
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.TypeTypeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Parameter>
+ </Parameters>
+ <Docs>
+ <param name="targetType">To be added.</param>
+ <summary>Intitializes a new <see cref="T:Xamarin.Forms.Style" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ApplyToDerivedTypes">
+ <MemberSignature Language="C#" Value="public bool ApplyToDerivedTypes { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool ApplyToDerivedTypes" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BasedOn">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Style BasedOn { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Style BasedOn" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Style</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The <see cref="T:Xamarin.Forms.Style" /> on which this <see cref="T:Xamarin.Forms.Style" /> is based.</summary>
+ <value>To be added.</value>
+ <remarks>The <see cref="T:Xamarin.Forms.Style" /> supports a mechanism in XAML that is similar to inheritance in C#.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BaseResourceKey">
+ <MemberSignature Language="C#" Value="public string BaseResourceKey { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string BaseResourceKey" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the key that identifies the <see cref="T:Xamarin.Forms.Style" /> on which this <see cref="T:Xamarin.Forms.Style" /> is based.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Behaviors">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.Behavior&gt; Behaviors { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Behavior&gt; Behaviors" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.Behavior&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the list of <see cref="T:Xamarin.Forms.Behavior" /> objects that belong to this <see cref="T:Xamarin.Forms.Style" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanCascade">
+ <MemberSignature Language="C#" Value="public bool CanCascade { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool CanCascade" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Class">
+ <MemberSignature Language="C#" Value="public string Class { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Class" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Setters">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt; Setters { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Setter&gt; Setters" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the list of <see cref="T:Xamarin.Forms.Setter" /> objects that belong to this <see cref="T:Xamarin.Forms.Style" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TargetType">
+ <MemberSignature Language="C#" Value="public Type TargetType { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Type TargetType" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Type</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the type of object that this style can describe. See Remarks.</summary>
+ <value>To be added.</value>
+ <remarks>
+ <p>Developers should be aware that implicit styles are only applied to the specific type that is described by <see cref="P:Xamarin.Forms.Style.TargetType" />, and not to types that inherit from it.</p>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Triggers">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.TriggerBase&gt; Triggers { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.TriggerBase&gt; Triggers" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.TriggerBase&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the list of <see cref="T:Xamarin.Forms.Trigger" /> objects that belong to this <see cref="T:Xamarin.Forms.Style" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Switch.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Switch.xml
new file mode 100644
index 00000000..71bd528d
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Switch.xml
@@ -0,0 +1,193 @@
+<Type Name="Switch" FullName="Xamarin.Forms.Switch">
+ <TypeSignature Language="C#" Value="public class Switch : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Switch extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._SwitchRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.View" /> control that provides a toggled value.</summary>
+ <remarks>
+ <para>The following example describes a basic use.</para>
+ <example>
+ <code lang="C#"><![CDATA[using System;
+using Xamarin.Forms;
+
+namespace FormsGallery
+{
+ class SwitchDemoPage : ContentPage
+ {
+ Label label;
+
+ public SwitchDemoPage()
+ {
+ Label header = new Label
+ {
+ Text = "Switch",
+ FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ Switch switcher = new Switch
+ {
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+ switcher.Toggled += switcher_Toggled;
+
+ label = new Label
+ {
+ Text = "Switch is now False",
+ FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.CenterAndExpand
+ };
+
+ // Accomodate iPhone status bar.
+ this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
+
+ // Build the page.
+ this.Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ switcher,
+ label
+ }
+ };
+ }
+
+ void switcher_Toggled(object sender, ToggledEventArgs e)
+ {
+ label.Text = String.Format("Switch is now {0}", e.Value);
+ }
+ }
+}]]></code>
+ </example>
+ <para>
+ <img href="Switch.TripleScreenShot.png" />
+ </para>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.Switch" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>IsToggled</term>
+ <description>
+ <para>
+ <c>true</c> or <c>false</c>, to indicate whether the switch has been toggled.</para>
+ </description>
+ </item>
+ <item>
+ <term>Toggled</term>
+ <description>
+ <para>The name of an event handler. Note that this tag must appear below <c>IsToggled</c>.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Switch ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Switch" /> element with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsToggled">
+ <MemberSignature Language="C#" Value="public bool IsToggled { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsToggled" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a Boolean value that indicates whether this <see cref="T:Xamarin.Forms.Switch" /> element is toggled.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsToggledProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsToggledProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsToggledProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.Switch.IsToggled" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Toggled">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ToggledEventArgs&gt; Toggled;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ToggledEventArgs&gt; Toggled" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ToggledEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when this <see cref="T:Xamarin.Forms.Switch" /> is toggled.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/SwitchCell.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/SwitchCell.xml
new file mode 100644
index 00000000..3bcf3764
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/SwitchCell.xml
@@ -0,0 +1,230 @@
+<Type Name="SwitchCell" FullName="Xamarin.Forms.SwitchCell">
+ <TypeSignature Language="C#" Value="public class SwitchCell : Xamarin.Forms.Cell" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit SwitchCell extends Xamarin.Forms.Cell" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Cell</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.Cell" /> with a label and an on/off switch.</summary>
+ <remarks>
+ <para>The following example shows a basic use.</para>
+ <example>
+ <code lang="C#"><![CDATA[using System;
+using Xamarin.Forms;
+
+namespace FormsGallery
+{
+ class SwitchCellDemoPage : ContentPage
+ {
+ public SwitchCellDemoPage()
+ {
+ Label header = new Label
+ {
+ Text = "SwitchCell",
+ FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ TableView tableView = new TableView
+ {
+ Intent = TableIntent.Form,
+ Root = new TableRoot
+ {
+ new TableSection
+ {
+ new SwitchCell
+ {
+ Text = "SwitchCell:"
+ }
+ }
+ }
+ };
+
+ // Accomodate iPhone status bar.
+ this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
+
+ // Build the page.
+ this.Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ tableView
+ }
+ };
+ }
+ }
+}]]></code>
+ </example>
+ <para>
+ <img href="SwitchCell.TripleScreenShot.png" />
+ </para>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.SwitchCell" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>On</term>
+ <description>
+ <para>
+ <c>true</c> or <c>false</c>, to indicate whether the switch cell is in the "on" position.</para>
+ </description>
+ </item>
+ <item>
+ <term>OnChanged</term>
+ <description>
+ <para>The name of an event handler. Note that this tag must appear below <c>On</c>.</para>
+ </description>
+ </item>
+ <item>
+ <term>Text</term>
+ <description>
+ <para>Text that represents the title of the switch cell.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public SwitchCell ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the SwitchCell class.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="On">
+ <MemberSignature Language="C#" Value="public bool On { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool On" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the state of the switch. This is a bindable property.</summary>
+ <value>Default is <see langword="false" />.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.ToggledEventArgs&gt; OnChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.ToggledEventArgs&gt; OnChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.ToggledEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Triggered when the switch has changed value.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty OnProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty OnProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.SwitchCell.On" /> bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Text">
+ <MemberSignature Language="C#" Value="public string Text { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Text" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the text displayed next to the switch. This is a bindable property.</summary>
+ <value>
+ </value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TextProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TextProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Text bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TabbedPage.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TabbedPage.xml
new file mode 100644
index 00000000..4d2945ca
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TabbedPage.xml
@@ -0,0 +1,211 @@
+<Type Name="TabbedPage" FullName="Xamarin.Forms.TabbedPage">
+ <TypeSignature Language="C#" Value="public class TabbedPage : Xamarin.Forms.MultiPage&lt;Xamarin.Forms.Page&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit TabbedPage extends Xamarin.Forms.MultiPage`1&lt;class Xamarin.Forms.Page&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.MultiPage&lt;Xamarin.Forms.Page&gt;</BaseTypeName>
+ <BaseTypeArguments>
+ <BaseTypeArgument TypeParamName="T">Xamarin.Forms.Page</BaseTypeArgument>
+ </BaseTypeArguments>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._TabbedPageRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>
+ <see cref="T:Xamarin.Forms.MultiPage`1" /> that displays an array of tabs across the top of the screen, each of which loads content onto the screen.</summary>
+ <remarks>
+ <para>The user interface of a tabbed page consists of a list of tabs and a larger detail area. On iOS, the list of tabs appears at the bottom of the screen, and the detail area is above. On Android and Windows phones, the tabs appear across the top of the screen. The user can scroll the collection of tabs that are across the top of the screen if that collection is too large to fit on one screen.</para>
+ <para>App developers can create tabbed pages in either of two ways. First, application developers can assign a list of objects of a single class, or its subclasses, to the <see cref="P:Xamarin.Forms.TabbedPage.ItemsSource" /> property and assign a <see cref="T:Xamarin.Forms.DataTemplate" /> to the <see cref="P:Xamarin.Forms.MultiPage{T}.ItemTemplate" /> property to return pages for objects of the least derived type. Second, app developers can add a succession of <see cref="T:Xamarin.Forms.Page" /> objects to the <see cref="P:Xamarin.Forms.MultiPage{T}.Children" /> property. Both methods are shown in the code examples below.</para>
+ <example>
+ <para>The following example code, adapted for brevity from the FormsGallery sample that can be found on the <format type="text/html"><a href="http://developer.xamarin.com/samples/tag/Xamarin.Forms/" target="_blank">Sample Applications</a></format> page, shows how to display data of a specific type by assigning a <see cref="T:Xamarin.Forms.DataTemplate" /> to the <see cref="P:Xamarin.Forms.MultiPage{T}.ItemTemplate" /> property. Note how <c>NamedColorPage</c> gets its color by binding its <see cref="F:Xamarin.Forms.BoxView.ColorProperty" /> field.</para>
+ <code lang="C#"><![CDATA[
+using System;
+using Xamarin.Forms;
+
+namespace MinimalTabbed
+{
+ class TabbedPageDemoPage : TabbedPage
+ {
+ public TabbedPageDemoPage ()
+ {
+ this.Title = "TabbedPage";
+
+ this.ItemsSource = new NamedColor[] {
+ new NamedColor ("Red", Color.Red),
+ new NamedColor ("Yellow", Color.Yellow),
+ new NamedColor ("Green", Color.Green),
+ new NamedColor ("Aqua", Color.Aqua),
+ new NamedColor ("Blue", Color.Blue),
+ new NamedColor ("Purple", Color.Purple)
+ };
+
+ this.ItemTemplate = new DataTemplate (() => {
+ return new NamedColorPage ();
+ });
+ }
+ }
+
+ // Data type:
+ class NamedColor
+ {
+ public NamedColor (string name, Color color)
+ {
+ this.Name = name;
+ this.Color = color;
+ }
+
+ public string Name { private set; get; }
+
+ public Color Color { private set; get; }
+
+ public override string ToString ()
+ {
+ return Name;
+ }
+ }
+
+ // Format page
+ class NamedColorPage : ContentPage
+ {
+ public NamedColorPage ()
+ {
+ // This binding is necessary to label the tabs in
+ // the TabbedPage.
+ this.SetBinding (ContentPage.TitleProperty, "Name");
+ // BoxView to show the color.
+ BoxView boxView = new BoxView {
+ WidthRequest = 100,
+ HeightRequest = 100,
+ HorizontalOptions = LayoutOptions.Center
+ };
+ boxView.SetBinding (BoxView.ColorProperty, "Color");
+
+ // Build the page
+ this.Content = boxView;
+ }
+ }
+}
+
+
+]]></code>
+ </example>
+ <example>
+ <para>The example below creates a tabbed view with two <see cref="T:Xamarin.Forms.ContentPage" /> instances.</para>
+ <code lang="C#"><![CDATA[
+class TabbedPageDemoPage2 : TabbedPage
+{
+ public TabbedPageDemoPage2 ()
+ {
+ this.Title = "TabbedPage";
+ this.Children.Add (new ContentPage
+ {
+ Title = "Blue",
+ Content = new BoxView
+ {
+ Color = Color.Blue,
+ HeightRequest = 100f,
+ VerticalOptions = LayoutOptions.Center
+ },
+ }
+ );
+ this.Children.Add (new ContentPage {
+ Title = "Blue and Red",
+ Content = new StackLayout {
+ Children = {
+ new BoxView { Color = Color.Blue },
+ new BoxView { Color = Color.Red}
+ }
+ }
+ });
+ }
+}
+ ]]></code>
+ </example>
+ <para>
+ <img href="TabbedPage.TripleScreenShot.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TabbedPage ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.TabbedPage" /> element with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CreateDefault">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.Page CreateDefault (object item);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance class Xamarin.Forms.Page CreateDefault(object item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Page</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="item">An object for which to create a default page.</param>
+ <summary>Creates a default page, suitable for display in <c>this</c><see cref="T:Xamarin.Forms.TabbedPage" /> page, for an object.</summary>
+ <returns>A page that is titled with the string value of <paramref name="item" />.</returns>
+ <remarks>This returns a new <see cref="T:Xamarin.Forms.Page" /> object that has its <see cref="P:Xamarin.Forms.Page.Title" /> property set to the value of <see cref="M:Object.ToString" /> when called on <paramref name="item" />.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnParentSet">
+ <MemberSignature Language="C#" Value="protected override void OnParentSet ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnParentSet() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Called when the parent is set.</summary>
+ <remarks>This method iterates up the <see cref="P:Xamarin.Forms.Page.Parent" /> hierarchy and writes a message to the debug listeners if it detects a <see cref="T:Xamarin.Forms.NavigationPage" />. Application developers are advised that adding a <see cref="T:Xamarin.Forms.TabbedPage" /> to a <see cref="T:Xamarin.Forms.NavigationPage" /> may produce undesirable results.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TableIntent.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TableIntent.xml
new file mode 100644
index 00000000..a4a106d4
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TableIntent.xml
@@ -0,0 +1,103 @@
+<Type Name="TableIntent" FullName="Xamarin.Forms.TableIntent">
+ <TypeSignature Language="C#" Value="public enum TableIntent" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed TableIntent extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>TableIntent provides hints to the renderer about how a table will be used.</summary>
+ <remarks>Using table intents will not effect the behavior of a table, and will only modify their visual appearance on screen, depending on the platform. Not all intents are unique on all platforms, however it is advisable to pick the intent which most closely represents your use case.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Data">
+ <MemberSignature Language="C#" Value="Data" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TableIntent Data = int32(3)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TableIntent</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A table intended to contain an arbitrary number of similar data entries.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Form">
+ <MemberSignature Language="C#" Value="Form" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TableIntent Form = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TableIntent</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A table which is used to contain information that would normally be contained in a form.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Menu">
+ <MemberSignature Language="C#" Value="Menu" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TableIntent Menu = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TableIntent</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A table intended to be used as a menu for selections.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Settings">
+ <MemberSignature Language="C#" Value="Settings" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TableIntent Settings = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TableIntent</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A table containing a set of switches, toggles, or other modifiable configuration settings.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TableRoot.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TableRoot.xml
new file mode 100644
index 00000000..07b326d4
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TableRoot.xml
@@ -0,0 +1,68 @@
+<Type Name="TableRoot" FullName="Xamarin.Forms.TableRoot">
+ <TypeSignature Language="C#" Value="public sealed class TableRoot : Xamarin.Forms.TableSectionBase&lt;Xamarin.Forms.TableSection&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit TableRoot extends Xamarin.Forms.TableSectionBase`1&lt;class Xamarin.Forms.TableSection&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TableSectionBase&lt;Xamarin.Forms.TableSection&gt;</BaseTypeName>
+ <BaseTypeArguments>
+ <BaseTypeArgument TypeParamName="T">Xamarin.Forms.TableSection</BaseTypeArgument>
+ </BaseTypeArguments>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TableSection" /> that contains either a table section or the entire table.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TableRoot ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Constructs and initializes a new instance of the <see cref="T:Xamarin.Forms.TableRoot" /> class.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TableRoot (string title);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string title) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="title" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="title">The title of the table.</param>
+ <summary>Constructs and initializes a new instance of the <see cref="T:Xamarin.Forms.TableRoot" /> class with a title.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TableSection.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TableSection.xml
new file mode 100644
index 00000000..7faeb599
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TableSection.xml
@@ -0,0 +1,68 @@
+<Type Name="TableSection" FullName="Xamarin.Forms.TableSection">
+ <TypeSignature Language="C#" Value="public sealed class TableSection : Xamarin.Forms.TableSectionBase&lt;Xamarin.Forms.Cell&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit TableSection extends Xamarin.Forms.TableSectionBase`1&lt;class Xamarin.Forms.Cell&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TableSectionBase&lt;Xamarin.Forms.Cell&gt;</BaseTypeName>
+ <BaseTypeArguments>
+ <BaseTypeArgument TypeParamName="T">Xamarin.Forms.Cell</BaseTypeArgument>
+ </BaseTypeArguments>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A logical and visible section of a <see cref="T:Xamarin.Forms.TableView" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TableSection ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.TableSection" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TableSection (string title);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string title) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="title" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="title">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.TableSection" /> with the title <paramref name="title" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TableSectionBase.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TableSectionBase.xml
new file mode 100644
index 00000000..8bcf927c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TableSectionBase.xml
@@ -0,0 +1,125 @@
+<Type Name="TableSectionBase" FullName="Xamarin.Forms.TableSectionBase">
+ <TypeSignature Language="C#" Value="public abstract class TableSectionBase : Xamarin.Forms.BindableObject" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit TableSectionBase extends Xamarin.Forms.BindableObject" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Abstract base class defining a table section.</summary>
+ <remarks>
+ <para>
+ <img href="TableSectionBase.Hierarchy.png" />
+ </para>
+ <para>XAML for Xamarin.Forms supports the following property for the <see cref="T:Xamarin.Forms.TableSectionBase" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>Title</term>
+ <description>
+ <para>A title for the section.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected TableSectionBase ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.TableSectionBase" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected TableSectionBase (string title);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor(string title) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="title" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="title">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.TableSectionBase" /> object with the specified <paramref name="title" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Title">
+ <MemberSignature Language="C#" Value="public string Title { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Title" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the title.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TitleProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TitleProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TitleProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.TableSectionBase.Title" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TableSectionBase`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TableSectionBase`1.xml
new file mode 100644
index 00000000..d974e629
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TableSectionBase`1.xml
@@ -0,0 +1,504 @@
+<Type Name="TableSectionBase&lt;T&gt;" FullName="Xamarin.Forms.TableSectionBase&lt;T&gt;">
+ <TypeSignature Language="C#" Value="public abstract class TableSectionBase&lt;T&gt; : Xamarin.Forms.TableSectionBase, System.Collections.Generic.ICollection&lt;T&gt;, System.Collections.Generic.IEnumerable&lt;T&gt;, System.Collections.Generic.IList&lt;T&gt;, System.Collections.Specialized.INotifyCollectionChanged where T : BindableObject" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit TableSectionBase`1&lt;(class Xamarin.Forms.BindableObject) T&gt; extends Xamarin.Forms.TableSectionBase implements class System.Collections.Generic.ICollection`1&lt;!T&gt;, class System.Collections.Generic.IEnumerable`1&lt;!T&gt;, class System.Collections.Generic.IList`1&lt;!T&gt;, class System.Collections.IEnumerable, class System.Collections.Specialized.INotifyCollectionChanged" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="T">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TableSectionBase</BaseTypeName>
+ <BaseTypeArguments>
+ <BaseTypeArgument TypeParamName="!0">T</BaseTypeArgument>
+ </BaseTypeArguments>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.ICollection&lt;T&gt;</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.IEnumerable&lt;T&gt;</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.IList&lt;T&gt;</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>System.Collections.Specialized.INotifyCollectionChanged</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <summary>
+ Table section that contains instances of type T that are rendered by Xamarin.Forms.</summary>
+ <remarks>
+ <para>
+ Sections are used to group cells in the screen and they are the
+ only valid direct child of the <see cref="T:Xamarin.Forms.TableRoot" />. Sections can contain
+ any of the standard <see cref="T:Xamarin.Forms.Cell" />s, including new <see cref="T:Xamarin.Forms.TableRoot" />s.
+ </para>
+ <para>
+ <see cref="T:Xamarin.Forms.TableRoot" />s embedded in a section are used to navigate to a new
+ deeper level.
+ </para>
+ <para>
+ You can assign a header and a footer either as strings (Header and Footer)
+ properties, or as Views to be shown (HeaderView and FooterView). Internally
+ this uses the same storage, so you can only show one or the other.
+ </para>
+ <para>Subtypes of <see cref="T:Xamarin.Forms.TableSectionBase`1" /> are <see cref="T:Xamarin.Forms.TableSection" /> and <see cref="T:Xamarin.Forms.TableRoot" />, as shown in the following diagram:</para>
+ <para>
+ <img href="TableSection.Hierarchy.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected TableSectionBase ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>
+ Constructs a new <see cref="T:Xamarin.Forms.TableSection`1" /> instance with an empty title.
+ </summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected TableSectionBase (string title);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor(string title) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="title" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="title">To be added.</param>
+ <summary>
+ Constructs a new <see cref="T:Xamarin.Forms.TableSection`1" /> instance with the specified <paramref name="title" />.
+ </summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (System.Collections.Generic.IEnumerable&lt;T&gt; items);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void Add(class System.Collections.Generic.IEnumerable`1&lt;!T&gt; items) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="items" Type="System.Collections.Generic.IEnumerable&lt;T&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="items">The items to add.</param>
+ <summary>Adds a list of items to this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (T item);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Add(!T item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="item">The item to add.</param>
+ <summary>Adds an item to this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Clear">
+ <MemberSignature Language="C#" Value="public void Clear ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Clear() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Removes all items in this <see cref="T:Xamarin.Forms.TableSectionBase`1" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CollectionChanged">
+ <MemberSignature Language="C#" Value="public event System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Specialized.NotifyCollectionChangedEventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when one or more items is added to or removed from this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Contains">
+ <MemberSignature Language="C#" Value="public bool Contains (T item);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance bool Contains(!T item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="item">The object for which to determine whether or not this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object has a reference.</param>
+ <summary>Returns a Boolean value that indicates whether or not this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> has a reference to a particular object.</summary>
+ <returns>
+ <see langword="true" /> if this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object contains a reference to <paramref name="item" />. Otherwise, <see langword="false" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CopyTo">
+ <MemberSignature Language="C#" Value="public void CopyTo (T[] array, int arrayIndex);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void CopyTo(!T[] array, int32 arrayIndex) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="array" Type="T[]" />
+ <Parameter Name="arrayIndex" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="array">To be added.</param>
+ <param name="arrayIndex">To be added.</param>
+ <summary>Copies the elements of the current collection to an <see cref="T:System.Array" />, starting at the specified index.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Count">
+ <MemberSignature Language="C#" Value="public int Count { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 Count" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the number of items in this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object.</summary>
+ <value>The number of items in this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetEnumerator">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IEnumerator&lt;T&gt; GetEnumerator ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Collections.Generic.IEnumerator`1&lt;!T&gt; GetEnumerator() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IEnumerator&lt;T&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns an enumerator that iterates through the items in this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IndexOf">
+ <MemberSignature Language="C#" Value="public int IndexOf (T item);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance int32 IndexOf(!T item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="item">The instance for which to find its index.</param>
+ <summary>Returns the index of the first occurrence of <paramref name="item" /> in this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object.</summary>
+ <returns>The index of the first occurrence of <paramref name="item" /> in this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Insert">
+ <MemberSignature Language="C#" Value="public void Insert (int index, T item);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void Insert(int32 index, !T item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="index" Type="System.Int32" />
+ <Parameter Name="item" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="index">The position at which to insert <paramref name="item" />.</param>
+ <param name="item">The item to insert.</param>
+ <summary>Inserts an item into this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object at the specified position.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Item">
+ <MemberSignature Language="C#" Value="public T this[int index] { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance !T Item(int32)" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="index" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="index">The location of the item to return.</param>
+ <summary>Returns the item that is stored at the location in this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object that is specified by <paramref name="index" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBindingContextChanged">
+ <MemberSignature Language="C#" Value="protected override void OnBindingContextChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnBindingContextChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Calls the <see cref="M:Xamarin.Forms.BindableObject.SetInheritedBindingContext" /> method, passing the new binding context, on each of the items in this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Remove">
+ <MemberSignature Language="C#" Value="public bool Remove (T item);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance bool Remove(!T item) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="item" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="item">To be added.</param>
+ <summary>Removes a specified item from this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object.</summary>
+ <returns>
+ <see langword="true" />, if item was removed from the current collection; <see langword="false" /> if item was not found in the current collection..</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RemoveAt">
+ <MemberSignature Language="C#" Value="public void RemoveAt (int index);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void RemoveAt(int32 index) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="index" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="index">The position in this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object from which to remove an item.</param>
+ <summary>Removes a specified item from this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object at the position that is specified by <paramref name="index" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="System.Collections.Generic.ICollection&lt;T&gt;.IsReadOnly">
+ <MemberSignature Language="C#" Value="bool System.Collections.Generic.ICollection&lt;T&gt;.IsReadOnly { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool System.Collections.Generic.ICollection&lt;T&gt;.IsReadOnly" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Returns <see langword="false" />; The collection of objects in this can be changed.</summary>
+ <value>
+ <see langword="false" />; The collection of objects in this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object can be changed.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="System.Collections.IEnumerable.GetEnumerator">
+ <MemberSignature Language="C#" Value="System.Collections.IEnumerator IEnumerable.GetEnumerator ();" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance class System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.IEnumerator</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns an enumerator that iterates through the collection of objects in this <see cref="T:Xamarin.Forms.TableSectionBase`1" /> object.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TableView.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TableView.xml
new file mode 100644
index 00000000..96e0db49
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TableView.xml
@@ -0,0 +1,353 @@
+<Type Name="TableView" FullName="Xamarin.Forms.TableView">
+ <TypeSignature Language="C#" Value="public class TableView : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit TableView extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Root")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._TableViewRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.View" /> that holds rows of <see cref="T:Xamarin.Forms.Cell" /> elements.</summary>
+ <remarks>
+ <para>A <see cref="T:Xamarin.Forms.TableView" /> has a <see cref="T:Xamarin.Forms.TableRoot" /> as its <see cref="P:Xamarin.Forms.TableView.Root" /> property. The <see cref="T:Xamarin.Forms.TableView.TableRoot" /> is a type of <see cref="T:Xamarin.Forms.TableSection" />. </para>
+ <para>The following example shows a basic table with two sections.</para>
+ <example>
+ <code lang="C#"><![CDATA[
+public class App : Application
+{
+ public App()
+ {
+ MainPage = new ContentPage {
+ Content = new TableView {
+ Intent = TableIntent.Form,
+ Root = new TableRoot ("Table Title") {
+ new TableSection ("Section 1 Title") {
+ new TextCell {
+ Text = "TextCell Text",
+ Detail = "TextCell Detail"
+ },
+ new EntryCell {
+ Label = "EntryCell:",
+ Placeholder = "default keyboard",
+ Keyboard = Keyboard.Default
+ }
+ },
+ new TableSection ("Section 2 Title") {
+ new EntryCell {
+ Label = "Another EntryCell:",
+ Placeholder = "phone keyboard",
+ Keyboard = Keyboard.Telephone
+ },
+ new SwitchCell {
+ Text = "SwitchCell:"
+ }
+ }
+ }
+ }
+ };
+ }
+ // OnStart, OnSleep, OnResume overrides omitted...
+}
+ ]]></code>
+ </example>
+ <para>
+ <img href="TableView.TripleScreenShot.png" />
+ </para>
+ <para>XAML for Xamarin.Forms supports the following properties for the <see cref="T:Xamarin.Forms.TableView" /> class:</para>
+ <list type="table">
+ <listheader>
+ <term>Property</term>
+ <description>Value</description>
+ </listheader>
+ <item>
+ <term>HasUnevenRows</term>
+ <description>
+ <para>
+ <c>true</c> or <c>false</c>, to indicate whether rows in the table view will specify their own height.</para>
+ </description>
+ </item>
+ <item>
+ <term>Intent</term>
+ <description>
+ <para>
+ <c>Data</c>, <c>Form</c>, <c>Menu</c>, or <c>Settings</c>.</para>
+ </description>
+ </item>
+ <item>
+ <term>RowHeight</term>
+ <description>
+ <para>
+ <c>Horizontal</c> or <c>Vertical</c>, to indicate the scroll direction.</para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TableView ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new <see cref="T:Xamarin.Forms.TableView" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TableView (Xamarin.Forms.TableRoot root);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class Xamarin.Forms.TableRoot root) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="root" Type="Xamarin.Forms.TableRoot" />
+ </Parameters>
+ <Docs>
+ <param name="root">To be added.</param>
+ <summary>Initializes a new <see cref="T:Xamarin.Forms.TableView" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasUnevenRows">
+ <MemberSignature Language="C#" Value="public bool HasUnevenRows { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool HasUnevenRows" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that indicates whether the rows that are contained in this <see cref="T:Xamarin.Forms.TableView" /> can have uneven rows.</summary>
+ <value>To be added.</value>
+ <remarks>
+ <para>When the <see cref="P:Xamarin.Forms.TableView.HasUnevenRows" /> property is <see langword="true" />, application developers can set the <see cref="P:Xamarin.Forms.Cell.Height" /> properties to control the height of <see cref="T:Xamarin.Forms.Cell" /> items in the table. When the <see cref="P:Xamarin.Forms.TableView.HasUnevenRows" /> property is <see langword="true" />, the <see cref="P:Xamarin.Forms.TableView.RowHeight" /> property is ignored. When the <see cref="P:Xamarin.Forms.TableView.HasUnevenRows" /> property is <see langword="false" />, app developers can set the <see cref="P:Xamarin.Forms.TableView.RowHeight" /> property to set the height of all Cells, and their individual <see cref="P:Xamarin.Forms.Cell.Height" /> properties are ignored.</para>
+ <block subset="none" type="note"><para>Developers must specify row heights on the iOS platform, even when <see cref="P:Xamarin.Forms.TableView.HasUnevenRows" /> is <see langword="true" />.</para></block>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasUnevenRowsProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HasUnevenRowsProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HasUnevenRowsProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the HasUnevenRows property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Intent">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.TableIntent Intent { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.TableIntent Intent" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TableIntent</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the intent of the table.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBindingContextChanged">
+ <MemberSignature Language="C#" Value="protected override void OnBindingContextChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnBindingContextChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Method that is called when the binding context changes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnModelChanged">
+ <MemberSignature Language="C#" Value="protected virtual void OnModelChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnModelChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Method that is called when the model changes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeRequest">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance valuetype Xamarin.Forms.SizeRequest OnSizeRequest(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use OnMeasure")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">To be added.</param>
+ <param name="heightConstraint">To be added.</param>
+ <summary>Method that is called when a size request is made.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Root">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.TableRoot Root { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.TableRoot Root" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TableRoot</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the root of the table.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RowHeight">
+ <MemberSignature Language="C#" Value="public int RowHeight { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 RowHeight" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>An integer that describes the height of the items in the list. This is ignored if HasUnevenRows is true.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RowHeightProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty RowHeightProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty RowHeightProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the row height property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TapGestureRecognizer.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TapGestureRecognizer.xml
new file mode 100644
index 00000000..77ead9a4
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TapGestureRecognizer.xml
@@ -0,0 +1,361 @@
+<Type Name="TapGestureRecognizer" FullName="Xamarin.Forms.TapGestureRecognizer">
+ <TypeSignature Language="C#" Value="public sealed class TapGestureRecognizer : Xamarin.Forms.GestureRecognizer" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit TapGestureRecognizer extends Xamarin.Forms.GestureRecognizer" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.GestureRecognizer</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Provides tap gesture recognition and events.</summary>
+ <remarks>Can be used to recognize single and multiple tap gestures.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TapGestureRecognizer ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of a TapGestureRecognizer object.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TapGestureRecognizer (Action&lt;Xamarin.Forms.View,object&gt; tappedCallback);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Action`2&lt;class Xamarin.Forms.View, object&gt; tappedCallback) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Obsolete in 1.0.2. Use Command instead")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Parameters>
+ <Parameter Name="tappedCallback" Type="System.Action&lt;Xamarin.Forms.View,System.Object&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="tappedCallback">An action whose first argument is the View the recognizer is associated with and whose second argument is the callback parameter.</param>
+ <summary>Initializes a new instance of a TapGestureRecognizer object with a parameterized callback.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TapGestureRecognizer (Action&lt;Xamarin.Forms.View&gt; tappedCallback);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Action`1&lt;class Xamarin.Forms.View&gt; tappedCallback) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Obsolete in 1.0.2. Use Command instead")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Parameters>
+ <Parameter Name="tappedCallback" Type="System.Action&lt;Xamarin.Forms.View&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="tappedCallback">An action whose first argument is the View the recognizer is associated with.</param>
+ <summary>Initializes a new instance of a TapGestureRecognizer object with a callback.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Command">
+ <MemberSignature Language="C#" Value="public System.Windows.Input.ICommand Command { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Windows.Input.ICommand Command" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Windows.Input.ICommand</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The Command to invoke when the gesture has been triggered by the user. This is a bindable property.</summary>
+ <value>To be added.</value>
+ <remarks>The object passed to the Command will be the contents of <see cref="P:Xamarin.Forms.TapGestureRecognizer.CommandParameter" /></remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CommandParameter">
+ <MemberSignature Language="C#" Value="public object CommandParameter { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object CommandParameter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>An object to be passed to the TappedCallback. This is a bindable property.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CommandParameterProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty CommandParameterProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty CommandParameterProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the CommandParameter bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CommandProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty CommandProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty CommandProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Command bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="NumberOfTapsRequired">
+ <MemberSignature Language="C#" Value="public int NumberOfTapsRequired { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 NumberOfTapsRequired" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The number of taps required to trigger the callback. This is a bindable property.</summary>
+ <value>The number of taps to recognize. The default value is 1.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="NumberOfTapsRequiredProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty NumberOfTapsRequiredProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty NumberOfTapsRequiredProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the NumberOfTapsRequired bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Tapped">
+ <MemberSignature Language="C#" Value="public event EventHandler Tapped;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Tapped" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the user taps.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TappedCallback">
+ <MemberSignature Language="C#" Value="public Action&lt;Xamarin.Forms.View,object&gt; TappedCallback { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Action`2&lt;class Xamarin.Forms.View, object&gt; TappedCallback" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Obsolete in 1.0.2. Use Command instead")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Action&lt;Xamarin.Forms.View,System.Object&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The action to invoke when the gesture has been triggered by the user. This is a bindable property.</summary>
+ <value>An action that will be invoked.</value>
+ <remarks>The object passed to the callback will be the contents of <see cref="P:Xamarin.Forms.TapGestureRecognizer.TappedCallbackParameter" />.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TappedCallbackParameter">
+ <MemberSignature Language="C#" Value="public object TappedCallbackParameter { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object TappedCallbackParameter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Obsolete in 1.0.2. Use Command instead")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>An object to be passed to the TappedCallback. This is a bindable property.</summary>
+ <value>An object.</value>
+ <remarks>The primary use case for this property is Xaml bindings.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TappedCallbackParameterProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TappedCallbackParameterProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TappedCallbackParameterProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Obsolete in 1.0.2. Use Command instead")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the TappedCallbackParameter bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TappedCallbackProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TappedCallbackProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TappedCallbackProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Obsolete in 1.0.2. Use Command instead")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the TappedCallback bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TappedEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TappedEventArgs.xml
new file mode 100644
index 00000000..bb12cd7a
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TappedEventArgs.xml
@@ -0,0 +1,68 @@
+<Type Name="TappedEventArgs" FullName="Xamarin.Forms.TappedEventArgs">
+ <TypeSignature Language="C#" Value="public class TappedEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit TappedEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Arguments for the <see cref="T:Xamarin.Forms.TappedEvent" /> event.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TappedEventArgs (object parameter);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(object parameter) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="parameter" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="parameter">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.TappedEventArgs" /> object with the supplied parameter.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Parameter">
+ <MemberSignature Language="C#" Value="public object Parameter { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Parameter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the parameter object for this <see cref="T:Xamarin.Forms.TappedEventArgs" /> object.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TargetIdiom.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TargetIdiom.xml
new file mode 100644
index 00000000..1541f7a9
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TargetIdiom.xml
@@ -0,0 +1,104 @@
+<Type Name="TargetIdiom" FullName="Xamarin.Forms.TargetIdiom">
+ <TypeSignature Language="C#" Value="public enum TargetIdiom" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed TargetIdiom extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Indicates the type of device Forms is working on.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Desktop">
+ <MemberSignature Language="C#" Value="Desktop" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TargetIdiom Desktop = int32(3)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TargetIdiom</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that Forms is running on a UWP app on Windows 10.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Phone">
+ <MemberSignature Language="C#" Value="Phone" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TargetIdiom Phone = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TargetIdiom</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that the width of the iPhone, iPod Touch, Windows Phone, or Android device on which Forms is running is narrower than 600 dips.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Tablet">
+ <MemberSignature Language="C#" Value="Tablet" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TargetIdiom Tablet = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TargetIdiom</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that the width of the iPad, Windows 8.1, or Android device on which Forms is running is wider than 600 dips.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Unsupported">
+ <MemberSignature Language="C#" Value="Unsupported" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TargetIdiom Unsupported = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TargetIdiom</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>(Unused) Indicates that Forms is running on an unsupported device.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TargetPlatform.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TargetPlatform.xml
new file mode 100644
index 00000000..40fd72bd
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TargetPlatform.xml
@@ -0,0 +1,120 @@
+<Type Name="TargetPlatform" FullName="Xamarin.Forms.TargetPlatform">
+ <TypeSignature Language="C#" Value="public enum TargetPlatform" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed TargetPlatform extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Indicates the kind of OS Forms is currently working on.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Android">
+ <MemberSignature Language="C#" Value="Android" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TargetPlatform Android = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TargetPlatform</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that Forms is running on a Google Android OS.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="iOS">
+ <MemberSignature Language="C#" Value="iOS" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TargetPlatform iOS = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TargetPlatform</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that Forms is running on an Apple iOS OS.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Other">
+ <MemberSignature Language="C#" Value="Other" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TargetPlatform Other = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TargetPlatform</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>(Unused) Indicates that Forms is running on an undefined platform.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Windows">
+ <MemberSignature Language="C#" Value="Windows" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TargetPlatform Windows = int32(4)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TargetPlatform</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that forms is running on the Windows platform.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="WinPhone">
+ <MemberSignature Language="C#" Value="WinPhone" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TargetPlatform WinPhone = int32(3)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TargetPlatform</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that Forms is running on a Microsoft WinPhone OS.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TemplateBinding.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TemplateBinding.xml
new file mode 100644
index 00000000..f7ef08c6
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TemplateBinding.xml
@@ -0,0 +1,112 @@
+<Type Name="TemplateBinding" FullName="Xamarin.Forms.TemplateBinding">
+ <TypeSignature Language="C#" Value="public class TemplateBinding : Xamarin.Forms.BindingBase" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit TemplateBinding extends Xamarin.Forms.BindingBase" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.BindingBase</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Binds a template property to the parent of the view that owns a <see cref="T:Xamarin.Forms.ControlTemplate" />.</summary>
+ <remarks><para>Control templates provide reusable styling and functionality for common UI elements in an application. They do this by providing a common set of properties that bind to the parents of the View that owns the View to which the control template is bound.</para>
+ <example><para>Application developers can assign these properties through XAML, as in the following example: </para><code lang="XAML"><![CDATA[
+<ControlTemplate x:Key="LoginTemplate">
+ <StackLayout VerticalOptions="CenterAndExpand" Spacing="20" Padding="20">
+ <Entry Text="{TemplateBinding Username}" Placeholder="Username" />
+ <Entry Text="{TemplateBinding Password}" Placeholder="Password" />
+ <Button Command="{TemplateBinding Command}" Text="Click Here To Log In" />
+ </StackLayout>
+</ControlTemplate>]]></code>
+<para>Additionally, application developers can use the <see cref="T:Xamarin.Forms.TemplateExtensions.SetBinding" /> static method to set template bindings in code.</para></example></remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TemplateBinding ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates an empty template binding.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TemplateBinding (string path, Xamarin.Forms.BindingMode mode = Xamarin.Forms.BindingMode.Default, Xamarin.Forms.IValueConverter converter = null, object converterParameter = null, string stringFormat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string path, valuetype Xamarin.Forms.BindingMode mode, class Xamarin.Forms.IValueConverter converter, object converterParameter, string stringFormat) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="path" Type="System.String" />
+ <Parameter Name="mode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="converter" Type="Xamarin.Forms.IValueConverter" />
+ <Parameter Name="converterParameter" Type="System.Object" />
+ <Parameter Name="stringFormat" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="path">A string that identifies the property to which to bind.</param>
+ <param name="mode">The binding mode.</param>
+ <param name="converter">A type converter to use to convert strings into instances of the bound property type.</param>
+ <param name="converterParameter">A parameter to pass to the converter.</param>
+ <param name="stringFormat">A format string to use for displaying property values.</param>
+ <summary>Creates a new TemplateBinding with the specified values. Must be non-empty and non-null.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Converter">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.IValueConverter Converter { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.IValueConverter Converter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.IValueConverter</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the type converter to use to convert strings into instances of the bound property type.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConverterParameter">
+ <MemberSignature Language="C#" Value="public object ConverterParameter { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object ConverterParameter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a format string to use for displaying property values.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Path">
+ <MemberSignature Language="C#" Value="public string Path { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Path" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a string that identifies the property to which to bind.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TemplateExtensions.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TemplateExtensions.xml
new file mode 100644
index 00000000..d7095849
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TemplateExtensions.xml
@@ -0,0 +1,53 @@
+<Type Name="TemplateExtensions" FullName="Xamarin.Forms.TemplateExtensions">
+ <TypeSignature Language="C#" Value="public static class TemplateExtensions" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract sealed beforefieldinit TemplateExtensions extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Extension class for DataTemplate, providing a string-based shortcut method for defining a Binding.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="SetBinding">
+ <MemberSignature Language="C#" Value="public static void SetBinding (this Xamarin.Forms.DataTemplate self, Xamarin.Forms.BindableProperty targetProperty, string path);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetBinding(class Xamarin.Forms.DataTemplate self, class Xamarin.Forms.BindableProperty targetProperty, string path) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.DataTemplate" RefType="this" />
+ <Parameter Name="targetProperty" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="path" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="self">To be added.</param>
+ <param name="targetProperty">To be added.</param>
+ <param name="path">To be added.</param>
+ <summary>Binds the <paramref name="self" /> object's <paramref name="targetProperty" /> to a new <see cref="T:Xamarin.Forms.Binding" /> instance that was created with <paramref name="path" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TemplatedPage.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TemplatedPage.xml
new file mode 100644
index 00000000..d1c3de04
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TemplatedPage.xml
@@ -0,0 +1,62 @@
+<Type Name="TemplatedPage" FullName="Xamarin.Forms.TemplatedPage">
+ <TypeSignature Language="C#" Value="public class TemplatedPage : Xamarin.Forms.Page" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit TemplatedPage extends Xamarin.Forms.Page" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Page</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A page that displays full-screen content with a control template, and the base class for <see cref="T:Xamarin.Forms.ContentPage" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TemplatedPage ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new empty templated page.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ControlTemplate">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.ControlTemplate ControlTemplate { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.ControlTemplate ControlTemplate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ControlTemplate</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the control template that is used to display content.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ControlTemplateProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ControlTemplateProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ControlTemplateProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="T:Xamarin.Forms.TemplatedPage.ControlTemplate" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TemplatedView.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TemplatedView.xml
new file mode 100644
index 00000000..f15d38c9
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TemplatedView.xml
@@ -0,0 +1,114 @@
+<Type Name="TemplatedView" FullName="Xamarin.Forms.TemplatedView">
+ <TypeSignature Language="C#" Value="public class TemplatedView : Xamarin.Forms.Layout" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit TemplatedView extends Xamarin.Forms.Layout" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Layout</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A view that displays content with a control template, and the base class for <see cref="T:Xamarin.Forms.ContentView" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TemplatedView ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new empty templated view.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ControlTemplate">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.ControlTemplate ControlTemplate { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.ControlTemplate ControlTemplate" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ControlTemplate</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the control template that is used to display content.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ControlTemplateProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ControlTemplateProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ControlTemplateProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="T:Xamarin.Forms.TemplatedView.ControlTemplate" /> property..</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutChildren">
+ <MemberSignature Language="C#" Value="protected override void LayoutChildren (double x, double y, double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void LayoutChildren(float64 x, float64 y, float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">The X coordinate of the upper left corner of the bounding rectangle.</param>
+ <param name="y">The Y coordinate of the upper left corner of the bounding rectangle.</param>
+ <param name="width">The width of the bounding rectangle.</param>
+ <param name="height">The height of the bounding rectangle.</param>
+ <summary>Positions and sizes the children of the templated view within the rectangle defined by <paramref name="x" />, <paramref name="y" />, <paramref name="width" />, and <paramref name="height" />T.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeRequest">
+ <MemberSignature Language="C#" Value="protected override Xamarin.Forms.SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance valuetype Xamarin.Forms.SizeRequest OnSizeRequest(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use OnMeasure")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">The width constraint that was passed with the request.</param>
+ <param name="heightConstraint">The height constraint that was passed with the request.</param>
+ <summary>Method that is called when the layout updates.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TextAlignment.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TextAlignment.xml
new file mode 100644
index 00000000..1030ae2b
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TextAlignment.xml
@@ -0,0 +1,83 @@
+<Type Name="TextAlignment" FullName="Xamarin.Forms.TextAlignment">
+ <TypeSignature Language="C#" Value="public enum TextAlignment" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed TextAlignment extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Represents vertical and horizontal text alignement.</summary>
+ <remarks>This affects the way the text is diaplayed inside of its control bounds.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Center">
+ <MemberSignature Language="C#" Value="Center" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TextAlignment Center = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TextAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Center-aligned text.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="End">
+ <MemberSignature Language="C#" Value="End" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TextAlignment End = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TextAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>End-flushed text. It means right-aligned (resp: bottom-aligned) for horizontal (resp vertical) alignemnt.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Start">
+ <MemberSignature Language="C#" Value="Start" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.TextAlignment Start = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TextAlignment</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Start-flushed text. It means left-aligned (resp: top-aligned) for horizontal (resp vertical) alignemnt.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TextCell.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TextCell.xml
new file mode 100644
index 00000000..a3f48842
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TextCell.xml
@@ -0,0 +1,382 @@
+<Type Name="TextCell" FullName="Xamarin.Forms.TextCell">
+ <TypeSignature Language="C#" Value="public class TextCell : Xamarin.Forms.Cell" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit TextCell extends Xamarin.Forms.Cell" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Cell</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>
+ A <see cref="T:Xamarin.Forms.Cell" /> with primary <see cref="P:Xamarin.Forms.TextCell.Text" /> and <see cref="P:Xamarin.Forms.TextCell.Detail" /> text.
+ </summary>
+ <remarks>
+ <para>The following example shows a basic use.</para>
+ <example>
+ <code lang="C#"><![CDATA[
+public class App : Application
+{
+ public App()
+ {
+ MainPage = new ContentPage {
+ Content = new TableView {
+ Intent = TableIntent.Form,
+ Root = new TableRoot ("Table Title") {
+ new TableSection ("Section 1 Title") {
+ new TextCell {
+ Text = "TextCell Text",
+ Detail = "TextCell Detail"
+ },
+ new EntryCell {
+ Label = "EntryCell:",
+ Placeholder = "default keyboard",
+ Keyboard = Keyboard.Default
+ }
+ },
+ new TableSection ("Section 2 Title") {
+ new EntryCell {
+ Label = "Another EntryCell:",
+ Placeholder = "phone keyboard",
+ Keyboard = Keyboard.Telephone
+ },
+ new SwitchCell {
+ Text = "SwitchCell:"
+ }
+ }
+ }
+ }
+ };
+ }
+ // OnStart, OnSleep, OnResume overrides omitted...
+}]]></code>
+ </example>
+ <para>
+ <img href="TextCell.TripleScreenShot.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TextCell ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the TextCell class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Command">
+ <MemberSignature Language="C#" Value="public System.Windows.Input.ICommand Command { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Windows.Input.ICommand Command" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Windows.Input.ICommand</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the ICommand to be executed when the TextCell is tapped. This is a bindable property.</summary>
+ <value>
+ </value>
+ <remarks>Setting the Command property has a side effect of changing the Enabled property depending on ICommand.CanExecute.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CommandParameter">
+ <MemberSignature Language="C#" Value="public object CommandParameter { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object CommandParameter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the parameter passed when invoking the Command. This is a bindable property.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CommandParameterProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty CommandParameterProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty CommandParameterProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the CommandParameter bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CommandProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty CommandProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty CommandProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Command bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Detail">
+ <MemberSignature Language="C#" Value="public string Detail { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Detail" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the secondary text to be displayed in the TextCell. This is a bindable property.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="DetailColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color DetailColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color DetailColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the color to render the secondary text. This is a bindable property.</summary>
+ <value>The color of the text. Color.Default is the default color value.</value>
+ <remarks>Not all platforms may support transparent text rendering. Using Color.Default will result in the system theme color being used.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="DetailColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty DetailColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty DetailColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the DetailColor bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="DetailProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty DetailProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty DetailProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the secondary text to be displayed. This is a bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnTapped">
+ <MemberSignature Language="C#" Value="protected override void OnTapped ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyorassemblyhidebysig virtual instance void OnTapped() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invoked whenever the Cell is Tapped.</summary>
+ <remarks>Overriden for TextCell.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Text">
+ <MemberSignature Language="C#" Value="public string Text { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Text" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the primary text to be displayed. This is a bindable property.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color TextColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color TextColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the color to render the primary text. This is a bindable property.</summary>
+ <value>The color of the text.</value>
+ <remarks>Not all platforms may support transparent text rendering. Using Color.Default will result in the system theme color being used. Color.Default is the default color value.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TextColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TextColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the TextColor bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TextProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TextProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TextProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Text bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TextChangedEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TextChangedEventArgs.xml
new file mode 100644
index 00000000..4b972455
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TextChangedEventArgs.xml
@@ -0,0 +1,92 @@
+<Type Name="TextChangedEventArgs" FullName="Xamarin.Forms.TextChangedEventArgs">
+ <TypeSignature Language="C#" Value="public class TextChangedEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit TextChangedEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Event arguments for <c>TextChanged</c> events. Provides old and new text values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TextChangedEventArgs (string oldTextValue, string newTextValue);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string oldTextValue, string newTextValue) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="oldTextValue" Type="System.String" />
+ <Parameter Name="newTextValue" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="oldTextValue">To be added.</param>
+ <param name="newTextValue">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.TextChangedEventArgs" /> with <paramref name="oldTextValue" /> and <paramref name="newTextValue" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="NewTextValue">
+ <MemberSignature Language="C#" Value="public string NewTextValue { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string NewTextValue" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the new text value.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OldTextValue">
+ <MemberSignature Language="C#" Value="public string OldTextValue { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string OldTextValue" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the old text value.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Thickness.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Thickness.xml
new file mode 100644
index 00000000..f7b8b5e3
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Thickness.xml
@@ -0,0 +1,402 @@
+<Type Name="Thickness" FullName="Xamarin.Forms.Thickness">
+ <TypeSignature Language="C#" Value="public struct Thickness" />
+ <TypeSignature Language="ILAsm" Value=".class public sequential ansi sealed beforefieldinit Thickness extends System.ValueType" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.ValueType</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.DebuggerDisplay("Left={Left}, Top={Top}, Right={Right}, Bottom={Bottom}, HorizontalThickness={HorizontalThickness}, VerticalThickness={VerticalThickness}")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.ThicknessTypeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Struct defining thickness around the edges of a <see cref="T:Xamarin.Forms.Rectangle" /> using doubles.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Thickness (double uniformSize);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 uniformSize) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="uniformSize" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="uniformSize">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Thickness" /> object that represents a uniform thickness of size <paramref name="uniformSize" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Thickness (double horizontalSize, double verticalSize);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 horizontalSize, float64 verticalSize) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="horizontalSize" Type="System.Double" />
+ <Parameter Name="verticalSize" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="horizontalSize">To be added.</param>
+ <param name="verticalSize">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Thickness" /> object that has a horizontal thickness of <paramref name="horizontalSize" /> and a vertical thickness of <paramref name="verticalSize" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Thickness (double left, double top, double right, double bottom);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 left, float64 top, float64 right, float64 bottom) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="left" Type="System.Double" />
+ <Parameter Name="top" Type="System.Double" />
+ <Parameter Name="right" Type="System.Double" />
+ <Parameter Name="bottom" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="left">To be added.</param>
+ <param name="top">To be added.</param>
+ <param name="right">To be added.</param>
+ <param name="bottom">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Thickness" /> object with thicknesses defined by <paramref name="left" />, <paramref name="top" />, <paramref name="right" />, and <paramref name="bottom" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Bottom">
+ <MemberSignature Language="C#" Value="public double Bottom { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Bottom" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The thickness of the bottom of a rectangle.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Equals">
+ <MemberSignature Language="C#" Value="public override bool Equals (object obj);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool Equals(object obj) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="obj" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="obj">A <see cref="T:Xamarin.Forms.Thickness" /> to be compared.</param>
+ <summary>Whether the <paramref name="obj" /> is a <see cref="T:Xamarin.Forms.Thickness" /> with equivalent values.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="obj" /> is a <see cref="T:Xamarin.Forms.Thickness" /> and has equivalent values..</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetHashCode">
+ <MemberSignature Language="C#" Value="public override int GetHashCode ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance int32 GetHashCode() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>A has value for this <see cref="T:Xamarin.Forms.Thickness" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HorizontalThickness">
+ <MemberSignature Language="C#" Value="public double HorizontalThickness { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 HorizontalThickness" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The sum of <see cref="P:Xamarin.Forms.Thickness.Left" /> and <see cref="P:Xamarin.Forms.Thickness.Right" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Left">
+ <MemberSignature Language="C#" Value="public double Left { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Left" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The thickness of the left side of a rectangle.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Equality">
+ <MemberSignature Language="C#" Value="public static bool op_Equality (Xamarin.Forms.Thickness left, Xamarin.Forms.Thickness right);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Equality(valuetype Xamarin.Forms.Thickness left, valuetype Xamarin.Forms.Thickness right) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="left" Type="Xamarin.Forms.Thickness" />
+ <Parameter Name="right" Type="Xamarin.Forms.Thickness" />
+ </Parameters>
+ <Docs>
+ <param name="left">A <see cref="T:Xamarin.Forms.Thickness" /> to be compared.</param>
+ <param name="right">A <see cref="T:Xamarin.Forms.Thickness" /> to be compared.</param>
+ <summary>Whether two <see cref="T:Xamarin.Forms.Thickness" />es have identical values.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="left" /> and <paramref name="right" /> have identical values for <see cref="P:Xamarin.Forms.Thickness.Left" />,<see cref="P:Xamarin.Forms.Thickness.Right" />, <see cref="P:Xamarin.Forms.Thickness.Top" />, and <see cref="P:Xamarin.Forms.Thickness.Bottom" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Implicit">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Thickness op_Implicit (double uniformSize);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname valuetype Xamarin.Forms.Thickness op_Implicit(float64 uniformSize) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Thickness</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="uniformSize" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="uniformSize">The value for the uniform Thickness.</param>
+ <summary>Implicit cast operator from <see cref="T:System.Double" />.</summary>
+ <returns>A Thickness with an uniform size.</returns>
+ <remarks>
+ <para>Application developers should bear in mind that <see cref="P:Xamarin.Forms.Thickness.HorizontalThickness" /> and <see cref="P:Xamarin.Forms.Thickness.VerticalThickness" /> are the sums of their components, so a <see cref="T:Xamarin.Forms.Thickness" /> created from a <paramref name="uniformSize" /> of, for instance, 1.0, will have <see cref="P:Xamarin.Forms.Thickness.HorizontalThickness" /> of 2.0.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Implicit">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Thickness op_Implicit (Xamarin.Forms.Size size);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname valuetype Xamarin.Forms.Thickness op_Implicit(valuetype Xamarin.Forms.Size size) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Thickness</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="size" Type="Xamarin.Forms.Size" />
+ </Parameters>
+ <Docs>
+ <param name="size">A <see cref="T:Xamarin.Forms.Size" /> to convert to a <see cref="T:Xamarin.Forms.Thickness" /></param>
+ <summary>Converts a <see cref="T:Xamarin.Forms.Size" /> into a <see cref="T:Xamarin.Forms.Thickness" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>
+ <para>The <see cref="T:Xamarin.Forms.Thickness" />'s <see cref="P:Xamarin.Forms.Thickness.Left" /> and <see cref="P:Xamarin.Forms.Thickness.Right" /> are both set equal to the <paramref name="size" />'s <see cref="P:Xamarin.Forms.Size.Width" /> and the <see cref="T:Xamarin.Forms.Thickness" />'s <see cref="P:Xamarin.Forms.Thickness.Top" /> and <see cref="P:Xamarin.Forms.Thickness.Bottom" /> are both set equal to the <paramref name="size" />'s <see cref="P:Xamarin.Forms.Size.Height" />.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Inequality">
+ <MemberSignature Language="C#" Value="public static bool op_Inequality (Xamarin.Forms.Thickness left, Xamarin.Forms.Thickness right);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Inequality(valuetype Xamarin.Forms.Thickness left, valuetype Xamarin.Forms.Thickness right) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="left" Type="Xamarin.Forms.Thickness" />
+ <Parameter Name="right" Type="Xamarin.Forms.Thickness" />
+ </Parameters>
+ <Docs>
+ <param name="left">A <see cref="T:Xamarin.Forms.Thickness" /> to be compared.</param>
+ <param name="right">A <see cref="T:Xamarin.Forms.Thickness" /> to be compared.</param>
+ <summary>Whether the values of two <see cref="T:Xamarin.Forms.Thickness" />'s have at least one difference.</summary>
+ <returns>
+ <see langword="true" /> if any of the <see cref="P:Xamarin.Forms.Thickness.Left" />,<see cref="P:Xamarin.Forms.Thickness.Right" />, <see cref="P:Xamarin.Forms.Thickness.Top" />, and <see cref="P:Xamarin.Forms.Thickness.Bottom" /> values differ between <paramref name="left" /> and <paramref name="right" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Right">
+ <MemberSignature Language="C#" Value="public double Right { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Right" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The thickness of the right side of a rectangle.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Top">
+ <MemberSignature Language="C#" Value="public double Top { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Top" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The thickness of the top of a rectangle.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="VerticalThickness">
+ <MemberSignature Language="C#" Value="public double VerticalThickness { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 VerticalThickness" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The sum of <see cref="P:Xamarin.Forms.Thickness.Top" /> and <see cref="P:Xamarin.Forms.Thickness.Bottom" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ThicknessTypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ThicknessTypeConverter.xml
new file mode 100644
index 00000000..a2229b55
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ThicknessTypeConverter.xml
@@ -0,0 +1,117 @@
+<Type Name="ThicknessTypeConverter" FullName="Xamarin.Forms.ThicknessTypeConverter">
+ <TypeSignature Language="C#" Value="public class ThicknessTypeConverter : Xamarin.Forms.TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ThicknessTypeConverter extends Xamarin.Forms.TypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TypeConverter" /> that converts from a string to a <see cref="T:Xamarin.Forms.Thickness" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ThicknessTypeConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.ThicknessTypeConverter" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>Returns a Boolean value that indicates whether this <see cref="T:Xamarin.Forms.ThicknessTypeConverter" /> can convert the <paramref name="sourceType" /> to a <see cref="T:Xamarin.Forms.Thickness" /> instance.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Converts <paramref name="value" /> into a <see cref="T:Xamarin.Forms.Thickness" /> by using the specified <paramref name="culture" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Returns a <see cref="T:Xamarin.Forms.Thickness" /> for a comma-separated list of doubles.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TimePicker.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TimePicker.xml
new file mode 100644
index 00000000..af19bfd8
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TimePicker.xml
@@ -0,0 +1,150 @@
+<Type Name="TimePicker" FullName="Xamarin.Forms.TimePicker">
+ <TypeSignature Language="C#" Value="public class TimePicker : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit TimePicker extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._TimePickerRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.View" /> control that provides time picking.</summary>
+ <remarks>
+ <para>The visual representation of a TimePicker is very similar to the one of <see cref="T:Xamarin.Forms.Entry" />, except that a special control for picking a time appears in place of a keyboard.</para>
+ <para>
+ The following example shows declaration of a TimePicker with a default time set.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+var beeroclock = new TimePicker () { Time = new TimeSpan (17,0,0) };
+ ]]></code>
+ </example>
+ <para>
+ <img href="TimePicker.TripleScreenShot.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TimePicker ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new TimePicker instance.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Format">
+ <MemberSignature Language="C#" Value="public string Format { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Format" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The format of the time to display to the user. This is a bindable property.</summary>
+ <value>A valid time format string.</value>
+ <remarks>Format string is the same is passed to DateTime.ToString (string format).</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FormatProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty FormatProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty FormatProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Format bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Time">
+ <MemberSignature Language="C#" Value="public TimeSpan Time { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype System.TimeSpan Time" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.TimeSpan</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the displayed time. This is a bindable property.</summary>
+ <value>The <see cref="T:System.TimeSpan" /> displayed in the TimePicker.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TimeProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TimeProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TimeProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Time bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ToggledEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ToggledEventArgs.xml
new file mode 100644
index 00000000..6da6417b
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ToggledEventArgs.xml
@@ -0,0 +1,68 @@
+<Type Name="ToggledEventArgs" FullName="Xamarin.Forms.ToggledEventArgs">
+ <TypeSignature Language="C#" Value="public class ToggledEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ToggledEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Event arguments for <see cref="E:Xamarin.Forms.Switch.Toggled" /> and <see cref="E:Xamarin.Forms.SwitchCell.OnChanged" /> events.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ToggledEventArgs (bool value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(bool value) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="value" Type="System.Boolean" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.ToggledEventArgs" /> that indicates that the toggle control was toggled to <paramref name="value" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Value">
+ <MemberSignature Language="C#" Value="public bool Value { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool Value" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the Boolean value to which the toggle control was toggled.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ToolbarItem.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ToolbarItem.xml
new file mode 100644
index 00000000..ad0705d2
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ToolbarItem.xml
@@ -0,0 +1,303 @@
+<Type Name="ToolbarItem" FullName="Xamarin.Forms.ToolbarItem">
+ <TypeSignature Language="C#" Value="public class ToolbarItem : Xamarin.Forms.MenuItem" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ToolbarItem extends Xamarin.Forms.MenuItem" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.MenuItem</BaseTypeName>
+ </Base>
+ <Interfaces>
+ </Interfaces>
+ <Docs>
+ <summary>An item in a toolbar or displayed on a <see cref="T:Xamarin.Forms.Page" />.</summary>
+ <remarks>
+ <para>Any changes made to the properties of the toolbar item after it has been added will be ignored.</para>
+ <block type="note">Windows Phone ApplicationBarButtons and MenuItems always display an associated text. Therefore, when developing for Windows Phone, application devs should provide a value for the <see cref="P:Xamarin.Forms.ToolbarItem.Text" /> property. Otherwise, the file name of the icon image will be dixplayed as the text of the <see cref="T:Xamarin.Forms.ToolbarItem" />. (For example, the user might see "menu.png" in the user interface.)</block>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ToolbarItem ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Constructs and initializes a new instance of the <see cref="T:Xamarin.Forms.ToolbarItem" /> class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ToolbarItem (string name, string icon, Action activated, Xamarin.Forms.ToolbarItemOrder order = Xamarin.Forms.ToolbarItemOrder.Default, int priority = 0);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string name, string icon, class System.Action activated, valuetype Xamarin.Forms.ToolbarItemOrder order, int32 priority) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="icon" Type="System.String" />
+ <Parameter Name="activated" Type="System.Action" />
+ <Parameter Name="order" Type="Xamarin.Forms.ToolbarItemOrder" />
+ <Parameter Name="priority" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="name">To be added.</param>
+ <param name="icon">To be added.</param>
+ <param name="activated">To be added.</param>
+ <param name="order">To be added.</param>
+ <param name="priority">To be added.</param>
+ <summary>Constructs and initializes a new instance of the <see cref="T:Xamarin.Forms.ToolbarItem" /> class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Activated">
+ <MemberSignature Language="C#" Value="public event EventHandler Activated;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Activated" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Activated has been replaced by the more consistent 'Clicked'")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Raised when the <see cref="T:Xamarin.Forms.ToolbarItem" /> is touched or clicked.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Command">
+ <MemberSignature Language="C#" Value="public System.Windows.Input.ICommand Command { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Windows.Input.ICommand Command" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Windows.Input.ICommand</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the <see cref="T:System.Windows.Input.ICommand" /> to be invoked on activation.</summary>
+ <value>The <see cref="T:System.Windows.Input.ICommand" /> to be invoked on activation.</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CommandParameter">
+ <MemberSignature Language="C#" Value="public object CommandParameter { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object CommandParameter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the parameter to pass to the <see cref="T:System.Windows.Input.ICommand" /> that is invoked on activation.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CommandParameterProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty CommandParameterProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty CommandParameterProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ToolBarItem.ComandParameter" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CommandProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty CommandProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty CommandProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.ToolBarItem.Comand" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Icon">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.FileImageSource Icon { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.FileImageSource Icon" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.FileImageSource</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a string that identifies the image that is displayed on this <see cref="T:Xamarin.Forms.ToolbarItem" /> element.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Name">
+ <MemberSignature Language="C#" Value="public string Name { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Name" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Now that ToolbarItem is based on MenuItem, .Text has replaced .Name")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the name of the <see cref="T:Xamarin.Forms.ToolbarItem" />.</summary>
+ <value>The name of the toolbar item..</value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Order">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.ToolbarItemOrder Order { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.ToolbarItemOrder Order" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ToolbarItemOrder</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that indicates on which of on the primary, secondary, or default toolbar surfaces to display this <see cref="T:Xamarin.Forms.ToolbarItem" /> element.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Priority">
+ <MemberSignature Language="C#" Value="public int Priority { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 Priority" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the priority of this <see cref="T:Xamarin.Forms.ToolbarItem" /> element.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElement.Parent">
+ <MemberSignature Language="C#" Value="Xamarin.Forms.Element Xamarin.Forms.IElement.Parent { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Element Xamarin.Forms.IElement.Parent" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Element</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the toolbar to which this <see cref="T:Xamarin.Forms.ToolbarItem" /> element belongs.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IElement.XamlParent">
+ <MemberSignature Language="C#" Value="WeakReference&lt;Xamarin.Forms.Element&gt; Xamarin.Forms.IElement.XamlParent { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.WeakReference`1&lt;class Xamarin.Forms.Element&gt; Xamarin.Forms.IElement.XamlParent" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.WeakReference&lt;Xamarin.Forms.Element&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a weak reference to the parent of this <see cref="T:Xamarin.Forms.ToolbarItem" /> object.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ToolbarItemOrder.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ToolbarItemOrder.xml
new file mode 100644
index 00000000..920b2d90
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ToolbarItemOrder.xml
@@ -0,0 +1,83 @@
+<Type Name="ToolbarItemOrder" FullName="Xamarin.Forms.ToolbarItemOrder">
+ <TypeSignature Language="C#" Value="public enum ToolbarItemOrder" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed ToolbarItemOrder extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumeration specifying whether the <see cref="T:Xamarin.Forms.ToolbarItem" /> appears on the primary toolbar surface or secondary.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Default">
+ <MemberSignature Language="C#" Value="Default" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ToolbarItemOrder Default = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ToolbarItemOrder</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Use the default choice for the toolbar item.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Primary">
+ <MemberSignature Language="C#" Value="Primary" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ToolbarItemOrder Primary = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ToolbarItemOrder</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Place the toolbar item on the primary toolbar surface.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Secondary">
+ <MemberSignature Language="C#" Value="Secondary" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ToolbarItemOrder Secondary = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ToolbarItemOrder</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Place the toolbar item on the secondary toolbar surface.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Trigger.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Trigger.xml
new file mode 100644
index 00000000..ef04bf9c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Trigger.xml
@@ -0,0 +1,135 @@
+<Type Name="Trigger" FullName="Xamarin.Forms.Trigger">
+ <TypeSignature Language="C#" Value="public sealed class Trigger : Xamarin.Forms.TriggerBase, Xamarin.Forms.Xaml.IValueProvider" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit Trigger extends Xamarin.Forms.TriggerBase implements class Xamarin.Forms.Xaml.IValueProvider" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TriggerBase</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IValueProvider</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Setters")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Class that represents a property condition and an action that is performed when the condition is met.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Trigger (Type targetType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Type targetType) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="targetType" Type="System.Type">
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.TypeTypeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Parameter>
+ </Parameters>
+ <Docs>
+ <param name="targetType">To be added.</param>
+ <summary>Initializes a new <see cref="T:Xamarin.Forms.Trigger" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Property">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.BindableProperty Property { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.BindableProperty Property" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the property whose value will be compared to <see cref="P:Xamarin.Forms.Trigger.Value" /> to determine when to invoke the setters.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Setters">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt; Setters { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Setter&gt; Setters" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the list of <see cref="T:Xamarin.Forms.Setter" /> objects that will be applied when the property that is named by <see cref="P:Xamarin.Forms.Trigger.Property" /> becomes equal to <see cref="P:Xamarin.Forms.Trigger.Value" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Value">
+ <MemberSignature Language="C#" Value="public object Value { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Value" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the value of the property, named by the <see cref="P:Xamarin.Forms.Trigger.Property" /> property, that will cause the setters to be applied.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IValueProvider.ProvideValue">
+ <MemberSignature Language="C#" Value="object IValueProvider.ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.Xaml.IValueProvider.ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>This property supports XAML infrastructure and is not intended to be directly used by application developers.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TriggerAction.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TriggerAction.xml
new file mode 100644
index 00000000..adf804e1
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TriggerAction.xml
@@ -0,0 +1,80 @@
+<Type Name="TriggerAction" FullName="Xamarin.Forms.TriggerAction">
+ <TypeSignature Language="C#" Value="public abstract class TriggerAction" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit TriggerAction extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A base class for user-defined actions that are performed when a trigger condition is met.</summary>
+ <remarks>Application developers should use <see cref="T:Xamarin.Forms.TriggerAction`1" />, instead.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected TriggerAction (Type associatedType);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor(class System.Type associatedType) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="associatedType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="associatedType">The type of the objects with which this <see cref="T:Xamarin.Forms.TriggerAction" /> can be associated.</param>
+ <summary>Creates a new instance of the TriggerAction class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AssociatedType">
+ <MemberSignature Language="C#" Value="protected Type AssociatedType { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Type AssociatedType" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Type</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the type of the objects with which this <see cref="T:Xamarin.Forms.TriggerAction" /> can be associated.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Invoke">
+ <MemberSignature Language="C#" Value="protected abstract void Invoke (object sender);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void Invoke(object sender) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sender" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="sender">To be added.</param>
+ <summary>Application developers override this method to provide the behavior that is triggered.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TriggerAction`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TriggerAction`1.xml
new file mode 100644
index 00000000..f1748b04
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TriggerAction`1.xml
@@ -0,0 +1,93 @@
+<Type Name="TriggerAction&lt;T&gt;" FullName="Xamarin.Forms.TriggerAction&lt;T&gt;">
+ <TypeSignature Language="C#" Value="public abstract class TriggerAction&lt;T&gt; : Xamarin.Forms.TriggerAction where T : BindableObject" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit TriggerAction`1&lt;(class Xamarin.Forms.BindableObject) T&gt; extends Xamarin.Forms.TriggerAction" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <TypeParameters>
+ <TypeParameter Name="T">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TriggerAction</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <typeparam name="T">The type of which the <see cref="P:Xamarin.Forms.TriggerAction`1.AttachedObject" /> property must be an instance.</typeparam>
+ <summary>A generic base class for user-defined actions that are performed when a trigger condition is met.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected TriggerAction ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new instance of the <see cref="T:Xamarin.Forms.TriggerAction`1" /> class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Invoke">
+ <MemberSignature Language="C#" Value="protected override void Invoke (object sender);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void Invoke(object sender) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sender" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="sender">To be added.</param>
+ <summary>Application developers override this method to provide the action that is performed when the trigger condition is met.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Invoke">
+ <MemberSignature Language="C#" Value="protected abstract void Invoke (T sender);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void Invoke(!T sender) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sender" Type="T" />
+ </Parameters>
+ <Docs>
+ <param name="sender">To be added.</param>
+ <summary>Application developers override this method to provide the action that is performed when the trigger condition is met.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TriggerBase.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TriggerBase.xml
new file mode 100644
index 00000000..4a7888d3
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TriggerBase.xml
@@ -0,0 +1,147 @@
+<Type Name="TriggerBase" FullName="Xamarin.Forms.TriggerBase">
+ <TypeSignature Language="C#" Value="public abstract class TriggerBase : Xamarin.Forms.BindableObject" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit TriggerBase extends Xamarin.Forms.BindableObject" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Base>
+ <Interfaces>
+ </Interfaces>
+ <Docs>
+ <summary>Base class for classes that contain a condition and a list of actions to perform when the condition is met.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="EnterActions">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.TriggerAction&gt; EnterActions { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.TriggerAction&gt; EnterActions" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.TriggerAction&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the list of <see cref="T:Xamarin.Forms.TirggerAction" /> objects that will be invoked when the trigger condition is met. Ignored for the <see cref="T:Xamarin.Forms.EventTrigger" /> class.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ExitActions">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.TriggerAction&gt; ExitActions { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.TriggerAction&gt; ExitActions" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.TriggerAction&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the list of <see cref="T:Xamarin.Forms.TirggerAction" /> objects that will be invoked after the trigger condition is no longer met. Ignored for the <see cref="T:Xamarin.Forms.EventTrigger" /> class.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsSealed">
+ <MemberSignature Language="C#" Value="public bool IsSealed { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsSealed" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that indicates whether or not the trigger is sealed.</summary>
+ <value>To be added.</value>
+ <remarks>A trigger becomes sealed when its <see cref="M:Xamarin.Forms.IAttachedObject.AttachTo" /> method is called. Once it is sealed, its <see cref="P:Xamarin.Forms.TriggerBase.EnterActions" /> and <see cref="P:Xamarin.Forms.TriggerBase.ExitActions" /> lists become readonly.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TargetType">
+ <MemberSignature Language="C#" Value="public Type TargetType { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Type TargetType" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Type</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The type of object to which this <see cref="T:Xamarin.Forms.TriggerBase" /> object can be attached.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IAttachedObject.AttachTo">
+ <MemberSignature Language="C#" Value="void IAttachedObject.AttachTo (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IAttachedObject.AttachTo(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <summary>Attempts to attach to <paramref name="bindable" />. If successful, calls the <see cref="M:Xamarin.Forms.TriggerBase.OnAttachedTo" /> method.</summary>
+ <remarks>This method throws an exception if <paramref name="bindable" /> is not an instance of <see cref="P:Xamarin.Forms.TriggerBase.TargetType" />. In that case, the <see cref="M:Xamarin.Forms.TriggerBase.OnAttachedTo" /> method is not called.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IAttachedObject.DetachFrom">
+ <MemberSignature Language="C#" Value="void IAttachedObject.DetachFrom (Xamarin.Forms.BindableObject bindable);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IAttachedObject.DetachFrom(class Xamarin.Forms.BindableObject bindable) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bindable" Type="Xamarin.Forms.BindableObject" />
+ </Parameters>
+ <Docs>
+ <param name="bindable">To be added.</param>
+ <summary>Attempts to detach from <paramref name="bindable" />. If successful, calls <see cref="M:Xamarin.Forms.TriggerBase.OnDetachedFrom" />..</summary>
+ <remarks>This method throws an exception if <paramref name="bindable" /> is <see langword="null" />. In that case, the <see cref="M:Xamarin.Forms.TriggerBase.OnDetachedFrom" /> method is not called.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TypeConverter.xml
new file mode 100644
index 00000000..0e90556b
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TypeConverter.xml
@@ -0,0 +1,158 @@
+<Type Name="TypeConverter" FullName="Xamarin.Forms.TypeConverter">
+ <TypeSignature Language="C#" Value="public abstract class TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit TypeConverter extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Abstract base class whose subclasses can convert values between different types.</summary>
+ <remarks>
+ <para>The following diagram shows subclasses of <see cref="T:Xamarin.Forms.TypeConverter" />.</para>
+ <para>
+ <img href="TypeConverter.Hierarchy.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected TypeConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.TypeConverter" /> object.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public virtual bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>When implemented in a derived class, returns a Boolean value that indicates whether or not the derived type converter can convert <paramref name="sourceType" /> to its target type.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public virtual object ConvertFrom (object o);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ConvertFrom(object o) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("use ConvertFromInvariantString (string)")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="o" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="o">To be added.</param>
+ <summary>Calls <see cref="M:Xamarin.Forms.TypeConverter.ConvertFrom(System.Globalization.CultureInfo, object)" /> with the current culture information and <paramref name="o" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public virtual object ConvertFrom (System.Globalization.CultureInfo culture, object o);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object o) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("use ConvertFromInvariantString (string)")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="o">To be added.</param>
+ <summary>When implemented in a derived class, converts an object that is a version of <paramref name="value" /> and that can be cast to the target type.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public virtual object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>When overriden in a derived class, converts XAML extension syntax into instances of various <see cref="N:Xamarin.Forms" /> types.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TypeConverterAttribute.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TypeConverterAttribute.xml
new file mode 100644
index 00000000..36b6f50e
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TypeConverterAttribute.xml
@@ -0,0 +1,184 @@
+<Type Name="TypeConverterAttribute" FullName="Xamarin.Forms.TypeConverterAttribute">
+ <TypeSignature Language="C#" Value="public sealed class TypeConverterAttribute : Attribute" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit TypeConverterAttribute extends System.Attribute" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Attribute</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.AttributeUsage(System.AttributeTargets.All)</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Attribute that specifies the type of <see cref="T:Xamarin.Forms.TypeConverter" /> used by its target.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TypeConverterAttribute ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.TypeConverterAttribute" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TypeConverterAttribute (string typeName);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string typeName) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="typeName" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="typeName">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.TypeConverterAttribute" /> object that specifies that the class it decorates converts values to the <paramref name="typeName" /> type.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TypeConverterAttribute (Type type);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Type type) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="type" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="type">To be added.</param>
+ <summary>reates a new <see cref="T:Xamarin.Forms.TypeConverterAttribute" /> object that specifies that the class it decorates converts values to <paramref name="type" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConverterTypeName">
+ <MemberSignature Language="C#" Value="public string ConverterTypeName { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string ConverterTypeName" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The name of the type to which the class decorated with this attribute can convert values.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Default">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.TypeConverterAttribute Default;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.TypeConverterAttribute Default" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.TypeConverterAttribute</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TypeConverterAttribute" /> that contains no information about the types to which the class that it decorates can convert values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Equals">
+ <MemberSignature Language="C#" Value="public override bool Equals (object obj);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool Equals(object obj) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="obj" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="obj">To be added.</param>
+ <summary>Returns true if <paramref name="obj" /> is a <see cref="T:Xamarin.Forms.TypeConverterAttribute" /> and has the same <see cref="P:Xamarin.Forms.TypeConverterAttribute.ConverterTypeName" /> value.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetHashCode">
+ <MemberSignature Language="C#" Value="public override int GetHashCode ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance int32 GetHashCode() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns a value that is used for efficient storage and lookup of this <see cref="T:Xamarin.Forms.TypeConverterAttribute" /> object.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/TypeTypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/TypeTypeConverter.xml
new file mode 100644
index 00000000..996c02ef
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/TypeTypeConverter.xml
@@ -0,0 +1,154 @@
+<Type Name="TypeTypeConverter" FullName="Xamarin.Forms.TypeTypeConverter">
+ <TypeSignature Language="C#" Value="public sealed class TypeTypeConverter : Xamarin.Forms.TypeConverter, Xamarin.Forms.IExtendedTypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit TypeTypeConverter extends Xamarin.Forms.TypeConverter implements class Xamarin.Forms.IExtendedTypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IExtendedTypeConverter</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>Class that takes a string representation of a <see cref="T:System.Type" /> and returns a corresponding <see cref="T:System.Type" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TypeTypeConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.TypeTypeConverter" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>Returns <see langword="true" /> if the converter can create and return a <see cref="T:System.Type" /> for items of the specified source type. Otherwise, <see langword="false" />.</summary>
+ <returns>
+ <see langword="true" /> if the converter can create and return a <see cref="T:System.Type" /> for items of the specified source type. Otherwise, <see langword="false" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Creates and returns a <see cref="T:System.Type" /> for the specified <paramref name="value" /> and <paramref name="culture" />.</summary>
+ <returns>A <see cref="T:System.Type" /> for the specified <paramref name="value" /> and <paramref name="culture" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Returns a type for a valid type name.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IExtendedTypeConverter.ConvertFrom">
+ <MemberSignature Language="C#" Value="object IExtendedTypeConverter.ConvertFrom (System.Globalization.CultureInfo culture, object value, IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.IExtendedTypeConverter.ConvertFrom(class System.Globalization.CultureInfo culture, object value, class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use ConvertFromInvariantString (string, IServiceProvider)")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use only.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IExtendedTypeConverter.ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="object IExtendedTypeConverter.ConvertFromInvariantString (string value, IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.IExtendedTypeConverter.ConvertFromInvariantString(string value, class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use only.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/UnsolvableConstraintsException.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/UnsolvableConstraintsException.xml
new file mode 100644
index 00000000..6595bdf8
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/UnsolvableConstraintsException.xml
@@ -0,0 +1,46 @@
+<Type Name="UnsolvableConstraintsException" FullName="Xamarin.Forms.UnsolvableConstraintsException">
+ <TypeSignature Language="C#" Value="public class UnsolvableConstraintsException : Exception" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit UnsolvableConstraintsException extends System.Exception" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Exception</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Exception indicating that the <see cref="T:Xamarin.Forms.Constraint" />s specified cannot be simultaneously satisfied.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public UnsolvableConstraintsException (string message);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string message) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="message" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="message">A description for this exception.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.UnsolvableConstraintsException" /> object with the <paramref name="message" /> explanatory message.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/UriImageSource.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/UriImageSource.xml
new file mode 100644
index 00000000..1404ef49
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/UriImageSource.xml
@@ -0,0 +1,135 @@
+<Type Name="UriImageSource" FullName="Xamarin.Forms.UriImageSource">
+ <TypeSignature Language="C#" Value="public sealed class UriImageSource : Xamarin.Forms.ImageSource" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed UriImageSource extends Xamarin.Forms.ImageSource" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.ImageSource</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>An ImageSource that loads an image from a URI, caching the result.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public UriImageSource ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.UriImageSource" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CacheValidity">
+ <MemberSignature Language="C#" Value="public TimeSpan CacheValidity { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype System.TimeSpan CacheValidity" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.TimeSpan</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a <see cref="T:System.TimeSpan" /> structure that indicates the length of time after which the image cache becomes invalid.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CachingEnabled">
+ <MemberSignature Language="C#" Value="public bool CachingEnabled { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool CachingEnabled" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a Boolean value that indicates whether caching is enabled on this <see cref="T:Xamarin.Forms.UriImageSource" /> object.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Uri">
+ <MemberSignature Language="C#" Value="public Uri Uri { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Uri Uri" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.UriTypeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>System.Uri</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the URI for the image to get.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="UriProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty UriProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty UriProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.UriImageSource.Uri" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/UriTypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/UriTypeConverter.xml
new file mode 100644
index 00000000..7938fb70
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/UriTypeConverter.xml
@@ -0,0 +1,117 @@
+<Type Name="UriTypeConverter" FullName="Xamarin.Forms.UriTypeConverter">
+ <TypeSignature Language="C#" Value="public class UriTypeConverter : Xamarin.Forms.TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit UriTypeConverter extends Xamarin.Forms.TypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TypeConverter" /> that converts from a string or <see cref="T:System.Uri" /> to a <see cref="T:System.Uri" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public UriTypeConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.UriTypeConverter" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>Returns a Boolean value that indicates whether this <see cref="T:Xamarin.Forms.UriTypeConverter" /> can convert the <paramref name="sourceType" /> to a <see cref="T:System.Uri" /> instance.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Converts <paramref name="value" /> into a <see cref="T:System.Uri" /> by using the specified <paramref name="culture" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Returns a <see cref="T:System.Uri" /> object for a string representation of a URI.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/UrlWebViewSource.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/UrlWebViewSource.xml
new file mode 100644
index 00000000..fccfd9f5
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/UrlWebViewSource.xml
@@ -0,0 +1,86 @@
+<Type Name="UrlWebViewSource" FullName="Xamarin.Forms.UrlWebViewSource">
+ <TypeSignature Language="C#" Value="public class UrlWebViewSource : Xamarin.Forms.WebViewSource" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit UrlWebViewSource extends Xamarin.Forms.WebViewSource" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.WebViewSource</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A WebViewSource bound to a URL.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public UrlWebViewSource ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.UrlWebViewSource" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Url">
+ <MemberSignature Language="C#" Value="public string Url { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Url" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the URL for this <see cref="T:Xamarin.Forms.UrlWebViewSource" /> object.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="UrlProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty UrlProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty UrlProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.UrlWebViewSource.Url" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ValueChangedEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ValueChangedEventArgs.xml
new file mode 100644
index 00000000..b0b7d675
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ValueChangedEventArgs.xml
@@ -0,0 +1,92 @@
+<Type Name="ValueChangedEventArgs" FullName="Xamarin.Forms.ValueChangedEventArgs">
+ <TypeSignature Language="C#" Value="public class ValueChangedEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ValueChangedEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Event arguments for <c>ValueChanged</c> events. Provides both old and new values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ValueChangedEventArgs (double oldValue, double newValue);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 oldValue, float64 newValue) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="oldValue" Type="System.Double" />
+ <Parameter Name="newValue" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="oldValue">To be added.</param>
+ <param name="newValue">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.ValueChangedEventArgs" /> event with <paramref name="oldValue" /> and <paramref name="newValue" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="NewValue">
+ <MemberSignature Language="C#" Value="public double NewValue { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 NewValue" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the new value.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OldValue">
+ <MemberSignature Language="C#" Value="public double OldValue { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 OldValue" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the old value.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Vec2.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Vec2.xml
new file mode 100644
index 00000000..67c116c0
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/Vec2.xml
@@ -0,0 +1,90 @@
+<Type Name="Vec2" FullName="Xamarin.Forms.Vec2">
+ <TypeSignature Language="C#" Value="public struct Vec2" />
+ <TypeSignature Language="ILAsm" Value=".class public sequential ansi sealed beforefieldinit Vec2 extends System.ValueType" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.ValueType</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Struct defining X and Y double values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Vec2 (double x, double y);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 x, float64 y) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="x">To be added.</param>
+ <param name="y">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Vec2" /> that is defined by <paramref name="x" /> and <paramref name="y" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="X">
+ <MemberSignature Language="C#" Value="public double X;" />
+ <MemberSignature Language="ILAsm" Value=".field public float64 X" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The horizontal coordinate.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Y">
+ <MemberSignature Language="C#" Value="public double Y;" />
+ <MemberSignature Language="ILAsm" Value=".field public float64 Y" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The vertical coordinate.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/View.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/View.xml
new file mode 100644
index 00000000..9c8decbb
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/View.xml
@@ -0,0 +1,290 @@
+<Type Name="View" FullName="Xamarin.Forms.View">
+ <TypeSignature Language="C#" Value="public class View : Xamarin.Forms.VisualElement, Xamarin.Forms.IViewController" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit View extends Xamarin.Forms.VisualElement implements class Xamarin.Forms.IElementController, class Xamarin.Forms.IViewController, class Xamarin.Forms.IVisualElementController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.VisualElement</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IViewController</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>A visual element that is used to place layouts and controls on the screen.</summary>
+ <remarks>
+ <para>The <see cref="T:Xamarin.Forms.View" /> class is a base class for the <see cref="T:Xamarin.Forms.Layout" /> class, and most of the controls that application developers will use. Nearly all UI elements that an application developer will use are derived from <see cref="T:Xamarin.Forms.View" /> class. Because the <see cref="T:Xamarin.Forms.View" /> class ultimately inherits from <see cref="T:Xamarin.Forms.BindableObject" /> class, application developers can use the Model-View-ViewModel architecture, as well as XAML, to develop portable user interfaces. The remarks in the <see cref="T:Xamarin.Forms.BindableObject" /> topic provide a discussion of MVVM and bound properties.</para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected View ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyorassemblyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the View class.</summary>
+ <remarks>It is unlikely that an application developer would want to create a new View instance on their own.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GestureRecognizers">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.IGestureRecognizer&gt; GestureRecognizers { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.IGestureRecognizer&gt; GestureRecognizers" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.IGestureRecognizer&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The collection of gesture recognizers associated with this view.</summary>
+ <value>A List of <see cref="T:Xamarin.Forms.IGestureRecognizer" />.</value>
+ <remarks>
+ <para>
+ Adding items to this collection will associate gesture events with this element. This is not nessesary for elements which natively support input, such as a Button.
+ </para>
+ <para>
+ This example creates a tap gesture recognizer and associates it with an image. When the image is double tapped, it will become semi-transparent.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+ var image = new Image {Source = "image.png"};
+ var gestureRecognizer = new TapGestureRecognizer {
+ TappedCallback = o => image.Opacity = 0.5,
+ NumberOfTapsRequired = 2
+ };
+ image.GestureRecognizers.Add (gestureRecognizer);
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HorizontalOptions">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.LayoutOptions HorizontalOptions { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.LayoutOptions HorizontalOptions" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LayoutOptions</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the <see cref="T:Xamarin.Forms.LayoutOptions" /> that define how the element gets laid in a layout cycle. This is a bindable property.</summary>
+ <value>A <see cref="T:Xamarin.Forms.LayoutOptions" /> which defines how to lay out the element. Default value is <see cref="F:Xamarin.Forms.LayoutOptions.Fill" /> unless otherwise documented.</value>
+ <remarks>
+ <para>
+ Assigning the HorizontalOptions modifies how the element is laid out when there is excess space available along the X axis from the parent layout. Additionally it specifies if the element should consume leftover space in the X axis from the parent layout. If multiple children of a layout are set to expand, the extra space is distributed proportionally.
+ </para>
+ <para>
+ This example creates four views and adds them to a stack, each laying out in a different manner.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+ private View CreateButtons ()
+ {
+ var button1 = new Button {Text = "LeftAligned", HorizontalOptions=LayoutOptions.Start};
+ var button2 = new Button {Text = "CenterAligned", HorizontalOptions=LayoutOptions.Center};
+ var button3 = new Button {Text = "EndAligned", HorizontalOptions=LayoutOptions.End};
+ var button4 = new Button {Text = "Fill", HorizontalOptions=LayoutOptions.Fill};
+
+ StackLayout stack = new StackLayout {
+ Children = {
+ button1,
+ button2,
+ button3,
+ button4
+ }
+ };
+
+ return stack;
+ }
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HorizontalOptionsProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HorizontalOptionsProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HorizontalOptionsProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the HorizontalOptions bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Margin">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Thickness Margin { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Thickness Margin" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Thickness</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the margin for the view.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MarginProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty MarginProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty MarginProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.View.Margin" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBindingContextChanged">
+ <MemberSignature Language="C#" Value="protected override void OnBindingContextChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnBindingContextChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invoked whenever the binding context of the <see cref="T:Xamarin.Forms.View" /> changes. Override this method to add class handling for this event.</summary>
+ <remarks>
+ <para>Overriders must call the base method.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="VerticalOptions">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.LayoutOptions VerticalOptions { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.LayoutOptions VerticalOptions" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.LayoutOptions</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the <see cref="T:Xamarin.Forms.LayoutOptions" /> that define how the element gets laid in a layout cycle. This is a bindable property.</summary>
+ <value>A <see cref="T:Xamarin.Forms.LayoutOptions" /> which defines how to lay out the element. Default value is <see cref="F:Xamarin.Forms.LayoutOptions.Fill" /> unless otherwise documented.</value>
+ <remarks>
+ <para>
+ Assigning the VerticalOptions modifies how the element is laid out when there is excess space available along the Y axis from the parent layout. Additionally it specifies if the element should consume leftover space in the Y axis from the parent layout. If multiple children of a layout are set to expand, the extra space is distributed proportionally.
+ </para>
+ <para>
+ This example creates four views and adds them to a stack, each laying out in a different manner.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+ private View CreateButtons ()
+ {
+ var button1 = new Button {Text = "TopAligned", VerticalOptions=LayoutOptions.Start};
+ var button2 = new Button {Text = "CenterAligned", VerticalOptions=LayoutOptions.Center};
+ var button3 = new Button {Text = "BottomAligned", VerticalOptions=LayoutOptions.End};
+ var button4 = new Button {Text = "Fill", VerticalOptions=LayoutOptions.Fill};
+
+ StackLayout stack = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children = {
+ button1,
+ button2,
+ button3,
+ button4
+ }
+ };
+
+ return stack;
+ }
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="VerticalOptionsProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty VerticalOptionsProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty VerticalOptionsProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the VerticalOptions bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ViewCell.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ViewCell.xml
new file mode 100644
index 00000000..deea3745
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ViewCell.xml
@@ -0,0 +1,74 @@
+<Type Name="ViewCell" FullName="Xamarin.Forms.ViewCell">
+ <TypeSignature Language="C#" Value="public class ViewCell : Xamarin.Forms.Cell" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ViewCell extends Xamarin.Forms.Cell" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Cell</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("View")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.Cell" /> containing a developer-defined <see cref="T:Xamarin.Forms.View" />.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ViewCell ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Initializes a new instance of the ViewCell class.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="View">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.View View { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.View View" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.View</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the View representing the content of the ViewCell.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ViewExtensions.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ViewExtensions.xml
new file mode 100644
index 00000000..1ea4b51f
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ViewExtensions.xml
@@ -0,0 +1,338 @@
+<Type Name="ViewExtensions" FullName="Xamarin.Forms.ViewExtensions">
+ <TypeSignature Language="C#" Value="public static class ViewExtensions" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract sealed beforefieldinit ViewExtensions extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Extension methods for <see cref="T:Xamarin.Forms.View" />s, providing animatable scaling, rotation, and layout functions.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="CancelAnimations">
+ <MemberSignature Language="C#" Value="public static void CancelAnimations (Xamarin.Forms.VisualElement view);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void CancelAnimations(class Xamarin.Forms.VisualElement view) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <summary>Aborts the TranslateTo, LayoutTo, RotateTo, ScaleTo, and FadeTo animations on <paramref name="view" /> element.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FadeTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; FadeTo (this Xamarin.Forms.VisualElement view, double opacity, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; FadeTo(class Xamarin.Forms.VisualElement view, float64 opacity, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="opacity" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="opacity">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Returns a task that performs the fade that is described by the <paramref name="opacity" />, <paramref name="length" />, and <paramref name="easing" /> parameters.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LayoutTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; LayoutTo (this Xamarin.Forms.VisualElement view, Xamarin.Forms.Rectangle bounds, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; LayoutTo(class Xamarin.Forms.VisualElement view, valuetype Xamarin.Forms.Rectangle bounds, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="bounds" Type="Xamarin.Forms.Rectangle" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="bounds">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Returns a task that eases the bounds of the <see cref="T:Xamarin.Forms.VisualElement" /> that is specified by the <paramref name="view" /> to the rectangle that is specified by the <paramref name="bounds" /> parameter.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RelRotateTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; RelRotateTo (this Xamarin.Forms.VisualElement view, double drotation, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; RelRotateTo(class Xamarin.Forms.VisualElement view, float64 drotation, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="drotation" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="drotation">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Rotates the <see cref="T:Xamarin.Forms.VisualElement" /> that is specified by <paramref name="view" /> from its current rotation by <paramref name="drotation" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RelScaleTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; RelScaleTo (this Xamarin.Forms.VisualElement view, double dscale, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; RelScaleTo(class Xamarin.Forms.VisualElement view, float64 dscale, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="dscale" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="dscale">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Returns a task that scales the <see cref="T:Xamarin.Forms.VisualElement" /> that is specified by <paramref name="view" /> from its current scale to <paramref name="dscale" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RotateTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; RotateTo (this Xamarin.Forms.VisualElement view, double rotation, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; RotateTo(class Xamarin.Forms.VisualElement view, float64 rotation, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="rotation" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="rotation">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Returns a task that performs the rotation that is described by the <paramref name="rotation" />, <paramref name="length" />, and <paramref name="easing" /> parameters..</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RotateXTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; RotateXTo (this Xamarin.Forms.VisualElement view, double rotation, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; RotateXTo(class Xamarin.Forms.VisualElement view, float64 rotation, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="rotation" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="rotation">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Returns a task that skews the Y axis by <paramref name="opacity" />, taking time <paramref name="length" /> and using <paramref name="easing" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RotateYTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; RotateYTo (this Xamarin.Forms.VisualElement view, double rotation, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; RotateYTo(class Xamarin.Forms.VisualElement view, float64 rotation, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="rotation" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="rotation">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Returns a task that skews the X axis by <paramref name="opacity" />, taking time <paramref name="length" /> and using <paramref name="easing" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ScaleTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; ScaleTo (this Xamarin.Forms.VisualElement view, double scale, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; ScaleTo(class Xamarin.Forms.VisualElement view, float64 scale, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="scale" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="scale">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Returns a task that scales the <see cref="T:Xamarin.Forms.VisualElement" /> that is specified by <paramref name="view" /> to the absolute scale factor <paramref name="scale" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TranslateTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; TranslateTo (this Xamarin.Forms.VisualElement view, double x, double y, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; TranslateTo(class Xamarin.Forms.VisualElement view, float64 x, float64 y, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">The view to tanslate.</param>
+ <param name="x">The x component of the final translation vector.</param>
+ <param name="y">The y component of the final translation vector.</param>
+ <param name="length">The duration of the animation in milliseconds.</param>
+ <param name="easing">The easing of the animation.</param>
+ <summary>Animates an elements TranslationX and TranslationY properties from their current values to the new values.</summary>
+ <returns>To be added.</returns>
+ <remarks>Translate to is particular useful for animations because it is applied post-layout. Translation animations will not conflict with managed layouts and thus are ideal for doing slide in/out style animations.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ViewState.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ViewState.xml
new file mode 100644
index 00000000..be2ca0ab
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ViewState.xml
@@ -0,0 +1,88 @@
+<Type Name="ViewState" FullName="Xamarin.Forms.ViewState">
+ <TypeSignature Language="C#" Value="public enum ViewState" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed ViewState extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Flags</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Deprecated. Do not use.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Default">
+ <MemberSignature Language="C#" Value="Default" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ViewState Default = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ViewState</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Deprecated. Do not use.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Prelight">
+ <MemberSignature Language="C#" Value="Prelight" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ViewState Prelight = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ViewState</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Deprecated. Do not use.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Pressed">
+ <MemberSignature Language="C#" Value="Pressed" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ViewState Pressed = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ViewState</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Deprecated. Do not use..</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/VisualElement.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/VisualElement.xml
new file mode 100644
index 00000000..b4ee09d9
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/VisualElement.xml
@@ -0,0 +1,1913 @@
+<Type Name="VisualElement" FullName="Xamarin.Forms.VisualElement">
+ <TypeSignature Language="C#" Value="public class VisualElement : Xamarin.Forms.Element, Xamarin.Forms.IAnimatable, Xamarin.Forms.IVisualElementController" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit VisualElement extends Xamarin.Forms.Element implements class Xamarin.Forms.IAnimatable, class Xamarin.Forms.IElementController, class Xamarin.Forms.IVisualElementController" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.Element</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IAnimatable</InterfaceName>
+ </Interface>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.IVisualElementController</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.Element" /> that occupies an area on the screen, has a visual appearance, and can obtain touch input.</summary>
+ <remarks>
+ <para>The base class for most Xamarin.Forms on-screen elements. Provides most properties, events, and methods for presenting an item on screen.</para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="AnchorX">
+ <MemberSignature Language="C#" Value="public double AnchorX { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 AnchorX" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the X component of the center point for any transform, relative to the bounds of the element. This is a bindable property.</summary>
+ <value>The value that declares the X component of the transform. The default value is 0.5.</value>
+ <remarks>To be added.</remarks>
+ <altmember cref="P:Xamarin.Forms.VisualElement.AnchorY" />
+ </Docs>
+ </Member>
+ <Member MemberName="AnchorXProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty AnchorXProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty AnchorXProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the AnchorX bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AnchorY">
+ <MemberSignature Language="C#" Value="public double AnchorY { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 AnchorY" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the Y component of the center point for any transform, relative to the bounds of the element. This is a bindable property.</summary>
+ <value>The value that declares the Y component of the transform. The default value is 0.5.</value>
+ <remarks>To be added.</remarks>
+ <altmember cref="P:Xamarin.Forms.VisualElement.AnchorX" />
+ </Docs>
+ </Member>
+ <Member MemberName="AnchorYProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty AnchorYProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty AnchorYProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the AnchorY bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BackgroundColor">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Color BackgroundColor { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Color BackgroundColor" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Color</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the color which will fill the background of a VisualElement. This is a bindable property.</summary>
+ <value>The color that is used to fill the background of a VisualElement. The default is <see cref="P:Xamarin.Forms.Color.Default" />.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BackgroundColorProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty BackgroundColorProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty BackgroundColorProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the BackgroundColor bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BatchBegin">
+ <MemberSignature Language="C#" Value="public void BatchBegin ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void BatchBegin() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Signals the start of a batch of changes to the elements properties.</summary>
+ <remarks>Application authors will not generally need to batch updates manually as the animation framework will do this for them.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BatchCommit">
+ <MemberSignature Language="C#" Value="public void BatchCommit ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance void BatchCommit() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Signals the end of a batch of commands to the element and that those commands should now be committed.</summary>
+ <remarks>This method merely ensures that updates sent during the batch have been committed. It does not ensure that they were not committed before calling this.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Behaviors">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.Behavior&gt; Behaviors { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Behavior&gt; Behaviors" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.Behavior&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the list of Behavior associated to this element. This is a bindable propery.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="BehaviorsProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty BehaviorsProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty BehaviorsProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Behaviors bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Bounds">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Rectangle Bounds { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Rectangle Bounds" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Rectangle</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the bounds of the element.</summary>
+ <value>The bounds of an element, in device-independent units.</value>
+ <remarks>Bounds is assigned during the Layout cycle by a call to <see cref="M:Xamarin.Forms.VisualElement.Layout(Xamarin.Forms.Rectangle)" />.</remarks>
+ <altmember cref="P:Xamarin.Forms.VisualElement.WidthRequest" />
+ <altmember cref="P:Xamarin.Forms.VisualElement.HeightRequest" />
+ </Docs>
+ </Member>
+ <Member MemberName="ChildrenReordered">
+ <MemberSignature Language="C#" Value="public event EventHandler ChildrenReordered;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler ChildrenReordered" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs when the Children of a VisualElement have been re-ordered.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Focus">
+ <MemberSignature Language="C#" Value="public bool Focus ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance bool Focus() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Attemps to set focus to this element.</summary>
+ <returns>
+ <see langword="true" /> if the keyboard focus was set to this element; <see langword="false" /> if the call to this method did not force a focus change.</returns>
+ <remarks>Element must be able to receive focus for this to work. Calling Focus on offscreen or unrealized elements has undefined behavior.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Focused">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.FocusEventArgs&gt; Focused;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.FocusEventArgs&gt; Focused" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.FocusEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs when the element receives focus.</summary>
+ <remarks>Focused event is raised whenever the VisualElement receives focus. This event is not bubbled through the Forms stack and is received directly from the native control. This event is emitted by the IsFocusedProperty setter.</remarks>
+ <altmember cref="P:Xamarin.Forms.VisualElement.IsFocused" />
+ <altmember cref="M:Xamarin.Forms.VisualElement.Focus()" />
+ </Docs>
+ </Member>
+ <Member MemberName="GetSizeRequest">
+ <MemberSignature Language="C#" Value="public virtual Xamarin.Forms.SizeRequest GetSizeRequest (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance valuetype Xamarin.Forms.SizeRequest GetSizeRequest(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use Measure")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">The available width that a parent element can allocated to a child. Value will be between 0 and double.PositiveInfinity.</param>
+ <param name="heightConstraint">The available height that a parent element can allocated to a child. Value will be between 0 and double.PositiveInfinity.</param>
+ <summary>Returns the <see cref="T:Xamarin.Forms.SizeRequest" /> of the element. Calling this method begins the measure pass of a layout cycle.</summary>
+ <returns>A <see cref="T:Xamarin.Forms.SizeRequest" /> which contains a requested size and a minimum size.</returns>
+ <remarks>Calling GetSizeRequest causes a measure pass to occur for the subtree of elements it is called on. It is ideal to only call GetSizeRequest when needed as excessive calls can negatively impact the performance of your app. Overriding GetSizeRequest should only be done if you want to ignore Width/HeightRequest. More likely a subclass would wish to override <see cref="M:Xamarin.Forms.VisualElement.OnSizeRequest (double, double)" />.</remarks>
+ <altmember cref="M:Xamarin.Forms.OnSizeRequest (double, double)" />
+ </Docs>
+ </Member>
+ <Member MemberName="Height">
+ <MemberSignature Language="C#" Value="public double Height { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Height" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the current rendered height of this element. This is a read-only bindable property.</summary>
+ <value>The renderered height of this element.</value>
+ <remarks>The height of an element is set during the Layout phase.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HeightProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HeightProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HeightProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Height bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HeightRequest">
+ <MemberSignature Language="C#" Value="public double HeightRequest { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 HeightRequest" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the desired height override of this element.</summary>
+ <value>The height this element desires to be.</value>
+ <remarks>HeightRequest does not immediately change the Bounds of a VisualElement, however setting the HeightRequest will change the result of calls to GetSizeRequest, which will in turn modify the final size the element receives during a layout cycle.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HeightRequestProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HeightRequestProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HeightRequestProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the HeightRequest property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="InputTransparent">
+ <MemberSignature Language="C#" Value="public bool InputTransparent { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool InputTransparent" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value indicating whether this element should be involved in the user interaction cycle. This is a bindable property.</summary>
+ <value>
+ <see langword="false" /> if the element should receive input; <see langword="true" /> if element should not receive input and should, instead, pass inputs to the element below. Default is <see langword="false" />.</value>
+ <remarks>Setting InputTransparent is not the same as setting IsEnabled to false. Setting InputTransparent only disables inputs and instead causes them to be passed to the VisualElement below the element. Usually this is the parent of the element.</remarks>
+ <altmember cref="P:Xamarin.Forms.VisualElement.IsEnabled" />
+ </Docs>
+ </Member>
+ <Member MemberName="InputTransparentProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty InputTransparentProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty InputTransparentProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the InputTransparent bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="InvalidateMeasure">
+ <MemberSignature Language="C#" Value="protected virtual void InvalidateMeasure ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void InvalidateMeasure() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Method that is called to invalidate the layout of this <see cref="T:Xamarin.Forms.VisualElement" />. Raises the <see cref="E:Xamarin.Forms.VisualElement.MeasureInvalidated" /> event.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsEnabled">
+ <MemberSignature Language="C#" Value="public bool IsEnabled { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsEnabled" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value indicating whether this element is enabled in the user interface. This is a bindable property.</summary>
+ <value>
+ <see langword="true" /> if the element is enabled; otherwise, <see langword="false" />. The default value is <see langword="true" /></value>
+ <remarks>
+ <para>
+ Elements that are not enabled do not participate in hit detection, and therefore will not receive focus or emit input events.
+ </para>
+ <para>
+ The following example shows a handler on a button which will then set IsEnabled to false on another button.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+ public partial class ButtonDisableExample {
+ void BuildButtons ()
+ {
+ Button button1 = new Button {Text = "New button"};
+ Button button2 = new Button {Text = "Disabled on click"};
+ button1.Activated += (o, e) => button2.IsEnabled = false;
+ }
+ }
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsEnabledProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsEnabledProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsEnabledProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the IsEnabled bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsFocused">
+ <MemberSignature Language="C#" Value="public bool IsFocused { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsFocused" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value indicating whether this element is focused currently. This is a bindable property.</summary>
+ <value>
+ <see langword="true" /> if the element is focused; otherwise, <see langword="false" />.</value>
+ <remarks>
+ <para>
+ Applications may have multiple focuses depending on the implementation of the underlying toolkit. Menus and modals in particular may leave multiple items with focus.
+ </para>
+ <para>
+ The following example shows conditionally setting a background color based on the focus state.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+ void UpdateBackground ()
+ {
+ if (myElement.IsFocused)
+ myElement.BackgroundColor = Color.Red;
+ else
+ myElement.BackgroundColor = Color.Blue;
+ }
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsFocusedProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsFocusedProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsFocusedProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the IsFocused bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsVisible">
+ <MemberSignature Language="C#" Value="public bool IsVisible { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsVisible" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that determines whether this elements should be part of the visual tree or not. This is a bindable property.</summary>
+ <value>
+ <see langword="true" /> if the element should be rendered; otherwise, <see langword="false" />. Default value is <see langword="true" />.</value>
+ <remarks>
+ <para>Setting IsVisible to false will remove the element from the visual tree. The element will no longer take up space in layouts or be eligle to receive any kind of input event.</para>
+ <para>
+ The following example shows a stack where the middle element is toggled when a button is activated.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+ partial class LabelToggle {
+ Label label;
+
+ void Build ()
+ {
+ var firstView = new Button {Text = "Tap Me"};
+ label = new Label {Text = "I can be toggled"};
+ var thirdView = new Image {Source = "image.png"};
+
+ firstView.Activated += OnButtonActivated;
+
+ Content = new StackLayout {
+ Children {
+ firstView,
+ label,
+ thirdView
+ }
+ };
+ }
+
+ void OnButtonActivated (object sender, EventArgs args)
+ {
+ label.IsVisible = !label.IsVisible;
+ }
+ }
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsVisibleProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsVisibleProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsVisibleProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the IsVisible bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Layout">
+ <MemberSignature Language="C#" Value="public void Layout (Xamarin.Forms.Rectangle bounds);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void Layout(valuetype Xamarin.Forms.Rectangle bounds) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="bounds" Type="Xamarin.Forms.Rectangle" />
+ </Parameters>
+ <Docs>
+ <param name="bounds">The new bounds of the element.</param>
+ <summary>Updates the bounds of the element during the layout cycle.</summary>
+ <remarks>Calling Layout will trigger a layout cycle for the sub-tree of this element.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Measure">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.SizeRequest Measure (double widthConstraint, double heightConstraint, Xamarin.Forms.MeasureFlags flags = Xamarin.Forms.MeasureFlags.None);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance valuetype Xamarin.Forms.SizeRequest Measure(float64 widthConstraint, float64 heightConstraint, valuetype Xamarin.Forms.MeasureFlags flags) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ <Parameter Name="flags" Type="Xamarin.Forms.MeasureFlags" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">To be added.</param>
+ <param name="heightConstraint">To be added.</param>
+ <param name="flags">To be added.</param>
+ <summary>Measures a visual element for layout operations.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MeasureInvalidated">
+ <MemberSignature Language="C#" Value="public event EventHandler MeasureInvalidated;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler MeasureInvalidated" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the layout of a visual element is invalidated.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MinimumHeightRequest">
+ <MemberSignature Language="C#" Value="public double MinimumHeightRequest { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 MinimumHeightRequest" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value which overrides the minimum height the element will request during layout.</summary>
+ <value>The minimum height the element requires. Default value is -1.</value>
+ <remarks>
+ <para>
+ MinimumHeightRequest is used to override the results of a call to <see cref="M:Xamarin.Forms.VisualElement.GetSizeRequest (double, double)" /> by setting the minimum height property. This causes overflow handling to shrink this element to its minimum height before elements who do not have a minimum size set.
+ </para>
+ <para>
+ The following example sets the MinimumHeightRequest to enable an image to shrink below it's normal size.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+ void Build (string veryLongString)
+ {
+ var label = new Label {Text = veryLongString};
+ var image = new Image {Source = "image500x500.png"};
+
+ image.MinimumHeightRequest = 20;
+ Content = new StackLayout {
+ Children {
+ label,
+ image
+ }
+ };
+ }
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MinimumHeightRequestProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty MinimumHeightRequestProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty MinimumHeightRequestProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the MinimumHeightRequest property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MinimumWidthRequest">
+ <MemberSignature Language="C#" Value="public double MinimumWidthRequest { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 MinimumWidthRequest" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value which overrides the minimum width the element will request during layout.</summary>
+ <value>The minimum width the element requires. Default value is -1.</value>
+ <remarks>
+ <para>
+ MinimumWidthRequest is used to override the results of a call to <see cref="M:Xamarin.Forms.VisualElement.GetSizeRequest (double, double)" /> by setting the minimum width property. This causes overflow handling to shrink this element to its minimum width before elements who do not have a minimum size set.
+ </para>
+ <para>
+ The following example sets the MinimumWidthRequest to enable an image to shrink below it's normal size.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+ void Build (string veryLongString)
+ {
+ var label = new Label {Text = veryLongString};
+ var image = new Image {Source = "image500x500.png"};
+
+ image.MinimumWidthRequest = 20;
+ Content = new StackLayout {
+ Orientation = StackOrientation.Horizontal,
+ Children {
+ label,
+ image
+ }
+ };
+ }
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MinimumWidthRequestProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty MinimumWidthRequestProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty MinimumWidthRequestProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the MinimumWidthRequest property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Navigation">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.INavigation Navigation { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.INavigation Navigation" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.INavigation</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the context aware navigation interface for the element.</summary>
+ <value>An <see cref="T:Xamarin.Forms.INavigation" /> that allows for navigation using the ancestral navigation implementor.</value>
+ <remarks>
+ <para>
+ Use the Navigation property to perform navigation from any element. If the element has not yet been added to a tree which contains a navigation implementor, the actions are queued up until it is.
+ </para>
+ <para>
+ The following example navigates to a new page created in the callback of a buttons <see cref="E:Xamarin.Forms.VisualElement.Activated" /> event.</para>
+ <example>
+ <code lang="C#"><![CDATA[
+ partial class NavigationTest {
+ void BuildContent
+ {
+ Button button = new Button {Text = "Tap to Navigate"};
+ button.Activated += OnButtonActivated;
+ }
+
+ void OnButtonActivated (object sender, EventArgs args)
+ {
+ Button button = (Button) sender;
+ Page newPage = new ContentPage {
+ Content = new Label {Text = "Hello New Page"}
+ };
+
+ button.Navigation.Push (newPage);
+ }
+ }
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="NavigationProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty NavigationProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty NavigationProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Navigation bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnChildAdded">
+ <MemberSignature Language="C#" Value="protected override void OnChildAdded (Xamarin.Forms.Element child);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnChildAdded(class Xamarin.Forms.Element child) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="child" Type="Xamarin.Forms.Element" />
+ </Parameters>
+ <Docs>
+ <param name="child">To be added.</param>
+ <summary>Application developers can override this method to respond when a child is added.</summary>
+ <remarks>Application developers who override this method must call base.OnChildAdded before performing any other actions in their override.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnChildRemoved">
+ <MemberSignature Language="C#" Value="protected override void OnChildRemoved (Xamarin.Forms.Element child);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnChildRemoved(class Xamarin.Forms.Element child) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="child" Type="Xamarin.Forms.Element" />
+ </Parameters>
+ <Docs>
+ <param name="child">To be added.</param>
+ <summary>Application developers can override this method to respond when a child is removed.</summary>
+ <remarks>Application developers who override this method must call base.OnChildRemoved before performing any other actions in their override.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnChildrenReordered">
+ <MemberSignature Language="C#" Value="protected void OnChildrenReordered ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig instance void OnChildrenReordered() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invoked whenever the <see cref="E:Xamarin.Forms.VisualElement.ChildrenReordered" /> event is about to be emitted. Implement this method to add class handling for this event.</summary>
+ <remarks>This method has no default implementation. You should still call the base implementation in case an intermediate class has implemented this method.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnMeasure">
+ <MemberSignature Language="C#" Value="protected virtual Xamarin.Forms.SizeRequest OnMeasure (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance valuetype Xamarin.Forms.SizeRequest OnMeasure(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">To be added.</param>
+ <param name="heightConstraint">To be added.</param>
+ <summary>Method that is called when a layout measurement happens.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnParentSet">
+ <MemberSignature Language="C#" Value="protected override void OnParentSet ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnParentSet() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invoked whenever the Parent of an element is set. Implement this method in order to add behavior when the element is added to a parent.</summary>
+ <remarks>It is required to call the base implementation.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeAllocated">
+ <MemberSignature Language="C#" Value="protected virtual void OnSizeAllocated (double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance void OnSizeAllocated(float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="width">The new width of the element.</param>
+ <param name="height">The new height of the element.</param>
+ <summary>This method is called when the size of the element is set during a layout cycle. This method is called directly before the <see cref="E:Xamarin.Forms.VisualElement.SizeChanged" /> event is emitted. Implement this method to add class handling for this event.</summary>
+ <remarks>This method has no default implementation. You should still call the base implementation in case an intermediate class has implemented this method. Most layouts will want to implement this method in order to layout their children during a layout cycle.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSizeRequest">
+ <MemberSignature Language="C#" Value="protected virtual Xamarin.Forms.SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig newslot virtual instance valuetype Xamarin.Forms.SizeRequest OnSizeRequest(float64 widthConstraint, float64 heightConstraint) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Obsolete("Use OnMeasure")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.SizeRequest</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="widthConstraint" Type="System.Double" />
+ <Parameter Name="heightConstraint" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="widthConstraint">The available width for the element to use.</param>
+ <param name="heightConstraint">The available height for the element to use.</param>
+ <summary>This method is called during the measure pass of a layout cycle to get the desired size of an element.</summary>
+ <returns>A <see cref="T:Xamarin.Forms.SizeRequest&gt;" /> which contains the desired size of the element.</returns>
+ <remarks>The results of this method will be (-1, -1) if the element has not yet been realized with a platform specific backing control. Overriding this method does not require a call to the base class so long as a valid SizeRequest is returned.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Opacity">
+ <MemberSignature Language="C#" Value="public double Opacity { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Opacity" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the opacity value applied to the element when it is rendered. This is a bindable property.</summary>
+ <value>The opacity value. Default opacity is 1.0. Values will be clamped between 0 and 1 on set.</value>
+ <remarks>
+ <para>
+ The opacity value has no effect unless IsVisible is <see langword="true" />. Opacity is inherited down the element hierarchy. If a parent has 0.5 opacity, and a child has 0.5 opacity, the child will render with an effective 0.25 opacity. Setting opacity to 0 has undefined behavior with input elements.
+ </para>
+ <para>
+ The following example sets the opacity of a layout to 0.5 and the opacity of one of its children to 0.5, making the child 25% opaque.
+ </para>
+ <example>
+ <code lang="C#"><![CDATA[
+ StackLayout stack = new StackLayout ();
+ Button button1 = new Button {Text="A Button"};
+ Button button2 = new Button {Text="Another Button"};
+
+ stack.Children.Add (button1);
+ stack.Children.Add (button2);
+
+ // The stack and everything in it will become 50% opaque
+ stack.Opacity = 0.5;
+
+ // button1 will become 25% opaque while the stack and button2 remane 50% opaque
+ button1.Opacity = 0.5;
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OpacityProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty OpacityProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty OpacityProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Opacity bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Resources">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.ResourceDictionary Resources { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.ResourceDictionary Resources" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.ResourceDictionary</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the local resource dictionary.</summary>
+ <value>The current resource dictionary, where resources are stored by key.</value>
+ <remarks>
+ <para>In XAML, resource dictionaries are filled with key/value pairs that are specified in XML and consequently created at run time. The keys in the resource dictionary are specified with the <c>x:Key</c> attribute of the XML tag for the type to create. An object of that type is created, and is initialized with the property and field values that are specified either by additional attributes or by nested tags, both of which, when present are simply string representations of the property or field names. The object is then inserted into the <see cref="T:Xamarin.Forms.ResourceDictionary" /> for the enclosing type at runtime.</para>
+ <example>
+ <para>For example, the XAML below, taken from the <format type="text/html"><a href="http://developer.xamarin.com/guides/cross-platform/xamarin-forms/xaml-for-xamarin-forms/">XAML for Xamarin.Forms</a></format> series, creates a resource dictionary that contains <see cref="T:Xamarin.Forms.LayoutOptions" /> object constants that can be used for any <see cref="T:Xamarin.Forms.Layout" /> objects that are added to the surrounding <see cref="T:Xamarin.Forms.ContentPage" />:</para>
+ <code><![CDATA[
+<ContentPage.Resources>
+ <ResourceDictionary>
+ <LayoutOptions x:Key="horzOptions"
+ Alignment="Center" />
+
+ <LayoutOptions x:Key="vertOptions"
+ Alignment="Center"
+ Expands="True" />
+ </ResourceDictionary>
+</ContentPage.Resources>
+]]></code>
+ <para>Note that the above snippet is only valid when nested within a <c>&lt;ContentPage&gt;...&lt;/ContentPage&gt;</c> tag pair. Within that pair, the app developer can use both of the <c>horzOptions</c> and <c>vertOptions</c> keys to specify values for properties of type <see cref="T:Xamarin.Forms.LayoutOptions" /> by using the <c>"{...}"</c> static resource syntax. The short example below, also taken from the <format type="text/html"><a href="http://developer.xamarin.com/guides/cross-platform/xamarin-forms/xaml-for-xamarin-forms/">XAML for Xamarin.Forms</a></format> series, illustrates this syntax:</para>
+ <code><![CDATA[
+<Button Text="Do this!"
+ HorizontalOptions="{StaticResource horzOptions}"
+ VerticalOptions="{StaticResource vertOptions}"
+ BorderWidth="3"
+ Rotation="-15"
+ TextColor="Red"
+ Font="Large" />]]></code>
+ <para>Resource dictionaries and their associated XML provide the application developer with a convenient method to reuse code inside the XAML compile-time and run-time engines.</para>
+ </example>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Rotation">
+ <MemberSignature Language="C#" Value="public double Rotation { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Rotation" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the rotation about the Z-axis (affine rotation) when the element is rendered.</summary>
+ <value>The rotation about the Z-axis in degrees.</value>
+ <remarks>Rotation is applied relative to <see cref="P:Xamarin.Forms.VisualElement.AnchorX" /> and <see cref="P:Xamarin.Forms.VisualElement.AnchorY" />.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RotationProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty RotationProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty RotationProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Rotation bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RotationX">
+ <MemberSignature Language="C#" Value="public double RotationX { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 RotationX" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the rotation about the X-axis (perspective rotation) when the element is rendered.</summary>
+ <value>The rotation about the X-axis in degrees.</value>
+ <remarks>RotationX is applied relative to <see cref="P:Xamarin.Forms.VisualElement.AnchorX" /> and <see cref="P:Xamarin.Forms.VisualElement.AnchorY" />.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RotationXProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty RotationXProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty RotationXProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the RotationX bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RotationY">
+ <MemberSignature Language="C#" Value="public double RotationY { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 RotationY" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the rotation about the Y-axis (perspective rotation) when the element is rendered.</summary>
+ <value>The rotation about the Y-axis in degrees.</value>
+ <remarks>RotationY is applied relative to <see cref="P:Xamarin.Forms.VisualElement.AnchorX" /> and <see cref="P:Xamarin.Forms.VisualElement.AnchorY" />.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="RotationYProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty RotationYProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty RotationYProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the RotationY bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Scale">
+ <MemberSignature Language="C#" Value="public double Scale { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Scale" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the scale factor applied to the element.</summary>
+ <value>The scale factor of the element. Default value is 1.0.</value>
+ <remarks>Scale is applied relative to <see cref="P:Xamarin.Forms.VisualElement.AnchorX" /> and <see cref="P:Xamarin.Forms.VisualElement.AnchorY" />.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ScaleProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty ScaleProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty ScaleProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Scale bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SizeAllocated">
+ <MemberSignature Language="C#" Value="protected void SizeAllocated (double width, double height);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig instance void SizeAllocated(float64 width, float64 height) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="width" Type="System.Double" />
+ <Parameter Name="height" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="width">The newly allocated width.</param>
+ <param name="height">The newly allocated height.</param>
+ <summary>SizeAllocated is called during a layout cycle to signal the start of a sub-tree layout.</summary>
+ <remarks>Calling SizeAllocated will start a new layout cycle on the children of the element. Excessive calls to SizeAllocated may cause performance problems.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SizeChanged">
+ <MemberSignature Language="C#" Value="public event EventHandler SizeChanged;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler SizeChanged" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs when either the Width or the Height properties change value on this element.</summary>
+ <remarks>Classes should implement <see cref="M:Xamarin.Forms.VisualElement.OnSizeAllocated (double, double)" /> if they wish to respond to size change events directly.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Style">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Style Style { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Style Style" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Style</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the style that defines how this visual element is displayed.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="StyleClass">
+ <MemberSignature Language="C#" Value="public string StyleClass { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string StyleClass" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="StyleProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty StyleProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty StyleProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the Style property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TranslationX">
+ <MemberSignature Language="C#" Value="public double TranslationX { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 TranslationX" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the X translation delta of the element.</summary>
+ <value>The amount to translate the element.</value>
+ <remarks>Translation is applied post layout. It is particularly good for applying animations. Translating an element outside the bounds of its parent container may prevent inputs from working.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TranslationXProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TranslationXProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TranslationXProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the TranslationX bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TranslationY">
+ <MemberSignature Language="C#" Value="public double TranslationY { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 TranslationY" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the Y translation delta of the element.</summary>
+ <value>The amount to translate the element.</value>
+ <remarks>Translation is applied post layout. It is particularly good for applying animations. Translating an element outside the bounds of its parent container may prevent inputs from working.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TranslationYProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TranslationYProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TranslationYProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the TranslationY bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Triggers">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.TriggerBase&gt; Triggers { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.TriggerBase&gt; Triggers" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.TriggerBase&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the list of Trigger associated to this element. This is a bindable property.</summary>
+ <value>
+ </value>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TriggersProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TriggersProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TriggersProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Triggers bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Unfocus">
+ <MemberSignature Language="C#" Value="public void Unfocus ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void Unfocus() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Unsets focus to this element.</summary>
+ <remarks>Element must already have focus for this to have any effect.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Unfocused">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.FocusEventArgs&gt; Unfocused;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.FocusEventArgs&gt; Unfocused" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.FocusEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Occurs when the element loses focus.</summary>
+ <remarks>Unfocused event is raised whenever the VisualElement loses focus. This event is not bubbled through the Forms stack and is received directly from the native control. This event is emitted by the IsFocusedProperty setter.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Width">
+ <MemberSignature Language="C#" Value="public double Width { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Width" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the current rendered width of this element. This is a read-only bindable property.</summary>
+ <value>The renderered width of this element.</value>
+ <remarks>The width of an element is set during the Layout phase.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="WidthProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty WidthProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty WidthProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Width bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="WidthRequest">
+ <MemberSignature Language="C#" Value="public double WidthRequest { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 WidthRequest" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the desired width override of this element.</summary>
+ <value>The width this element desires to be.</value>
+ <remarks>WidthRequest does not immediately change the Bounds of a VisualElement, however setting the WidthRequest will change the result of calls to GetSizeRequest, which will in turn modify the final size the element receives during a layout cycle.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="WidthRequestProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty WidthRequestProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty WidthRequestProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the WidthRequest property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="X">
+ <MemberSignature Language="C#" Value="public double X { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 X" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the current X position of this element. This is a read-only bindable property.</summary>
+ <value>The X position of this element relative to its parents bounds.</value>
+ <remarks>The x value of an element is set during the Layout phase.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.IVisualElementController.NativeSizeChanged">
+ <MemberSignature Language="C#" Value="void IVisualElementController.NativeSizeChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance void Xamarin.Forms.IVisualElementController.NativeSizeChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Invalidates the measure when the native size of the element changes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="XProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty XProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty XProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the X bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Y">
+ <MemberSignature Language="C#" Value="public double Y { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Y" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the current Y position of this element. This is a read-only bindable property.</summary>
+ <value>The Y position of this element relative to its parents bounds.</value>
+ <remarks>The y value of an element is set during the Layout phase.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="YProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty YProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty YProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the Y bindable property.</summary>
+ <remarks>
+ </remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigatedEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigatedEventArgs.xml
new file mode 100644
index 00000000..e4254cfe
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigatedEventArgs.xml
@@ -0,0 +1,65 @@
+<Type Name="WebNavigatedEventArgs" FullName="Xamarin.Forms.WebNavigatedEventArgs">
+ <TypeSignature Language="C#" Value="public class WebNavigatedEventArgs : Xamarin.Forms.WebNavigationEventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit WebNavigatedEventArgs extends Xamarin.Forms.WebNavigationEventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.WebNavigationEventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Class that contains arguments for the event that is raised after web navigation completes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public WebNavigatedEventArgs (Xamarin.Forms.WebNavigationEvent navigationEvent, Xamarin.Forms.WebViewSource source, string url, Xamarin.Forms.WebNavigationResult result);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(valuetype Xamarin.Forms.WebNavigationEvent navigationEvent, class Xamarin.Forms.WebViewSource source, string url, valuetype Xamarin.Forms.WebNavigationResult result) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="navigationEvent" Type="Xamarin.Forms.WebNavigationEvent" />
+ <Parameter Name="source" Type="Xamarin.Forms.WebViewSource" />
+ <Parameter Name="url" Type="System.String" />
+ <Parameter Name="result" Type="Xamarin.Forms.WebNavigationResult" />
+ </Parameters>
+ <Docs>
+ <param name="navigationEvent">To be added.</param>
+ <param name="source">To be added.</param>
+ <param name="url">To be added.</param>
+ <param name="result">To be added.</param>
+ <summary>Initializes a new <see cref="E:Xamarin.Forms.WebNavigatedEventArgs" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Result">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.WebNavigationResult Result { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.WebNavigationResult Result" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.WebNavigationResult</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that describes the result of the navigation.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigatingEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigatingEventArgs.xml
new file mode 100644
index 00000000..b0f34427
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigatingEventArgs.xml
@@ -0,0 +1,63 @@
+<Type Name="WebNavigatingEventArgs" FullName="Xamarin.Forms.WebNavigatingEventArgs">
+ <TypeSignature Language="C#" Value="public class WebNavigatingEventArgs : Xamarin.Forms.WebNavigationEventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit WebNavigatingEventArgs extends Xamarin.Forms.WebNavigationEventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.WebNavigationEventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Class that contains arguments for the event that is raised after web navigation begins.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public WebNavigatingEventArgs (Xamarin.Forms.WebNavigationEvent navigationEvent, Xamarin.Forms.WebViewSource source, string url);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(valuetype Xamarin.Forms.WebNavigationEvent navigationEvent, class Xamarin.Forms.WebViewSource source, string url) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="navigationEvent" Type="Xamarin.Forms.WebNavigationEvent" />
+ <Parameter Name="source" Type="Xamarin.Forms.WebViewSource" />
+ <Parameter Name="url" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="navigationEvent">To be added.</param>
+ <param name="source">To be added.</param>
+ <param name="url">To be added.</param>
+ <summary>Initializes a new <see cref="E:Xamarin.Forms.WebNavigatingEventArgs" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Cancel">
+ <MemberSignature Language="C#" Value="public bool Cancel { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool Cancel" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that indicates whether or not to cancel the navigation.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigationEvent.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigationEvent.xml
new file mode 100644
index 00000000..13e3eff9
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigationEvent.xml
@@ -0,0 +1,88 @@
+<Type Name="WebNavigationEvent" FullName="Xamarin.Forms.WebNavigationEvent">
+ <TypeSignature Language="C#" Value="public enum WebNavigationEvent" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed WebNavigationEvent extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Contains values that indicate why a navigation event was raised.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Back">
+ <MemberSignature Language="C#" Value="Back" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.WebNavigationEvent Back = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.WebNavigationEvent</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that the navigation resulted from the user going back to a previous page in the navigation history.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Forward">
+ <MemberSignature Language="C#" Value="Forward" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.WebNavigationEvent Forward = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.WebNavigationEvent</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that the navigation resulted from the user going forward to a later page in the navigation history.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="NewPage">
+ <MemberSignature Language="C#" Value="NewPage" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.WebNavigationEvent NewPage = int32(3)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.WebNavigationEvent</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that the navigation was to a preiously unvisited page, according to the navigation history.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Refresh">
+ <MemberSignature Language="C#" Value="Refresh" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.WebNavigationEvent Refresh = int32(4)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.WebNavigationEvent</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Indicates that the navigation resulted from a page refresh.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigationEventArgs.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigationEventArgs.xml
new file mode 100644
index 00000000..edfa467a
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigationEventArgs.xml
@@ -0,0 +1,101 @@
+<Type Name="WebNavigationEventArgs" FullName="Xamarin.Forms.WebNavigationEventArgs">
+ <TypeSignature Language="C#" Value="public class WebNavigationEventArgs : EventArgs" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit WebNavigationEventArgs extends System.EventArgs" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.EventArgs</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>TClass that contains arguments for the event that is when web navigation begins.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected WebNavigationEventArgs (Xamarin.Forms.WebNavigationEvent navigationEvent, Xamarin.Forms.WebViewSource source, string url);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor(valuetype Xamarin.Forms.WebNavigationEvent navigationEvent, class Xamarin.Forms.WebViewSource source, string url) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="navigationEvent" Type="Xamarin.Forms.WebNavigationEvent" />
+ <Parameter Name="source" Type="Xamarin.Forms.WebViewSource" />
+ <Parameter Name="url" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="navigationEvent">To be added.</param>
+ <param name="source">To be added.</param>
+ <param name="url">To be added.</param>
+ <summary>Initializes a new <see cref="T:Xamarin.Forms.WebNavigationEventArgs" /> instance.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="NavigationEvent">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.WebNavigationEvent NavigationEvent { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.WebNavigationEvent NavigationEvent" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.WebNavigationEvent</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the navigation event that was raised.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Source">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.WebViewSource Source { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.WebViewSource Source" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.WebViewSource</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the element that performed the navigation.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Url">
+ <MemberSignature Language="C#" Value="public string Url { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Url" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The destination of the navigation.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigationResult.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigationResult.xml
new file mode 100644
index 00000000..fff388a7
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebNavigationResult.xml
@@ -0,0 +1,88 @@
+<Type Name="WebNavigationResult" FullName="Xamarin.Forms.WebNavigationResult">
+ <TypeSignature Language="C#" Value="public enum WebNavigationResult" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed WebNavigationResult extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumerates values that indicate the outcome of a web navigation.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Cancel">
+ <MemberSignature Language="C#" Value="Cancel" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.WebNavigationResult Cancel = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.WebNavigationResult</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The navigation was cancelled.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Failure">
+ <MemberSignature Language="C#" Value="Failure" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.WebNavigationResult Failure = int32(4)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.WebNavigationResult</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The navigation failed.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Success">
+ <MemberSignature Language="C#" Value="Success" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.WebNavigationResult Success = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.WebNavigationResult</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The navigation succeeded.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Timeout">
+ <MemberSignature Language="C#" Value="Timeout" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.WebNavigationResult Timeout = int32(3)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.WebNavigationResult</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The navigation timed out.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/WebView.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebView.xml
new file mode 100644
index 00000000..945ba719
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebView.xml
@@ -0,0 +1,381 @@
+<Type Name="WebView" FullName="Xamarin.Forms.WebView">
+ <TypeSignature Language="C#" Value="public class WebView : Xamarin.Forms.View" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit WebView extends Xamarin.Forms.View" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.RenderWith(typeof(Xamarin.Forms.Platform._WebViewRenderer))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.View" /> that presents HTML content.</summary>
+ <remarks>
+ <para>The following example shows a basic use.</para>
+ <example>
+ <code lang="C#"><![CDATA[using System;
+using Xamarin.Forms;
+
+namespace FormsGallery
+{
+ class WebViewDemoPage : ContentPage
+ {
+ public WebViewDemoPage()
+ {
+ Label header = new Label
+ {
+ Text = "WebView",
+ FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ WebView webView = new WebView
+ {
+ Source = new UrlWebViewSource
+ {
+ Url = "http://blog.xamarin.com/",
+ },
+ VerticalOptions = LayoutOptions.FillAndExpand
+ };
+
+ // Accomodate iPhone status bar.
+ this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
+
+ // Build the page.
+ this.Content = new StackLayout
+ {
+ Children =
+ {
+ header,
+ webView
+ }
+ };
+ }
+ }
+}]]></code>
+ </example>
+ <para>
+ <img href="WebView.TripleScreenShot.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public WebView ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.WebView" /> element with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanGoBack">
+ <MemberSignature Language="C#" Value="public bool CanGoBack { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool CanGoBack" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that indicates whether the user can navigate to previous pages.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanGoBackProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty CanGoBackProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty CanGoBackProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.WebView.CanGoBack" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanGoForward">
+ <MemberSignature Language="C#" Value="public bool CanGoForward { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool CanGoForward" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets a value that indicates whether the user can navigate forward.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanGoForwardProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty CanGoForwardProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty CanGoForwardProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.WebView.CanGoForward" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Eval">
+ <MemberSignature Language="C#" Value="public void Eval (string script);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void Eval(string script) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="script" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="script">A script to evaluate.</param>
+ <summary>Evaluates the script that is specified by <paramref name="script" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GoBack">
+ <MemberSignature Language="C#" Value="public void GoBack ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void GoBack() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Navigates to the previous page.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GoForward">
+ <MemberSignature Language="C#" Value="public void GoForward ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void GoForward() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Navigates to the next page in the list of visited pages.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Navigated">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.WebNavigatedEventArgs&gt; Navigated;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.WebNavigatedEventArgs&gt; Navigated" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.WebNavigatedEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised after navigation completes.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Navigating">
+ <MemberSignature Language="C#" Value="public event EventHandler&lt;Xamarin.Forms.WebNavigatingEventArgs&gt; Navigating;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler`1&lt;class Xamarin.Forms.WebNavigatingEventArgs&gt; Navigating" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler&lt;Xamarin.Forms.WebNavigatingEventArgs&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when navigation starts.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnBindingContextChanged">
+ <MemberSignature Language="C#" Value="protected override void OnBindingContextChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnBindingContextChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnPropertyChanged">
+ <MemberSignature Language="C#" Value="protected override void OnPropertyChanged (string propertyName);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnPropertyChanged(string propertyName) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="propertyName" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="propertyName">To be added.</param>
+ <summary>Method that is called when <see cref="P:Xamarin.Forms.WebView.Source" /> is changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSourceChanged">
+ <MemberSignature Language="C#" Value="protected void OnSourceChanged (object sender, EventArgs e);" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig instance void OnSourceChanged(object sender, class System.EventArgs e) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sender" Type="System.Object" />
+ <Parameter Name="e" Type="System.EventArgs" />
+ </Parameters>
+ <Docs>
+ <param name="sender">To be added.</param>
+ <param name="e">To be added.</param>
+ <summary>Method that is called when the view source that is specified by the <paramref name="sender" /> parameter is changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Source">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.WebViewSource Source { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.WebViewSource Source" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.WebViewSourceTypeConverter))</AttributeName>
+ </Attribute>
+ </Attributes>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.WebViewSource</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the <see cref="T:Xamarin.Forms.WebViewSource" /> object that represents the location that this <see cref="T:Xamarin.Forms.WebView" /> object displays.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SourceProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty SourceProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty SourceProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Backing store for the <see cref="P:Xamarin.Forms.WebView.Source" /> property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/WebViewSource.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebViewSource.xml
new file mode 100644
index 00000000..2d3ec52a
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebViewSource.xml
@@ -0,0 +1,117 @@
+<Type Name="WebViewSource" FullName="Xamarin.Forms.WebViewSource">
+ <TypeSignature Language="C#" Value="public abstract class WebViewSource : Xamarin.Forms.BindableObject" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit WebViewSource extends Xamarin.Forms.BindableObject" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Abstract class whose subclasses provide the data for a <see cref="T:Xamarin.Forms.WebView" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="protected WebViewSource ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.WebViewSource" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnSourceChanged">
+ <MemberSignature Language="C#" Value="protected void OnSourceChanged ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig instance void OnSourceChanged() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Method that is called when the source is changed.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Implicit">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.WebViewSource op_Implicit (string url);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname class Xamarin.Forms.WebViewSource op_Implicit(string url) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.WebViewSource</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="url" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="url">To be added.</param>
+ <summary>Casts a string that contains a URL to a <see cref="T:Xamarin.Forms.WebViewSource" /> instance.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Implicit">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.WebViewSource op_Implicit (Uri url);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname class Xamarin.Forms.WebViewSource op_Implicit(class System.Uri url) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.WebViewSource</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="url" Type="System.Uri" />
+ </Parameters>
+ <Docs>
+ <param name="url">To be added.</param>
+ <summary>Casts a <see cref="T:System.Uri" /> object to a <see cref="T:Xamarin.Forms.WebViewSource" /> instance.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/WebViewSourceTypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebViewSourceTypeConverter.xml
new file mode 100644
index 00000000..401b9d23
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/WebViewSourceTypeConverter.xml
@@ -0,0 +1,117 @@
+<Type Name="WebViewSourceTypeConverter" FullName="Xamarin.Forms.WebViewSourceTypeConverter">
+ <TypeSignature Language="C#" Value="public class WebViewSourceTypeConverter : Xamarin.Forms.TypeConverter" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit WebViewSourceTypeConverter extends Xamarin.Forms.TypeConverter" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.TypeConverter" /> that converts a string to a <see cref="T:Xamarin.Forms.UrlWebViewSource" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public WebViewSourceTypeConverter ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.WebViewSourceTypeConverter" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="CanConvertFrom">
+ <MemberSignature Language="C#" Value="public override bool CanConvertFrom (Type sourceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool CanConvertFrom(class System.Type sourceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="sourceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="sourceType">To be added.</param>
+ <summary>Returns a Boolean value that indicates whether this <see cref="T:Xamarin.Forms.WebViewSourceTypeConverter" /> can convert the <paramref name="sourceType" /> to a <see cref="T:Xamarin.Forms.WebViewSource" /> instance.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFrom">
+ <MemberSignature Language="C#" Value="public override object ConvertFrom (System.Globalization.CultureInfo culture, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFrom(class System.Globalization.CultureInfo culture, object value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="culture" Type="System.Globalization.CultureInfo" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="culture">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Converts <paramref name="value" /> into a <see cref="T:Xamarin.Forms.WebViewSource" /> by using the specified <paramref name="culture" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConvertFromInvariantString">
+ <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>Returns a web view source for the URL that is contained in <paramref name="value" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/AbsoluteLayout.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/AbsoluteLayout.TripleScreenShot.png
new file mode 100644
index 00000000..a90fdc96
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/AbsoluteLayout.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ActivityIndicator.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ActivityIndicator.TripleScreenShot.png
new file mode 100644
index 00000000..5a4b04cf
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ActivityIndicator.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/BindableObject.BasicInitialization.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/BindableObject.BasicInitialization.png
new file mode 100644
index 00000000..cdcac78a
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/BindableObject.BasicInitialization.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/BoxView.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/BoxView.TripleScreenShot.png
new file mode 100644
index 00000000..b8b17f79
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/BoxView.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Button.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Button.TripleScreenShot.png
new file mode 100644
index 00000000..a427e484
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Button.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/CarouselPage.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/CarouselPage.TripleScreenShot.png
new file mode 100644
index 00000000..f6d3d381
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/CarouselPage.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Cell.Gallery.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Cell.Gallery.png
new file mode 100644
index 00000000..35defd0f
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Cell.Gallery.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ContentView.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ContentView.TripleScreenShot.png
new file mode 100644
index 00000000..70ed3d35
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ContentView.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/DatePicker.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/DatePicker.TripleScreenShot.png
new file mode 100644
index 00000000..eae838ee
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/DatePicker.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.BounceIn.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.BounceIn.png
new file mode 100644
index 00000000..0ab8e013
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.BounceIn.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.BounceOut.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.BounceOut.png
new file mode 100644
index 00000000..4f7af34a
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.BounceOut.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.CubicIn.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.CubicIn.png
new file mode 100644
index 00000000..fe1a5b54
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.CubicIn.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.CubicInOut.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.CubicInOut.png
new file mode 100644
index 00000000..34ba4655
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.CubicInOut.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.CubicOut.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.CubicOut.png
new file mode 100644
index 00000000..e0832c4d
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.CubicOut.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.Linear.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.Linear.png
new file mode 100644
index 00000000..d8a0656f
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.Linear.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SinIn.gif b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SinIn.gif
new file mode 100644
index 00000000..a109beb7
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SinIn.gif
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SinInOut.gif b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SinInOut.gif
new file mode 100644
index 00000000..673c01e0
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SinInOut.gif
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SinOut.gif b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SinOut.gif
new file mode 100644
index 00000000..c801cdde
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SinOut.gif
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SpringIn.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SpringIn.png
new file mode 100644
index 00000000..a2bd19a4
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SpringIn.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SpringOut.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SpringOut.png
new file mode 100644
index 00000000..3ba20638
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Easing.SpringOut.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Editor.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Editor.TripleScreenShot.png
new file mode 100644
index 00000000..bf0046fc
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Editor.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Element.Hierarchy.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Element.Hierarchy.png
new file mode 100644
index 00000000..124ad057
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Element.Hierarchy.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Entry.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Entry.TripleScreenShot.png
new file mode 100644
index 00000000..b01b3573
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Entry.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/EntryCell.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/EntryCell.TripleScreenShot.png
new file mode 100644
index 00000000..96cf5bfd
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/EntryCell.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Frame.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Frame.TripleScreenShot.png
new file mode 100644
index 00000000..293cb7a4
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Frame.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Grid.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Grid.TripleScreenShot.png
new file mode 100644
index 00000000..e5c1521b
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Grid.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/IDefinition.DefinitionCollectionRelation.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/IDefinition.DefinitionCollectionRelation.png
new file mode 100644
index 00000000..633d1a3c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/IDefinition.DefinitionCollectionRelation.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ImageCell.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ImageCell.TripleScreenShot.png
new file mode 100644
index 00000000..ca69bffc
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ImageCell.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Label.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Label.TripleScreenShot.png
new file mode 100644
index 00000000..37b3e5e2
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Label.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Layout.Hierarchy.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Layout.Hierarchy.png
new file mode 100644
index 00000000..d35dc918
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Layout.Hierarchy.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ListView.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ListView.TripleScreenShot.png
new file mode 100644
index 00000000..5b75dc32
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ListView.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/NavigationPage.TitleIcon.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/NavigationPage.TitleIcon.png
new file mode 100644
index 00000000..c0e8053b
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/NavigationPage.TitleIcon.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/OpenGLView.Example.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/OpenGLView.Example.png
new file mode 100644
index 00000000..08371122
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/OpenGLView.Example.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Picker.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Picker.TripleScreenShot.png
new file mode 100644
index 00000000..0540435c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Picker.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ProgressBar.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ProgressBar.TripleScreenShot.png
new file mode 100644
index 00000000..36b6e6d3
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ProgressBar.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ScrollView.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ScrollView.TripleScreenShot.png
new file mode 100644
index 00000000..fb0a91d5
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/ScrollView.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/SearchBar.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/SearchBar.TripleScreenShot.png
new file mode 100644
index 00000000..e450e77c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/SearchBar.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Slider.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Slider.TripleScreenShot.png
new file mode 100644
index 00000000..eb2322ef
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Slider.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/StackLayout.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/StackLayout.TripleScreenShot.png
new file mode 100644
index 00000000..02c3828f
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/StackLayout.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Stepper.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Stepper.TripleScreenShot.png
new file mode 100644
index 00000000..21e478cf
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Stepper.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Switch.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Switch.TripleScreenShot.png
new file mode 100644
index 00000000..fd45baa5
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/Switch.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/SwitchCell.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/SwitchCell.TripleScreenShot.png
new file mode 100644
index 00000000..194b2cfe
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/SwitchCell.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TabbedPage.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TabbedPage.TripleScreenShot.png
new file mode 100644
index 00000000..ad370d6d
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TabbedPage.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableSectionBase.Hierarchy.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableSectionBase.Hierarchy.png
new file mode 100644
index 00000000..3bd2785a
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableSectionBase.Hierarchy.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableView.Sections.Android.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableView.Sections.Android.png
new file mode 100644
index 00000000..62766c1d
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableView.Sections.Android.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableView.Sections.iOS.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableView.Sections.iOS.png
new file mode 100644
index 00000000..882049ed
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableView.Sections.iOS.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableView.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableView.TripleScreenShot.png
new file mode 100644
index 00000000..86855f3e
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TableView.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TextCell.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TextCell.TripleScreenShot.png
new file mode 100644
index 00000000..fd477d35
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TextCell.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TimePicker.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TimePicker.TripleScreenShot.png
new file mode 100644
index 00000000..2ed3307c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TimePicker.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TypeConverter.Hierarchy.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TypeConverter.Hierarchy.png
new file mode 100644
index 00000000..615618a8
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/TypeConverter.Hierarchy.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/WebView.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/WebView.TripleScreenShot.png
new file mode 100644
index 00000000..5e7b6a4b
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/WebView.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/XamarinForms-ns.SharedProject.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/XamarinForms-ns.SharedProject.png
new file mode 100644
index 00000000..02737292
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/XamarinForms-ns.SharedProject.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/XamarinForms-ns.SolutionPad.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/XamarinForms-ns.SolutionPad.png
new file mode 100644
index 00000000..872b2642
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/XamarinForms-ns.SolutionPad.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/XamarinForms-ns.TripleScreenShot.png b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/XamarinForms-ns.TripleScreenShot.png
new file mode 100644
index 00000000..e1a63a89
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/_images/XamarinForms-ns.TripleScreenShot.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Core/index.xml b/docs/Xamarin.Forms.Core/index.xml
new file mode 100644
index 00000000..6c678c8c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/index.xml
@@ -0,0 +1,1079 @@
+<Overview>
+ <Assemblies>
+ <Assembly Name="Xamarin.Forms.Core" Version="2.0.0.0">
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.Default | System.Diagnostics.DebuggableAttribute+DebuggingModes.DisableOptimizations | System.Diagnostics.DebuggableAttribute+DebuggingModes.EnableEditAndContinue | System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints)</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyCompany("Xamarin Inc.")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyConfiguration("")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyCopyright("Copyright © Xamarin Inc. 2013-2015")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyDescription("")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyFileVersion("2.0.0.0")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyProduct("Xamarin.Forms")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyTitle("Xamarin.Forms.Core")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyTrademark("")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.CompilationRelaxations(8)</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Platform.iOS")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Platform.iOS.Classic")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Platform.Android")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Platform.UAP")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Platform.WinRT")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Platform.WinRT.Tablet")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Platform.WinRT.Phone")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Platform.WP8")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("iOSUnitTests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Controls")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Core.Design")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Core.UnitTests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Core.Android.UnitTests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Core.WP8.UnitTests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Xaml")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Maps")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Maps.iOS")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Maps.iOS.Classic")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Maps.Android")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Xaml.UnitTests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.UITests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Core.iOS.UITests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Core.Android.UITests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.iOS.UITests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Android.UITests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Loader")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.UITest.Validator")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Build.Tasks")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Platform")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true)</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.Versioning.TargetFramework(".NETPortable,Version=v4.5,Profile=Profile259", FrameworkDisplayName=".NET Portable Subset")</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Assembly>
+ </Assemblies>
+ <Remarks>To be added.</Remarks>
+ <Copyright>To be added.</Copyright>
+ <Types>
+ <Namespace Name="Xamarin.Forms">
+ <Type Name="AbsoluteLayout" Kind="Class" />
+ <Type Name="AbsoluteLayout+IAbsoluteList`1" DisplayName="AbsoluteLayout+IAbsoluteList&lt;T&gt;" Kind="Interface" />
+ <Type Name="AbsoluteLayoutFlags" Kind="Enumeration" />
+ <Type Name="ActivityIndicator" Kind="Class" />
+ <Type Name="Animation" Kind="Class" />
+ <Type Name="AnimationExtensions" Kind="Class" />
+ <Type Name="Application" Kind="Class" />
+ <Type Name="Aspect" Kind="Enumeration" />
+ <Type Name="BackButtonPressedEventArgs" Kind="Class" />
+ <Type Name="BaseMenuItem" Kind="Class" />
+ <Type Name="Behavior" Kind="Class" />
+ <Type Name="Behavior`1" DisplayName="Behavior&lt;T&gt;" Kind="Class" />
+ <Type Name="BindableObject" Kind="Class" />
+ <Type Name="BindableObjectExtensions" Kind="Class" />
+ <Type Name="BindableProperty" Kind="Class" />
+ <Type Name="BindableProperty+BindingPropertyChangedDelegate" Kind="Delegate" />
+ <Type Name="BindableProperty+BindingPropertyChangedDelegate`1" DisplayName="BindableProperty+BindingPropertyChangedDelegate&lt;TPropertyType&gt;" Kind="Delegate" />
+ <Type Name="BindableProperty+BindingPropertyChangingDelegate" Kind="Delegate" />
+ <Type Name="BindableProperty+BindingPropertyChangingDelegate`1" DisplayName="BindableProperty+BindingPropertyChangingDelegate&lt;TPropertyType&gt;" Kind="Delegate" />
+ <Type Name="BindableProperty+CoerceValueDelegate" Kind="Delegate" />
+ <Type Name="BindableProperty+CoerceValueDelegate`1" DisplayName="BindableProperty+CoerceValueDelegate&lt;TPropertyType&gt;" Kind="Delegate" />
+ <Type Name="BindableProperty+CreateDefaultValueDelegate" Kind="Delegate" />
+ <Type Name="BindableProperty+CreateDefaultValueDelegate`2" DisplayName="BindableProperty+CreateDefaultValueDelegate&lt;TDeclarer,TPropertyType&gt;" Kind="Delegate" />
+ <Type Name="BindableProperty+ValidateValueDelegate" Kind="Delegate" />
+ <Type Name="BindableProperty+ValidateValueDelegate`1" DisplayName="BindableProperty+ValidateValueDelegate&lt;TPropertyType&gt;" Kind="Delegate" />
+ <Type Name="BindablePropertyConverter" Kind="Class" />
+ <Type Name="BindablePropertyKey" Kind="Class" />
+ <Type Name="Binding" Kind="Class" />
+ <Type Name="BindingBase" Kind="Class" />
+ <Type Name="BindingCondition" Kind="Class" />
+ <Type Name="BindingMode" Kind="Enumeration" />
+ <Type Name="BindingTypeConverter" Kind="Class" />
+ <Type Name="BoundsConstraint" Kind="Class" />
+ <Type Name="BoundsTypeConverter" Kind="Class" />
+ <Type Name="BoxView" Kind="Class" />
+ <Type Name="Button" Kind="Class" />
+ <Type Name="CarouselPage" Kind="Class" />
+ <Type Name="CarouselView" Kind="Class" />
+ <Type Name="Cell" Kind="Class" />
+ <Type Name="CollectionSynchronizationCallback" Kind="Delegate" />
+ <Type Name="Color" Kind="Structure" />
+ <Type Name="ColorTypeConverter" Kind="Class" />
+ <Type Name="ColumnDefinition" Kind="Class" />
+ <Type Name="ColumnDefinitionCollection" Kind="Class" />
+ <Type Name="Command" Kind="Class" />
+ <Type Name="Command`1" DisplayName="Command&lt;T&gt;" Kind="Class" />
+ <Type Name="Condition" Kind="Class" />
+ <Type Name="Constraint" Kind="Class" />
+ <Type Name="ConstraintExpression" Kind="Class" />
+ <Type Name="ConstraintType" Kind="Enumeration" />
+ <Type Name="ConstraintTypeConverter" Kind="Class" />
+ <Type Name="ContentPage" Kind="Class" />
+ <Type Name="ContentPresenter" Kind="Class" />
+ <Type Name="ContentPropertyAttribute" Kind="Class" />
+ <Type Name="ContentView" Kind="Class" />
+ <Type Name="ControlTemplate" Kind="Class" />
+ <Type Name="DataTemplate" Kind="Class" />
+ <Type Name="DataTemplateSelector" Kind="Class" />
+ <Type Name="DataTrigger" Kind="Class" />
+ <Type Name="DateChangedEventArgs" Kind="Class" />
+ <Type Name="DatePicker" Kind="Class" />
+ <Type Name="DefinitionCollection`1" DisplayName="DefinitionCollection&lt;T&gt;" Kind="Class" />
+ <Type Name="DependencyAttribute" Kind="Class" />
+ <Type Name="DependencyFetchTarget" Kind="Enumeration" />
+ <Type Name="DependencyService" Kind="Class" />
+ <Type Name="Device" Kind="Class" />
+ <Type Name="Device+Styles" Kind="Class" />
+ <Type Name="Easing" Kind="Class" />
+ <Type Name="Editor" Kind="Class" />
+ <Type Name="Effect" Kind="Class" />
+ <Type Name="Element" Kind="Class" />
+ <Type Name="ElementEventArgs" Kind="Class" />
+ <Type Name="ElementTemplate" Kind="Class" />
+ <Type Name="Entry" Kind="Class" />
+ <Type Name="EntryCell" Kind="Class" />
+ <Type Name="EventTrigger" Kind="Class" />
+ <Type Name="ExportEffectAttribute" Kind="Class" />
+ <Type Name="FileImageSource" Kind="Class" />
+ <Type Name="FileImageSourceConverter" Kind="Class" />
+ <Type Name="FocusEventArgs" Kind="Class" />
+ <Type Name="Font" Kind="Structure" />
+ <Type Name="FontAttributes" Kind="Enumeration" />
+ <Type Name="FontSizeConverter" Kind="Class" />
+ <Type Name="FontTypeConverter" Kind="Class" />
+ <Type Name="FormattedString" Kind="Class" />
+ <Type Name="Frame" Kind="Class" />
+ <Type Name="GestureRecognizer" Kind="Class" />
+ <Type Name="GestureState" Kind="Enumeration" />
+ <Type Name="GestureStatus" Kind="Enumeration" />
+ <Type Name="Grid" Kind="Class" />
+ <Type Name="Grid+IGridList`1" DisplayName="Grid+IGridList&lt;T&gt;" Kind="Interface" />
+ <Type Name="GridLength" Kind="Structure" />
+ <Type Name="GridLengthTypeConverter" Kind="Class" />
+ <Type Name="GridUnitType" Kind="Enumeration" />
+ <Type Name="HandlerAttribute" Kind="Class" />
+ <Type Name="HtmlWebViewSource" Kind="Class" />
+ <Type Name="IAnimatable" Kind="Interface" />
+ <Type Name="ICarouselViewController" Kind="Interface" />
+ <Type Name="IApplicationController" Kind="Interface" />
+ <Type Name="IDefinition" Kind="Interface" />
+ <Type Name="IEffectControlProvider" Kind="Interface" />
+ <Type Name="IElementController" Kind="Interface" />
+ <Type Name="IExtendedTypeConverter" Kind="Interface" />
+ <Type Name="IGestureRecognizer" Kind="Interface" />
+ <Type Name="IItemViewController" Kind="Interface" />
+ <Type Name="ILayout" Kind="Interface" />
+ <Type Name="ILayoutController" Kind="Interface" />
+ <Type Name="Image" Kind="Class" />
+ <Type Name="ImageCell" Kind="Class" />
+ <Type Name="ImageSource" Kind="Class" />
+ <Type Name="ImageSourceConverter" Kind="Class" />
+ <Type Name="INativeElementView" Kind="Interface" />
+ <Type Name="INavigation" Kind="Interface" />
+ <Type Name="InputView" Kind="Class" />
+ <Type Name="IOpenGLViewController" Kind="Interface" />
+ <Type Name="IPageContainer`1" DisplayName="IPageContainer&lt;T&gt;" Kind="Interface" />
+ <Type Name="IPlatform" Kind="Interface" />
+ <Type Name="IPlatformEngine" Kind="Interface" />
+ <Type Name="IRegisterable" Kind="Interface" />
+ <Type Name="IScrollViewController" Kind="Interface" />
+ <Type Name="ItemsView" Kind="Class" />
+ <Type Name="ItemsView`1" DisplayName="ItemsView&lt;TVisual&gt;" Kind="Class" />
+ <Type Name="ItemTappedEventArgs" Kind="Class" />
+ <Type Name="ItemVisibilityEventArgs" Kind="Class" />
+ <Type Name="IValueConverter" Kind="Interface" />
+ <Type Name="IViewContainer`1" DisplayName="IViewContainer&lt;T&gt;" Kind="Interface" />
+ <Type Name="IViewController" Kind="Interface" />
+ <Type Name="IVisualElementController" Kind="Interface" />
+ <Type Name="Keyboard" Kind="Class" />
+ <Type Name="KeyboardFlags" Kind="Enumeration" />
+ <Type Name="KeyboardTypeConverter" Kind="Class" />
+ <Type Name="Label" Kind="Class" />
+ <Type Name="Layout" Kind="Class" />
+ <Type Name="Layout`1" DisplayName="Layout&lt;T&gt;" Kind="Class" />
+ <Type Name="LayoutAlignment" Kind="Enumeration" />
+ <Type Name="LayoutOptions" Kind="Structure" />
+ <Type Name="LayoutOptionsConverter" Kind="Class" />
+ <Type Name="LineBreakMode" Kind="Enumeration" />
+ <Type Name="ListView" Kind="Class" />
+ <Type Name="ListViewCachingStrategy" Kind="Enumeration" />
+ <Type Name="MasterBehavior" Kind="Enumeration" />
+ <Type Name="MasterDetailPage" Kind="Class" />
+ <Type Name="MeasureFlags" Kind="Enumeration" />
+ <Type Name="MenuItem" Kind="Class" />
+ <Type Name="MessagingCenter" Kind="Class" />
+ <Type Name="ModalEventArgs" Kind="Class" />
+ <Type Name="ModalPoppedEventArgs" Kind="Class" />
+ <Type Name="ModalPoppingEventArgs" Kind="Class" />
+ <Type Name="ModalPushedEventArgs" Kind="Class" />
+ <Type Name="ModalPushingEventArgs" Kind="Class" />
+ <Type Name="MultiPage`1" DisplayName="MultiPage&lt;T&gt;" Kind="Class" />
+ <Type Name="MultiTrigger" Kind="Class" />
+ <Type Name="NamedSize" Kind="Enumeration" />
+ <Type Name="NameScopeExtensions" Kind="Class" />
+ <Type Name="NavigationEventArgs" Kind="Class" />
+ <Type Name="NavigationMenu" Kind="Class" />
+ <Type Name="NavigationPage" Kind="Class" />
+ <Type Name="OnIdiom`1" DisplayName="OnIdiom&lt;T&gt;" Kind="Class" />
+ <Type Name="OnPlatform`1" DisplayName="OnPlatform&lt;T&gt;" Kind="Class" />
+ <Type Name="OpenGLView" Kind="Class" />
+ <Type Name="Page" Kind="Class" />
+ <Type Name="PanGestureRecognizer" Kind="Class" />
+ <Type Name="PanUpdatedEventArgs" Kind="Class" />
+ <Type Name="Picker" Kind="Class" />
+ <Type Name="PinchGestureRecognizer" Kind="Class" />
+ <Type Name="PinchGestureUpdatedEventArgs" Kind="Class" />
+ <Type Name="PlatformEffect`2" DisplayName="PlatformEffect&lt;TContainer,TControl&gt;" Kind="Class" />
+ <Type Name="Point" Kind="Structure" />
+ <Type Name="PointTypeConverter" Kind="Class" />
+ <Type Name="ProgressBar" Kind="Class" />
+ <Type Name="PropertyChangingEventArgs" Kind="Class" />
+ <Type Name="PropertyChangingEventHandler" Kind="Delegate" />
+ <Type Name="PropertyCondition" Kind="Class" />
+ <Type Name="Rectangle" Kind="Structure" />
+ <Type Name="RectangleTypeConverter" Kind="Class" />
+ <Type Name="RelativeLayout" Kind="Class" />
+ <Type Name="RelativeLayout+IRelativeList`1" DisplayName="RelativeLayout+IRelativeList&lt;T&gt;" Kind="Interface" />
+ <Type Name="RenderWithAttribute" Kind="Class" />
+ <Type Name="ResolutionGroupNameAttribute" Kind="Class" />
+ <Type Name="ResourceDictionary" Kind="Class" />
+ <Type Name="RoutingEffect" Kind="Class" />
+ <Type Name="RowDefinition" Kind="Class" />
+ <Type Name="RowDefinitionCollection" Kind="Class" />
+ <Type Name="ScrolledEventArgs" Kind="Class" />
+ <Type Name="ScrollOrientation" Kind="Enumeration" />
+ <Type Name="ScrollToMode" Kind="Enumeration" />
+ <Type Name="ScrollToPosition" Kind="Enumeration" />
+ <Type Name="ScrollToRequestedEventArgs" Kind="Class" />
+ <Type Name="ScrollView" Kind="Class" />
+ <Type Name="SearchBar" Kind="Class" />
+ <Type Name="SelectedItemChangedEventArgs" Kind="Class" />
+ <Type Name="SelectedPositionChangedEventArgs" Kind="Class" />
+ <Type Name="SeparatorVisibility" Kind="Enumeration" />
+ <Type Name="Setter" Kind="Class" />
+ <Type Name="SettersExtensions" Kind="Class" />
+ <Type Name="Size" Kind="Structure" />
+ <Type Name="SizeRequest" Kind="Structure" />
+ <Type Name="Slider" Kind="Class" />
+ <Type Name="Span" Kind="Class" />
+ <Type Name="StackLayout" Kind="Class" />
+ <Type Name="StackOrientation" Kind="Enumeration" />
+ <Type Name="Stepper" Kind="Class" />
+ <Type Name="StreamImageSource" Kind="Class" />
+ <Type Name="Style" Kind="Class" />
+ <Type Name="Switch" Kind="Class" />
+ <Type Name="SwitchCell" Kind="Class" />
+ <Type Name="TabbedPage" Kind="Class" />
+ <Type Name="TableIntent" Kind="Enumeration" />
+ <Type Name="TableRoot" Kind="Class" />
+ <Type Name="TableSection" Kind="Class" />
+ <Type Name="TableSectionBase" Kind="Class" />
+ <Type Name="TableSectionBase`1" DisplayName="TableSectionBase&lt;T&gt;" Kind="Class" />
+ <Type Name="TableView" Kind="Class" />
+ <Type Name="TapGestureRecognizer" Kind="Class" />
+ <Type Name="TappedEventArgs" Kind="Class" />
+ <Type Name="TargetIdiom" Kind="Enumeration" />
+ <Type Name="TargetPlatform" Kind="Enumeration" />
+ <Type Name="TemplateBinding" Kind="Class" />
+ <Type Name="TemplatedPage" Kind="Class" />
+ <Type Name="TemplatedView" Kind="Class" />
+ <Type Name="TemplateExtensions" Kind="Class" />
+ <Type Name="TextAlignment" Kind="Enumeration" />
+ <Type Name="TextCell" Kind="Class" />
+ <Type Name="TextChangedEventArgs" Kind="Class" />
+ <Type Name="Thickness" Kind="Structure" />
+ <Type Name="ThicknessTypeConverter" Kind="Class" />
+ <Type Name="TimePicker" Kind="Class" />
+ <Type Name="ToggledEventArgs" Kind="Class" />
+ <Type Name="ToolbarItem" Kind="Class" />
+ <Type Name="ToolbarItemOrder" Kind="Enumeration" />
+ <Type Name="Trigger" Kind="Class" />
+ <Type Name="TriggerAction" Kind="Class" />
+ <Type Name="TriggerAction`1" DisplayName="TriggerAction&lt;T&gt;" Kind="Class" />
+ <Type Name="TriggerBase" Kind="Class" />
+ <Type Name="TypeConverter" Kind="Class" />
+ <Type Name="TypeConverterAttribute" Kind="Class" />
+ <Type Name="TypeTypeConverter" Kind="Class" />
+ <Type Name="UnsolvableConstraintsException" Kind="Class" />
+ <Type Name="UriImageSource" Kind="Class" />
+ <Type Name="UriTypeConverter" Kind="Class" />
+ <Type Name="UrlWebViewSource" Kind="Class" />
+ <Type Name="ValueChangedEventArgs" Kind="Class" />
+ <Type Name="Vec2" Kind="Structure" />
+ <Type Name="View" Kind="Class" />
+ <Type Name="ViewCell" Kind="Class" />
+ <Type Name="ViewExtensions" Kind="Class" />
+ <Type Name="ViewState" Kind="Enumeration" />
+ <Type Name="VisualElement" Kind="Class" />
+ <Type Name="WebNavigatedEventArgs" Kind="Class" />
+ <Type Name="WebNavigatingEventArgs" Kind="Class" />
+ <Type Name="WebNavigationEvent" Kind="Enumeration" />
+ <Type Name="WebNavigationEventArgs" Kind="Class" />
+ <Type Name="WebNavigationResult" Kind="Enumeration" />
+ <Type Name="WebView" Kind="Class" />
+ <Type Name="WebViewSource" Kind="Class" />
+ <Type Name="WebViewSourceTypeConverter" Kind="Class" />
+ </Namespace>
+ <Namespace Name="Xamarin.Forms.Internals">
+ <Type Name="DynamicResource" Kind="Class" />
+ <Type Name="IDataTemplate" Kind="Interface" />
+ <Type Name="IDynamicResourceHandler" Kind="Interface" />
+ <Type Name="INameScope" Kind="Interface" />
+ <Type Name="NameScope" Kind="Class" />
+ </Namespace>
+ <Namespace Name="Xamarin.Forms.Xaml">
+ <Type Name="IMarkupExtension" Kind="Interface" />
+ <Type Name="IMarkupExtension`1" DisplayName="IMarkupExtension&lt;T&gt;" Kind="Interface" />
+ <Type Name="IProvideValueTarget" Kind="Interface" />
+ <Type Name="IRootObjectProvider" Kind="Interface" />
+ <Type Name="IValueProvider" Kind="Interface" />
+ <Type Name="IXamlTypeResolver" Kind="Interface" />
+ <Type Name="IXmlLineInfoProvider" Kind="Interface" />
+ <Type Name="XamlParseException" Kind="Class" />
+ <Type Name="XmlLineInfo" Kind="Class" />
+ </Namespace>
+ </Types>
+ <Title>Xamarin.Forms.Core</Title>
+ <ExtensionMethods>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.IAnimatable" />
+ </Targets>
+ <Member MemberName="AbortAnimation">
+ <MemberSignature Language="C#" Value="public static bool AbortAnimation (this Xamarin.Forms.IAnimatable self, string handle);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig bool AbortAnimation(class Xamarin.Forms.IAnimatable self, string handle) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.IAnimatable" RefType="this" />
+ <Parameter Name="handle" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="self">To be added.</param>
+ <param name="handle">To be added.</param>
+ <summary>Stops the animation.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.AnimationExtensions" Member="M:Xamarin.Forms.AnimationExtensions.AbortAnimation(Xamarin.Forms.IAnimatable,System.String)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.IAnimatable" />
+ </Targets>
+ <Member MemberName="Animate">
+ <MemberSignature Language="C#" Value="public static void Animate (this Xamarin.Forms.IAnimatable self, string name, Action&lt;double&gt; callback, double start, double end, uint rate = 16, uint length = 250, Xamarin.Forms.Easing easing = null, Action&lt;double,bool&gt; finished = null, Func&lt;bool&gt; repeat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Animate(class Xamarin.Forms.IAnimatable self, string name, class System.Action`1&lt;float64&gt; callback, float64 start, float64 end, unsigned int32 rate, unsigned int32 length, class Xamarin.Forms.Easing easing, class System.Action`2&lt;float64, bool&gt; finished, class System.Func`1&lt;bool&gt; repeat) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.IAnimatable" RefType="this" />
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="callback" Type="System.Action&lt;System.Double&gt;" />
+ <Parameter Name="start" Type="System.Double" />
+ <Parameter Name="end" Type="System.Double" />
+ <Parameter Name="rate" Type="System.UInt32" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ <Parameter Name="finished" Type="System.Action&lt;System.Double,System.Boolean&gt;" />
+ <Parameter Name="repeat" Type="System.Func&lt;System.Boolean&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="self">To be added.</param>
+ <param name="name">To be added.</param>
+ <param name="callback">To be added.</param>
+ <param name="start">To be added.</param>
+ <param name="end">To be added.</param>
+ <param name="rate">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <param name="finished">To be added.</param>
+ <param name="repeat">To be added.</param>
+ <summary>Sets the specified parameters and starts the animation.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.AnimationExtensions" Member="M:Xamarin.Forms.AnimationExtensions.Animate(Xamarin.Forms.IAnimatable,System.String,System.Action{System.Double},System.Double,System.Double,System.UInt32,System.UInt32,Xamarin.Forms.Easing,System.Action{System.Double,System.Boolean},System.Func{System.Boolean})" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.IAnimatable" />
+ </Targets>
+ <Member MemberName="Animate">
+ <MemberSignature Language="C#" Value="public static void Animate (this Xamarin.Forms.IAnimatable self, string name, Action&lt;double&gt; callback, uint rate = 16, uint length = 250, Xamarin.Forms.Easing easing = null, Action&lt;double,bool&gt; finished = null, Func&lt;bool&gt; repeat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Animate(class Xamarin.Forms.IAnimatable self, string name, class System.Action`1&lt;float64&gt; callback, unsigned int32 rate, unsigned int32 length, class Xamarin.Forms.Easing easing, class System.Action`2&lt;float64, bool&gt; finished, class System.Func`1&lt;bool&gt; repeat) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.IAnimatable" RefType="this" />
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="callback" Type="System.Action&lt;System.Double&gt;" />
+ <Parameter Name="rate" Type="System.UInt32" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ <Parameter Name="finished" Type="System.Action&lt;System.Double,System.Boolean&gt;" />
+ <Parameter Name="repeat" Type="System.Func&lt;System.Boolean&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="self">To be added.</param>
+ <param name="name">To be added.</param>
+ <param name="callback">To be added.</param>
+ <param name="rate">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <param name="finished">To be added.</param>
+ <param name="repeat">To be added.</param>
+ <summary>Sets the specified parameters and starts the animation.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.AnimationExtensions" Member="M:Xamarin.Forms.AnimationExtensions.Animate(Xamarin.Forms.IAnimatable,System.String,System.Action{System.Double},System.UInt32,System.UInt32,Xamarin.Forms.Easing,System.Action{System.Double,System.Boolean},System.Func{System.Boolean})" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.IAnimatable" />
+ </Targets>
+ <Member MemberName="Animate">
+ <MemberSignature Language="C#" Value="public static void Animate (this Xamarin.Forms.IAnimatable self, string name, Xamarin.Forms.Animation animation, uint rate = 16, uint length = 250, Xamarin.Forms.Easing easing = null, Action&lt;double,bool&gt; finished = null, Func&lt;bool&gt; repeat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Animate(class Xamarin.Forms.IAnimatable self, string name, class Xamarin.Forms.Animation animation, unsigned int32 rate, unsigned int32 length, class Xamarin.Forms.Easing easing, class System.Action`2&lt;float64, bool&gt; finished, class System.Func`1&lt;bool&gt; repeat) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.IAnimatable" RefType="this" />
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="animation" Type="Xamarin.Forms.Animation" />
+ <Parameter Name="rate" Type="System.UInt32" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ <Parameter Name="finished" Type="System.Action&lt;System.Double,System.Boolean&gt;" />
+ <Parameter Name="repeat" Type="System.Func&lt;System.Boolean&gt;" />
+ </Parameters>
+ <Docs>
+ <param name="self">To be added.</param>
+ <param name="name">To be added.</param>
+ <param name="animation">To be added.</param>
+ <param name="rate">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <param name="finished">To be added.</param>
+ <param name="repeat">To be added.</param>
+ <summary>Sets the specified parameters and starts the animation.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.AnimationExtensions" Member="M:Xamarin.Forms.AnimationExtensions.Animate(Xamarin.Forms.IAnimatable,System.String,Xamarin.Forms.Animation,System.UInt32,System.UInt32,Xamarin.Forms.Easing,System.Action{System.Double,System.Boolean},System.Func{System.Boolean})" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.IAnimatable" />
+ </Targets>
+ <Member MemberName="Animate&lt;T&gt;">
+ <MemberSignature Language="C#" Value="public static void Animate&lt;T&gt; (this Xamarin.Forms.IAnimatable self, string name, Func&lt;double,T&gt; transform, Action&lt;T&gt; callback, uint rate = 16, uint length = 250, Xamarin.Forms.Easing easing = null, Action&lt;T,bool&gt; finished = null, Func&lt;bool&gt; repeat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Animate&lt;T&gt;(class Xamarin.Forms.IAnimatable self, string name, class System.Func`2&lt;float64, !!T&gt; transform, class System.Action`1&lt;!!T&gt; callback, unsigned int32 rate, unsigned int32 length, class Xamarin.Forms.Easing easing, class System.Action`2&lt;!!T, bool&gt; finished, class System.Func`1&lt;bool&gt; repeat) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="T" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.IAnimatable" RefType="this" />
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="transform" Type="System.Func&lt;System.Double,T&gt;" />
+ <Parameter Name="callback" Type="System.Action&lt;T&gt;" />
+ <Parameter Name="rate" Type="System.UInt32" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ <Parameter Name="finished" Type="System.Action&lt;T,System.Boolean&gt;" />
+ <Parameter Name="repeat" Type="System.Func&lt;System.Boolean&gt;" />
+ </Parameters>
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <param name="self">To be added.</param>
+ <param name="name">To be added.</param>
+ <param name="transform">To be added.</param>
+ <param name="callback">To be added.</param>
+ <param name="rate">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <param name="finished">To be added.</param>
+ <param name="repeat">To be added.</param>
+ <summary>Sets the specified parameters and starts the animation.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.AnimationExtensions" Member="M:Xamarin.Forms.AnimationExtensions.Animate``1(Xamarin.Forms.IAnimatable,System.String,System.Func{System.Double,``0},System.Action{``0},System.UInt32,System.UInt32,Xamarin.Forms.Easing,System.Action{``0,System.Boolean},System.Func{System.Boolean})" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.IAnimatable" />
+ </Targets>
+ <Member MemberName="AnimateKinetic">
+ <MemberSignature Language="C#" Value="public static void AnimateKinetic (this Xamarin.Forms.IAnimatable self, string name, Func&lt;double,double,bool&gt; callback, double velocity, double drag, Action finished = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void AnimateKinetic(class Xamarin.Forms.IAnimatable self, string name, class System.Func`3&lt;float64, float64, bool&gt; callback, float64 velocity, float64 drag, class System.Action finished) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.IAnimatable" RefType="this" />
+ <Parameter Name="name" Type="System.String" />
+ <Parameter Name="callback" Type="System.Func&lt;System.Double,System.Double,System.Boolean&gt;" />
+ <Parameter Name="velocity" Type="System.Double" />
+ <Parameter Name="drag" Type="System.Double" />
+ <Parameter Name="finished" Type="System.Action" />
+ </Parameters>
+ <Docs>
+ <param name="self">To be added.</param>
+ <param name="name">To be added.</param>
+ <param name="callback">To be added.</param>
+ <param name="velocity">To be added.</param>
+ <param name="drag">To be added.</param>
+ <param name="finished">To be added.</param>
+ <summary>Sets the specified parameters and starts the kinetic animation.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.AnimationExtensions" Member="M:Xamarin.Forms.AnimationExtensions.AnimateKinetic(Xamarin.Forms.IAnimatable,System.String,System.Func{System.Double,System.Double,System.Boolean},System.Double,System.Double,System.Action)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.IAnimatable" />
+ </Targets>
+ <Member MemberName="AnimationIsRunning">
+ <MemberSignature Language="C#" Value="public static bool AnimationIsRunning (this Xamarin.Forms.IAnimatable self, string handle);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig bool AnimationIsRunning(class Xamarin.Forms.IAnimatable self, string handle) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.IAnimatable" RefType="this" />
+ <Parameter Name="handle" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="self">To be added.</param>
+ <param name="handle">To be added.</param>
+ <summary>Returns a Boolean value that indicates whether or not the animation that is specified by <paramref name="handle" /> is running.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.AnimationExtensions" Member="M:Xamarin.Forms.AnimationExtensions.AnimationIsRunning(Xamarin.Forms.IAnimatable,System.String)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.BindableObject" />
+ </Targets>
+ <Member MemberName="SetBinding">
+ <MemberSignature Language="C#" Value="public static void SetBinding (this Xamarin.Forms.BindableObject self, Xamarin.Forms.BindableProperty targetProperty, string path, Xamarin.Forms.BindingMode mode = Xamarin.Forms.BindingMode.Default, Xamarin.Forms.IValueConverter converter = null, string stringFormat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetBinding(class Xamarin.Forms.BindableObject self, class Xamarin.Forms.BindableProperty targetProperty, string path, valuetype Xamarin.Forms.BindingMode mode, class Xamarin.Forms.IValueConverter converter, string stringFormat) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.BindableObject" RefType="this" />
+ <Parameter Name="targetProperty" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="path" Type="System.String" />
+ <Parameter Name="mode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="converter" Type="Xamarin.Forms.IValueConverter" />
+ <Parameter Name="stringFormat" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="self">The <see cref="T:Xamarin.Forms.BindableObject" />.</param>
+ <param name="targetProperty">The BindableProperty on which to set a bindinge.</param>
+ <param name="path">A <see cref="T:System.String" /> indicating the property path to bind to.</param>
+ <param name="mode">The <see cref="T:Xamarin.Forms.BindingMode" /> for the binding. This parameter is optional. Default is <see cref="E:Xamarin.Forms.BindingMode.Default" />.</param>
+ <param name="converter">An <see cref="T:Xamarin.Forms.IValueConverter" /> for the binding. This parameter is optional. Default is <see langword="null" />.</param>
+ <param name="stringFormat">A string used as stringFormat for the binding. This parameter is optional. Default is <see langword="null" />.</param>
+ <summary>Creates and applies a binding to a property.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.BindableObjectExtensions" Member="M:Xamarin.Forms.BindableObjectExtensions.SetBinding(Xamarin.Forms.BindableObject,Xamarin.Forms.BindableProperty,System.String,Xamarin.Forms.BindingMode,Xamarin.Forms.IValueConverter,System.String)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.BindableObject" />
+ </Targets>
+ <Member MemberName="SetBinding&lt;TSource&gt;">
+ <MemberSignature Language="C#" Value="public static void SetBinding&lt;TSource&gt; (this Xamarin.Forms.BindableObject self, Xamarin.Forms.BindableProperty targetProperty, System.Linq.Expressions.Expression&lt;Func&lt;TSource,object&gt;&gt; sourceProperty, Xamarin.Forms.BindingMode mode = Xamarin.Forms.BindingMode.Default, Xamarin.Forms.IValueConverter converter = null, string stringFormat = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetBinding&lt;TSource&gt;(class Xamarin.Forms.BindableObject self, class Xamarin.Forms.BindableProperty targetProperty, class System.Linq.Expressions.Expression`1&lt;class System.Func`2&lt;!!TSource, object&gt;&gt; sourceProperty, valuetype Xamarin.Forms.BindingMode mode, class Xamarin.Forms.IValueConverter converter, string stringFormat) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TSource" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.BindableObject" RefType="this" />
+ <Parameter Name="targetProperty" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="sourceProperty" Type="System.Linq.Expressions.Expression&lt;System.Func&lt;TSource,System.Object&gt;&gt;" />
+ <Parameter Name="mode" Type="Xamarin.Forms.BindingMode" />
+ <Parameter Name="converter" Type="Xamarin.Forms.IValueConverter" />
+ <Parameter Name="stringFormat" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TSource">The source type.</typeparam>
+ <param name="self">The BindableObject.</param>
+ <param name="targetProperty">The BindableProperty to bind to</param>
+ <param name="sourceProperty">An expression used to retrieve the source path.</param>
+ <param name="mode">The BindingMode for the binding. This parameter is optional. Default is <see cref="E:Xamarin.Forms.BindingMode.Default" />.</param>
+ <param name="converter">An IValueConverter for the binding. This parameter is optional. Default is <see langword="null" />.</param>
+ <param name="stringFormat">A string used as stringFormat for the binding. This parameter is optional. Default is <see langword="null" />.</param>
+ <summary>Creates and applies a binding from an expression.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.BindableObjectExtensions" Member="M:Xamarin.Forms.BindableObjectExtensions.SetBinding``1(Xamarin.Forms.BindableObject,Xamarin.Forms.BindableProperty,System.Linq.Expressions.Expression{System.Func{``0,System.Object}},Xamarin.Forms.BindingMode,Xamarin.Forms.IValueConverter,System.String)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.Element" />
+ </Targets>
+ <Member MemberName="FindByName&lt;T&gt;">
+ <MemberSignature Language="C#" Value="public static T FindByName&lt;T&gt; (this Xamarin.Forms.Element element, string name);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig !!T FindByName&lt;T&gt;(class Xamarin.Forms.Element element, string name) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>T</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="T" />
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="element" Type="Xamarin.Forms.Element" RefType="this" />
+ <Parameter Name="name" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <param name="element">To be added.</param>
+ <param name="name">To be added.</param>
+ <summary>Returns the instance of type <paramref name="T" /> that has name <paramref name="T" /> in the scope that includes <paramref name="element" />.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.NameScopeExtensions" Member="M:Xamarin.Forms.NameScopeExtensions.FindByName``1(Xamarin.Forms.Element,System.String)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:System.Collections.Generic.IList`1" />
+ </Targets>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public static void Add (this System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt; setters, Xamarin.Forms.BindableProperty property, object value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void Add(class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Setter&gt; setters, class Xamarin.Forms.BindableProperty property, object value) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="setters" Type="System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt;" RefType="this" />
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="value" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="setters">To be added.</param>
+ <param name="property">To be added.</param>
+ <param name="value">To be added.</param>
+ <summary>Add a Setter with a value to the IList&lt;Setter&gt;</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.SettersExtensions" Member="M:Xamarin.Forms.SettersExtensions.Add(System.Collections.Generic.IList{Xamarin.Forms.Setter},Xamarin.Forms.BindableProperty,System.Object)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:System.Collections.Generic.IList`1" />
+ </Targets>
+ <Member MemberName="AddBinding">
+ <MemberSignature Language="C#" Value="public static void AddBinding (this System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt; setters, Xamarin.Forms.BindableProperty property, Xamarin.Forms.Binding binding);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void AddBinding(class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Setter&gt; setters, class Xamarin.Forms.BindableProperty property, class Xamarin.Forms.Binding binding) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="setters" Type="System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt;" RefType="this" />
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="binding" Type="Xamarin.Forms.Binding" />
+ </Parameters>
+ <Docs>
+ <param name="setters">To be added.</param>
+ <param name="property">To be added.</param>
+ <param name="binding">To be added.</param>
+ <summary>Add a Setter with a Binding to the IList&lt;Setter&gt;</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.SettersExtensions" Member="M:Xamarin.Forms.SettersExtensions.AddBinding(System.Collections.Generic.IList{Xamarin.Forms.Setter},Xamarin.Forms.BindableProperty,Xamarin.Forms.Binding)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:System.Collections.Generic.IList`1" />
+ </Targets>
+ <Member MemberName="AddDynamicResource">
+ <MemberSignature Language="C#" Value="public static void AddDynamicResource (this System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt; setters, Xamarin.Forms.BindableProperty property, string key);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void AddDynamicResource(class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Setter&gt; setters, class Xamarin.Forms.BindableProperty property, string key) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="setters" Type="System.Collections.Generic.IList&lt;Xamarin.Forms.Setter&gt;" RefType="this" />
+ <Parameter Name="property" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="key" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="setters">To be added.</param>
+ <param name="property">To be added.</param>
+ <param name="key">To be added.</param>
+ <summary>Add a Setter with a DynamicResource to the IList&lt;Setter&gt;</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.SettersExtensions" Member="M:Xamarin.Forms.SettersExtensions.AddDynamicResource(System.Collections.Generic.IList{Xamarin.Forms.Setter},Xamarin.Forms.BindableProperty,System.String)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.DataTemplate" />
+ </Targets>
+ <Member MemberName="SetBinding">
+ <MemberSignature Language="C#" Value="public static void SetBinding (this Xamarin.Forms.DataTemplate self, Xamarin.Forms.BindableProperty targetProperty, string path);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig void SetBinding(class Xamarin.Forms.DataTemplate self, class Xamarin.Forms.BindableProperty targetProperty, string path) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="self" Type="Xamarin.Forms.DataTemplate" RefType="this" />
+ <Parameter Name="targetProperty" Type="Xamarin.Forms.BindableProperty" />
+ <Parameter Name="path" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="self">To be added.</param>
+ <param name="targetProperty">To be added.</param>
+ <param name="path">To be added.</param>
+ <summary>Binds the <paramref name="self" /> object's <paramref name="targetProperty" /> to a new <see cref="T:Xamarin.Forms.Binding" /> instance that was created with <paramref name="path" />.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.TemplateExtensions" Member="M:Xamarin.Forms.TemplateExtensions.SetBinding(Xamarin.Forms.DataTemplate,Xamarin.Forms.BindableProperty,System.String)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.VisualElement" />
+ </Targets>
+ <Member MemberName="FadeTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; FadeTo (this Xamarin.Forms.VisualElement view, double opacity, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; FadeTo(class Xamarin.Forms.VisualElement view, float64 opacity, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="opacity" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="opacity">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Returns a task that performs the fade that is described by the <paramref name="opacity" />, <paramref name="length" />, and <paramref name="easing" /> parameters.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.ViewExtensions" Member="M:Xamarin.Forms.ViewExtensions.FadeTo(Xamarin.Forms.VisualElement,System.Double,System.UInt32,Xamarin.Forms.Easing)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.VisualElement" />
+ </Targets>
+ <Member MemberName="LayoutTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; LayoutTo (this Xamarin.Forms.VisualElement view, Xamarin.Forms.Rectangle bounds, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; LayoutTo(class Xamarin.Forms.VisualElement view, valuetype Xamarin.Forms.Rectangle bounds, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="bounds" Type="Xamarin.Forms.Rectangle" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="bounds">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Returns a task that eases the bounds of the <see cref="T:Xamarin.Forms.VisualElement" /> that is specified by the <paramref name="view" /> to the rectangle that is specified by the <paramref name="bounds" /> parameter.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.ViewExtensions" Member="M:Xamarin.Forms.ViewExtensions.LayoutTo(Xamarin.Forms.VisualElement,Xamarin.Forms.Rectangle,System.UInt32,Xamarin.Forms.Easing)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.VisualElement" />
+ </Targets>
+ <Member MemberName="RelRotateTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; RelRotateTo (this Xamarin.Forms.VisualElement view, double drotation, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; RelRotateTo(class Xamarin.Forms.VisualElement view, float64 drotation, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="drotation" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="drotation">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Rotates the <see cref="T:Xamarin.Forms.VisualElement" /> that is specified by <paramref name="view" /> from its current rotation by <paramref name="drotation" />.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.ViewExtensions" Member="M:Xamarin.Forms.ViewExtensions.RelRotateTo(Xamarin.Forms.VisualElement,System.Double,System.UInt32,Xamarin.Forms.Easing)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.VisualElement" />
+ </Targets>
+ <Member MemberName="RelScaleTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; RelScaleTo (this Xamarin.Forms.VisualElement view, double dscale, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; RelScaleTo(class Xamarin.Forms.VisualElement view, float64 dscale, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="dscale" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="dscale">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Returns a task that scales the <see cref="T:Xamarin.Forms.VisualElement" /> that is specified by <paramref name="view" /> from its current scale to <paramref name="dscale" />.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.ViewExtensions" Member="M:Xamarin.Forms.ViewExtensions.RelScaleTo(Xamarin.Forms.VisualElement,System.Double,System.UInt32,Xamarin.Forms.Easing)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.VisualElement" />
+ </Targets>
+ <Member MemberName="RotateTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; RotateTo (this Xamarin.Forms.VisualElement view, double rotation, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; RotateTo(class Xamarin.Forms.VisualElement view, float64 rotation, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="rotation" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="rotation">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Returns a task that performs the rotation that is described by the <paramref name="rotation" />, <paramref name="length" />, and <paramref name="easing" /> parameters..</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.ViewExtensions" Member="M:Xamarin.Forms.ViewExtensions.RotateTo(Xamarin.Forms.VisualElement,System.Double,System.UInt32,Xamarin.Forms.Easing)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.VisualElement" />
+ </Targets>
+ <Member MemberName="RotateXTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; RotateXTo (this Xamarin.Forms.VisualElement view, double rotation, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; RotateXTo(class Xamarin.Forms.VisualElement view, float64 rotation, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="rotation" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="rotation">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Returns a task that skews the Y axis by <paramref name="opacity" />, taking time <paramref name="length" /> and using <paramref name="easing" />.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.ViewExtensions" Member="M:Xamarin.Forms.ViewExtensions.RotateXTo(Xamarin.Forms.VisualElement,System.Double,System.UInt32,Xamarin.Forms.Easing)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.VisualElement" />
+ </Targets>
+ <Member MemberName="RotateYTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; RotateYTo (this Xamarin.Forms.VisualElement view, double rotation, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; RotateYTo(class Xamarin.Forms.VisualElement view, float64 rotation, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="rotation" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="rotation">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Returns a task that skews the X axis by <paramref name="opacity" />, taking time <paramref name="length" /> and using <paramref name="easing" />.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.ViewExtensions" Member="M:Xamarin.Forms.ViewExtensions.RotateYTo(Xamarin.Forms.VisualElement,System.Double,System.UInt32,Xamarin.Forms.Easing)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.VisualElement" />
+ </Targets>
+ <Member MemberName="ScaleTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; ScaleTo (this Xamarin.Forms.VisualElement view, double scale, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; ScaleTo(class Xamarin.Forms.VisualElement view, float64 scale, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="scale" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">To be added.</param>
+ <param name="scale">To be added.</param>
+ <param name="length">To be added.</param>
+ <param name="easing">To be added.</param>
+ <summary>Returns a task that scales the <see cref="T:Xamarin.Forms.VisualElement" /> that is specified by <paramref name="view" /> to the absolute scale factor <paramref name="scale" />.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.ViewExtensions" Member="M:Xamarin.Forms.ViewExtensions.ScaleTo(Xamarin.Forms.VisualElement,System.Double,System.UInt32,Xamarin.Forms.Easing)" />
+ </Member>
+ </ExtensionMethod>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.VisualElement" />
+ </Targets>
+ <Member MemberName="TranslateTo">
+ <MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;bool&gt; TranslateTo (this Xamarin.Forms.VisualElement view, double x, double y, uint length = 250, Xamarin.Forms.Easing easing = null);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;bool&gt; TranslateTo(class Xamarin.Forms.VisualElement view, float64 x, float64 y, unsigned int32 length, class Xamarin.Forms.Easing easing) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Boolean&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="view" Type="Xamarin.Forms.VisualElement" RefType="this" />
+ <Parameter Name="x" Type="System.Double" />
+ <Parameter Name="y" Type="System.Double" />
+ <Parameter Name="length" Type="System.UInt32" />
+ <Parameter Name="easing" Type="Xamarin.Forms.Easing" />
+ </Parameters>
+ <Docs>
+ <param name="view">The view to tanslate.</param>
+ <param name="x">The x component of the final translation vector.</param>
+ <param name="y">The y component of the final translation vector.</param>
+ <param name="length">The duration of the animation in milliseconds.</param>
+ <param name="easing">The easing of the animation.</param>
+ <summary>Animates an elements TranslationX and TranslationY properties from their current values to the new values.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.ViewExtensions" Member="M:Xamarin.Forms.ViewExtensions.TranslateTo(Xamarin.Forms.VisualElement,System.Double,System.Double,System.UInt32,Xamarin.Forms.Easing)" />
+ </Member>
+ </ExtensionMethod>
+ </ExtensionMethods>
+</Overview>
diff --git a/docs/Xamarin.Forms.Core/ns-.xml b/docs/Xamarin.Forms.Core/ns-.xml
new file mode 100644
index 00000000..36dfeb30
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/ns-.xml
@@ -0,0 +1,6 @@
+<Namespace Name="">
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Namespace>
diff --git a/docs/Xamarin.Forms.Core/ns-Xamarin.Forms.Internals.xml b/docs/Xamarin.Forms.Core/ns-Xamarin.Forms.Internals.xml
new file mode 100644
index 00000000..d598a99d
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/ns-Xamarin.Forms.Internals.xml
@@ -0,0 +1,6 @@
+<Namespace Name="Xamarin.Forms.Internals">
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Namespace>
diff --git a/docs/Xamarin.Forms.Core/ns-Xamarin.Forms.Xaml.xml b/docs/Xamarin.Forms.Core/ns-Xamarin.Forms.Xaml.xml
new file mode 100644
index 00000000..97c4746c
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/ns-Xamarin.Forms.Xaml.xml
@@ -0,0 +1,6 @@
+<Namespace Name="Xamarin.Forms.Xaml">
+ <Docs>
+ <summary>Namespace defining types necessary for Xamarin.Forms XAML support.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Namespace>
diff --git a/docs/Xamarin.Forms.Core/ns-Xamarin.Forms.xml b/docs/Xamarin.Forms.Core/ns-Xamarin.Forms.xml
new file mode 100644
index 00000000..b6de4608
--- /dev/null
+++ b/docs/Xamarin.Forms.Core/ns-Xamarin.Forms.xml
@@ -0,0 +1,103 @@
+<Namespace Name="Xamarin.Forms">
+ <Docs>
+ <summary>Cross-platform, natively-backed UI toolkit.</summary>
+ <remarks>
+ <para>Xamarin.Forms is a cross-platform, natively-backed UI toolkit abstraction that allows developers to create user interfaces that can be shared across Android, iOS, and Windows Phone. Because the user interfaces use the native controls of the target platforms, they have the appearance and, importantly, the responsiveness of natively built apps.</para>
+ <format type="text/html">
+ <h2>Hello, Xamarin.Forms!</h2>
+ </format>
+ <para>The user-experience of a Xamarin.Forms application is usually defined in a cross-platform shared project (either a Portable Class Library or a Shared Project) and combined with platform-specific projects that, at the least, initialize the native platform rendering (note the call to <c>Forms.Init()</c> in the platform code samples below) and, more generally, extend the user-experience and user-interface in platform-specific manners (for instance, by accessing platform-specific sensors or capabilities).</para>
+ <para>The dependencies are one-way: the platforms depend on the shared project, but not vice-versa:</para>
+ <para><img href="XamarinForms-ns.SharedProject.png"/></para>
+ <para>
+ The Solution Explorer for a cross-platform "Hello, World!" app might look like this:</para>
+ <para><img href="XamarinForms-ns.SolutionPad.png"/></para>
+ <para>The shared portion of the Xamarin.Forms code might look like this:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+public class App : Xamarin.Forms.Application
+{
+ public App ()
+ {
+ MainPage = new ContentPage
+ {
+ Content = new Label
+ {
+ Text = "Hello, Forms !",
+ VerticalOptions = LayoutOptions.CenterAndExpand,
+ HorizontalOptions = LayoutOptions.CenterAndExpand,
+ },
+ };
+ }
+}
+ ]]></code>
+ </example>
+ <para>The iOS platform code would look like this:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+[Register("AppDelegate")]
+public class AppDelegate : FormsApplicationDelegate
+{
+ UIWindow window;
+
+ public override bool FinishedLaunching(UIApplication app, NSDictionary options)
+ {
+ Forms.Init();
+
+ LoadApplication (new App ());
+
+ return base.FinishedLaunching (app, options);
+ }
+}
+ ]]></code>
+ </example>
+ <para>The Android platform code would look like this:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+[Activity(Label = "HelloXamarinFormsWorld", MainLauncher = true)]
+public class MainActivity : FormsApplicationActivity
+{
+ protected override void OnCreate(Bundle bundle)
+ {
+ base.OnCreate(bundle);
+
+ Forms.Init(this, bundle);
+
+ LoadApplication (new App ());
+ }
+}
+ ]]></code>
+ </example>
+ <para>And the Windows Phone code would look like this:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+public partial class MainPage
+{
+ public MainPage()
+ {
+ InitializeComponent();
+
+ Forms.Init();
+
+ LoadApplication (new HelloXamarinFormsWorld.App ());
+ }
+}
+ ]]></code>
+ </example>
+ <para>The resulting app looks like this on the various devices:</para>
+ <para><img href="XamarinForms-ns.TripleScreenShot.png"/></para>
+ <format type="text/html">
+ <h2>Elements in Xamarin.Forms</h2>
+ </format>
+ <para>Important types in the Xamarin.Forms namespace include <see cref="T:Xamarin.Forms.Page"/>, <see cref="T:Xamarin.Forms.View"/>, and <see cref="T:Xamarin.Forms.Layout"/>. <see cref="T:Xamarin.Forms.Page"/>s typically correspond with controller objects (Activities in the Android world, UIViewControllers in the iOS world), <see cref="T:Xamarin.Forms.View"/>s with controls or widgets, and <see cref="T:Xamarin.Forms.Layout"/>s arrange <see cref="T:Xamarin.Forms.View"/>s on other <see cref="T:Xamarin.Forms.View"/>s. These types are all derived from <see cref="T:Xamarin.Forms.Element"/>.</para>
+ <format type="text/html">
+ <h2>Model-View-ViewModel and Xamarin.Forms</h2>
+ </format>
+ <para>Application developers use the Model-View-ViewModel (MVVM) pattern to create Xamarin.Forms apps that cleanly separate the concerns of data presentation and user interface from the concerns of data storage and manipulation. The <see cref="N:Xamarin.Forms" /> framework enables this by providing, among a few other related types, the <see cref="T:Xamarin.Forms.BindableObject" /> and <see cref="T:Xamarin.Forms.BindableProperty" /> classes. Objects that inherit from <see cref="T:Xamarin.Forms.BindableObject" /> can be bound to members of type <see cref="T:Xamarin.Forms.BindableProperty" /> on other objects.</para>
+ <para>A <see cref="T:Xamarin.Forms.BindableObject" /> maintains dictionary of <see cref="T:Xamarin.Forms.BindableProperty" /> names and an association with their corresponding binding contexts--simply the object on which the <see cref="T:Xamarin.Forms.BindableProperty" /> is defined and that the application developer has assigned to the <see cref="P:Xamarin.Forms.BindingObject.BindingContext" /> property--through a <see cref="T:Xamarin.Forms.Binding" />. See <see cref="T:Xamarin.Forms.BindableObject" /> for more information.</para>
+ </remarks>
+ <related type="article" href="http://developer.xamarin.com/guides/cross-platform/xamarin-forms/introduction-to-xamarin-forms/">Introduction to Xamarin.Forms</related>
+ <related type="article" href="http://developer.xamarin.com/guides/cross-platform/xamarin-forms/controls/">Xamarin.Forms View Gallery</related>
+
+ </Docs>
+</Namespace>
diff --git a/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Distance.xml b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Distance.xml
new file mode 100644
index 00000000..a04a471b
--- /dev/null
+++ b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Distance.xml
@@ -0,0 +1,312 @@
+<Type Name="Distance" FullName="Xamarin.Forms.Maps.Distance">
+ <TypeSignature Language="C#" Value="public struct Distance" />
+ <TypeSignature Language="ILAsm" Value=".class public sequential ansi sealed beforefieldinit Distance extends System.ValueType" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Maps</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.ValueType</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Struct that encapsulates a distance (natively stored as a double of meters).</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Distance (double meters);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 meters) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="meters" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="meters">The distance value, in meters, with which to initialize a new <see cref="T:Xamarin.Forms.Maps.Distance" /> structure.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Maps.Distance" /> that represents the distance described by <paramref name="meters" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Equals">
+ <MemberSignature Language="C#" Value="public override bool Equals (object obj);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool Equals(object obj) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="obj" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="obj">An Object to compare to <c>this</c>.</param>
+ <summary>Whether an <see cref="T:System.Object" /> is a <see cref="T:Xamarin.Forms.Maps.Distance" /> and has exactly the same values as <c>this</c><see cref="T:Xamarin.Forms.Maps.Distance" />.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="obj" /> is a <see cref="T:Xamarin.Forms.Maps.Distance" /> and has exactly the same values as <c>this</c><see cref="T:Xamarin.Forms.Maps.Distance" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Equals">
+ <MemberSignature Language="C#" Value="public bool Equals (Xamarin.Forms.Maps.Distance other);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance bool Equals(valuetype Xamarin.Forms.Maps.Distance other) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="other" Type="Xamarin.Forms.Maps.Distance" />
+ </Parameters>
+ <Docs>
+ <param name="other">The <see cref="T:Xamarin.Forms.Maps.Distance" /> being compared to <c>this</c><see cref="T:Xamarin.Forms.Maps.Distance" />.</param>
+ <summary>Whether a <see cref="T:Xamaring.Forms.Maps.Distance" /> has exactly the same values as <c>this </c><see cref="T:Xamaring.Forms.Maps.Distance" />.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="other" /> has exactly the same value as <c>this</c><see cref="T:Xamaring.Forms.Maps.Distance" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromKilometers">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Maps.Distance FromKilometers (double kilometers);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Maps.Distance FromKilometers(float64 kilometers) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.Distance</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="kilometers" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="kilometers">A double value representing the distance, in kilometers, for the <see cref="T:Xamarin.Forms.Maps.Distance" /> to create.</param>
+ <summary>Factory method to create a <see cref="T:Xamarin.Forms.Maps.Distance" /> from a value provided in kilometers.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromMeters">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Maps.Distance FromMeters (double meters);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Maps.Distance FromMeters(float64 meters) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.Distance</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="meters" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="meters">A double value representing the distance, in meters, for the <see cref="T:Xamarin.Forms.Maps.Distance" /> to create.</param>
+ <summary>Factory method to create a <see cref="T:Xamarin.Forms.Maps.Distance" /> from a value provided in meters.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromMiles">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Maps.Distance FromMiles (double miles);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig valuetype Xamarin.Forms.Maps.Distance FromMiles(float64 miles) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.Distance</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="miles" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="miles">A double value representing the distance, in miles, for the <see cref="T:Xamarin.Forms.Maps.Distance" /> to create.</param>
+ <summary>Factory method to create a <see cref="T:Xamarin.Forms.Maps.Distance" /> from a value provided in miles.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetHashCode">
+ <MemberSignature Language="C#" Value="public override int GetHashCode ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance int32 GetHashCode() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>The hashcode for the <see cref="T:Xamarin.Forms.Maps.Distance" />.</summary>
+ <returns>A value optimized for fast insertion and retrieval in a hash-based data structure.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Kilometers">
+ <MemberSignature Language="C#" Value="public double Kilometers { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Kilometers" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the distance in kilometers that is spanned by <c>this</c><see cref="T:Xamarin.Forms.Maps.Distance" />.</summary>
+ <value>The distance in kilometers that is spanned by <c>this</c><see cref="T:Xamarin.Forms.Maps.Distance" /></value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Meters">
+ <MemberSignature Language="C#" Value="public double Meters { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Meters" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the distance in meters that is spanned by <c>this</c><see cref="T:Xamarin.Forms.Maps.Distance" />.</summary>
+ <value>Toe distance in meters that is spanned by <c>this</c><see cref="T:Xamarin.Forms.Maps.Distance" />.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Miles">
+ <MemberSignature Language="C#" Value="public double Miles { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Miles" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the distance in miles that is spanned by <c>this</c><see cref="T:Xamarin.Forms.Maps.Distance" />.</summary>
+ <value>The distance in miles that is spanned by <c>this</c><see cref="T:Xamarin.Forms.Maps.Distance" />.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Equality">
+ <MemberSignature Language="C#" Value="public static bool op_Equality (Xamarin.Forms.Maps.Distance left, Xamarin.Forms.Maps.Distance right);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Equality(valuetype Xamarin.Forms.Maps.Distance left, valuetype Xamarin.Forms.Maps.Distance right) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="left" Type="Xamarin.Forms.Maps.Distance" />
+ <Parameter Name="right" Type="Xamarin.Forms.Maps.Distance" />
+ </Parameters>
+ <Docs>
+ <param name="left">A <see cref="T:Xamarin.Forms.Maps.Distance" /> to compare to another <see cref="T:Xamarin.Forms.Maps.Distance" />.</param>
+ <param name="right">A <see cref="T:Xamarin.Forms.Maps.Distance" /> to compare to <paramref name="left" />.</param>
+ <summary>Whether two <see cref="T:Xamarin.Forms.Maps.Distance" />s have <see cref="P:Xamarin.Forms.Maps.Distance.Meters" /> properties that are exactly the same.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="left" /> and <paramref name="right" /> have identical <see cref="P:Xamarin.Forms.Maps.Distance.Meters" /> properties.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Inequality">
+ <MemberSignature Language="C#" Value="public static bool op_Inequality (Xamarin.Forms.Maps.Distance left, Xamarin.Forms.Maps.Distance right);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Inequality(valuetype Xamarin.Forms.Maps.Distance left, valuetype Xamarin.Forms.Maps.Distance right) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="left" Type="Xamarin.Forms.Maps.Distance" />
+ <Parameter Name="right" Type="Xamarin.Forms.Maps.Distance" />
+ </Parameters>
+ <Docs>
+ <param name="left">A <see cref="T:Xamarin.Forms.Maps.Distance" /> to compare to another <see cref="T:Xamarin.Forms.Maps.Distance" />.</param>
+ <param name="right">A <see cref="T:Xamarin.Forms.Maps.Distance" /> to compare to <paramref name="left" />.</param>
+ <summary>Whether two <see cref="T:Xamarin.Forms.Maps.Distance" />s have differing <see cref="P:Xamarin.Forms.Maps.Distance.Meters" /> properties.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="left" /> and <paramref name="right" /> have different <see cref="P:Xamarin.Forms.Maps.Distance.Meters" /> properties.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Geocoder.xml b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Geocoder.xml
new file mode 100644
index 00000000..2b3bf7d4
--- /dev/null
+++ b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Geocoder.xml
@@ -0,0 +1,91 @@
+<Type Name="Geocoder" FullName="Xamarin.Forms.Maps.Geocoder">
+ <TypeSignature Language="C#" Value="public class Geocoder" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Geocoder extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Maps</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Converts between string addresses and <see cref="T:Xamarin.Forms.Maps.Position" />s.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Geocoder ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Maps.Geocoder" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetAddressesForPositionAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task&lt;System.Collections.Generic.IEnumerable&lt;string&gt;&gt; GetAddressesForPositionAsync (Xamarin.Forms.Maps.Position position);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Threading.Tasks.Task`1&lt;class System.Collections.Generic.IEnumerable`1&lt;string&gt;&gt; GetAddressesForPositionAsync(valuetype Xamarin.Forms.Maps.Position position) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Collections.Generic.IEnumerable&lt;System.String&gt;&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="position" Type="Xamarin.Forms.Maps.Position" />
+ </Parameters>
+ <Docs>
+ <param name="position">To be added.</param>
+ <summary>Returns the addresses near <paramref name="position" />, asynchronously.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetPositionsForAddressAsync">
+ <MemberSignature Language="C#" Value="public System.Threading.Tasks.Task&lt;System.Collections.Generic.IEnumerable&lt;Xamarin.Forms.Maps.Position&gt;&gt; GetPositionsForAddressAsync (string address);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class System.Threading.Tasks.Task`1&lt;class System.Collections.Generic.IEnumerable`1&lt;valuetype Xamarin.Forms.Maps.Position&gt;&gt; GetPositionsForAddressAsync(string address) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Threading.Tasks.Task&lt;System.Collections.Generic.IEnumerable&lt;Xamarin.Forms.Maps.Position&gt;&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="address" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="address">To be added.</param>
+ <summary>Returns a list of positions for <paramref name="address" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Map.xml b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Map.xml
new file mode 100644
index 00000000..2776d0b3
--- /dev/null
+++ b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Map.xml
@@ -0,0 +1,363 @@
+<Type Name="Map" FullName="Xamarin.Forms.Maps.Map">
+ <TypeSignature Language="C#" Value="public class Map : Xamarin.Forms.View, System.Collections.Generic.IEnumerable&lt;Xamarin.Forms.Maps.Pin&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Map extends Xamarin.Forms.View implements class System.Collections.Generic.IEnumerable`1&lt;class Xamarin.Forms.Maps.Pin&gt;, class System.Collections.IEnumerable" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Maps</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.View</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.Collections.Generic.IEnumerable&lt;Xamarin.Forms.Maps.Pin&gt;</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>A <see cref="T:Xamarin.Forms.View" /> that shows a map provided by a platform-specific service.</summary>
+ <remarks>
+ <para>Here is a very simple example of a <see cref="T:Xamarin.Forms.Map" />:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+var map = new Map (MapSpan.FromCenterAndRadius (new Position (37, -122), Distance.FromMiles (10)));
+
+var pin = new Pin () {
+ Position = new Position (37, -122),
+ Label = "Some Pin!"
+};
+map.Pins.Add (pin);
+
+var cp = new ContentPage {
+ Content = map,
+};
+ ]]></code>
+ </example>
+ <para>
+ <img href="Pin.Label.png" />
+ </para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Map ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Maps.Map" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Map (Xamarin.Forms.Maps.MapSpan region);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class Xamarin.Forms.Maps.MapSpan region) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="region" Type="Xamarin.Forms.Maps.MapSpan" />
+ </Parameters>
+ <Docs>
+ <param name="region">To be added.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Maps.Map" /> object with that shows the region that is specified by <paramref name="region" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetEnumerator">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IEnumerator&lt;Xamarin.Forms.Maps.Pin&gt; GetEnumerator ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Collections.Generic.IEnumerator`1&lt;class Xamarin.Forms.Maps.Pin&gt; GetEnumerator() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IEnumerator&lt;Xamarin.Forms.Maps.Pin&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>An <see cref="T:System.Collections.Generic.IEnumerator`1" /> of the <see cref="T:Xamarin.Forms.Maps.Pin" />s on this <see cref="T:Xamarin.Forms.Maps.Map" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasScrollEnabled">
+ <MemberSignature Language="C#" Value="public bool HasScrollEnabled { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool HasScrollEnabled" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Whether this <see cref="T:Xamarin.Forms.Maps.Map" /> is allowed to scroll.</summary>
+ <value>
+ <see langword="true" /> if scrolling is enabled.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasScrollEnabledProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HasScrollEnabledProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HasScrollEnabledProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.Maps.Map.HasScrollEnabled" /> bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasZoomEnabled">
+ <MemberSignature Language="C#" Value="public bool HasZoomEnabled { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool HasZoomEnabled" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Whether this <see cref="T:Xamarin.Forms.Maps.Map" /> is allowed to zoom.</summary>
+ <value>
+ <see langword="true" /> if zooming is enabled.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasZoomEnabledProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HasZoomEnabledProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HasZoomEnabledProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.Maps.Map.HasZoomEnabled" /> bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsShowingUser">
+ <MemberSignature Language="C#" Value="public bool IsShowingUser { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance bool IsShowingUser" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Whether this <see cref="T:Xamarin.Forms.Maps.Map" /> is showing the user's current location.</summary>
+ <value>
+ <see langword="true" /> if the user's current location is being displayed.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="IsShowingUserProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsShowingUserProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsShowingUserProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.Maps.Map.IsShowingUser" /> bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MapType">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Maps.MapType MapType { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Maps.MapType MapType" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.MapType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The <see cref="T:Xamarin.Forms.Maps.MapType" /> display style of this <see cref="T:Xamarin.Forms.Maps.Map" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MapTypeProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty MapTypeProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty MapTypeProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.Maps.Map.MapType" /> bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MoveToRegion">
+ <MemberSignature Language="C#" Value="public void MoveToRegion (Xamarin.Forms.Maps.MapSpan mapSpan);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void MoveToRegion(class Xamarin.Forms.Maps.MapSpan mapSpan) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="mapSpan" Type="Xamarin.Forms.Maps.MapSpan" />
+ </Parameters>
+ <Docs>
+ <param name="mapSpan">The <see cref="T:Xamarin.Forms.Maps.MapSpan" /> to make visible.</param>
+ <summary>Moves the map so that it displays the specified <paramref name="mapSpan" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Pins">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;Xamarin.Forms.Maps.Pin&gt; Pins { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;class Xamarin.Forms.Maps.Pin&gt; Pins" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IList&lt;Xamarin.Forms.Maps.Pin&gt;</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>An <see cref="T:System.Collections.IList`1" /> of the <see cref="T:Xamarin.Forms.Maps.Pin" />s on this <see cref="T:Xamarin.Forms.Maps.Map" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="System.Collections.IEnumerable.GetEnumerator">
+ <MemberSignature Language="C#" Value="System.Collections.IEnumerator IEnumerable.GetEnumerator ();" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance class System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.IEnumerator</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>An <see cref="T:System.Collections.IEnumerator" /> of the <see cref="T:Xamarin.Forms.Maps.Pin" />s on this <see cref="T:Xamarin.Forms.Maps.Map" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="VisibleRegion">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Maps.MapSpan VisibleRegion { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Maps.MapSpan VisibleRegion" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.MapSpan</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The currently visible <see cref="T:Xamarin.Forms.Maps.MapSpan" /> of this <see cref="T:Xamarin.Forms.Maps.Map" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/MapSpan.xml b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/MapSpan.xml
new file mode 100644
index 00000000..72c50b80
--- /dev/null
+++ b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/MapSpan.xml
@@ -0,0 +1,315 @@
+<Type Name="MapSpan" FullName="Xamarin.Forms.Maps.MapSpan">
+ <TypeSignature Language="C#" Value="public sealed class MapSpan" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit MapSpan extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Maps</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A circular region on a <see cref="T:Xamarin.Forms.Maps.Map" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public MapSpan (Xamarin.Forms.Maps.Position center, double latitudeDegrees, double longitudeDegrees);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(valuetype Xamarin.Forms.Maps.Position center, float64 latitudeDegrees, float64 longitudeDegrees) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="center" Type="Xamarin.Forms.Maps.Position" />
+ <Parameter Name="latitudeDegrees" Type="System.Double" />
+ <Parameter Name="longitudeDegrees" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="center">To be added.</param>
+ <param name="latitudeDegrees">To be added.</param>
+ <param name="longitudeDegrees">To be added.</param>
+ <summary>Returns a <see cref="T:Xamarin.Forms.Maps.MapSpan" /> that is centered on <paramref name="center" /> and extends to <paramref name="latitudeDegress" /> and <paramref name="longitudeDegress" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Center">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Maps.Position Center { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Maps.Position Center" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.Position</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The <see cref="T:Xamarin.Forms.Maps.Position" /> in the geographical center of the <see cref="T:Xamarin.Forms.Maps.MapSpan" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ClampLatitude">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Maps.MapSpan ClampLatitude (double north, double south);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class Xamarin.Forms.Maps.MapSpan ClampLatitude(float64 north, float64 south) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.MapSpan</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="north" Type="System.Double" />
+ <Parameter Name="south" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="north">The northern limit of the new <see cref="T:Xamarin.Forms.Maps.MapSpan" />.</param>
+ <param name="south">The southern limit of the new <see cref="T:Xamarin.Forms.Maps.MapSpan" />.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Maps.MapSpan" /> with the same <see cref="P:Xamarin.Forms.Maps.MapSpan.LongitudeDegrees" /> as <c>this</c> and a radius defined by <paramref name="north" /> and <paramref name="south" />.</summary>
+ <returns>A new <see cref="T:Xamarin.Forms.Maps.MapSpan" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Equals">
+ <MemberSignature Language="C#" Value="public override bool Equals (object obj);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool Equals(object obj) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="obj" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="obj">To be added.</param>
+ <summary>Whether <paramref name="obj" /> is a <see cref="T:Xamarin.Forms.MapsSpan" /> with identical position and radius values as this <see cref="T:Xamarin.Forms.Maps.MapSpan" />.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="obj" /> is a <see cref="T:Xamarin.Forms.MapsSpan" /> with identical position and radius values as this <see cref="T:Xamarin.Forms.Maps.MapSpan" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="FromCenterAndRadius">
+ <MemberSignature Language="C#" Value="public static Xamarin.Forms.Maps.MapSpan FromCenterAndRadius (Xamarin.Forms.Maps.Position center, Xamarin.Forms.Maps.Distance radius);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.Maps.MapSpan FromCenterAndRadius(valuetype Xamarin.Forms.Maps.Position center, valuetype Xamarin.Forms.Maps.Distance radius) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.MapSpan</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="center" Type="Xamarin.Forms.Maps.Position" />
+ <Parameter Name="radius" Type="Xamarin.Forms.Maps.Distance" />
+ </Parameters>
+ <Docs>
+ <param name="center">To be added.</param>
+ <param name="radius">To be added.</param>
+ <summary>Returns a <see cref="Xamarin.Forms.Maps.MapSpan" /> that displays the area that is defined by <paramref name="center" /> and <paramref name="radius" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetHashCode">
+ <MemberSignature Language="C#" Value="public override int GetHashCode ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance int32 GetHashCode() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>The hash value for this <see cref="T:Xamarin.Forms.Maps.MapSpan" />, based on the position and radius.</summary>
+ <returns>A value optimized for insertion and retrieval in hash-based data structures.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LatitudeDegrees">
+ <MemberSignature Language="C#" Value="public double LatitudeDegrees { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 LatitudeDegrees" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The degrees of latitude that are spanned by the <see cref="T:Xamarin.Forms.Maps.MapSpan" />.</summary>
+ <value>The number of degrees of latitude that are spanned by the <see cref="T:Xamarin.Forms.Maps.MapSpan" />.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LongitudeDegrees">
+ <MemberSignature Language="C#" Value="public double LongitudeDegrees { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 LongitudeDegrees" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The degrees of longitude that are spanned by the <see cref="T:Xamarin.Forms.Maps.MapSpan" />.</summary>
+ <value>The number of degrees of longitude that are spanned by the <see cref="T:Xamarin.Forms.Maps.MapSpan" />.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Equality">
+ <MemberSignature Language="C#" Value="public static bool op_Equality (Xamarin.Forms.Maps.MapSpan left, Xamarin.Forms.Maps.MapSpan right);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Equality(class Xamarin.Forms.Maps.MapSpan left, class Xamarin.Forms.Maps.MapSpan right) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="left" Type="Xamarin.Forms.Maps.MapSpan" />
+ <Parameter Name="right" Type="Xamarin.Forms.Maps.MapSpan" />
+ </Parameters>
+ <Docs>
+ <param name="left">A <see cref="T:Xamarin.Forms.Maps.MapSpan" /> to be compared.</param>
+ <param name="right">A <see cref="T:Xamarin.Forms.Maps.MapSpan" /> to be compared.</param>
+ <summary>Whether two <see cref="T:Xamarin.Forms.Maps.MapSpan" /> have equivalent values.</summary>
+ <returns>
+ <see langword="true" /> if the two <see cref="T:Xamarin.Forms.Maps.MapSpan" />s have equivalent <see cref="P:Xamarin.Forms.Maps.MapSpan.Center" /> and <see cref="P:Xamarin.Forms.Maps.MapSpan.Radius" /> values.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Inequality">
+ <MemberSignature Language="C#" Value="public static bool op_Inequality (Xamarin.Forms.Maps.MapSpan left, Xamarin.Forms.Maps.MapSpan right);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Inequality(class Xamarin.Forms.Maps.MapSpan left, class Xamarin.Forms.Maps.MapSpan right) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="left" Type="Xamarin.Forms.Maps.MapSpan" />
+ <Parameter Name="right" Type="Xamarin.Forms.Maps.MapSpan" />
+ </Parameters>
+ <Docs>
+ <param name="left">A <see cref="T:Xamarin.Forms.Maps.MapSpan" /> to be compared.</param>
+ <param name="right">A <see cref="T:Xamarin.Forms.Maps.MapSpan" /> to be compared.</param>
+ <summary>Whether two <see cref="T:Xamarin.Forms.Maps.MapSpan" /> have different values.</summary>
+ <returns>
+ <see langword="true" /> if the two <see cref="T:Xamarin.Forms.Maps.MapSpan" />s have different values for either <see cref="P:Xamarin.Forms.Maps.MapSpan.Center" /> or <see cref="P:Xamarin.Forms.Maps.MapSpan.Radius" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Radius">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Maps.Distance Radius { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Maps.Distance Radius" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.Distance</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the smallest distance across the <see cref="T:Xamarin.Forms.Maps.MapSpan" />.</summary>
+ <value>The smallest distance across the <see cref="T:Xamarin.Forms.Maps.MapSpan" />.</value>
+ <remarks>Application developers can get the distance in their desired units from the returned <see cref="T:Xamarin.Forms.Distance" /> struct.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="WithZoom">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Maps.MapSpan WithZoom (double zoomFactor);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance class Xamarin.Forms.Maps.MapSpan WithZoom(float64 zoomFactor) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.MapSpan</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="zoomFactor" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="zoomFactor">The factor by which to enlarge or decrease <c>this</c>.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Maps.MapSpan" /> with the same <see cref="P:Xamarin.Forms.Maps.MapSpan.Center" /> as <c>this</c> but with a <see cref="P:Xamarin.Forms.Maps.MapSpan.Radius" /> multiplied by <paramref name="zoomFactor" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/MapType.xml b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/MapType.xml
new file mode 100644
index 00000000..56eaf173
--- /dev/null
+++ b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/MapType.xml
@@ -0,0 +1,79 @@
+<Type Name="MapType" FullName="Xamarin.Forms.Maps.MapType">
+ <TypeSignature Language="C#" Value="public enum MapType" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed MapType extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Maps</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumeration that specifies the display style of the map.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Hybrid">
+ <MemberSignature Language="C#" Value="Hybrid" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.Maps.MapType Hybrid = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.MapType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A map that combinse satellite imagery and street data.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Satellite">
+ <MemberSignature Language="C#" Value="Satellite" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.Maps.MapType Satellite = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.MapType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A map that contains satellite imagery.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Street">
+ <MemberSignature Language="C#" Value="Street" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.Maps.MapType Street = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.MapType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A street map.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Pin.xml b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Pin.xml
new file mode 100644
index 00000000..3280b0bb
--- /dev/null
+++ b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Pin.xml
@@ -0,0 +1,333 @@
+<Type Name="Pin" FullName="Xamarin.Forms.Maps.Pin">
+ <TypeSignature Language="C#" Value="public sealed class Pin : Xamarin.Forms.BindableObject" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit Pin extends Xamarin.Forms.BindableObject" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Maps</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A marker on a <see cref="T:Xamarin.Forms.Maps.Map" />.</summary>
+ <remarks>
+ <para> A <see cref="T:Xamarin.Forms.Maps.Pin" /> must have its <see cref="P:Xamarin.Forms.Maps.Pin.Label" /> property assigned before it is added to a map. If not, a <see cref="T:System.ArgumentException" /> is thrown.</para>
+ <example>
+ <code lang="C#"><![CDATA[
+public static Page GetMapPage ()
+{
+ var map = new Map (MapSpan.FromCenterAndRadius (new Position (37, -122), Distance.FromMiles (10)));
+
+//If Label is not set, runtime exception
+ var pin = new Pin () {
+ Position = new Position (37, -122),
+ Label = "Some Pin!"
+ };
+ map.Pins.Add (pin);
+
+ var cp = new ContentPage {
+ Content = map,
+ };
+
+ return cp;
+}
+
+ ]]></code>
+ </example>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Pin ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Maps.Pin" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Address">
+ <MemberSignature Language="C#" Value="public string Address { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Address" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A <langword see="string" /> describing the street address.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="AddressProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty AddressProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty AddressProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.Maps.Pin.Address" /> bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Clicked">
+ <MemberSignature Language="C#" Value="public event EventHandler Clicked;" />
+ <MemberSignature Language="ILAsm" Value=".event class System.EventHandler Clicked" />
+ <MemberType>Event</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.EventHandler</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Event that is raised when the pin is clicked.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Equals">
+ <MemberSignature Language="C#" Value="public override bool Equals (object obj);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool Equals(object obj) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="obj" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="obj">To be added.</param>
+ <summary>Whether <paramref name="obj" /> with equivalent <see cref="P:Xamarin.Forms.Maps.Pin.Type" />, <see cref="P:Xamarin.Forms.Maps.Pin.Position" />, <see cref="P:Xamarin.Forms.Maps.Pin.Label" /> and <see cref="P:Xamarin.Forms.Maps.Pin.Address" />.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="obj" /> is a <see cref="T:Xamarin.Forms.Maps.Pin" /> with equivalent <see cref="P:Xamarin.Forms.Maps.Pin.Type" />, <see cref="P:Xamarin.Forms.Maps.Pin.Position" />, <see cref="P:Xamarin.Forms.Maps.Pin.Label" /> and <see cref="P:Xamarin.Forms.Maps.Pin.Address" /> values.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetHashCode">
+ <MemberSignature Language="C#" Value="public override int GetHashCode ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance int32 GetHashCode() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>The hash value for the <see cref="T:Xamarin.Forms.Maps.Pin" /></summary>
+ <returns>A value optimized for fast insertion and retrieval in a hash-based data structure.</returns>
+ <remarks>
+ <para>A <see cref="T:Xamarin.Forms.Maps.Pin" /> hash-value is based on its <see cref="P:Xamarin.Forms.Maps.Pin.Type" />, <see cref="P:Xamarin.Forms.Maps.Pin.Position" />, <see cref="P:Xamarin.Forms.Maps.Pin.Label" /> and <see cref="P:Xamarin.Forms.Maps.Pin.Address" /> properties.</para>
+ </remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Label">
+ <MemberSignature Language="C#" Value="public string Label { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Label" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A user-readable <langword see="string" /> associated with the <see cref="T:Xamarin.Forms.Maps.Pin" />.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Equality">
+ <MemberSignature Language="C#" Value="public static bool op_Equality (Xamarin.Forms.Maps.Pin left, Xamarin.Forms.Maps.Pin right);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Equality(class Xamarin.Forms.Maps.Pin left, class Xamarin.Forms.Maps.Pin right) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="left" Type="Xamarin.Forms.Maps.Pin" />
+ <Parameter Name="right" Type="Xamarin.Forms.Maps.Pin" />
+ </Parameters>
+ <Docs>
+ <param name="left">A <see cref="T:Xamarin.Forms.Maps.Pin" /> to be compared.</param>
+ <param name="right">A <see cref="T:Xamarin.Forms.Maps.Pin" /> to be compared.</param>
+ <summary>Whether <paramref name="left" /> and <paramref name="right" /> have equivalent <see cref="P:Xamarin.Forms.Maps.Pin.Type" />, <see cref="P:Xamarin.Forms.Maps.Pin.Position" />, <see cref="P:Xamarin.Forms.Maps.Pin.Label" /> and <see cref="P:Xamarin.Forms.Maps.Pin.Address" /> values.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="left" /> and <paramref name="right" /> have equivalent <see cref="P:Xamarin.Forms.Maps.Pin.Type" />, <see cref="P:Xamarin.Forms.Maps.Pin.Position" />, <see cref="P:Xamarin.Forms.Maps.Pin.Label" /> and <see cref="P:Xamarin.Forms.Maps.Pin.Address" /> values.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Inequality">
+ <MemberSignature Language="C#" Value="public static bool op_Inequality (Xamarin.Forms.Maps.Pin left, Xamarin.Forms.Maps.Pin right);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Inequality(class Xamarin.Forms.Maps.Pin left, class Xamarin.Forms.Maps.Pin right) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="left" Type="Xamarin.Forms.Maps.Pin" />
+ <Parameter Name="right" Type="Xamarin.Forms.Maps.Pin" />
+ </Parameters>
+ <Docs>
+ <param name="left">A <see cref="T:Xamarin.Forms.Maps.Pin" /> to be compared.</param>
+ <param name="right">A <see cref="T:Xamarin.Forms.Maps.Pin" /> to be compared.</param>
+ <summary>Whether <paramref name="left" /> and <paramref name="right" /> differ in any of their <see cref="P:Xamarin.Forms.Maps.Pin.Type" />, <see cref="P:Xamarin.Forms.Maps.Pin.Position" />, <see cref="P:Xamarin.Forms.Maps.Pin.Label" /> and <see cref="P:Xamarin.Forms.Maps.Pin.Address" /> values.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="left" /> and <paramref name="right" /> have any differences between their <see cref="P:Xamarin.Forms.Maps.Pin.Type" />, <see cref="P:Xamarin.Forms.Maps.Pin.Position" />, <see cref="P:Xamarin.Forms.Maps.Pin.Label" /> and <see cref="P:Xamarin.Forms.Maps.Pin.Address" /> values.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Position">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Maps.Position Position { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Maps.Position Position" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.Position</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The latitude and longitude of the <see cref="T:Xamarin.Forms.Maps.Pin" />.</summary>
+ <value>The <see cref="T:Xamarin.Forms.Maps.Position" /> of the <see cref="T:Xamarin.Forms.Maps.Pin" />.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="PositionProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty PositionProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty PositionProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="P:Xamarin.Forms.Maps.Pin.Position" /> bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Type">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Maps.PinType Type { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Maps.PinType Type" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.PinType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>The kind of pin.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TypeProperty">
+ <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty TypeProperty;" />
+ <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty TypeProperty" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Identifies the <see cref="T:Xamarin.Forms.Maps.Pin.Type" /> bindable property.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/PinType.xml b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/PinType.xml
new file mode 100644
index 00000000..13a920fe
--- /dev/null
+++ b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/PinType.xml
@@ -0,0 +1,98 @@
+<Type Name="PinType" FullName="Xamarin.Forms.Maps.PinType">
+ <TypeSignature Language="C#" Value="public enum PinType" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed PinType extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Maps</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Docs>
+ <summary>Enumeration specifying the various kinds of <see cref="T:Xamarin.Forms.Map.Pin" />.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Generic">
+ <MemberSignature Language="C#" Value="Generic" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.Maps.PinType Generic = int32(0)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.PinType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>A generic pin.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Place">
+ <MemberSignature Language="C#" Value="Place" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.Maps.PinType Place = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.PinType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Pin for a place.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="SavedPin">
+ <MemberSignature Language="C#" Value="SavedPin" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.Maps.PinType SavedPin = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.PinType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Pin for a saved location.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="SearchResult">
+ <MemberSignature Language="C#" Value="SearchResult" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.Maps.PinType SearchResult = int32(3)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Maps.PinType</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Pin for a search result.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Position.xml b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Position.xml
new file mode 100644
index 00000000..0d09974b
--- /dev/null
+++ b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/Position.xml
@@ -0,0 +1,192 @@
+<Type Name="Position" FullName="Xamarin.Forms.Maps.Position">
+ <TypeSignature Language="C#" Value="public struct Position" />
+ <TypeSignature Language="ILAsm" Value=".class public sequential ansi sealed beforefieldinit Position extends System.ValueType" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Maps</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.ValueType</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>A struct that has a latitude and longitude, stored as doubles.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public Position (double latitude, double longitude);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(float64 latitude, float64 longitude) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="latitude" Type="System.Double" />
+ <Parameter Name="longitude" Type="System.Double" />
+ </Parameters>
+ <Docs>
+ <param name="latitude">The latitude of the new position in degrees, as a double. This value will be clamped between -90.0 and 90.0, inclusive.</param>
+ <param name="longitude">The longitude of the new position, as a double. This value will be clamped between -180.0 and 180.0, inclusive.</param>
+ <summary>Constructs a new <see cref="T:Xamarin.Forms.Maps.Position" /> structure with a given latitude and longitude.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Equals">
+ <MemberSignature Language="C#" Value="public override bool Equals (object obj);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance bool Equals(object obj) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="obj" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="obj">To be added.</param>
+ <summary>Returns a Boolean value that indicates whether or not <paramref name="obj" /> is another <see cref="T:Xamarin.Forms.Position" /> structure and represents exactly the same latitude and longitude as <see langword="this" /> one.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="obj" /> is another <see cref="T:Xamarin.Forms.Position" /> structure and represents exactly the same latitude and longitude as <see langword="this" /> one. Otherwise, <see langword="false" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetHashCode">
+ <MemberSignature Language="C#" Value="public override int GetHashCode ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance int32 GetHashCode() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>Returns the hash code for this instance.</summary>
+ <returns>The hash code for this instance.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Latitude">
+ <MemberSignature Language="C#" Value="public double Latitude { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Latitude" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the latitude of this position in decimal degrees.</summary>
+ <value>The latitude of this position in degrees, as a double. The returned value will be between -90.0 and 90.0 degrees, inclusive.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Longitude">
+ <MemberSignature Language="C#" Value="public double Longitude { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 Longitude" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets the longitude of this position in decimal degrees.</summary>
+ <value>The longitude of this position in degrees, as a double. The returned value will be between -180.0 and 180.0 degrees, inclusive.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Equality">
+ <MemberSignature Language="C#" Value="public static bool op_Equality (Xamarin.Forms.Maps.Position left, Xamarin.Forms.Maps.Position right);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Equality(valuetype Xamarin.Forms.Maps.Position left, valuetype Xamarin.Forms.Maps.Position right) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="left" Type="Xamarin.Forms.Maps.Position" />
+ <Parameter Name="right" Type="Xamarin.Forms.Maps.Position" />
+ </Parameters>
+ <Docs>
+ <param name="left">A <see cref="T:Xamarin.Forms.Maps.Position" /> to compare.</param>
+ <param name="right">A <see cref="T:Xamarin.Forms.Maps.Position" /> to compare.</param>
+ <summary>Returns a Boolean value that indicates whether or not <paramref name="left" /> represents exactly the same latitude and longitude as <paramref name="right" />.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="left" /> represents exactly the same latitude and longitude as <paramref name="right" />. Otherwise, <see langword="false" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="op_Inequality">
+ <MemberSignature Language="C#" Value="public static bool op_Inequality (Xamarin.Forms.Maps.Position left, Xamarin.Forms.Maps.Position right);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname bool op_Inequality(valuetype Xamarin.Forms.Maps.Position left, valuetype Xamarin.Forms.Maps.Position right) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="left" Type="Xamarin.Forms.Maps.Position" />
+ <Parameter Name="right" Type="Xamarin.Forms.Maps.Position" />
+ </Parameters>
+ <Docs>
+ <param name="left">A <see cref="T:Xamarin.Forms.Maps.Position" /> to compare.</param>
+ <param name="right">A <see cref="T:Xamarin.Forms.Maps.Position" /> to compare.</param>
+ <summary>Returns a Boolean value that indicates whether or not <paramref name="left" /> and <paramref name="right" /> represent different latitudes or longitudes.</summary>
+ <returns>
+ <see langword="true" /> if <paramref name="left" /> and <paramref name="right" /> represent different latitudes or longitudes. Otherwise, <see langword="false" />.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/_images/Pin.Label.png b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/_images/Pin.Label.png
new file mode 100644
index 00000000..3d7e0556
--- /dev/null
+++ b/docs/Xamarin.Forms.Maps/Xamarin.Forms.Maps/_images/Pin.Label.png
Binary files differ
diff --git a/docs/Xamarin.Forms.Maps/index.xml b/docs/Xamarin.Forms.Maps/index.xml
new file mode 100644
index 00000000..94c91402
--- /dev/null
+++ b/docs/Xamarin.Forms.Maps/index.xml
@@ -0,0 +1,98 @@
+<Overview>
+ <Assemblies>
+ <Assembly Name="Xamarin.Forms.Maps" Version="2.0.0.0">
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.Default | System.Diagnostics.DebuggableAttribute+DebuggingModes.DisableOptimizations | System.Diagnostics.DebuggableAttribute+DebuggingModes.EnableEditAndContinue | System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints)</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyCompany("Xamarin Inc.")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyConfiguration("")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyCopyright("Copyright © Xamarin Inc. 2013-2015")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyDescription("")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyFileVersion("2.0.0.0")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyProduct("Xamarin.Forms")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyTitle("Xamarin.Forms.Maps")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyTrademark("")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Resources.NeutralResourcesLanguage("en")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.CompilationRelaxations(8)</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Maps.iOS")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Maps.iOS.Classic")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Maps.Android")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Maps.WP8")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("iOSUnitTests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Core.UnitTests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Core.Android.UnitTests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Core.WP8.UnitTests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Xaml.UnitTests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Xaml")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Maps.Design")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true)</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.Versioning.TargetFramework(".NETPortable,Version=v4.5,Profile=Profile259", FrameworkDisplayName=".NET Portable Subset")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.Preserve</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Assembly>
+ </Assemblies>
+ <Remarks>To be added.</Remarks>
+ <Copyright>To be added.</Copyright>
+ <Types>
+ <Namespace Name="Xamarin.Forms.Maps">
+ <Type Name="Distance" Kind="Structure" />
+ <Type Name="Geocoder" Kind="Class" />
+ <Type Name="Map" Kind="Class" />
+ <Type Name="MapSpan" Kind="Class" />
+ <Type Name="MapType" Kind="Enumeration" />
+ <Type Name="Pin" Kind="Class" />
+ <Type Name="PinType" Kind="Enumeration" />
+ <Type Name="Position" Kind="Structure" />
+ </Namespace>
+ </Types>
+ <Title>Xamarin.Forms.Maps</Title>
+</Overview>
diff --git a/docs/Xamarin.Forms.Maps/ns-Xamarin.Forms.Maps.xml b/docs/Xamarin.Forms.Maps/ns-Xamarin.Forms.Maps.xml
new file mode 100644
index 00000000..c8335cbf
--- /dev/null
+++ b/docs/Xamarin.Forms.Maps/ns-Xamarin.Forms.Maps.xml
@@ -0,0 +1,59 @@
+<Namespace Name="Xamarin.Forms.Maps">
+ <Docs>
+ <summary>Cross-Platform Library for Displaying and Annotating Maps.</summary>
+ <remarks>
+ <para>Xamarin.Forms.Maps provides a cross-platform abstraction for displaying maps. To use Xamarin.Forms.Maps, application developers must calls Xamarin.FormsMaps.Init() as part of platform initialization, as shown in the following example:</para>
+ <example>
+ <code lang="C#"><![CDATA[
+//Shared
+public class App
+{
+ public static Page GetMainPage ()
+ {
+ return new ContentPage {
+ Content = new Map (MapSpan.FromCenterAndRadius (new Position (37, -122), Distance.FromMiles (10)))
+ };
+ }
+}
+//iOS
+[Register ("AppDelegate")]
+public partial class AppDelegate : UIApplicationDelegate
+{
+ UIWindow window;
+
+ public override bool FinishedLaunching (UIApplication app, NSDictionary options)
+ {
+ Forms.Init ();
+ FormsMaps.Init ();
+
+ window = new UIWindow (UIScreen.MainScreen.Bounds);
+
+ window.RootViewController = App.GetMainPage ().CreateViewController ();
+ window.MakeKeyAndVisible ();
+
+ return true;
+ }
+}
+//Android
+namespace HelloMap.Android
+{
+ [Activity (Label = "HelloMap.Android.Android", MainLauncher = true)]
+ public class MainActivity : AndroidActivity
+ {
+ protected override void OnCreate (Bundle bundle)
+ {
+ base.OnCreate (bundle);
+
+ Xamarin.Forms.Forms.Init (this, bundle);
+ FormsMaps.Init(this, bundle);
+
+ SetPage (App.GetMainPage ());
+ }
+ }
+}
+ ]]></code>
+ </example>
+
+ </remarks>
+ </Docs>
+</Namespace>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/NameScopeProvider.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/NameScopeProvider.xml
new file mode 100644
index 00000000..38b257f5
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/NameScopeProvider.xml
@@ -0,0 +1,50 @@
+<Type Name="NameScopeProvider" FullName="Xamarin.Forms.Xaml.Internals.NameScopeProvider">
+ <TypeSignature Language="C#" Value="public class NameScopeProvider" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit NameScopeProvider extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public NameScopeProvider ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="NameScope">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Internals.INameScope NameScope { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Internals.INameScope NameScope" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Internals.INameScope</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/SimpleValueTargetProvider.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/SimpleValueTargetProvider.xml
new file mode 100644
index 00000000..81070033
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/SimpleValueTargetProvider.xml
@@ -0,0 +1,70 @@
+<Type Name="SimpleValueTargetProvider" FullName="Xamarin.Forms.Xaml.Internals.SimpleValueTargetProvider">
+ <TypeSignature Language="C#" Value="public class SimpleValueTargetProvider" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit SimpleValueTargetProvider extends System.Object implements class Xamarin.Forms.Xaml.IProvideValueTarget" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public SimpleValueTargetProvider (object[] objectAndParents);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(object[] objectAndParents) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="objectAndParents" Type="System.Object[]" />
+ </Parameters>
+ <Docs>
+ <param name="objectAndParents">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IProvideValueTarget.TargetObject">
+ <MemberSignature Language="C#" Value="object Xamarin.Forms.Xaml.IProvideValueTarget.TargetObject { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Xamarin.Forms.Xaml.IProvideValueTarget.TargetObject" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IProvideValueTarget.TargetProperty">
+ <MemberSignature Language="C#" Value="object Xamarin.Forms.Xaml.IProvideValueTarget.TargetProperty { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Xamarin.Forms.Xaml.IProvideValueTarget.TargetProperty" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XamlServiceProvider.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XamlServiceProvider.xml
new file mode 100644
index 00000000..5e4bd3e6
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XamlServiceProvider.xml
@@ -0,0 +1,80 @@
+<Type Name="XamlServiceProvider" FullName="Xamarin.Forms.Xaml.Internals.XamlServiceProvider">
+ <TypeSignature Language="C#" Value="public class XamlServiceProvider : IServiceProvider" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit XamlServiceProvider extends System.Object implements class System.IServiceProvider" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.IServiceProvider</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public XamlServiceProvider ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (Type type, object service);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void Add(class System.Type type, object service) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="type" Type="System.Type" />
+ <Parameter Name="service" Type="System.Object" />
+ </Parameters>
+ <Docs>
+ <param name="type">To be added.</param>
+ <param name="service">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetService">
+ <MemberSignature Language="C#" Value="public object GetService (Type serviceType);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object GetService(class System.Type serviceType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <param name="serviceType">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XamlTypeResolver.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XamlTypeResolver.xml
new file mode 100644
index 00000000..58b5d652
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XamlTypeResolver.xml
@@ -0,0 +1,88 @@
+<Type Name="XamlTypeResolver" FullName="Xamarin.Forms.Xaml.Internals.XamlTypeResolver">
+ <TypeSignature Language="C#" Value="public class XamlTypeResolver : Xamarin.Forms.Xaml.IXamlTypeResolver" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit XamlTypeResolver extends System.Object implements class Xamarin.Forms.Xaml.IXamlTypeResolver" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IXamlTypeResolver</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public XamlTypeResolver (System.Xml.IXmlNamespaceResolver namespaceResolver, System.Reflection.Assembly currentAssembly);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Xml.IXmlNamespaceResolver namespaceResolver, class System.Reflection.Assembly currentAssembly) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="namespaceResolver" Type="System.Xml.IXmlNamespaceResolver" />
+ <Parameter Name="currentAssembly" Type="System.Reflection.Assembly" />
+ </Parameters>
+ <Docs>
+ <param name="namespaceResolver">To be added.</param>
+ <param name="currentAssembly">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IXamlTypeResolver.Resolve">
+ <MemberSignature Language="C#" Value="Type IXamlTypeResolver.Resolve (string qualifiedTypeName, IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance class System.Type Xamarin.Forms.Xaml.IXamlTypeResolver.Resolve(string qualifiedTypeName, class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Type</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="qualifiedTypeName" Type="System.String" />
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="qualifiedTypeName">To be added.</param>
+ <param name="serviceProvider">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IXamlTypeResolver.TryResolve">
+ <MemberSignature Language="C#" Value="bool IXamlTypeResolver.TryResolve (string qualifiedTypeName, out Type type);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance bool Xamarin.Forms.Xaml.IXamlTypeResolver.TryResolve(string qualifiedTypeName, class System.Type type) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="qualifiedTypeName" Type="System.String" />
+ <Parameter Name="type" Type="System.Type&amp;" RefType="out" />
+ </Parameters>
+ <Docs>
+ <param name="qualifiedTypeName">To be added.</param>
+ <param name="type">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XmlLineInfoProvider.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XmlLineInfoProvider.xml
new file mode 100644
index 00000000..312452de
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XmlLineInfoProvider.xml
@@ -0,0 +1,57 @@
+<Type Name="XmlLineInfoProvider" FullName="Xamarin.Forms.Xaml.Internals.XmlLineInfoProvider">
+ <TypeSignature Language="C#" Value="public class XmlLineInfoProvider : Xamarin.Forms.Xaml.IXmlLineInfoProvider" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit XmlLineInfoProvider extends System.Object implements class Xamarin.Forms.Xaml.IXmlLineInfoProvider" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IXmlLineInfoProvider</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public XmlLineInfoProvider (System.Xml.IXmlLineInfo xmlLineInfo);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Xml.IXmlLineInfo xmlLineInfo) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="xmlLineInfo" Type="System.Xml.IXmlLineInfo" />
+ </Parameters>
+ <Docs>
+ <param name="xmlLineInfo">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="XmlLineInfo">
+ <MemberSignature Language="C#" Value="public System.Xml.IXmlLineInfo XmlLineInfo { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Xml.IXmlLineInfo XmlLineInfo" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Xml.IXmlLineInfo</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XmlNamespaceResolver.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XmlNamespaceResolver.xml
new file mode 100644
index 00000000..5b1f8527
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml.Internals/XmlNamespaceResolver.xml
@@ -0,0 +1,122 @@
+<Type Name="XmlNamespaceResolver" FullName="Xamarin.Forms.Xaml.Internals.XmlNamespaceResolver">
+ <TypeSignature Language="C#" Value="public class XmlNamespaceResolver : System.Xml.IXmlNamespaceResolver" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit XmlNamespaceResolver extends System.Object implements class System.Xml.IXmlNamespaceResolver" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.Xml.IXmlNamespaceResolver</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public XmlNamespaceResolver ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Add">
+ <MemberSignature Language="C#" Value="public void Add (string prefix, string ns);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance void Add(string prefix, string ns) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="prefix" Type="System.String" />
+ <Parameter Name="ns" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="prefix">To be added.</param>
+ <param name="ns">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="GetNamespacesInScope">
+ <MemberSignature Language="C#" Value="public System.Collections.Generic.IDictionary&lt;string,string&gt; GetNamespacesInScope (System.Xml.XmlNamespaceScope scope);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Collections.Generic.IDictionary`2&lt;string, string&gt; GetNamespacesInScope(valuetype System.Xml.XmlNamespaceScope scope) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.Generic.IDictionary&lt;System.String,System.String&gt;</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="scope" Type="System.Xml.XmlNamespaceScope" />
+ </Parameters>
+ <Docs>
+ <param name="scope">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LookupNamespace">
+ <MemberSignature Language="C#" Value="public string LookupNamespace (string prefix);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance string LookupNamespace(string prefix) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="prefix" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="prefix">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LookupPrefix">
+ <MemberSignature Language="C#" Value="public string LookupPrefix (string namespaceName);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance string LookupPrefix(string namespaceName) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="namespaceName" Type="System.String" />
+ </Parameters>
+ <Docs>
+ <param name="namespaceName">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/ArrayExtension.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/ArrayExtension.xml
new file mode 100644
index 00000000..91d847df
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/ArrayExtension.xml
@@ -0,0 +1,177 @@
+<Type Name="ArrayExtension" FullName="Xamarin.Forms.Xaml.ArrayExtension">
+ <TypeSignature Language="C#" Value="public class ArrayExtension : Xamarin.Forms.Xaml.IMarkupExtension&lt;Array&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ArrayExtension extends System.Object implements class Xamarin.Forms.Xaml.IMarkupExtension, class Xamarin.Forms.Xaml.IMarkupExtension`1&lt;class System.Array&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IMarkupExtension&lt;System.Array&gt;</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Items")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ArrayExtension ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Items">
+ <MemberSignature Language="C#" Value="public System.Collections.IList Items { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.IList Items" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.IList</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ProvideValue">
+ <MemberSignature Language="C#" Value="public Array ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Array ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Array</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ProvideValue">
+ <MemberSignature Language="C#" Value="public System.Collections.IEnumerable ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Collections.IEnumerable ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Collections.IEnumerable</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ProvideValue">
+ <MemberSignature Language="C#" Value="public object ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Type">
+ <MemberSignature Language="C#" Value="public Type Type { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class System.Type Type" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Type</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IMarkupExtension.ProvideValue">
+ <MemberSignature Language="C#" Value="object IMarkupExtension.ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.Xaml.IMarkupExtension.ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/BindingExtension.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/BindingExtension.xml
new file mode 100644
index 00000000..fd4e25be
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/BindingExtension.xml
@@ -0,0 +1,196 @@
+<Type Name="BindingExtension" FullName="Xamarin.Forms.Xaml.BindingExtension">
+ <TypeSignature Language="C#" Value="public sealed class BindingExtension : Xamarin.Forms.Xaml.IMarkupExtension&lt;Xamarin.Forms.BindingBase&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit BindingExtension extends System.Object implements class Xamarin.Forms.Xaml.IMarkupExtension, class Xamarin.Forms.Xaml.IMarkupExtension`1&lt;class Xamarin.Forms.BindingBase&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IMarkupExtension&lt;Xamarin.Forms.BindingBase&gt;</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Path")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public BindingExtension ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Converter">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.IValueConverter Converter { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.IValueConverter Converter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.IValueConverter</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConverterParameter">
+ <MemberSignature Language="C#" Value="public object ConverterParameter { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object ConverterParameter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Mode">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.BindingMode Mode { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.BindingMode Mode" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindingMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Path">
+ <MemberSignature Language="C#" Value="public string Path { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Path" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Source">
+ <MemberSignature Language="C#" Value="public object Source { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object Source" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="StringFormat">
+ <MemberSignature Language="C#" Value="public string StringFormat { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string StringFormat" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IMarkupExtension.ProvideValue">
+ <MemberSignature Language="C#" Value="object IMarkupExtension.ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.Xaml.IMarkupExtension.ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IMarkupExtension&lt;Xamarin.Forms.BindingBase&gt;.ProvideValue">
+ <MemberSignature Language="C#" Value="Xamarin.Forms.BindingBase IMarkupExtension&lt;BindingBase&gt;.ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance class Xamarin.Forms.BindingBase Xamarin.Forms.Xaml.IMarkupExtension&lt;Xamarin.Forms.BindingBase&gt;.ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindingBase</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/DynamicResourceExtension.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/DynamicResourceExtension.xml
new file mode 100644
index 00000000..7f8ebcd6
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/DynamicResourceExtension.xml
@@ -0,0 +1,130 @@
+<Type Name="DynamicResourceExtension" FullName="Xamarin.Forms.Xaml.DynamicResourceExtension">
+ <TypeSignature Language="C#" Value="public sealed class DynamicResourceExtension : Xamarin.Forms.Xaml.IMarkupExtension&lt;Xamarin.Forms.Internals.DynamicResource&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit DynamicResourceExtension extends System.Object implements class Xamarin.Forms.Xaml.IMarkupExtension, class Xamarin.Forms.Xaml.IMarkupExtension`1&lt;class Xamarin.Forms.Internals.DynamicResource&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IMarkupExtension&lt;Xamarin.Forms.Internals.DynamicResource&gt;</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Key")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public DynamicResourceExtension ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Internal.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Key">
+ <MemberSignature Language="C#" Value="public string Key { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Key" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ProvideValue">
+ <MemberSignature Language="C#" Value="public object ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IMarkupExtension&lt;Xamarin.Forms.DynamicResource&gt;.ProvideValue">
+ <MemberSignature Language="C#" Value="Xamarin.Forms.DynamicResource IMarkupExtension&lt;DynamicResource&gt;.ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance class Xamarin.Forms.DynamicResource Xamarin.Forms.Xaml.IMarkupExtension&lt;Xamarin.Forms.DynamicResource&gt;.ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.DynamicResource</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IMarkupExtension&lt;Xamarin.Forms.Internals.DynamicResource&gt;.ProvideValue">
+ <MemberSignature Language="C#" Value="Xamarin.Forms.Internals.DynamicResource IMarkupExtension&lt;DynamicResource&gt;.ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance class Xamarin.Forms.Internals.DynamicResource Xamarin.Forms.Xaml.IMarkupExtension&lt;Xamarin.Forms.Internals.DynamicResource&gt;.ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Internals.DynamicResource</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/Extensions.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/Extensions.xml
new file mode 100644
index 00000000..6a6a19a8
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/Extensions.xml
@@ -0,0 +1,60 @@
+<Type Name="Extensions" FullName="Xamarin.Forms.Xaml.Extensions">
+ <TypeSignature Language="C#" Value="public static class Extensions" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract sealed beforefieldinit Extensions extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Extension class for <see cref="T:Xamarin.Forms.View" /> defining <see cref="M:Xamarin.Forms.Xaml.Extensions.LoadFromXaml{TView}" /> method.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="LoadFromXaml&lt;TView&gt;">
+ <MemberSignature Language="C#" Value="public static TView LoadFromXaml&lt;TView&gt; (this TView view, Type callingType) where TView : Xamarin.Forms.BindableObject;" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig !!TView LoadFromXaml&lt;(class Xamarin.Forms.BindableObject) TView&gt;(!!TView view, class System.Type callingType) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.3.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>TView</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TView">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="view" Type="TView" RefType="this" />
+ <Parameter Name="callingType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TView">To be added.</typeparam>
+ <param name="view">To be added.</param>
+ <param name="callingType">To be added.</param>
+ <summary>Configures <paramref name="view" /> with the properties that are defined in the application manifest for <paramref name="callingType" />.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/NullExtension.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/NullExtension.xml
new file mode 100644
index 00000000..7d58670f
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/NullExtension.xml
@@ -0,0 +1,70 @@
+<Type Name="NullExtension" FullName="Xamarin.Forms.Xaml.NullExtension">
+ <TypeSignature Language="C#" Value="public class NullExtension : Xamarin.Forms.Xaml.IMarkupExtension" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit NullExtension extends System.Object implements class Xamarin.Forms.Xaml.IMarkupExtension" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IMarkupExtension</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>Extension class that differentiates between null values and empty strings.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public NullExtension ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Xaml.NullExtension" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ProvideValue">
+ <MemberSignature Language="C#" Value="public object ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>Returns the null object.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/ReferenceExtension.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/ReferenceExtension.xml
new file mode 100644
index 00000000..3e5eb740
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/ReferenceExtension.xml
@@ -0,0 +1,96 @@
+<Type Name="ReferenceExtension" FullName="Xamarin.Forms.Xaml.ReferenceExtension">
+ <TypeSignature Language="C#" Value="public class ReferenceExtension : Xamarin.Forms.Xaml.IMarkupExtension" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ReferenceExtension extends System.Object implements class Xamarin.Forms.Xaml.IMarkupExtension" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IMarkupExtension</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Name")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Markup extension for referring to other XAML-defined types.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public ReferenceExtension ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Xaml.ReferenceExtension" /> with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Name">
+ <MemberSignature Language="C#" Value="public string Name { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Name" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the name of the entity to reference.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ProvideValue">
+ <MemberSignature Language="C#" Value="public object ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>Returns an object that represents the type that was referred to.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/StaticExtension.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/StaticExtension.xml
new file mode 100644
index 00000000..680d9ac8
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/StaticExtension.xml
@@ -0,0 +1,96 @@
+<Type Name="StaticExtension" FullName="Xamarin.Forms.Xaml.StaticExtension">
+ <TypeSignature Language="C#" Value="public class StaticExtension : Xamarin.Forms.Xaml.IMarkupExtension" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit StaticExtension extends System.Object implements class Xamarin.Forms.Xaml.IMarkupExtension" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IMarkupExtension</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Member")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>A markup extension that gets a static member value.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public StaticExtension ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Xaml.StaticExtension" /> object with default values.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Member">
+ <MemberSignature Language="C#" Value="public string Member { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Member" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets the member name.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ProvideValue">
+ <MemberSignature Language="C#" Value="public object ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>Returns the value of the member.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/StaticResourceExtension.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/StaticResourceExtension.xml
new file mode 100644
index 00000000..e64b27e5
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/StaticResourceExtension.xml
@@ -0,0 +1,84 @@
+<Type Name="StaticResourceExtension" FullName="Xamarin.Forms.Xaml.StaticResourceExtension">
+ <TypeSignature Language="C#" Value="public sealed class StaticResourceExtension : Xamarin.Forms.Xaml.IMarkupExtension" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit StaticResourceExtension extends System.Object implements class Xamarin.Forms.Xaml.IMarkupExtension" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IMarkupExtension</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Key")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public StaticResourceExtension ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Key">
+ <MemberSignature Language="C#" Value="public string Key { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Key" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ProvideValue">
+ <MemberSignature Language="C#" Value="public object ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/TemplateBindingExtension.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/TemplateBindingExtension.xml
new file mode 100644
index 00000000..c546ecec
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/TemplateBindingExtension.xml
@@ -0,0 +1,160 @@
+<Type Name="TemplateBindingExtension" FullName="Xamarin.Forms.Xaml.TemplateBindingExtension">
+ <TypeSignature Language="C#" Value="public sealed class TemplateBindingExtension : Xamarin.Forms.Xaml.IMarkupExtension&lt;Xamarin.Forms.BindingBase&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit TemplateBindingExtension extends System.Object implements class Xamarin.Forms.Xaml.IMarkupExtension, class Xamarin.Forms.Xaml.IMarkupExtension`1&lt;class Xamarin.Forms.BindingBase&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IMarkupExtension&lt;Xamarin.Forms.BindingBase&gt;</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("Path")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TemplateBindingExtension ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Converter">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.IValueConverter Converter { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.IValueConverter Converter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.IValueConverter</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ConverterParameter">
+ <MemberSignature Language="C#" Value="public object ConverterParameter { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance object ConverterParameter" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Mode">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.BindingMode Mode { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.BindingMode Mode" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindingMode</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Path">
+ <MemberSignature Language="C#" Value="public string Path { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string Path" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="StringFormat">
+ <MemberSignature Language="C#" Value="public string StringFormat { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string StringFormat" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IMarkupExtension.ProvideValue">
+ <MemberSignature Language="C#" Value="object IMarkupExtension.ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.Xaml.IMarkupExtension.ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IMarkupExtension&lt;Xamarin.Forms.BindingBase&gt;.ProvideValue">
+ <MemberSignature Language="C#" Value="Xamarin.Forms.BindingBase IMarkupExtension&lt;BindingBase&gt;.ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance class Xamarin.Forms.BindingBase Xamarin.Forms.Xaml.IMarkupExtension&lt;Xamarin.Forms.BindingBase&gt;.ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.BindingBase</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/TypeExtension.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/TypeExtension.xml
new file mode 100644
index 00000000..31d0cde8
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/TypeExtension.xml
@@ -0,0 +1,137 @@
+<Type Name="TypeExtension" FullName="Xamarin.Forms.Xaml.TypeExtension">
+ <TypeSignature Language="C#" Value="public class TypeExtension : Xamarin.Forms.Xaml.IMarkupExtension&lt;Type&gt;" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit TypeExtension extends System.Object implements class Xamarin.Forms.Xaml.IMarkupExtension, class Xamarin.Forms.Xaml.IMarkupExtension`1&lt;class System.Type&gt;" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>Xamarin.Forms.Xaml.IMarkupExtension&lt;System.Type&gt;</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Attributes>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.ContentProperty("TypeName")</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public TypeExtension ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ProvideValue">
+ <MemberSignature Language="C#" Value="public object ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance object ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="ProvideValue">
+ <MemberSignature Language="C#" Value="public Type ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Type ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Type</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="TypeName">
+ <MemberSignature Language="C#" Value="public string TypeName { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string TypeName" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Xamarin.Forms.Xaml.IMarkupExtension.ProvideValue">
+ <MemberSignature Language="C#" Value="object IMarkupExtension.ProvideValue (IServiceProvider serviceProvider);" />
+ <MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance object Xamarin.Forms.Xaml.IMarkupExtension.ProvideValue(class System.IServiceProvider serviceProvider) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Object</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="serviceProvider" Type="System.IServiceProvider" />
+ </Parameters>
+ <Docs>
+ <param name="serviceProvider">To be added.</param>
+ <summary>For internal use by the XAML infrastructure.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XamlCompilationAttribute.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XamlCompilationAttribute.xml
new file mode 100644
index 00000000..98952581
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XamlCompilationAttribute.xml
@@ -0,0 +1,58 @@
+<Type Name="XamlCompilationAttribute" FullName="Xamarin.Forms.Xaml.XamlCompilationAttribute">
+ <TypeSignature Language="C#" Value="public sealed class XamlCompilationAttribute : Attribute" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed beforefieldinit XamlCompilationAttribute extends System.Attribute" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Attribute</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.AttributeUsage(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Module, Inherited=false)</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Attribute that controls whether XAML will be compiled at build time or run time.</summary>
+ <remarks>By default, XAML compilation at build time is turned off.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public XamlCompilationAttribute (Xamarin.Forms.Xaml.XamlCompilationOptions xamlCompilationOptions);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(valuetype Xamarin.Forms.Xaml.XamlCompilationOptions xamlCompilationOptions) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="xamlCompilationOptions" Type="Xamarin.Forms.Xaml.XamlCompilationOptions" />
+ </Parameters>
+ <Docs>
+ <param name="xamlCompilationOptions">A value that tells whether to compile XAML at run time or compile time.</param>
+ <summary>Creates a new <see cref="T:Xamarin.Forms.Xaml.XamlCompilationAttribute" /> with the specified value.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="XamlCompilationOptions">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.Xaml.XamlCompilationOptions XamlCompilationOptions { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance valuetype Xamarin.Forms.Xaml.XamlCompilationOptions XamlCompilationOptions" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Xaml.XamlCompilationOptions</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Gets or sets a value that tells whether to compile XAML at run time or compile time.</summary>
+ <value>A value that tells whether to compile XAML at run time or compile time.</value>
+ <remarks>By default, XAML compilation at build time is turned off.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XamlCompilationOptions.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XamlCompilationOptions.xml
new file mode 100644
index 00000000..52266c29
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XamlCompilationOptions.xml
@@ -0,0 +1,56 @@
+<Type Name="XamlCompilationOptions" FullName="Xamarin.Forms.Xaml.XamlCompilationOptions">
+ <TypeSignature Language="C#" Value="public enum XamlCompilationOptions" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi sealed XamlCompilationOptions extends System.Enum" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Enum</BaseTypeName>
+ </Base>
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Flags</AttributeName>
+ </Attribute>
+ </Attributes>
+ <Docs>
+ <summary>Enumerates values that control when XAML is compiled into IL.</summary>
+ <remarks>
+ <para>Enabling build-time compilation by specifying the <c>Compile</c> option checks the XAML at build time, reduces loading time, and produces a smaller assembly or application.</para>
+ <para>By default, XAML compilation at build time is turned off.</para>
+ </remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="Compile">
+ <MemberSignature Language="C#" Value="Compile" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.Xaml.XamlCompilationOptions Compile = int32(2)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Xaml.XamlCompilationOptions</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Compile the XAML for the class or project when the application is built.</summary>
+ </Docs>
+ </Member>
+ <Member MemberName="Skip">
+ <MemberSignature Language="C#" Value="Skip" />
+ <MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.Xaml.XamlCompilationOptions Skip = int32(1)" />
+ <MemberType>Field</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.Xaml.XamlCompilationOptions</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>Compile the XAML for the class or project when the application is run on the device.</summary>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XamlParseException.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XamlParseException.xml
new file mode 100644
index 00000000..0bafd600
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XamlParseException.xml
@@ -0,0 +1,19 @@
+<Type Name="XamlParseException" FullName="Xamarin.Forms.Xaml.XamlParseException">
+ <TypeSignature Language="C#" Value="public class XamlParseException : Exception" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit XamlParseException extends System.Exception" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.0.0.0</AssemblyVersion>
+ <AssemblyVersion>1.1.0.0</AssemblyVersion>
+ <AssemblyVersion>1.2.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Exception</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>Exception that is raised when the XAML parser encounters a XAML error.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members />
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XmlLineInfo.xml b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XmlLineInfo.xml
new file mode 100644
index 00000000..02894766
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/Xamarin.Forms.Xaml/XmlLineInfo.xml
@@ -0,0 +1,96 @@
+<Type Name="XmlLineInfo" FullName="Xamarin.Forms.Xaml.XmlLineInfo">
+ <TypeSignature Language="C#" Value="public class XmlLineInfo : System.Xml.IXmlLineInfo" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit XmlLineInfo extends System.Object implements class System.Xml.IXmlLineInfo" />
+ <AssemblyInfo>
+ <AssemblyName>Xamarin.Forms.Xaml</AssemblyName>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces>
+ <Interface>
+ <InterfaceName>System.Xml.IXmlLineInfo</InterfaceName>
+ </Interface>
+ </Interfaces>
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public XmlLineInfo (bool hasLineInfo, int linenumber, int lineposition);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(bool hasLineInfo, int32 linenumber, int32 lineposition) cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters>
+ <Parameter Name="hasLineInfo" Type="System.Boolean" />
+ <Parameter Name="linenumber" Type="System.Int32" />
+ <Parameter Name="lineposition" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="hasLineInfo">To be added.</param>
+ <param name="linenumber">To be added.</param>
+ <param name="lineposition">To be added.</param>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="HasLineInfo">
+ <MemberSignature Language="C#" Value="public bool HasLineInfo ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance bool HasLineInfo() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LineNumber">
+ <MemberSignature Language="C#" Value="public int LineNumber { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 LineNumber" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="LinePosition">
+ <MemberSignature Language="C#" Value="public int LinePosition { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance int32 LinePosition" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>1.4.0.0</AssemblyVersion>
+ <AssemblyVersion>1.5.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Int32</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/docs/Xamarin.Forms.Xaml/index.xml b/docs/Xamarin.Forms.Xaml/index.xml
new file mode 100644
index 00000000..7f663c63
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/index.xml
@@ -0,0 +1,118 @@
+<Overview>
+ <Assemblies>
+ <Assembly Name="Xamarin.Forms.Xaml" Version="2.0.0.0">
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.Default | System.Diagnostics.DebuggableAttribute+DebuggingModes.DisableOptimizations | System.Diagnostics.DebuggableAttribute+DebuggingModes.EnableEditAndContinue | System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints)</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyCompany("Xamarin Inc.")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyConfiguration("")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyCopyright("Copyright © Xamarin Inc. 2013-2015")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyDescription("")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyFileVersion("2.0.0.0")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyProduct("Xamarin.Forms")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyTitle("Xamarin.Forms.Xaml")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Reflection.AssemblyTrademark("")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.CompilationRelaxations(8)</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Xaml.UnitTests")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Build.Tasks")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.InternalsVisibleTo("Xamarin.Forms.Xaml.Design")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true)</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.Versioning.TargetFramework(".NETPortable,Version=v4.5,Profile=Profile259", FrameworkDisplayName=".NET Portable Subset")</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>Xamarin.Forms.Preserve</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Assembly>
+ </Assemblies>
+ <Remarks>To be added.</Remarks>
+ <Copyright>To be added.</Copyright>
+ <Types>
+ <Namespace Name="Xamarin.Forms.Xaml">
+ <Type Name="ArrayExtension" Kind="Class" />
+ <Type Name="BindingExtension" Kind="Class" />
+ <Type Name="DynamicResourceExtension" Kind="Class" />
+ <Type Name="Extensions" Kind="Class" />
+ <Type Name="NullExtension" Kind="Class" />
+ <Type Name="ReferenceExtension" Kind="Class" />
+ <Type Name="StaticExtension" Kind="Class" />
+ <Type Name="StaticResourceExtension" Kind="Class" />
+ <Type Name="TemplateBindingExtension" Kind="Class" />
+ <Type Name="TypeExtension" Kind="Class" />
+ <Type Name="XamlCompilationAttribute" Kind="Class" />
+ <Type Name="XamlCompilationOptions" Kind="Enumeration" />
+ <Type Name="XamlParseException" Kind="Class" />
+ <Type Name="XmlLineInfo" Kind="Class" />
+ </Namespace>
+ <Namespace Name="Xamarin.Forms.Xaml.Internals">
+ <Type Name="NameScopeProvider" Kind="Class" />
+ <Type Name="SimpleValueTargetProvider" Kind="Class" />
+ <Type Name="XamlServiceProvider" Kind="Class" />
+ <Type Name="XamlTypeResolver" Kind="Class" />
+ <Type Name="XmlLineInfoProvider" Kind="Class" />
+ <Type Name="XmlNamespaceResolver" Kind="Class" />
+ </Namespace>
+ </Types>
+ <Title>Xamarin.Forms.Xaml</Title>
+ <ExtensionMethods>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:Xamarin.Forms.BindableObject" />
+ </Targets>
+ <Member MemberName="LoadFromXaml&lt;TView&gt;">
+ <MemberSignature Language="C#" Value="public static TView LoadFromXaml&lt;TView&gt; (this TView view, Type callingType) where TView : Xamarin.Forms.BindableObject;" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig !!TView LoadFromXaml&lt;(class Xamarin.Forms.BindableObject) TView&gt;(!!TView view, class System.Type callingType) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>TView</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="TView">
+ <Constraints>
+ <BaseTypeName>Xamarin.Forms.BindableObject</BaseTypeName>
+ </Constraints>
+ </TypeParameter>
+ </TypeParameters>
+ <Parameters>
+ <Parameter Name="view" Type="TView" RefType="this" />
+ <Parameter Name="callingType" Type="System.Type" />
+ </Parameters>
+ <Docs>
+ <typeparam name="TView">To be added.</typeparam>
+ <param name="view">To be added.</param>
+ <param name="callingType">To be added.</param>
+ <summary>Configures <paramref name="view" /> with the properties that are defined in the application manifest for <paramref name="callingType" />.</summary>
+ </Docs>
+ <Link Type="Xamarin.Forms.Xaml.Extensions" Member="M:Xamarin.Forms.Xaml.Extensions.LoadFromXaml``1(``0,System.Type)" />
+ </Member>
+ </ExtensionMethod>
+ </ExtensionMethods>
+</Overview>
diff --git a/docs/Xamarin.Forms.Xaml/ns-Xamarin.Forms.Xaml.Internals.xml b/docs/Xamarin.Forms.Xaml/ns-Xamarin.Forms.Xaml.Internals.xml
new file mode 100644
index 00000000..881ec37c
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/ns-Xamarin.Forms.Xaml.Internals.xml
@@ -0,0 +1,6 @@
+<Namespace Name="Xamarin.Forms.Xaml.Internals">
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Namespace>
diff --git a/docs/Xamarin.Forms.Xaml/ns-Xamarin.Forms.Xaml.xml b/docs/Xamarin.Forms.Xaml/ns-Xamarin.Forms.Xaml.xml
new file mode 100644
index 00000000..98089a4e
--- /dev/null
+++ b/docs/Xamarin.Forms.Xaml/ns-Xamarin.Forms.Xaml.xml
@@ -0,0 +1,6 @@
+<Namespace Name="Xamarin.Forms.Xaml">
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Namespace>
diff --git a/update-docs-windows.bat b/update-docs-windows.bat
new file mode 100644
index 00000000..c7838795
--- /dev/null
+++ b/update-docs-windows.bat
@@ -0,0 +1,29 @@
+@echo off
+PATH="C:\Program Files (x86)\Mono\bin";%PATH%
+
+echo "Updating Xamarin.Forms.Core"
+tools\mdoc\mdoc update --delete Xamarin.Forms.Core\bin\Debug\Xamarin.Forms.Core.dll -L "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile259" --out docs\Xamarin.Forms.Core | findstr /r "^Members.Added:..," > tmpFile
+set /p RESULT= < tmpFile
+echo "%RESULT%"
+del tmpFile
+
+IF NOT "%RESULT%" == "Members Added: 0, Members Deleted: 0" (exit 1)
+
+echo "Updating Xamarin.Forms.Xaml"
+tools\mdoc\mdoc update --delete Xamarin.Forms.Xaml\bin\Debug\Xamarin.Forms.Xaml.dll -L "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile259" --out docs\Xamarin.Forms.Xaml | findstr /r "^Members.Added:..," > tmpFile
+set /p RESULT= < tmpFile
+echo "%RESULT%"
+del tmpFile
+
+IF NOT "%RESULT%" == "Members Added: 0, Members Deleted: 0" (exit 1)
+
+echo "Updating Xamarin.Forms.Maps"
+tools\mdoc\mdoc update --delete Xamarin.Forms.Maps\bin\Debug\Xamarin.Forms.Maps.dll -L "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile259" --out docs\Xamarin.Forms.Maps | findstr /r "^Members.Added:..," > tmpFile
+set /p RESULT= < tmpFile
+echo "%RESULT%"
+del tmpFile
+
+IF NOT "%RESULT%" == "Members Added: 0, Members Deleted: 0" (exit 1)
+
+exit 0
+
diff --git a/verify-nuspecs.ps1 b/verify-nuspecs.ps1
new file mode 100644
index 00000000..0559cfe5
--- /dev/null
+++ b/verify-nuspecs.ps1
@@ -0,0 +1,130 @@
+[CmdletBinding()]
+param ( )
+
+# Namespace for msbuild csproj files
+$namespace = @{msb="http://schemas.microsoft.com/developer/msbuild/2003"}
+
+# The various Windows projects and their nuspec targets
+$projectTargets = @{
+ "Xamarin.Forms.Platform.WinRT.Phone" = @("lib\wpa81\Xamarin.Forms.Platform.WinRT.Phone");
+ "Xamarin.Forms.Platform.WinRT" = @("lib\wpa81\Xamarin.Forms.Platform.WinRT", "lib\win81\Xamarin.Forms.Platform.WinRT");
+ "Xamarin.Forms.Platform.WinRT.Tablet" = @("lib\win81\Xamarin.Forms.Platform.WinRT.Tablet");
+ "Xamarin.Forms.Platform.UAP" = @("lib\uap10.0\Xamarin.Forms.Platform.UAP");
+}
+
+# Iterate over the Windows projects, load their csproj files,
+# and build a hashtable of the required .xbf files and their targets
+
+$projectNames = @()
+$projectTargets.Keys | % {
+ $projectNames += $_
+}
+
+$requirements = @{}
+
+$projectNames | % {
+
+ $name = $_
+
+ # Find the csproj file
+ $csproj = (Get-ChildItem -r ($_ + '.csproj')).FullName
+
+ # Load it up
+ [xml]$proj = Get-Content $csproj
+
+ # Check for XAML files as part of control with codebehind files
+ $dependentUpon = Select-Xml -Xml $proj -XPath "//msb:Compile/msb:DependentUpon" -Namespace $namespace | Select-Object -ExpandProperty Node
+ $dependentUpon | % {
+ $filename = $_.InnerText
+
+ Write-Verbose "Found $filename for project $name";
+
+ # Build the .xbf source file name that should be in the nuspec
+ $xbf = (Split-Path $filename -leaf).Replace(".xaml", ".xbf")
+ $xbf = "..\$name\bin\`$Configuration`$\$xbf"
+
+ # Add this .xbf to our requirements
+ $requirements[$xbf] = $projectTargets[$name]
+ }
+
+ # Check for XAML files included as Pages (Resources files, styles, etc.)
+ $pageInclude = Select-Xml -Xml $proj -XPath "//msb:Page" -Namespace $namespace | Select-Object -ExpandProperty Node
+ $pageInclude | % {
+
+ Write-Verbose "Found $($_.Include) for project $name";
+
+ # Build the .xbf source file name that should be in the nuspec
+ $xbf = (Split-Path $_.Include -leaf).Replace(".xaml", ".xbf")
+ $xbf = "..\$name\bin\`$Configuration`$\$xbf"
+
+ # Add this .xbf to our requirements
+ $requirements[$xbf] = $projectTargets[$name]
+ }
+}
+
+
+# load up the nuspec file
+[xml]$nuspec = Get-Content .\.nuspec\Xamarin.Forms.nuspec
+
+# Keep track of which requirements aren't being met so we can display that in the build output
+$failedRequirements = @()
+
+# Also keep track of extra XBF entries which aren't required so we can display that in the build output
+$extraEntries = @()
+
+# Find all the xbf files listed in the nuspec
+$nuspecFiles = $nuspec.package.files.file | ? { $_.src.EndsWith(".xbf") }
+
+# Iterate over the requirements and track each one that isn't met
+Write-Verbose "Verifying that required XAML file has a corresponding XBF in nuspec..."
+$requirements.Keys | % {
+ $xbf = $_
+
+ $requirements[$_] | % {
+ $target = $_
+
+ Write-Verbose "Checking for nuspec entry file = $xbf with target $target"
+
+ $entries = $nuspecFiles | ? {
+ ($_.src -eq $xbf) -and ($_.target -eq $target)
+ }
+
+ if(!$entries) {
+ $failedRequirements += "Missing nuspec entry for $xbf with target $target"
+ }
+ }
+}
+
+# Iterate over the xbf entries and track each one that isn't a requirement
+Write-Verbose "Verifying that each XBF entry in nuspec has an actual XAML file..."
+$nuspecFiles | % {
+ $entry = $_
+
+ Write-Verbose "Checking entry with src = $($entry.src) and target = $($entry.target)"
+
+ $srcMatch = $requirements.Keys | ? { $_ -eq $entry.src }
+
+ if($srcMatch) {
+ $requirements[$entry.src] | % { Write-Verbose $_ }
+ $targetMatch = $requirements[$entry.src] | ? { $_ -eq $entry.target }
+ if(-not $targetMatch) {
+ $extraEntries += "XBF entry $($entry.src) doesn't have a corresponding XAML file"
+ }
+ } else {
+ $extraEntries += "XBF entry $($entry.src) doesn't have a corresponding XAML file"
+ }
+}
+
+
+# Emit the failed requirements and extra entries so they show up in build ouput
+$failedRequirements
+$extraEntries
+
+if($failedRequirements -or $extraEntries) {
+ # D'oh!
+ exit 13
+} else {
+ # Woohoo!
+ exit 0
+}
+